From 1f80b0d67e86f0180c72e9e943046d79a63c83f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 15:45:51 +0200 Subject: [PATCH 01/15] hw/nvram/fw_cfg: Add trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add trace events to dump the key content. Reviewed-by: Michael S. Tsirkin Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-2-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/nvram/fw_cfg.c | 63 ++++++++++++++++++++++++++++++++++++++++++- hw/nvram/trace-events | 7 ++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 5c3a46ce6f..d374a970fe 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -60,6 +60,62 @@ struct FWCfgEntry { FWCfgWriteCallback write_cb; }; +/** + * key_name: + * + * @key: The uint16 selector key. + * + * Returns: The stringified name if the selector refers to a well-known + * numerically defined item, or NULL on key lookup failure. + */ +static const char *key_name(uint16_t key) +{ + static const char *fw_cfg_wellknown_keys[FW_CFG_FILE_FIRST] = { + [FW_CFG_SIGNATURE] = "signature", + [FW_CFG_ID] = "id", + [FW_CFG_UUID] = "uuid", + [FW_CFG_RAM_SIZE] = "ram_size", + [FW_CFG_NOGRAPHIC] = "nographic", + [FW_CFG_NB_CPUS] = "nb_cpus", + [FW_CFG_MACHINE_ID] = "machine_id", + [FW_CFG_KERNEL_ADDR] = "kernel_addr", + [FW_CFG_KERNEL_SIZE] = "kernel_size", + [FW_CFG_KERNEL_CMDLINE] = "kernel_cmdline", + [FW_CFG_INITRD_ADDR] = "initrd_addr", + [FW_CFG_INITRD_SIZE] = "initdr_size", + [FW_CFG_BOOT_DEVICE] = "boot_device", + [FW_CFG_NUMA] = "numa", + [FW_CFG_BOOT_MENU] = "boot_menu", + [FW_CFG_MAX_CPUS] = "max_cpus", + [FW_CFG_KERNEL_ENTRY] = "kernel_entry", + [FW_CFG_KERNEL_DATA] = "kernel_data", + [FW_CFG_INITRD_DATA] = "initrd_data", + [FW_CFG_CMDLINE_ADDR] = "cmdline_addr", + [FW_CFG_CMDLINE_SIZE] = "cmdline_size", + [FW_CFG_CMDLINE_DATA] = "cmdline_data", + [FW_CFG_SETUP_ADDR] = "setup_addr", + [FW_CFG_SETUP_SIZE] = "setup_size", + [FW_CFG_SETUP_DATA] = "setup_data", + [FW_CFG_FILE_DIR] = "file_dir", + }; + + if (key & FW_CFG_ARCH_LOCAL) { + return NULL; + } + if (key < FW_CFG_FILE_FIRST) { + return fw_cfg_wellknown_keys[key]; + } + + return NULL; +} + +static inline const char *trace_key_name(uint16_t key) +{ + const char *name = key_name(key); + + return name ? name : "unknown"; +} + #define JPG_FILE 0 #define BMP_FILE 1 @@ -233,7 +289,7 @@ static int fw_cfg_select(FWCfgState *s, uint16_t key) } } - trace_fw_cfg_select(s, key, ret); + trace_fw_cfg_select(s, key, trace_key_name(key), ret); return ret; } @@ -616,6 +672,7 @@ static void *fw_cfg_modify_bytes_read(FWCfgState *s, uint16_t key, void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len) { + trace_fw_cfg_add_bytes(key, trace_key_name(key), len); fw_cfg_add_bytes_callback(s, key, NULL, NULL, NULL, data, len, true); } @@ -623,6 +680,7 @@ void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value) { size_t sz = strlen(value) + 1; + trace_fw_cfg_add_string(key, trace_key_name(key), value); fw_cfg_add_bytes(s, key, g_memdup(value, sz), sz); } @@ -632,6 +690,7 @@ void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value) copy = g_malloc(sizeof(value)); *copy = cpu_to_le16(value); + trace_fw_cfg_add_i16(key, trace_key_name(key), value); fw_cfg_add_bytes(s, key, copy, sizeof(value)); } @@ -651,6 +710,7 @@ void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value) copy = g_malloc(sizeof(value)); *copy = cpu_to_le32(value); + trace_fw_cfg_add_i32(key, trace_key_name(key), value); fw_cfg_add_bytes(s, key, copy, sizeof(value)); } @@ -660,6 +720,7 @@ void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value) copy = g_malloc(sizeof(value)); *copy = cpu_to_le64(value); + trace_fw_cfg_add_i64(key, trace_key_name(key), value); fw_cfg_add_bytes(s, key, copy, sizeof(value)); } diff --git a/hw/nvram/trace-events b/hw/nvram/trace-events index e191991e2a..0dea9260ce 100644 --- a/hw/nvram/trace-events +++ b/hw/nvram/trace-events @@ -5,6 +5,11 @@ nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x" nvram_write(uint32_t addr, uint32_t old, uint32_t val) "write addr %d: 0x%02x -> 0x%02x" # fw_cfg.c -fw_cfg_select(void *s, uint16_t key, int ret) "%p key %d = %d" +fw_cfg_select(void *s, uint16_t key_value, const char *key_name, int ret) "%p key 0x%04" PRIx16 " '%s', ret: %d" fw_cfg_read(void *s, uint64_t ret) "%p = 0x%"PRIx64 +fw_cfg_add_bytes(uint16_t key_value, const char *key_name, size_t len) "key 0x%04" PRIx16 " '%s', %zu bytes" fw_cfg_add_file(void *s, int index, char *name, size_t len) "%p #%d: %s (%zd bytes)" +fw_cfg_add_string(uint16_t key_value, const char *key_name, const char *value) "key 0x%04" PRIx16 " '%s', value '%s'" +fw_cfg_add_i16(uint16_t key_value, const char *key_name, uint16_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx16 +fw_cfg_add_i32(uint16_t key_value, const char *key_name, uint32_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx32 +fw_cfg_add_i64(uint16_t key_value, const char *key_name, uint64_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx64 From b15c0f7d55934c609969f4e6e08efa5ed0f3ad28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 15:49:41 +0200 Subject: [PATCH 02/15] hw/nvram/fw_cfg: Add fw_cfg_arch_key_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add fw_cfg_arch_key_name() which returns the name of an architecture-specific key. Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-3-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + hw/nvram/fw_cfg.c | 2 +- include/hw/nvram/fw_cfg.h | 14 ++++++++++++++ stubs/Makefile.objs | 1 + stubs/fw_cfg.c | 21 +++++++++++++++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 stubs/fw_cfg.c diff --git a/MAINTAINERS b/MAINTAINERS index 73a0105082..3cacd751bf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1696,6 +1696,7 @@ R: Gerd Hoffmann S: Supported F: docs/specs/fw_cfg.txt F: hw/nvram/fw_cfg.c +F: stubs/fw_cfg.c F: include/hw/nvram/fw_cfg.h F: include/standard-headers/linux/qemu_fw_cfg.h F: tests/libqos/fw_cfg.c diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index d374a970fe..b2dc0a80cb 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -100,7 +100,7 @@ static const char *key_name(uint16_t key) }; if (key & FW_CFG_ARCH_LOCAL) { - return NULL; + return fw_cfg_arch_key_name(key); } if (key < FW_CFG_FILE_FIRST) { return fw_cfg_wellknown_keys[key]; diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index f5a6895a74..80e435d303 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -226,4 +226,18 @@ FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, FWCfgState *fw_cfg_find(void); bool fw_cfg_dma_enabled(void *opaque); +/** + * fw_cfg_arch_key_name: + * + * @key: The uint16 selector key. + * + * The key is architecture-specific (the FW_CFG_ARCH_LOCAL mask is expected + * to be set in the key). + * + * Returns: The stringified architecture-specific name if the selector + * refers to a well-known numerically defined item, or NULL on + * key lookup failure. + */ +const char *fw_cfg_arch_key_name(uint16_t key); + #endif diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 269dfa5832..73452ad265 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -39,3 +39,4 @@ stub-obj-y += xen-hvm.o stub-obj-y += pci-host-piix.o stub-obj-y += ram-block.o stub-obj-y += ramfb.o +stub-obj-y += fw_cfg.o diff --git a/stubs/fw_cfg.c b/stubs/fw_cfg.c new file mode 100644 index 0000000000..bb1e3c8aa9 --- /dev/null +++ b/stubs/fw_cfg.c @@ -0,0 +1,21 @@ +/* + * fw_cfg stubs + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: + * Philippe Mathieu-Daudé + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/nvram/fw_cfg.h" + +const char *fw_cfg_arch_key_name(uint16_t key) +{ + return NULL; +} From 87abaa5d8c32cea835601f510ab145f2edbc3da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 18:58:21 +0200 Subject: [PATCH 03/15] hw/i386: Extract fw_cfg definitions to local "fw_cfg.h" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the architecture-specific fw_cfg definitions to "fw_cfg.h". Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-4-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/fw_cfg.h | 20 ++++++++++++++++++++ hw/i386/pc.c | 7 +------ 2 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 hw/i386/fw_cfg.h diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h new file mode 100644 index 0000000000..17a4bc32f2 --- /dev/null +++ b/hw/i386/fw_cfg.h @@ -0,0 +1,20 @@ +/* + * QEMU fw_cfg helpers (X86 specific) + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * SPDX-License-Identifier: MIT + */ + +#ifndef HW_I386_FW_CFG_H +#define HW_I386_FW_CFG_H + +#include "hw/nvram/fw_cfg.h" + +#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) +#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) +#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) +#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) +#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) + +#endif diff --git a/hw/i386/pc.c b/hw/i386/pc.c index d98b737b8f..2632b73f80 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -30,6 +30,7 @@ #include "hw/char/parallel.h" #include "hw/i386/apic.h" #include "hw/i386/topology.h" +#include "hw/i386/fw_cfg.h" #include "sysemu/cpus.h" #include "hw/block/fdc.h" #include "hw/ide.h" @@ -88,12 +89,6 @@ #define DPRINTF(fmt, ...) #endif -#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) -#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) -#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) -#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) -#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) - #define E820_NR_ENTRIES 16 struct e820_entry { From bd3f680f66f429451efae2e5f0ace2fa8af199bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 15:50:25 +0200 Subject: [PATCH 04/15] hw/i386: Implement fw_cfg_arch_key_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fw_cfg_arch_key_name(), which returns the name of a i386-specific key. Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-5-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/Makefile.objs | 2 +- hw/i386/fw_cfg.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 hw/i386/fw_cfg.c diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 27248a0777..5d9c9efd5f 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -3,7 +3,7 @@ obj-y += multiboot.o obj-y += pc.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o -obj-y += pc_sysfw.o +obj-y += fw_cfg.o pc_sysfw.o obj-y += x86-iommu.o obj-$(CONFIG_VTD) += intel_iommu.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c new file mode 100644 index 0000000000..380a819230 --- /dev/null +++ b/hw/i386/fw_cfg.c @@ -0,0 +1,38 @@ +/* + * QEMU fw_cfg helpers (X86 specific) + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: + * Philippe Mathieu-Daudé + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/i386/fw_cfg.h" +#include "hw/nvram/fw_cfg.h" + +const char *fw_cfg_arch_key_name(uint16_t key) +{ + static const struct { + uint16_t key; + const char *name; + } fw_cfg_arch_wellknown_keys[] = { + {FW_CFG_ACPI_TABLES, "acpi_tables"}, + {FW_CFG_SMBIOS_ENTRIES, "smbios_entries"}, + {FW_CFG_IRQ0_OVERRIDE, "irq0_override"}, + {FW_CFG_E820_TABLE, "e820_table"}, + {FW_CFG_HPET, "hpet"}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) { + if (fw_cfg_arch_wellknown_keys[i].key == key) { + return fw_cfg_arch_wellknown_keys[i].name; + } + } + return NULL; +} From d632b9de7865e05f06f02549e6dbdcf9a61f4ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 15:50:42 +0200 Subject: [PATCH 05/15] hw/ppc: Implement fw_cfg_arch_key_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fw_cfg_arch_key_name(), which returns the name of a ppc-specific key. The fw_cfg device is used by the machine using OpenBIOS: - 40p - mac99 (oldworld) - g3beige (newworld) Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-6-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/ppc/Makefile.objs | 2 +- hw/ppc/fw_cfg.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/fw_cfg.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 636e717f20..9da93af905 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -1,5 +1,5 @@ # shared objects -obj-y += ppc.o ppc_booke.o fdt.o +obj-y += ppc.o ppc_booke.o fdt.o fw_cfg.o # IBM pSeries (sPAPR) obj-$(CONFIG_PSERIES) += spapr.o spapr_caps.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o diff --git a/hw/ppc/fw_cfg.c b/hw/ppc/fw_cfg.c new file mode 100644 index 0000000000..a88b5c4bde --- /dev/null +++ b/hw/ppc/fw_cfg.c @@ -0,0 +1,45 @@ +/* + * fw_cfg helpers (PPC specific) + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: + * Philippe Mathieu-Daudé + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/ppc/ppc.h" +#include "hw/nvram/fw_cfg.h" + +const char *fw_cfg_arch_key_name(uint16_t key) +{ + static const struct { + uint16_t key; + const char *name; + } fw_cfg_arch_wellknown_keys[] = { + {FW_CFG_PPC_WIDTH, "width"}, + {FW_CFG_PPC_HEIGHT, "height"}, + {FW_CFG_PPC_DEPTH, "depth"}, + {FW_CFG_PPC_TBFREQ, "tbfreq"}, + {FW_CFG_PPC_CLOCKFREQ, "clockfreq"}, + {FW_CFG_PPC_IS_KVM, "is_kvm"}, + {FW_CFG_PPC_KVM_HC, "kvm_hc"}, + {FW_CFG_PPC_KVM_PID, "pid"}, + {FW_CFG_PPC_NVRAM_ADDR, "nvram_addr"}, + {FW_CFG_PPC_BUSFREQ, "busfreq"}, + {FW_CFG_PPC_NVRAM_FLAT, "nvram_flat"}, + {FW_CFG_PPC_VIACONFIG, "viaconfig"}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) { + if (fw_cfg_arch_wellknown_keys[i].key == key) { + return fw_cfg_arch_wellknown_keys[i].name; + } + } + return NULL; +} From d5a42d1942b77de0d1271f53d47c14a40b831be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 15:51:17 +0200 Subject: [PATCH 06/15] hw/sparc: Implement fw_cfg_arch_key_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fw_cfg_arch_key_name(), which returns the name of a sparc32-specific key. Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-7-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/sparc/sun4m.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 07d126aea8..5151a7202b 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -97,6 +97,25 @@ struct sun4m_hwdef { uint8_t nvram_machine_id; }; +const char *fw_cfg_arch_key_name(uint16_t key) +{ + static const struct { + uint16_t key; + const char *name; + } fw_cfg_arch_wellknown_keys[] = { + {FW_CFG_SUN4M_DEPTH, "depth"}, + {FW_CFG_SUN4M_WIDTH, "width"}, + {FW_CFG_SUN4M_HEIGHT, "height"}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) { + if (fw_cfg_arch_wellknown_keys[i].key == key) { + return fw_cfg_arch_wellknown_keys[i].name; + } + } + return NULL; +} + static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) { From a2b45ea5087dbaf4a57b47763da61339b1e7adb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 15:51:26 +0200 Subject: [PATCH 07/15] hw/sparc64: Implement fw_cfg_arch_key_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fw_cfg_arch_key_name(), which returns the name of a sparc64-specific key. Reviewed-by: Laszlo Ersek Message-Id: <20190422195020.1494-8-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/sparc64/sun4u.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 399f2d73c8..4230b17b87 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -91,6 +91,25 @@ typedef struct EbusState { #define TYPE_EBUS "ebus" #define EBUS(obj) OBJECT_CHECK(EbusState, (obj), TYPE_EBUS) +const char *fw_cfg_arch_key_name(uint16_t key) +{ + static const struct { + uint16_t key; + const char *name; + } fw_cfg_arch_wellknown_keys[] = { + {FW_CFG_SPARC64_WIDTH, "width"}, + {FW_CFG_SPARC64_HEIGHT, "height"}, + {FW_CFG_SPARC64_DEPTH, "depth"}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) { + if (fw_cfg_arch_wellknown_keys[i].key == key) { + return fw_cfg_arch_wellknown_keys[i].name; + } + } + return NULL; +} + static void fw_cfg_boot_set(void *opaque, const char *boot_device, Error **errp) { From 0729d833d6d6f9ec7a865b3f1c2bb727bb9e604b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 11:57:30 +0200 Subject: [PATCH 08/15] tests/libqos: Add io_fw_cfg_uninit() and mm_fw_cfg_uninit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mm_fw_cfg_init() allocates a QFWCFG object, add mm_fw_cfg_uninit() to deallocate it. Similarly with io_fw_cfg_init(), add io_fw_cfg_uninit(). Signed-off-by: Li Qiang Tested-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20190424140643.62457-2-liq3ea@163.com> [PMD: Split patch, filled commit description] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laszlo Ersek --- tests/libqos/fw_cfg.c | 10 ++++++++++ tests/libqos/fw_cfg.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/tests/libqos/fw_cfg.c b/tests/libqos/fw_cfg.c index d0889d1e22..c6839c53c8 100644 --- a/tests/libqos/fw_cfg.c +++ b/tests/libqos/fw_cfg.c @@ -81,6 +81,11 @@ QFWCFG *mm_fw_cfg_init(QTestState *qts, uint64_t base) return fw_cfg; } +void mm_fw_cfg_uninit(QFWCFG *fw_cfg) +{ + g_free(fw_cfg); +} + static void io_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) { qtest_outw(fw_cfg->qts, fw_cfg->base, key); @@ -107,3 +112,8 @@ QFWCFG *io_fw_cfg_init(QTestState *qts, uint16_t base) return fw_cfg; } + +void io_fw_cfg_uninit(QFWCFG *fw_cfg) +{ + g_free(fw_cfg); +} diff --git a/tests/libqos/fw_cfg.h b/tests/libqos/fw_cfg.h index 0353416af0..391669031a 100644 --- a/tests/libqos/fw_cfg.h +++ b/tests/libqos/fw_cfg.h @@ -33,7 +33,9 @@ uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key); uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key); QFWCFG *mm_fw_cfg_init(QTestState *qts, uint64_t base); +void mm_fw_cfg_uninit(QFWCFG *fw_cfg); QFWCFG *io_fw_cfg_init(QTestState *qts, uint16_t base); +void io_fw_cfg_uninit(QFWCFG *fw_cfg); static inline QFWCFG *pc_fw_cfg_init(QTestState *qts) { From 65461d124363d97b387337db9b970df60c31819d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 22 Apr 2019 11:58:00 +0200 Subject: [PATCH 09/15] tests/libqos: Add pc_fw_cfg_uninit() and use it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pc_fw_cfg_init() function allocates an IO QFWCFG object. Add the pc_fw_cfg_uninit() function to deallocate it (and use it). Signed-off-by: Li Qiang Tested-by: Thomas Huth Message-Id: <20190424140643.62457-2-liq3ea@163.com> Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé [PMD: Split patch, fill commit description, call uninit in malloc-pc.c] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laszlo Ersek --- tests/libqos/fw_cfg.h | 5 +++++ tests/libqos/malloc-pc.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/libqos/fw_cfg.h b/tests/libqos/fw_cfg.h index 391669031a..60de81e863 100644 --- a/tests/libqos/fw_cfg.h +++ b/tests/libqos/fw_cfg.h @@ -42,4 +42,9 @@ static inline QFWCFG *pc_fw_cfg_init(QTestState *qts) return io_fw_cfg_init(qts, 0x510); } +static inline void pc_fw_cfg_uninit(QFWCFG *fw_cfg) +{ + io_fw_cfg_uninit(fw_cfg); +} + #endif diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c index 949a99361d..6f92ce4135 100644 --- a/tests/libqos/malloc-pc.c +++ b/tests/libqos/malloc-pc.c @@ -29,5 +29,5 @@ void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags) alloc_init(s, flags, 1 << 20, MIN(ram_size, 0xE0000000), PAGE_SIZE); /* clean-up */ - g_free(fw_cfg); + pc_fw_cfg_uninit(fw_cfg); } From 10b789b70cb78e7215f4efd2c568bec7b0b826a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 21 May 2019 18:38:24 +0200 Subject: [PATCH 10/15] tests/fw_cfg: Free QFWCFG object after qtest has run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We allocate the QFWCFG object previous to run the qtests, free it once we are finished. Signed-off-by: Li Qiang Message-Id: <20190424140643.62457-2-liq3ea@163.com> Reviewed-by: Philippe Mathieu-Daudé [PMD: Split patch, fill commit description] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laszlo Ersek --- tests/fw_cfg-test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c index 1c5103fe1c..a370ad5667 100644 --- a/tests/fw_cfg-test.c +++ b/tests/fw_cfg-test.c @@ -128,6 +128,7 @@ int main(int argc, char **argv) ret = g_test_run(); + pc_fw_cfg_uninit(fw_cfg); qtest_quit(s); return ret; From 7a44091d48c1054a859f44a70ef280c7cef4698f Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Sat, 18 May 2019 21:35:10 +0200 Subject: [PATCH 11/15] tests: refactor fw_cfg_test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, fw_cfg_test uses one QTestState for every test case. This will add all command lines for every test case and this is unnecessary. This patch split the test cases and for every test case it uses his own QTestState. This patch does following things: 1. Get rid of the global 'fw_cfg', this need add a uninit function 2. Convert every test case in a separate QTestState After this patch, we can add fw_cfg test case freely and will not have effect on other test cases. Signed-off-by: Li Qiang Acked-by: Thomas Huth Tested-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20190424140643.62457-2-liq3ea@163.com> [PMD: Removed 'ret' local variable in main()] Signed-off-by: Philippe Mathieu-Daudé --- tests/fw_cfg-test.c | 93 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c index a370ad5667..4597626dd7 100644 --- a/tests/fw_cfg-test.c +++ b/tests/fw_cfg-test.c @@ -21,62 +21,127 @@ static uint16_t nb_cpus = 1; static uint16_t max_cpus = 1; static uint64_t nb_nodes = 0; static uint16_t boot_menu = 0; -static QFWCFG *fw_cfg = NULL; static void test_fw_cfg_signature(void) { + QFWCFG *fw_cfg; + QTestState *s; char buf[5]; + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + qfw_cfg_get(fw_cfg, FW_CFG_SIGNATURE, buf, 4); buf[4] = 0; g_assert_cmpstr(buf, ==, "QEMU"); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_id(void) { - uint32_t id = qfw_cfg_get_u32(fw_cfg, FW_CFG_ID); + QFWCFG *fw_cfg; + QTestState *s; + uint32_t id; + + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + + id = qfw_cfg_get_u32(fw_cfg, FW_CFG_ID); g_assert((id == 1) || (id == 3)); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_uuid(void) { + QFWCFG *fw_cfg; + QTestState *s; + uint8_t buf[16]; static const uint8_t uuid[16] = { 0x46, 0x00, 0xcb, 0x32, 0x38, 0xec, 0x4b, 0x2f, 0x8a, 0xcb, 0x81, 0xc6, 0xea, 0x54, 0xf2, 0xd8, }; + s = qtest_init("-uuid 4600cb32-38ec-4b2f-8acb-81c6ea54f2d8"); + fw_cfg = pc_fw_cfg_init(s); + qfw_cfg_get(fw_cfg, FW_CFG_UUID, buf, 16); g_assert(memcmp(buf, uuid, sizeof(buf)) == 0); + + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); + } static void test_fw_cfg_ram_size(void) { + QFWCFG *fw_cfg; + QTestState *s; + + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + g_assert_cmpint(qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE), ==, ram_size); + + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_nographic(void) { + QFWCFG *fw_cfg; + QTestState *s; + + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_NOGRAPHIC), ==, 0); + + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_nb_cpus(void) { + QFWCFG *fw_cfg; + QTestState *s; + + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_NB_CPUS), ==, nb_cpus); + + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_max_cpus(void) { + QFWCFG *fw_cfg; + QTestState *s; + + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_MAX_CPUS), ==, max_cpus); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_numa(void) { + QFWCFG *fw_cfg; + QTestState *s; uint64_t *cpu_mask; uint64_t *node_mask; + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + g_assert_cmpint(qfw_cfg_get_u64(fw_cfg, FW_CFG_NUMA), ==, nb_nodes); cpu_mask = g_new0(uint64_t, max_cpus); @@ -92,24 +157,27 @@ static void test_fw_cfg_numa(void) g_free(node_mask); g_free(cpu_mask); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } static void test_fw_cfg_boot_menu(void) { + QFWCFG *fw_cfg; + QTestState *s; + + s = qtest_init(""); + fw_cfg = pc_fw_cfg_init(s); + g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_MENU), ==, boot_menu); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); } int main(int argc, char **argv) { - QTestState *s; - int ret; - g_test_init(&argc, &argv, NULL); - s = qtest_init("-uuid 4600cb32-38ec-4b2f-8acb-81c6ea54f2d8"); - - fw_cfg = pc_fw_cfg_init(s); - qtest_add_func("fw_cfg/signature", test_fw_cfg_signature); qtest_add_func("fw_cfg/id", test_fw_cfg_id); qtest_add_func("fw_cfg/uuid", test_fw_cfg_uuid); @@ -126,10 +194,5 @@ int main(int argc, char **argv) qtest_add_func("fw_cfg/numa", test_fw_cfg_numa); qtest_add_func("fw_cfg/boot_menu", test_fw_cfg_boot_menu); - ret = g_test_run(); - - pc_fw_cfg_uninit(fw_cfg); - qtest_quit(s); - - return ret; + return g_test_run(); } From c99f5f1dd4161012ee9ba69e7f5d351e52ed18ae Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Wed, 24 Apr 2019 07:06:40 -0700 Subject: [PATCH 12/15] tests: fw_cfg: add a function to get the fw_cfg file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful to write qtest about fw_cfg file entry. Signed-off-by: Li Qiang Acked-by: Thomas Huth Tested-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20190424140643.62457-3-liq3ea@163.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/libqos/fw_cfg.c | 45 +++++++++++++++++++++++++++++++++++++++++++ tests/libqos/fw_cfg.h | 2 ++ 2 files changed, 47 insertions(+) diff --git a/tests/libqos/fw_cfg.c b/tests/libqos/fw_cfg.c index c6839c53c8..1f46258f96 100644 --- a/tests/libqos/fw_cfg.c +++ b/tests/libqos/fw_cfg.c @@ -16,6 +16,7 @@ #include "libqos/fw_cfg.h" #include "libqtest.h" #include "qemu/bswap.h" +#include "hw/nvram/fw_cfg.h" void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key) { @@ -59,6 +60,50 @@ static void mm_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key) qtest_writew(fw_cfg->qts, fw_cfg->base, key); } +/* + * The caller need check the return value. When the return value is + * nonzero, it means that some bytes have been transferred. + * + * If the fw_cfg file in question is smaller than the allocated & passed-in + * buffer, then the buffer has been populated only in part. + * + * If the fw_cfg file in question is larger than the passed-in + * buffer, then the return value explains how much room would have been + * necessary in total. And, while the caller's buffer has been fully + * populated, it has received only a starting slice of the fw_cfg file. + */ +size_t qfw_cfg_get_file(QFWCFG *fw_cfg, const char *filename, + void *data, size_t buflen) +{ + uint32_t count; + uint32_t i; + unsigned char *filesbuf = NULL; + size_t dsize; + FWCfgFile *pdir_entry; + size_t filesize = 0; + + qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, &count, sizeof(count)); + count = be32_to_cpu(count); + dsize = sizeof(uint32_t) + count * sizeof(struct fw_cfg_file); + filesbuf = g_malloc(dsize); + qfw_cfg_get(fw_cfg, FW_CFG_FILE_DIR, filesbuf, dsize); + pdir_entry = (FWCfgFile *)(filesbuf + sizeof(uint32_t)); + for (i = 0; i < count; ++i, ++pdir_entry) { + if (!strcmp(pdir_entry->name, filename)) { + uint32_t len = be32_to_cpu(pdir_entry->size); + uint16_t sel = be16_to_cpu(pdir_entry->select); + filesize = len; + if (len > buflen) { + len = buflen; + } + qfw_cfg_get(fw_cfg, sel, data, len); + break; + } + } + g_free(filesbuf); + return filesize; +} + static void mm_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len) { uint8_t *ptr = data; diff --git a/tests/libqos/fw_cfg.h b/tests/libqos/fw_cfg.h index 60de81e863..13325cc4ff 100644 --- a/tests/libqos/fw_cfg.h +++ b/tests/libqos/fw_cfg.h @@ -31,6 +31,8 @@ void qfw_cfg_get(QFWCFG *fw_cfg, uint16_t key, void *data, size_t len); uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key); uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key); uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key); +size_t qfw_cfg_get_file(QFWCFG *fw_cfg, const char *filename, + void *data, size_t buflen); QFWCFG *mm_fw_cfg_init(QTestState *qts, uint64_t base); void mm_fw_cfg_uninit(QFWCFG *fw_cfg); From 04da973501b591525ce68c2925c61c8886badd4d Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Wed, 24 Apr 2019 07:06:41 -0700 Subject: [PATCH 13/15] hw/nvram/fw_cfg: Store 'reboot-timeout' as little endian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current codebase is not specific about the endianess of the fw_cfg 'file' entry 'reboot-timeout'. Per docs/specs/fw_cfg.txt: === All Other Data Items === Please consult the QEMU source for the most up-to-date and authoritative list of selector keys and their respective items' purpose, format and writeability. Checking the git history, this code was introduced in commit ac05f3492421, very similar to commit 3d3b8303c6f8 for the 'boot-menu-wait' entry, which explicitely use little-endian. OVMF consumes 'boot-menu-wait' as little-endian, however it does not consume 'reboot-timeout'. Regarding the git history and OVMF use, we choose to explicit 'reboot-timeout' endianess as little-endian. Signed-off-by: Li Qiang Tested-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20190424140643.62457-4-liq3ea@163.com> [PMD: Reword commit description based on review comments] Signed-off-by: Philippe Mathieu-Daudé --- hw/nvram/fw_cfg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index b2dc0a80cb..9f7b7789bc 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -234,6 +234,7 @@ static void fw_cfg_reboot(FWCfgState *s) { const char *reboot_timeout = NULL; int64_t rt_val = -1; + uint32_t rt_le32; /* get user configuration */ QemuOptsList *plist = qemu_find_opts("boot-opts"); @@ -250,7 +251,8 @@ static void fw_cfg_reboot(FWCfgState *s) } } - fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_val, 4), 4); + rt_le32 = cpu_to_le32(rt_val); + fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_le32, 4), 4); } static void fw_cfg_write(FWCfgState *s, uint8_t value) From b41e912f32db79f97cc289dce57a13ca7d45332c Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Wed, 24 Apr 2019 07:06:42 -0700 Subject: [PATCH 14/15] tests: fw_cfg: add 'reboot-timeout' test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Li Qiang Tested-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20190424140643.62457-5-liq3ea@163.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/fw_cfg-test.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c index 4597626dd7..20b1eb75f4 100644 --- a/tests/fw_cfg-test.c +++ b/tests/fw_cfg-test.c @@ -15,6 +15,7 @@ #include "libqtest.h" #include "standard-headers/linux/qemu_fw_cfg.h" #include "libqos/fw_cfg.h" +#include "qemu/bswap.h" static uint64_t ram_size = 128 << 20; static uint16_t nb_cpus = 1; @@ -174,6 +175,25 @@ static void test_fw_cfg_boot_menu(void) qtest_quit(s); } +static void test_fw_cfg_reboot_timeout(void) +{ + QFWCFG *fw_cfg; + QTestState *s; + uint32_t reboot_timeout = 0; + size_t filesize; + + s = qtest_init("-boot reboot-timeout=15"); + fw_cfg = pc_fw_cfg_init(s); + + filesize = qfw_cfg_get_file(fw_cfg, "etc/boot-fail-wait", + &reboot_timeout, sizeof(reboot_timeout)); + g_assert_cmpint(filesize, ==, sizeof(reboot_timeout)); + reboot_timeout = le32_to_cpu(reboot_timeout); + g_assert_cmpint(reboot_timeout, ==, 15); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -193,6 +213,7 @@ int main(int argc, char **argv) qtest_add_func("fw_cfg/max_cpus", test_fw_cfg_max_cpus); qtest_add_func("fw_cfg/numa", test_fw_cfg_numa); qtest_add_func("fw_cfg/boot_menu", test_fw_cfg_boot_menu); + qtest_add_func("fw_cfg/reboot_timeout", test_fw_cfg_reboot_timeout); return g_test_run(); } From 3ae9dd1a304248e1f6ca631cdd43eb44a3e9e7b4 Mon Sep 17 00:00:00 2001 From: Li Qiang Date: Wed, 24 Apr 2019 07:06:43 -0700 Subject: [PATCH 15/15] tests: fw_cfg: add 'splash-time' test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Li Qiang Tested-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20190424140643.62457-6-liq3ea@163.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/fw_cfg-test.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c index 20b1eb75f4..1d3147f821 100644 --- a/tests/fw_cfg-test.c +++ b/tests/fw_cfg-test.c @@ -194,6 +194,25 @@ static void test_fw_cfg_reboot_timeout(void) qtest_quit(s); } +static void test_fw_cfg_splash_time(void) +{ + QFWCFG *fw_cfg; + QTestState *s; + uint16_t splash_time = 0; + size_t filesize; + + s = qtest_init("-boot splash-time=12"); + fw_cfg = pc_fw_cfg_init(s); + + filesize = qfw_cfg_get_file(fw_cfg, "etc/boot-menu-wait", + &splash_time, sizeof(splash_time)); + g_assert_cmpint(filesize, ==, sizeof(splash_time)); + splash_time = le16_to_cpu(splash_time); + g_assert_cmpint(splash_time, ==, 12); + pc_fw_cfg_uninit(fw_cfg); + qtest_quit(s); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -214,6 +233,7 @@ int main(int argc, char **argv) qtest_add_func("fw_cfg/numa", test_fw_cfg_numa); qtest_add_func("fw_cfg/boot_menu", test_fw_cfg_boot_menu); qtest_add_func("fw_cfg/reboot_timeout", test_fw_cfg_reboot_timeout); + qtest_add_func("fw_cfg/splash_time", test_fw_cfg_splash_time); return g_test_run(); }