From 8b5dea33584261cc5d600614970d1cbed6d99f91 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 3 Mar 2021 14:05:05 +0100 Subject: [PATCH 1/7] efi_loader: disable GRUB_ARM32_WORKAROUND on ARCH_SUNXI GRUB_ARM32_WORKAROUND can be disabled on ARCH_SUNXI as the Allwinner SoCs only have a level 2 cache controlled via CP15 and not an architecturally defined cache. Having the cache available speeds up booting Linux. On ARCH_BCM283X it is already disabled via rpi_2_defconfig. But let's move this setting to Kconfig. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index e729f727df1..634d3b1ff4e 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -281,7 +281,7 @@ config EFI_HAVE_RUNTIME_RESET config EFI_GRUB_ARM32_WORKAROUND bool "Workaround for GRUB on 32bit ARM" - default n if ARCH_QEMU + default n if ARCH_BCM283X || ARCH_SUNXI || ARCH_QEMU default y depends on ARM && !ARM64 help From 9ff9f4b4268946f3b73d9759766ccfcc599da004 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sun, 14 Mar 2021 20:04:24 +0100 Subject: [PATCH 2/7] efi_loader: fix memory type for memory reservation block The (yet unreleased version of the) devicetree specification clearly states that: As with the /reserved-memory node, when booting via UEFI entries in the Memory Reservation Block must also be listed in the system memory map obtained via the GetMemoryMap() toi protect against allocations by UEFI applications. The memory reservation block entries should be listed with type EfiReservedMemoryType. This restores the behaviour that was changed by commit 4cbb2930bd8c ("efi_loader: consider no-map property of reserved memory"). Fixes: 4cbb2930bd8c ("efi_loader: consider no-map property of reserved memory") Signed-off-by: Mark Kettenis Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_dt_fixup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c index a4529ee3ef2..b6fe5d2e5a3 100644 --- a/lib/efi_loader/efi_dt_fixup.c +++ b/lib/efi_loader/efi_dt_fixup.c @@ -61,7 +61,7 @@ void efi_carve_out_dt_rsv(void *fdt) for (i = 0; i < nr_rsv; i++) { if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) continue; - efi_reserve_memory(addr, size, false); + efi_reserve_memory(addr, size, true); } /* process reserved-memory */ From fbc6ceae6f0d97672d11bef8df406ea31c49c0fe Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 14 Mar 2021 10:12:01 +0100 Subject: [PATCH 3/7] efi_selftest: illegal cast to pointer in initrddump On 32bit systems u64 cannot directly be cast to void *. Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/initrddump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_selftest/initrddump.c b/lib/efi_selftest/initrddump.c index c23a05c718f..325951b4986 100644 --- a/lib/efi_selftest/initrddump.c +++ b/lib/efi_selftest/initrddump.c @@ -272,7 +272,7 @@ static efi_status_t get_initrd(void **initrd, efi_uintn_t *initrd_size) error(L"Out of memory\r\n"); return ret; } - *initrd = (void *)buffer; + *initrd = (void *)(uintptr_t)buffer; ret = load_file2_prot->load_file(load_file2_prot, dp, false, initrd_size, *initrd); if (ret != EFI_SUCCESS) { From ad09004ac472dedeb6e72f703035e76efa9810ca Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Feb 2021 14:27:01 -0700 Subject: [PATCH 4/7] mkeficapsule: Correct printf() strings Use %z when printing size_t values. This avoids errors on 32-bit machines. Signed-off-by: Simon Glass Use a conversion to size_t for printing stat.st_size. Reviewed-by: Heinrich Schuchardt Signed-off-by: Heinrich Schuchardt --- tools/mkeficapsule.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 1613e74ca73..f2725124515 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -278,7 +278,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, } data = malloc(bin_stat.st_size); if (!data) { - printf("cannot allocate memory: %lx\n", bin_stat.st_size); + printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size); goto err_1; } f = fopen(path, "w"); @@ -297,7 +297,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, size = fwrite(&header, 1, sizeof(header), f); if (size < sizeof(header)) { - printf("write failed (%lx)\n", size); + printf("write failed (%zx)\n", size); goto err_3; } @@ -306,13 +306,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, capsule.payload_item_count = 1; size = fwrite(&capsule, 1, sizeof(capsule), f); if (size < (sizeof(capsule))) { - printf("write failed (%lx)\n", size); + printf("write failed (%zx)\n", size); goto err_3; } offset = sizeof(capsule) + sizeof(u64); size = fwrite(&offset, 1, sizeof(offset), f); if (size < sizeof(offset)) { - printf("write failed (%lx)\n", size); + printf("write failed (%zx)\n", size); goto err_3; } @@ -329,17 +329,17 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, size = fwrite(&image, 1, sizeof(image), f); if (size < sizeof(image)) { - printf("write failed (%lx)\n", size); + printf("write failed (%zx)\n", size); goto err_3; } size = fread(data, 1, bin_stat.st_size, g); if (size < bin_stat.st_size) { - printf("read failed (%lx)\n", size); + printf("read failed (%zx)\n", size); goto err_3; } size = fwrite(data, 1, bin_stat.st_size, f); if (size < bin_stat.st_size) { - printf("write failed (%lx)\n", size); + printf("write failed (%zx)\n", size); goto err_3; } From d2ac8af95b690b490e1f336acc13037102c8828e Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Sat, 13 Mar 2021 23:47:32 +0200 Subject: [PATCH 5/7] efi_selftest: Remove loadfile2 for initrd selftests We are redefining how u-boot locates the initrd to load via the kernel LoadFile2 protocol. This selftest is not relevant any more, so remove it. A new one will be added later Signed-off-by: Ilias Apalodimas Reviewed-by: Heinrich Schuchardt Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/Makefile | 1 - lib/efi_selftest/efi_selftest_load_initrd.c | 221 -------------------- 2 files changed, 222 deletions(-) delete mode 100644 lib/efi_selftest/efi_selftest_load_initrd.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index b02fd56e0a7..50de581b776 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -61,7 +61,6 @@ obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_selftest_rng.o obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o -obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_selftest_load_initrd.o obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_selftest_tcg2.o ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) diff --git a/lib/efi_selftest/efi_selftest_load_initrd.c b/lib/efi_selftest/efi_selftest_load_initrd.c deleted file mode 100644 index f591dcd2115..00000000000 --- a/lib/efi_selftest/efi_selftest_load_initrd.c +++ /dev/null @@ -1,221 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * efi_selftest_load_initrd - * - * Copyright (c) 2020 Ilias Apalodimas - * - * This test checks the FileLoad2 protocol. - * A known file is read from the file system and verified. - * - * An example usage - given a file image with a file system in partition 1 - * holding file initrd - is: - * - * * Configure the sandbox with - * - * CONFIG_EFI_SELFTEST=y - * CONFIG_EFI_LOAD_FILE2_INITRD=y - * CONFIG_EFI_INITRD_FILESPEC="host 0:1 initrd" - * - * * Run ./u-boot and execute - * - * host bind 0 image - * setenv efi_selftest load initrd - * bootefi selftest - * - * This would provide a test output like: - * - * Testing EFI API implementation - * - * Selected test: 'load initrd' - * - * Setting up 'load initrd' - * Setting up 'load initrd' succeeded - * - * Executing 'load initrd' - * Loaded 12378613 bytes - * CRC32 2997478465 - * - * Now the size and CRC32 can be compared to the provided file. - */ - -#include -#include -#include - -static struct efi_boot_services *boottime; - -static struct efi_initrd_dp dp = { - .vendor = { - { - DEVICE_PATH_TYPE_MEDIA_DEVICE, - DEVICE_PATH_SUB_TYPE_VENDOR_PATH, - sizeof(dp.vendor), - }, - EFI_INITRD_MEDIA_GUID, - }, - .end = { - DEVICE_PATH_TYPE_END, - DEVICE_PATH_SUB_TYPE_END, - sizeof(dp.end), - } -}; - -static struct efi_initrd_dp dp_invalid = { - .vendor = { - { - DEVICE_PATH_TYPE_MEDIA_DEVICE, - DEVICE_PATH_SUB_TYPE_VENDOR_PATH, - sizeof(dp.vendor), - }, - EFI_INITRD_MEDIA_GUID, - }, - .end = { - 0x8f, /* invalid */ - 0xfe, /* invalid */ - sizeof(dp.end), - } -}; - -static int setup(const efi_handle_t handle, - const struct efi_system_table *systable) -{ - boottime = systable->boottime; - - return EFI_ST_SUCCESS; -} - -static int execute(void) -{ - struct efi_load_file_protocol *lf2; - struct efi_device_path *dp2, *dp2_invalid; - efi_status_t status; - efi_handle_t handle; - char buffer[64]; - efi_uintn_t buffer_size; - void *buf; - u32 crc32; - - memset(buffer, 0, sizeof(buffer)); - - dp2 = (struct efi_device_path *)&dp; - status = boottime->locate_device_path(&efi_guid_load_file2_protocol, - &dp2, &handle); - if (status != EFI_SUCCESS) { - efi_st_error("Unable to locate device path\n"); - return EFI_ST_FAILURE; - } - - status = boottime->handle_protocol(handle, - &efi_guid_load_file2_protocol, - (void **)&lf2); - if (status != EFI_SUCCESS) { - efi_st_error("Unable to locate protocol\n"); - return EFI_ST_FAILURE; - } - - /* Case 1: - * buffer_size can't be NULL - * protocol can't be NULL - */ - status = lf2->load_file(lf2, dp2, false, NULL, &buffer); - if (status != EFI_INVALID_PARAMETER) { - efi_st_error("Buffer size can't be NULL\n"); - return EFI_ST_FAILURE; - } - buffer_size = sizeof(buffer); - status = lf2->load_file(NULL, dp2, false, &buffer_size, &buffer); - if (status != EFI_INVALID_PARAMETER) { - efi_st_error("Protocol can't be NULL\n"); - return EFI_ST_FAILURE; - } - - /* - * Case 2: Match end node type/sub-type on device path - */ - dp2_invalid = (struct efi_device_path *)&dp_invalid; - buffer_size = sizeof(buffer); - status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer); - if (status != EFI_INVALID_PARAMETER) { - efi_st_error("Invalid device path type must return EFI_INVALID_PARAMETER\n"); - return EFI_ST_FAILURE; - } - - status = lf2->load_file(lf2, dp2_invalid, false, &buffer_size, &buffer); - if (status != EFI_INVALID_PARAMETER) { - efi_st_error("Invalid device path sub-type must return EFI_INVALID_PARAMETER\n"); - return EFI_ST_FAILURE; - } - - /* - * Case 3: - * BootPolicy 'true' must return EFI_UNSUPPORTED - */ - buffer_size = sizeof(buffer); - status = lf2->load_file(lf2, dp2, true, &buffer_size, &buffer); - if (status != EFI_UNSUPPORTED) { - efi_st_error("BootPolicy true must return EFI_UNSUPPORTED\n"); - return EFI_ST_FAILURE; - } - - /* - * Case: Pass buffer size as zero, firmware must return - * EFI_BUFFER_TOO_SMALL and an appropriate size - */ - buffer_size = 0; - status = lf2->load_file(lf2, dp2, false, &buffer_size, NULL); - if (status != EFI_BUFFER_TOO_SMALL || !buffer_size) { - efi_st_printf("buffer_size: %u\n", (unsigned int)buffer_size); - efi_st_printf("status: %x\n", (unsigned int)status); - efi_st_error("Buffer size not updated\n"); - return EFI_ST_FAILURE; - } - - /* - * Case: Pass buffer size as smaller than the file_size, - * firmware must return * EFI_BUFFER_TOO_SMALL and an appropriate size - */ - buffer_size = 1; - status = lf2->load_file(lf2, dp2, false, &buffer_size, &buffer); - if (status != EFI_BUFFER_TOO_SMALL || buffer_size <= 1) { - efi_st_error("Buffer size not updated\n"); - return EFI_ST_FAILURE; - } - - status = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size, - &buf); - if (status != EFI_SUCCESS) { - efi_st_error("Cannot allocate buffer\n"); - return EFI_ST_FAILURE; - } - - /* Case: Pass correct buffer, load the file and verify checksum*/ - status = lf2->load_file(lf2, dp2, false, &buffer_size, buf); - if (status != EFI_SUCCESS) { - efi_st_error("Loading initrd failed\n"); - return EFI_ST_FAILURE; - } - - efi_st_printf("Loaded %u bytes\n", (unsigned int)buffer_size); - status = boottime->calculate_crc32(buf, buffer_size, &crc32); - if (status != EFI_SUCCESS) { - efi_st_error("Could not determine CRC32\n"); - return EFI_ST_FAILURE; - } - efi_st_printf("CRC32 %.8x\n", (unsigned int)crc32); - - status = boottime->free_pool(buf); - if (status != EFI_SUCCESS) { - efi_st_error("Cannot free buffer\n"); - return EFI_ST_FAILURE; - } - - return EFI_ST_SUCCESS; -} - -EFI_UNIT_TEST(load_initrd) = { - .name = "load initrd", - .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, - .setup = setup, - .execute = execute, - .on_request = true, -}; From 64d809b4cbecd2d767b1c51d1107e40d25fd174e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 7 Feb 2021 14:27:02 -0700 Subject: [PATCH 6/7] efi: Fix compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This occur when building on Raspberry Pi 400 (32-bit ARM). Fix them. Examples: cmd/efidebug.c: In function ‘do_efi_capsule_update’: cmd/efidebug.c:75:49: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL)); ^ include/efi_loader.h:104:9: note: in definition of macro ‘EFI_CALL’ typeof(exp) _r = exp; \ ^~~ cmd/efidebug.c:75:49: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL)); ^ include/efi_loader.h:104:19: note: in definition of macro ‘EFI_CALL’ typeof(exp) _r = exp; \ ^~~ In file included from include/common.h:20, from lib/efi_loader/efi_capsule.c:9: lib/efi_loader/efi_capsule.c: In function ‘efi_update_capsule’: include/efi_loader.h:83:8: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 10 has type ‘size_t’ {aka ‘unsigned int’} [-Wformat=] debug("%sEFI: Entry %s(" format ")\n", __efi_nesting_inc(), \ ^~~~~~~~~~~~~~~~~~ include/linux/printk.h:37:21: note: in definition of macro ‘pr_fmt’ #define pr_fmt(fmt) fmt ^~~ include/log.h:229:2: note: in expansion of macro ‘log’ log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \ ^~~ include/log.h:249:2: note: in expansion of macro ‘debug_cond’ debug_cond(_DEBUG, fmt, ##args) ^~~~~~~~~~ include/efi_loader.h:83:2: note: in expansion of macro ‘debug’ debug("%sEFI: Entry %s(" format ")\n", __efi_nesting_inc(), \ ^~~~~ lib/efi_loader/efi_capsule.c:444:2: note: in expansion of macro ‘EFI_ENTRY’ EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count, ^~~~~~~~~ lib/efi_loader/efi_capsule.c:444:19: note: format string is defined here EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count, ~~^ %u Signed-off-by: Simon Glass Replace (uintptr_t)NULL by 0. Reviewed-by: Heinrich Schuchardt --- cmd/efidebug.c | 2 +- lib/efi_loader/efi_capsule.c | 4 ++-- lib/efi_loader/efi_firmware.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index e4030f514a6..55c7abe3d07 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -72,7 +72,7 @@ static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag, capsule->capsule_image_size); } - ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL)); + ret = EFI_CALL(RT->update_capsule(&capsule, 1, 0)); if (ret) { printf("Cannot handle a capsule at %p", capsule); return CMD_RET_FAILURE; diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index b57f0302c59..7ba1ced0a08 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -449,7 +449,7 @@ efi_status_t EFIAPI efi_update_capsule( unsigned int i; efi_status_t ret; - EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count, + EFI_ENTRY("%p, %zu, %llu\n", capsule_header_array, capsule_count, scatter_gather_list); if (!capsule_count) { @@ -509,7 +509,7 @@ efi_status_t EFIAPI efi_query_capsule_caps( unsigned int i; efi_status_t ret; - EFI_ENTRY("%p, %lu, %p, %p\n", capsule_header_array, capsule_count, + EFI_ENTRY("%p, %zu, %p, %p\n", capsule_header_array, capsule_count, maximum_capsule_size, reset_type); if (!maximum_capsule_size) { diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 5e401bbca2b..7a3cca27936 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -299,7 +299,7 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( efi_status_t (*progress)(efi_uintn_t completion), u16 **abort_reason) { - EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image, + EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image, image_size, vendor_code, progress, abort_reason); if (!image || image_index != 1) @@ -414,7 +414,7 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( efi_status_t status; efi_uintn_t capsule_payload_size; - EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image, + EFI_ENTRY("%p %d %p %zd %p %p %p\n", this, image_index, image, image_size, vendor_code, progress, abort_reason); if (!image) From 75d48d11db2e2f07659abbbf2dc0483e929b3fc2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 5 Mar 2021 12:58:37 +0100 Subject: [PATCH 7/7] doc: move README.dfu to HTML documentation Move README.dfu to doc/usage/dfu.rst and convert to reStructured text. In the long run this page should be split into two. One for the overview and one for the dfu command. UEFI capsule updates and dfutftp should be integrated into the overview page. Signed-off-by: Heinrich Schuchardt --- MAINTAINERS | 1 + doc/README.dfu | 311 ---------------------------------- doc/usage/dfu.rst | 404 ++++++++++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + 4 files changed, 406 insertions(+), 311 deletions(-) delete mode 100644 doc/README.dfu create mode 100644 doc/usage/dfu.rst diff --git a/MAINTAINERS b/MAINTAINERS index de499940e57..c6dd9bf838d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -670,6 +670,7 @@ F: common/dfu.c F: common/update.c F: common/usb_storage.c F: doc/api/dfu.rst +F: doc/usage/dfu.rst F: drivers/dfu/ F: drivers/usb/gadget/ F: include/dfu.h diff --git a/doc/README.dfu b/doc/README.dfu deleted file mode 100644 index eacd5bbfb41..00000000000 --- a/doc/README.dfu +++ /dev/null @@ -1,311 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ - -Device Firmware Upgrade (DFU) - -Overview: - - The Device Firmware Upgrade (DFU) allows to download and upload firmware - to/from U-Boot connected over USB. - - U-boot follows the Universal Serial Bus Device Class Specification for - Device Firmware Upgrade Version 1.1 the USB forum (DFU v1.1 in www.usb.org). - - U-Boot implements this DFU capability (CONFIG_DFU) with the command dfu - (cmd/dfu.c / CONFIG_CMD_DFU) based on: - - the DFU stack (common/dfu.c and common/spl/spl_dfu.c), based on the - USB DFU download gadget (drivers/usb/gadget/f_dfu.c) - - The access to mediums is done in DFU backends (driver/dfu) - - Today the supported DFU backends are: - - MMC (RAW or FAT / EXT2 / EXT3 / EXT4 file system / SKIP / SCRIPT) - - NAND - - RAM - - SF (serial flash) - - MTD (all MTD device: NAND, SPI-NOR, SPI-NAND,...) - - virtual - - These DFU backends are also used by - - the dfutftp (see README.dfutftp) - - the thordown command (cmd/thordown.c and gadget/f_thor.c) - - The "virtual" backend is a generic DFU backend to support a board specific - target (for example OTP), only based on the weak functions: - - dfu_write_medium_virt - - dfu_get_medium_size_virt - - dfu_read_medium_virt - -Configuration Options: - CONFIG_DFU - CONFIG_DFU_OVER_USB - CONFIG_DFU_MMC - CONFIG_DFU_MTD - CONFIG_DFU_NAND - CONFIG_DFU_RAM - CONFIG_DFU_SF - CONFIG_DFU_SF_PART - CONFIG_DFU_TIMEOUT - CONFIG_DFU_VIRTUAL - CONFIG_CMD_DFU - -Environment variables: - the dfu command uses 3 environments variables: - "dfu_alt_info" : the DFU setting for the USB download gadget with a semicolon - separated string of information on each alternate: - dfu_alt_info=";;....;" - - when several devices are used, the format is: - - '='alternate list (';' separated) - - each interface is separated by '&' - dfu_alt_info=\ - " =;....;&"\ - " =;....;&"\ - ...\ - " =;....;&" - - "dfu_bufsiz" : size of the DFU buffer, when absent, use - CONFIG_SYS_DFU_DATA_BUF_SIZE (8 MiB by default) - - "dfu_hash_algo" : name of the hash algorithm to use - -Commands: - dfu [ ] list - list the alternate device defined in "dfu_alt_info" - - dfu [ ] [] - start the dfu stack on the USB instance with the selected medium - backend and use the "dfu_alt_info" variable to configure the - alternate setting and link each one with the medium - The dfu command continue until receive a ^C in console or - a DFU detach transaction from HOST. If CONFIG_DFU_TIMEOUT option - is enabled and parameter is present in the command line, - the DFU operation will be aborted automatically after - seconds of waiting remote to initiate DFU session. - - The possible values of are : - (with = 0 in the dfu command example) - - "mmc" (for eMMC and SD card) - cmd: dfu 0 mmc - each element in "dfu_alt_info" = - raw [mmcpart ] raw access to mmc device - part [mmcpart ] raw access to partition - fat [mmcpart ] file in FAT partition - ext4 [mmcpart ] file in EXT4 partition - skip 0 0 ignore flashed data - script 0 0 execute commands in shell - - with being the GPT or DOS partition index, - with being the eMMC hardware partition number. - - A value of environment variable dfu_alt_info for eMMC could be: - - "u-boot raw 0x3e 0x800 mmcpart 1;bl2 raw 0x1e 0x1d mmcpart 1" - - A value of environment variable dfu_alt_info for SD card could be: - - "u-boot raw 0x80 0x800;uImage ext4 0 2" - - If don't want to flash given image file to storage, use "skip" type - entity. - - It can be used to protect flashing wrong image for the specific board. - - Especailly, this layout will be useful when thor protocol is used, - which performs flashing in batch mode, where more than one file is - processed. - For example, if one makes a single tar file with support for the two - boards with u-boot-.bin and u-boot-.bin files, one - can use it to flash a proper u-boot image on both without a failure: - - "u-boot-.bin raw 0x80 0x800; u-boot-.bin skip 0 0" - - When flashing new system image requires do some more complex things - than just writing data to the storage medium, one can use 'script' - type. Data written to such entity will be executed as a command list - in the u-boot's shell. This for example allows to re-create partition - layout and even set new dfu_alt_info for the newly created paritions. - Such script would look like: - --->8--- - setenv dfu_alt_info ... - setenv mbr_parts ... - mbr write ... - --->8--- - Please note that this means that user will be able to execute any - arbitrary commands just like in the u-boot's shell. - - "nand" (raw slc nand device) - cmd: dfu 0 nand - each element in "dfu_alt_info" = - raw raw access to mmc device - part raw acces to partition - partubi raw acces to ubi partition - - with is the MTD partition index - - "ram" - cmd: dfu 0 ram - ( is not used for RAM target) - each element in "dfu_alt_info" = - ram raw access to ram - - "sf" (serial flash : NOR) - cmd: dfu 0 sf - each element in "dfu_alt_info" = - raw raw access to sf device - part raw acces to partition - partubi raw acces to ubi partition - - with is the MTD partition index - - "mtd" (all MTD device: NAND, SPI-NOR, SPI-NAND,...) - cmd: dfu 0 mtd - with the mtd identifier as defined in mtd command - (nand0, nor0, spi-nand0,...) - each element in "dfu_alt_info" = - raw raw access to mtd device - part raw acces to partition - partubi raw acces to ubi partition - - with is the MTD partition index - - "virt" - cmd: dfu 0 virt - each element in "dfu_alt_info" = - - - and are absent: - the dfu command to use multiple devices - cmd: dfu 0 list - cmd: dfu 0 - "dfu_alt_info" variable provides the list of with - alternate list separated by '&' with the same format for each - mmc =;....; - nand =;....; - ram =;....; - sf =;....; - mtd =;....; - virt =;....; - -Callbacks: - The weak callback functions can be implemented to manage specific behavior - - dfu_initiated_callback : called when the DFU transaction is started, - used to initiase the device - - dfu_flush_callback : called at the end of the DFU write after DFU - manifestation, used to manage the device when - DFU transaction is closed - -Host tools: - When U-Boot runs the dfu stack, the DFU host tools can be used - to send/receive firmwares on each configurated alternate. - - For example dfu-util is a host side implementation of the DFU 1.1 - specifications(http://dfu-util.sourceforge.net/) which works with U-Boot. - -Usage: - Example 1: firmware located in eMMC or SD card, with: - - alternate 1 (alt=1) for SPL partition (GPT partition 1) - - alternate 2 (alt=2) for U-Boot partition (GPT partition 2) - - The U-Boot configuration is: - - U-Boot> env set dfu_alt_info "spl part 0 1;u-boot part 0 2" - - U-Boot> dfu 0 mmc 0 list - DFU alt settings list: - dev: eMMC alt: 0 name: spl layout: RAW_ADDR - dev: eMMC alt: 1 name: u-boot layout: RAW_ADDR - - Boot> dfu 0 mmc 0 - - On the Host side: - - list the available alternate setting: - - $> dfu-util -l - dfu-util 0.9 - - Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. - Copyright 2010-2016 Tormod Volden and Stefan Schmidt - This program is Free Software and has ABSOLUTELY NO WARRANTY - Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ - - Found DFU: [0483:5720] ver=0200, devnum=45, cfg=1, intf=0, path="3-1.3.1", \ - alt=1, name="u-boot", serial="003A00203438510D36383238" - Found DFU: [0483:5720] ver=0200, devnum=45, cfg=1, intf=0, path="3-1.3.1", \ - alt=0, name="spl", serial="003A00203438510D36383238" - - To download to U-Boot, use -D option - - $> dfu-util -a 0 -D u-boot-spl.bin - $> dfu-util -a 1 -D u-boot.bin - - To upload from U-Boot, use -U option - - $> dfu-util -a 0 -U u-boot-spl.bin - $> dfu-util -a 1 -U u-boot.bin - - To request a DFU detach and reset the USB connection: - $> dfu-util -a 0 -e -R - - - Example 2: firmware located in NOR (sf) and NAND, with: - - alternate 1 (alt=1) for SPL partition (NOR GPT partition 1) - - alternate 2 (alt=2) for U-Boot partition (NOR GPT partition 2) - - alternate 3 (alt=3) for U-Boot-env partition (NOR GPT partition 3) - - alternate 4 (alt=4) for UBI partition (NAND GPT partition 1) - - U-Boot> env set dfu_alt_info \ - "sf 0:0:10000000:0=spl part 0 1;u-boot part 0 2; \ - u-boot-env part 0 3&nand 0=UBI partubi 0,1" - - U-Boot> dfu 0 list - - DFU alt settings list: - dev: SF alt: 0 name: spl layout: RAW_ADDR - dev: SF alt: 1 name: ssbl layout: RAW_ADDR - dev: SF alt: 2 name: u-boot-env layout: RAW_ADDR - dev: NAND alt: 3 name: UBI layout: RAW_ADDR - - U-Boot> dfu 0 - - $> dfu-util -l - Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ - intf=0, alt=3, name="UBI", serial="002700333338511934383330" - Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ - intf=0, alt=2, name="u-boot-env", serial="002700333338511934383330" - Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ - intf=0, alt=1, name="u-boot", serial="002700333338511934383330" - Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ - intf=0, alt=0, name="spl", serial="002700333338511934383330" - - Same example with MTD backend - - U-Boot> env set dfu_alt_info \ - "mtd nor0=spl part 1;u-boot part 2;u-boot-env part 3&"\ - "mtd nand0=UBI partubi 1" - - U-Boot> dfu 0 list - using id 'nor0,0' - using id 'nor0,1' - using id 'nor0,2' - using id 'nand0,0' - DFU alt settings list: - dev: MTD alt: 0 name: spl layout: RAW_ADDR - dev: MTD alt: 1 name: u-boot layout: RAW_ADDR - dev: MTD alt: 2 name: u-boot-env layout: RAW_ADDR - dev: MTD alt: 3 name: UBI layout: RAW_ADDR - - Example 3: firmware located in SD Card (mmc) and virtual partition on - OTP and PMIC not volatile memory - - alternate 1 (alt=1) for scard - - alternate 2 (alt=2) for OTP (virtual) - - alternate 3 (alt=3) for PMIC NVM (virtual) - - U-Boot> env set dfu_alt_info \ - "mmc 0=sdcard raw 0 0x100000&"\ - "virt 0=otp" \ - "virt 1=pmic" - - U-Boot> dfu 0 list - DFU alt settings list: - dev: eMMC alt: 0 name: sdcard layout: RAW_ADDR - dev: VIRT alt: 1 name: otp layout: RAW_ADDR - dev: VIRT alt: 2 name: pmic layout: RAW_ADDR diff --git a/doc/usage/dfu.rst b/doc/usage/dfu.rst new file mode 100644 index 00000000000..11c88072b89 --- /dev/null +++ b/doc/usage/dfu.rst @@ -0,0 +1,404 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Device Firmware Upgrade (DFU) +============================= + +Overview +-------- + +The Device Firmware Upgrade (DFU) allows to download and upload firmware +to/from U-Boot connected over USB. + +U-boot follows the Universal Serial Bus Device Class Specification for +Device Firmware Upgrade Version 1.1 the USB forum (DFU v1.1 in www.usb.org). + +U-Boot implements this DFU capability (CONFIG_DFU) with the command dfu +(cmd/dfu.c / CONFIG_CMD_DFU) based on: + +- the DFU stack (common/dfu.c and common/spl/spl_dfu.c), based on the + USB DFU download gadget (drivers/usb/gadget/f_dfu.c) +- The access to mediums is done in DFU backends (driver/dfu) + +Today the supported DFU backends are: + +- MMC (RAW or FAT / EXT2 / EXT3 / EXT4 file system / SKIP / SCRIPT) +- NAND +- RAM +- SF (serial flash) +- MTD (all MTD device: NAND, SPI-NOR, SPI-NAND,...) +- virtual + +These DFU backends are also used by + +- the dfutftp (see README.dfutftp) +- the thordown command (cmd/thordown.c and gadget/f_thor.c) + +The "virtual" backend is a generic DFU backend to support a board specific +target (for example OTP), only based on the weak functions: + +- dfu_write_medium_virt +- dfu_get_medium_size_virt +- dfu_read_medium_virt + +Configuration Options +--------------------- + +The following configuration option are relevant for device firmware upgrade: + +* CONFIG_DFU +* CONFIG_DFU_OVER_USB +* CONFIG_DFU_MMC +* CONFIG_DFU_MTD +* CONFIG_DFU_NAND +* CONFIG_DFU_RAM +* CONFIG_DFU_SF +* CONFIG_DFU_SF_PART +* CONFIG_DFU_TIMEOUT +* CONFIG_DFU_VIRTUAL +* CONFIG_CMD_DFU + +Environment variables +--------------------- + +The dfu command uses 3 environments variables: + +dfu_alt_info + The DFU setting for the USB download gadget with a semicolon separated + string of information on each alternate:: + + dfu_alt_info=";;....;" + + When several devices are used, the format is: + + - '='alternate list (';' separated) + - each interface is separated by '&':: + + dfu_alt_info=\ + " =;....;&"\ + " =;....;&"\ + ...\ + " =;....;&" + +dfu_bufsiz + size of the DFU buffer, when absent, defaults to + CONFIG_SYS_DFU_DATA_BUF_SIZE (8 MiB by default) + +dfu_hash_algo + name of the hash algorithm to use + +Commands +-------- + +dfu [ ] list + list the alternate device defined in *dfu_alt_info* + +dfu [ ] [] + start the dfu stack on the USB instance with the selected medium + backend and use the *dfu_alt_info* variable to configure the + alternate setting and link each one with the medium + The dfu command continue until receive a ^C in console or + a DFU detach transaction from HOST. If CONFIG_DFU_TIMEOUT option + is enabled and parameter is present in the command line, + the DFU operation will be aborted automatically after + seconds of waiting remote to initiate DFU session. + +The possible values of are (with = 0 in the dfu +command example) + +mmc + for eMMC and SD card:: + + dfu 0 mmc + + each element in *dfu_alt_info* being + + * raw [mmcpart ] raw access to mmc device + * part [mmcpart ] raw access to partition + * fat [mmcpart ] file in FAT partition + * ext4 [mmcpart ] file in EXT4 partition + * skip 0 0 ignore flashed data + * script 0 0 execute commands in shell + + with + + partid + being the GPT or DOS partition index, + num + being the eMMC hardware partition number. + + A value of environment variable *dfu_alt_info* for eMMC could be:: + + u-boot raw 0x3e 0x800 mmcpart 1;bl2 raw 0x1e 0x1d mmcpart 1 + + A value of environment variable *dfu_alt_info* for SD card could be:: + + u-boot raw 0x80 0x800;uImage ext4 0 2 + + If don't want to flash given image file to storage, use "skip" type + entity. + + - It can be used to protect flashing wrong image for the specific board. + - Especailly, this layout will be useful when thor protocol is used, + which performs flashing in batch mode, where more than one file is + processed. + + For example, if one makes a single tar file with support for the two + boards with u-boot-.bin and u-boot-.bin files, one + can use it to flash a proper u-boot image on both without a failure:: + + u-boot-.bin raw 0x80 0x800; u-boot-.bin skip 0 0 + + When flashing new system image requires do some more complex things + than just writing data to the storage medium, one can use 'script' + type. Data written to such entity will be executed as a command list + in the u-boot's shell. This for example allows to re-create partition + layout and even set new *dfu_alt_info* for the newly created paritions. + Such script would look like:: + + setenv dfu_alt_info ... + setenv mbr_parts ... + mbr write ... + + Please note that this means that user will be able to execute any + arbitrary commands just like in the u-boot's shell. + +nand + raw slc nand device:: + + dfu 0 nand + + each element in *dfu_alt_info* being either of + + * raw raw access to mmc device + * part raw acces to partition + * partubi raw acces to ubi partition + + with + + partid + is the MTD partition index + +ram + raw access to ram:: + + dfu 0 ram + + dev + is not used for RAM target + + each element in *dfu_alt_info* being:: + + ram raw access to ram + +sf + serial flash : NOR:: + + cmd: dfu 0 sf + + each element in *dfu_alt_info* being either of: + + * raw raw access to sf device + * part raw acces to partition + * partubi raw acces to ubi partition + + with + + partid + is the MTD partition index + +mtd + all MTD device: NAND, SPI-NOR, SPI-NAND,...:: + + cmd: dfu 0 mtd + + with + + dev + the mtd identifier as defined in mtd command + (nand0, nor0, spi-nand0,...) + + each element in *dfu_alt_info* being either of: + + * raw forraw access to mtd device + * part for raw acces to partition + * partubi for raw acces to ubi partition + + with + + partid + is the MTD partition index + +virt + virtual flash back end for DFU + + :: + + cmd: dfu 0 virt + + each element in *dfu_alt_info* being: + + * + + and are absent, the dfu command to use multiple devices:: + + cmd: dfu 0 list + cmd: dfu 0 + +*dfu_alt_info* variable provides the list of with +alternate list separated by '&' with the same format for each :: + + mmc =;....; + nand =;....; + ram =;....; + sf =;....; + mtd =;....; + virt =;....; + +Callbacks +--------- + +The weak callback functions can be implemented to manage specific behavior + +dfu_initiated_callback + called when the DFU transaction is started, used to initiase the device + +dfu_flush_callback + called at the end of the DFU write after DFU manifestation, used to manage + the device when DFU transaction is closed + +Host tools +---------- + +When U-Boot runs the dfu stack, the DFU host tools can be used +to send/receive firmwares on each configurated alternate. + +For example dfu-util is a host side implementation of the DFU 1.1 +specifications(http://dfu-util.sourceforge.net/) which works with U-Boot. + +Usage +----- + +Example 1: firmware located in eMMC or SD card, with: + +- alternate 1 (alt=1) for SPL partition (GPT partition 1) +- alternate 2 (alt=2) for U-Boot partition (GPT partition 2) + +The U-Boot configuration is:: + + U-Boot> env set dfu_alt_info "spl part 0 1;u-boot part 0 2" + + U-Boot> dfu 0 mmc 0 list + DFU alt settings list: + dev: eMMC alt: 0 name: spl layout: RAW_ADDR + dev: eMMC alt: 1 name: u-boot layout: RAW_ADDR + + Boot> dfu 0 mmc 0 + +On the Host side: + +list the available alternate setting:: + + $> dfu-util -l + dfu-util 0.9 + + Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. + Copyright 2010-2016 Tormod Volden and Stefan Schmidt + This program is Free Software and has ABSOLUTELY NO WARRANTY + Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ + + Found DFU: [0483:5720] ver=0200, devnum=45, cfg=1, intf=0, path="3-1.3.1", \ + alt=1, name="u-boot", serial="003A00203438510D36383238" + Found DFU: [0483:5720] ver=0200, devnum=45, cfg=1, intf=0, path="3-1.3.1", \ + alt=0, name="spl", serial="003A00203438510D36383238" + + To download to U-Boot, use -D option + + $> dfu-util -a 0 -D u-boot-spl.bin + $> dfu-util -a 1 -D u-boot.bin + + To upload from U-Boot, use -U option + + $> dfu-util -a 0 -U u-boot-spl.bin + $> dfu-util -a 1 -U u-boot.bin + + To request a DFU detach and reset the USB connection: + $> dfu-util -a 0 -e -R + + +Example 2: firmware located in NOR (sf) and NAND, with: + +- alternate 1 (alt=1) for SPL partition (NOR GPT partition 1) +- alternate 2 (alt=2) for U-Boot partition (NOR GPT partition 2) +- alternate 3 (alt=3) for U-Boot-env partition (NOR GPT partition 3) +- alternate 4 (alt=4) for UBI partition (NAND GPT partition 1) + +:: + + U-Boot> env set dfu_alt_info \ + "sf 0:0:10000000:0=spl part 0 1;u-boot part 0 2; \ + u-boot-env part 0 3&nand 0=UBI partubi 0,1" + + U-Boot> dfu 0 list + + DFU alt settings list: + dev: SF alt: 0 name: spl layout: RAW_ADDR + dev: SF alt: 1 name: ssbl layout: RAW_ADDR + dev: SF alt: 2 name: u-boot-env layout: RAW_ADDR + dev: NAND alt: 3 name: UBI layout: RAW_ADDR + + U-Boot> dfu 0 + +:: + + $> dfu-util -l + Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ + intf=0, alt=3, name="UBI", serial="002700333338511934383330" + Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ + intf=0, alt=2, name="u-boot-env", serial="002700333338511934383330" + Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ + intf=0, alt=1, name="u-boot", serial="002700333338511934383330" + Found DFU: [0483:5720] ver=9999, devnum=96, cfg=1,\ + intf=0, alt=0, name="spl", serial="002700333338511934383330" + +Same example with MTD backend + +:: + + U-Boot> env set dfu_alt_info \ + "mtd nor0=spl part 1;u-boot part 2;u-boot-env part 3&"\ + "mtd nand0=UBI partubi 1" + + U-Boot> dfu 0 list + using id 'nor0,0' + using id 'nor0,1' + using id 'nor0,2' + using id 'nand0,0' + DFU alt settings list: + dev: MTD alt: 0 name: spl layout: RAW_ADDR + dev: MTD alt: 1 name: u-boot layout: RAW_ADDR + dev: MTD alt: 2 name: u-boot-env layout: RAW_ADDR + dev: MTD alt: 3 name: UBI layout: RAW_ADDR + +Example 3 + +firmware located in SD Card (mmc) and virtual partition on OTP and PMIC not +volatile memory + +- alternate 1 (alt=1) for scard +- alternate 2 (alt=2) for OTP (virtual) +- alternate 3 (alt=3) for PMIC NVM (virtual) + +:: + + U-Boot> env set dfu_alt_info \ + "mmc 0=sdcard raw 0 0x100000&"\ + "virt 0=otp" \ + "virt 1=pmic" + +:: + + U-Boot> dfu 0 list + DFU alt settings list: + dev: eMMC alt: 0 name: sdcard layout: RAW_ADDR + dev: VIRT alt: 1 name: otp layout: RAW_ADDR + dev: VIRT alt: 2 name: pmic layout: RAW_ADDR diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 9169fff0be8..6c59bbadab4 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -4,6 +4,7 @@ Use U-Boot .. toctree:: :maxdepth: 1 + dfu fdt_overlays netconsole partitions