From 79e984c470f7a2bfa4d292214a985ec39185d935 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 17 Sep 2019 17:09:33 -0400 Subject: [PATCH 01/30] tools: dumpimage: Provide more feedback on internal errors The dumpimage utility errors out in a number of places without providing sufficient feedback to allow the user to easily determine what has gone wrong. Add additional error messages to make the cause of the failure more obvious. Signed-off-by: Andrew F. Davis Reviewed-by: Lokesh Vutla --- tools/dumpimage.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/dumpimage.c b/tools/dumpimage.c index ee3d41dda4..d5f893daf1 100644 --- a/tools/dumpimage.c +++ b/tools/dumpimage.c @@ -35,14 +35,23 @@ static int dumpimage_extract_subimage(struct image_type_params *tparams, if (tparams->verify_header) { retval = tparams->verify_header((unsigned char *)ptr, sbuf->st_size, ¶ms); - if (retval != 0) + if (retval != 0) { + fprintf(stderr, "%s: failed to verify header of %s\n", + params.cmdname, tparams->name); return -1; + } + /* * Extract the file from the image * if verify is successful */ if (tparams->extract_subimage) { retval = tparams->extract_subimage(ptr, ¶ms); + if (retval != 0) { + fprintf(stderr, "%s: extract_subimage failed for %s\n", + params.cmdname, tparams->name); + return -3; + } } else { fprintf(stderr, "%s: extract_subimage undefined for %s\n", @@ -175,6 +184,9 @@ int main(int argc, char **argv) * image type. Returns the error code if not matched */ retval = dumpimage_extract_subimage(tparams, ptr, &sbuf); + if (retval) + fprintf(stderr, "%s: Can't extract subimage from %s\n", + params.cmdname, params.imagefile); } else { /* * Print the image information for matched image type From e5b5628e8a3e4476509a025121315480ea7b79ca Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 17 Sep 2019 17:09:34 -0400 Subject: [PATCH 02/30] tools: fit_image: Use fit_image_get_data_and_size for getting offset/size This is very similar to fit_image_get_data but has the benefit of working on FIT images with external data unlike fit_image_get_data. This is useful for extracting sub-images from type of FIT image as this would previously just silently fail. Add an error message also so if this still fails it is easier to find out why. Signed-off-by: Andrew F. Davis Reviewed-by: Lokesh Vutla --- tools/fit_image.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/fit_image.c b/tools/fit_image.c index 0201cc44d8..114df5af30 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -741,9 +741,14 @@ static int fit_image_extract( { const void *file_data; size_t file_size = 0; + int ret; - /* get the "data" property of component at offset "image_noffset" */ - fit_image_get_data(fit, image_noffset, &file_data, &file_size); + /* get the data address and size of component at offset "image_noffset" */ + ret = fit_image_get_data_and_size(fit, image_noffset, &file_data, &file_size); + if (ret) { + fprintf(stderr, "Could not get component information\n"); + return ret; + } /* save the "file_data" into the file specified by "file_name" */ return imagetool_save_subimage(file_name, (ulong) file_data, file_size); From e3cd06be93e7e669a93d5786d131f421f346a925 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 17 Sep 2019 17:09:35 -0400 Subject: [PATCH 03/30] tools: dumpimage: Fall-though to print usage for help command This has the same result but some compilers will warn about this fall-through if there are statements as part of the label block. Signed-off-by: Andrew F. Davis Reviewed-by: Lokesh Vutla --- tools/dumpimage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/dumpimage.c b/tools/dumpimage.c index d5f893daf1..e5481435a7 100644 --- a/tools/dumpimage.c +++ b/tools/dumpimage.c @@ -104,7 +104,6 @@ int main(int argc, char **argv) printf("dumpimage version %s\n", PLAIN_VERSION); exit(EXIT_SUCCESS); case 'h': - usage(); default: usage(); break; From 6b8b98d54d8e74c8b4c6cfe431e88c90efcea72d Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:10 +0200 Subject: [PATCH 04/30] spl: fit: don't load the firmware twice When u-boot.img is a FIT image generated automatically by mkimage, the configuration node has the following structure: conf-1 { description = "k3-am654-base-board"; firmware = "firmware-1"; loadables = "firmware-1"; fdt = "fdt-1"; }; The firmware is referenced twice. Once by the 'firmware' property and once by the 'loadables' property. Currently this result in the firmware being loaded twice. This is not a big problem but has an impact on the boot time. Fixing it by not loading a loadable image if it is also the firmware image. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass Tested-by: Andreas Dannenberg --- common/spl/spl_fit.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index cbc00a4e7c..346f9edaa5 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -373,6 +373,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 +503,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 +512,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) From 9d13b8725481ee5651c6e881e5d336142b813b14 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 22 Oct 2019 16:39:11 +0200 Subject: [PATCH 05/30] spl: fit: Add support for applying DT overlay doc/uImage.FIT/overlay-fdt-boot.txt is describing how to create FIT image with DT overlays in it. Add support for this feature to SPL. Here is the ZynqMP fragment where dtb points to full DT and dtbo is overlay which should be applied on the top of dtb. config { description = "ATF with full u-boot overlay"; firmware = "atf"; loadables = "uboot"; fdt = "dtb", "dtbo"; }; The whole feature depends on OF_LIBFDT_OVERLAY which is adding +4kB code and 0 for platforms which are not enabling this feature. Signed-off-by: Michal Simek Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- Kconfig | 9 +++++++++ common/spl/spl_fit.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Kconfig b/Kconfig index 46a31f45b9..0edd4ec2b0 100644 --- a/Kconfig +++ b/Kconfig @@ -444,6 +444,15 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot. +config SPL_LOAD_FIT_APPLY_OVERLAY + bool "Enable SPL applying DT overlays from FIT" + depends on SPL_LOAD_FIT + select OF_LIBFDT_OVERLAY + help + The device tree is loaded from the FIT image. Allow the SPL is to + also load device-tree overlays from the FIT image an apply them + over the device tree. + config SPL_LOAD_FIT_FULL bool "Enable SPL loading U-Boot as a FIT (full fitImage features)" select SPL_FIT diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 346f9edaa5..39e406b237 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -281,7 +281,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 +290,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__); @@ -315,8 +315,32 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, #if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY) /* 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 + if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) { + for (; ; index++) { + node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, + index); + if (node < 0) { + debug("%s: No additional FDT node\n", __func__); + return 0; + } + ret = spl_load_fit_image(info, sector, fit, base_offset, + node, &image_info); + if (ret < 0) + return ret; + + ret = fdt_overlay_apply_verbose(spl_image->fdt_addr, + (void *)image_info.load_addr); + if (ret) + return ret; + + debug("%s: DT overlay %s applied\n", __func__, + fit_get_name(fit, node, NULL)); + } + } return ret; } From 99329be2c58d53ccf8f597bab3de85f4c572b152 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:12 +0200 Subject: [PATCH 06/30] spl: fit: Make room in the FDT before applying overlays Make room in the FDT before applying the overlay, otherwise it may fail if the overlay is big. As the exact added size is not known in advance, just add the size of the overlay. Move after the end of the application of the overlays, the resize of the FDT for the injection of the details on the loadables. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 39e406b237..65dd835ecc 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -313,11 +313,6 @@ 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) - /* 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 if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) { for (; ; index++) { node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, @@ -332,6 +327,12 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, if (ret < 0) return ret; + /* Make room in FDT for changes from the overlay */ + ret = fdt_increase_size(spl_image->fdt_addr, + image_info.size); + if (ret < 0) + return ret; + ret = fdt_overlay_apply_verbose(spl_image->fdt_addr, (void *)image_info.load_addr); if (ret) @@ -341,6 +342,12 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, fit_get_name(fit, node, NULL)); } } + /* 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; } From ea376ebc9b166dd2bf8328c133e51d0ff58376ef Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:13 +0200 Subject: [PATCH 07/30] spl: fit: allocate a temporary buffer to load the overlays If the node describing an overlay does not specify a load address, it will be loaded at the address previously used. Fixing it by allocating a temporary buffer that will be used as a default load address. By default, the size of the buffer is 64kB which should be plenty for most use cases. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- Kconfig | 9 +++++++++ common/spl/spl_fit.c | 34 +++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/Kconfig b/Kconfig index 0edd4ec2b0..99cc56f3c2 100644 --- a/Kconfig +++ b/Kconfig @@ -453,6 +453,15 @@ config SPL_LOAD_FIT_APPLY_OVERLAY also load device-tree overlays from the FIT image an apply them over the device tree. +config SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ + depends on SPL_LOAD_FIT_APPLY_OVERLAY + default 0x10000 + hex "size of temporary buffer used to load the overlays" + help + The size of the area where the overlays will be loaded and + uncompress. Must be at least as large as biggest overlay + (uncompressed) + config SPL_LOAD_FIT_FULL bool "Enable SPL loading U-Boot as a FIT (full fitImage features)" select SPL_FIT diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 65dd835ecc..e6935c16b7 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -9,11 +9,16 @@ #include #include #include -#include +#include #include +#include 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 @@ -314,33 +319,52 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, 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 < 0) { debug("%s: No additional FDT node\n", __func__); - return 0; + break; } + 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) - return ret; + break; /* Make room in FDT for changes from the overlay */ ret = fdt_increase_size(spl_image->fdt_addr, image_info.size); if (ret < 0) - return ret; + break; ret = fdt_overlay_apply_verbose(spl_image->fdt_addr, (void *)image_info.load_addr); if (ret) - return ret; + 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); From 24bf44cf88e7ee04c4bb962ede3c0e6462339c5e Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:14 +0200 Subject: [PATCH 08/30] spl: fit: Do not fail immediately if an overlay is not available If one overlay that must be applied cannot be found in the FIT, the current implementation stops applying the overlays. Let's make it skip only the failing overlay instead. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index e6935c16b7..0245dcadb4 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -324,9 +324,13 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, for (; ; index++) { node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, index); - if (node < 0) { + 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) { From 19141d698302dd7192f04f69d32826494905031e Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:15 +0200 Subject: [PATCH 09/30] spl: fit: be more verbose when an error occurs when applying the overlays There are many ways the overlay application can fail. 2 of them are probably the most common: - the application itself failed. Usually this is comes from an unresolved reference - DTBO not available in FIT (could be because of a typo) In both case it is good to be more explicit about the error and at least show which overlay is failing. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 0245dcadb4..5aeb9528fe 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -113,7 +113,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; } @@ -359,8 +359,11 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, ret = fdt_overlay_apply_verbose(spl_image->fdt_addr, (void *)image_info.load_addr); - if (ret) + 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)); From 47818e23a2281bbbf64df5936f67a6f98bbd6563 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:16 +0200 Subject: [PATCH 10/30] Makefile.lib: include /__symbols__ in dtb if SPL_LOAD_FIT_APPLY_OVERLAY is enabled In order to apply an overlay to a DTB. The DTB must have been generated with the option '-@'. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- scripts/Makefile.lib | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index c10cd83a0a..4ea898a421 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -292,6 +292,10 @@ cmd_dt_S_dtb= \ $(obj)/%.dtb.S: $(obj)/%.dtb $(call cmd,dt_S_dtb) +ifeq ($(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY),y) +DTC_FLAGS += -@ +endif + quiet_cmd_dtc = DTC $@ # Modified for U-Boot # Bring in any U-Boot-specific include at the end of the file From c1648d056ebb92711f6e37bcccb2d4acc78e3836 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:17 +0200 Subject: [PATCH 11/30] spl: fit: constify the output parameter of spl_fit_get_image_name() There is no need for it to be non-constant. Making it constant, allows to return constant string without warning. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 5aeb9528fe..9001731303 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -46,7 +46,7 @@ __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) { const char *name, *str; __maybe_unused int node; @@ -101,7 +101,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; @@ -387,7 +387,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", From 8c86f96d209837345200495048b4503cb02f6599 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:18 +0200 Subject: [PATCH 12/30] drivers: board: Make the board drivers available in SPL Make the board driver available in the SPL too. The board driver is a way to provide useful information about the board and that can be useful in the SPL too. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- drivers/Makefile | 2 +- drivers/board/Kconfig | 3 +++ drivers/board/Makefile | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index cb8c215e76..b51bdeedbe 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/ obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/ obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/ obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += power/acpi_pmc/ +obj-$(CONFIG_$(SPL_)BOARD) += board/ ifndef CONFIG_TPL_BUILD ifdef CONFIG_SPL_BUILD @@ -75,7 +76,6 @@ obj-y += ata/ obj-$(CONFIG_DM_DEMO) += demo/ obj-$(CONFIG_BIOSEMU) += bios_emulator/ obj-y += block/ -obj-y += board/ obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/ obj-y += cache/ obj-$(CONFIG_CPU) += cpu/ diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig index 2a3fc9c049..254f657049 100644 --- a/drivers/board/Kconfig +++ b/drivers/board/Kconfig @@ -8,6 +8,9 @@ menuconfig BOARD if BOARD +config SPL_BOARD + depends on SPL_DM + bool "Enable board driver support in SPL" config BOARD_GAZERBEAM bool "Enable board driver for the Gazerbeam board" diff --git a/drivers/board/Makefile b/drivers/board/Makefile index c8dab4fa0b..cc16361755 100644 --- a/drivers/board/Makefile +++ b/drivers/board/Makefile @@ -2,6 +2,6 @@ # # (C) Copyright 2017 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc -obj-$(CONFIG_BOARD) += board-uclass.o +obj-y += board-uclass.o obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o obj-$(CONFIG_BOARD_SANDBOX) += sandbox.o From d42730e8c67a0955c2f8236157b4723c585b9d24 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:19 +0200 Subject: [PATCH 13/30] drivers: board: Add get_fit_loadable() This function will be used by the SPL to get the names of images to load from the FIT. This allows to load different images based on runtime HW detection. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- drivers/board/board-uclass.c | 11 +++++++++++ include/board.h | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/board/board-uclass.c b/drivers/board/board-uclass.c index a516ba4962..b5485e9895 100644 --- a/drivers/board/board-uclass.c +++ b/drivers/board/board-uclass.c @@ -23,6 +23,17 @@ int board_detect(struct udevice *dev) return ops->detect(dev); } +int board_get_fit_loadable(struct udevice *dev, int index, + const char *type, const char **strp) +{ + struct board_ops *ops = board_get_ops(dev); + + if (!ops->get_fit_loadable) + return -ENOSYS; + + return ops->get_fit_loadable(dev, index, type, strp); +} + int board_get_bool(struct udevice *dev, int id, bool *val) { struct board_ops *ops = board_get_ops(dev); diff --git a/include/board.h b/include/board.h index 9dc78684f8..fd6a486702 100644 --- a/include/board.h +++ b/include/board.h @@ -79,6 +79,24 @@ struct board_ops { * Return: 0 if OK, -ve on error. */ int (*get_str)(struct udevice *dev, int id, size_t size, char *val); + + /** + * get_fit_loadable - Get the name of an image to load from FIT + * This function can be used to provide the image names based on runtime + * detection. A classic use-case would when DTBOs are used to describe + * additionnal daughter cards. + * + * @dev: The board instance to gather the data. + * @index: Index of the image. Starts at 0 and gets incremented + * after each call to this function. + * @type: The type of image. For example, "fdt" for DTBs + * @strp: A pointer to string. Untouched if the function fails + * + * Return: 0 if OK, -ENOENT if no loadable is available else -ve on + * error. + */ + int (*get_fit_loadable)(struct udevice *dev, int index, + const char *type, const char **strp); }; #define board_get_ops(dev) ((struct board_ops *)(dev)->driver->ops) @@ -137,3 +155,22 @@ int board_get_str(struct udevice *dev, int id, size_t size, char *val); * Return: 0 if OK, -ve on error. */ int board_get(struct udevice **devp); + +/** + * board_get_fit_loadable - Get the name of an image to load from FIT + * This function can be used to provide the image names based on runtime + * detection. A classic use-case would when DTBOs are used to describe + * additionnal daughter cards. + * + * @dev: The board instance to gather the data. + * @index: Index of the image. Starts at 0 and gets incremented + * after each call to this function. + * @type: The type of image. For example, "fdt" for DTBs + * @strp: A pointer to string. Untouched if the function fails + * + * + * Return: 0 if OK, -ENOENT if no loadable is available else -ve on + * error. + */ +int board_get_fit_loadable(struct udevice *dev, int index, + const char *type, const char **strp); From 02806e9ac1fbff2f1507f5565d738ac4e3c25709 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:20 +0200 Subject: [PATCH 14/30] include: board: provide empty stubs when the BOARD option is not selected Useful to avoid #ifdef throughout the code that uses the board driver API. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- include/board.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/include/board.h b/include/board.h index fd6a486702..678b652b0a 100644 --- a/include/board.h +++ b/include/board.h @@ -31,6 +31,7 @@ * to read the serial number. */ +#if CONFIG_IS_ENABLED(BOARD) struct board_ops { /** * detect() - Run the hardware info detection procedure for this @@ -174,3 +175,39 @@ int board_get(struct udevice **devp); */ int board_get_fit_loadable(struct udevice *dev, int index, const char *type, const char **strp); + +#else + +static inline int board_detect(struct udevice *dev) +{ + return -ENOSYS; +} + +static inline int board_get_bool(struct udevice *dev, int id, bool *val) +{ + return -ENOSYS; +} + +static inline int board_get_int(struct udevice *dev, int id, int *val) +{ + return -ENOSYS; +} + +static inline int board_get_str(struct udevice *dev, int id, size_t size, + char *val) +{ + return -ENOSYS; +} + +static inline int board_get(struct udevice **devp) +{ + return -ENOSYS; +} + +static inline int board_get_fit_loadable(struct udevice *dev, int index, + const char *type, const char **strp) +{ + return -ENOSYS; +} + +#endif From 557bc97fe8093506673985d3afcb66d64ee43c2c Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:21 +0200 Subject: [PATCH 15/30] dts: Add support for adding DT overlays in u-boot.img If u-boot.img is a FIT image, CONFIG_OF_OVERLAY_LIST can be used to add DT overlays to u-boot.img. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- Makefile | 3 ++- dts/Kconfig | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1766f5ab18..6f62d764db 100644 --- a/Makefile +++ b/Makefile @@ -1292,7 +1292,8 @@ MKIMAGEFLAGS_u-boot.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \ -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ -p $(CONFIG_FIT_EXTERNAL_OFFSET) \ -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \ - $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) + $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) \ + $(patsubst %,-b arch/$(ARCH)/dts/%.dtbo,$(subst ",,$(CONFIG_OF_OVERLAY_LIST))) else MKIMAGEFLAGS_u-boot.img = -A $(ARCH) -T firmware -C none -O u-boot \ -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ diff --git a/dts/Kconfig b/dts/Kconfig index 2bd959a7dc..64c98dd723 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -130,6 +130,14 @@ config OF_LIST device tree files (without the directory or .dtb suffix) separated by . +config OF_OVERLAY_LIST + string "List of device tree overlays to include for DT control" + depends on SPL_LOAD_FIT_APPLY_OVERLAY + help + This option specifies a list of device tree overlays to use for DT + control. This option can then be used by a FIT generator to include + the overlays in the FIT image. + choice prompt "OF LIST compression" depends on MULTI_DTB_FIT From 152781d4641e0e4c37b3a32f699cf99aeec877c8 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 16:39:22 +0200 Subject: [PATCH 16/30] spl: fit: Allow the board to tell if more images must be loaded from FIT spl_fit_get_image_name() is used to get the names of the images that the SPL must load from the FIT. It relies on the content of a property present in the FIT. The list of images is thus statically defined in the FIT. With this scheme, it quickly becomes hard to manage combinations of more than a handful of images. To address this problem, give the board driver code the opportunity to add to the list of images. The images from the FIT property are loaded first, and then the board_get_fit_loadable() is called to get more image names. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 65 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 9001731303..ac69d8312e 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -32,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 @@ -48,10 +72,12 @@ static int spl_fit_get_image_name(const void *fit, int images, const char *type, int index, 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) { @@ -77,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; } From ffcb880de81c7a8fb4328b415bf95cae57bc6b2b Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 30 Oct 2019 14:38:28 +0100 Subject: [PATCH 17/30] remoteproc: elf_loader: Add elf resource table load support Add rproc_elf_load_rsc_table(), which searches for a resource table in an elf64/elf32 image, and if found, copies it to device memory. Add also the elf32 and elf64 variants of this API. Add a test for this. Signed-off-by: Fabien Dessenne Acked-by: Patrick Delaunay Reviewed-by: Lokesh Vutla --- drivers/remoteproc/rproc-elf-loader.c | 269 ++++++++++++++++++++++++++ include/remoteproc.h | 70 +++++++ test/dm/remoteproc.c | 91 +++++++-- 3 files changed, 419 insertions(+), 11 deletions(-) diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index e8026cdfbb..538481241f 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -8,6 +8,39 @@ #include #include +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote processor. It may also include configuration entries. + * If needed, the remote processor firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * Some resources entries are mere announcements, where the host is informed + * of specific remoteproc configuration. Other entries require the host to + * do something (e.g. allocate a system resource). Sometimes a negotiation + * is expected, where the firmware requests a resource, and once allocated, + * the host should provide back its details (e.g. address of an allocated + * memory region). + * + * The header of the resource table, as expressed by this structure, + * contains a version number (should we need to change this format in the + * future), the number of available resource entries, and their offsets + * in the table. + * + * Immediately following this header are the resource entries themselves. + */ +struct resource_table { + u32 ver; + u32 num; + u32 reserved[2]; + u32 offset[0]; +} __packed; + /* Basic function to verify ELF32 image format */ int rproc_elf32_sanity_check(ulong addr, ulong size) { @@ -276,3 +309,239 @@ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) else return rproc_elf32_get_boot_addr(addr); } + +/* + * Search for the resource table in an ELF32 image. + * Returns the address of the resource table section if found, NULL if there is + * no resource table section, or error pointer. + */ +static Elf32_Shdr *rproc_elf32_find_rsc_table(struct udevice *dev, + ulong fw_addr, ulong fw_size) +{ + int ret; + unsigned int i; + const char *name_table; + struct resource_table *table; + const u8 *elf_data = (void *)fw_addr; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr; + Elf32_Shdr *shdr; + + ret = rproc_elf32_sanity_check(fw_addr, fw_size); + if (ret) { + pr_debug("Invalid ELF32 Image %d\n", ret); + return ERR_PTR(ret); + } + + /* look for the resource table and handle it */ + shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff); + name_table = (const char *)(elf_data + + shdr[ehdr->e_shstrndx].sh_offset); + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + u32 size = shdr->sh_size; + u32 offset = shdr->sh_offset; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + table = (struct resource_table *)(elf_data + offset); + + /* make sure we have the entire table */ + if (offset + size > fw_size) { + pr_debug("resource table truncated\n"); + return ERR_PTR(-ENOSPC); + } + + /* make sure table has at least the header */ + if (sizeof(*table) > size) { + pr_debug("header-less resource table\n"); + return ERR_PTR(-ENOSPC); + } + + /* we don't support any version beyond the first */ + if (table->ver != 1) { + pr_debug("unsupported fw ver: %d\n", table->ver); + return ERR_PTR(-EPROTONOSUPPORT); + } + + /* make sure reserved bytes are zeroes */ + if (table->reserved[0] || table->reserved[1]) { + pr_debug("non zero reserved bytes\n"); + return ERR_PTR(-EBADF); + } + + /* make sure the offsets array isn't truncated */ + if (table->num * sizeof(table->offset[0]) + + sizeof(*table) > size) { + pr_debug("resource table incomplete\n"); + return ERR_PTR(-ENOSPC); + } + + return shdr; + } + + return NULL; +} + +/* Load the resource table from an ELF32 image */ +int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size) +{ + const struct dm_rproc_ops *ops; + Elf32_Shdr *shdr; + void *src, *dst; + + shdr = rproc_elf32_find_rsc_table(dev, fw_addr, fw_size); + if (!shdr) + return -ENODATA; + if (IS_ERR(shdr)) + return PTR_ERR(shdr); + + ops = rproc_get_ops(dev); + *rsc_addr = (ulong)shdr->sh_addr; + *rsc_size = (ulong)shdr->sh_size; + + src = (void *)fw_addr + shdr->sh_offset; + if (ops->device_to_virt) + dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size); + else + dst = (void *)rsc_addr; + + dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n", + (ulong)dst, *rsc_size); + + memcpy(dst, src, *rsc_size); + flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), + roundup((unsigned long)dst + *rsc_size, + ARCH_DMA_MINALIGN) - + rounddown((unsigned long)dst, ARCH_DMA_MINALIGN)); + + return 0; +} + +/* + * Search for the resource table in an ELF64 image. + * Returns the address of the resource table section if found, NULL if there is + * no resource table section, or error pointer. + */ +static Elf64_Shdr *rproc_elf64_find_rsc_table(struct udevice *dev, + ulong fw_addr, ulong fw_size) +{ + int ret; + unsigned int i; + const char *name_table; + struct resource_table *table; + const u8 *elf_data = (void *)fw_addr; + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)fw_addr; + Elf64_Shdr *shdr; + + ret = rproc_elf64_sanity_check(fw_addr, fw_size); + if (ret) { + pr_debug("Invalid ELF64 Image %d\n", ret); + return ERR_PTR(ret); + } + + /* look for the resource table and handle it */ + shdr = (Elf64_Shdr *)(elf_data + ehdr->e_shoff); + name_table = (const char *)(elf_data + + shdr[ehdr->e_shstrndx].sh_offset); + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + u64 size = shdr->sh_size; + u64 offset = shdr->sh_offset; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + table = (struct resource_table *)(elf_data + offset); + + /* make sure we have the entire table */ + if (offset + size > fw_size) { + pr_debug("resource table truncated\n"); + return ERR_PTR(-ENOSPC); + } + + /* make sure table has at least the header */ + if (sizeof(*table) > size) { + pr_debug("header-less resource table\n"); + return ERR_PTR(-ENOSPC); + } + + /* we don't support any version beyond the first */ + if (table->ver != 1) { + pr_debug("unsupported fw ver: %d\n", table->ver); + return ERR_PTR(-EPROTONOSUPPORT); + } + + /* make sure reserved bytes are zeroes */ + if (table->reserved[0] || table->reserved[1]) { + pr_debug("non zero reserved bytes\n"); + return ERR_PTR(-EBADF); + } + + /* make sure the offsets array isn't truncated */ + if (table->num * sizeof(table->offset[0]) + + sizeof(*table) > size) { + pr_debug("resource table incomplete\n"); + return ERR_PTR(-ENOSPC); + } + + return shdr; + } + + return NULL; +} + +/* Load the resource table from an ELF64 image */ +int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size) +{ + const struct dm_rproc_ops *ops; + Elf64_Shdr *shdr; + void *src, *dst; + + shdr = rproc_elf64_find_rsc_table(dev, fw_addr, fw_size); + if (!shdr) + return -ENODATA; + if (IS_ERR(shdr)) + return PTR_ERR(shdr); + + ops = rproc_get_ops(dev); + *rsc_addr = (ulong)shdr->sh_addr; + *rsc_size = (ulong)shdr->sh_size; + + src = (void *)fw_addr + shdr->sh_offset; + if (ops->device_to_virt) + dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size); + else + dst = (void *)rsc_addr; + + dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n", + (ulong)dst, *rsc_size); + + memcpy(dst, src, *rsc_size); + flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), + roundup((unsigned long)dst + *rsc_size, + ARCH_DMA_MINALIGN) - + rounddown((unsigned long)dst, ARCH_DMA_MINALIGN)); + + return 0; +} + +/* Load the resource table from an ELF32 or ELF64 image */ +int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size) + +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr; + + if (!fw_addr) + return -EFAULT; + + if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) + return rproc_elf64_load_rsc_table(dev, fw_addr, fw_size, + rsc_addr, rsc_size); + else + return rproc_elf32_load_rsc_table(dev, fw_addr, fw_size, + rsc_addr, rsc_size); +} diff --git a/include/remoteproc.h b/include/remoteproc.h index 046cd9e54e..a903acb9b2 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -277,6 +277,64 @@ int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size); * image. */ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr); + +/** + * rproc_elf32_load_rsc_table() - load the resource table from an ELF32 image + * + * Search for the resource table in an ELF32 image, and if found, copy it to + * device memory. + * + * @dev: device loading the resource table + * @fw_addr: ELF image address + * @fw_size: size of the ELF image + * @rsc_addr: pointer to the found resource table address. Updated on + * operation success + * @rsc_size: pointer to the found resource table size. Updated on operation + * success + * + * @return 0 if a valid resource table is successfully loaded, -ENODATA if there + * is no resource table (which is optional), or another appropriate error value. + */ +int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size); +/** + * rproc_elf64_load_rsc_table() - load the resource table from an ELF64 image + * + * Search for the resource table in an ELF64 image, and if found, copy it to + * device memory. + * + * @dev: device loading the resource table + * @fw_addr: ELF image address + * @fw_size: size of the ELF image + * @rsc_addr: pointer to the found resource table address. Updated on + * operation success + * @rsc_size: pointer to the found resource table size. Updated on operation + * success + * + * @return 0 if a valid resource table is successfully loaded, -ENODATA if there + * is no resource table (which is optional), or another appropriate error value. + */ +int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size); +/** + * rproc_elf_load_rsc_table() - load the resource table from an ELF image + * + * Auto detects if the image is ELF32 or ELF64 image and search accordingly for + * the resource table, and if found, copy it to device memory. + * + * @dev: device loading the resource table + * @fw_addr: ELF image address + * @fw_size: size of the ELF image + * @rsc_addr: pointer to the found resource table address. Updated on + * operation success + * @rsc_size: pointer to the found resource table size. Updated on operation + * success + * + * @return 0 if a valid resource table is successfully loaded, -ENODATA if there + * is no resource table (which is optional), or another appropriate error value. + */ +int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, ulong *rsc_size); #else static inline int rproc_init(void) { return -ENOSYS; } static inline int rproc_dev_init(int id) { return -ENOSYS; } @@ -304,6 +362,18 @@ static inline int rproc_elf_load_image(struct udevice *dev, ulong addr, { return -ENOSYS; } static inline ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr) { return 0; } +static inline int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, + ulong *rsc_size) +{ return -ENOSYS; } +static inline int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, + ulong *rsc_size) +{ return -ENOSYS; } +static inline int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr, + ulong fw_size, ulong *rsc_addr, + ulong *rsc_size) +{ return -ENOSYS; } #endif #endif /* _RPROC_H_ */ diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c index 1d9a9b32d5..40675962d8 100644 --- a/test/dm/remoteproc.c +++ b/test/dm/remoteproc.c @@ -103,8 +103,8 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x00, 0x00, 0x00, 0x08, /* phoff (program header offset @ 0x40)*/ 0x40, 0x00, 0x00, 0x00, - /* shoff (section header offset : none) */ - 0x00, 0x00, 0x00, 0x00, + /* shoff (section header offset @ 0x90) */ + 0x90, 0x00, 0x00, 0x00, /* flags */ 0x00, 0x00, 0x00, 0x00, /* ehsize (elf header size = 0x34) */ @@ -113,16 +113,17 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x20, 0x00, /* phnum (program header number : 1) */ 0x01, 0x00, - /* shentsize (section heade size : none) */ - 0x00, 0x00, - /* shnum (section header number: none) */ - 0x00, 0x00, - /* shstrndx (section header name section index: none) */ - 0x00, 0x00, + /* shentsize (section header size : 40 bytes) */ + 0x28, 0x00, + /* shnum (section header number: 3) */ + 0x02, 0x00, + /* shstrndx (section header name section index: 1) */ + 0x01, 0x00, /* padding */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* @0x40 - PROGRAM HEADER TABLE - */ /* type : PT_LOAD */ 0x01, 0x00, 0x00, 0x00, @@ -140,14 +141,63 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x05, 0x00, 0x00, 0x00, /* padding */ 0x00, 0x00, 0x00, 0x00, + + /* @0x60 - RESOURCE TABLE SECTION - */ + /* version */ + 0x01, 0x00, 0x00, 0x00, + /* num (0, no entries) */ + 0x00, 0x00, 0x00, 0x00, + /* Reserved */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* @0x70 - SECTION'S NAMES SECTION - */ + /* section 0 name (".shrtrtab") */ + 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00, + /* section 1 name (".resource_table") */ + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, + /* padding */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* @0x90 - SECTION HEADER TABLE - */ + /* Section 0 : resource table header */ + /* sh_name - index into section header string table section */ + 0x0a, 0x00, 0x00, 0x00, + /* sh_type and sh_flags */ + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + /* sh_addr = where the resource table has to be copied to */ + 0x00, 0x00, 0x00, 0x00, + /* sh_offset = 0x60 */ + 0x60, 0x00, 0x00, 0x00, + /* sh_size = 16 bytes */ + 0x10, 0x00, 0x00, 0x00, + /* sh_link, sh_info, sh_addralign, sh_entsize */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Section 1 : section's names section header */ + /* sh_name - index into section header string table section */ + 0x00, 0x00, 0x00, 0x00, + /* sh_type and sh_flags */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* sh_addr */ + 0x00, 0x00, 0x00, 0x00, + /* sh_offset = 0x70 */ + 0x70, 0x00, 0x00, 0x00, + /* sh_size = 27 bytes */ + 0x1b, 0x00, 0x00, 0x00, + /* sh_link, sh_info, sh_addralign, sh_entsize */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; unsigned int size = ARRAY_SIZE(valid_elf32); struct udevice *dev; - phys_addr_t loaded_firmware_paddr; - void *loaded_firmware; - u32 loaded_firmware_size; + phys_addr_t loaded_firmware_paddr, loaded_rsc_table_paddr; + void *loaded_firmware, *loaded_rsc_table; + u32 loaded_firmware_size, rsc_table_size; + ulong rsc_addr, rsc_size; Elf32_Ehdr *ehdr = (Elf32_Ehdr *)valid_elf32; Elf32_Phdr *phdr = (Elf32_Phdr *)(valid_elf32 + ehdr->e_phoff); + Elf32_Shdr *shdr = (Elf32_Shdr *)(valid_elf32 + ehdr->e_shoff); ut_assertok(uclass_get_device(UCLASS_REMOTEPROC, 0, &dev)); @@ -178,6 +228,25 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts) 0x08000000); unmap_physmem(loaded_firmware, MAP_NOCACHE); + /* Resource table */ + shdr->sh_addr = CONFIG_SYS_SDRAM_BASE; + rsc_table_size = shdr->sh_size; + + loaded_rsc_table_paddr = shdr->sh_addr + DEVICE_TO_PHYSICAL_OFFSET; + loaded_rsc_table = map_physmem(loaded_rsc_table_paddr, + rsc_table_size, MAP_NOCACHE); + ut_assertnonnull(loaded_rsc_table); + memset(loaded_rsc_table, 0, rsc_table_size); + + /* Load and verify */ + ut_assertok(rproc_elf32_load_rsc_table(dev, (ulong)valid_elf32, size, + &rsc_addr, &rsc_size)); + ut_asserteq(rsc_addr, CONFIG_SYS_SDRAM_BASE); + ut_asserteq(rsc_size, rsc_table_size); + ut_assertok(memcmp(loaded_firmware, valid_elf32 + shdr->sh_offset, + shdr->sh_size)); + unmap_physmem(loaded_firmware, MAP_NOCACHE); + /* Invalid ELF Magic */ valid_elf32[0] = 0; ut_asserteq(-EPROTONOSUPPORT, From ee16c9a60b582d48e80d132fd64c06e5bd4c90e0 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 30 Oct 2019 14:38:29 +0100 Subject: [PATCH 18/30] stm32mp1: declare backup registers for coprocessor Use the backup register #17 as coprocessor resource table address and backup register #18 as coprocessor state. Signed-off-by: Fabien Dessenne Acked-by: Patrick Delaunay --- arch/arm/mach-stm32mp/include/mach/stm32.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index b3e9ccc5d3..88126b8cdb 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -86,9 +86,18 @@ enum boot_device { #define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 * x) #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) +#define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) +#define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) #define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21) +#define TAMP_COPRO_STATE_OFF 0 +#define TAMP_COPRO_STATE_INIT 1 +#define TAMP_COPRO_STATE_CRUN 2 +#define TAMP_COPRO_STATE_CSTOP 3 +#define TAMP_COPRO_STATE_STANDBY 4 +#define TAMP_COPRO_STATE_CRASH 5 + #define TAMP_BOOT_MODE_MASK GENMASK(15, 8) #define TAMP_BOOT_MODE_SHIFT 8 #define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4) From 7bff971a145c9fa0aa59c61c1fe0081c6b2db6dd Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 30 Oct 2019 14:38:30 +0100 Subject: [PATCH 19/30] stm32mp1: reset coprocessor status at cold boot Reset ResourceTableAddress and CoprocessorState at cold boot, preserve these values at standby wakeup. Signed-off-by: Fabien Dessenne Acked-by: Patrick Delaunay --- arch/arm/mach-stm32mp/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index ed7d9f61dc..6a71465494 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -35,7 +35,9 @@ #define TAMP_CR1 (STM32_TAMP_BASE + 0x00) #define PWR_CR1 (STM32_PWR_BASE + 0x00) +#define PWR_MCUCR (STM32_PWR_BASE + 0x14) #define PWR_CR1_DBP BIT(8) +#define PWR_MCUCR_SBF BIT(6) /* DBGMCU register */ #define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00) @@ -206,6 +208,11 @@ int arch_cpu_init(void) security_init(); update_bootmode(); #endif + /* Reset Coprocessor state unless it wakes up from Standby power mode */ + if (!(readl(PWR_MCUCR) & PWR_MCUCR_SBF)) { + writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE); + writel(0, TAMP_COPRO_RSC_TBL_ADDRESS); + } #endif boot_mode = get_bootmode(); From 4a4deb870f9a19569e6b86afe36d0e0fbee4fa61 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 30 Oct 2019 14:38:31 +0100 Subject: [PATCH 20/30] remoteproc: stm32: track the coprocessor state in a backup register Update the dedicated backup register to track the coprocessor state and rely on that register to compute the .is_running() value (which expects a return value of 0 -not 1- if the processor is running). Signed-off-by: Fabien Dessenne Acked-by: Patrick Delaunay --- drivers/remoteproc/stm32_copro.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index 40bba37211..dcafa549d6 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -22,14 +22,12 @@ * @hold_boot_regmap: regmap for remote processor reset hold boot * @hold_boot_offset: offset of the register controlling the hold boot setting * @hold_boot_mask: bitmask of the register for the hold boot field - * @is_running: is the remote processor running */ struct stm32_copro_privdata { struct reset_ctl reset_ctl; struct regmap *hold_boot_regmap; uint hold_boot_offset; uint hold_boot_mask; - bool is_running; }; /** @@ -165,11 +163,8 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) */ static int stm32_copro_start(struct udevice *dev) { - struct stm32_copro_privdata *priv; int ret; - priv = dev_get_priv(dev); - /* move hold boot from true to false start the copro */ ret = stm32_copro_set_hold_boot(dev, false); if (ret) @@ -180,7 +175,8 @@ static int stm32_copro_start(struct udevice *dev) * rebooting autonomously */ ret = stm32_copro_set_hold_boot(dev, true); - priv->is_running = !ret; + writel(ret ? TAMP_COPRO_STATE_OFF : TAMP_COPRO_STATE_CRUN, + TAMP_COPRO_STATE); return ret; } @@ -206,7 +202,7 @@ static int stm32_copro_reset(struct udevice *dev) return ret; } - priv->is_running = false; + writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE); return 0; } @@ -224,14 +220,11 @@ static int stm32_copro_stop(struct udevice *dev) /** * stm32_copro_is_running() - Is the STM32 remote processor running * @dev: corresponding STM32 remote processor device - * @return 1 if the remote processor is running, 0 otherwise + * @return 0 if the remote processor is running, 1 otherwise */ static int stm32_copro_is_running(struct udevice *dev) { - struct stm32_copro_privdata *priv; - - priv = dev_get_priv(dev); - return priv->is_running; + return (readl(TAMP_COPRO_STATE) == TAMP_COPRO_STATE_OFF); } static const struct dm_rproc_ops stm32_copro_ops = { From 790d5b367025921c1c520eba280b1bd4313a0aa0 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 30 Oct 2019 14:38:32 +0100 Subject: [PATCH 21/30] stm32mp1: remove copro_state environment variable Since the coprocessor state is tracked in a backup register, there is no more need for tracking it in an environment variable : remove it. Signed-off-by: Fabien Dessenne Acked-by: Patrick Delaunay --- board/st/stm32mp1/stm32mp1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index cee3500737..1d4a54c902 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -1096,10 +1096,8 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size) printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n", id, fw_image, fw_size, ret ? " Failed!" : " Success!"); - if (!ret) { + if (!ret) rproc_start(id); - env_set("copro_state", "booted"); - } } U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); From 33fd41951a8bf61be33b2b793a2c87a62eb0c1cf Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 30 Oct 2019 14:38:33 +0100 Subject: [PATCH 22/30] remoteproc: stm32: load resource table from firmware Load the optional resource table from the firmware, and write its address in the dedicated backup register. Signed-off-by: Fabien Dessenne Acked-by: Patrick Delaunay --- drivers/remoteproc/stm32_copro.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index dcafa549d6..c25488f54d 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -22,12 +22,14 @@ * @hold_boot_regmap: regmap for remote processor reset hold boot * @hold_boot_offset: offset of the register controlling the hold boot setting * @hold_boot_mask: bitmask of the register for the hold boot field + * @rsc_table_addr: resource table address */ struct stm32_copro_privdata { struct reset_ctl reset_ctl; struct regmap *hold_boot_regmap; uint hold_boot_offset; uint hold_boot_mask; + ulong rsc_table_addr; }; /** @@ -139,6 +141,7 @@ static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da, static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) { struct stm32_copro_privdata *priv; + ulong rsc_table_size; int ret; priv = dev_get_priv(dev); @@ -153,6 +156,12 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) return ret; } + if (rproc_elf32_load_rsc_table(dev, addr, size, &priv->rsc_table_addr, + &rsc_table_size)) { + priv->rsc_table_addr = 0; + dev_warn(dev, "No valid resource table for this firmware\n"); + } + return rproc_elf32_load_image(dev, addr, size); } @@ -163,8 +172,11 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size) */ static int stm32_copro_start(struct udevice *dev) { + struct stm32_copro_privdata *priv; int ret; + priv = dev_get_priv(dev); + /* move hold boot from true to false start the copro */ ret = stm32_copro_set_hold_boot(dev, false); if (ret) @@ -177,6 +189,10 @@ static int stm32_copro_start(struct udevice *dev) ret = stm32_copro_set_hold_boot(dev, true); writel(ret ? TAMP_COPRO_STATE_OFF : TAMP_COPRO_STATE_CRUN, TAMP_COPRO_STATE); + if (!ret) + /* Store rsc_address in bkp register */ + writel(priv->rsc_table_addr, TAMP_COPRO_RSC_TBL_ADDRESS); + return ret; } From 5677fe9d6b82a931b058de76b1668fe5b63d4616 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 4 Nov 2019 09:27:23 +0000 Subject: [PATCH 23/30] power: regulator: support off-on-delay-us off-on-delay-us has been supported by Linux, so let's use it. Signed-off-by: Peng Fan --- drivers/power/regulator/regulator_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c index 2041086567..939efb2c0d 100644 --- a/drivers/power/regulator/regulator_common.c +++ b/drivers/power/regulator/regulator_common.c @@ -37,7 +37,11 @@ int regulator_common_ofdata_to_platdata(struct udevice *dev, dev_pdata->startup_delay_us = dev_read_u32_default(dev, "startup-delay-us", 0); dev_pdata->off_on_delay_us = + dev_read_u32_default(dev, "off-on-delay-us", 0); + if (!dev_pdata->off_on_delay_us) { + dev_pdata->off_on_delay_us = dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0); + } return 0; } From 4ad4edfe77fce829c54d9a804e037923e7474451 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 17 Dec 2019 19:07:04 +0100 Subject: [PATCH 24/30] cmd_ut: add a parameter prefix to the function cmd_ut_category There is black magic in the file conftest.py that list all the test unit. Then, all those test unit are called in pytest. This call is done with the end of the name (for example checksum if the full name is bloblist_test_checksum). The result is that only test for dm are really executed. by pytest, all others tests are listed but never executed. This behaviour happens because the dm test unit only check the end of the name and others tests checks the full name. To fix this issue, I've added a prefix to the function cmd_ut_category, and this prefix is removed when looking for the unit test. Signed-off-by: Philippe Reynes Tested-by: Heinrich Schuchardt --- include/test/suites.h | 4 +++- test/bloblist.c | 3 ++- test/cmd_ut.c | 12 ++++++++++-- test/compression.c | 3 ++- test/env/cmd_ut_env.c | 3 ++- test/lib/cmd_ut_lib.c | 2 +- test/optee/cmd_ut_optee.c | 6 +++--- test/overlay/cmd_ut_overlay.c | 2 +- test/unicode_ut.c | 3 ++- 9 files changed, 26 insertions(+), 12 deletions(-) diff --git a/include/test/suites.h b/include/test/suites.h index 20970f08d6..0748185eaf 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -13,6 +13,7 @@ struct unit_test; * cmd_ut_category() - Run a category of unit tests * * @name: Category name + * @prefix: Prefix of test name * @tests: List of tests to run * @n_ents: Number of tests in @tests * @argc: Argument count provided. Must be >= 1. If this is 1 then all @@ -20,7 +21,8 @@ struct unit_test; * @argv: Arguments: argv[1] is the test to run (if @argc >= 2) * @return 0 if OK, CMD_RET_FAILURE on failure */ -int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents, +int cmd_ut_category(const char *name, const char *prefix, + struct unit_test *tests, int n_ents, int argc, char * const argv[]); int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); diff --git a/test/bloblist.c b/test/bloblist.c index 89bdb012e3..d0f7296e0d 100644 --- a/test/bloblist.c +++ b/test/bloblist.c @@ -183,5 +183,6 @@ int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) bloblist_test); const int n_ents = ll_entry_count(struct unit_test, bloblist_test); - return cmd_ut_category("bloblist", tests, n_ents, argc, argv); + return cmd_ut_category("bloblist", "bloblist_test_", + tests, n_ents, argc, argv); } diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 2781f8bd56..400719e7b6 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -11,17 +11,25 @@ static int do_ut_all(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); -int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents, +int cmd_ut_category(const char *name, const char *prefix, + struct unit_test *tests, int n_ents, int argc, char * const argv[]) { struct unit_test_state uts = { .fail_count = 0 }; struct unit_test *test; + int prefix_len = prefix ? strlen(prefix) : 0; if (argc == 1) printf("Running %d %s tests\n", n_ents, name); for (test = tests; test < tests + n_ents; test++) { - if (argc > 1 && strcmp(argv[1], test->name)) + const char *test_name = test->name; + + /* Remove the prefix */ + if (!strncmp(test_name, prefix, prefix_len)) + test_name += prefix_len; + + if (argc > 1 && strcmp(argv[1], test_name)) continue; printf("Test: %s\n", test->name); diff --git a/test/compression.c b/test/compression.c index 48dccc0e89..cf040d7c86 100644 --- a/test/compression.c +++ b/test/compression.c @@ -540,5 +540,6 @@ int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) compression_test); const int n_ents = ll_entry_count(struct unit_test, compression_test); - return cmd_ut_category("compression", tests, n_ents, argc, argv); + return cmd_ut_category("compression", "compression_test_", + tests, n_ents, argc, argv); } diff --git a/test/env/cmd_ut_env.c b/test/env/cmd_ut_env.c index 54041a0219..ad67dbe792 100644 --- a/test/env/cmd_ut_env.c +++ b/test/env/cmd_ut_env.c @@ -15,5 +15,6 @@ int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct unit_test *tests = ll_entry_start(struct unit_test, env_test); const int n_ents = ll_entry_count(struct unit_test, env_test); - return cmd_ut_category("environment", tests, n_ents, argc, argv); + return cmd_ut_category("environment", "env_test_", + tests, n_ents, argc, argv); } diff --git a/test/lib/cmd_ut_lib.c b/test/lib/cmd_ut_lib.c index eb90e53914..c73e8d7b05 100644 --- a/test/lib/cmd_ut_lib.c +++ b/test/lib/cmd_ut_lib.c @@ -16,5 +16,5 @@ int do_ut_lib(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct unit_test *tests = ll_entry_start(struct unit_test, lib_test); const int n_ents = ll_entry_count(struct unit_test, lib_test); - return cmd_ut_category("lib", tests, n_ents, argc, argv); + return cmd_ut_category("lib", "lib_test_", tests, n_ents, argc, argv); } diff --git a/test/optee/cmd_ut_optee.c b/test/optee/cmd_ut_optee.c index 670682f3d4..092710326a 100644 --- a/test/optee/cmd_ut_optee.c +++ b/test/optee/cmd_ut_optee.c @@ -129,20 +129,20 @@ int do_ut_optee(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ut_assertok(optee_copy_fdt_nodes(fdt_no_optee, fdt)); expect_success = false; - ret = cmd_ut_category("optee", tests, n_ents, argc, argv); + ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); /* (2) Try to copy optee nodes from prefilled dt */ ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); expect_success = true; - ret = cmd_ut_category("optee", tests, n_ents, argc, argv); + ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); /* (3) Try to copy OP-TEE nodes into a already filled DT */ ut_assertok(fdt_open_into(fdt_optee, fdt, FDT_COPY_SIZE)); ut_assertok(optee_copy_fdt_nodes(fdt_optee, fdt)); expect_success = true; - ret = cmd_ut_category("optee", tests, n_ents, argc, argv); + ret = cmd_ut_category("optee", "", tests, n_ents, argc, argv); free(fdt); return ret; diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c index fc2491d0b4..d0083fd6be 100644 --- a/test/overlay/cmd_ut_overlay.c +++ b/test/overlay/cmd_ut_overlay.c @@ -272,7 +272,7 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Apply the stacked overlay */ ut_assertok(fdt_overlay_apply(fdt, fdt_overlay_stacked_copy)); - ret = cmd_ut_category("overlay", tests, n_ents, argc, argv); + ret = cmd_ut_category("overlay", "", tests, n_ents, argc, argv); free(fdt_overlay_stacked_copy); err3: diff --git a/test/unicode_ut.c b/test/unicode_ut.c index 8875cdc6b2..47532a64df 100644 --- a/test/unicode_ut.c +++ b/test/unicode_ut.c @@ -585,5 +585,6 @@ int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test); const int n_ents = ll_entry_count(struct unit_test, unicode_test); - return cmd_ut_category("Unicode", tests, n_ents, argc, argv); + return cmd_ut_category("Unicode", "unicode_test_", + tests, n_ents, argc, argv); } From 8ad0c66437a3c5bafbbaddffd58436ba6763837d Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sat, 9 Nov 2019 04:56:10 +0100 Subject: [PATCH 25/30] bdinfo: show multi_dtb_fit if MULTI_DTB_FIT is enabled it is helpful to display the value of gd->multi_dtb_fit in bdinfo. Signed-off-by: Heiko Schocher Reviewed-by: Simon Glass --- cmd/bdinfo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index abd9151432..d6a7175b37 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -348,6 +348,9 @@ static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, #if CONFIG_VAL(SYS_MALLOC_F_LEN) printf("Early malloc usage: %lx / %x\n", gd->malloc_ptr, CONFIG_VAL(SYS_MALLOC_F_LEN)); +#endif +#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) + print_num("multi_dtb_fit", (ulong)gd->multi_dtb_fit); #endif if (gd->fdt_blob) print_num("fdt_blob", (ulong)gd->fdt_blob); From 14a2dee765fe0849a49d5007398eb64677ed1544 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 5 Dec 2019 18:46:11 -0500 Subject: [PATCH 26/30] cmd/Kconfig: Add more dependencies to OSE bootm support Per Enea OSE documentation, it supports some classes of ARM, PowerPC and X86. Limit the option to those platforms. Signed-off-by: Tom Rini --- cmd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index 4e29e7b3c5..5f2562bbea 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -294,6 +294,7 @@ config BOOTM_OPENRTOS config BOOTM_OSE bool "Support booting Enea OSE images" + depends on (ARM && (ARM64 || CPU_V7A || CPU_V7R) || SANDBOX || PPC || X86) depends on CMD_BOOTM help Support booting Enea OSE images via the bootm command. From 38a6cce65737096b836d43a22f09b7a54c9d020c Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 6 Dec 2019 15:01:48 +0100 Subject: [PATCH 27/30] Makefile: Fix CONFIG_SYS_UBOOT_START default value This patches restores boot on boards which rely on CONFIG_SYS_UBOOT_START equal to CONFIG_SYS_TEXT_BASE when using SPL Fixes: d3e97b53c1f2 ("spl: fix entry_point equal to load_addr") Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6f62d764db..cc126ebc53 100644 --- a/Makefile +++ b/Makefile @@ -1265,7 +1265,7 @@ u-boot.ldr.hex u-boot.ldr.srec: u-boot.ldr FORCE # from the SPL U-Boot version. # ifndef CONFIG_SYS_UBOOT_START -CONFIG_SYS_UBOOT_START := 0 +CONFIG_SYS_UBOOT_START := $(CONFIG_SYS_TEXT_BASE) endif # Boards with more complex image requirements can provide an .its source file From 74bb4570a952b06fecfafc5b961a5cb5147ec544 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 6 Dec 2019 15:01:49 +0100 Subject: [PATCH 28/30] treewide: Remove CONFIG_SYS_UBOOT_START from configs board files As previous CONFIG_SYS_UBOOT_START is now set by default to CONFIG_SYS_TEXT_BASE when not defined, CONFIG_SYS_UBOOT_START can be removed from include/configs board files. Signed-off-by: Patrice Chotard Acked-by: Lukasz Majewski --- include/configs/gardena-smart-gateway-at91sam.h | 1 - include/configs/ls1046a_common.h | 1 - include/configs/mccmon6.h | 1 - include/configs/microblaze-generic.h | 2 -- include/configs/mt7623.h | 1 - include/configs/mt7629.h | 1 - include/configs/mt8518.h | 1 - include/configs/omap3_cairo.h | 1 - include/configs/pumpkin.h | 1 - include/configs/tegra-common.h | 1 - include/configs/x600.h | 1 - include/configs/xilinx_zynqmp_r5.h | 2 -- include/configs/zynq-common.h | 2 -- 13 files changed, 16 deletions(-) diff --git a/include/configs/gardena-smart-gateway-at91sam.h b/include/configs/gardena-smart-gateway-at91sam.h index 482e4714b1..f5ee65cb8a 100644 --- a/include/configs/gardena-smart-gateway-at91sam.h +++ b/include/configs/gardena-smart-gateway-at91sam.h @@ -64,7 +64,6 @@ #define CONFIG_SPL_NAND_RAW_ONLY #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x40000 #define CONFIG_SYS_NAND_U_BOOT_SIZE 0xa0000 -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_NAND_U_BOOT_DST CONFIG_SYS_TEXT_BASE diff --git a/include/configs/ls1046a_common.h b/include/configs/ls1046a_common.h index cc8f4c0210..6543cfd868 100644 --- a/include/configs/ls1046a_common.h +++ b/include/configs/ls1046a_common.h @@ -98,7 +98,6 @@ CONFIG_SPL_BSS_MAX_SIZE) #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000 #define CONFIG_SYS_MONITOR_LEN 0x100000 -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #endif /* NAND SPL */ diff --git a/include/configs/mccmon6.h b/include/configs/mccmon6.h index 045a9f7bdf..0aee1e1cf6 100644 --- a/include/configs/mccmon6.h +++ b/include/configs/mccmon6.h @@ -12,7 +12,6 @@ #define CONFIG_SPL_LIBCOMMON_SUPPORT #include "imx6_spl.h" -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_UBOOT_BASE (CONFIG_SYS_FLASH_BASE + 0x80000) #define CONFIG_SYS_SPL_ARGS_ADDR 0x18000000 diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index 385b30c99b..8ca0e83c78 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -173,8 +173,6 @@ /* Just for sure that there is a space for stack */ #define CONFIG_SPL_STACK_SIZE 0x100 -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE - #define CONFIG_SPL_MAX_FOOTPRINT (CONFIG_SYS_INIT_RAM_SIZE - \ CONFIG_SYS_INIT_RAM_ADDR - \ CONFIG_SYS_MALLOC_F_LEN - \ diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h index e5182aeea8..faab0913fc 100644 --- a/include/configs/mt7623.h +++ b/include/configs/mt7623.h @@ -31,7 +31,6 @@ #define CONFIG_ENV_OVERWRITE /* Preloader -> Uboot */ -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - \ GENERATED_GBL_DATA_SIZE) diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h index 4aef894c6e..6a6c2f2414 100644 --- a/include/configs/mt7629.h +++ b/include/configs/mt7629.h @@ -40,7 +40,6 @@ #define CONFIG_SYS_UBOOT_BASE (CONFIG_SPI_ADDR + CONFIG_SPL_PAD_TO) /* SPL -> Uboot */ -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - \ GENERATED_GBL_DATA_SIZE) diff --git a/include/configs/mt8518.h b/include/configs/mt8518.h index a7fe83a605..514722be99 100644 --- a/include/configs/mt8518.h +++ b/include/configs/mt8518.h @@ -29,7 +29,6 @@ #define CONFIG_SYS_BOOTM_LEN SZ_64M /* Uboot definition */ -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + \ SZ_2M - \ GENERATED_GBL_DATA_SIZE) diff --git a/include/configs/omap3_cairo.h b/include/configs/omap3_cairo.h index 1b1a56d7cd..c76c81ddd5 100644 --- a/include/configs/omap3_cairo.h +++ b/include/configs/omap3_cairo.h @@ -26,7 +26,6 @@ * other needs. We use this rather than the inherited defines from * ti_armv7_common.h for backwards compatibility. */ -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SPL_BSS_START_ADDR 0x80000000 #define CONFIG_SPL_BSS_MAX_SIZE (512 << 10) /* 512 KB */ #define CONFIG_SYS_SPL_MALLOC_START 0x80208000 diff --git a/include/configs/pumpkin.h b/include/configs/pumpkin.h index 35e28be950..9c52cae41d 100644 --- a/include/configs/pumpkin.h +++ b/include/configs/pumpkin.h @@ -23,7 +23,6 @@ #define CONFIG_SYS_NS16550_COM1 0x11005000 #define CONFIG_SYS_NS16550_CLK 26000000 -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - \ GENERATED_GBL_DATA_SIZE) diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index b4da1f8428..f2cdd9c019 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -61,7 +61,6 @@ #define PHYS_SDRAM_1 NV_PA_SDRC_CS0 #define PHYS_SDRAM_1_SIZE 0x20000000 /* 512M */ -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 #define CONFIG_SYS_BOOTMAPSZ (256 << 20) /* 256M */ diff --git a/include/configs/x600.h b/include/configs/x600.h index 63092b24a5..8b6caae7be 100644 --- a/include/configs/x600.h +++ b/include/configs/x600.h @@ -27,7 +27,6 @@ #define CONFIG_SYS_SPL_LEN CONFIG_SPL_PAD_TO #define CONFIG_SYS_UBOOT_BASE (CONFIG_SYS_FLASH_BASE + \ CONFIG_SYS_SPL_LEN) -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE #define CONFIG_SYS_MONITOR_LEN 0x60000 diff --git a/include/configs/xilinx_zynqmp_r5.h b/include/configs/xilinx_zynqmp_r5.h index 38d952d0c0..155d7fe883 100644 --- a/include/configs/xilinx_zynqmp_r5.h +++ b/include/configs/xilinx_zynqmp_r5.h @@ -35,8 +35,6 @@ /* Extend size of kernel image for uncompression */ #define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024) -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE - #define CONFIG_SKIP_LOWLEVEL_INIT /* 0x0 - 0x40 is used for placing exception vectors */ diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index 274cc19112..189ca81bbe 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -274,6 +274,4 @@ #define CONFIG_SPL_LOAD_FIT_ADDRESS 0x10000000 -#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE - #endif /* __CONFIG_ZYNQ_COMMON_H */ From 40cdf26eeb560f786c54de6aba6a342887fc8011 Mon Sep 17 00:00:00 2001 From: Peng Ma Date: Wed, 4 Dec 2019 10:36:42 +0000 Subject: [PATCH 29/30] ata: sata_sil: Continue probing other sata port when failed current port. In the initialization of sata driver, we want to initialize all port probes, Therefore, any detection failure between of them should continue initialization by skipping the current port instead of exit. Signed-off-by: Peng Ma --- drivers/ata/sata_sil.c | 60 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 4a50460c5a..71ee0c04ef 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -20,6 +20,7 @@ #if CONFIG_IS_ENABLED(BLK) #include #include +#include #endif #include "sata_sil.h" @@ -763,15 +764,33 @@ U_BOOT_DRIVER(sata_sil_driver) = { .platdata_auto_alloc_size = sizeof(struct sil_sata_priv), }; +static int sil_unbind_device(struct udevice *dev) +{ + int ret; + + ret = device_remove(dev, DM_REMOVE_NORMAL); + if (ret) + return ret; + + ret = device_unbind(dev); + if (ret) + return ret; + + return 0; +} + static int sil_pci_probe(struct udevice *dev) { struct udevice *blk; + int failed_number; char sata_name[10]; pci_dev_t devno; u16 word; int ret; int i; + failed_number = 0; + /* Get PCI device number */ devno = dm_pci_get_bdf(dev); if (devno == -1) @@ -824,12 +843,44 @@ static int sil_pci_probe(struct udevice *dev) } ret = sil_init_sata(blk, i); - if (ret) - return -ENODEV; + if (ret) { + ret = sil_unbind_device(blk); + if (ret) + return ret; + + failed_number++; + continue; + } ret = scan_sata(blk, i); - if (ret) - return -ENODEV; + if (ret) { + ret = sil_unbind_device(blk); + if (ret) + return ret; + + failed_number++; + continue; + } + } + + if (failed_number == sata_info.maxport) + return -ENODEV; + else + return 0; +} + +static int sil_pci_remove(struct udevice *dev) +{ + int i; + struct sil_sata *sata; + struct sil_sata_priv *priv; + + priv = dev_get_priv(dev); + + for (i = sata_info.portbase; i < sata_info.maxport; i++) { + sata = priv->sil_sata_desc[i]; + if (sata) + free(sata); } return 0; @@ -857,6 +908,7 @@ U_BOOT_DRIVER(sil_ahci_pci) = { .of_match = sil_pci_ids, .ops = &sata_sil_ops, .probe = sil_pci_probe, + .remove = sil_pci_remove, .priv_auto_alloc_size = sizeof(struct sil_sata_priv), }; From 964b90f61d2b49844bd42d0a0580e1a404063ee1 Mon Sep 17 00:00:00 2001 From: Peng Ma Date: Wed, 4 Dec 2019 10:36:45 +0000 Subject: [PATCH 30/30] ata: fsl_sata: Continue probing other sata port when failed current port. In the initialization of sata driver, we want to initialize all port probes, Therefore, any detection failure between of them should continue initialization by skipping the current port instead of exit. Signed-off-by: Peng Ma --- drivers/ata/fsl_sata.c | 58 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/drivers/ata/fsl_sata.c b/drivers/ata/fsl_sata.c index 6609bf8a76..c6680dc1c9 100644 --- a/drivers/ata/fsl_sata.c +++ b/drivers/ata/fsl_sata.c @@ -22,6 +22,7 @@ #include #include #include +#include #else #ifndef CONFIG_SYS_SATA1_FLAGS #define CONFIG_SYS_SATA1_FLAGS FLAGS_DMA @@ -122,7 +123,7 @@ static int init_sata(struct fsl_ata_priv *priv, int dev) /* Zero all of the device driver struct */ memset((void *)sata, 0, sizeof(fsl_sata_t)); - snprintf(sata->name, 12, "SATA%d:\n", dev); + snprintf(sata->name, 12, "SATA%d:", dev); /* Set the controller register base address to device struct */ #if !CONFIG_IS_ENABLED(BLK) @@ -233,10 +234,7 @@ static int init_sata(struct fsl_ata_priv *priv, int dev) mdelay(100); /* print sata device name */ - if (!dev) - printf("%s ", sata->name); - else - printf(" %s ", sata->name); + printf("%s ", sata->name); /* Wait PHY RDY signal changed for 500ms */ ata_wait_register(®->hstatus, HSTATUS_PHY_RDY, @@ -917,15 +915,32 @@ static int fsl_ata_ofdata_to_platdata(struct udevice *dev) return 0; } +static int fsl_unbind_device(struct udevice *dev) +{ + int ret; + + ret = device_remove(dev, DM_REMOVE_NORMAL); + if (ret) + return ret; + + ret = device_unbind(dev); + if (ret) + return ret; + + return 0; +} + static int fsl_ata_probe(struct udevice *dev) { struct fsl_ata_priv *blk_priv, *priv; struct udevice *blk; + int failed_number; char sata_name[10]; int nr_ports; int ret; int i; + failed_number = 0; priv = dev_get_priv(dev); nr_ports = priv->number; nr_ports = min(nr_ports, CONFIG_SYS_SATA_MAX_DEVICE); @@ -943,7 +958,12 @@ static int fsl_ata_probe(struct udevice *dev) ret = init_sata(priv, i); if (ret) { debug("%s: Failed to init sata\n", __func__); - return ret; + ret = fsl_unbind_device(blk); + if (ret) + return ret; + + failed_number++; + continue; } blk_priv = dev_get_platdata(blk); @@ -952,10 +972,33 @@ static int fsl_ata_probe(struct udevice *dev) ret = scan_sata(blk); if (ret) { debug("%s: Failed to scan bus\n", __func__); - return ret; + ret = fsl_unbind_device(blk); + if (ret) + return ret; + + failed_number++; + continue; } } + if (failed_number == nr_ports) + return -ENODEV; + else + return 0; +} + +static int fsl_ata_remove(struct udevice *dev) +{ + fsl_sata_t *sata; + struct fsl_ata_priv *priv; + + priv = dev_get_priv(dev); + sata = priv->fsl_sata; + + free(sata->cmd_hdr_tbl_offset); + free(sata->cmd_desc_offset); + free(sata); + return 0; } @@ -982,6 +1025,7 @@ U_BOOT_DRIVER(fsl_ahci) = { .ops = &sata_fsl_ahci_ops, .ofdata_to_platdata = fsl_ata_ofdata_to_platdata, .probe = fsl_ata_probe, + .remove = fsl_ata_remove, .priv_auto_alloc_size = sizeof(struct fsl_ata_priv), }; #endif