Re: [U-Boot] [PATCH v4 1/8] x86: qemu: add fw_cfg support

2016-01-03 Thread Bin Meng
Hi Miao,

On Thu, Dec 31, 2015 at 10:55 AM, 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
>
> 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

2015-12-31 Thread Miao Yan
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

2015-12-31 Thread Simon Glass
Hi Miao,

On 31 December 2015 at 01:42, Miao Yan  wrote:
> 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

2015-12-30 Thread Miao Yan
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

2015-12-30 Thread 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

> +
> +   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;
>