Statistics
| Branch: | Revision:

root / hw / fw_cfg.c @ 78ced65e

History | View | Annotate | Download (10.9 kB)

1 3cce6243 blueswir1
/*
2 3cce6243 blueswir1
 * QEMU Firmware configuration device emulation
3 3cce6243 blueswir1
 *
4 3cce6243 blueswir1
 * Copyright (c) 2008 Gleb Natapov
5 3cce6243 blueswir1
 *
6 3cce6243 blueswir1
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 3cce6243 blueswir1
 * of this software and associated documentation files (the "Software"), to deal
8 3cce6243 blueswir1
 * in the Software without restriction, including without limitation the rights
9 3cce6243 blueswir1
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 3cce6243 blueswir1
 * copies of the Software, and to permit persons to whom the Software is
11 3cce6243 blueswir1
 * furnished to do so, subject to the following conditions:
12 3cce6243 blueswir1
 *
13 3cce6243 blueswir1
 * The above copyright notice and this permission notice shall be included in
14 3cce6243 blueswir1
 * all copies or substantial portions of the Software.
15 3cce6243 blueswir1
 *
16 3cce6243 blueswir1
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 3cce6243 blueswir1
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 3cce6243 blueswir1
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 3cce6243 blueswir1
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 3cce6243 blueswir1
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 3cce6243 blueswir1
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 3cce6243 blueswir1
 * THE SOFTWARE.
23 3cce6243 blueswir1
 */
24 3cce6243 blueswir1
#include "hw.h"
25 084a197a blueswir1
#include "sysemu.h"
26 3cce6243 blueswir1
#include "isa.h"
27 3cce6243 blueswir1
#include "fw_cfg.h"
28 3a5c16fc Blue Swirl
#include "sysbus.h"
29 3cce6243 blueswir1
30 3cce6243 blueswir1
/* debug firmware config */
31 3cce6243 blueswir1
//#define DEBUG_FW_CFG
32 3cce6243 blueswir1
33 3cce6243 blueswir1
#ifdef DEBUG_FW_CFG
34 001faf32 Blue Swirl
#define FW_CFG_DPRINTF(fmt, ...)                        \
35 001faf32 Blue Swirl
    do { printf("FW_CFG: " fmt , ## __VA_ARGS__); } while (0)
36 3cce6243 blueswir1
#else
37 001faf32 Blue Swirl
#define FW_CFG_DPRINTF(fmt, ...)
38 3cce6243 blueswir1
#endif
39 3cce6243 blueswir1
40 3cce6243 blueswir1
#define FW_CFG_SIZE 2
41 3cce6243 blueswir1
42 b96ae2da Blue Swirl
typedef struct FWCfgEntry {
43 ff06108b Juan Quintela
    uint32_t len;
44 3cce6243 blueswir1
    uint8_t *data;
45 3cce6243 blueswir1
    void *callback_opaque;
46 3cce6243 blueswir1
    FWCfgCallback callback;
47 3cce6243 blueswir1
} FWCfgEntry;
48 3cce6243 blueswir1
49 b96ae2da Blue Swirl
struct FWCfgState {
50 3a5c16fc Blue Swirl
    SysBusDevice busdev;
51 3a5c16fc Blue Swirl
    uint32_t ctl_iobase, data_iobase;
52 3cce6243 blueswir1
    FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
53 abe147e0 Gerd Hoffmann
    FWCfgFiles *files;
54 3cce6243 blueswir1
    uint16_t cur_entry;
55 ff06108b Juan Quintela
    uint32_t cur_offset;
56 c2b5bda4 Gerd Hoffmann
};
57 3cce6243 blueswir1
58 3cce6243 blueswir1
static void fw_cfg_write(FWCfgState *s, uint8_t value)
59 3cce6243 blueswir1
{
60 3cce6243 blueswir1
    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
61 3cce6243 blueswir1
    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
62 3cce6243 blueswir1
63 3cce6243 blueswir1
    FW_CFG_DPRINTF("write %d\n", value);
64 3cce6243 blueswir1
65 3cce6243 blueswir1
    if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) {
66 3cce6243 blueswir1
        e->data[s->cur_offset++] = value;
67 3cce6243 blueswir1
        if (s->cur_offset == e->len) {
68 3cce6243 blueswir1
            e->callback(e->callback_opaque, e->data);
69 3cce6243 blueswir1
            s->cur_offset = 0;
70 3cce6243 blueswir1
        }
71 3cce6243 blueswir1
    }
72 3cce6243 blueswir1
}
73 3cce6243 blueswir1
74 3cce6243 blueswir1
static int fw_cfg_select(FWCfgState *s, uint16_t key)
75 3cce6243 blueswir1
{
76 3cce6243 blueswir1
    int ret;
77 3cce6243 blueswir1
78 3cce6243 blueswir1
    s->cur_offset = 0;
79 3cce6243 blueswir1
    if ((key & FW_CFG_ENTRY_MASK) >= FW_CFG_MAX_ENTRY) {
80 3cce6243 blueswir1
        s->cur_entry = FW_CFG_INVALID;
81 3cce6243 blueswir1
        ret = 0;
82 3cce6243 blueswir1
    } else {
83 3cce6243 blueswir1
        s->cur_entry = key;
84 3cce6243 blueswir1
        ret = 1;
85 3cce6243 blueswir1
    }
86 3cce6243 blueswir1
87 3cce6243 blueswir1
    FW_CFG_DPRINTF("select key %d (%sfound)\n", key, ret ? "" : "not ");
88 3cce6243 blueswir1
89 3cce6243 blueswir1
    return ret;
90 3cce6243 blueswir1
}
91 3cce6243 blueswir1
92 3cce6243 blueswir1
static uint8_t fw_cfg_read(FWCfgState *s)
93 3cce6243 blueswir1
{
94 3cce6243 blueswir1
    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
95 3cce6243 blueswir1
    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
96 3cce6243 blueswir1
    uint8_t ret;
97 3cce6243 blueswir1
98 3cce6243 blueswir1
    if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
99 3cce6243 blueswir1
        ret = 0;
100 3cce6243 blueswir1
    else
101 3cce6243 blueswir1
        ret = e->data[s->cur_offset++];
102 3cce6243 blueswir1
103 3cce6243 blueswir1
    FW_CFG_DPRINTF("read %d\n", ret);
104 3cce6243 blueswir1
105 3cce6243 blueswir1
    return ret;
106 3cce6243 blueswir1
}
107 3cce6243 blueswir1
108 3cce6243 blueswir1
static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
109 3cce6243 blueswir1
{
110 3cce6243 blueswir1
    return fw_cfg_read(opaque);
111 3cce6243 blueswir1
}
112 3cce6243 blueswir1
113 3cce6243 blueswir1
static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
114 3cce6243 blueswir1
{
115 7442511c blueswir1
    fw_cfg_write(opaque, (uint8_t)value);
116 3cce6243 blueswir1
}
117 3cce6243 blueswir1
118 3cce6243 blueswir1
static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
119 3cce6243 blueswir1
{
120 3cce6243 blueswir1
    fw_cfg_select(opaque, (uint16_t)value);
121 3cce6243 blueswir1
}
122 3cce6243 blueswir1
123 c227f099 Anthony Liguori
static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
124 3cce6243 blueswir1
{
125 3cce6243 blueswir1
    return fw_cfg_read(opaque);
126 3cce6243 blueswir1
}
127 3cce6243 blueswir1
128 c227f099 Anthony Liguori
static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
129 3cce6243 blueswir1
                              uint32_t value)
130 3cce6243 blueswir1
{
131 7442511c blueswir1
    fw_cfg_write(opaque, (uint8_t)value);
132 3cce6243 blueswir1
}
133 3cce6243 blueswir1
134 c227f099 Anthony Liguori
static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
135 3cce6243 blueswir1
                              uint32_t value)
136 3cce6243 blueswir1
{
137 3cce6243 blueswir1
    fw_cfg_select(opaque, (uint16_t)value);
138 3cce6243 blueswir1
}
139 3cce6243 blueswir1
140 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const fw_cfg_ctl_mem_read[3] = {
141 3cce6243 blueswir1
    NULL,
142 3cce6243 blueswir1
    NULL,
143 3cce6243 blueswir1
    NULL,
144 3cce6243 blueswir1
};
145 3cce6243 blueswir1
146 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const fw_cfg_ctl_mem_write[3] = {
147 3cce6243 blueswir1
    NULL,
148 3cce6243 blueswir1
    fw_cfg_mem_writew,
149 3cce6243 blueswir1
    NULL,
150 3cce6243 blueswir1
};
151 3cce6243 blueswir1
152 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const fw_cfg_data_mem_read[3] = {
153 3cce6243 blueswir1
    fw_cfg_mem_readb,
154 3cce6243 blueswir1
    NULL,
155 3cce6243 blueswir1
    NULL,
156 3cce6243 blueswir1
};
157 3cce6243 blueswir1
158 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
159 3cce6243 blueswir1
    fw_cfg_mem_writeb,
160 3cce6243 blueswir1
    NULL,
161 3cce6243 blueswir1
    NULL,
162 3cce6243 blueswir1
};
163 3cce6243 blueswir1
164 3a5c16fc Blue Swirl
static void fw_cfg_reset(DeviceState *d)
165 3cce6243 blueswir1
{
166 3a5c16fc Blue Swirl
    FWCfgState *s = DO_UPCAST(FWCfgState, busdev.qdev, d);
167 3cce6243 blueswir1
168 3cce6243 blueswir1
    fw_cfg_select(s, 0);
169 3cce6243 blueswir1
}
170 3cce6243 blueswir1
171 ff06108b Juan Quintela
/* Save restore 32 bit int as uint16_t
172 ff06108b Juan Quintela
   This is a Big hack, but it is how the old state did it.
173 ff06108b Juan Quintela
   Or we broke compatibility in the state, or we can't use struct tm
174 ff06108b Juan Quintela
 */
175 ff06108b Juan Quintela
176 ff06108b Juan Quintela
static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size)
177 ff06108b Juan Quintela
{
178 ff06108b Juan Quintela
    uint32_t *v = pv;
179 ff06108b Juan Quintela
    *v = qemu_get_be16(f);
180 ff06108b Juan Quintela
    return 0;
181 ff06108b Juan Quintela
}
182 ff06108b Juan Quintela
183 ff06108b Juan Quintela
static void put_unused(QEMUFile *f, void *pv, size_t size)
184 ff06108b Juan Quintela
{
185 66c80e75 Vagrant Cascadian
    fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
186 ff06108b Juan Quintela
    fprintf(stderr, "This functions shouldn't be called.\n");
187 ff06108b Juan Quintela
}
188 ff06108b Juan Quintela
189 d05ac8fa Blue Swirl
static const VMStateInfo vmstate_hack_uint32_as_uint16 = {
190 ff06108b Juan Quintela
    .name = "int32_as_uint16",
191 ff06108b Juan Quintela
    .get  = get_uint32_as_uint16,
192 ff06108b Juan Quintela
    .put  = put_unused,
193 ff06108b Juan Quintela
};
194 ff06108b Juan Quintela
195 ff06108b Juan Quintela
#define VMSTATE_UINT16_HACK(_f, _s, _t)                                    \
196 ff06108b Juan Quintela
    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_hack_uint32_as_uint16, uint32_t)
197 ff06108b Juan Quintela
198 ff06108b Juan Quintela
199 ff06108b Juan Quintela
static bool is_version_1(void *opaque, int version_id)
200 ff06108b Juan Quintela
{
201 ff06108b Juan Quintela
    return version_id == 1;
202 ff06108b Juan Quintela
}
203 ff06108b Juan Quintela
204 7d2edd40 Juan Quintela
static const VMStateDescription vmstate_fw_cfg = {
205 7d2edd40 Juan Quintela
    .name = "fw_cfg",
206 ff06108b Juan Quintela
    .version_id = 2,
207 7d2edd40 Juan Quintela
    .minimum_version_id = 1,
208 7d2edd40 Juan Quintela
    .minimum_version_id_old = 1,
209 7d2edd40 Juan Quintela
    .fields      = (VMStateField []) {
210 7d2edd40 Juan Quintela
        VMSTATE_UINT16(cur_entry, FWCfgState),
211 ff06108b Juan Quintela
        VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
212 ff06108b Juan Quintela
        VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
213 7d2edd40 Juan Quintela
        VMSTATE_END_OF_LIST()
214 7d2edd40 Juan Quintela
    }
215 7d2edd40 Juan Quintela
};
216 3cce6243 blueswir1
217 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len)
218 3cce6243 blueswir1
{
219 3cce6243 blueswir1
    int arch = !!(key & FW_CFG_ARCH_LOCAL);
220 3cce6243 blueswir1
221 3cce6243 blueswir1
    key &= FW_CFG_ENTRY_MASK;
222 3cce6243 blueswir1
223 3cce6243 blueswir1
    if (key >= FW_CFG_MAX_ENTRY)
224 3cce6243 blueswir1
        return 0;
225 3cce6243 blueswir1
226 3cce6243 blueswir1
    s->entries[arch][key].data = data;
227 3cce6243 blueswir1
    s->entries[arch][key].len = len;
228 3cce6243 blueswir1
229 3cce6243 blueswir1
    return 1;
230 3cce6243 blueswir1
}
231 3cce6243 blueswir1
232 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value)
233 3cce6243 blueswir1
{
234 3cce6243 blueswir1
    uint16_t *copy;
235 3cce6243 blueswir1
236 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
237 3cce6243 blueswir1
    *copy = cpu_to_le16(value);
238 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
239 3cce6243 blueswir1
}
240 3cce6243 blueswir1
241 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)
242 3cce6243 blueswir1
{
243 3cce6243 blueswir1
    uint32_t *copy;
244 3cce6243 blueswir1
245 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
246 3cce6243 blueswir1
    *copy = cpu_to_le32(value);
247 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
248 3cce6243 blueswir1
}
249 3cce6243 blueswir1
250 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)
251 3cce6243 blueswir1
{
252 3cce6243 blueswir1
    uint64_t *copy;
253 3cce6243 blueswir1
254 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
255 3cce6243 blueswir1
    *copy = cpu_to_le64(value);
256 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
257 3cce6243 blueswir1
}
258 3cce6243 blueswir1
259 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
260 3cce6243 blueswir1
                        void *callback_opaque, uint8_t *data, size_t len)
261 3cce6243 blueswir1
{
262 3cce6243 blueswir1
    int arch = !!(key & FW_CFG_ARCH_LOCAL);
263 3cce6243 blueswir1
264 85df0de4 blueswir1
    if (!(key & FW_CFG_WRITE_CHANNEL))
265 85df0de4 blueswir1
        return 0;
266 85df0de4 blueswir1
267 3cce6243 blueswir1
    key &= FW_CFG_ENTRY_MASK;
268 3cce6243 blueswir1
269 85df0de4 blueswir1
    if (key >= FW_CFG_MAX_ENTRY || len > 65535)
270 3cce6243 blueswir1
        return 0;
271 3cce6243 blueswir1
272 3cce6243 blueswir1
    s->entries[arch][key].data = data;
273 3cce6243 blueswir1
    s->entries[arch][key].len = len;
274 3cce6243 blueswir1
    s->entries[arch][key].callback_opaque = callback_opaque;
275 3cce6243 blueswir1
    s->entries[arch][key].callback = callback;
276 3cce6243 blueswir1
277 3cce6243 blueswir1
    return 1;
278 3cce6243 blueswir1
}
279 3cce6243 blueswir1
280 abe147e0 Gerd Hoffmann
int fw_cfg_add_file(FWCfgState *s,  const char *dir, const char *filename,
281 abe147e0 Gerd Hoffmann
                    uint8_t *data, uint32_t len)
282 abe147e0 Gerd Hoffmann
{
283 abe147e0 Gerd Hoffmann
    const char *basename;
284 de9352bc Gerd Hoffmann
    int i, index;
285 abe147e0 Gerd Hoffmann
286 abe147e0 Gerd Hoffmann
    if (!s->files) {
287 abe147e0 Gerd Hoffmann
        int dsize = sizeof(uint32_t) + sizeof(FWCfgFile) * FW_CFG_FILE_SLOTS;
288 abe147e0 Gerd Hoffmann
        s->files = qemu_mallocz(dsize);
289 abe147e0 Gerd Hoffmann
        fw_cfg_add_bytes(s, FW_CFG_FILE_DIR, (uint8_t*)s->files, dsize);
290 abe147e0 Gerd Hoffmann
    }
291 abe147e0 Gerd Hoffmann
292 abe147e0 Gerd Hoffmann
    index = be32_to_cpu(s->files->count);
293 abe147e0 Gerd Hoffmann
    if (index == FW_CFG_FILE_SLOTS) {
294 abe147e0 Gerd Hoffmann
        fprintf(stderr, "fw_cfg: out of file slots\n");
295 abe147e0 Gerd Hoffmann
        return 0;
296 abe147e0 Gerd Hoffmann
    }
297 abe147e0 Gerd Hoffmann
298 abe147e0 Gerd Hoffmann
    fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
299 abe147e0 Gerd Hoffmann
300 abe147e0 Gerd Hoffmann
    basename = strrchr(filename, '/');
301 abe147e0 Gerd Hoffmann
    if (basename) {
302 abe147e0 Gerd Hoffmann
        basename++;
303 abe147e0 Gerd Hoffmann
    } else {
304 abe147e0 Gerd Hoffmann
        basename = filename;
305 abe147e0 Gerd Hoffmann
    }
306 de9352bc Gerd Hoffmann
307 de9352bc Gerd Hoffmann
    snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
308 de9352bc Gerd Hoffmann
             "%s/%s", dir, basename);
309 de9352bc Gerd Hoffmann
    for (i = 0; i < index; i++) {
310 de9352bc Gerd Hoffmann
        if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
311 de9352bc Gerd Hoffmann
            FW_CFG_DPRINTF("%s: skip duplicate: %s\n", __FUNCTION__,
312 de9352bc Gerd Hoffmann
                           s->files->f[index].name);
313 de9352bc Gerd Hoffmann
            return 1;
314 de9352bc Gerd Hoffmann
        }
315 abe147e0 Gerd Hoffmann
    }
316 de9352bc Gerd Hoffmann
317 abe147e0 Gerd Hoffmann
    s->files->f[index].size   = cpu_to_be32(len);
318 abe147e0 Gerd Hoffmann
    s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
319 abe147e0 Gerd Hoffmann
    FW_CFG_DPRINTF("%s: #%d: %s (%d bytes)\n", __FUNCTION__,
320 abe147e0 Gerd Hoffmann
                   index, s->files->f[index].name, len);
321 abe147e0 Gerd Hoffmann
322 abe147e0 Gerd Hoffmann
    s->files->count = cpu_to_be32(index+1);
323 abe147e0 Gerd Hoffmann
    return 1;
324 abe147e0 Gerd Hoffmann
}
325 abe147e0 Gerd Hoffmann
326 c2b5bda4 Gerd Hoffmann
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
327 c2b5bda4 Gerd Hoffmann
                        target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
328 3cce6243 blueswir1
{
329 3a5c16fc Blue Swirl
    DeviceState *dev;
330 3a5c16fc Blue Swirl
    SysBusDevice *d;
331 3cce6243 blueswir1
    FWCfgState *s;
332 3cce6243 blueswir1
333 3a5c16fc Blue Swirl
    dev = qdev_create(NULL, "fw_cfg");
334 3a5c16fc Blue Swirl
    qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
335 3a5c16fc Blue Swirl
    qdev_prop_set_uint32(dev, "data_iobase", data_port);
336 3a5c16fc Blue Swirl
    qdev_init_nofail(dev);
337 3a5c16fc Blue Swirl
    d = sysbus_from_qdev(dev);
338 3a5c16fc Blue Swirl
339 3a5c16fc Blue Swirl
    s = DO_UPCAST(FWCfgState, busdev.qdev, dev);
340 3cce6243 blueswir1
341 3cce6243 blueswir1
    if (ctl_addr) {
342 3a5c16fc Blue Swirl
        sysbus_mmio_map(d, 0, ctl_addr);
343 3cce6243 blueswir1
    }
344 3cce6243 blueswir1
    if (data_addr) {
345 3a5c16fc Blue Swirl
        sysbus_mmio_map(d, 1, data_addr);
346 3cce6243 blueswir1
    }
347 3cce6243 blueswir1
    fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (uint8_t *)"QEMU", 4);
348 084a197a blueswir1
    fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
349 993fbfdb Anthony Liguori
    fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
350 905fdcb5 blueswir1
    fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
351 6be68d7e Jes Sorensen
    fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
352 95387491 Jan Kiszka
    fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
353 905fdcb5 blueswir1
354 3cce6243 blueswir1
    return s;
355 3cce6243 blueswir1
}
356 3a5c16fc Blue Swirl
357 3a5c16fc Blue Swirl
static int fw_cfg_init1(SysBusDevice *dev)
358 3a5c16fc Blue Swirl
{
359 3a5c16fc Blue Swirl
    FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
360 3a5c16fc Blue Swirl
    int io_ctl_memory, io_data_memory;
361 3a5c16fc Blue Swirl
362 3a5c16fc Blue Swirl
    io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
363 3a5c16fc Blue Swirl
                                           fw_cfg_ctl_mem_write, s);
364 3a5c16fc Blue Swirl
    sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
365 3a5c16fc Blue Swirl
366 3a5c16fc Blue Swirl
    io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
367 3a5c16fc Blue Swirl
                                            fw_cfg_data_mem_write, s);
368 3a5c16fc Blue Swirl
    sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
369 3a5c16fc Blue Swirl
370 3a5c16fc Blue Swirl
    if (s->ctl_iobase) {
371 3a5c16fc Blue Swirl
        register_ioport_write(s->ctl_iobase, 2, 2, fw_cfg_io_writew, s);
372 3a5c16fc Blue Swirl
    }
373 3a5c16fc Blue Swirl
    if (s->data_iobase) {
374 3a5c16fc Blue Swirl
        register_ioport_read(s->data_iobase, 1, 1, fw_cfg_io_readb, s);
375 3a5c16fc Blue Swirl
        register_ioport_write(s->data_iobase, 1, 1, fw_cfg_io_writeb, s);
376 3a5c16fc Blue Swirl
    }
377 3a5c16fc Blue Swirl
    return 0;
378 3a5c16fc Blue Swirl
}
379 3a5c16fc Blue Swirl
380 3a5c16fc Blue Swirl
static SysBusDeviceInfo fw_cfg_info = {
381 3a5c16fc Blue Swirl
    .init = fw_cfg_init1,
382 3a5c16fc Blue Swirl
    .qdev.name = "fw_cfg",
383 3a5c16fc Blue Swirl
    .qdev.size = sizeof(FWCfgState),
384 3a5c16fc Blue Swirl
    .qdev.vmsd = &vmstate_fw_cfg,
385 3a5c16fc Blue Swirl
    .qdev.reset = fw_cfg_reset,
386 3a5c16fc Blue Swirl
    .qdev.no_user = 1,
387 3a5c16fc Blue Swirl
    .qdev.props = (Property[]) {
388 3a5c16fc Blue Swirl
        DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
389 3a5c16fc Blue Swirl
        DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
390 3a5c16fc Blue Swirl
        DEFINE_PROP_END_OF_LIST(),
391 3a5c16fc Blue Swirl
    },
392 3a5c16fc Blue Swirl
};
393 3a5c16fc Blue Swirl
394 3a5c16fc Blue Swirl
static void fw_cfg_register_devices(void)
395 3a5c16fc Blue Swirl
{
396 3a5c16fc Blue Swirl
    sysbus_register_withprop(&fw_cfg_info);
397 3a5c16fc Blue Swirl
}
398 3a5c16fc Blue Swirl
399 3a5c16fc Blue Swirl
device_init(fw_cfg_register_devices)