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 d89ddc32b0d..1d58462509c 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 44d1484d3d2..da6289b218d 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 c52f9451208..231612ff5f0 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 eb626dcac92..75d5dd944ff 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 c527617e434..61488daa3c3 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 cbc00a4e7c5..ac69d8312ee 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) | 
