mirror of https://github.com/xemu-project/xemu.git
fw_cfg: drop write support, qemu cmdline support, bugfixes.
bios-tables-test: fix smbios test. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJVd9lhAAoJEEy22O7T6HE41aEP/Avmt5hKB3h83U2BRAZRtta1 s1CO6AqM94h/NiZlOInZIlH05fn87Aycp5HzyyGsl9Gjjve8/ZUNYYpbl5LPylq0 Fbm8oOO1R3QjhOEnHCBO0WJStkzbk3U8lNNIO6xhhNFho3FgYkdGvNs1f81vG2iV gnCQBQI90BpqzMZA7Hr/5iAXgAmX0fo8gd/iN2LCX9rMpJfjZLCfKYzb5KaFu+Ha WI6gxFCLwrQz94P4hA8KsEGgGZv9C3ZEVCmRL0RDDCwTsI1VYfeQvUNwmWOumD9g kLEnIRj561hD+UV/b/kzpeLZw7QszluAm4aO8/0dmDvKi3/h19BIXFht3QB4BmEd 1J4KbWYvWW2xBYe6OnpnGYs+xG9L+8qnYTNg/+/ng7Akev1nGBsccPwlOCijCojL jvTF7jCiQLPvGWM2ImRPwTxV09Ys644lJfoRQ8euy1yrpAKT8mAXGthKfLcprk1j MJ8GSmqJHKt71svtLqKquWcXX/IdK/ZTQdsAKUwffUKJ40iFpMjx2NLq22yZtoYj Gcec54acjf/Ej0rA09J8SG+jnEPFJqaVEAn3XcQZ99V5I3LOlOZoSy84/xjB0QTl bcJN4P8S3srgqIWN+j82VkjoL/D3qqYnJaEgB0LjMXiUkTbYHxJtL32sgYJhUOy/ VDi6MmPkyrZHcyuTYbNs =ZUVk -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/pull-fw_cfg-20150610-1' into staging fw_cfg: drop write support, qemu cmdline support, bugfixes. bios-tables-test: fix smbios test. # gpg: Signature made Wed Jun 10 07:29:53 2015 BST using RSA key ID D3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" * remotes/kraxel/tags/pull-fw_cfg-20150610-1: bios-tables-test: handle false-positive smbios signature matches fw_cfg: insert fw_cfg file blobs via qemu cmdline fw_cfg: prohibit insertion of duplicate fw_cfg file names fw_cfg: prevent selector key conflict fw_cfg: remove support for guest-side data writes fw_cfg: fix FW_CFG_BOOT_DEVICE update on ppc and sparc fw_cfg: add fw_cfg_modify_i16 (update) method QemuOpts: increase number of vm_config_groups Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3974c9d8cc
|
@ -203,3 +203,24 @@ completes fully overwriting the item's data.
|
||||||
|
|
||||||
NOTE: This function is deprecated, and will be completely removed
|
NOTE: This function is deprecated, and will be completely removed
|
||||||
starting with QEMU v2.4.
|
starting with QEMU v2.4.
|
||||||
|
|
||||||
|
== Externally Provided Items ==
|
||||||
|
|
||||||
|
As of v2.4, "file" fw_cfg items (i.e., items with selector keys above
|
||||||
|
FW_CFG_FILE_FIRST, and with a corresponding entry in the fw_cfg file
|
||||||
|
directory structure) may be inserted via the QEMU command line, using
|
||||||
|
the following syntax:
|
||||||
|
|
||||||
|
-fw_cfg [name=]<item_name>,file=<path>
|
||||||
|
|
||||||
|
where <item_name> is the fw_cfg item name, and <path> is the location
|
||||||
|
on the host file system of a file containing the data to be inserted.
|
||||||
|
|
||||||
|
NOTE: Users *SHOULD* choose item names beginning with the prefix "opt/"
|
||||||
|
when using the "-fw_cfg" command line option, to avoid conflicting with
|
||||||
|
item names used internally by QEMU. For instance:
|
||||||
|
|
||||||
|
-fw_cfg name=opt/my_item_name,file=./my_blob.bin
|
||||||
|
|
||||||
|
Similarly, QEMU developers *SHOULD NOT* use item names prefixed with
|
||||||
|
"opt/" when inserting items programmatically, e.g. via fw_cfg_add_file().
|
||||||
|
|
|
@ -46,7 +46,6 @@ typedef struct FWCfgEntry {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
void *callback_opaque;
|
void *callback_opaque;
|
||||||
FWCfgCallback callback;
|
|
||||||
FWCfgReadCallback read_callback;
|
FWCfgReadCallback read_callback;
|
||||||
} FWCfgEntry;
|
} FWCfgEntry;
|
||||||
|
|
||||||
|
@ -232,19 +231,7 @@ static void fw_cfg_reboot(FWCfgState *s)
|
||||||
|
|
||||||
static void fw_cfg_write(FWCfgState *s, uint8_t value)
|
static void fw_cfg_write(FWCfgState *s, uint8_t value)
|
||||||
{
|
{
|
||||||
int arch = !!(s->cur_entry & FW_CFG_ARCH_LOCAL);
|
/* nothing, write support removed in QEMU v2.4+ */
|
||||||
FWCfgEntry *e = &s->entries[arch][s->cur_entry & FW_CFG_ENTRY_MASK];
|
|
||||||
|
|
||||||
trace_fw_cfg_write(s, value);
|
|
||||||
|
|
||||||
if (s->cur_entry & FW_CFG_WRITE_CHANNEL && e->callback &&
|
|
||||||
s->cur_offset < e->len) {
|
|
||||||
e->data[s->cur_offset++] = value;
|
|
||||||
if (s->cur_offset == e->len) {
|
|
||||||
e->callback(e->callback_opaque, e->data);
|
|
||||||
s->cur_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fw_cfg_select(FWCfgState *s, uint16_t key)
|
static int fw_cfg_select(FWCfgState *s, uint16_t key)
|
||||||
|
@ -436,6 +423,7 @@ static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
|
||||||
key &= FW_CFG_ENTRY_MASK;
|
key &= FW_CFG_ENTRY_MASK;
|
||||||
|
|
||||||
assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
|
assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
|
||||||
|
assert(s->entries[arch][key].data == NULL); /* avoid key conflict */
|
||||||
|
|
||||||
s->entries[arch][key].data = data;
|
s->entries[arch][key].data = data;
|
||||||
s->entries[arch][key].len = (uint32_t)len;
|
s->entries[arch][key].len = (uint32_t)len;
|
||||||
|
@ -458,7 +446,6 @@ static void *fw_cfg_modify_bytes_read(FWCfgState *s, uint16_t key,
|
||||||
s->entries[arch][key].data = data;
|
s->entries[arch][key].data = data;
|
||||||
s->entries[arch][key].len = len;
|
s->entries[arch][key].len = len;
|
||||||
s->entries[arch][key].callback_opaque = NULL;
|
s->entries[arch][key].callback_opaque = NULL;
|
||||||
s->entries[arch][key].callback = NULL;
|
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -484,6 +471,16 @@ void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value)
|
||||||
fw_cfg_add_bytes(s, key, copy, sizeof(value));
|
fw_cfg_add_bytes(s, key, copy, sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value)
|
||||||
|
{
|
||||||
|
uint16_t *copy, *old;
|
||||||
|
|
||||||
|
copy = g_malloc(sizeof(value));
|
||||||
|
*copy = cpu_to_le16(value);
|
||||||
|
old = fw_cfg_modify_bytes_read(s, key, copy, sizeof(value));
|
||||||
|
g_free(old);
|
||||||
|
}
|
||||||
|
|
||||||
void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)
|
void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)
|
||||||
{
|
{
|
||||||
uint32_t *copy;
|
uint32_t *copy;
|
||||||
|
@ -502,23 +499,6 @@ void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)
|
||||||
fw_cfg_add_bytes(s, key, copy, sizeof(value));
|
fw_cfg_add_bytes(s, key, copy, sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
|
||||||
void *callback_opaque, void *data, size_t len)
|
|
||||||
{
|
|
||||||
int arch = !!(key & FW_CFG_ARCH_LOCAL);
|
|
||||||
|
|
||||||
assert(key & FW_CFG_WRITE_CHANNEL);
|
|
||||||
|
|
||||||
key &= FW_CFG_ENTRY_MASK;
|
|
||||||
|
|
||||||
assert(key < FW_CFG_MAX_ENTRY && len <= UINT32_MAX);
|
|
||||||
|
|
||||||
s->entries[arch][key].data = data;
|
|
||||||
s->entries[arch][key].len = (uint32_t)len;
|
|
||||||
s->entries[arch][key].callback_opaque = callback_opaque;
|
|
||||||
s->entries[arch][key].callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
||||||
FWCfgReadCallback callback, void *callback_opaque,
|
FWCfgReadCallback callback, void *callback_opaque,
|
||||||
void *data, size_t len)
|
void *data, size_t len)
|
||||||
|
@ -535,18 +515,19 @@ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
||||||
index = be32_to_cpu(s->files->count);
|
index = be32_to_cpu(s->files->count);
|
||||||
assert(index < FW_CFG_FILE_SLOTS);
|
assert(index < FW_CFG_FILE_SLOTS);
|
||||||
|
|
||||||
fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
|
|
||||||
callback, callback_opaque, data, len);
|
|
||||||
|
|
||||||
pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
|
pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
|
||||||
filename);
|
filename);
|
||||||
for (i = 0; i < index; i++) {
|
for (i = 0; i < index; i++) {
|
||||||
if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
|
if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
|
||||||
trace_fw_cfg_add_file_dupe(s, s->files->f[index].name);
|
error_report("duplicate fw_cfg file name: %s",
|
||||||
return;
|
s->files->f[index].name);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fw_cfg_add_bytes_read_callback(s, FW_CFG_FILE_FIRST + index,
|
||||||
|
callback, callback_opaque, data, len);
|
||||||
|
|
||||||
s->files->f[index].size = cpu_to_be32(len);
|
s->files->f[index].size = cpu_to_be32(len);
|
||||||
s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
|
s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
|
||||||
trace_fw_cfg_add_file(s, index, s->files->f[index].name, len);
|
trace_fw_cfg_add_file(s, index, s->files->f[index].name, len);
|
||||||
|
|
|
@ -119,7 +119,7 @@ static const MemoryRegionOps unin_ops = {
|
||||||
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
||||||
|
|
|
@ -124,7 +124,7 @@ void DMA_register_channel (int nchan,
|
||||||
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nvram_init(Nvram *nvram, uint8_t *macaddr,
|
static void nvram_init(Nvram *nvram, uint8_t *macaddr,
|
||||||
|
|
|
@ -127,7 +127,7 @@ void DMA_register_channel (int nchan,
|
||||||
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_t NVRAM_size,
|
static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_t NVRAM_size,
|
||||||
|
|
|
@ -67,10 +67,9 @@ typedef void (*FWCfgReadCallback)(void *opaque, uint32_t offset);
|
||||||
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
|
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
|
||||||
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
|
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
|
||||||
void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
|
void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
|
||||||
|
void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value);
|
||||||
void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
|
void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
|
||||||
void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
|
void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
|
||||||
void fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
|
||||||
void *callback_opaque, void *data, size_t len);
|
|
||||||
void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
|
void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
||||||
|
|
|
@ -2686,6 +2686,17 @@ STEXI
|
||||||
@table @option
|
@table @option
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
|
DEF("fw_cfg", HAS_ARG, QEMU_OPTION_fwcfg,
|
||||||
|
"-fw_cfg [name=]<name>,file=<file>\n"
|
||||||
|
" add named fw_cfg entry from file\n",
|
||||||
|
QEMU_ARCH_ALL)
|
||||||
|
STEXI
|
||||||
|
@item -fw_cfg [name=]@var{name},file=@var{file}
|
||||||
|
@findex -fw_cfg
|
||||||
|
Add named fw_cfg entry from file. @var{name} determines the name of
|
||||||
|
the entry in the fw_cfg file directory exposed to the guest.
|
||||||
|
ETEXI
|
||||||
|
|
||||||
DEF("serial", HAS_ARG, QEMU_OPTION_serial, \
|
DEF("serial", HAS_ARG, QEMU_OPTION_serial, \
|
||||||
"-serial dev redirect the serial port to char device 'dev'\n",
|
"-serial dev redirect the serial port to char device 'dev'\n",
|
||||||
QEMU_ARCH_ALL)
|
QEMU_ARCH_ALL)
|
||||||
|
|
|
@ -599,7 +599,45 @@ static void test_acpi_asl(test_data *data)
|
||||||
free_test_data(&exp_data);
|
free_test_data(&exp_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_smbios_ep_address(test_data *data)
|
static bool smbios_ep_table_ok(test_data *data)
|
||||||
|
{
|
||||||
|
struct smbios_entry_point *ep_table = &data->smbios_ep_table;
|
||||||
|
uint32_t addr = data->smbios_ep_addr;
|
||||||
|
|
||||||
|
ACPI_READ_ARRAY(ep_table->anchor_string, addr);
|
||||||
|
if (memcmp(ep_table->anchor_string, "_SM_", 4)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ACPI_READ_FIELD(ep_table->checksum, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->length, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->smbios_major_version, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->smbios_minor_version, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->max_structure_size, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->entry_point_revision, addr);
|
||||||
|
ACPI_READ_ARRAY(ep_table->formatted_area, addr);
|
||||||
|
ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr);
|
||||||
|
if (memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ACPI_READ_FIELD(ep_table->intermediate_checksum, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->structure_table_length, addr);
|
||||||
|
if (ep_table->structure_table_length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ACPI_READ_FIELD(ep_table->structure_table_address, addr);
|
||||||
|
ACPI_READ_FIELD(ep_table->number_of_structures, addr);
|
||||||
|
if (ep_table->number_of_structures == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
|
||||||
|
if (acpi_checksum((uint8_t *)ep_table, sizeof *ep_table) ||
|
||||||
|
acpi_checksum((uint8_t *)ep_table + 0x10, sizeof *ep_table - 0x10)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_smbios_entry_point(test_data *data)
|
||||||
{
|
{
|
||||||
uint32_t off;
|
uint32_t off;
|
||||||
|
|
||||||
|
@ -613,40 +651,15 @@ static void test_smbios_ep_address(test_data *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memcmp(sig, "_SM_", sizeof sig)) {
|
if (!memcmp(sig, "_SM_", sizeof sig)) {
|
||||||
break;
|
/* signature match, but is this a valid entry point? */
|
||||||
|
data->smbios_ep_addr = off;
|
||||||
|
if (smbios_ep_table_ok(data)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert_cmphex(off, <, 0x100000);
|
g_assert_cmphex(off, <, 0x100000);
|
||||||
data->smbios_ep_addr = off;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_smbios_ep_table(test_data *data)
|
|
||||||
{
|
|
||||||
struct smbios_entry_point *ep_table = &data->smbios_ep_table;
|
|
||||||
uint32_t addr = data->smbios_ep_addr;
|
|
||||||
|
|
||||||
ACPI_READ_ARRAY(ep_table->anchor_string, addr);
|
|
||||||
g_assert(!memcmp(ep_table->anchor_string, "_SM_", 4));
|
|
||||||
ACPI_READ_FIELD(ep_table->checksum, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->length, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->smbios_major_version, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->smbios_minor_version, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->max_structure_size, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->entry_point_revision, addr);
|
|
||||||
ACPI_READ_ARRAY(ep_table->formatted_area, addr);
|
|
||||||
ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr);
|
|
||||||
g_assert(!memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5));
|
|
||||||
ACPI_READ_FIELD(ep_table->intermediate_checksum, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->structure_table_length, addr);
|
|
||||||
g_assert_cmpuint(ep_table->structure_table_length, >, 0);
|
|
||||||
ACPI_READ_FIELD(ep_table->structure_table_address, addr);
|
|
||||||
ACPI_READ_FIELD(ep_table->number_of_structures, addr);
|
|
||||||
g_assert_cmpuint(ep_table->number_of_structures, >, 0);
|
|
||||||
ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
|
|
||||||
g_assert(!acpi_checksum((uint8_t *)ep_table, sizeof *ep_table));
|
|
||||||
g_assert(!acpi_checksum((uint8_t *)ep_table + 0x10,
|
|
||||||
sizeof *ep_table - 0x10));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool smbios_single_instance(uint8_t type)
|
static inline bool smbios_single_instance(uint8_t type)
|
||||||
|
@ -767,8 +780,7 @@ static void test_acpi_one(const char *params, test_data *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test_smbios_ep_address(data);
|
test_smbios_entry_point(data);
|
||||||
test_smbios_ep_table(data);
|
|
||||||
test_smbios_structs(data);
|
test_smbios_structs(data);
|
||||||
|
|
||||||
qtest_quit(global_qtest);
|
qtest_quit(global_qtest);
|
||||||
|
|
|
@ -193,10 +193,8 @@ ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %
|
||||||
ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x"
|
ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x"
|
||||||
|
|
||||||
# hw/nvram/fw_cfg.c
|
# hw/nvram/fw_cfg.c
|
||||||
fw_cfg_write(void *s, uint8_t value) "%p %d"
|
|
||||||
fw_cfg_select(void *s, uint16_t key, int ret) "%p key %d = %d"
|
fw_cfg_select(void *s, uint16_t key, int ret) "%p key %d = %d"
|
||||||
fw_cfg_read(void *s, uint8_t ret) "%p = %d"
|
fw_cfg_read(void *s, uint8_t ret) "%p = %d"
|
||||||
fw_cfg_add_file_dupe(void *s, char *name) "%p %s"
|
|
||||||
fw_cfg_add_file(void *s, int index, char *name, size_t len) "%p #%d: %s (%zd bytes)"
|
fw_cfg_add_file(void *s, int index, char *name, size_t len) "%p #%d: %s (%zd bytes)"
|
||||||
|
|
||||||
# hw/block/hd-geometry.c
|
# hw/block/hd-geometry.c
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
|
|
||||||
static QemuOptsList *vm_config_groups[32];
|
static QemuOptsList *vm_config_groups[48];
|
||||||
static QemuOptsList *drive_config_groups[4];
|
static QemuOptsList *drive_config_groups[4];
|
||||||
|
|
||||||
static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
|
static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
|
||||||
|
|
63
vl.c
63
vl.c
|
@ -492,6 +492,25 @@ static QemuOptsList qemu_semihosting_config_opts = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static QemuOptsList qemu_fw_cfg_opts = {
|
||||||
|
.name = "fw_cfg",
|
||||||
|
.implied_opt_name = "name",
|
||||||
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_fw_cfg_opts.head),
|
||||||
|
.desc = {
|
||||||
|
{
|
||||||
|
.name = "name",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "Sets the fw_cfg name of the blob to be inserted",
|
||||||
|
}, {
|
||||||
|
.name = "file",
|
||||||
|
.type = QEMU_OPT_STRING,
|
||||||
|
.help = "Sets the name of the file from which\n"
|
||||||
|
"the fw_cfg blob will be loaded",
|
||||||
|
},
|
||||||
|
{ /* end of list */ }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get machine options
|
* Get machine options
|
||||||
*
|
*
|
||||||
|
@ -2127,6 +2146,38 @@ char *qemu_find_file(int type, const char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
|
{
|
||||||
|
gchar *buf;
|
||||||
|
size_t size;
|
||||||
|
const char *name, *file;
|
||||||
|
|
||||||
|
if (opaque == NULL) {
|
||||||
|
error_report("fw_cfg device not available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
name = qemu_opt_get(opts, "name");
|
||||||
|
file = qemu_opt_get(opts, "file");
|
||||||
|
if (name == NULL || *name == '\0' || file == NULL || *file == '\0') {
|
||||||
|
error_report("invalid argument value");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strlen(name) > FW_CFG_MAX_FILE_PATH - 1) {
|
||||||
|
error_report("name too long (max. %d char)", FW_CFG_MAX_FILE_PATH - 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strncmp(name, "opt/", 4) != 0) {
|
||||||
|
error_report("WARNING: externally provided fw_cfg item names "
|
||||||
|
"should be prefixed with \"opt/\"!");
|
||||||
|
}
|
||||||
|
if (!g_file_get_contents(file, &buf, &size, NULL)) {
|
||||||
|
error_report("can't load %s", file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fw_cfg_add_file((FWCfgState *)opaque, name, buf, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int device_help_func(void *opaque, QemuOpts *opts, Error **errp)
|
static int device_help_func(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
{
|
{
|
||||||
return qdev_device_help(opts);
|
return qdev_device_help(opts);
|
||||||
|
@ -2822,6 +2873,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
qemu_add_opts(&qemu_numa_opts);
|
qemu_add_opts(&qemu_numa_opts);
|
||||||
qemu_add_opts(&qemu_icount_opts);
|
qemu_add_opts(&qemu_icount_opts);
|
||||||
qemu_add_opts(&qemu_semihosting_config_opts);
|
qemu_add_opts(&qemu_semihosting_config_opts);
|
||||||
|
qemu_add_opts(&qemu_fw_cfg_opts);
|
||||||
|
|
||||||
runstate_init();
|
runstate_init();
|
||||||
|
|
||||||
|
@ -3438,6 +3490,12 @@ int main(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
do_smbios_option(opts);
|
do_smbios_option(opts);
|
||||||
break;
|
break;
|
||||||
|
case QEMU_OPTION_fwcfg:
|
||||||
|
opts = qemu_opts_parse(qemu_find_opts("fw_cfg"), optarg, 1);
|
||||||
|
if (opts == NULL) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case QEMU_OPTION_enable_kvm:
|
case QEMU_OPTION_enable_kvm:
|
||||||
olist = qemu_find_opts("machine");
|
olist = qemu_find_opts("machine");
|
||||||
qemu_opts_parse(olist, "accel=kvm", 0);
|
qemu_opts_parse(olist, "accel=kvm", 0);
|
||||||
|
@ -4274,6 +4332,11 @@ int main(int argc, char **argv, char **envp)
|
||||||
|
|
||||||
numa_post_machine_init();
|
numa_post_machine_init();
|
||||||
|
|
||||||
|
if (qemu_opts_foreach(qemu_find_opts("fw_cfg"),
|
||||||
|
parse_fw_cfg, fw_cfg_find(), NULL) != 0) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* init USB devices */
|
/* init USB devices */
|
||||||
if (usb_enabled()) {
|
if (usb_enabled()) {
|
||||||
if (foreach_device_config(DEV_USB, usb_parse) < 0)
|
if (foreach_device_config(DEV_USB, usb_parse) < 0)
|
||||||
|
|
Loading…
Reference in New Issue