[U-Boot] [PATCH v2] x86: qemu: Move qfw command over to cmd and add Kconfig entry

- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c - Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h - Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com --- Changes in v2: - Depend on X86 (per Miao Yan) --- arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 2604a68..13bec7a 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -11,6 +11,7 @@ #include <dm.h> #include <errno.h> #include <malloc.h> +#include <qemu_fw_cfg.h> #include <asm/atomic.h> #include <asm/cpu.h> #include <asm/interrupt.h> @@ -21,7 +22,6 @@ #include <asm/mtrr.h> #include <asm/processor.h> #include <asm/sipi.h> -#include <asm/fw_cfg.h> #include <dm/device-internal.h> #include <dm/uclass-internal.h> #include <dm/lists.h> diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile index 6eeddf1..97b965c 100644 --- a/arch/x86/cpu/qemu/Makefile +++ b/arch/x86/cpu/qemu/Makefile @@ -7,4 +7,5 @@ ifndef CONFIG_EFI_STUB obj-y += car.o dram.o endif -obj-y += cpu.o fw_cfg.o qemu.o +obj-y += cpu.o qemu.o +obj-$(CONFIG_QEMU_ACPI_TABLE) += acpi_table.o diff --git a/arch/x86/cpu/qemu/acpi_table.c b/arch/x86/cpu/qemu/acpi_table.c new file mode 100644 index 0000000..49381ac --- /dev/null +++ b/arch/x86/cpu/qemu/acpi_table.c @@ -0,0 +1,243 @@ +/* + * (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <errno.h> +#include <malloc.h> +#include <qemu_fw_cfg.h> +#include <asm/io.h> +#include <asm/tables.h> +#include <asm/e820.h> +#include <linux/list.h> +#include <memalign.h> + +/* + * This function allocates memory for ACPI tables + * + * @entry : BIOS linker command entry which tells where to allocate memory + * (either high memory or low memory) + * @addr : The address that should be used for low memory allcation. If the + * memory allocation request is 'ZONE_HIGH' then this parameter will + * be ignored. + * @return: 0 on success, or negative value on failure + */ +static int bios_linker_allocate(struct bios_linker_entry *entry, u32 *addr) +{ + uint32_t size, align; + struct fw_file *file; + unsigned long aligned_addr; + + align = le32_to_cpu(entry->alloc.align); + /* align must be power of 2 */ + if (align & (align - 1)) { + printf("error: wrong alignment %u\n", align); + return -EINVAL; + } + + file = qemu_fwcfg_find_file(entry->alloc.file); + if (!file) { + printf("error: can't find file %s\n", entry->alloc.file); + return -ENOENT; + } + + size = be32_to_cpu(file->cfg.size); + + /* + * ZONE_HIGH means we need to allocate from high memory, since + * malloc space is already at the end of RAM, so we directly use it. + * If allocation zone is ZONE_FSEG, then we use the 'addr' passed + * in which is low memory + */ + if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) { + aligned_addr = (unsigned long)memalign(align, size); + if (!aligned_addr) { + printf("error: allocating resource\n"); + return -ENOMEM; + } + } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) { + aligned_addr = ALIGN(*addr, align); + } else { + printf("error: invalid allocation zone\n"); + return -EINVAL; + } + + debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n", + file->cfg.name, size, entry->alloc.zone, align, aligned_addr); + + qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select), + size, (void *)aligned_addr); + file->addr = aligned_addr; + + /* adjust address for low memory allocation */ + if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) + *addr = (aligned_addr + size); + + return 0; +} + +/* + * This function patches ACPI tables previously loaded + * by bios_linker_allocate() + * + * @entry : BIOS linker command entry which tells how to patch + * ACPI tables + * @return: 0 on success, or negative value on failure + */ +static int bios_linker_add_pointer(struct bios_linker_entry *entry) +{ + struct fw_file *dest, *src; + uint32_t offset = le32_to_cpu(entry->pointer.offset); + uint64_t pointer = 0; + + dest = qemu_fwcfg_find_file(entry->pointer.dest_file); + if (!dest || !dest->addr) + return -ENOENT; + src = qemu_fwcfg_find_file(entry->pointer.src_file); + if (!src || !src->addr) + return -ENOENT; + + debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n", + dest->addr, src->addr, offset, entry->pointer.size, pointer); + + memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size); + pointer = le64_to_cpu(pointer); + pointer += (unsigned long)src->addr; + pointer = cpu_to_le64(pointer); + memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size); + + return 0; +} + +/* + * This function updates checksum fields of ACPI tables previously loaded + * by bios_linker_allocate() + * + * @entry : BIOS linker command entry which tells where to update ACPI table + * checksums + * @return: 0 on success, or negative value on failure + */ +static int bios_linker_add_checksum(struct bios_linker_entry *entry) +{ + struct fw_file *file; + uint8_t *data, cksum = 0; + uint8_t *cksum_start; + + file = qemu_fwcfg_find_file(entry->cksum.file); + if (!file || !file->addr) + return -ENOENT; + + data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset)); + cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start)); + cksum = table_compute_checksum(cksum_start, + le32_to_cpu(entry->cksum.length)); + *data = cksum; + + return 0; +} + +unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) +{ + entries[0].addr = 0; + entries[0].size = ISA_START_ADDRESS; + entries[0].type = E820_RAM; + + entries[1].addr = ISA_START_ADDRESS; + entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS; + entries[1].type = E820_RESERVED; + + /* + * since we use memalign(malloc) to allocate high memory for + * storing ACPI tables, we need to reserve them in e820 tables, + * otherwise kernel will reclaim them and data will be corrupted + */ + entries[2].addr = ISA_END_ADDRESS; + entries[2].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS; + entries[2].type = E820_RAM; + + /* for simplicity, reserve entire malloc space */ + entries[3].addr = gd->relocaddr - TOTAL_MALLOC_LEN; + entries[3].size = TOTAL_MALLOC_LEN; + entries[3].type = E820_RESERVED; + + entries[4].addr = gd->relocaddr; + entries[4].size = gd->ram_size - gd->relocaddr; + entries[4].type = E820_RESERVED; + + entries[5].addr = CONFIG_PCIE_ECAM_BASE; + entries[5].size = CONFIG_PCIE_ECAM_SIZE; + entries[5].type = E820_RESERVED; + + return 6; +} + +/* This function loads and patches ACPI tables provided by QEMU */ +u32 write_acpi_tables(u32 addr) +{ + int i, ret = 0; + struct fw_file *file; + struct bios_linker_entry *table_loader; + struct bios_linker_entry *entry; + uint32_t size; + + /* make sure fw_list is loaded */ + ret = qemu_fwcfg_read_firmware_list(); + if (ret) { + printf("error: can't read firmware file list\n"); + return addr; + } + + file = qemu_fwcfg_find_file("etc/table-loader"); + if (!file) { + printf("error: can't find etc/table-loader\n"); + return addr; + } + + size = be32_to_cpu(file->cfg.size); + if ((size % sizeof(*entry)) != 0) { + printf("error: table-loader maybe corrupted\n"); + return addr; + } + + table_loader = malloc(size); + if (!table_loader) { + printf("error: no memory for table-loader\n"); + return addr; + } + + qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select), + size, table_loader); + + for (i = 0; i < (size / sizeof(*entry)); i++) { + entry = table_loader + i; + switch (le32_to_cpu(entry->command)) { + case BIOS_LINKER_LOADER_COMMAND_ALLOCATE: + ret = bios_linker_allocate(entry, &addr); + if (ret) + goto out; + break; + case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER: + ret = bios_linker_add_pointer(entry); + if (ret) + goto out; + break; + case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM: + ret = bios_linker_add_checksum(entry); + if (ret) + goto out; + break; + default: + break; + } + } + +out: + if (ret) + qemu_fwcfg_free_files(); + + free(table_loader); + return addr; +} diff --git a/arch/x86/cpu/qemu/cpu.c b/arch/x86/cpu/qemu/cpu.c index a1b70c6..4d2989a 100644 --- a/arch/x86/cpu/qemu/cpu.c +++ b/arch/x86/cpu/qemu/cpu.c @@ -8,8 +8,8 @@ #include <cpu.h> #include <dm.h> #include <errno.h> +#include <qemu_fw_cfg.h> #include <asm/cpu.h> -#include <asm/fw_cfg.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/x86/cpu/qemu/fw_cfg.c b/arch/x86/cpu/qemu/fw_cfg.c deleted file mode 100644 index 2e2794e..0000000 --- a/arch/x86/cpu/qemu/fw_cfg.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <command.h> -#include <errno.h> -#include <malloc.h> -#include <asm/io.h> -#include <asm/fw_cfg.h> -#include <asm/tables.h> -#include <asm/e820.h> -#include <linux/list.h> -#include <memalign.h> - -static bool fwcfg_present; -static bool fwcfg_dma_present; - -static LIST_HEAD(fw_list); - -/* 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_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, &initrd_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); - data_addr += le32_to_cpu(initrd_size); - } - - qemu_fwcfg_read_entry(FW_CFG_CMDLINE_SIZE, 4, &cmdline_size); - if (cmdline_size) { - qemu_fwcfg_read_entry(FW_CFG_CMDLINE_DATA, - le32_to_cpu(cmdline_size), data_addr); - /* - * if kernel cmdline only contains '\0', (e.g. no -append - * when invoking qemu), do not update bootargs - */ - if (*data_addr != '\0') { - if (setenv("bootargs", data_addr) < 0) - printf("warning: unable to change bootargs\n"); - } - } - - printf("loading kernel to address %p size %x", load_addr, - le32_to_cpu(kernel_size)); - if (initrd_size) - printf(" initrd %p size %x\n", - initrd_addr, - le32_to_cpu(initrd_size)); - else - printf("\n"); - - return 0; -} - -static int qemu_fwcfg_read_firmware_list(void) -{ - int i; - uint32_t count; - struct fw_file *file; - struct list_head *entry; - - /* don't read it twice */ - if (!list_empty(&fw_list)) - return 0; - - qemu_fwcfg_read_entry(FW_CFG_FILE_DIR, 4, &count); - if (!count) - return 0; - - count = be32_to_cpu(count); - for (i = 0; i < count; i++) { - file = malloc(sizeof(*file)); - if (!file) { - printf("error: allocating resource\n"); - goto err; - } - qemu_fwcfg_read_entry(FW_CFG_INVALID, - sizeof(struct fw_cfg_file), &file->cfg); - file->addr = 0; - list_add_tail(&file->list, &fw_list); - } - - return 0; - -err: - list_for_each(entry, &fw_list) { - file = list_entry(entry, struct fw_file, list); - free(file); - } - - return -ENOMEM; -} - -#ifdef CONFIG_QEMU_ACPI_TABLE -static struct fw_file *qemu_fwcfg_find_file(const char *name) -{ - struct list_head *entry; - struct fw_file *file; - - list_for_each(entry, &fw_list) { - file = list_entry(entry, struct fw_file, list); - if (!strcmp(file->cfg.name, name)) - return file; - } - - return NULL; -} - -/* - * This function allocates memory for ACPI tables - * - * @entry : BIOS linker command entry which tells where to allocate memory - * (either high memory or low memory) - * @addr : The address that should be used for low memory allcation. If the - * memory allocation request is 'ZONE_HIGH' then this parameter will - * be ignored. - * @return: 0 on success, or negative value on failure - */ -static int bios_linker_allocate(struct bios_linker_entry *entry, u32 *addr) -{ - uint32_t size, align; - struct fw_file *file; - unsigned long aligned_addr; - - align = le32_to_cpu(entry->alloc.align); - /* align must be power of 2 */ - if (align & (align - 1)) { - printf("error: wrong alignment %u\n", align); - return -EINVAL; - } - - file = qemu_fwcfg_find_file(entry->alloc.file); - if (!file) { - printf("error: can't find file %s\n", entry->alloc.file); - return -ENOENT; - } - - size = be32_to_cpu(file->cfg.size); - - /* - * ZONE_HIGH means we need to allocate from high memory, since - * malloc space is already at the end of RAM, so we directly use it. - * If allocation zone is ZONE_FSEG, then we use the 'addr' passed - * in which is low memory - */ - if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) { - aligned_addr = (unsigned long)memalign(align, size); - if (!aligned_addr) { - printf("error: allocating resource\n"); - return -ENOMEM; - } - } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) { - aligned_addr = ALIGN(*addr, align); - } else { - printf("error: invalid allocation zone\n"); - return -EINVAL; - } - - debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n", - file->cfg.name, size, entry->alloc.zone, align, aligned_addr); - - qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select), - size, (void *)aligned_addr); - file->addr = aligned_addr; - - /* adjust address for low memory allocation */ - if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) - *addr = (aligned_addr + size); - - return 0; -} - -/* - * This function patches ACPI tables previously loaded - * by bios_linker_allocate() - * - * @entry : BIOS linker command entry which tells how to patch - * ACPI tables - * @return: 0 on success, or negative value on failure - */ -static int bios_linker_add_pointer(struct bios_linker_entry *entry) -{ - struct fw_file *dest, *src; - uint32_t offset = le32_to_cpu(entry->pointer.offset); - uint64_t pointer = 0; - - dest = qemu_fwcfg_find_file(entry->pointer.dest_file); - if (!dest || !dest->addr) - return -ENOENT; - src = qemu_fwcfg_find_file(entry->pointer.src_file); - if (!src || !src->addr) - return -ENOENT; - - debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n", - dest->addr, src->addr, offset, entry->pointer.size, pointer); - - memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size); - pointer = le64_to_cpu(pointer); - pointer += (unsigned long)src->addr; - pointer = cpu_to_le64(pointer); - memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size); - - return 0; -} - -/* - * This function updates checksum fields of ACPI tables previously loaded - * by bios_linker_allocate() - * - * @entry : BIOS linker command entry which tells where to update ACPI table - * checksums - * @return: 0 on success, or negative value on failure - */ -static int bios_linker_add_checksum(struct bios_linker_entry *entry) -{ - struct fw_file *file; - uint8_t *data, cksum = 0; - uint8_t *cksum_start; - - file = qemu_fwcfg_find_file(entry->cksum.file); - if (!file || !file->addr) - return -ENOENT; - - data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset)); - cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start)); - cksum = table_compute_checksum(cksum_start, - le32_to_cpu(entry->cksum.length)); - *data = cksum; - - return 0; -} - -unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) -{ - entries[0].addr = 0; - entries[0].size = ISA_START_ADDRESS; - entries[0].type = E820_RAM; - - entries[1].addr = ISA_START_ADDRESS; - entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS; - entries[1].type = E820_RESERVED; - - /* - * since we use memalign(malloc) to allocate high memory for - * storing ACPI tables, we need to reserve them in e820 tables, - * otherwise kernel will reclaim them and data will be corrupted - */ - entries[2].addr = ISA_END_ADDRESS; - entries[2].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS; - entries[2].type = E820_RAM; - - /* for simplicity, reserve entire malloc space */ - entries[3].addr = gd->relocaddr - TOTAL_MALLOC_LEN; - entries[3].size = TOTAL_MALLOC_LEN; - entries[3].type = E820_RESERVED; - - entries[4].addr = gd->relocaddr; - entries[4].size = gd->ram_size - gd->relocaddr; - entries[4].type = E820_RESERVED; - - entries[5].addr = CONFIG_PCIE_ECAM_BASE; - entries[5].size = CONFIG_PCIE_ECAM_SIZE; - entries[5].type = E820_RESERVED; - - return 6; -} - -/* This function loads and patches ACPI tables provided by QEMU */ -u32 write_acpi_tables(u32 addr) -{ - int i, ret = 0; - struct fw_file *file; - struct bios_linker_entry *table_loader; - struct bios_linker_entry *entry; - uint32_t size; - struct list_head *list; - - /* make sure fw_list is loaded */ - ret = qemu_fwcfg_read_firmware_list(); - if (ret) { - printf("error: can't read firmware file list\n"); - return addr; - } - - file = qemu_fwcfg_find_file("etc/table-loader"); - if (!file) { - printf("error: can't find etc/table-loader\n"); - return addr; - } - - size = be32_to_cpu(file->cfg.size); - if ((size % sizeof(*entry)) != 0) { - printf("error: table-loader maybe corrupted\n"); - return addr; - } - - table_loader = malloc(size); - if (!table_loader) { - printf("error: no memory for table-loader\n"); - return addr; - } - - qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select), - size, table_loader); - - for (i = 0; i < (size / sizeof(*entry)); i++) { - entry = table_loader + i; - switch (le32_to_cpu(entry->command)) { - case BIOS_LINKER_LOADER_COMMAND_ALLOCATE: - ret = bios_linker_allocate(entry, &addr); - if (ret) - goto out; - break; - case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER: - ret = bios_linker_add_pointer(entry); - if (ret) - goto out; - break; - case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM: - ret = bios_linker_add_checksum(entry); - if (ret) - goto out; - break; - default: - break; - } - } - -out: - if (ret) { - list_for_each(list, &fw_list) { - file = list_entry(list, struct fw_file, list); - if (file->addr) - free((void *)file->addr); - } - } - - free(table_loader); - return addr; -} -#endif - -static int qemu_fwcfg_list_firmware(void) -{ - int ret; - struct list_head *entry; - struct fw_file *file; - - /* make sure fw_list is loaded */ - ret = qemu_fwcfg_read_firmware_list(); - if (ret) - return ret; - - list_for_each(entry, &fw_list) { - file = list_entry(entry, struct fw_file, list); - printf("%-56s\n", file->cfg.name); - } - - return 0; -} - -void qemu_fwcfg_init(void) -{ - fwcfg_present = qemu_fwcfg_present(); - if (fwcfg_present) - fwcfg_dma_present = qemu_fwcfg_dma_present(); -} - -static int qemu_fwcfg_do_list(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - if (qemu_fwcfg_list_firmware() < 0) - return CMD_RET_FAILURE; - - return 0; -} - -static int qemu_fwcfg_do_cpus(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - int ret = qemu_fwcfg_online_cpus(); - if (ret < 0) { - printf("QEMU fw_cfg interface not found\n"); - return CMD_RET_FAILURE; - } - - printf("%d cpu(s) online\n", qemu_fwcfg_online_cpus()); - - return 0; -} - -static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - char *env; - void *load_addr; - void *initrd_addr; - - env = getenv("loadaddr"); - load_addr = env ? - (void *)simple_strtoul(env, NULL, 16) : - (void *)CONFIG_LOADADDR; - - env = getenv("ramdiskaddr"); - initrd_addr = env ? - (void *)simple_strtoul(env, NULL, 16) : - (void *)CONFIG_RAMDISK_ADDR; - - if (argc == 2) { - load_addr = (void *)simple_strtoul(argv[0], NULL, 16); - initrd_addr = (void *)simple_strtoul(argv[1], NULL, 16); - } else if (argc == 1) { - load_addr = (void *)simple_strtoul(argv[0], NULL, 16); - } - - return qemu_fwcfg_setup_kernel(load_addr, initrd_addr); -} - -static cmd_tbl_t fwcfg_commands[] = { - U_BOOT_CMD_MKENT(list, 0, 1, qemu_fwcfg_do_list, "", ""), - U_BOOT_CMD_MKENT(cpus, 0, 1, qemu_fwcfg_do_cpus, "", ""), - U_BOOT_CMD_MKENT(load, 2, 1, qemu_fwcfg_do_load, "", ""), -}; - -static int do_qemu_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int ret; - cmd_tbl_t *fwcfg_cmd; - - if (!fwcfg_present) { - printf("QEMU fw_cfg interface not found\n"); - return CMD_RET_USAGE; - } - - fwcfg_cmd = find_cmd_tbl(argv[1], fwcfg_commands, - ARRAY_SIZE(fwcfg_commands)); - argc -= 2; - argv += 2; - if (!fwcfg_cmd || argc > fwcfg_cmd->maxargs) - return CMD_RET_USAGE; - - ret = fwcfg_cmd->cmd(fwcfg_cmd, flag, argc, argv); - - return cmd_process_error(fwcfg_cmd, ret); -} - -U_BOOT_CMD( - qfw, 4, 1, do_qemu_fw, - "QEMU firmware interface", - "<command>\n" - " - list : print firmware(s) currently loaded\n" - " - cpus : print online cpu number\n" - " - load <kernel addr> <initrd addr> : load kernel and initrd (if any), and setup for zboot\n" -) diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c index 7ad0ee4..b41e4ec 100644 --- a/arch/x86/cpu/qemu/qemu.c +++ b/arch/x86/cpu/qemu/qemu.c @@ -6,12 +6,12 @@
#include <common.h> #include <pci.h> +#include <qemu_fw_cfg.h> #include <asm/irq.h> #include <asm/post.h> #include <asm/processor.h> #include <asm/arch/device.h> #include <asm/arch/qemu.h> -#include <asm/fw_cfg.h>
static bool i440fx;
diff --git a/arch/x86/include/asm/fw_cfg.h b/arch/x86/include/asm/fw_cfg.h deleted file mode 100644 index e9450c6..0000000 --- a/arch/x86/include/asm/fw_cfg.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __FW_CFG__ -#define __FW_CFG__ - -#define FW_CONTROL_PORT 0x510 -#define FW_DATA_PORT 0x511 -#define FW_DMA_PORT_LOW 0x514 -#define FW_DMA_PORT_HIGH 0x518 - -#include <linux/list.h> - -enum qemu_fwcfg_items { - FW_CFG_SIGNATURE = 0x00, - FW_CFG_ID = 0x01, - FW_CFG_UUID = 0x02, - FW_CFG_RAM_SIZE = 0x03, - FW_CFG_NOGRAPHIC = 0x04, - FW_CFG_NB_CPUS = 0x05, - FW_CFG_MACHINE_ID = 0x06, - FW_CFG_KERNEL_ADDR = 0x07, - FW_CFG_KERNEL_SIZE = 0x08, - FW_CFG_KERNEL_CMDLINE = 0x09, - FW_CFG_INITRD_ADDR = 0x0a, - FW_CFG_INITRD_SIZE = 0x0b, - FW_CFG_BOOT_DEVICE = 0x0c, - FW_CFG_NUMA = 0x0d, - FW_CFG_BOOT_MENU = 0x0e, - FW_CFG_MAX_CPUS = 0x0f, - FW_CFG_KERNEL_ENTRY = 0x10, - FW_CFG_KERNEL_DATA = 0x11, - FW_CFG_INITRD_DATA = 0x12, - FW_CFG_CMDLINE_ADDR = 0x13, - FW_CFG_CMDLINE_SIZE = 0x14, - FW_CFG_CMDLINE_DATA = 0x15, - FW_CFG_SETUP_ADDR = 0x16, - FW_CFG_SETUP_SIZE = 0x17, - FW_CFG_SETUP_DATA = 0x18, - FW_CFG_FILE_DIR = 0x19, - FW_CFG_FILE_FIRST = 0x20, - FW_CFG_WRITE_CHANNEL = 0x4000, - FW_CFG_ARCH_LOCAL = 0x8000, - FW_CFG_INVALID = 0xffff, -}; - -enum { - BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1, - BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2, - BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3, -}; - -enum { - BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1, - BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2, -}; - -#define FW_CFG_FILE_SLOTS 0x10 -#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS) -#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL) - -#define FW_CFG_MAX_FILE_PATH 56 -#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH - -#define QEMU_FW_CFG_SIGNATURE (('Q' << 24) | ('E' << 16) | ('M' << 8) | 'U') - -#define FW_CFG_DMA_ERROR (1 << 0) -#define FW_CFG_DMA_READ (1 << 1) -#define FW_CFG_DMA_SKIP (1 << 2) -#define FW_CFG_DMA_SELECT (1 << 3) - -#define FW_CFG_DMA_ENABLED (1 << 1) - -struct fw_cfg_file { - __be32 size; - __be16 select; - __be16 reserved; - char name[FW_CFG_MAX_FILE_PATH]; -}; - -struct fw_file { - struct fw_cfg_file cfg; /* firmware file information */ - unsigned long addr; /* firmware file in-memory address */ - struct list_head list; /* list node to link to fw_list */ -}; - -struct fw_cfg_dma_access { - __be32 control; - __be32 length; - __be64 address; -}; - -struct bios_linker_entry { - __le32 command; - union { - /* - * COMMAND_ALLOCATE - allocate a table from @alloc.file - * subject to @alloc.align alignment (must be power of 2) - * and @alloc.zone (can be HIGH or FSEG) requirements. - * - * Must appear exactly once for each file, and before - * this file is referenced by any other command. - */ - struct { - char file[BIOS_LINKER_LOADER_FILESZ]; - __le32 align; - uint8_t zone; - } alloc; - - /* - * COMMAND_ADD_POINTER - patch the table (originating from - * @dest_file) at @pointer.offset, by adding a pointer to the - * table originating from @src_file. 1,2,4 or 8 byte unsigned - * addition is used depending on @pointer.size. - */ - struct { - char dest_file[BIOS_LINKER_LOADER_FILESZ]; - char src_file[BIOS_LINKER_LOADER_FILESZ]; - __le32 offset; - uint8_t size; - } pointer; - - /* - * COMMAND_ADD_CHECKSUM - calculate checksum of the range - * specified by @cksum_start and @cksum_length fields, - * and then add the value at @cksum.offset. - * Checksum simply sums -X for each byte X in the range - * using 8-bit math. - */ - struct { - char file[BIOS_LINKER_LOADER_FILESZ]; - __le32 offset; - __le32 start; - __le32 length; - } cksum; - - /* padding */ - char pad[124]; - }; -} __packed; - -/** - * Initialize QEMU fw_cfg interface - */ -void qemu_fwcfg_init(void); - -/** - * Get system cpu number - * - * @return: cpu number in system - */ -int qemu_fwcfg_online_cpus(void); - -#endif diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 790f6fb..bb4139a 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -333,7 +333,7 @@ static void acpi_create_ssdt_generator(acpi_header_t *ssdt,
/* * QEMU's version of write_acpi_tables is defined in - * arch/x86/cpu/qemu/fw_cfg.c + * arch/x86/cpu/qemu/acpi_table.c */ u32 write_acpi_tables(u32 start) { diff --git a/cmd/Kconfig b/cmd/Kconfig index 9336752..c0fffe3 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -593,6 +593,13 @@ config CMD_SOUND sound init - set up sound system sound play - play a sound
+config CMD_QEMU_FW_CFG + bool "qfw" + depends on X86 + help + This provides access to the QEMU firmware interface. The main + feature is to allow easy loading of files passed to qemu-system + via -kernel / -initrd endmenu
config CMD_BOOTSTAGE diff --git a/cmd/Makefile b/cmd/Makefile index f95759e..f99e67d 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -105,6 +105,7 @@ endif obj-y += pcmcia.o obj-$(CONFIG_CMD_PORTIO) += portio.o obj-$(CONFIG_CMD_PXE) += pxe.o +obj-$(CONFIG_CMD_QEMU_FW_CFG) += qemu_fw_cfg.o obj-$(CONFIG_CMD_READ) += read.o obj-$(CONFIG_CMD_REGINFO) += reginfo.o obj-$(CONFIG_CMD_REISER) += reiser.o diff --git a/cmd/qemu_fw_cfg.c b/cmd/qemu_fw_cfg.c new file mode 100644 index 0000000..48ae476 --- /dev/null +++ b/cmd/qemu_fw_cfg.c @@ -0,0 +1,343 @@ +/* + * (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <errno.h> +#include <malloc.h> +#include <qemu_fw_cfg.h> +#include <asm/io.h> +#include <linux/list.h> + +static bool fwcfg_present; +static bool fwcfg_dma_present; + +static LIST_HEAD(fw_list); + +/* 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; +} + +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_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, &initrd_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); + data_addr += le32_to_cpu(initrd_size); + } + + qemu_fwcfg_read_entry(FW_CFG_CMDLINE_SIZE, 4, &cmdline_size); + if (cmdline_size) { + qemu_fwcfg_read_entry(FW_CFG_CMDLINE_DATA, + le32_to_cpu(cmdline_size), data_addr); + /* + * if kernel cmdline only contains '\0', (e.g. no -append + * when invoking qemu), do not update bootargs + */ + if (*data_addr != '\0') { + if (setenv("bootargs", data_addr) < 0) + printf("warning: unable to change bootargs\n"); + } + } + + printf("loading kernel to address %p size %x", load_addr, + le32_to_cpu(kernel_size)); + if (initrd_size) + printf(" initrd %p size %x\n", + initrd_addr, + le32_to_cpu(initrd_size)); + else + printf("\n"); + + return 0; +} + +int qemu_fwcfg_read_firmware_list(void) +{ + int i; + uint32_t count; + struct fw_file *file; + struct list_head *entry; + + /* don't read it twice */ + if (!list_empty(&fw_list)) + return 0; + + qemu_fwcfg_read_entry(FW_CFG_FILE_DIR, 4, &count); + if (!count) + return 0; + + count = be32_to_cpu(count); + for (i = 0; i < count; i++) { + file = malloc(sizeof(*file)); + if (!file) { + printf("error: allocating resource\n"); + goto err; + } + qemu_fwcfg_read_entry(FW_CFG_INVALID, + sizeof(struct fw_cfg_file), &file->cfg); + file->addr = 0; + list_add_tail(&file->list, &fw_list); + } + + return 0; + +err: + list_for_each(entry, &fw_list) { + file = list_entry(entry, struct fw_file, list); + free(file); + } + + return -ENOMEM; +} + +struct fw_file *qemu_fwcfg_find_file(const char *name) +{ + struct list_head *entry; + struct fw_file *file; + + list_for_each(entry, &fw_list) { + file = list_entry(entry, struct fw_file, list); + if (!strcmp(file->cfg.name, name)) + return file; + } + + return NULL; +} + +void qemu_fwcfg_free_files(void) +{ + struct fw_file *file; + struct list_head *list; + + list_for_each(list, &fw_list) { + file = list_entry(list, struct fw_file, list); + if (file->addr) + free((void *)file->addr); + } +} + +static int qemu_fwcfg_list_firmware(void) +{ + int ret; + struct list_head *entry; + struct fw_file *file; + + /* make sure fw_list is loaded */ + ret = qemu_fwcfg_read_firmware_list(); + if (ret) + return ret; + + list_for_each(entry, &fw_list) { + file = list_entry(entry, struct fw_file, list); + printf("%-56s\n", file->cfg.name); + } + + return 0; +} + +void qemu_fwcfg_init(void) +{ + fwcfg_present = qemu_fwcfg_present(); + if (fwcfg_present) + fwcfg_dma_present = qemu_fwcfg_dma_present(); +} + +static int qemu_fwcfg_do_list(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + if (qemu_fwcfg_list_firmware() < 0) + return CMD_RET_FAILURE; + + return 0; +} + +static int qemu_fwcfg_do_cpus(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + int ret = qemu_fwcfg_online_cpus(); + if (ret < 0) { + printf("QEMU fw_cfg interface not found\n"); + return CMD_RET_FAILURE; + } + + printf("%d cpu(s) online\n", qemu_fwcfg_online_cpus()); + + return 0; +} + +static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + char *env; + void *load_addr; + void *initrd_addr; + + env = getenv("loadaddr"); + load_addr = env ? + (void *)simple_strtoul(env, NULL, 16) : + (void *)CONFIG_LOADADDR; + + env = getenv("ramdiskaddr"); + initrd_addr = env ? + (void *)simple_strtoul(env, NULL, 16) : + (void *)CONFIG_RAMDISK_ADDR; + + if (argc == 2) { + load_addr = (void *)simple_strtoul(argv[0], NULL, 16); + initrd_addr = (void *)simple_strtoul(argv[1], NULL, 16); + } else if (argc == 1) { + load_addr = (void *)simple_strtoul(argv[0], NULL, 16); + } + + return qemu_fwcfg_setup_kernel(load_addr, initrd_addr); +} + +static cmd_tbl_t fwcfg_commands[] = { + U_BOOT_CMD_MKENT(list, 0, 1, qemu_fwcfg_do_list, "", ""), + U_BOOT_CMD_MKENT(cpus, 0, 1, qemu_fwcfg_do_cpus, "", ""), + U_BOOT_CMD_MKENT(load, 2, 1, qemu_fwcfg_do_load, "", ""), +}; + +static int do_qemu_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret; + cmd_tbl_t *fwcfg_cmd; + + if (!fwcfg_present) { + printf("QEMU fw_cfg interface not found\n"); + return CMD_RET_USAGE; + } + + fwcfg_cmd = find_cmd_tbl(argv[1], fwcfg_commands, + ARRAY_SIZE(fwcfg_commands)); + argc -= 2; + argv += 2; + if (!fwcfg_cmd || argc > fwcfg_cmd->maxargs) + return CMD_RET_USAGE; + + ret = fwcfg_cmd->cmd(fwcfg_cmd, flag, argc, argv); + + return cmd_process_error(fwcfg_cmd, ret); +} + +U_BOOT_CMD( + qfw, 4, 1, do_qemu_fw, + "QEMU firmware interface", + "<command>\n" + " - list : print firmware(s) currently loaded\n" + " - cpus : print online cpu number\n" + " - load <kernel addr> <initrd addr> : load kernel and initrd (if any), and setup for zboot\n" +) diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 53b1ff6..a813e5b 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -20,6 +20,7 @@ CONFIG_CMD_DHCP=y # CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y +CONFIG_CMD_QEMU_FW_CFG=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_EXT2=y CONFIG_CMD_EXT4=y diff --git a/include/qemu_fw_cfg.h b/include/qemu_fw_cfg.h new file mode 100644 index 0000000..e21f150 --- /dev/null +++ b/include/qemu_fw_cfg.h @@ -0,0 +1,162 @@ +/* + * (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __FW_CFG__ +#define __FW_CFG__ + +#define FW_CONTROL_PORT 0x510 +#define FW_DATA_PORT 0x511 +#define FW_DMA_PORT_LOW 0x514 +#define FW_DMA_PORT_HIGH 0x518 + +#include <linux/list.h> + +enum qemu_fwcfg_items { + FW_CFG_SIGNATURE = 0x00, + FW_CFG_ID = 0x01, + FW_CFG_UUID = 0x02, + FW_CFG_RAM_SIZE = 0x03, + FW_CFG_NOGRAPHIC = 0x04, + FW_CFG_NB_CPUS = 0x05, + FW_CFG_MACHINE_ID = 0x06, + FW_CFG_KERNEL_ADDR = 0x07, + FW_CFG_KERNEL_SIZE = 0x08, + FW_CFG_KERNEL_CMDLINE = 0x09, + FW_CFG_INITRD_ADDR = 0x0a, + FW_CFG_INITRD_SIZE = 0x0b, + FW_CFG_BOOT_DEVICE = 0x0c, + FW_CFG_NUMA = 0x0d, + FW_CFG_BOOT_MENU = 0x0e, + FW_CFG_MAX_CPUS = 0x0f, + FW_CFG_KERNEL_ENTRY = 0x10, + FW_CFG_KERNEL_DATA = 0x11, + FW_CFG_INITRD_DATA = 0x12, + FW_CFG_CMDLINE_ADDR = 0x13, + FW_CFG_CMDLINE_SIZE = 0x14, + FW_CFG_CMDLINE_DATA = 0x15, + FW_CFG_SETUP_ADDR = 0x16, + FW_CFG_SETUP_SIZE = 0x17, + FW_CFG_SETUP_DATA = 0x18, + FW_CFG_FILE_DIR = 0x19, + FW_CFG_FILE_FIRST = 0x20, + FW_CFG_WRITE_CHANNEL = 0x4000, + FW_CFG_ARCH_LOCAL = 0x8000, + FW_CFG_INVALID = 0xffff, +}; + +enum { + BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1, + BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2, + BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3, +}; + +enum { + BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1, + BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2, +}; + +#define FW_CFG_FILE_SLOTS 0x10 +#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS) +#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL) + +#define FW_CFG_MAX_FILE_PATH 56 +#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH + +#define QEMU_FW_CFG_SIGNATURE (('Q' << 24) | ('E' << 16) | ('M' << 8) | 'U') + +#define FW_CFG_DMA_ERROR (1 << 0) +#define FW_CFG_DMA_READ (1 << 1) +#define FW_CFG_DMA_SKIP (1 << 2) +#define FW_CFG_DMA_SELECT (1 << 3) + +#define FW_CFG_DMA_ENABLED (1 << 1) + +struct fw_cfg_file { + __be32 size; + __be16 select; + __be16 reserved; + char name[FW_CFG_MAX_FILE_PATH]; +}; + +struct fw_file { + struct fw_cfg_file cfg; /* firmware file information */ + unsigned long addr; /* firmware file in-memory address */ + struct list_head list; /* list node to link to fw_list */ +}; + +struct fw_cfg_dma_access { + __be32 control; + __be32 length; + __be64 address; +}; + +struct bios_linker_entry { + __le32 command; + union { + /* + * COMMAND_ALLOCATE - allocate a table from @alloc.file + * subject to @alloc.align alignment (must be power of 2) + * and @alloc.zone (can be HIGH or FSEG) requirements. + * + * Must appear exactly once for each file, and before + * this file is referenced by any other command. + */ + struct { + char file[BIOS_LINKER_LOADER_FILESZ]; + __le32 align; + uint8_t zone; + } alloc; + + /* + * COMMAND_ADD_POINTER - patch the table (originating from + * @dest_file) at @pointer.offset, by adding a pointer to the + * table originating from @src_file. 1,2,4 or 8 byte unsigned + * addition is used depending on @pointer.size. + */ + struct { + char dest_file[BIOS_LINKER_LOADER_FILESZ]; + char src_file[BIOS_LINKER_LOADER_FILESZ]; + __le32 offset; + uint8_t size; + } pointer; + + /* + * COMMAND_ADD_CHECKSUM - calculate checksum of the range + * specified by @cksum_start and @cksum_length fields, + * and then add the value at @cksum.offset. + * Checksum simply sums -X for each byte X in the range + * using 8-bit math. + */ + struct { + char file[BIOS_LINKER_LOADER_FILESZ]; + __le32 offset; + __le32 start; + __le32 length; + } cksum; + + /* padding */ + char pad[124]; + }; +} __packed; + +/** + * Initialize QEMU fw_cfg interface + */ +void qemu_fwcfg_init(void); + +void qemu_fwcfg_read_entry(uint16_t entry, uint32_t length, void *address); +int qemu_fwcfg_read_firmware_list(void); +struct fw_file *qemu_fwcfg_find_file(const char *name); +void qemu_fwcfg_free_files(void); + +/** + * Get system cpu number + * + * @return: cpu number in system + */ +int qemu_fwcfg_online_cpus(void); + +#endif

2016-05-06 22:40 GMT+08:00 Tom Rini trini@konsulko.com:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
I am afraid this still doesn't build. At least you need to make the ACPI stuff depend on the new config option CONFIG_CMD_QEMU_FW_CFG, as well as some tweaks in qemu.c and mp_init.c because they call functions from the origin fw_cfg.c and they used to be guarded by CONFIG_QEMU, something like the following diff:
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4ef27dc..efede32 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -444,7 +444,7 @@ config GENERATE_ACPI_TABLE
config QEMU_ACPI_TABLE bool "Load ACPI table from QEMU fw_cfg interface" - depends on GENERATE_ACPI_TABLE && QEMU + depends on GENERATE_ACPI_TABLE && CMD_QEMU_FW_CFG default y help By default, U-Boot generates its own ACPI tables. This option, if diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 13bec7a..7b870b7 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -420,7 +420,7 @@ static int init_bsp(struct udevice **devp) return 0; }
-#ifdef CONFIG_QEMU +#ifdef CONFIG_CMD_QEMU_FW_CFG static int qemu_cpu_fixup(void) { int ret; @@ -496,7 +496,7 @@ int mp_init(struct mp_params *p) if (ret) return ret;
-#ifdef CONFIG_QEMU +#ifdef CONFIG_CMD_QEMU_FW_CFG ret = qemu_cpu_fixup(); if (ret) return ret; diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile index 97b965c..d0e146e 100644 --- a/arch/x86/cpu/qemu/Makefile +++ b/arch/x86/cpu/qemu/Makefile @@ -7,5 +7,11 @@ ifndef CONFIG_EFI_STUB obj-y += car.o dram.o endif -obj-y += cpu.o qemu.o + +obj-y += qemu.o + +ifdef CONFIG_CMD_QEMU_FW_CFG +obj-y += cpu.o obj-$(CONFIG_QEMU_ACPI_TABLE) += acpi_table.o +endif + diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c index b41e4ec..2730a5f 100644 --- a/arch/x86/cpu/qemu/qemu.c +++ b/arch/x86/cpu/qemu/qemu.c @@ -88,7 +88,9 @@ static void qemu_chipset_init(void) enable_pm_ich9(); }
+#ifdef CONFIG_CMD_QEMU_FW_CFG qemu_fwcfg_init(); +#endif }
int arch_cpu_init(void)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 2604a68..13bec7a 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -11,6 +11,7 @@ #include <dm.h> #include <errno.h> #include <malloc.h> +#include <qemu_fw_cfg.h> #include <asm/atomic.h> #include <asm/cpu.h> #include <asm/interrupt.h> @@ -21,7 +22,6 @@ #include <asm/mtrr.h> #include <asm/processor.h> #include <asm/sipi.h> -#include <asm/fw_cfg.h> #include <dm/device-internal.h> #include <dm/uclass-internal.h> #include <dm/lists.h> diff --git a/arch/x86/cpu/qemu/Makefile b/arch/x86/cpu/qemu/Makefile index 6eeddf1..97b965c 100644 --- a/arch/x86/cpu/qemu/Makefile +++ b/arch/x86/cpu/qemu/Makefile @@ -7,4 +7,5 @@ ifndef CONFIG_EFI_STUB obj-y += car.o dram.o endif -obj-y += cpu.o fw_cfg.o qemu.o +obj-y += cpu.o qemu.o +obj-$(CONFIG_QEMU_ACPI_TABLE) += acpi_table.o diff --git a/arch/x86/cpu/qemu/acpi_table.c b/arch/x86/cpu/qemu/acpi_table.c new file mode 100644 index 0000000..49381ac --- /dev/null +++ b/arch/x86/cpu/qemu/acpi_table.c @@ -0,0 +1,243 @@ +/*
- (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <command.h> +#include <errno.h> +#include <malloc.h> +#include <qemu_fw_cfg.h> +#include <asm/io.h> +#include <asm/tables.h> +#include <asm/e820.h> +#include <linux/list.h> +#include <memalign.h>
+/*
- This function allocates memory for ACPI tables
- @entry : BIOS linker command entry which tells where to allocate memory
(either high memory or low memory)
- @addr : The address that should be used for low memory allcation. If the
memory allocation request is 'ZONE_HIGH' then this parameter will
be ignored.
- @return: 0 on success, or negative value on failure
- */
+static int bios_linker_allocate(struct bios_linker_entry *entry, u32 *addr) +{
uint32_t size, align;
struct fw_file *file;
unsigned long aligned_addr;
align = le32_to_cpu(entry->alloc.align);
/* align must be power of 2 */
if (align & (align - 1)) {
printf("error: wrong alignment %u\n", align);
return -EINVAL;
}
file = qemu_fwcfg_find_file(entry->alloc.file);
if (!file) {
printf("error: can't find file %s\n", entry->alloc.file);
return -ENOENT;
}
size = be32_to_cpu(file->cfg.size);
/*
* ZONE_HIGH means we need to allocate from high memory, since
* malloc space is already at the end of RAM, so we directly use it.
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
* in which is low memory
*/
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
aligned_addr = (unsigned long)memalign(align, size);
if (!aligned_addr) {
printf("error: allocating resource\n");
return -ENOMEM;
}
} else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
aligned_addr = ALIGN(*addr, align);
} else {
printf("error: invalid allocation zone\n");
return -EINVAL;
}
debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
size, (void *)aligned_addr);
file->addr = aligned_addr;
/* adjust address for low memory allocation */
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
*addr = (aligned_addr + size);
return 0;
+}
+/*
- This function patches ACPI tables previously loaded
- by bios_linker_allocate()
- @entry : BIOS linker command entry which tells how to patch
ACPI tables
- @return: 0 on success, or negative value on failure
- */
+static int bios_linker_add_pointer(struct bios_linker_entry *entry) +{
struct fw_file *dest, *src;
uint32_t offset = le32_to_cpu(entry->pointer.offset);
uint64_t pointer = 0;
dest = qemu_fwcfg_find_file(entry->pointer.dest_file);
if (!dest || !dest->addr)
return -ENOENT;
src = qemu_fwcfg_find_file(entry->pointer.src_file);
if (!src || !src->addr)
return -ENOENT;
debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n",
dest->addr, src->addr, offset, entry->pointer.size, pointer);
memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size);
pointer = le64_to_cpu(pointer);
pointer += (unsigned long)src->addr;
pointer = cpu_to_le64(pointer);
memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size);
return 0;
+}
+/*
- This function updates checksum fields of ACPI tables previously loaded
- by bios_linker_allocate()
- @entry : BIOS linker command entry which tells where to update ACPI table
checksums
- @return: 0 on success, or negative value on failure
- */
+static int bios_linker_add_checksum(struct bios_linker_entry *entry) +{
struct fw_file *file;
uint8_t *data, cksum = 0;
uint8_t *cksum_start;
file = qemu_fwcfg_find_file(entry->cksum.file);
if (!file || !file->addr)
return -ENOENT;
data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset));
cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start));
cksum = table_compute_checksum(cksum_start,
le32_to_cpu(entry->cksum.length));
*data = cksum;
return 0;
+}
+unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) +{
entries[0].addr = 0;
entries[0].size = ISA_START_ADDRESS;
entries[0].type = E820_RAM;
entries[1].addr = ISA_START_ADDRESS;
entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
entries[1].type = E820_RESERVED;
/*
* since we use memalign(malloc) to allocate high memory for
* storing ACPI tables, we need to reserve them in e820 tables,
* otherwise kernel will reclaim them and data will be corrupted
*/
entries[2].addr = ISA_END_ADDRESS;
entries[2].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS;
entries[2].type = E820_RAM;
/* for simplicity, reserve entire malloc space */
entries[3].addr = gd->relocaddr - TOTAL_MALLOC_LEN;
entries[3].size = TOTAL_MALLOC_LEN;
entries[3].type = E820_RESERVED;
entries[4].addr = gd->relocaddr;
entries[4].size = gd->ram_size - gd->relocaddr;
entries[4].type = E820_RESERVED;
entries[5].addr = CONFIG_PCIE_ECAM_BASE;
entries[5].size = CONFIG_PCIE_ECAM_SIZE;
entries[5].type = E820_RESERVED;
return 6;
+}
+/* This function loads and patches ACPI tables provided by QEMU */ +u32 write_acpi_tables(u32 addr) +{
int i, ret = 0;
struct fw_file *file;
struct bios_linker_entry *table_loader;
struct bios_linker_entry *entry;
uint32_t size;
/* make sure fw_list is loaded */
ret = qemu_fwcfg_read_firmware_list();
if (ret) {
printf("error: can't read firmware file list\n");
return addr;
}
file = qemu_fwcfg_find_file("etc/table-loader");
if (!file) {
printf("error: can't find etc/table-loader\n");
return addr;
}
size = be32_to_cpu(file->cfg.size);
if ((size % sizeof(*entry)) != 0) {
printf("error: table-loader maybe corrupted\n");
return addr;
}
table_loader = malloc(size);
if (!table_loader) {
printf("error: no memory for table-loader\n");
return addr;
}
qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
size, table_loader);
for (i = 0; i < (size / sizeof(*entry)); i++) {
entry = table_loader + i;
switch (le32_to_cpu(entry->command)) {
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
ret = bios_linker_allocate(entry, &addr);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
ret = bios_linker_add_pointer(entry);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
ret = bios_linker_add_checksum(entry);
if (ret)
goto out;
break;
default:
break;
}
}
+out:
if (ret)
qemu_fwcfg_free_files();
free(table_loader);
return addr;
+} diff --git a/arch/x86/cpu/qemu/cpu.c b/arch/x86/cpu/qemu/cpu.c index a1b70c6..4d2989a 100644 --- a/arch/x86/cpu/qemu/cpu.c +++ b/arch/x86/cpu/qemu/cpu.c @@ -8,8 +8,8 @@ #include <cpu.h> #include <dm.h> #include <errno.h> +#include <qemu_fw_cfg.h> #include <asm/cpu.h> -#include <asm/fw_cfg.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/x86/cpu/qemu/fw_cfg.c b/arch/x86/cpu/qemu/fw_cfg.c deleted file mode 100644 index 2e2794e..0000000 --- a/arch/x86/cpu/qemu/fw_cfg.c +++ /dev/null @@ -1,570 +0,0 @@ -/*
- (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h> -#include <command.h> -#include <errno.h> -#include <malloc.h> -#include <asm/io.h> -#include <asm/fw_cfg.h> -#include <asm/tables.h> -#include <asm/e820.h> -#include <linux/list.h> -#include <memalign.h>
-static bool fwcfg_present; -static bool fwcfg_dma_present;
-static LIST_HEAD(fw_list);
-/* 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_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, &initrd_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);
data_addr += le32_to_cpu(initrd_size);
}
qemu_fwcfg_read_entry(FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);
if (cmdline_size) {
qemu_fwcfg_read_entry(FW_CFG_CMDLINE_DATA,
le32_to_cpu(cmdline_size), data_addr);
/*
* if kernel cmdline only contains '\0', (e.g. no -append
* when invoking qemu), do not update bootargs
*/
if (*data_addr != '\0') {
if (setenv("bootargs", data_addr) < 0)
printf("warning: unable to change bootargs\n");
}
}
printf("loading kernel to address %p size %x", load_addr,
le32_to_cpu(kernel_size));
if (initrd_size)
printf(" initrd %p size %x\n",
initrd_addr,
le32_to_cpu(initrd_size));
else
printf("\n");
return 0;
-}
-static int qemu_fwcfg_read_firmware_list(void) -{
int i;
uint32_t count;
struct fw_file *file;
struct list_head *entry;
/* don't read it twice */
if (!list_empty(&fw_list))
return 0;
qemu_fwcfg_read_entry(FW_CFG_FILE_DIR, 4, &count);
if (!count)
return 0;
count = be32_to_cpu(count);
for (i = 0; i < count; i++) {
file = malloc(sizeof(*file));
if (!file) {
printf("error: allocating resource\n");
goto err;
}
qemu_fwcfg_read_entry(FW_CFG_INVALID,
sizeof(struct fw_cfg_file), &file->cfg);
file->addr = 0;
list_add_tail(&file->list, &fw_list);
}
return 0;
-err:
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
free(file);
}
return -ENOMEM;
-}
-#ifdef CONFIG_QEMU_ACPI_TABLE -static struct fw_file *qemu_fwcfg_find_file(const char *name) -{
struct list_head *entry;
struct fw_file *file;
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
if (!strcmp(file->cfg.name, name))
return file;
}
return NULL;
-}
-/*
- This function allocates memory for ACPI tables
- @entry : BIOS linker command entry which tells where to allocate memory
(either high memory or low memory)
- @addr : The address that should be used for low memory allcation. If the
memory allocation request is 'ZONE_HIGH' then this parameter will
be ignored.
- @return: 0 on success, or negative value on failure
- */
-static int bios_linker_allocate(struct bios_linker_entry *entry, u32 *addr) -{
uint32_t size, align;
struct fw_file *file;
unsigned long aligned_addr;
align = le32_to_cpu(entry->alloc.align);
/* align must be power of 2 */
if (align & (align - 1)) {
printf("error: wrong alignment %u\n", align);
return -EINVAL;
}
file = qemu_fwcfg_find_file(entry->alloc.file);
if (!file) {
printf("error: can't find file %s\n", entry->alloc.file);
return -ENOENT;
}
size = be32_to_cpu(file->cfg.size);
/*
* ZONE_HIGH means we need to allocate from high memory, since
* malloc space is already at the end of RAM, so we directly use it.
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
* in which is low memory
*/
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
aligned_addr = (unsigned long)memalign(align, size);
if (!aligned_addr) {
printf("error: allocating resource\n");
return -ENOMEM;
}
} else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
aligned_addr = ALIGN(*addr, align);
} else {
printf("error: invalid allocation zone\n");
return -EINVAL;
}
debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
size, (void *)aligned_addr);
file->addr = aligned_addr;
/* adjust address for low memory allocation */
if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
*addr = (aligned_addr + size);
return 0;
-}
-/*
- This function patches ACPI tables previously loaded
- by bios_linker_allocate()
- @entry : BIOS linker command entry which tells how to patch
ACPI tables
- @return: 0 on success, or negative value on failure
- */
-static int bios_linker_add_pointer(struct bios_linker_entry *entry) -{
struct fw_file *dest, *src;
uint32_t offset = le32_to_cpu(entry->pointer.offset);
uint64_t pointer = 0;
dest = qemu_fwcfg_find_file(entry->pointer.dest_file);
if (!dest || !dest->addr)
return -ENOENT;
src = qemu_fwcfg_find_file(entry->pointer.src_file);
if (!src || !src->addr)
return -ENOENT;
debug("bios_linker_add_pointer: dest->addr 0x%lx, src->addr 0x%lx, offset 0x%x size %u, 0x%llx\n",
dest->addr, src->addr, offset, entry->pointer.size, pointer);
memcpy(&pointer, (char *)dest->addr + offset, entry->pointer.size);
pointer = le64_to_cpu(pointer);
pointer += (unsigned long)src->addr;
pointer = cpu_to_le64(pointer);
memcpy((char *)dest->addr + offset, &pointer, entry->pointer.size);
return 0;
-}
-/*
- This function updates checksum fields of ACPI tables previously loaded
- by bios_linker_allocate()
- @entry : BIOS linker command entry which tells where to update ACPI table
checksums
- @return: 0 on success, or negative value on failure
- */
-static int bios_linker_add_checksum(struct bios_linker_entry *entry) -{
struct fw_file *file;
uint8_t *data, cksum = 0;
uint8_t *cksum_start;
file = qemu_fwcfg_find_file(entry->cksum.file);
if (!file || !file->addr)
return -ENOENT;
data = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.offset));
cksum_start = (uint8_t *)(file->addr + le32_to_cpu(entry->cksum.start));
cksum = table_compute_checksum(cksum_start,
le32_to_cpu(entry->cksum.length));
*data = cksum;
return 0;
-}
-unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) -{
entries[0].addr = 0;
entries[0].size = ISA_START_ADDRESS;
entries[0].type = E820_RAM;
entries[1].addr = ISA_START_ADDRESS;
entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
entries[1].type = E820_RESERVED;
/*
* since we use memalign(malloc) to allocate high memory for
* storing ACPI tables, we need to reserve them in e820 tables,
* otherwise kernel will reclaim them and data will be corrupted
*/
entries[2].addr = ISA_END_ADDRESS;
entries[2].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS;
entries[2].type = E820_RAM;
/* for simplicity, reserve entire malloc space */
entries[3].addr = gd->relocaddr - TOTAL_MALLOC_LEN;
entries[3].size = TOTAL_MALLOC_LEN;
entries[3].type = E820_RESERVED;
entries[4].addr = gd->relocaddr;
entries[4].size = gd->ram_size - gd->relocaddr;
entries[4].type = E820_RESERVED;
entries[5].addr = CONFIG_PCIE_ECAM_BASE;
entries[5].size = CONFIG_PCIE_ECAM_SIZE;
entries[5].type = E820_RESERVED;
return 6;
-}
-/* This function loads and patches ACPI tables provided by QEMU */ -u32 write_acpi_tables(u32 addr) -{
int i, ret = 0;
struct fw_file *file;
struct bios_linker_entry *table_loader;
struct bios_linker_entry *entry;
uint32_t size;
struct list_head *list;
/* make sure fw_list is loaded */
ret = qemu_fwcfg_read_firmware_list();
if (ret) {
printf("error: can't read firmware file list\n");
return addr;
}
file = qemu_fwcfg_find_file("etc/table-loader");
if (!file) {
printf("error: can't find etc/table-loader\n");
return addr;
}
size = be32_to_cpu(file->cfg.size);
if ((size % sizeof(*entry)) != 0) {
printf("error: table-loader maybe corrupted\n");
return addr;
}
table_loader = malloc(size);
if (!table_loader) {
printf("error: no memory for table-loader\n");
return addr;
}
qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select),
size, table_loader);
for (i = 0; i < (size / sizeof(*entry)); i++) {
entry = table_loader + i;
switch (le32_to_cpu(entry->command)) {
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
ret = bios_linker_allocate(entry, &addr);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
ret = bios_linker_add_pointer(entry);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
ret = bios_linker_add_checksum(entry);
if (ret)
goto out;
break;
default:
break;
}
}
-out:
if (ret) {
list_for_each(list, &fw_list) {
file = list_entry(list, struct fw_file, list);
if (file->addr)
free((void *)file->addr);
}
}
free(table_loader);
return addr;
-} -#endif
-static int qemu_fwcfg_list_firmware(void) -{
int ret;
struct list_head *entry;
struct fw_file *file;
/* make sure fw_list is loaded */
ret = qemu_fwcfg_read_firmware_list();
if (ret)
return ret;
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
printf("%-56s\n", file->cfg.name);
}
return 0;
-}
-void qemu_fwcfg_init(void) -{
fwcfg_present = qemu_fwcfg_present();
if (fwcfg_present)
fwcfg_dma_present = qemu_fwcfg_dma_present();
-}
-static int qemu_fwcfg_do_list(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
-{
if (qemu_fwcfg_list_firmware() < 0)
return CMD_RET_FAILURE;
return 0;
-}
-static int qemu_fwcfg_do_cpus(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
-{
int ret = qemu_fwcfg_online_cpus();
if (ret < 0) {
printf("QEMU fw_cfg interface not found\n");
return CMD_RET_FAILURE;
}
printf("%d cpu(s) online\n", qemu_fwcfg_online_cpus());
return 0;
-}
-static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
-{
char *env;
void *load_addr;
void *initrd_addr;
env = getenv("loadaddr");
load_addr = env ?
(void *)simple_strtoul(env, NULL, 16) :
(void *)CONFIG_LOADADDR;
env = getenv("ramdiskaddr");
initrd_addr = env ?
(void *)simple_strtoul(env, NULL, 16) :
(void *)CONFIG_RAMDISK_ADDR;
if (argc == 2) {
load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
initrd_addr = (void *)simple_strtoul(argv[1], NULL, 16);
} else if (argc == 1) {
load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
}
return qemu_fwcfg_setup_kernel(load_addr, initrd_addr);
-}
-static cmd_tbl_t fwcfg_commands[] = {
U_BOOT_CMD_MKENT(list, 0, 1, qemu_fwcfg_do_list, "", ""),
U_BOOT_CMD_MKENT(cpus, 0, 1, qemu_fwcfg_do_cpus, "", ""),
U_BOOT_CMD_MKENT(load, 2, 1, qemu_fwcfg_do_load, "", ""),
-};
-static int do_qemu_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{
int ret;
cmd_tbl_t *fwcfg_cmd;
if (!fwcfg_present) {
printf("QEMU fw_cfg interface not found\n");
return CMD_RET_USAGE;
}
fwcfg_cmd = find_cmd_tbl(argv[1], fwcfg_commands,
ARRAY_SIZE(fwcfg_commands));
argc -= 2;
argv += 2;
if (!fwcfg_cmd || argc > fwcfg_cmd->maxargs)
return CMD_RET_USAGE;
ret = fwcfg_cmd->cmd(fwcfg_cmd, flag, argc, argv);
return cmd_process_error(fwcfg_cmd, ret);
-}
-U_BOOT_CMD(
qfw, 4, 1, do_qemu_fw,
"QEMU firmware interface",
"<command>\n"
" - list : print firmware(s) currently loaded\n"
" - cpus : print online cpu number\n"
" - load <kernel addr> <initrd addr> : load kernel and initrd (if any), and setup for zboot\n"
-) diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c index 7ad0ee4..b41e4ec 100644 --- a/arch/x86/cpu/qemu/qemu.c +++ b/arch/x86/cpu/qemu/qemu.c @@ -6,12 +6,12 @@
#include <common.h> #include <pci.h> +#include <qemu_fw_cfg.h> #include <asm/irq.h> #include <asm/post.h> #include <asm/processor.h> #include <asm/arch/device.h> #include <asm/arch/qemu.h> -#include <asm/fw_cfg.h>
static bool i440fx;
diff --git a/arch/x86/include/asm/fw_cfg.h b/arch/x86/include/asm/fw_cfg.h deleted file mode 100644 index e9450c6..0000000 --- a/arch/x86/include/asm/fw_cfg.h +++ /dev/null @@ -1,157 +0,0 @@ -/*
- (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
-#ifndef __FW_CFG__ -#define __FW_CFG__
-#define FW_CONTROL_PORT 0x510 -#define FW_DATA_PORT 0x511 -#define FW_DMA_PORT_LOW 0x514 -#define FW_DMA_PORT_HIGH 0x518
-#include <linux/list.h>
-enum qemu_fwcfg_items {
FW_CFG_SIGNATURE = 0x00,
FW_CFG_ID = 0x01,
FW_CFG_UUID = 0x02,
FW_CFG_RAM_SIZE = 0x03,
FW_CFG_NOGRAPHIC = 0x04,
FW_CFG_NB_CPUS = 0x05,
FW_CFG_MACHINE_ID = 0x06,
FW_CFG_KERNEL_ADDR = 0x07,
FW_CFG_KERNEL_SIZE = 0x08,
FW_CFG_KERNEL_CMDLINE = 0x09,
FW_CFG_INITRD_ADDR = 0x0a,
FW_CFG_INITRD_SIZE = 0x0b,
FW_CFG_BOOT_DEVICE = 0x0c,
FW_CFG_NUMA = 0x0d,
FW_CFG_BOOT_MENU = 0x0e,
FW_CFG_MAX_CPUS = 0x0f,
FW_CFG_KERNEL_ENTRY = 0x10,
FW_CFG_KERNEL_DATA = 0x11,
FW_CFG_INITRD_DATA = 0x12,
FW_CFG_CMDLINE_ADDR = 0x13,
FW_CFG_CMDLINE_SIZE = 0x14,
FW_CFG_CMDLINE_DATA = 0x15,
FW_CFG_SETUP_ADDR = 0x16,
FW_CFG_SETUP_SIZE = 0x17,
FW_CFG_SETUP_DATA = 0x18,
FW_CFG_FILE_DIR = 0x19,
FW_CFG_FILE_FIRST = 0x20,
FW_CFG_WRITE_CHANNEL = 0x4000,
FW_CFG_ARCH_LOCAL = 0x8000,
FW_CFG_INVALID = 0xffff,
-};
-enum {
BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1,
BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2,
BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
-};
-enum {
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1,
BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2,
-};
-#define FW_CFG_FILE_SLOTS 0x10 -#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS) -#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)
-#define FW_CFG_MAX_FILE_PATH 56 -#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH
-#define QEMU_FW_CFG_SIGNATURE (('Q' << 24) | ('E' << 16) | ('M' << 8) | 'U')
-#define FW_CFG_DMA_ERROR (1 << 0) -#define FW_CFG_DMA_READ (1 << 1) -#define FW_CFG_DMA_SKIP (1 << 2) -#define FW_CFG_DMA_SELECT (1 << 3)
-#define FW_CFG_DMA_ENABLED (1 << 1)
-struct fw_cfg_file {
__be32 size;
__be16 select;
__be16 reserved;
char name[FW_CFG_MAX_FILE_PATH];
-};
-struct fw_file {
struct fw_cfg_file cfg; /* firmware file information */
unsigned long addr; /* firmware file in-memory address */
struct list_head list; /* list node to link to fw_list */
-};
-struct fw_cfg_dma_access {
__be32 control;
__be32 length;
__be64 address;
-};
-struct bios_linker_entry {
__le32 command;
union {
/*
* COMMAND_ALLOCATE - allocate a table from @alloc.file
* subject to @alloc.align alignment (must be power of 2)
* and @alloc.zone (can be HIGH or FSEG) requirements.
*
* Must appear exactly once for each file, and before
* this file is referenced by any other command.
*/
struct {
char file[BIOS_LINKER_LOADER_FILESZ];
__le32 align;
uint8_t zone;
} alloc;
/*
* COMMAND_ADD_POINTER - patch the table (originating from
* @dest_file) at @pointer.offset, by adding a pointer to the
* table originating from @src_file. 1,2,4 or 8 byte unsigned
* addition is used depending on @pointer.size.
*/
struct {
char dest_file[BIOS_LINKER_LOADER_FILESZ];
char src_file[BIOS_LINKER_LOADER_FILESZ];
__le32 offset;
uint8_t size;
} pointer;
/*
* COMMAND_ADD_CHECKSUM - calculate checksum of the range
* specified by @cksum_start and @cksum_length fields,
* and then add the value at @cksum.offset.
* Checksum simply sums -X for each byte X in the range
* using 8-bit math.
*/
struct {
char file[BIOS_LINKER_LOADER_FILESZ];
__le32 offset;
__le32 start;
__le32 length;
} cksum;
/* padding */
char pad[124];
};
-} __packed;
-/**
- Initialize QEMU fw_cfg interface
- */
-void qemu_fwcfg_init(void);
-/**
- Get system cpu number
- @return: cpu number in system
- */
-int qemu_fwcfg_online_cpus(void);
-#endif diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 790f6fb..bb4139a 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -333,7 +333,7 @@ static void acpi_create_ssdt_generator(acpi_header_t *ssdt,
/*
- QEMU's version of write_acpi_tables is defined in
- arch/x86/cpu/qemu/fw_cfg.c
*/
- arch/x86/cpu/qemu/acpi_table.c
u32 write_acpi_tables(u32 start) { diff --git a/cmd/Kconfig b/cmd/Kconfig index 9336752..c0fffe3 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -593,6 +593,13 @@ config CMD_SOUND sound init - set up sound system sound play - play a sound
+config CMD_QEMU_FW_CFG
bool "qfw"
depends on X86
help
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
endmenu
This should really be "depends on QEMU". Sorry for my earlier comment.
Thanks, Miao
config CMD_BOOTSTAGE diff --git a/cmd/Makefile b/cmd/Makefile index f95759e..f99e67d 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -105,6 +105,7 @@ endif obj-y += pcmcia.o obj-$(CONFIG_CMD_PORTIO) += portio.o obj-$(CONFIG_CMD_PXE) += pxe.o +obj-$(CONFIG_CMD_QEMU_FW_CFG) += qemu_fw_cfg.o obj-$(CONFIG_CMD_READ) += read.o obj-$(CONFIG_CMD_REGINFO) += reginfo.o obj-$(CONFIG_CMD_REISER) += reiser.o diff --git a/cmd/qemu_fw_cfg.c b/cmd/qemu_fw_cfg.c new file mode 100644 index 0000000..48ae476 --- /dev/null +++ b/cmd/qemu_fw_cfg.c @@ -0,0 +1,343 @@ +/*
- (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <command.h> +#include <errno.h> +#include <malloc.h> +#include <qemu_fw_cfg.h> +#include <asm/io.h> +#include <linux/list.h>
+static bool fwcfg_present; +static bool fwcfg_dma_present;
+static LIST_HEAD(fw_list);
+/* 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;
+}
+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_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, &initrd_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);
data_addr += le32_to_cpu(initrd_size);
}
qemu_fwcfg_read_entry(FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);
if (cmdline_size) {
qemu_fwcfg_read_entry(FW_CFG_CMDLINE_DATA,
le32_to_cpu(cmdline_size), data_addr);
/*
* if kernel cmdline only contains '\0', (e.g. no -append
* when invoking qemu), do not update bootargs
*/
if (*data_addr != '\0') {
if (setenv("bootargs", data_addr) < 0)
printf("warning: unable to change bootargs\n");
}
}
printf("loading kernel to address %p size %x", load_addr,
le32_to_cpu(kernel_size));
if (initrd_size)
printf(" initrd %p size %x\n",
initrd_addr,
le32_to_cpu(initrd_size));
else
printf("\n");
return 0;
+}
+int qemu_fwcfg_read_firmware_list(void) +{
int i;
uint32_t count;
struct fw_file *file;
struct list_head *entry;
/* don't read it twice */
if (!list_empty(&fw_list))
return 0;
qemu_fwcfg_read_entry(FW_CFG_FILE_DIR, 4, &count);
if (!count)
return 0;
count = be32_to_cpu(count);
for (i = 0; i < count; i++) {
file = malloc(sizeof(*file));
if (!file) {
printf("error: allocating resource\n");
goto err;
}
qemu_fwcfg_read_entry(FW_CFG_INVALID,
sizeof(struct fw_cfg_file), &file->cfg);
file->addr = 0;
list_add_tail(&file->list, &fw_list);
}
return 0;
+err:
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
free(file);
}
return -ENOMEM;
+}
+struct fw_file *qemu_fwcfg_find_file(const char *name) +{
struct list_head *entry;
struct fw_file *file;
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
if (!strcmp(file->cfg.name, name))
return file;
}
return NULL;
+}
+void qemu_fwcfg_free_files(void) +{
struct fw_file *file;
struct list_head *list;
list_for_each(list, &fw_list) {
file = list_entry(list, struct fw_file, list);
if (file->addr)
free((void *)file->addr);
}
+}
+static int qemu_fwcfg_list_firmware(void) +{
int ret;
struct list_head *entry;
struct fw_file *file;
/* make sure fw_list is loaded */
ret = qemu_fwcfg_read_firmware_list();
if (ret)
return ret;
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
printf("%-56s\n", file->cfg.name);
}
return 0;
+}
+void qemu_fwcfg_init(void) +{
fwcfg_present = qemu_fwcfg_present();
if (fwcfg_present)
fwcfg_dma_present = qemu_fwcfg_dma_present();
+}
+static int qemu_fwcfg_do_list(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
+{
if (qemu_fwcfg_list_firmware() < 0)
return CMD_RET_FAILURE;
return 0;
+}
+static int qemu_fwcfg_do_cpus(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
+{
int ret = qemu_fwcfg_online_cpus();
if (ret < 0) {
printf("QEMU fw_cfg interface not found\n");
return CMD_RET_FAILURE;
}
printf("%d cpu(s) online\n", qemu_fwcfg_online_cpus());
return 0;
+}
+static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
+{
char *env;
void *load_addr;
void *initrd_addr;
env = getenv("loadaddr");
load_addr = env ?
(void *)simple_strtoul(env, NULL, 16) :
(void *)CONFIG_LOADADDR;
env = getenv("ramdiskaddr");
initrd_addr = env ?
(void *)simple_strtoul(env, NULL, 16) :
(void *)CONFIG_RAMDISK_ADDR;
if (argc == 2) {
load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
initrd_addr = (void *)simple_strtoul(argv[1], NULL, 16);
} else if (argc == 1) {
load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
}
return qemu_fwcfg_setup_kernel(load_addr, initrd_addr);
+}
+static cmd_tbl_t fwcfg_commands[] = {
U_BOOT_CMD_MKENT(list, 0, 1, qemu_fwcfg_do_list, "", ""),
U_BOOT_CMD_MKENT(cpus, 0, 1, qemu_fwcfg_do_cpus, "", ""),
U_BOOT_CMD_MKENT(load, 2, 1, qemu_fwcfg_do_load, "", ""),
+};
+static int do_qemu_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{
int ret;
cmd_tbl_t *fwcfg_cmd;
if (!fwcfg_present) {
printf("QEMU fw_cfg interface not found\n");
return CMD_RET_USAGE;
}
fwcfg_cmd = find_cmd_tbl(argv[1], fwcfg_commands,
ARRAY_SIZE(fwcfg_commands));
argc -= 2;
argv += 2;
if (!fwcfg_cmd || argc > fwcfg_cmd->maxargs)
return CMD_RET_USAGE;
ret = fwcfg_cmd->cmd(fwcfg_cmd, flag, argc, argv);
return cmd_process_error(fwcfg_cmd, ret);
+}
+U_BOOT_CMD(
qfw, 4, 1, do_qemu_fw,
"QEMU firmware interface",
"<command>\n"
" - list : print firmware(s) currently loaded\n"
" - cpus : print online cpu number\n"
" - load <kernel addr> <initrd addr> : load kernel and initrd (if any), and setup for zboot\n"
+) diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 53b1ff6..a813e5b 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -20,6 +20,7 @@ CONFIG_CMD_DHCP=y # CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y CONFIG_CMD_TIME=y +CONFIG_CMD_QEMU_FW_CFG=y CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_EXT2=y CONFIG_CMD_EXT4=y diff --git a/include/qemu_fw_cfg.h b/include/qemu_fw_cfg.h new file mode 100644 index 0000000..e21f150 --- /dev/null +++ b/include/qemu_fw_cfg.h @@ -0,0 +1,162 @@ +/*
- (C) Copyright 2015 Miao Yan yanmiaobest@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __FW_CFG__ +#define __FW_CFG__
+#define FW_CONTROL_PORT 0x510 +#define FW_DATA_PORT 0x511 +#define FW_DMA_PORT_LOW 0x514 +#define FW_DMA_PORT_HIGH 0x518
+#include <linux/list.h>
+enum qemu_fwcfg_items {
FW_CFG_SIGNATURE = 0x00,
FW_CFG_ID = 0x01,
FW_CFG_UUID = 0x02,
FW_CFG_RAM_SIZE = 0x03,
FW_CFG_NOGRAPHIC = 0x04,
FW_CFG_NB_CPUS = 0x05,
FW_CFG_MACHINE_ID = 0x06,
FW_CFG_KERNEL_ADDR = 0x07,
FW_CFG_KERNEL_SIZE = 0x08,
FW_CFG_KERNEL_CMDLINE = 0x09,
FW_CFG_INITRD_ADDR = 0x0a,
FW_CFG_INITRD_SIZE = 0x0b,
FW_CFG_BOOT_DEVICE = 0x0c,
FW_CFG_NUMA = 0x0d,
FW_CFG_BOOT_MENU = 0x0e,
FW_CFG_MAX_CPUS = 0x0f,
FW_CFG_KERNEL_ENTRY = 0x10,
FW_CFG_KERNEL_DATA = 0x11,
FW_CFG_INITRD_DATA = 0x12,
FW_CFG_CMDLINE_ADDR = 0x13,
FW_CFG_CMDLINE_SIZE = 0x14,
FW_CFG_CMDLINE_DATA = 0x15,
FW_CFG_SETUP_ADDR = 0x16,
FW_CFG_SETUP_SIZE = 0x17,
FW_CFG_SETUP_DATA = 0x18,
FW_CFG_FILE_DIR = 0x19,
FW_CFG_FILE_FIRST = 0x20,
FW_CFG_WRITE_CHANNEL = 0x4000,
FW_CFG_ARCH_LOCAL = 0x8000,
FW_CFG_INVALID = 0xffff,
+};
+enum {
BIOS_LINKER_LOADER_COMMAND_ALLOCATE = 0x1,
BIOS_LINKER_LOADER_COMMAND_ADD_POINTER = 0x2,
BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
+};
+enum {
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH = 0x1,
BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG = 0x2,
+};
+#define FW_CFG_FILE_SLOTS 0x10 +#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST + FW_CFG_FILE_SLOTS) +#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL)
+#define FW_CFG_MAX_FILE_PATH 56 +#define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH
+#define QEMU_FW_CFG_SIGNATURE (('Q' << 24) | ('E' << 16) | ('M' << 8) | 'U')
+#define FW_CFG_DMA_ERROR (1 << 0) +#define FW_CFG_DMA_READ (1 << 1) +#define FW_CFG_DMA_SKIP (1 << 2) +#define FW_CFG_DMA_SELECT (1 << 3)
+#define FW_CFG_DMA_ENABLED (1 << 1)
+struct fw_cfg_file {
__be32 size;
__be16 select;
__be16 reserved;
char name[FW_CFG_MAX_FILE_PATH];
+};
+struct fw_file {
struct fw_cfg_file cfg; /* firmware file information */
unsigned long addr; /* firmware file in-memory address */
struct list_head list; /* list node to link to fw_list */
+};
+struct fw_cfg_dma_access {
__be32 control;
__be32 length;
__be64 address;
+};
+struct bios_linker_entry {
__le32 command;
union {
/*
* COMMAND_ALLOCATE - allocate a table from @alloc.file
* subject to @alloc.align alignment (must be power of 2)
* and @alloc.zone (can be HIGH or FSEG) requirements.
*
* Must appear exactly once for each file, and before
* this file is referenced by any other command.
*/
struct {
char file[BIOS_LINKER_LOADER_FILESZ];
__le32 align;
uint8_t zone;
} alloc;
/*
* COMMAND_ADD_POINTER - patch the table (originating from
* @dest_file) at @pointer.offset, by adding a pointer to the
* table originating from @src_file. 1,2,4 or 8 byte unsigned
* addition is used depending on @pointer.size.
*/
struct {
char dest_file[BIOS_LINKER_LOADER_FILESZ];
char src_file[BIOS_LINKER_LOADER_FILESZ];
__le32 offset;
uint8_t size;
} pointer;
/*
* COMMAND_ADD_CHECKSUM - calculate checksum of the range
* specified by @cksum_start and @cksum_length fields,
* and then add the value at @cksum.offset.
* Checksum simply sums -X for each byte X in the range
* using 8-bit math.
*/
struct {
char file[BIOS_LINKER_LOADER_FILESZ];
__le32 offset;
__le32 start;
__le32 length;
} cksum;
/* padding */
char pad[124];
};
+} __packed;
+/**
- Initialize QEMU fw_cfg interface
- */
+void qemu_fwcfg_init(void);
+void qemu_fwcfg_read_entry(uint16_t entry, uint32_t length, void *address); +int qemu_fwcfg_read_firmware_list(void); +struct fw_file *qemu_fwcfg_find_file(const char *name); +void qemu_fwcfg_free_files(void);
+/**
- Get system cpu number
- @return: cpu number in system
- */
+int qemu_fwcfg_online_cpus(void);
+#endif
1.9.1

On Mon, May 09, 2016 at 02:32:51PM +0800, Miao Yan wrote:
2016-05-06 22:40 GMT+08:00 Tom Rini trini@konsulko.com:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
I am afraid this still doesn't build. At least you need to make the ACPI stuff depend on the new config option CONFIG_CMD_QEMU_FW_CFG, as well as some tweaks in qemu.c and mp_init.c because they call functions from the origin fw_cfg.c and they used to be guarded by CONFIG_QEMU, something like the following diff:
OK, I can go and poke around with these changes as well but for the record: $ uboot-build.sh x86 Testing x86 Mon May 9 11:52:21 EDT 2016 ... Building current source for 12 boards (6 threads, 1 job per thread) 12 0 0 /12 chromebook_link $
So it's all building in-tree today. Thanks!

+config CMD_QEMU_FW_CFG
bool "qfw"
depends on X86
help
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
endmenu
This should really be "depends on QEMU". Sorry for my earlier comment.
This line should be "depends on X86 && QEMU". Sorry I wasn't thinking right.
Miao

On Tue, May 10, 2016 at 10:10:17AM +0800, Miao Yan wrote:
+config CMD_QEMU_FW_CFG
bool "qfw"
depends on X86
help
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
endmenu
This should really be "depends on QEMU". Sorry for my earlier comment.
This line should be "depends on X86 && QEMU". Sorry I wasn't thinking right.
In general, I want to see the least restrictive set of depends used. This should be "easy" to throw into sandbox for testing there and when we use normal boards under qemu this should also be easy to enable.

Hi Miao,
On Tue, May 10, 2016 at 10:10 AM, Miao Yan yanmiaobest@gmail.com wrote:
+config CMD_QEMU_FW_CFG
bool "qfw"
depends on X86
help
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
endmenu
This should really be "depends on QEMU". Sorry for my earlier comment.
This line should be "depends on X86 && QEMU". Sorry I wasn't thinking right.
This "depends on X86 && QEMU" still does not work as users can still unselect this qfw command from menuconfig. We should make QEMU select this qfw command when CONFIG_GENERATE_ACPI_TABLE.
Regards, Bin

2016-05-11 10:11 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
Hi Miao,
On Tue, May 10, 2016 at 10:10 AM, Miao Yan yanmiaobest@gmail.com wrote:
+config CMD_QEMU_FW_CFG
bool "qfw"
depends on X86
help
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
endmenu
This should really be "depends on QEMU". Sorry for my earlier comment.
This line should be "depends on X86 && QEMU". Sorry I wasn't thinking right.
This "depends on X86 && QEMU" still does not work as users can still unselect this qfw command from menuconfig.
The qfw commands are not mandatory, so users should be able to disable it.
We should make QEMU select this qfw command when CONFIG_GENERATE_ACPI_TABLE.
GENERATE_ACPI_TABLE should select qfw core, not qfw command interface.
Anyway I'll prepare patches for you guys to review.
Thanks, Miao
Regards, Bin

On Wed, May 11, 2016 at 5:01 PM, Miao Yan yanmiaobest@gmail.com wrote:
2016-05-11 10:11 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
Hi Miao,
On Tue, May 10, 2016 at 10:10 AM, Miao Yan yanmiaobest@gmail.com wrote:
+config CMD_QEMU_FW_CFG
bool "qfw"
depends on X86
help
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
endmenu
This should really be "depends on QEMU". Sorry for my earlier comment.
This line should be "depends on X86 && QEMU". Sorry I wasn't thinking right.
This "depends on X86 && QEMU" still does not work as users can still unselect this qfw command from menuconfig.
The qfw commands are not mandatory, so users should be able to disable it.
Yes
We should make QEMU select this qfw command when CONFIG_GENERATE_ACPI_TABLE.
GENERATE_ACPI_TABLE should select qfw core, not qfw command interface.
Correct
Anyway I'll prepare patches for you guys to review.
Thanks!
Regards, Bin

On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
[1] http://patchwork.ozlabs.org/patch/619748/
Regards, Bin

On Tue, May 10, 2016 at 09:20:45AM +0800, Bin Meng wrote:
On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
For the next release, and I'll leave it to you to pull in. Thanks!

On Tue, May 10, 2016 at 10:17 AM, Tom Rini trini@konsulko.com wrote:
On Tue, May 10, 2016 at 09:20:45AM +0800, Bin Meng wrote:
On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
For the next release, and I'll leave it to you to pull in. Thanks!
applied to u-boot-x86/next, thanks!

2016-05-10 11:08 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
On Tue, May 10, 2016 at 10:17 AM, Tom Rini trini@konsulko.com wrote:
On Tue, May 10, 2016 at 09:20:45AM +0800, Bin Meng wrote:
On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
For the next release, and I'll leave it to you to pull in. Thanks!
applied to u-boot-x86/next, thanks!
Wait, you applied this already ? Did you include the diff I mentioned ? This patch has build issues. Before the patch, the qfw is built unconditionally for x86-qemu, after applying this patch, qfw depends on CONFIG_CMD_QEMU_FW_CFG. This is a change of behavior, so you need to test:
1) defconfig build 2) defconfig with CONFIG_CMD_QEMU_FW_CFG disabled because it's user visible now
This patch breaks 2):
arch/x86/cpu/built-in.o: In function `cpu_qemu_get_count': /home/myan/work/u-boot/arch/x86/cpu/qemu/cpu.c:28: undefined reference to `qemu_fwcfg_online_cpus' arch/x86/cpu/built-in.o: In function `qemu_chipset_init': /home/myan/work/u-boot/arch/x86/cpu/qemu/qemu.c:91: undefined reference to `qemu_fwcfg_init' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:187: undefined reference to `qemu_fwcfg_read_firmware_list' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:193: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:211: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_allocate': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:41: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:71: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_add_pointer': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:96: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:99: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `bios_linker_add_checksum': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:129: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:239: undefined reference to `qemu_fwcfg_free_files' arch/x86/cpu/built-in.o: In function `qemu_cpu_fixup': /home/myan/work/u-boot/arch/x86/cpu/mp_init.c:454: undefined reference to `qemu_fwcfg_online_cpus' make: *** [u-boot] Error 1
And I still think for this patch, it should depend on x86 && qemu. It doesn't make sense to build qfw for other non-qemu boards.
Miao

Hi Miao,
On Tue, May 10, 2016 at 12:35 PM, Miao Yan yanmiaobest@gmail.com wrote:
2016-05-10 11:08 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
On Tue, May 10, 2016 at 10:17 AM, Tom Rini trini@konsulko.com wrote:
On Tue, May 10, 2016 at 09:20:45AM +0800, Bin Meng wrote:
On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
For the next release, and I'll leave it to you to pull in. Thanks!
applied to u-boot-x86/next, thanks!
Wait, you applied this already ? Did you include the diff I mentioned
The patch is not in mainline. It's currently in x86 tree and we can always fix issues before a pull request is sent out.
? This patch has build issues. Before the patch, the qfw is built unconditionally for x86-qemu, after applying this patch, qfw depends on CONFIG_CMD_QEMU_FW_CFG. This is a change of behavior, so you need to test:
1) defconfig build 2) defconfig with CONFIG_CMD_QEMU_FW_CFG disabled because it's
user visible now
This patch breaks 2):
I doubt everything can be build error free if we randomly switch something on or off from the Kconfig GUI. I did buildman testing for this patch and nothing breaks by default. Having said that, I agree the build error you reported is something we should fix.
arch/x86/cpu/built-in.o: In function `cpu_qemu_get_count': /home/myan/work/u-boot/arch/x86/cpu/qemu/cpu.c:28: undefined reference to `qemu_fwcfg_online_cpus' arch/x86/cpu/built-in.o: In function `qemu_chipset_init': /home/myan/work/u-boot/arch/x86/cpu/qemu/qemu.c:91: undefined reference to `qemu_fwcfg_init' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:187: undefined reference to `qemu_fwcfg_read_firmware_list' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:193: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:211: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_allocate': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:41: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:71: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_add_pointer': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:96: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:99: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `bios_linker_add_checksum': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:129: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:239: undefined reference to `qemu_fwcfg_free_files' arch/x86/cpu/built-in.o: In function `qemu_cpu_fixup': /home/myan/work/u-boot/arch/x86/cpu/mp_init.c:454: undefined reference to `qemu_fwcfg_online_cpus' make: *** [u-boot] Error 1
And I still think for this patch, it should depend on x86 && qemu. It doesn't make sense to build qfw for other non-qemu boards.
Tom has the following statement regarding adding qemu dependency to the Kconfig option:
"In general, I want to see the least restrictive set of depends used. This should be "easy" to throw into sandbox for testing there and when we use normal boards under qemu this should also be easy to enable."
I believe Tom wanted to enable this command build testing for Sanbox, hence increase our build coverage. I think more refactoring work needs to done to achieve that. Like you said, now QEMU's ACPI table generation depends on CONFIG_CMD_QEMU_FW_CFG. This looks to me a little bit odd. We may further split the qemu_fw_cfg.c to two parts: one only does the command line handling, and the other one does the fw_cfg stuff.
Maybe you can send out some patches to address these?
Regards, Bin

Hi Bin,
2016-05-10 13:12 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
Hi Miao,
On Tue, May 10, 2016 at 12:35 PM, Miao Yan yanmiaobest@gmail.com wrote:
2016-05-10 11:08 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
On Tue, May 10, 2016 at 10:17 AM, Tom Rini trini@konsulko.com wrote:
On Tue, May 10, 2016 at 09:20:45AM +0800, Bin Meng wrote:
On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote:
- Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into cmd/qemu_fw_cfg.c
- Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h
- Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c
Signed-off-by: Tom Rini trini@konsulko.com
Changes in v2:
- Depend on X86 (per Miao Yan)
arch/x86/cpu/mp_init.c | 2 +- arch/x86/cpu/qemu/Makefile | 3 +- arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ arch/x86/cpu/qemu/cpu.c | 2 +- arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- arch/x86/cpu/qemu/qemu.c | 2 +- arch/x86/include/asm/fw_cfg.h | 157 ------------ arch/x86/lib/acpi_table.c | 2 +- cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ configs/qemu-x86_defconfig | 1 + include/qemu_fw_cfg.h | 162 ++++++++++++ 13 files changed, 763 insertions(+), 732 deletions(-) create mode 100644 arch/x86/cpu/qemu/acpi_table.c delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c delete mode 100644 arch/x86/include/asm/fw_cfg.h create mode 100644 cmd/qemu_fw_cfg.c create mode 100644 include/qemu_fw_cfg.h
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
For the next release, and I'll leave it to you to pull in. Thanks!
applied to u-boot-x86/next, thanks!
Wait, you applied this already ? Did you include the diff I mentioned
The patch is not in mainline. It's currently in x86 tree and we can always fix issues before a pull request is sent out.
? This patch has build issues. Before the patch, the qfw is built unconditionally for x86-qemu, after applying this patch, qfw depends on CONFIG_CMD_QEMU_FW_CFG. This is a change of behavior, so you need to test:
1) defconfig build 2) defconfig with CONFIG_CMD_QEMU_FW_CFG disabled because it's
user visible now
This patch breaks 2):
I doubt everything can be build error free if we randomly switch something on or off from the Kconfig GUI. I did buildman testing for
Well I don't think it's "random", we have mature tools to deal with dependencies, it's not like I was directly modifying random stuff in .config with a text editor. Kconfig options should be there for a reason, otherwise why bother. And if it doesn't work then it's a bug.
this patch and nothing breaks by default. Having said that, I agree the build error you reported is something we should fix.
OK. So can you please apply the diff or ask for v3 if you like ?
arch/x86/cpu/built-in.o: In function `cpu_qemu_get_count': /home/myan/work/u-boot/arch/x86/cpu/qemu/cpu.c:28: undefined reference to `qemu_fwcfg_online_cpus' arch/x86/cpu/built-in.o: In function `qemu_chipset_init': /home/myan/work/u-boot/arch/x86/cpu/qemu/qemu.c:91: undefined reference to `qemu_fwcfg_init' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:187: undefined reference to `qemu_fwcfg_read_firmware_list' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:193: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:211: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_allocate': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:41: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:71: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_add_pointer': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:96: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:99: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `bios_linker_add_checksum': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:129: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:239: undefined reference to `qemu_fwcfg_free_files' arch/x86/cpu/built-in.o: In function `qemu_cpu_fixup': /home/myan/work/u-boot/arch/x86/cpu/mp_init.c:454: undefined reference to `qemu_fwcfg_online_cpus' make: *** [u-boot] Error 1
And I still think for this patch, it should depend on x86 && qemu. It doesn't make sense to build qfw for other non-qemu boards.
Tom has the following statement regarding adding qemu dependency to the Kconfig option:
"In general, I want to see the least restrictive set of depends used. This should be "easy" to throw into sandbox for testing there and when we use normal boards under qemu this should also be easy to enable."
I believe Tom wanted to enable this command build testing for Sanbox, hence increase our build coverage. I think more refactoring work needs
Maybe some kind of random/allyes/allno config should be in that build coverage test.
to done to achieve that. Like you said, now QEMU's ACPI table generation depends on CONFIG_CMD_QEMU_FW_CFG. This looks to me a little bit odd. We may further split the qemu_fw_cfg.c to two parts: one only does the command line handling, and the other one does the fw_cfg stuff.
Agreed. I just thought these will be automatically sorted out when we extend qfw to other architectures.
Maybe you can send out some patches to address these?
Looks like Tom has plans for this ?
Thanks, Miao
Regards, Bin

On Tue, May 10, 2016 at 03:17:04PM +0800, Miao Yan wrote:
Hi Bin,
2016-05-10 13:12 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
Hi Miao,
On Tue, May 10, 2016 at 12:35 PM, Miao Yan yanmiaobest@gmail.com wrote:
2016-05-10 11:08 GMT+08:00 Bin Meng bmeng.cn@gmail.com:
On Tue, May 10, 2016 at 10:17 AM, Tom Rini trini@konsulko.com wrote:
On Tue, May 10, 2016 at 09:20:45AM +0800, Bin Meng wrote:
On Fri, May 6, 2016 at 10:40 PM, Tom Rini trini@konsulko.com wrote: > - Move the command portion of arch/x86/cpu/qemu/fw_cfg.c into > cmd/qemu_fw_cfg.c > - Move arch/x86/include/asm/fw_cfg.h to include/qemu_fw_cfg.h > - Rename ACPI table portion to arch/x86/cpu/qemu/acpi_table.c > > Signed-off-by: Tom Rini trini@konsulko.com > --- > Changes in v2: > - Depend on X86 (per Miao Yan) > --- > arch/x86/cpu/mp_init.c | 2 +- > arch/x86/cpu/qemu/Makefile | 3 +- > arch/x86/cpu/qemu/acpi_table.c | 243 ++++++++++++++++++ > arch/x86/cpu/qemu/cpu.c | 2 +- > arch/x86/cpu/qemu/fw_cfg.c | 570 ----------------------------------------- > arch/x86/cpu/qemu/qemu.c | 2 +- > arch/x86/include/asm/fw_cfg.h | 157 ------------ > arch/x86/lib/acpi_table.c | 2 +- > cmd/Kconfig | 7 + > cmd/Makefile | 1 + > cmd/qemu_fw_cfg.c | 343 +++++++++++++++++++++++++ > configs/qemu-x86_defconfig | 1 + > include/qemu_fw_cfg.h | 162 ++++++++++++ > 13 files changed, 763 insertions(+), 732 deletions(-) > create mode 100644 arch/x86/cpu/qemu/acpi_table.c > delete mode 100644 arch/x86/cpu/qemu/fw_cfg.c > delete mode 100644 arch/x86/include/asm/fw_cfg.h > create mode 100644 cmd/qemu_fw_cfg.c > create mode 100644 include/qemu_fw_cfg.h >
Looks good.
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tom, will you pick this for this release, or next release?
Miao has a patch [1] to remove CONFIG_QEMU_ACPI_TABLE. If your patch comes first, Miao needs to rebase his and submit v2.
For the next release, and I'll leave it to you to pull in. Thanks!
applied to u-boot-x86/next, thanks!
Wait, you applied this already ? Did you include the diff I mentioned
The patch is not in mainline. It's currently in x86 tree and we can always fix issues before a pull request is sent out.
? This patch has build issues. Before the patch, the qfw is built unconditionally for x86-qemu, after applying this patch, qfw depends on CONFIG_CMD_QEMU_FW_CFG. This is a change of behavior, so you need to test:
1) defconfig build 2) defconfig with CONFIG_CMD_QEMU_FW_CFG disabled because it's
user visible now
This patch breaks 2):
I doubt everything can be build error free if we randomly switch something on or off from the Kconfig GUI. I did buildman testing for
Well I don't think it's "random", we have mature tools to deal with dependencies, it's not like I was directly modifying random stuff in .config with a text editor. Kconfig options should be there for a reason, otherwise why bother. And if it doesn't work then it's a bug.
So yes, I suppose QEMU should select this new option since it is required there for other non-selectable options, rather than just being enabled in the defconfigs (which is why this is build clean from my point of view, qemu-x86_defconfig was updated).
this patch and nothing breaks by default. Having said that, I agree the build error you reported is something we should fix.
OK. So can you please apply the diff or ask for v3 if you like ?
arch/x86/cpu/built-in.o: In function `cpu_qemu_get_count': /home/myan/work/u-boot/arch/x86/cpu/qemu/cpu.c:28: undefined reference to `qemu_fwcfg_online_cpus' arch/x86/cpu/built-in.o: In function `qemu_chipset_init': /home/myan/work/u-boot/arch/x86/cpu/qemu/qemu.c:91: undefined reference to `qemu_fwcfg_init' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:187: undefined reference to `qemu_fwcfg_read_firmware_list' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:193: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:211: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_allocate': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:41: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:71: undefined reference to `qemu_fwcfg_read_entry' arch/x86/cpu/built-in.o: In function `bios_linker_add_pointer': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:96: undefined reference to `qemu_fwcfg_find_file' /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:99: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `bios_linker_add_checksum': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:129: undefined reference to `qemu_fwcfg_find_file' arch/x86/cpu/built-in.o: In function `write_acpi_tables': /home/myan/work/u-boot/arch/x86/cpu/qemu/acpi_table.c:239: undefined reference to `qemu_fwcfg_free_files' arch/x86/cpu/built-in.o: In function `qemu_cpu_fixup': /home/myan/work/u-boot/arch/x86/cpu/mp_init.c:454: undefined reference to `qemu_fwcfg_online_cpus' make: *** [u-boot] Error 1
And I still think for this patch, it should depend on x86 && qemu. It doesn't make sense to build qfw for other non-qemu boards.
Tom has the following statement regarding adding qemu dependency to the Kconfig option:
"In general, I want to see the least restrictive set of depends used. This should be "easy" to throw into sandbox for testing there and when we use normal boards under qemu this should also be easy to enable."
I believe Tom wanted to enable this command build testing for Sanbox, hence increase our build coverage. I think more refactoring work needs
Maybe some kind of random/allyes/allno config should be in that build coverage test.
Yes, my long term goal is that we can make use of random/allyes/allno for real, along with making the sandbox config extremely full. Which is partly why I want lose depends lines
to done to achieve that. Like you said, now QEMU's ACPI table generation depends on CONFIG_CMD_QEMU_FW_CFG. This looks to me a little bit odd. We may further split the qemu_fw_cfg.c to two parts: one only does the command line handling, and the other one does the fw_cfg stuff.
Agreed. I just thought these will be automatically sorted out when we extend qfw to other architectures.
Well, this patch was a first pass at trying to separate out the logic. My end goal is to be able to use -kernel / -initrd / -dtb to pass in files "directly" to say vexpress_ca9x4 rather than have to fiddle with fake networking. So we need to keep that in mind when splitting the code into cmd/ common/ and arch/x86/ (I'll set aside ACPI tables on ARM in QEMU for the moment, but lets also not forget that will be something someone will talk about in the future).
Maybe you can send out some patches to address these?
Looks like Tom has plans for this ?
Well, what you posted before addresses things well enough to start with, when I have time to cycle back and make use of this on either ARM or PowerPC or MIPS (and sandbox) I'll re-tweak the Kconfig logic again as needed. So lets fold that in for now, thanks!

Hi Tom,
Well, this patch was a first pass at trying to separate out the logic. My end goal is to be able to use -kernel / -initrd / -dtb to pass in files "directly" to say vexpress_ca9x4 rather than have to fiddle with fake networking. So we need to keep that in mind when splitting the
Well, about that, the fw_cfg is only exposed on certain QEMU emulated boards. For ARM, it is only available on arm_virt which supports cortexA15/53/57. Does U-boot have out-of-box support for that ?
Thanks, Miao
code into cmd/ common/ and arch/x86/ (I'll set aside ACPI tables on ARM in QEMU for the moment, but lets also not forget that will be something someone will talk about in the future).
participants (3)
-
Bin Meng
-
Miao Yan
-
Tom Rini