Statistics
| Branch: | Revision:

root / hw / fw_cfg.c @ e72d5c9d

History | View | Annotate | Download (11.2 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 962630f2 Gleb Natapov
    Notifier machine_ready;
57 c2b5bda4 Gerd Hoffmann
};
58 3cce6243 blueswir1
59 3cce6243 blueswir1
static void fw_cfg_write(FWCfgState *s, uint8_t value)
60 3cce6243 blueswir1
{
61 3cce6243 blueswir1
    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
62 3cce6243 blueswir1
    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
63 3cce6243 blueswir1
64 3cce6243 blueswir1
    FW_CFG_DPRINTF("write %d\n", value);
65 3cce6243 blueswir1
66 3cce6243 blueswir1
    if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) {
67 3cce6243 blueswir1
        e->data[s->cur_offset++] = value;
68 3cce6243 blueswir1
        if (s->cur_offset == e->len) {
69 3cce6243 blueswir1
            e->callback(e->callback_opaque, e->data);
70 3cce6243 blueswir1
            s->cur_offset = 0;
71 3cce6243 blueswir1
        }
72 3cce6243 blueswir1
    }
73 3cce6243 blueswir1
}
74 3cce6243 blueswir1
75 3cce6243 blueswir1
static int fw_cfg_select(FWCfgState *s, uint16_t key)
76 3cce6243 blueswir1
{
77 3cce6243 blueswir1
    int ret;
78 3cce6243 blueswir1
79 3cce6243 blueswir1
    s->cur_offset = 0;
80 3cce6243 blueswir1
    if ((key & FW_CFG_ENTRY_MASK) >= FW_CFG_MAX_ENTRY) {
81 3cce6243 blueswir1
        s->cur_entry = FW_CFG_INVALID;
82 3cce6243 blueswir1
        ret = 0;
83 3cce6243 blueswir1
    } else {
84 3cce6243 blueswir1
        s->cur_entry = key;
85 3cce6243 blueswir1
        ret = 1;
86 3cce6243 blueswir1
    }
87 3cce6243 blueswir1
88 3cce6243 blueswir1
    FW_CFG_DPRINTF("select key %d (%sfound)\n", key, ret ? "" : "not ");
89 3cce6243 blueswir1
90 3cce6243 blueswir1
    return ret;
91 3cce6243 blueswir1
}
92 3cce6243 blueswir1
93 3cce6243 blueswir1
static uint8_t fw_cfg_read(FWCfgState *s)
94 3cce6243 blueswir1
{
95 3cce6243 blueswir1
    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
96 3cce6243 blueswir1
    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
97 3cce6243 blueswir1
    uint8_t ret;
98 3cce6243 blueswir1
99 3cce6243 blueswir1
    if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
100 3cce6243 blueswir1
        ret = 0;
101 3cce6243 blueswir1
    else
102 3cce6243 blueswir1
        ret = e->data[s->cur_offset++];
103 3cce6243 blueswir1
104 3cce6243 blueswir1
    FW_CFG_DPRINTF("read %d\n", ret);
105 3cce6243 blueswir1
106 3cce6243 blueswir1
    return ret;
107 3cce6243 blueswir1
}
108 3cce6243 blueswir1
109 3cce6243 blueswir1
static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
110 3cce6243 blueswir1
{
111 3cce6243 blueswir1
    return fw_cfg_read(opaque);
112 3cce6243 blueswir1
}
113 3cce6243 blueswir1
114 3cce6243 blueswir1
static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
115 3cce6243 blueswir1
{
116 7442511c blueswir1
    fw_cfg_write(opaque, (uint8_t)value);
117 3cce6243 blueswir1
}
118 3cce6243 blueswir1
119 3cce6243 blueswir1
static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
120 3cce6243 blueswir1
{
121 3cce6243 blueswir1
    fw_cfg_select(opaque, (uint16_t)value);
122 3cce6243 blueswir1
}
123 3cce6243 blueswir1
124 c227f099 Anthony Liguori
static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
125 3cce6243 blueswir1
{
126 3cce6243 blueswir1
    return fw_cfg_read(opaque);
127 3cce6243 blueswir1
}
128 3cce6243 blueswir1
129 c227f099 Anthony Liguori
static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
130 3cce6243 blueswir1
                              uint32_t value)
131 3cce6243 blueswir1
{
132 7442511c blueswir1
    fw_cfg_write(opaque, (uint8_t)value);
133 3cce6243 blueswir1
}
134 3cce6243 blueswir1
135 c227f099 Anthony Liguori
static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
136 3cce6243 blueswir1
                              uint32_t value)
137 3cce6243 blueswir1
{
138 3cce6243 blueswir1
    fw_cfg_select(opaque, (uint16_t)value);
139 3cce6243 blueswir1
}
140 3cce6243 blueswir1
141 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const fw_cfg_ctl_mem_read[3] = {
142 3cce6243 blueswir1
    NULL,
143 3cce6243 blueswir1
    NULL,
144 3cce6243 blueswir1
    NULL,
145 3cce6243 blueswir1
};
146 3cce6243 blueswir1
147 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const fw_cfg_ctl_mem_write[3] = {
148 3cce6243 blueswir1
    NULL,
149 3cce6243 blueswir1
    fw_cfg_mem_writew,
150 3cce6243 blueswir1
    NULL,
151 3cce6243 blueswir1
};
152 3cce6243 blueswir1
153 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const fw_cfg_data_mem_read[3] = {
154 3cce6243 blueswir1
    fw_cfg_mem_readb,
155 3cce6243 blueswir1
    NULL,
156 3cce6243 blueswir1
    NULL,
157 3cce6243 blueswir1
};
158 3cce6243 blueswir1
159 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
160 3cce6243 blueswir1
    fw_cfg_mem_writeb,
161 3cce6243 blueswir1
    NULL,
162 3cce6243 blueswir1
    NULL,
163 3cce6243 blueswir1
};
164 3cce6243 blueswir1
165 3a5c16fc Blue Swirl
static void fw_cfg_reset(DeviceState *d)
166 3cce6243 blueswir1
{
167 3a5c16fc Blue Swirl
    FWCfgState *s = DO_UPCAST(FWCfgState, busdev.qdev, d);
168 3cce6243 blueswir1
169 3cce6243 blueswir1
    fw_cfg_select(s, 0);
170 3cce6243 blueswir1
}
171 3cce6243 blueswir1
172 ff06108b Juan Quintela
/* Save restore 32 bit int as uint16_t
173 ff06108b Juan Quintela
   This is a Big hack, but it is how the old state did it.
174 ff06108b Juan Quintela
   Or we broke compatibility in the state, or we can't use struct tm
175 ff06108b Juan Quintela
 */
176 ff06108b Juan Quintela
177 ff06108b Juan Quintela
static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size)
178 ff06108b Juan Quintela
{
179 ff06108b Juan Quintela
    uint32_t *v = pv;
180 ff06108b Juan Quintela
    *v = qemu_get_be16(f);
181 ff06108b Juan Quintela
    return 0;
182 ff06108b Juan Quintela
}
183 ff06108b Juan Quintela
184 ff06108b Juan Quintela
static void put_unused(QEMUFile *f, void *pv, size_t size)
185 ff06108b Juan Quintela
{
186 66c80e75 Vagrant Cascadian
    fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
187 ff06108b Juan Quintela
    fprintf(stderr, "This functions shouldn't be called.\n");
188 ff06108b Juan Quintela
}
189 ff06108b Juan Quintela
190 d05ac8fa Blue Swirl
static const VMStateInfo vmstate_hack_uint32_as_uint16 = {
191 ff06108b Juan Quintela
    .name = "int32_as_uint16",
192 ff06108b Juan Quintela
    .get  = get_uint32_as_uint16,
193 ff06108b Juan Quintela
    .put  = put_unused,
194 ff06108b Juan Quintela
};
195 ff06108b Juan Quintela
196 ff06108b Juan Quintela
#define VMSTATE_UINT16_HACK(_f, _s, _t)                                    \
197 ff06108b Juan Quintela
    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_hack_uint32_as_uint16, uint32_t)
198 ff06108b Juan Quintela
199 ff06108b Juan Quintela
200 ff06108b Juan Quintela
static bool is_version_1(void *opaque, int version_id)
201 ff06108b Juan Quintela
{
202 ff06108b Juan Quintela
    return version_id == 1;
203 ff06108b Juan Quintela
}
204 ff06108b Juan Quintela
205 7d2edd40 Juan Quintela
static const VMStateDescription vmstate_fw_cfg = {
206 7d2edd40 Juan Quintela
    .name = "fw_cfg",
207 ff06108b Juan Quintela
    .version_id = 2,
208 7d2edd40 Juan Quintela
    .minimum_version_id = 1,
209 7d2edd40 Juan Quintela
    .minimum_version_id_old = 1,
210 7d2edd40 Juan Quintela
    .fields      = (VMStateField []) {
211 7d2edd40 Juan Quintela
        VMSTATE_UINT16(cur_entry, FWCfgState),
212 ff06108b Juan Quintela
        VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
213 ff06108b Juan Quintela
        VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
214 7d2edd40 Juan Quintela
        VMSTATE_END_OF_LIST()
215 7d2edd40 Juan Quintela
    }
216 7d2edd40 Juan Quintela
};
217 3cce6243 blueswir1
218 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len)
219 3cce6243 blueswir1
{
220 3cce6243 blueswir1
    int arch = !!(key & FW_CFG_ARCH_LOCAL);
221 3cce6243 blueswir1
222 3cce6243 blueswir1
    key &= FW_CFG_ENTRY_MASK;
223 3cce6243 blueswir1
224 3cce6243 blueswir1
    if (key >= FW_CFG_MAX_ENTRY)
225 3cce6243 blueswir1
        return 0;
226 3cce6243 blueswir1
227 3cce6243 blueswir1
    s->entries[arch][key].data = data;
228 3cce6243 blueswir1
    s->entries[arch][key].len = len;
229 3cce6243 blueswir1
230 3cce6243 blueswir1
    return 1;
231 3cce6243 blueswir1
}
232 3cce6243 blueswir1
233 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value)
234 3cce6243 blueswir1
{
235 3cce6243 blueswir1
    uint16_t *copy;
236 3cce6243 blueswir1
237 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
238 3cce6243 blueswir1
    *copy = cpu_to_le16(value);
239 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
240 3cce6243 blueswir1
}
241 3cce6243 blueswir1
242 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)
243 3cce6243 blueswir1
{
244 3cce6243 blueswir1
    uint32_t *copy;
245 3cce6243 blueswir1
246 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
247 3cce6243 blueswir1
    *copy = cpu_to_le32(value);
248 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
249 3cce6243 blueswir1
}
250 3cce6243 blueswir1
251 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)
252 3cce6243 blueswir1
{
253 3cce6243 blueswir1
    uint64_t *copy;
254 3cce6243 blueswir1
255 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
256 3cce6243 blueswir1
    *copy = cpu_to_le64(value);
257 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
258 3cce6243 blueswir1
}
259 3cce6243 blueswir1
260 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
261 3cce6243 blueswir1
                        void *callback_opaque, uint8_t *data, size_t len)
262 3cce6243 blueswir1
{
263 3cce6243 blueswir1
    int arch = !!(key & FW_CFG_ARCH_LOCAL);
264 3cce6243 blueswir1
265 85df0de4 blueswir1
    if (!(key & FW_CFG_WRITE_CHANNEL))
266 85df0de4 blueswir1
        return 0;
267 85df0de4 blueswir1
268 3cce6243 blueswir1
    key &= FW_CFG_ENTRY_MASK;
269 3cce6243 blueswir1
270 85df0de4 blueswir1
    if (key >= FW_CFG_MAX_ENTRY || len > 65535)
271 3cce6243 blueswir1
        return 0;
272 3cce6243 blueswir1
273 3cce6243 blueswir1
    s->entries[arch][key].data = data;
274 3cce6243 blueswir1
    s->entries[arch][key].len = len;
275 3cce6243 blueswir1
    s->entries[arch][key].callback_opaque = callback_opaque;
276 3cce6243 blueswir1
    s->entries[arch][key].callback = callback;
277 3cce6243 blueswir1
278 3cce6243 blueswir1
    return 1;
279 3cce6243 blueswir1
}
280 3cce6243 blueswir1
281 de1f34cb Gleb Natapov
int fw_cfg_add_file(FWCfgState *s,  const char *filename, uint8_t *data,
282 de1f34cb Gleb Natapov
                    uint32_t len)
283 abe147e0 Gerd Hoffmann
{
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 de1f34cb Gleb Natapov
    pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
301 de1f34cb Gleb Natapov
            filename);
302 de9352bc Gerd Hoffmann
    for (i = 0; i < index; i++) {
303 de9352bc Gerd Hoffmann
        if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
304 de9352bc Gerd Hoffmann
            FW_CFG_DPRINTF("%s: skip duplicate: %s\n", __FUNCTION__,
305 de9352bc Gerd Hoffmann
                           s->files->f[index].name);
306 de9352bc Gerd Hoffmann
            return 1;
307 de9352bc Gerd Hoffmann
        }
308 abe147e0 Gerd Hoffmann
    }
309 de9352bc Gerd Hoffmann
310 abe147e0 Gerd Hoffmann
    s->files->f[index].size   = cpu_to_be32(len);
311 abe147e0 Gerd Hoffmann
    s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
312 abe147e0 Gerd Hoffmann
    FW_CFG_DPRINTF("%s: #%d: %s (%d bytes)\n", __FUNCTION__,
313 abe147e0 Gerd Hoffmann
                   index, s->files->f[index].name, len);
314 abe147e0 Gerd Hoffmann
315 abe147e0 Gerd Hoffmann
    s->files->count = cpu_to_be32(index+1);
316 abe147e0 Gerd Hoffmann
    return 1;
317 abe147e0 Gerd Hoffmann
}
318 abe147e0 Gerd Hoffmann
319 962630f2 Gleb Natapov
static void fw_cfg_machine_ready(struct Notifier* n)
320 962630f2 Gleb Natapov
{
321 962630f2 Gleb Natapov
    uint32_t len;
322 962630f2 Gleb Natapov
    FWCfgState *s = container_of(n, FWCfgState, machine_ready);
323 962630f2 Gleb Natapov
    char *bootindex = get_boot_devices_list(&len);
324 962630f2 Gleb Natapov
325 962630f2 Gleb Natapov
    fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
326 962630f2 Gleb Natapov
}
327 962630f2 Gleb Natapov
328 c2b5bda4 Gerd Hoffmann
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
329 c2b5bda4 Gerd Hoffmann
                        target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
330 3cce6243 blueswir1
{
331 3a5c16fc Blue Swirl
    DeviceState *dev;
332 3a5c16fc Blue Swirl
    SysBusDevice *d;
333 3cce6243 blueswir1
    FWCfgState *s;
334 3cce6243 blueswir1
335 3a5c16fc Blue Swirl
    dev = qdev_create(NULL, "fw_cfg");
336 3a5c16fc Blue Swirl
    qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
337 3a5c16fc Blue Swirl
    qdev_prop_set_uint32(dev, "data_iobase", data_port);
338 3a5c16fc Blue Swirl
    qdev_init_nofail(dev);
339 3a5c16fc Blue Swirl
    d = sysbus_from_qdev(dev);
340 3a5c16fc Blue Swirl
341 3a5c16fc Blue Swirl
    s = DO_UPCAST(FWCfgState, busdev.qdev, dev);
342 3cce6243 blueswir1
343 3cce6243 blueswir1
    if (ctl_addr) {
344 3a5c16fc Blue Swirl
        sysbus_mmio_map(d, 0, ctl_addr);
345 3cce6243 blueswir1
    }
346 3cce6243 blueswir1
    if (data_addr) {
347 3a5c16fc Blue Swirl
        sysbus_mmio_map(d, 1, data_addr);
348 3cce6243 blueswir1
    }
349 3cce6243 blueswir1
    fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (uint8_t *)"QEMU", 4);
350 084a197a blueswir1
    fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
351 993fbfdb Anthony Liguori
    fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
352 905fdcb5 blueswir1
    fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
353 6be68d7e Jes Sorensen
    fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
354 95387491 Jan Kiszka
    fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
355 905fdcb5 blueswir1
356 962630f2 Gleb Natapov
357 962630f2 Gleb Natapov
    s->machine_ready.notify = fw_cfg_machine_ready;
358 962630f2 Gleb Natapov
    qemu_add_machine_init_done_notifier(&s->machine_ready);
359 962630f2 Gleb Natapov
360 3cce6243 blueswir1
    return s;
361 3cce6243 blueswir1
}
362 3a5c16fc Blue Swirl
363 3a5c16fc Blue Swirl
static int fw_cfg_init1(SysBusDevice *dev)
364 3a5c16fc Blue Swirl
{
365 3a5c16fc Blue Swirl
    FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
366 3a5c16fc Blue Swirl
    int io_ctl_memory, io_data_memory;
367 3a5c16fc Blue Swirl
368 3a5c16fc Blue Swirl
    io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
369 2507c12a Alexander Graf
                                           fw_cfg_ctl_mem_write, s,
370 2507c12a Alexander Graf
                                           DEVICE_NATIVE_ENDIAN);
371 3a5c16fc Blue Swirl
    sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
372 3a5c16fc Blue Swirl
373 3a5c16fc Blue Swirl
    io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
374 2507c12a Alexander Graf
                                            fw_cfg_data_mem_write, s,
375 2507c12a Alexander Graf
                                            DEVICE_NATIVE_ENDIAN);
376 3a5c16fc Blue Swirl
    sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
377 3a5c16fc Blue Swirl
378 3a5c16fc Blue Swirl
    if (s->ctl_iobase) {
379 3a5c16fc Blue Swirl
        register_ioport_write(s->ctl_iobase, 2, 2, fw_cfg_io_writew, s);
380 3a5c16fc Blue Swirl
    }
381 3a5c16fc Blue Swirl
    if (s->data_iobase) {
382 3a5c16fc Blue Swirl
        register_ioport_read(s->data_iobase, 1, 1, fw_cfg_io_readb, s);
383 3a5c16fc Blue Swirl
        register_ioport_write(s->data_iobase, 1, 1, fw_cfg_io_writeb, s);
384 3a5c16fc Blue Swirl
    }
385 3a5c16fc Blue Swirl
    return 0;
386 3a5c16fc Blue Swirl
}
387 3a5c16fc Blue Swirl
388 3a5c16fc Blue Swirl
static SysBusDeviceInfo fw_cfg_info = {
389 3a5c16fc Blue Swirl
    .init = fw_cfg_init1,
390 3a5c16fc Blue Swirl
    .qdev.name = "fw_cfg",
391 3a5c16fc Blue Swirl
    .qdev.size = sizeof(FWCfgState),
392 3a5c16fc Blue Swirl
    .qdev.vmsd = &vmstate_fw_cfg,
393 3a5c16fc Blue Swirl
    .qdev.reset = fw_cfg_reset,
394 3a5c16fc Blue Swirl
    .qdev.no_user = 1,
395 3a5c16fc Blue Swirl
    .qdev.props = (Property[]) {
396 3a5c16fc Blue Swirl
        DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
397 3a5c16fc Blue Swirl
        DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
398 3a5c16fc Blue Swirl
        DEFINE_PROP_END_OF_LIST(),
399 3a5c16fc Blue Swirl
    },
400 3a5c16fc Blue Swirl
};
401 3a5c16fc Blue Swirl
402 3a5c16fc Blue Swirl
static void fw_cfg_register_devices(void)
403 3a5c16fc Blue Swirl
{
404 3a5c16fc Blue Swirl
    sysbus_register_withprop(&fw_cfg_info);
405 3a5c16fc Blue Swirl
}
406 3a5c16fc Blue Swirl
407 3a5c16fc Blue Swirl
device_init(fw_cfg_register_devices)