Re: [U-Boot] [PATCH v6 2/8] x86: qemu: add fw_cfg support

2016-01-11 Thread Bin Meng
On Tue, Jan 12, 2016 at 11:47 AM, Bin Meng  wrote:
> On Thu, Jan 7, 2016 at 5:32 PM, 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 
>> Reviewed-by: Simon Glass 
>> Reviewed-by: Bin Meng 
>> ---
>> Changes in v6:
>>   - fix oneline comment
>>   - do not update bootargs when kernel cmdline only contains '\0'
>>
>>  arch/x86/cpu/qemu/Makefile|   2 +-
>>  arch/x86/cpu/qemu/fw_cfg.c| 283 
>> ++
>>  arch/x86/cpu/qemu/qemu.c  |   3 +
>>  arch/x86/include/asm/fw_cfg.h |  93 ++
>>  4 files changed, 380 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/x86/cpu/qemu/fw_cfg.c
>>  create mode 100644 arch/x86/include/asm/fw_cfg.h
>>
>
> Tested-by: Bin Meng 

applied to u-boot-x86/next, thanks!
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH v6 2/8] x86: qemu: add fw_cfg support

2016-01-11 Thread Bin Meng
On Thu, Jan 7, 2016 at 5:32 PM, 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 
> Reviewed-by: Simon Glass 
> Reviewed-by: Bin Meng 
> ---
> Changes in v6:
>   - fix oneline comment
>   - do not update bootargs when kernel cmdline only contains '\0'
>
>  arch/x86/cpu/qemu/Makefile|   2 +-
>  arch/x86/cpu/qemu/fw_cfg.c| 283 
> ++
>  arch/x86/cpu/qemu/qemu.c  |   3 +
>  arch/x86/include/asm/fw_cfg.h |  93 ++
>  4 files changed, 380 insertions(+), 1 deletion(-)
>  create mode 100644 arch/x86/cpu/qemu/fw_cfg.c
>  create mode 100644 arch/x86/include/asm/fw_cfg.h
>

Tested-by: Bin Meng 
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v6 2/8] x86: qemu: add fw_cfg support

2016-01-07 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 
Reviewed-by: Simon Glass 
Reviewed-by: Bin Meng 
---
Changes in v6:
  - fix oneline comment
  - do not update bootargs when kernel cmdline only contains '\0'

 arch/x86/cpu/qemu/Makefile|   2 +-
 arch/x86/cpu/qemu/fw_cfg.c| 283 ++
 arch/x86/cpu/qemu/qemu.c  |   3 +
 arch/x86/include/asm/fw_cfg.h |  93 ++
 4 files changed, 380 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/cpu/qemu/fw_cfg.c
 create mode 100644 arch/x86/include/asm/fw_cfg.h

diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile
index 3f3958a..d613798 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 += fw_cfg.o qemu.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..0599214
--- /dev/null
+++ b/arch/x86/cpu/qemu/fw_cfg.c
@@ -0,0 +1,283 @@
+/*
+ * (C) Copyright 2015 Miao Yan 
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static bool fwcfg_present;
+static bool fwcfg_dma_present;
+
+/* Read configuration item using fw_cfg PIO interface */
+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);
+}
+
+/* Read configuration item using fw_cfg DMA interface */
+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)&dma), 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, &qemu);
+   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, &dma_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 -ENODEV;
+
+   qemu_fwcfg_read_entry(FW_CFG_NB_CPUS, 2, &nb_cpus);
+
+   return le16_to_cpu(nb_cpus);
+}
+
+/*
+ * This function prepares kernel for zboot. It loads kernel data
+ * to 'load_addr', initrd to 'initrd_addr' and kernel command
+ * line using qemu fw_cfg interface.
+ */
+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, &setup_size);
+   qemu_fwcfg_read_entry(FW_CFG_KERNEL_SIZE, 4, &kernel_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_fw