Re: [U-Boot] [PATCH v4 1/8] x86: qemu: add fw_cfg support
Hi Miao, On Thu, Dec 31, 2015 at 10:55 AM, Miao Yanwrote: > The QEMU fw_cfg interface allows the guest to retrieve various > data information from QEMU. For example, APCI/SMBios tables, number > of online cpus, kernel data and command line, etc. > > This patch adds support for QEMU fw_cfg interface. > > Signed-off-by: Miao Yan > --- > Changes in v4: > - cleanups > - change 'fw load' to take second parameter for initrd load address > > arch/x86/cpu/qemu/Makefile | 2 +- > arch/x86/cpu/qemu/fw_cfg.c | 268 > + > arch/x86/cpu/qemu/fw_cfg.h | 97 > arch/x86/cpu/qemu/qemu.c | 3 + > 4 files changed, 369 insertions(+), 1 deletion(-) > create mode 100644 arch/x86/cpu/qemu/fw_cfg.c > create mode 100644 arch/x86/cpu/qemu/fw_cfg.h > > diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile > index 3f3958a..ad424ec 100644 > --- a/arch/x86/cpu/qemu/Makefile > +++ b/arch/x86/cpu/qemu/Makefile > @@ -7,5 +7,5 @@ > ifndef CONFIG_EFI_STUB > obj-y += car.o dram.o > endif > -obj-y += qemu.o > +obj-y += qemu.o fw_cfg.o > obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o > diff --git a/arch/x86/cpu/qemu/fw_cfg.c b/arch/x86/cpu/qemu/fw_cfg.c > new file mode 100644 > index 000..9de8680 > --- /dev/null > +++ b/arch/x86/cpu/qemu/fw_cfg.c > @@ -0,0 +1,268 @@ > +/* > + * (C) Copyright 2015 Miao Yan > + * > + * SPDX-License-Identifier:GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include "fw_cfg.h" > + > +static bool fwcfg_present; > +static bool fwcfg_dma_present; > + > +static void qemu_fwcfg_read_entry_pio(uint16_t entry, > + uint32_t size, void *address) > +{ > + uint32_t i = 0; > + uint8_t *data = address; > + > + /* > +* writting FW_CFG_INVALID will cause > +* read operation to resume at > +* last offset, otherwise read will > +* start at offset 0 > +*/ > + > + if (entry != FW_CFG_INVALID) > + outw(entry, FW_CONTROL_PORT); > + while (size--) > + data[i++] = inb(FW_DATA_PORT); > +} > + > +static void qemu_fwcfg_read_entry_dma(uint16_t entry, > + uint32_t size, void *address) > +{ > + struct fw_cfg_dma_access dma; > + > + dma.length = cpu_to_be32(size); > + dma.address = cpu_to_be64((uintptr_t)address); > + dma.control = cpu_to_be32(FW_CFG_DMA_READ); > + > + /* > +* writting FW_CFG_INVALID will cause > +* read operation to resume at > +* last offset, otherwise read will > +* start at offset 0 > +*/ > + > + if (entry != FW_CFG_INVALID) > + dma.control |= cpu_to_be32(FW_CFG_DMA_SELECT | (entry << 16)); > + > + barrier(); > + > + debug("qemu_fwcfg_dma_read_entry: addr %p, length %u control 0x%x\n", > + address, size, be32_to_cpu(dma.control)); > + > + outl(cpu_to_be32((uint32_t)), FW_DMA_PORT_HIGH); > + > + while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_ERROR) > + __asm__ __volatile__ ("pause"); > +} > + > +static bool qemu_fwcfg_present(void) > +{ > + uint32_t qemu; > + > + qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, ); > + return be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE; > +} > + > +static bool qemu_fwcfg_dma_present(void) > +{ > + uint8_t dma_enabled; > + > + qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, _enabled); > + if (dma_enabled & FW_CFG_DMA_ENABLED) > + return true; > + > + return false; > +} > + > +static void qemu_fwcfg_read_entry(uint16_t entry, > + uint32_t length, void *address) > +{ > + if (fwcfg_dma_present) > + qemu_fwcfg_read_entry_dma(entry, length, address); > + else > + qemu_fwcfg_read_entry_pio(entry, length, address); > +} > + > +int qemu_fwcfg_online_cpus(void) > +{ > + uint16_t nb_cpus; > + > + if (!fwcfg_present) > + return 1; > + > + qemu_fwcfg_read_entry(FW_CFG_NB_CPUS, 2, _cpus); > + > + return le16_to_cpu(nb_cpus); > +} > + > +static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr) > +{ > + char *data_addr; > + uint32_t setup_size, kernel_size, cmdline_size, initrd_size; > + > + qemu_fwcfg_read_entry(FW_CFG_SETUP_SIZE, 4, _size); > + qemu_fwcfg_read_entry(FW_CFG_KERNEL_SIZE, 4, _size); > + > + if (setup_size == 0 || kernel_size == 0) { > + printf("warning: no kernel available\n"); > + return -1; > + } > + > + data_addr = load_addr; > + qemu_fwcfg_read_entry(FW_CFG_SETUP_DATA, > + le32_to_cpu(setup_size), data_addr); > + data_addr += le32_to_cpu(setup_size); > + > + qemu_fwcfg_read_entry(FW_CFG_KERNEL_DATA, > +
Re: [U-Boot] [PATCH v4 1/8] x86: qemu: add fw_cfg support
Hi Simon, 2015-12-31 13:07 GMT+08:00 Simon Glass: > Hi Miao, > > On 30 December 2015 at 19:55, Miao Yan wrote: >> The QEMU fw_cfg interface allows the guest to retrieve various >> data information from QEMU. For example, APCI/SMBios tables, number >> of online cpus, kernel data and command line, etc. >> >> This patch adds support for QEMU fw_cfg interface. >> >> Signed-off-by: Miao Yan >> --- >> Changes in v4: >> - cleanups >> - change 'fw load' to take second parameter for initrd load address >> >> arch/x86/cpu/qemu/Makefile | 2 +- >> arch/x86/cpu/qemu/fw_cfg.c | 268 >> + >> arch/x86/cpu/qemu/fw_cfg.h | 97 >> arch/x86/cpu/qemu/qemu.c | 3 + >> 4 files changed, 369 insertions(+), 1 deletion(-) >> create mode 100644 arch/x86/cpu/qemu/fw_cfg.c >> create mode 100644 arch/x86/cpu/qemu/fw_cfg.h > > Reviewed-by: Simon Glass > > But a few nits... > >> >> diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile >> index 3f3958a..ad424ec 100644 >> --- a/arch/x86/cpu/qemu/Makefile >> +++ b/arch/x86/cpu/qemu/Makefile >> @@ -7,5 +7,5 @@ >> ifndef CONFIG_EFI_STUB >> obj-y += car.o dram.o >> endif >> -obj-y += qemu.o >> +obj-y += qemu.o fw_cfg.o > > Can you put the new file first, so that the list is in alphabetical order? > >> obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o >> diff --git a/arch/x86/cpu/qemu/fw_cfg.c b/arch/x86/cpu/qemu/fw_cfg.c >> new file mode 100644 >> index 000..9de8680 >> --- /dev/null >> +++ b/arch/x86/cpu/qemu/fw_cfg.c >> @@ -0,0 +1,268 @@ >> +/* >> + * (C) Copyright 2015 Miao Yan >> + * >> + * SPDX-License-Identifier:GPL-2.0+ >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include "fw_cfg.h" >> + >> +static bool fwcfg_present; >> +static bool fwcfg_dma_present; >> + >> +static void qemu_fwcfg_read_entry_pio(uint16_t entry, >> + uint32_t size, void *address) > > Function comment - what does this do? > >> +{ >> + uint32_t i = 0; >> + uint8_t *data = address; >> + >> + /* >> +* writting FW_CFG_INVALID will cause >> +* read operation to resume at >> +* last offset, otherwise read will >> +* start at offset 0 > > Please can you format comments to 75 columns or thereabout? > >> +*/ >> + >> + if (entry != FW_CFG_INVALID) >> + outw(entry, FW_CONTROL_PORT); >> + while (size--) >> + data[i++] = inb(FW_DATA_PORT); >> +} >> + >> +static void qemu_fwcfg_read_entry_dma(uint16_t entry, >> + uint32_t size, void *address) >> +{ >> + struct fw_cfg_dma_access dma; >> + >> + dma.length = cpu_to_be32(size); >> + dma.address = cpu_to_be64((uintptr_t)address); >> + dma.control = cpu_to_be32(FW_CFG_DMA_READ); >> + >> + /* >> +* writting FW_CFG_INVALID will cause >> +* read operation to resume at >> +* last offset, otherwise read will >> +* start at offset 0 >> +*/ >> + >> + if (entry != FW_CFG_INVALID) >> + dma.control |= cpu_to_be32(FW_CFG_DMA_SELECT | (entry << >> 16)); >> + >> + barrier(); >> + >> + debug("qemu_fwcfg_dma_read_entry: addr %p, length %u control 0x%x\n", >> + address, size, be32_to_cpu(dma.control)); >> + >> + outl(cpu_to_be32((uint32_t)), FW_DMA_PORT_HIGH); >> + >> + while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_ERROR) >> + __asm__ __volatile__ ("pause"); >> +} >> + >> +static bool qemu_fwcfg_present(void) >> +{ >> + uint32_t qemu; >> + >> + qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, ); >> + return be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE; >> +} >> + >> +static bool qemu_fwcfg_dma_present(void) >> +{ >> + uint8_t dma_enabled; >> + >> + qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, _enabled); >> + if (dma_enabled & FW_CFG_DMA_ENABLED) >> + return true; >> + >> + return false; >> +} >> + >> +static void qemu_fwcfg_read_entry(uint16_t entry, >> + uint32_t length, void *address) >> +{ >> + if (fwcfg_dma_present) >> + qemu_fwcfg_read_entry_dma(entry, length, address); >> + else >> + qemu_fwcfg_read_entry_pio(entry, length, address); >> +} >> + >> +int qemu_fwcfg_online_cpus(void) >> +{ >> + uint16_t nb_cpus; >> + >> + if (!fwcfg_present) >> + return 1; > > -ENODEV Can we return 1 cpu if fw_cfg interface is not avaliable (which is quite unlikey), and print a warning maybe ? Because there has to be one cpu at least and returning -ENODEV wouldn't make much difference. I'll fix rest of your comments and thanks for the review. Miao > >> + >> + qemu_fwcfg_read_entry(FW_CFG_NB_CPUS, 2, _cpus); >> + >> + return le16_to_cpu(nb_cpus); >> +} >> + >>
Re: [U-Boot] [PATCH v4 1/8] x86: qemu: add fw_cfg support
Hi Miao, On 31 December 2015 at 01:42, Miao Yanwrote: > Hi Simon, > > 2015-12-31 13:07 GMT+08:00 Simon Glass : >> Hi Miao, >> >> On 30 December 2015 at 19:55, Miao Yan wrote: >>> The QEMU fw_cfg interface allows the guest to retrieve various >>> data information from QEMU. For example, APCI/SMBios tables, number >>> of online cpus, kernel data and command line, etc. >>> >>> This patch adds support for QEMU fw_cfg interface. >>> >>> Signed-off-by: Miao Yan >>> --- >>> Changes in v4: >>> - cleanups >>> - change 'fw load' to take second parameter for initrd load address >>> >>> arch/x86/cpu/qemu/Makefile | 2 +- >>> arch/x86/cpu/qemu/fw_cfg.c | 268 >>> + >>> arch/x86/cpu/qemu/fw_cfg.h | 97 >>> arch/x86/cpu/qemu/qemu.c | 3 + >>> 4 files changed, 369 insertions(+), 1 deletion(-) >>> create mode 100644 arch/x86/cpu/qemu/fw_cfg.c >>> create mode 100644 arch/x86/cpu/qemu/fw_cfg.h >> >> Reviewed-by: Simon Glass >> >> But a few nits... [snip] >>> +int qemu_fwcfg_online_cpus(void) >>> +{ >>> + uint16_t nb_cpus; >>> + >>> + if (!fwcfg_present) >>> + return 1; >> >> -ENODEV > > > Can we return 1 cpu if fw_cfg interface is not avaliable (which is > quite unlikey), > and print a warning maybe ? Because there has to be one cpu at least > and returning > -ENODEV wouldn't make much difference. I see. In that case I think it is better if qemu_fwcfg_online_cpus() returns an error and its caller can detect -ENODEV and use '1' as the value. Then the decision as to how to deal with the error is handled at the layer that is taking action. > > I'll fix rest of your comments and thanks for the review. > > Miao > [snip] ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH v4 1/8] x86: qemu: add fw_cfg support
The QEMU fw_cfg interface allows the guest to retrieve various data information from QEMU. For example, APCI/SMBios tables, number of online cpus, kernel data and command line, etc. This patch adds support for QEMU fw_cfg interface. Signed-off-by: Miao Yan--- Changes in v4: - cleanups - change 'fw load' to take second parameter for initrd load address arch/x86/cpu/qemu/Makefile | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 268 + arch/x86/cpu/qemu/fw_cfg.h | 97 arch/x86/cpu/qemu/qemu.c | 3 + 4 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/qemu/fw_cfg.c create mode 100644 arch/x86/cpu/qemu/fw_cfg.h diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile index 3f3958a..ad424ec 100644 --- a/arch/x86/cpu/qemu/Makefile +++ b/arch/x86/cpu/qemu/Makefile @@ -7,5 +7,5 @@ ifndef CONFIG_EFI_STUB obj-y += car.o dram.o endif -obj-y += qemu.o +obj-y += qemu.o fw_cfg.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o diff --git a/arch/x86/cpu/qemu/fw_cfg.c b/arch/x86/cpu/qemu/fw_cfg.c new file mode 100644 index 000..9de8680 --- /dev/null +++ b/arch/x86/cpu/qemu/fw_cfg.c @@ -0,0 +1,268 @@ +/* + * (C) Copyright 2015 Miao Yan + * + * SPDX-License-Identifier:GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include "fw_cfg.h" + +static bool fwcfg_present; +static bool fwcfg_dma_present; + +static void qemu_fwcfg_read_entry_pio(uint16_t entry, + uint32_t size, void *address) +{ + uint32_t i = 0; + uint8_t *data = address; + + /* +* writting FW_CFG_INVALID will cause +* read operation to resume at +* last offset, otherwise read will +* start at offset 0 +*/ + + if (entry != FW_CFG_INVALID) + outw(entry, FW_CONTROL_PORT); + while (size--) + data[i++] = inb(FW_DATA_PORT); +} + +static void qemu_fwcfg_read_entry_dma(uint16_t entry, + uint32_t size, void *address) +{ + struct fw_cfg_dma_access dma; + + dma.length = cpu_to_be32(size); + dma.address = cpu_to_be64((uintptr_t)address); + dma.control = cpu_to_be32(FW_CFG_DMA_READ); + + /* +* writting FW_CFG_INVALID will cause +* read operation to resume at +* last offset, otherwise read will +* start at offset 0 +*/ + + if (entry != FW_CFG_INVALID) + dma.control |= cpu_to_be32(FW_CFG_DMA_SELECT | (entry << 16)); + + barrier(); + + debug("qemu_fwcfg_dma_read_entry: addr %p, length %u control 0x%x\n", + address, size, be32_to_cpu(dma.control)); + + outl(cpu_to_be32((uint32_t)), FW_DMA_PORT_HIGH); + + while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_ERROR) + __asm__ __volatile__ ("pause"); +} + +static bool qemu_fwcfg_present(void) +{ + uint32_t qemu; + + qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, ); + return be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE; +} + +static bool qemu_fwcfg_dma_present(void) +{ + uint8_t dma_enabled; + + qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, _enabled); + if (dma_enabled & FW_CFG_DMA_ENABLED) + return true; + + return false; +} + +static void qemu_fwcfg_read_entry(uint16_t entry, + uint32_t length, void *address) +{ + if (fwcfg_dma_present) + qemu_fwcfg_read_entry_dma(entry, length, address); + else + qemu_fwcfg_read_entry_pio(entry, length, address); +} + +int qemu_fwcfg_online_cpus(void) +{ + uint16_t nb_cpus; + + if (!fwcfg_present) + return 1; + + qemu_fwcfg_read_entry(FW_CFG_NB_CPUS, 2, _cpus); + + return le16_to_cpu(nb_cpus); +} + +static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr) +{ + char *data_addr; + uint32_t setup_size, kernel_size, cmdline_size, initrd_size; + + qemu_fwcfg_read_entry(FW_CFG_SETUP_SIZE, 4, _size); + qemu_fwcfg_read_entry(FW_CFG_KERNEL_SIZE, 4, _size); + + if (setup_size == 0 || kernel_size == 0) { + printf("warning: no kernel available\n"); + return -1; + } + + data_addr = load_addr; + qemu_fwcfg_read_entry(FW_CFG_SETUP_DATA, + le32_to_cpu(setup_size), data_addr); + data_addr += le32_to_cpu(setup_size); + + qemu_fwcfg_read_entry(FW_CFG_KERNEL_DATA, + le32_to_cpu(kernel_size), data_addr); + data_addr += le32_to_cpu(kernel_size); + + data_addr = initrd_addr; + qemu_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, _size); + if (initrd_size == 0) { + printf("warning: no initrd available\n"); + } else { + qemu_fwcfg_read_entry(FW_CFG_INITRD_DATA, + le32_to_cpu(initrd_size), data_addr); +
Re: [U-Boot] [PATCH v4 1/8] x86: qemu: add fw_cfg support
Hi Miao, On 30 December 2015 at 19:55, Miao Yanwrote: > The QEMU fw_cfg interface allows the guest to retrieve various > data information from QEMU. For example, APCI/SMBios tables, number > of online cpus, kernel data and command line, etc. > > This patch adds support for QEMU fw_cfg interface. > > Signed-off-by: Miao Yan > --- > Changes in v4: > - cleanups > - change 'fw load' to take second parameter for initrd load address > > arch/x86/cpu/qemu/Makefile | 2 +- > arch/x86/cpu/qemu/fw_cfg.c | 268 > + > arch/x86/cpu/qemu/fw_cfg.h | 97 > arch/x86/cpu/qemu/qemu.c | 3 + > 4 files changed, 369 insertions(+), 1 deletion(-) > create mode 100644 arch/x86/cpu/qemu/fw_cfg.c > create mode 100644 arch/x86/cpu/qemu/fw_cfg.h Reviewed-by: Simon Glass But a few nits... > > diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile > index 3f3958a..ad424ec 100644 > --- a/arch/x86/cpu/qemu/Makefile > +++ b/arch/x86/cpu/qemu/Makefile > @@ -7,5 +7,5 @@ > ifndef CONFIG_EFI_STUB > obj-y += car.o dram.o > endif > -obj-y += qemu.o > +obj-y += qemu.o fw_cfg.o Can you put the new file first, so that the list is in alphabetical order? > obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o dsdt.o > diff --git a/arch/x86/cpu/qemu/fw_cfg.c b/arch/x86/cpu/qemu/fw_cfg.c > new file mode 100644 > index 000..9de8680 > --- /dev/null > +++ b/arch/x86/cpu/qemu/fw_cfg.c > @@ -0,0 +1,268 @@ > +/* > + * (C) Copyright 2015 Miao Yan > + * > + * SPDX-License-Identifier:GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include "fw_cfg.h" > + > +static bool fwcfg_present; > +static bool fwcfg_dma_present; > + > +static void qemu_fwcfg_read_entry_pio(uint16_t entry, > + uint32_t size, void *address) Function comment - what does this do? > +{ > + uint32_t i = 0; > + uint8_t *data = address; > + > + /* > +* writting FW_CFG_INVALID will cause > +* read operation to resume at > +* last offset, otherwise read will > +* start at offset 0 Please can you format comments to 75 columns or thereabout? > +*/ > + > + if (entry != FW_CFG_INVALID) > + outw(entry, FW_CONTROL_PORT); > + while (size--) > + data[i++] = inb(FW_DATA_PORT); > +} > + > +static void qemu_fwcfg_read_entry_dma(uint16_t entry, > + uint32_t size, void *address) > +{ > + struct fw_cfg_dma_access dma; > + > + dma.length = cpu_to_be32(size); > + dma.address = cpu_to_be64((uintptr_t)address); > + dma.control = cpu_to_be32(FW_CFG_DMA_READ); > + > + /* > +* writting FW_CFG_INVALID will cause > +* read operation to resume at > +* last offset, otherwise read will > +* start at offset 0 > +*/ > + > + if (entry != FW_CFG_INVALID) > + dma.control |= cpu_to_be32(FW_CFG_DMA_SELECT | (entry << 16)); > + > + barrier(); > + > + debug("qemu_fwcfg_dma_read_entry: addr %p, length %u control 0x%x\n", > + address, size, be32_to_cpu(dma.control)); > + > + outl(cpu_to_be32((uint32_t)), FW_DMA_PORT_HIGH); > + > + while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_ERROR) > + __asm__ __volatile__ ("pause"); > +} > + > +static bool qemu_fwcfg_present(void) > +{ > + uint32_t qemu; > + > + qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, ); > + return be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE; > +} > + > +static bool qemu_fwcfg_dma_present(void) > +{ > + uint8_t dma_enabled; > + > + qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, _enabled); > + if (dma_enabled & FW_CFG_DMA_ENABLED) > + return true; > + > + return false; > +} > + > +static void qemu_fwcfg_read_entry(uint16_t entry, > + uint32_t length, void *address) > +{ > + if (fwcfg_dma_present) > + qemu_fwcfg_read_entry_dma(entry, length, address); > + else > + qemu_fwcfg_read_entry_pio(entry, length, address); > +} > + > +int qemu_fwcfg_online_cpus(void) > +{ > + uint16_t nb_cpus; > + > + if (!fwcfg_present) > + return 1; -ENODEV > + > + qemu_fwcfg_read_entry(FW_CFG_NB_CPUS, 2, _cpus); > + > + return le16_to_cpu(nb_cpus); > +} > + > +static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr) Function comment > +{ > + char *data_addr; > + uint32_t setup_size, kernel_size, cmdline_size, initrd_size; > + > + qemu_fwcfg_read_entry(FW_CFG_SETUP_SIZE, 4, _size); > + qemu_fwcfg_read_entry(FW_CFG_KERNEL_SIZE, 4, _size); > + > + if (setup_size == 0 || kernel_size == 0) { > + printf("warning: no kernel available\n"); > + return -1; > + } > + > + data_addr = load_addr; >