ARM: imx8m: Do not define do_reset() if sysreset is enabled
[oweals/u-boot.git] / common / spl / spl_fit.c
index 346f9edaa52d9fac7063dd201ad84b21104ffae9..c51e4beb1c0e2b8c24e265275d90bb20c7b7ec52 100644 (file)
@@ -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;
+               }
+       }
+
+       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;
                }
        }
 
-       *outname = (char *)str;
+       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;
        }
 
@@ -195,11 +259,9 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
                        debug("%s ", genimg_get_type_name(type));
        }
 
-       if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP)) {
-               if (fit_image_get_comp(fit, node, &image_comp))
-                       puts("Cannot get image compression format.\n");
-               else
-                       debug("%s ", genimg_get_comp_name(image_comp));
+       if (IS_ENABLED(CONFIG_SPL_GZIP)) {
+               fit_image_get_comp(fit, node, &image_comp);
+               debug("%s ", genimg_get_comp_name(image_comp));
        }
 
        if (fit_image_get_load(fit, node, &load_addr))
@@ -281,7 +343,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 +352,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 +375,64 @@ 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));
+               }
+               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 +443,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",
@@ -527,10 +645,6 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 
                if (!spl_fit_image_get_os(fit, node, &os_type))
                        debug("Loadable is %s\n", genimg_get_os_name(os_type));
-#if CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
-               else
-                       os_type = IH_OS_U_BOOT;
-#endif
 
                if (os_type == IH_OS_U_BOOT) {
                        spl_fit_append_fdt(&image_info, info, sector,