diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/bootm_os.c | 56 | ||||
-rw-r--r-- | common/dfu.c | 17 | ||||
-rw-r--r-- | common/image-fit.c | 3 | ||||
-rw-r--r-- | common/image.c | 1 | ||||
-rw-r--r-- | common/spl/Kconfig | 6 | ||||
-rw-r--r-- | common/spl/spl_fit.c | 151 |
6 files changed, 223 insertions, 11 deletions
diff --git a/common/bootm_os.c b/common/bootm_os.c index d89ddc32b0..1d58462509 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -7,10 +7,12 @@ #include <common.h> #include <bootm.h> #include <cpu_func.h> +#include <efi_loader.h> #include <env.h> #include <fdt_support.h> #include <linux/libfdt.h> #include <malloc.h> +#include <mapmem.h> #include <vxworks.h> #include <tee/optee.h> @@ -498,6 +500,57 @@ static int do_bootm_tee(int flag, int argc, char * const argv[], } #endif +#ifdef CONFIG_BOOTM_EFI +static int do_bootm_efi(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + int ret; + efi_status_t efi_ret; + void *image_buf; + + if (flag != BOOTM_STATE_OS_GO) + return 0; + + /* Locate FDT, if provided */ + ret = bootm_find_images(flag, argc, argv); + if (ret) + return ret; + + /* Initialize EFI drivers */ + efi_ret = efi_init_obj_list(); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to initialize UEFI sub-system: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Install device tree */ + efi_ret = efi_install_fdt(images->ft_len + ? images->ft_addr : EFI_FDT_USE_INTERNAL); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to install device tree: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Run EFI image */ + printf("## Transferring control to EFI (at address %08lx) ...\n", + images->ep); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + image_buf = map_sysmem(images->ep, images->os.image_len); + + efi_ret = efi_run_image(image_buf, images->os.image_len); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to run EFI image: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + return 0; +} +#endif + static boot_os_fn *boot_os[] = { [IH_OS_U_BOOT] = do_bootm_standalone, #ifdef CONFIG_BOOTM_LINUX @@ -534,6 +587,9 @@ static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_OPTEE [IH_OS_TEE] = do_bootm_tee, #endif +#ifdef CONFIG_BOOTM_EFI + [IH_OS_EFI] = do_bootm_efi, +#endif }; /* Allow for arch specific config before we boot */ diff --git a/common/dfu.c b/common/dfu.c index 44d1484d3d..da6289b218 100644 --- a/common/dfu.c +++ b/common/dfu.c @@ -35,6 +35,10 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) return CMD_RET_FAILURE; } +#ifdef CONFIG_DFU_TIMEOUT + unsigned long start_time = get_timer(0); +#endif + while (1) { if (g_dnl_detach()) { /* @@ -79,6 +83,19 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) } } +#ifdef CONFIG_DFU_TIMEOUT + unsigned long wait_time = dfu_get_timeout(); + + if (wait_time) { + unsigned long current_time = get_timer(start_time); + + if (current_time > wait_time) { + debug("Inactivity timeout, abort DFU\n"); + goto exit; + } + } +#endif + WATCHDOG_RESET(); usb_gadget_handle_interrupts(usbctrl_index); } diff --git a/common/image-fit.c b/common/image-fit.c index c52f945120..231612ff5f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1926,7 +1926,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, image_type == IH_TYPE_FPGA || fit_image_check_os(fit, noffset, IH_OS_LINUX) || fit_image_check_os(fit, noffset, IH_OS_U_BOOT) || - fit_image_check_os(fit, noffset, IH_OS_OPENRTOS); + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI); /* * If either of the checks fail, we should report an error, but diff --git a/common/image.c b/common/image.c index eb626dcac9..75d5dd944f 100644 --- a/common/image.c +++ b/common/image.c @@ -137,6 +137,7 @@ static const table_entry_t uimage_os[] = { { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, #endif { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, + { IH_OS_EFI, "efi", "EFI Firmware" }, { -1, "", "", }, }; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index c527617e43..61488daa3c 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -731,6 +731,12 @@ config SPL_UBI README.ubispl for more info. if SPL_DM +config SPL_CACHE + depends on CACHE + bool "Support cache drivers in SPL" + help + Enable support for cache drivers in SPL. + config SPL_DM_SPI bool "Support SPI DM drivers in SPL" help diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index cbc00a4e7c..ac69d8312e 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -6,14 +6,20 @@ #include <common.h> #include <errno.h> +#include <board.h> #include <fpga.h> #include <gzip.h> #include <image.h> -#include <linux/libfdt.h> +#include <malloc.h> #include <spl.h> +#include <linux/libfdt.h> DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ +#define CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ (64 * 1024) +#endif + #ifndef CONFIG_SYS_BOOTM_LEN #define CONFIG_SYS_BOOTM_LEN (64 << 20) #endif @@ -27,6 +33,29 @@ __weak ulong board_spl_fit_size_align(ulong size) return size; } +static int find_node_from_desc(const void *fit, int node, const char *str) +{ + int child; + + if (node < 0) + return -EINVAL; + + /* iterate the FIT nodes and find a matching description */ + for (child = fdt_first_subnode(fit, node); child >= 0; + child = fdt_next_subnode(fit, child)) { + int len; + const char *desc = fdt_getprop(fit, child, "description", &len); + + if (!desc) + continue; + + if (!strcmp(desc, str)) + return child; + } + + return -ENOENT; +} + /** * spl_fit_get_image_name(): By using the matching configuration subnode, * retrieve the name of an image, specified by a property name and an index @@ -41,12 +70,14 @@ __weak ulong board_spl_fit_size_align(ulong size) */ static int spl_fit_get_image_name(const void *fit, int images, const char *type, int index, - char **outname) + const char **outname) { + struct udevice *board; const char *name, *str; __maybe_unused int node; int conf_node; int len, i; + bool found = true; conf_node = fit_find_config_node(fit); if (conf_node < 0) { @@ -72,12 +103,45 @@ static int spl_fit_get_image_name(const void *fit, int images, for (i = 0; i < index; i++) { str = strchr(str, '\0') + 1; if (!str || (str - name >= len)) { - debug("no string for index %d\n", index); - return -E2BIG; + found = false; + break; } } - *outname = (char *)str; + if (!found && !board_get(&board)) { + int rc; + /* + * no string in the property for this index. Check if the board + * level code can supply one. + */ + rc = board_get_fit_loadable(board, index - i - 1, type, &str); + if (rc && rc != -ENOENT) + return rc; + + if (!rc) { + /* + * The board provided a name for a loadable. + * Try to match it against the description properties + * first. If no matching node is found, use it as a + * node name. + */ + int node; + int images = fdt_path_offset(fit, FIT_IMAGES_PATH); + + node = find_node_from_desc(fit, images, str); + if (node > 0) + str = fdt_get_name(fit, node, NULL); + + found = true; + } + } + + if (!found) { + debug("no string for index %d\n", index); + return -E2BIG; + } + + *outname = str; return 0; } @@ -96,7 +160,7 @@ static int spl_fit_get_image_name(const void *fit, int images, static int spl_fit_get_image_node(const void *fit, int images, const char *type, int index) { - char *str; + const char *str; int err; int node; @@ -108,7 +172,7 @@ static int spl_fit_get_image_node(const void *fit, int images, node = fdt_subnode_offset(fit, images, str); if (node < 0) { - debug("cannot find image node '%s': %d\n", str, node); + pr_err("cannot find image node '%s': %d\n", str, node); return -EINVAL; } @@ -281,7 +345,7 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, void *fit, int images, ulong base_offset) { struct spl_image_info image_info; - int node, ret = 0; + int node, ret = 0, index = 0; /* * Use the address following the image as target address for the @@ -290,7 +354,7 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, image_info.load_addr = spl_image->load_addr + spl_image->size; /* Figure out which device tree the board wants to use */ - node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0); + node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, index++); if (node < 0) { debug("%s: cannot find FDT node\n", __func__); @@ -313,8 +377,65 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, /* Make the load-address of the FDT available for the SPL framework */ spl_image->fdt_addr = (void *)image_info.load_addr; #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY) + if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) { + void *tmpbuffer = NULL; + + for (; ; index++) { + node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, + index); + if (node == -E2BIG) { + debug("%s: No additional FDT node\n", __func__); + break; + } else if (node < 0) { + debug("%s: unable to find FDT node %d\n", + __func__, index); + continue; + } + + if (!tmpbuffer) { + /* + * allocate memory to store the DT overlay + * before it is applied. It may not be used + * depending on how the overlay is stored, so + * don't fail yet if the allocation failed. + */ + tmpbuffer = malloc(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ); + if (!tmpbuffer) + debug("%s: unable to allocate space for overlays\n", + __func__); + } + image_info.load_addr = (ulong)tmpbuffer; + ret = spl_load_fit_image(info, sector, fit, base_offset, + node, &image_info); + if (ret < 0) + break; + + /* Make room in FDT for changes from the overlay */ + ret = fdt_increase_size(spl_image->fdt_addr, + image_info.size); + if (ret < 0) + break; + + ret = fdt_overlay_apply_verbose(spl_image->fdt_addr, + (void *)image_info.load_addr); + if (ret) { + pr_err("failed to apply DT overlay %s\n", + fit_get_name(fit, node, NULL)); + break; + } + + debug("%s: DT overlay %s applied\n", __func__, + fit_get_name(fit, node, NULL)); + } + if (tmpbuffer) + free(tmpbuffer); + if (ret) + return ret; + } /* Try to make space, so we can inject details on the loadables */ ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192); + if (ret < 0) + return ret; #endif return ret; @@ -325,7 +446,7 @@ static int spl_fit_record_loadable(const void *fit, int images, int index, { int ret = 0; #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY) - char *name; + const char *name; int node; ret = spl_fit_get_image_name(fit, images, "loadables", @@ -373,6 +494,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, int images, ret; int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1; int index = 0; + int firmware_node; /* * For FIT with external data, figure out where the external images @@ -502,6 +624,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, spl_fit_append_fdt(spl_image, info, sector, fit, images, base_offset); + firmware_node = node; /* Now check if there are more images for us to load */ for (; ; index++) { uint8_t os_type = IH_OS_INVALID; @@ -510,6 +633,14 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (node < 0) break; + /* + * if the firmware is also a loadable, skip it because + * it already has been loaded. This is typically the case with + * u-boot.img generated by mkimage. + */ + if (firmware_node == node) + continue; + ret = spl_load_fit_image(info, sector, fit, base_offset, node, &image_info); if (ret < 0) |