Statistics
| Branch: | Revision:

root / hw / fw_cfg.c @ c494dd6f

History | View | Annotate | Download (9.8 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 3cce6243 blueswir1
29 3cce6243 blueswir1
/* debug firmware config */
30 3cce6243 blueswir1
//#define DEBUG_FW_CFG
31 3cce6243 blueswir1
32 3cce6243 blueswir1
#ifdef DEBUG_FW_CFG
33 001faf32 Blue Swirl
#define FW_CFG_DPRINTF(fmt, ...)                        \
34 001faf32 Blue Swirl
    do { printf("FW_CFG: " fmt , ## __VA_ARGS__); } while (0)
35 3cce6243 blueswir1
#else
36 001faf32 Blue Swirl
#define FW_CFG_DPRINTF(fmt, ...)
37 3cce6243 blueswir1
#endif
38 3cce6243 blueswir1
39 3cce6243 blueswir1
#define FW_CFG_SIZE 2
40 3cce6243 blueswir1
41 b96ae2da Blue Swirl
typedef struct FWCfgEntry {
42 ff06108b Juan Quintela
    uint32_t len;
43 3cce6243 blueswir1
    uint8_t *data;
44 3cce6243 blueswir1
    void *callback_opaque;
45 3cce6243 blueswir1
    FWCfgCallback callback;
46 3cce6243 blueswir1
} FWCfgEntry;
47 3cce6243 blueswir1
48 b96ae2da Blue Swirl
struct FWCfgState {
49 3cce6243 blueswir1
    FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
50 abe147e0 Gerd Hoffmann
    FWCfgFiles *files;
51 3cce6243 blueswir1
    uint16_t cur_entry;
52 ff06108b Juan Quintela
    uint32_t cur_offset;
53 c2b5bda4 Gerd Hoffmann
};
54 3cce6243 blueswir1
55 3cce6243 blueswir1
static void fw_cfg_write(FWCfgState *s, uint8_t value)
56 3cce6243 blueswir1
{
57 3cce6243 blueswir1
    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
58 3cce6243 blueswir1
    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
59 3cce6243 blueswir1
60 3cce6243 blueswir1
    FW_CFG_DPRINTF("write %d\n", value);
61 3cce6243 blueswir1
62 3cce6243 blueswir1
    if (s->cur_entry & FW_CFG_WRITE_CHANNEL && s->cur_offset < e->len) {
63 3cce6243 blueswir1
        e->data[s->cur_offset++] = value;
64 3cce6243 blueswir1
        if (s->cur_offset == e->len) {
65 3cce6243 blueswir1
            e->callback(e->callback_opaque, e->data);
66 3cce6243 blueswir1
            s->cur_offset = 0;
67 3cce6243 blueswir1
        }
68 3cce6243 blueswir1
    }
69 3cce6243 blueswir1
}
70 3cce6243 blueswir1
71 3cce6243 blueswir1
static int fw_cfg_select(FWCfgState *s, uint16_t key)
72 3cce6243 blueswir1
{
73 3cce6243 blueswir1
    int ret;
74 3cce6243 blueswir1
75 3cce6243 blueswir1
    s->cur_offset = 0;
76 3cce6243 blueswir1
    if ((key & FW_CFG_ENTRY_MASK) >= FW_CFG_MAX_ENTRY) {
77 3cce6243 blueswir1
        s->cur_entry = FW_CFG_INVALID;
78 3cce6243 blueswir1
        ret = 0;
79 3cce6243 blueswir1
    } else {
80 3cce6243 blueswir1
        s->cur_entry = key;
81 3cce6243 blueswir1
        ret = 1;
82 3cce6243 blueswir1
    }
83 3cce6243 blueswir1
84 3cce6243 blueswir1
    FW_CFG_DPRINTF("select key %d (%sfound)\n", key, ret ? "" : "not ");
85 3cce6243 blueswir1
86 3cce6243 blueswir1
    return ret;
87 3cce6243 blueswir1
}
88 3cce6243 blueswir1
89 3cce6243 blueswir1
static uint8_t fw_cfg_read(FWCfgState *s)
90 3cce6243 blueswir1
{
91 3cce6243 blueswir1
    int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
92 3cce6243 blueswir1
    FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
93 3cce6243 blueswir1
    uint8_t ret;
94 3cce6243 blueswir1
95 3cce6243 blueswir1
    if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len)
96 3cce6243 blueswir1
        ret = 0;
97 3cce6243 blueswir1
    else
98 3cce6243 blueswir1
        ret = e->data[s->cur_offset++];
99 3cce6243 blueswir1
100 3cce6243 blueswir1
    FW_CFG_DPRINTF("read %d\n", ret);
101 3cce6243 blueswir1
102 3cce6243 blueswir1
    return ret;
103 3cce6243 blueswir1
}
104 3cce6243 blueswir1
105 3cce6243 blueswir1
static uint32_t fw_cfg_io_readb(void *opaque, uint32_t addr)
106 3cce6243 blueswir1
{
107 3cce6243 blueswir1
    return fw_cfg_read(opaque);
108 3cce6243 blueswir1
}
109 3cce6243 blueswir1
110 3cce6243 blueswir1
static void fw_cfg_io_writeb(void *opaque, uint32_t addr, uint32_t value)
111 3cce6243 blueswir1
{
112 7442511c blueswir1
    fw_cfg_write(opaque, (uint8_t)value);
113 3cce6243 blueswir1
}
114 3cce6243 blueswir1
115 3cce6243 blueswir1
static void fw_cfg_io_writew(void *opaque, uint32_t addr, uint32_t value)
116 3cce6243 blueswir1
{
117 3cce6243 blueswir1
    fw_cfg_select(opaque, (uint16_t)value);
118 3cce6243 blueswir1
}
119 3cce6243 blueswir1
120 c227f099 Anthony Liguori
static uint32_t fw_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
121 3cce6243 blueswir1
{
122 3cce6243 blueswir1
    return fw_cfg_read(opaque);
123 3cce6243 blueswir1
}
124 3cce6243 blueswir1
125 c227f099 Anthony Liguori
static void fw_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
126 3cce6243 blueswir1
                              uint32_t value)
127 3cce6243 blueswir1
{
128 7442511c blueswir1
    fw_cfg_write(opaque, (uint8_t)value);
129 3cce6243 blueswir1
}
130 3cce6243 blueswir1
131 c227f099 Anthony Liguori
static void fw_cfg_mem_writew(void *opaque, target_phys_addr_t addr,
132 3cce6243 blueswir1
                              uint32_t value)
133 3cce6243 blueswir1
{
134 3cce6243 blueswir1
    fw_cfg_select(opaque, (uint16_t)value);
135 3cce6243 blueswir1
}
136 3cce6243 blueswir1
137 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const fw_cfg_ctl_mem_read[3] = {
138 3cce6243 blueswir1
    NULL,
139 3cce6243 blueswir1
    NULL,
140 3cce6243 blueswir1
    NULL,
141 3cce6243 blueswir1
};
142 3cce6243 blueswir1
143 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const fw_cfg_ctl_mem_write[3] = {
144 3cce6243 blueswir1
    NULL,
145 3cce6243 blueswir1
    fw_cfg_mem_writew,
146 3cce6243 blueswir1
    NULL,
147 3cce6243 blueswir1
};
148 3cce6243 blueswir1
149 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const fw_cfg_data_mem_read[3] = {
150 3cce6243 blueswir1
    fw_cfg_mem_readb,
151 3cce6243 blueswir1
    NULL,
152 3cce6243 blueswir1
    NULL,
153 3cce6243 blueswir1
};
154 3cce6243 blueswir1
155 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
156 3cce6243 blueswir1
    fw_cfg_mem_writeb,
157 3cce6243 blueswir1
    NULL,
158 3cce6243 blueswir1
    NULL,
159 3cce6243 blueswir1
};
160 3cce6243 blueswir1
161 3cce6243 blueswir1
static void fw_cfg_reset(void *opaque)
162 3cce6243 blueswir1
{
163 3cce6243 blueswir1
    FWCfgState *s = opaque;
164 3cce6243 blueswir1
165 3cce6243 blueswir1
    fw_cfg_select(s, 0);
166 3cce6243 blueswir1
}
167 3cce6243 blueswir1
168 ff06108b Juan Quintela
/* Save restore 32 bit int as uint16_t
169 ff06108b Juan Quintela
   This is a Big hack, but it is how the old state did it.
170 ff06108b Juan Quintela
   Or we broke compatibility in the state, or we can't use struct tm
171 ff06108b Juan Quintela
 */
172 ff06108b Juan Quintela
173 ff06108b Juan Quintela
static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size)
174 ff06108b Juan Quintela
{
175 ff06108b Juan Quintela
    uint32_t *v = pv;
176 ff06108b Juan Quintela
    *v = qemu_get_be16(f);
177 ff06108b Juan Quintela
    return 0;
178 ff06108b Juan Quintela
}
179 ff06108b Juan Quintela
180 ff06108b Juan Quintela
static void put_unused(QEMUFile *f, void *pv, size_t size)
181 ff06108b Juan Quintela
{
182 66c80e75 Vagrant Cascadian
    fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
183 ff06108b Juan Quintela
    fprintf(stderr, "This functions shouldn't be called.\n");
184 ff06108b Juan Quintela
}
185 ff06108b Juan Quintela
186 d05ac8fa Blue Swirl
static const VMStateInfo vmstate_hack_uint32_as_uint16 = {
187 ff06108b Juan Quintela
    .name = "int32_as_uint16",
188 ff06108b Juan Quintela
    .get  = get_uint32_as_uint16,
189 ff06108b Juan Quintela
    .put  = put_unused,
190 ff06108b Juan Quintela
};
191 ff06108b Juan Quintela
192 ff06108b Juan Quintela
#define VMSTATE_UINT16_HACK(_f, _s, _t)                                    \
193 ff06108b Juan Quintela
    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_hack_uint32_as_uint16, uint32_t)
194 ff06108b Juan Quintela
195 ff06108b Juan Quintela
196 ff06108b Juan Quintela
static bool is_version_1(void *opaque, int version_id)
197 ff06108b Juan Quintela
{
198 ff06108b Juan Quintela
    return version_id == 1;
199 ff06108b Juan Quintela
}
200 ff06108b Juan Quintela
201 7d2edd40 Juan Quintela
static const VMStateDescription vmstate_fw_cfg = {
202 7d2edd40 Juan Quintela
    .name = "fw_cfg",
203 ff06108b Juan Quintela
    .version_id = 2,
204 7d2edd40 Juan Quintela
    .minimum_version_id = 1,
205 7d2edd40 Juan Quintela
    .minimum_version_id_old = 1,
206 7d2edd40 Juan Quintela
    .fields      = (VMStateField []) {
207 7d2edd40 Juan Quintela
        VMSTATE_UINT16(cur_entry, FWCfgState),
208 ff06108b Juan Quintela
        VMSTATE_UINT16_HACK(cur_offset, FWCfgState, is_version_1),
209 ff06108b Juan Quintela
        VMSTATE_UINT32_V(cur_offset, FWCfgState, 2),
210 7d2edd40 Juan Quintela
        VMSTATE_END_OF_LIST()
211 7d2edd40 Juan Quintela
    }
212 7d2edd40 Juan Quintela
};
213 3cce6243 blueswir1
214 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len)
215 3cce6243 blueswir1
{
216 3cce6243 blueswir1
    int arch = !!(key & FW_CFG_ARCH_LOCAL);
217 3cce6243 blueswir1
218 3cce6243 blueswir1
    key &= FW_CFG_ENTRY_MASK;
219 3cce6243 blueswir1
220 3cce6243 blueswir1
    if (key >= FW_CFG_MAX_ENTRY)
221 3cce6243 blueswir1
        return 0;
222 3cce6243 blueswir1
223 3cce6243 blueswir1
    s->entries[arch][key].data = data;
224 3cce6243 blueswir1
    s->entries[arch][key].len = len;
225 3cce6243 blueswir1
226 3cce6243 blueswir1
    return 1;
227 3cce6243 blueswir1
}
228 3cce6243 blueswir1
229 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value)
230 3cce6243 blueswir1
{
231 3cce6243 blueswir1
    uint16_t *copy;
232 3cce6243 blueswir1
233 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
234 3cce6243 blueswir1
    *copy = cpu_to_le16(value);
235 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
236 3cce6243 blueswir1
}
237 3cce6243 blueswir1
238 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)
239 3cce6243 blueswir1
{
240 3cce6243 blueswir1
    uint32_t *copy;
241 3cce6243 blueswir1
242 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
243 3cce6243 blueswir1
    *copy = cpu_to_le32(value);
244 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
245 3cce6243 blueswir1
}
246 3cce6243 blueswir1
247 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)
248 3cce6243 blueswir1
{
249 3cce6243 blueswir1
    uint64_t *copy;
250 3cce6243 blueswir1
251 3cce6243 blueswir1
    copy = qemu_malloc(sizeof(value));
252 3cce6243 blueswir1
    *copy = cpu_to_le64(value);
253 c2b5bda4 Gerd Hoffmann
    return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
254 3cce6243 blueswir1
}
255 3cce6243 blueswir1
256 c2b5bda4 Gerd Hoffmann
int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
257 3cce6243 blueswir1
                        void *callback_opaque, uint8_t *data, size_t len)
258 3cce6243 blueswir1
{
259 3cce6243 blueswir1
    int arch = !!(key & FW_CFG_ARCH_LOCAL);
260 3cce6243 blueswir1
261 85df0de4 blueswir1
    if (!(key & FW_CFG_WRITE_CHANNEL))
262 85df0de4 blueswir1
        return 0;
263 85df0de4 blueswir1
264 3cce6243 blueswir1
    key &= FW_CFG_ENTRY_MASK;
265 3cce6243 blueswir1
266 85df0de4 blueswir1
    if (key >= FW_CFG_MAX_ENTRY || len > 65535)
267 3cce6243 blueswir1
        return 0;
268 3cce6243 blueswir1
269 3cce6243 blueswir1
    s->entries[arch][key].data = data;
270 3cce6243 blueswir1
    s->entries[arch][key].len = len;
271 3cce6243 blueswir1
    s->entries[arch][key].callback_opaque = callback_opaque;
272 3cce6243 blueswir1
    s->entries[arch][key].callback = callback;
273 3cce6243 blueswir1
274 3cce6243 blueswir1
    return 1;
275 3cce6243 blueswir1
}
276 3cce6243 blueswir1
277 abe147e0 Gerd Hoffmann
int fw_cfg_add_file(FWCfgState *s,  const char *dir, const char *filename,
278 abe147e0 Gerd Hoffmann
                    uint8_t *data, uint32_t len)
279 abe147e0 Gerd Hoffmann
{
280 abe147e0 Gerd Hoffmann
    const char *basename;
281 de9352bc Gerd Hoffmann
    int i, index;
282 abe147e0 Gerd Hoffmann
283 abe147e0 Gerd Hoffmann
    if (!s->files) {
284 abe147e0 Gerd Hoffmann
        int dsize = sizeof(uint32_t) + sizeof(FWCfgFile) * FW_CFG_FILE_SLOTS;
285 abe147e0 Gerd Hoffmann
        s->files = qemu_mallocz(dsize);
286 abe147e0 Gerd Hoffmann
        fw_cfg_add_bytes(s, FW_CFG_FILE_DIR, (uint8_t*)s->files, dsize);
287 abe147e0 Gerd Hoffmann
    }
288 abe147e0 Gerd Hoffmann
289 abe147e0 Gerd Hoffmann
    index = be32_to_cpu(s->files->count);
290 abe147e0 Gerd Hoffmann
    if (index == FW_CFG_FILE_SLOTS) {
291 abe147e0 Gerd Hoffmann
        fprintf(stderr, "fw_cfg: out of file slots\n");
292 abe147e0 Gerd Hoffmann
        return 0;
293 abe147e0 Gerd Hoffmann
    }
294 abe147e0 Gerd Hoffmann
295 abe147e0 Gerd Hoffmann
    fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
296 abe147e0 Gerd Hoffmann
297 abe147e0 Gerd Hoffmann
    basename = strrchr(filename, '/');
298 abe147e0 Gerd Hoffmann
    if (basename) {
299 abe147e0 Gerd Hoffmann
        basename++;
300 abe147e0 Gerd Hoffmann
    } else {
301 abe147e0 Gerd Hoffmann
        basename = filename;
302 abe147e0 Gerd Hoffmann
    }
303 de9352bc Gerd Hoffmann
304 de9352bc Gerd Hoffmann
    snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
305 de9352bc Gerd Hoffmann
             "%s/%s", dir, basename);
306 de9352bc Gerd Hoffmann
    for (i = 0; i < index; i++) {
307 de9352bc Gerd Hoffmann
        if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
308 de9352bc Gerd Hoffmann
            FW_CFG_DPRINTF("%s: skip duplicate: %s\n", __FUNCTION__,
309 de9352bc Gerd Hoffmann
                           s->files->f[index].name);
310 de9352bc Gerd Hoffmann
            return 1;
311 de9352bc Gerd Hoffmann
        }
312 abe147e0 Gerd Hoffmann
    }
313 de9352bc Gerd Hoffmann
314 abe147e0 Gerd Hoffmann
    s->files->f[index].size   = cpu_to_be32(len);
315 abe147e0 Gerd Hoffmann
    s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
316 abe147e0 Gerd Hoffmann
    FW_CFG_DPRINTF("%s: #%d: %s (%d bytes)\n", __FUNCTION__,
317 abe147e0 Gerd Hoffmann
                   index, s->files->f[index].name, len);
318 abe147e0 Gerd Hoffmann
319 abe147e0 Gerd Hoffmann
    s->files->count = cpu_to_be32(index+1);
320 abe147e0 Gerd Hoffmann
    return 1;
321 abe147e0 Gerd Hoffmann
}
322 abe147e0 Gerd Hoffmann
323 c2b5bda4 Gerd Hoffmann
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
324 c2b5bda4 Gerd Hoffmann
                        target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
325 3cce6243 blueswir1
{
326 3cce6243 blueswir1
    FWCfgState *s;
327 3cce6243 blueswir1
    int io_ctl_memory, io_data_memory;
328 3cce6243 blueswir1
329 3cce6243 blueswir1
    s = qemu_mallocz(sizeof(FWCfgState));
330 3cce6243 blueswir1
331 3cce6243 blueswir1
    if (ctl_port) {
332 3cce6243 blueswir1
        register_ioport_write(ctl_port, 2, 2, fw_cfg_io_writew, s);
333 3cce6243 blueswir1
    }
334 3cce6243 blueswir1
    if (data_port) {
335 3cce6243 blueswir1
        register_ioport_read(data_port, 1, 1, fw_cfg_io_readb, s);
336 3cce6243 blueswir1
        register_ioport_write(data_port, 1, 1, fw_cfg_io_writeb, s);
337 3cce6243 blueswir1
    }
338 3cce6243 blueswir1
    if (ctl_addr) {
339 1eed09cb Avi Kivity
        io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
340 3cce6243 blueswir1
                                           fw_cfg_ctl_mem_write, s);
341 3cce6243 blueswir1
        cpu_register_physical_memory(ctl_addr, FW_CFG_SIZE, io_ctl_memory);
342 3cce6243 blueswir1
    }
343 3cce6243 blueswir1
    if (data_addr) {
344 1eed09cb Avi Kivity
        io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
345 3cce6243 blueswir1
                                           fw_cfg_data_mem_write, s);
346 3cce6243 blueswir1
        cpu_register_physical_memory(data_addr, FW_CFG_SIZE, io_data_memory);
347 3cce6243 blueswir1
    }
348 3cce6243 blueswir1
    fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (uint8_t *)"QEMU", 4);
349 084a197a blueswir1
    fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
350 993fbfdb Anthony Liguori
    fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC));
351 905fdcb5 blueswir1
    fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
352 6be68d7e Jes Sorensen
    fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
353 95387491 Jan Kiszka
    fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
354 905fdcb5 blueswir1
355 7d2edd40 Juan Quintela
    vmstate_register(-1, &vmstate_fw_cfg, s);
356 a08d4367 Jan Kiszka
    qemu_register_reset(fw_cfg_reset, s);
357 3cce6243 blueswir1
358 3cce6243 blueswir1
    return s;
359 3cce6243 blueswir1
}