From dd6f3abbb81d4d0f8883a523e26fd45833a6b0d3 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 6 May 2016 10:40:22 -0400 Subject: 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 Reviewed-by: Bin Meng --- cmd/Kconfig | 7 ++ cmd/Makefile | 1 + cmd/qemu_fw_cfg.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 cmd/qemu_fw_cfg.c (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index 93367521286..c0fffe305c0 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 e3e0c74ffc6..d4432c84d9a 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 00000000000..48ae47683f9 --- /dev/null +++ b/cmd/qemu_fw_cfg.c @@ -0,0 +1,343 @@ +/* + * (C) Copyright 2015 Miao Yan + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +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", + "\n" + " - list : print firmware(s) currently loaded\n" + " - cpus : print online cpu number\n" + " - load : load kernel and initrd (if any), and setup for zboot\n" +) -- cgit v1.2.3 From 099b2196e4a693968fd6205ac6d61f6eaab79fb1 Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:11 -0700 Subject: cmd: qfw: add API to iterate firmware list This patch is part of the refactor work of qfw. It adds 3 APIs to qfw core to iterate firmware list. Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/qemu_fw_cfg.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/qemu_fw_cfg.c b/cmd/qemu_fw_cfg.c index 48ae47683f9..192b7d18d81 100644 --- a/cmd/qemu_fw_cfg.c +++ b/cmd/qemu_fw_cfg.c @@ -229,10 +229,27 @@ void qemu_fwcfg_free_files(void) } } +struct fw_file *qemu_fwcfg_file_iter_init(struct fw_cfg_file_iter *iter) +{ + iter->entry = fw_list.next; + return list_entry(iter->entry, struct fw_file, list); +} + +struct fw_file *qemu_fwcfg_file_iter_next(struct fw_cfg_file_iter *iter) +{ + iter->entry = iter->entry->next; + return list_entry(iter->entry, struct fw_file, list); +} + +bool qemu_fwcfg_file_iter_end(struct fw_cfg_file_iter *iter) +{ + return iter->entry == &fw_list; +} + static int qemu_fwcfg_list_firmware(void) { int ret; - struct list_head *entry; + struct fw_cfg_file_iter iter; struct fw_file *file; /* make sure fw_list is loaded */ @@ -240,8 +257,10 @@ static int qemu_fwcfg_list_firmware(void) if (ret) return ret; - list_for_each(entry, &fw_list) { - file = list_entry(entry, struct fw_file, list); + + for (file = qemu_fwcfg_file_iter_init(&iter); + !qemu_fwcfg_file_iter_end(&iter); + file = qemu_fwcfg_file_iter_next(&iter)) { printf("%-56s\n", file->cfg.name); } -- cgit v1.2.3 From 05dd6f183c8c20f0176a67ac885f8143c0052203 Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:12 -0700 Subject: cmd: qfw: remove qemu_fwcfg_free_files() This patch is part of the qfw refactor work. The qemu_fwcfg_free_files() function is only used in error handling in ACPI table generation, let's not make this a core function and move it to the right place. Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/qemu_fw_cfg.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'cmd') diff --git a/cmd/qemu_fw_cfg.c b/cmd/qemu_fw_cfg.c index 192b7d18d81..9f03ab60ab1 100644 --- a/cmd/qemu_fw_cfg.c +++ b/cmd/qemu_fw_cfg.c @@ -217,18 +217,6 @@ struct fw_file *qemu_fwcfg_find_file(const char *name) 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); - } -} - struct fw_file *qemu_fwcfg_file_iter_init(struct fw_cfg_file_iter *iter) { iter->entry = fw_list.next; -- cgit v1.2.3 From d3ad06239291d89c1c598248d577cde5470ac1ee Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:13 -0700 Subject: cmd: qfw: make fwcfg_present and fwcfg_dma_present public This patch is part of the qfw refactor work. This patch makes qemu_fwcfg_present() and qemu_fwcfg_dma_present() public functions. Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/qemu_fw_cfg.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'cmd') diff --git a/cmd/qemu_fw_cfg.c b/cmd/qemu_fw_cfg.c index 9f03ab60ab1..aab6b1a4526 100644 --- a/cmd/qemu_fw_cfg.c +++ b/cmd/qemu_fw_cfg.c @@ -62,23 +62,14 @@ static void qemu_fwcfg_read_entry_dma(uint16_t entry, __asm__ __volatile__ ("pause"); } -static bool qemu_fwcfg_present(void) +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; + return fwcfg_present; } -static bool qemu_fwcfg_dma_present(void) +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; + return fwcfg_dma_present; } void qemu_fwcfg_read_entry(uint16_t entry, uint32_t length, void *address) @@ -257,9 +248,21 @@ static int qemu_fwcfg_list_firmware(void) void qemu_fwcfg_init(void) { - fwcfg_present = qemu_fwcfg_present(); - if (fwcfg_present) - fwcfg_dma_present = qemu_fwcfg_dma_present(); + uint32_t qemu; + uint32_t dma_enabled; + + fwcfg_present = false; + fwcfg_dma_present = false; + + qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, &qemu); + if (be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE) + fwcfg_present = true; + + if (fwcfg_present) { + qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, &dma_enabled); + if (dma_enabled & FW_CFG_DMA_ENABLED) + fwcfg_dma_present = true; + } } static int qemu_fwcfg_do_list(cmd_tbl_t *cmdtp, int flag, @@ -323,7 +326,7 @@ 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) { + if (!qemu_fwcfg_present()) { printf("QEMU fw_cfg interface not found\n"); return CMD_RET_USAGE; } -- cgit v1.2.3 From fcf5c04193b48c3f5e2d337a85d28c4026f90ac3 Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:14 -0700 Subject: x86: qemu: split qfw command interface and qfw core This patch splits qfw command interface and qfw core function into two files, and introduces a new Kconfig option (CONFIG_QFW) for qfw core. Now when qfw command interface is enabled, it will automatically select qfw core. This patch also makes the ACPI table generation select CONFIG_QFW. Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/Kconfig | 1 + cmd/Makefile | 2 +- cmd/qemu_fw_cfg.c | 353 ------------------------------------------------------ cmd/qfw.c | 181 ++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 354 deletions(-) delete mode 100644 cmd/qemu_fw_cfg.c create mode 100644 cmd/qfw.c (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index c0fffe305c0..08b761f6db9 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -596,6 +596,7 @@ config CMD_SOUND config CMD_QEMU_FW_CFG bool "qfw" depends on X86 + select QFW help This provides access to the QEMU firmware interface. The main feature is to allow easy loading of files passed to qemu-system diff --git a/cmd/Makefile b/cmd/Makefile index d4432c84d9a..ff4fc5b98e8 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -105,7 +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_QEMU_FW_CFG) += qfw.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 deleted file mode 100644 index aab6b1a4526..00000000000 --- a/cmd/qemu_fw_cfg.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * (C) Copyright 2015 Miao Yan - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -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"); -} - -bool qemu_fwcfg_present(void) -{ - return fwcfg_present; -} - -bool qemu_fwcfg_dma_present(void) -{ - return fwcfg_dma_present; -} - -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; -} - -struct fw_file *qemu_fwcfg_file_iter_init(struct fw_cfg_file_iter *iter) -{ - iter->entry = fw_list.next; - return list_entry(iter->entry, struct fw_file, list); -} - -struct fw_file *qemu_fwcfg_file_iter_next(struct fw_cfg_file_iter *iter) -{ - iter->entry = iter->entry->next; - return list_entry(iter->entry, struct fw_file, list); -} - -bool qemu_fwcfg_file_iter_end(struct fw_cfg_file_iter *iter) -{ - return iter->entry == &fw_list; -} - -static int qemu_fwcfg_list_firmware(void) -{ - int ret; - struct fw_cfg_file_iter iter; - struct fw_file *file; - - /* make sure fw_list is loaded */ - ret = qemu_fwcfg_read_firmware_list(); - if (ret) - return ret; - - - for (file = qemu_fwcfg_file_iter_init(&iter); - !qemu_fwcfg_file_iter_end(&iter); - file = qemu_fwcfg_file_iter_next(&iter)) { - printf("%-56s\n", file->cfg.name); - } - - return 0; -} - -void qemu_fwcfg_init(void) -{ - uint32_t qemu; - uint32_t dma_enabled; - - fwcfg_present = false; - fwcfg_dma_present = false; - - qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, &qemu); - if (be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE) - fwcfg_present = true; - - if (fwcfg_present) { - qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, &dma_enabled); - if (dma_enabled & FW_CFG_DMA_ENABLED) - fwcfg_dma_present = true; - } -} - -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 (!qemu_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", - "\n" - " - list : print firmware(s) currently loaded\n" - " - cpus : print online cpu number\n" - " - load : load kernel and initrd (if any), and setup for zboot\n" -) diff --git a/cmd/qfw.c b/cmd/qfw.c new file mode 100644 index 00000000000..37f1aa6fc7b --- /dev/null +++ b/cmd/qfw.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2015 Miao Yan + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +/* + * 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_list_firmware(void) +{ + int ret; + struct fw_cfg_file_iter iter; + struct fw_file *file; + + /* make sure fw_list is loaded */ + ret = qemu_fwcfg_read_firmware_list(); + if (ret) + return ret; + + + for (file = qemu_fwcfg_file_iter_init(&iter); + !qemu_fwcfg_file_iter_end(&iter); + file = qemu_fwcfg_file_iter_next(&iter)) { + printf("%-56s\n", file->cfg.name); + } + + return 0; +} + +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 (!qemu_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", + "\n" + " - list : print firmware(s) currently loaded\n" + " - cpus : print online cpu number\n" + " - load : load kernel and initrd (if any), and setup for zboot\n" +) -- cgit v1.2.3 From 1868659002a6b7ab3b1da7be74f53d3e10e915be Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:17 -0700 Subject: cmd: qfw: rename qemu_fw_cfg.[c|h] to qfw.[c|h] Make file names consistent with CONFIG_QFW and CONFIG_CMD_QFW Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/Kconfig | 2 +- cmd/Makefile | 2 +- cmd/qfw.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index 08b761f6db9..c5a7a590644 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -593,7 +593,7 @@ config CMD_SOUND sound init - set up sound system sound play - play a sound -config CMD_QEMU_FW_CFG +config CMD_QFW bool "qfw" depends on X86 select QFW diff --git a/cmd/Makefile b/cmd/Makefile index ff4fc5b98e8..9ce7861f822 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -105,7 +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) += qfw.o +obj-$(CONFIG_CMD_QFW) += qfw.o obj-$(CONFIG_CMD_READ) += read.o obj-$(CONFIG_CMD_REGINFO) += reginfo.o obj-$(CONFIG_CMD_REISER) += reiser.o diff --git a/cmd/qfw.c b/cmd/qfw.c index 37f1aa6fc7b..c6730bf2d3e 100644 --- a/cmd/qfw.c +++ b/cmd/qfw.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include /* * This function prepares kernel for zboot. It loads kernel data -- cgit v1.2.3 From 86e30e67ad068ebedd1e6cc8833ba413ea28ed75 Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:18 -0700 Subject: cmd: qfw: do not require default macros when building qfw command The qfw command interface makes use of CONFIG_LOADADDR and CONFIG_RAMDISKADDR to setup kernel. But not all boards have these macros, which causes build problem on those platforms. This patch fixes this issue. Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/qfw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'cmd') diff --git a/cmd/qfw.c b/cmd/qfw.c index c6730bf2d3e..12436ec9b4e 100644 --- a/cmd/qfw.c +++ b/cmd/qfw.c @@ -126,12 +126,20 @@ static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag, env = getenv("loadaddr"); load_addr = env ? (void *)simple_strtoul(env, NULL, 16) : +#ifdef CONFIG_LOADADDR (void *)CONFIG_LOADADDR; +#else + NULL; +#endif env = getenv("ramdiskaddr"); initrd_addr = env ? (void *)simple_strtoul(env, NULL, 16) : +#ifdef CONFIG_RAMDISK_ADDR (void *)CONFIG_RAMDISK_ADDR; +#else + NULL; +#endif if (argc == 2) { load_addr = (void *)simple_strtoul(argv[0], NULL, 16); @@ -140,6 +148,11 @@ static int qemu_fwcfg_do_load(cmd_tbl_t *cmdtp, int flag, load_addr = (void *)simple_strtoul(argv[0], NULL, 16); } + if (!load_addr || !initrd_addr) { + printf("missing load or initrd address\n"); + return CMD_RET_FAILURE; + } + return qemu_fwcfg_setup_kernel(load_addr, initrd_addr); } -- cgit v1.2.3 From d6ccb14e5a8f3b782f9f09b88d5ca6695039a5f6 Mon Sep 17 00:00:00 2001 From: Miao Yan Date: Sun, 22 May 2016 19:37:19 -0700 Subject: cmd: qfw: do not depend on x86 The qfw command interface used to depend on X86, this patch removes this restriction so it can be built for sandbox for testing. For normal usage, it can only be used with CONFIG_QEMU. Signed-off-by: Miao Yan Reviewed-by: Bin Meng --- cmd/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index c5a7a590644..d51645c634e 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -595,7 +595,6 @@ config CMD_SOUND config CMD_QFW bool "qfw" - depends on X86 select QFW help This provides access to the QEMU firmware interface. The main -- cgit v1.2.3 From f9a90ace21c52a5a6948b9f3a0d8fe088e47a595 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 25 May 2016 09:48:14 +0100 Subject: arm64: fix arm64 Linux boot image header field sizes The arm64 Linux boot protocol [1] describes the fields in the Image header as being 64-bit little endian values. So fix the endianess conversion to use 64-bit sized operations, for both image_size and text_offset. Also we use a local variable for the image_size to avoid both writing to the header and also accessing it after we actually unmapped it. Signed-off-by: Andre Przywara [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/booting.txt --- cmd/bootm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/bootm.c b/cmd/bootm.c index 1bca6fa920e..ee3b460adb0 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -655,6 +655,7 @@ static int booti_setup(bootm_headers_t *images) { struct Image_header *ih; uint64_t dst; + uint64_t image_size; ih = (struct Image_header *)map_sysmem(images->ep, 0); @@ -665,14 +666,16 @@ static int booti_setup(bootm_headers_t *images) if (ih->image_size == 0) { puts("Image lacks image_size field, assuming 16MiB\n"); - ih->image_size = (16 << 20); + image_size = 16 << 20; + } else { + image_size = le64_to_cpu(ih->image_size); } /* * If we are not at the correct run-time location, set the new * correct location and then move the image there. */ - dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset); + dst = gd->bd->bi_dram[0].start + le64_to_cpu(ih->text_offset); unmap_sysmem(ih); @@ -683,7 +686,7 @@ static int booti_setup(bootm_headers_t *images) src = (void *)images->ep; images->ep = dst; - memmove((void *)dst, src, le32_to_cpu(ih->image_size)); + memmove((void *)dst, src, image_size); } return 0; -- cgit v1.2.3 From 9cf7b1a74c8c17145e39d34893cce763e098efd2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 14 May 2016 14:02:56 -0600 Subject: mmc: Drop dead mmc code for non-generic MMC All boards that use MMC define CONFIG_GENERIC_MMC now, so we can drop this old code. Signed-off-by: Simon Glass --- cmd/mmc.c | 62 -------------------------------------------------------------- 1 file changed, 62 deletions(-) (limited to 'cmd') diff --git a/cmd/mmc.c b/cmd/mmc.c index eb4a547a970..b2761e934bd 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -11,66 +11,6 @@ #include static int curr_device = -1; -#ifndef CONFIG_GENERIC_MMC -int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int dev; - - if (argc < 2) - return CMD_RET_USAGE; - - if (strcmp(argv[1], "init") == 0) { - if (argc == 2) { - if (curr_device < 0) - dev = 1; - else - dev = curr_device; - } else if (argc == 3) { - dev = (int)simple_strtoul(argv[2], NULL, 10); - } else { - return CMD_RET_USAGE; - } - - if (mmc_legacy_init(dev) != 0) { - puts("No MMC card found\n"); - return 1; - } - - curr_device = dev; - printf("mmc%d is available\n", curr_device); - } else if (strcmp(argv[1], "device") == 0) { - if (argc == 2) { - if (curr_device < 0) { - puts("No MMC device available\n"); - return 1; - } - } else if (argc == 3) { - dev = (int)simple_strtoul(argv[2], NULL, 10); - -#ifdef CONFIG_SYS_MMC_SET_DEV - if (mmc_set_dev(dev) != 0) - return 1; -#endif - curr_device = dev; - } else { - return CMD_RET_USAGE; - } - - printf("mmc%d is current device\n", curr_device); - } else { - return CMD_RET_USAGE; - } - - return 0; -} - -U_BOOT_CMD( - mmc, 3, 1, do_mmc, - "MMC sub-system", - "init [dev] - init MMC sub system\n" - "mmc device [dev] - show or set current device" -); -#else /* !CONFIG_GENERIC_MMC */ static void print_mmcinfo(struct mmc *mmc) { @@ -881,5 +821,3 @@ U_BOOT_CMD( "display MMC info", "- display info of the current MMC device" ); - -#endif /* !CONFIG_GENERIC_MMC */ -- cgit v1.2.3 From 04681cb3a4d2ef5351f94132e325fb8841d37961 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 1 May 2016 00:35:54 +0200 Subject: cmd: disk: Fix unused variable warning If serial support is not compiled into U-Boot, which may be the case for some SPL builds, the following warning will be generated in disk.c: cmd/disk.c: In function 'common_diskboot': cmd/disk.c:16:6: warning: variable 'dev' set but not used [-Wunused-but-set-variable] int dev, part; ^ The warning is a result of printf() calls being optimized away, and thus the whole dev variable becomes indeed unused. Mark the variable as __maybe_unused . Signed-off-by: Marek Vasut Cc: Simon Glass Cc: Tom Rini Reviewed-by: Simon Glass Reviewed-by: Tom Rini --- cmd/disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/disk.c b/cmd/disk.c index fcc41231271..92de3af8a5c 100644 --- a/cmd/disk.c +++ b/cmd/disk.c @@ -13,7 +13,8 @@ int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, char *const argv[]) { - int dev, part; + __maybe_unused int dev; + int part; ulong addr = CONFIG_SYS_LOAD_ADDR; ulong cnt; disk_partition_t info; -- cgit v1.2.3 From dafd64888c21abc43edbe7634b8edaacf9e2fe5c Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Wed, 4 May 2016 14:20:04 +0900 Subject: cmd: replace the cast of the memory access to a fixed bit type in itest This patch fixes a bug that long word(.l) memory access in 'itest' command reads the 8bytes of the actual memory on 64-bit architecture. The cast to the memory pointer should use a fixed bit type. Signed-off-by: Kunihiko Hayashi Signed-off-by: Masahiro Yamada Reviewed-by: Stefan Roese Reviewed-by: Simon Glass --- cmd/itest.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/itest.c b/cmd/itest.c index fb4d797e43d..60626c7fe9c 100644 --- a/cmd/itest.c +++ b/cmd/itest.c @@ -65,13 +65,13 @@ static long evalexp(char *s, int w) } switch (w) { case 1: - l = (long)(*(unsigned char *)buf); + l = (long)(*(u8 *)buf); break; case 2: - l = (long)(*(unsigned short *)buf); + l = (long)(*(u16 *)buf); break; case 4: - l = (long)(*(unsigned long *)buf); + l = (long)(*(u32 *)buf); break; } unmap_physmem(buf, w); -- cgit v1.2.3 From 0efe1bcf5c2ce89d7c2467550e2823d7f95733e0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 6 May 2016 21:01:01 +0200 Subject: efi_loader: Add network access support We can now successfully boot EFI applications from disk, but users may want to also run them from a PXE setup. This patch implements rudimentary network support, allowing a payload to send and receive network packets. With this patch, I was able to successfully run grub2 with network access inside of QEMU's -M xlnx-ep108. Signed-off-by: Alexander Graf --- cmd/bootefi.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 7f552fc0d4d..d3a23318702 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -197,6 +197,13 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) #ifdef CONFIG_LCD efi_gop_register(); #endif +#ifdef CONFIG_NET + void *nethandle = loaded_image_info.device_handle; + efi_net_register(&nethandle); + + if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6)) + loaded_image_info.device_handle = nethandle; +#endif /* Call our payload! */ #ifdef DEBUG_EFI -- cgit v1.2.3 From 151c06ec61d74b77cf27d6d622bab6370c949c66 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 30 May 2016 13:57:54 -0500 Subject: mtd: nand: Remove nand_info_t typedef This typedef serves no purpose other than causing confusion with struct nand_chip. Signed-off-by: Scott Wood --- cmd/bootm.c | 30 ++++++----- cmd/jffs2.c | 6 +-- cmd/nand.c | 161 ++++++++++++++++++++++++++++++------------------------------ 3 files changed, 98 insertions(+), 99 deletions(-) (limited to 'cmd') diff --git a/cmd/bootm.c b/cmd/bootm.c index ee3b460adb0..24f1054f34b 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -372,8 +372,8 @@ next_bank: ; #endif #if defined(CONFIG_CMD_IMLS_NAND) -static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off, - size_t len) +static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev, + loff_t off, size_t len) { void *imgdata; int ret; @@ -386,8 +386,7 @@ static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off, return -ENOMEM; } - ret = nand_read_skip_bad(nand, off, &len, - imgdata); + ret = nand_read_skip_bad(mtd, off, &len, imgdata); if (ret < 0 && ret != -EUCLEAN) { free(imgdata); return ret; @@ -413,8 +412,8 @@ static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off, return 0; } -static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off, - size_t len) +static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off, + size_t len) { void *imgdata; int ret; @@ -427,8 +426,7 @@ static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off, return -ENOMEM; } - ret = nand_read_skip_bad(nand, off, &len, - imgdata); + ret = nand_read_skip_bad(mtd, off, &len, imgdata); if (ret < 0 && ret != -EUCLEAN) { free(imgdata); return ret; @@ -449,7 +447,7 @@ static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off, static int do_imls_nand(void) { - nand_info_t *nand; + struct mtd_info *mtd; int nand_dev = nand_curr_device; size_t len; loff_t off; @@ -463,20 +461,20 @@ static int do_imls_nand(void) printf("\n"); for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { - nand = &nand_info[nand_dev]; - if (!nand->name || !nand->size) + mtd = &nand_info[nand_dev]; + if (!mtd->name || !mtd->size) continue; - for (off = 0; off < nand->size; off += nand->erasesize) { + for (off = 0; off < mtd->size; off += mtd->erasesize) { const image_header_t *header; int ret; - if (nand_block_isbad(nand, off)) + if (nand_block_isbad(mtd, off)) continue; len = sizeof(buffer); - ret = nand_read(nand, off, &len, (u8 *)buffer); + ret = nand_read(mtd, off, &len, (u8 *)buffer); if (ret < 0 && ret != -EUCLEAN) { printf("NAND read error %d at offset %08llX\n", ret, off); @@ -489,13 +487,13 @@ static int do_imls_nand(void) header = (const image_header_t *)buffer; len = image_get_image_size(header); - nand_imls_legacyimage(nand, nand_dev, off, len); + nand_imls_legacyimage(mtd, nand_dev, off, len); break; #endif #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: len = fit_get_size(buffer); - nand_imls_fitimage(nand, nand_dev, off, len); + nand_imls_fitimage(mtd, nand_dev, off, len); break; #endif } diff --git a/cmd/jffs2.c b/cmd/jffs2.c index 0b2eefa1954..e4eaa48c1f5 100644 --- a/cmd/jffs2.c +++ b/cmd/jffs2.c @@ -242,11 +242,11 @@ static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *d static inline u32 get_part_sector_size_nand(struct mtdids *id) { #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) - nand_info_t *nand; + struct mtd_info *mtd; - nand = &nand_info[id->num]; + mtd = &nand_info[id->num]; - return nand->erasesize; + return mtd->erasesize; #else BUG(); return 0; diff --git a/cmd/nand.c b/cmd/nand.c index a6b67e29f1c..0439607d682 100644 --- a/cmd/nand.c +++ b/cmd/nand.c @@ -38,7 +38,8 @@ int find_dev_and_part(const char *id, struct mtd_device **dev, u8 *part_num, struct part_info **part); #endif -static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) +static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob, + int repeat) { int i; u_char *datbuf, *oobbuf, *p; @@ -46,32 +47,32 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) int ret = 0; if (repeat) - off = last + nand->writesize; + off = last + mtd->writesize; last = off; - datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize); + datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize); if (!datbuf) { puts("No memory for page buffer\n"); return 1; } - oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize); + oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize); if (!oobbuf) { puts("No memory for page buffer\n"); ret = 1; goto free_dat; } - off &= ~(nand->writesize - 1); + off &= ~(mtd->writesize - 1); loff_t addr = (loff_t) off; struct mtd_oob_ops ops; memset(&ops, 0, sizeof(ops)); ops.datbuf = datbuf; ops.oobbuf = oobbuf; - ops.len = nand->writesize; - ops.ooblen = nand->oobsize; + ops.len = mtd->writesize; + ops.ooblen = mtd->oobsize; ops.mode = MTD_OPS_RAW; - i = mtd_read_oob(nand, addr, &ops); + i = mtd_read_oob(mtd, addr, &ops); if (i < 0) { printf("Error (%d) reading page %08lx\n", i, off); ret = 1; @@ -80,7 +81,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) printf("Page %08lx dump:\n", off); if (!only_oob) { - i = nand->writesize >> 4; + i = mtd->writesize >> 4; p = datbuf; while (i--) { @@ -94,7 +95,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) } puts("OOB:\n"); - i = nand->oobsize >> 3; + i = mtd->oobsize >> 3; p = oobbuf; while (i--) { printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", @@ -152,32 +153,32 @@ static void print_status(ulong start, ulong end, ulong erasesize, int status) ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); } -static void do_nand_status(nand_info_t *nand) +static void do_nand_status(struct mtd_info *mtd) { ulong block_start = 0; ulong off; int last_status = -1; - struct nand_chip *nand_chip = nand->priv; + struct nand_chip *nand_chip = mtd->priv; /* check the WP bit */ - nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1); + nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); printf("device is %swrite protected\n", - (nand_chip->read_byte(nand) & 0x80 ? - "NOT " : "")); + (nand_chip->read_byte(mtd) & 0x80 ? + "NOT " : "")); - for (off = 0; off < nand->size; off += nand->erasesize) { - int s = nand_get_lock_status(nand, off); + for (off = 0; off < mtd->size; off += mtd->erasesize) { + int s = nand_get_lock_status(mtd, off); /* print message only if status has changed */ if (s != last_status && off != 0) { - print_status(block_start, off, nand->erasesize, + print_status(block_start, off, mtd->erasesize, last_status); block_start = off; } last_status = s; } /* Print the last block info */ - print_status(block_start, off, nand->erasesize, last_status); + print_status(block_start, off, mtd->erasesize, last_status); } #endif @@ -188,10 +189,10 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) { int ret; uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)]; - nand_info_t *nand = &nand_info[0]; + struct mtd_info *mtd = &nand_info[0]; char *cmd = argv[1]; - if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) { + if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd->name) { puts("no devices available\n"); return 1; } @@ -199,7 +200,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) set_dev(0); if (!strcmp(cmd, "get")) { - ret = get_nand_env_oob(nand, &nand_env_oob_offset); + ret = get_nand_env_oob(mtd, &nand_env_oob_offset); if (ret) return 1; @@ -229,15 +230,15 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) return 1; } - if (nand->oobavail < ENV_OFFSET_SIZE) { + if (mtd->oobavail < ENV_OFFSET_SIZE) { printf("Insufficient available OOB bytes:\n" "%d OOB bytes available but %d required for " "env.oob support\n", - nand->oobavail, ENV_OFFSET_SIZE); + mtd->oobavail, ENV_OFFSET_SIZE); return 1; } - if ((addr & (nand->erasesize - 1)) != 0) { + if ((addr & (mtd->erasesize - 1)) != 0) { printf("Environment offset must be block-aligned\n"); return 1; } @@ -249,15 +250,15 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) ops.oobbuf = (void *) oob_buf; oob_buf[0] = ENV_OOB_MARKER; - oob_buf[1] = addr / nand->erasesize; + oob_buf[1] = addr / mtd->erasesize; - ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops); + ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops); if (ret) { printf("Error writing OOB block 0\n"); return ret; } - ret = get_nand_env_oob(nand, &nand_env_oob_offset); + ret = get_nand_env_oob(mtd, &nand_env_oob_offset); if (ret) { printf("Error reading env offset in OOB\n"); return ret; @@ -283,29 +284,29 @@ usage: static void nand_print_and_set_info(int idx) { - nand_info_t *nand = &nand_info[idx]; - struct nand_chip *chip = nand->priv; + struct mtd_info *mtd = &nand_info[idx]; + struct nand_chip *chip = mtd->priv; printf("Device %d: ", idx); if (chip->numchips > 1) printf("%dx ", chip->numchips); printf("%s, sector size %u KiB\n", - nand->name, nand->erasesize >> 10); - printf(" Page size %8d b\n", nand->writesize); - printf(" OOB size %8d b\n", nand->oobsize); - printf(" Erase size %8d b\n", nand->erasesize); + mtd->name, mtd->erasesize >> 10); + printf(" Page size %8d b\n", mtd->writesize); + printf(" OOB size %8d b\n", mtd->oobsize); + printf(" Erase size %8d b\n", mtd->erasesize); printf(" subpagesize %8d b\n", chip->subpagesize); printf(" options 0x%8x\n", chip->options); printf(" bbt options 0x%8x\n", chip->bbt_options); /* Set geometry info */ - setenv_hex("nand_writesize", nand->writesize); - setenv_hex("nand_oobsize", nand->oobsize); - setenv_hex("nand_erasesize", nand->erasesize); + setenv_hex("nand_writesize", mtd->writesize); + setenv_hex("nand_oobsize", mtd->oobsize); + setenv_hex("nand_erasesize", mtd->erasesize); } -static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, - int read) +static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off, + ulong count, int read) { int ret = 0; @@ -313,18 +314,18 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, /* Raw access */ mtd_oob_ops_t ops = { .datbuf = (u8 *)addr, - .oobbuf = ((u8 *)addr) + nand->writesize, - .len = nand->writesize, - .ooblen = nand->oobsize, + .oobbuf = ((u8 *)addr) + mtd->writesize, + .len = mtd->writesize, + .ooblen = mtd->oobsize, .mode = MTD_OPS_RAW }; if (read) { - ret = mtd_read_oob(nand, off, &ops); + ret = mtd_read_oob(mtd, off, &ops); } else { - ret = mtd_write_oob(nand, off, &ops); + ret = mtd_write_oob(mtd, off, &ops); if (!ret) - ret = nand_verify_page_oob(nand, &ops, off); + ret = nand_verify_page_oob(mtd, &ops, off); } if (ret) { @@ -333,8 +334,8 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, break; } - addr += nand->writesize + nand->oobsize; - off += nand->writesize; + addr += mtd->writesize + mtd->oobsize; + off += mtd->writesize; } return ret; @@ -348,18 +349,18 @@ static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev) /* We grab the nand info object here fresh because this is usually * called after arg_off_size() which can change the value of dev. */ - nand_info_t *nand = &nand_info[dev]; + struct mtd_info *mtd = &nand_info[dev]; loff_t maxoffset = offset + *size; int badblocks = 0; /* count badblocks in NAND from offset to offset + size */ - for (; offset < maxoffset; offset += nand->erasesize) { - if (nand_block_isbad(nand, offset)) + for (; offset < maxoffset; offset += mtd->erasesize) { + if (nand_block_isbad(mtd, offset)) badblocks++; } /* adjust size if any bad blocks found */ if (badblocks) { - *size -= badblocks * nand->erasesize; + *size -= badblocks * mtd->erasesize; printf("size adjusted to 0x%llx (%d bad blocks)\n", (unsigned long long)*size, badblocks); } @@ -371,7 +372,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong addr; loff_t off, size, maxsize; char *cmd, *s; - nand_info_t *nand; + struct mtd_info *mtd; #ifdef CONFIG_SYS_NAND_QUIET int quiet = CONFIG_SYS_NAND_QUIET; #else @@ -437,12 +438,12 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) puts("\nno devices available\n"); return 1; } - nand = &nand_info[dev]; + mtd = &nand_info[dev]; if (strcmp(cmd, "bad") == 0) { printf("\nDevice %d bad blocks:\n", dev); - for (off = 0; off < nand->size; off += nand->erasesize) - if (nand_block_isbad(nand, off)) + for (off = 0; off < mtd->size; off += mtd->erasesize) + if (nand_block_isbad(mtd, off)) printf(" %08llx\n", (unsigned long long)off); return 0; } @@ -502,7 +503,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (set_dev(dev)) return 1; - nand = &nand_info[dev]; + mtd = &nand_info[dev]; memset(&opts, 0, sizeof(opts)); opts.offset = off; @@ -524,7 +525,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } } } - ret = nand_erase_opts(nand, &opts); + ret = nand_erase_opts(mtd, &opts); printf("%s\n", ret ? "ERROR" : "OK"); return ret == 0 ? 0 : 1; @@ -535,7 +536,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) goto usage; off = (int)simple_strtoul(argv[2], NULL, 16); - ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat); + ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat); return ret == 0 ? 1 : 0; } @@ -567,19 +568,19 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (set_dev(dev)) return 1; - nand = &nand_info[dev]; + mtd = &nand_info[dev]; if (argc > 4 && !str2long(argv[4], &pagecount)) { printf("'%s' is not a number\n", argv[4]); return 1; } - if (pagecount * nand->writesize > size) { + if (pagecount * mtd->writesize > size) { puts("Size exceeds partition or device limit\n"); return -1; } - rwsize = pagecount * (nand->writesize + nand->oobsize); + rwsize = pagecount * (mtd->writesize + mtd->oobsize); } else { if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off, &size, &maxsize, @@ -596,16 +597,16 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) rwsize = size; } - nand = &nand_info[dev]; + mtd = &nand_info[dev]; if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { if (read) - ret = nand_read_skip_bad(nand, off, &rwsize, + ret = nand_read_skip_bad(mtd, off, &rwsize, NULL, maxsize, (u_char *)addr); else - ret = nand_write_skip_bad(nand, off, &rwsize, + ret = nand_write_skip_bad(mtd, off, &rwsize, NULL, maxsize, (u_char *)addr, WITH_WR_VERIFY); @@ -615,7 +616,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("Unknown nand command suffix '%s'\n", s); return 1; } - ret = nand_write_skip_bad(nand, off, &rwsize, NULL, + ret = nand_write_skip_bad(mtd, off, &rwsize, NULL, maxsize, (u_char *)addr, WITH_DROP_FFS | WITH_WR_VERIFY); #endif @@ -628,11 +629,11 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }; if (read) - ret = mtd_read_oob(nand, off, &ops); + ret = mtd_read_oob(mtd, off, &ops); else - ret = mtd_write_oob(nand, off, &ops); + ret = mtd_write_oob(mtd, off, &ops); } else if (raw) { - ret = raw_access(nand, addr, off, pagecount, read); + ret = raw_access(mtd, addr, off, pagecount, read); } else { printf("Unknown nand command suffix '%s'.\n", s); return 1; @@ -655,8 +656,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n", - dev, off, nand->erasesize); - ret = nand_torture(nand, off); + dev, off, mtd->erasesize); + ret = nand_torture(mtd, off); printf(" %s\n", ret ? "Failed" : "Passed"); return ret == 0 ? 0 : 1; @@ -673,7 +674,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) while (argc > 0) { addr = simple_strtoul(*argv, NULL, 16); - if (mtd_block_markbad(nand, addr)) { + if (mtd_block_markbad(mtd, addr)) { printf("block 0x%08lx NOT marked " "as bad! ERROR %d\n", addr, ret); @@ -705,9 +706,9 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) status = 1; } if (status) { - do_nand_status(nand); + do_nand_status(mtd); } else { - if (!nand_lock(nand, tight)) { + if (!nand_lock(mtd, tight)) { puts("NAND flash successfully locked\n"); } else { puts("Error locking NAND flash\n"); @@ -801,7 +802,7 @@ U_BOOT_CMD( "NAND sub-system", nand_help_text ); -static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, +static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd, ulong offset, ulong addr, char *cmd) { int r; @@ -822,11 +823,11 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, return 1; } - printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset); + printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset); - cnt = nand->writesize; - r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size, - (u_char *)addr); + cnt = mtd->writesize; + r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size, + (u_char *)addr); if (r) { puts("** Read error\n"); bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ); @@ -860,8 +861,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, } bootstage_mark(BOOTSTAGE_ID_NAND_TYPE); - r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size, - (u_char *)addr); + r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size, + (u_char *)addr); if (r) { puts("** Read error\n"); bootstage_error(BOOTSTAGE_ID_NAND_READ); -- cgit v1.2.3 From b616d9b0a708eb90eb474e1b6ec6dfe4c48a1678 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 30 May 2016 13:57:55 -0500 Subject: nand: Embed mtd_info in struct nand_chip nand_info[] is now an array of pointers, with the actual mtd_info instance embedded in struct nand_chip. This is in preparation for syncing the NAND code with Linux 4.6, which makes the same change to struct nand_chip. It's in a separate commit due to the large amount of changes required to accommodate the change to nand_info[]. Signed-off-by: Scott Wood --- cmd/bootm.c | 2 +- cmd/jffs2.c | 4 ++-- cmd/nand.c | 42 +++++++++++++++++++++--------------------- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'cmd') diff --git a/cmd/bootm.c b/cmd/bootm.c index 24f1054f34b..f5e91f40a9b 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -461,7 +461,7 @@ static int do_imls_nand(void) printf("\n"); for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { - mtd = &nand_info[nand_dev]; + mtd = nand_info[nand_dev]; if (!mtd->name || !mtd->size) continue; diff --git a/cmd/jffs2.c b/cmd/jffs2.c index e4eaa48c1f5..f00d53a6c83 100644 --- a/cmd/jffs2.c +++ b/cmd/jffs2.c @@ -167,7 +167,7 @@ static int mtd_device_validate(u8 type, u8 num, u32 *size) } else if (type == MTD_DEV_TYPE_NAND) { #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) if (num < CONFIG_SYS_MAX_NAND_DEVICE) { - *size = nand_info[num].size; + *size = nand_info[num]->size; return 0; } @@ -244,7 +244,7 @@ static inline u32 get_part_sector_size_nand(struct mtdids *id) #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND) struct mtd_info *mtd; - mtd = &nand_info[id->num]; + mtd = nand_info[id->num]; return mtd->erasesize; #else diff --git a/cmd/nand.c b/cmd/nand.c index 0439607d682..f1d5a1161d1 100644 --- a/cmd/nand.c +++ b/cmd/nand.c @@ -116,7 +116,7 @@ free_dat: static int set_dev(int dev) { if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[dev].name) { + !nand_info[dev]->name) { puts("No such device\n"); return -1; } @@ -124,12 +124,12 @@ static int set_dev(int dev) if (nand_curr_device == dev) return 0; - printf("Device %d: %s", dev, nand_info[dev].name); + printf("Device %d: %s", dev, nand_info[dev]->name); puts("... is now current device\n"); nand_curr_device = dev; #ifdef CONFIG_SYS_NAND_SELECT_DEVICE - board_nand_select_device(nand_info[dev].priv, dev); + board_nand_select_device(nand_info[dev]->priv, dev); #endif return 0; @@ -189,7 +189,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) { int ret; uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)]; - struct mtd_info *mtd = &nand_info[0]; + struct mtd_info *mtd = nand_info[0]; char *cmd = argv[1]; if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd->name) { @@ -216,7 +216,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) /* We don't care about size, or maxsize. */ if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize, - MTD_DEV_TYPE_NAND, nand_info[idx].size)) { + MTD_DEV_TYPE_NAND, nand_info[idx]->size)) { puts("Offset or partition name expected\n"); return 1; } @@ -284,7 +284,7 @@ usage: static void nand_print_and_set_info(int idx) { - struct mtd_info *mtd = &nand_info[idx]; + struct mtd_info *mtd = nand_info[idx]; struct nand_chip *chip = mtd->priv; printf("Device %d: ", idx); @@ -349,7 +349,7 @@ static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev) /* We grab the nand info object here fresh because this is usually * called after arg_off_size() which can change the value of dev. */ - struct mtd_info *mtd = &nand_info[dev]; + struct mtd_info *mtd = nand_info[dev]; loff_t maxoffset = offset + *size; int badblocks = 0; @@ -399,7 +399,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) putc('\n'); for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { - if (nand_info[i].name) + if (nand_info[i]->name) nand_print_and_set_info(i); } return 0; @@ -434,11 +434,11 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * for another device is to be used. */ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[dev].name) { + !nand_info[dev]->name) { puts("\nno devices available\n"); return 1; } - mtd = &nand_info[dev]; + mtd = nand_info[dev]; if (strcmp(cmd, "bad") == 0) { printf("\nDevice %d bad blocks:\n", dev); @@ -497,13 +497,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* skip first two or three arguments, look for offset and size */ if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size, &maxsize, MTD_DEV_TYPE_NAND, - nand_info[dev].size) != 0) + nand_info[dev]->size) != 0) return 1; if (set_dev(dev)) return 1; - mtd = &nand_info[dev]; + mtd = nand_info[dev]; memset(&opts, 0, sizeof(opts)); opts.offset = off; @@ -562,13 +562,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize, MTD_DEV_TYPE_NAND, - nand_info[dev].size)) + nand_info[dev]->size)) return 1; if (set_dev(dev)) return 1; - mtd = &nand_info[dev]; + mtd = nand_info[dev]; if (argc > 4 && !str2long(argv[4], &pagecount)) { printf("'%s' is not a number\n", argv[4]); @@ -585,7 +585,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off, &size, &maxsize, MTD_DEV_TYPE_NAND, - nand_info[dev].size) != 0) + nand_info[dev]->size) != 0) return 1; if (set_dev(dev)) @@ -597,7 +597,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) rwsize = size; } - mtd = &nand_info[dev]; + mtd = nand_info[dev]; if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { @@ -728,13 +728,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size, &maxsize, MTD_DEV_TYPE_NAND, - nand_info[dev].size) < 0) + nand_info[dev]->size) < 0) return 1; if (set_dev(dev)) return 1; - if (!nand_unlock(&nand_info[dev], off, size, allexcept)) { + if (!nand_unlock(nand_info[dev], off, size, allexcept)) { puts("NAND flash successfully unlocked\n"); } else { puts("Error unlocking NAND flash, " @@ -915,7 +915,7 @@ static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc, addr = simple_strtoul(argv[1], NULL, 16); else addr = CONFIG_SYS_LOAD_ADDR; - return nand_load_image(cmdtp, &nand_info[dev->id->num], + return nand_load_image(cmdtp, nand_info[dev->id->num], part->offset, addr, argv[0]); } } @@ -958,14 +958,14 @@ usage: idx = simple_strtoul(boot_device, NULL, 16); - if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) { + if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx]->name) { printf("\n** Device %d not available\n", idx); bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE); return 1; } bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE); - return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]); + return nand_load_image(cmdtp, nand_info[idx], offset, addr, argv[0]); } U_BOOT_CMD(nboot, 4, 1, do_nandboot, -- cgit v1.2.3 From 17cb4b8f327eb983cef7c510fcf77f1635a00e48 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 30 May 2016 13:57:56 -0500 Subject: mtd: nand: Add+use mtd_to/from_nand and nand_get/set_controller_data These functions are part of the Linux 4.6 sync. They are being added before the main sync patch in order to make it easier to address the issue across all NAND drivers (many/most of which do not closely track their Linux counterparts) separately from other merge issues. Signed-off-by: Scott Wood --- cmd/nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cmd') diff --git a/cmd/nand.c b/cmd/nand.c index f1d5a1161d1..583a18f341a 100644 --- a/cmd/nand.c +++ b/cmd/nand.c @@ -159,7 +159,7 @@ static void do_nand_status(struct mtd_info *mtd) ulong off; int last_status = -1; - struct nand_chip *nand_chip = mtd->priv; + struct nand_chip *nand_chip = mtd_to_nand(mtd); /* check the WP bit */ nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); printf("device is %swrite protected\n", @@ -285,7 +285,7 @@ usage: static void nand_print_and_set_info(int idx) { struct mtd_info *mtd = nand_info[idx]; - struct nand_chip *chip = mtd->priv; + struct nand_chip *chip = mtd_to_nand(mtd); printf("Device %d: ", idx); if (chip->numchips > 1) -- cgit v1.2.3 From a86aeaf228da739bce6bc40927949efc33672050 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 20 May 2016 23:28:23 +0200 Subject: efi_loader: Add exit support Some times you may want to exit an EFI payload again, for example to default boot into a PXE installation and decide that you would rather want to boot from the local disk instead. This patch adds exit functionality to the EFI implementation, allowing EFI payloads to exit. Signed-off-by: Alexander Graf --- cmd/bootefi.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d3a23318702..2a62dce702b 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -209,6 +209,12 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) #ifdef DEBUG_EFI printf("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); #endif + + if (setjmp(&loaded_image_info.exit_jmp)) { + efi_status_t status = loaded_image_info.exit_status; + return status == EFI_SUCCESS ? 0 : -EINVAL; + } + return entry(&loaded_image_info, &systab); } -- cgit v1.2.3 From edcef3ba1d2d5beb92fcd7df253e196e77ba174d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 2 Jun 2016 11:38:27 +0200 Subject: efi_loader: Move to normal debug infrastructure We introduced special "DEBUG_EFI" defines when the efi loader support was new. After giving it a bit of thought, turns out we really didn't have to - the normal #define DEBUG infrastructure works well enough for efi loader as well. So this patch switches to the common debug() and #define DEBUG way of printing debug information. Signed-off-by: Alexander Graf --- cmd/bootefi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 2a62dce702b..216906527fe 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -206,9 +206,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt) #endif /* Call our payload! */ -#ifdef DEBUG_EFI - printf("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); -#endif + debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); if (setjmp(&loaded_image_info.exit_jmp)) { efi_status_t status = loaded_image_info.exit_status; -- cgit v1.2.3 From cddfc97d1fc892353d6616cd4287c34c454941e6 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Tue, 7 Jun 2016 08:55:40 +0200 Subject: ubi: add new ubi command "ubi detach" simple detachs ubi from the mtd partition. Signed-off-by: Heiko Schocher --- cmd/ubi.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'cmd') diff --git a/cmd/ubi.c b/cmd/ubi.c index 753a4dba3d7..4a92d840b6c 100644 --- a/cmd/ubi.c +++ b/cmd/ubi.c @@ -443,14 +443,8 @@ static int ubi_dev_scan(struct mtd_info *info, char *ubidev, return 0; } -int ubi_part(char *part_name, const char *vid_header_offset) +int ubi_detach(void) { - int err = 0; - char mtd_dev[16]; - struct mtd_device *dev; - struct part_info *part; - u8 pnum; - if (mtdparts_init() != 0) { printf("Error initializing mtdparts!\n"); return 1; @@ -466,17 +460,28 @@ int ubi_part(char *part_name, const char *vid_header_offset) cmd_ubifs_umount(); #endif - /* todo: get dev number for NAND... */ - ubi_dev.nr = 0; - /* * Call ubi_exit() before re-initializing the UBI subsystem */ if (ubi_initialized) { ubi_exit(); del_mtd_partitions(ubi_dev.mtd_info); + ubi_initialized = 0; } + ubi_dev.selected = 0; + return 0; +} + +int ubi_part(char *part_name, const char *vid_header_offset) +{ + int err = 0; + char mtd_dev[16]; + struct mtd_device *dev; + struct part_info *part; + u8 pnum; + + ubi_detach(); /* * Search the mtd device number where this partition * is located @@ -517,6 +522,15 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc < 2) return CMD_RET_USAGE; + + if (strcmp(argv[1], "detach") == 0) { + if (argc < 2) + return CMD_RET_USAGE; + + return ubi_detach(); + } + + if (strcmp(argv[1], "part") == 0) { const char *vid_header_offset = NULL; @@ -661,7 +675,9 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( ubi, 6, 1, do_ubi, "ubi commands", - "part [part] [offset]\n" + "detach" + " - detach ubi from a mtd partition\n" + "ubi part [part] [offset]\n" " - Show or set current partition (with optional VID" " header offset)\n" "ubi info [l[ayout]]" -- cgit v1.2.3