]> git.baikalelectronics.ru Git - uboot.git/commitdiff
image: Allow loading a FIT image for a particular phase
authorSimon Glass <sjg@chromium.org>
Fri, 21 Oct 2022 00:23:04 +0000 (18:23 -0600)
committerTom Rini <trini@konsulko.com>
Mon, 31 Oct 2022 15:02:45 +0000 (11:02 -0400)
Add support for filtering out FIT images by phase. Rather than adding yet
another argument to this already overloaded function, use a composite
value, where the phase is only added in if needed.

The FIT config is still selected (and verified) as normal, but the images
are selected based on the phase.

Tests for this come in a little later, as part of the updated VPL test.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/image-fit.c
doc/uImage.FIT/howto.txt
include/image.h

index 02f1d28c771b078053628d66c1aea874f29c1d41..3cc556b727f5a01af255f733725abe45a2dd247e 100644 (file)
@@ -802,6 +802,40 @@ int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
        return 0;
 }
 
+/**
+ * fit_image_get_phase() - get the phase for a configuration node
+ * @fit: pointer to the FIT format image header
+ * @offset: configuration-node offset
+ * @phasep: returns the phase
+ *
+ * Finds the phase property in a given configuration node. If the property is
+ * found, its (string) value is translated to the numeric id which is returned
+ * to the caller.
+ *
+ * Returns: 0 on success, -ENOENT if missing, -EINVAL for invalid value
+ */
+int fit_image_get_phase(const void *fit, int offset, enum image_phase_t *phasep)
+{
+       const void *data;
+       int len, ret;
+
+       /* Get phase name from property data */
+       data = fdt_getprop(fit, offset, FIT_PHASE_PROP, &len);
+       if (!data) {
+               fit_get_debug(fit, offset, FIT_PHASE_PROP, len);
+               *phasep = 0;
+               return -ENOENT;
+       }
+
+       /* Translate phase name to id */
+       ret = genimg_get_phase_id(data);
+       if (ret < 0)
+               return ret;
+       *phasep = ret;
+
+       return 0;
+}
+
 static int fit_image_get_address(const void *fit, int noffset, char *name,
                          ulong *load)
 {
@@ -1867,10 +1901,37 @@ int fit_conf_get_prop_node_index(const void *fit, int noffset,
        return fit_image_get_node(fit, uname);
 }
 
-int fit_conf_get_prop_node(const void *fit, int noffset,
-               const char *prop_name)
+int fit_conf_get_prop_node(const void *fit, int noffset, const char *prop_name,
+                          enum image_phase_t sel_phase)
 {
-       return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0);
+       int i, count;
+
+       if (sel_phase == IH_PHASE_NONE)
+               return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0);
+
+       count = fit_conf_get_prop_node_count(fit, noffset, prop_name);
+       if (count < 0)
+               return count;
+
+       /* check each image in the list */
+       for (i = 0; i < count; i++) {
+               enum image_phase_t phase;
+               int ret, node;
+
+               node = fit_conf_get_prop_node_index(fit, noffset, prop_name, i);
+               ret = fit_image_get_phase(fit, node, &phase);
+
+               /* if the image is for any phase, let's use it */
+               if (ret == -ENOENT)
+                       return node;
+               else if (ret < 0)
+                       return ret;
+
+               if (phase == sel_phase)
+                       return node;
+       }
+
+       return -ENOENT;
 }
 
 static int fit_get_data_tail(const void *fit, int noffset,
@@ -1906,7 +1967,8 @@ int fit_get_data_conf_prop(const void *fit, const char *prop_name,
 {
        int noffset = fit_conf_get_node(fit, NULL);
 
-       noffset = fit_conf_get_prop_node(fit, noffset, prop_name);
+       noffset = fit_conf_get_prop_node(fit, noffset, prop_name,
+                                        IH_PHASE_NONE);
        return fit_get_data_tail(fit, noffset, data, size);
 }
 
@@ -1944,7 +2006,8 @@ int fit_get_node_from_config(struct bootm_headers *images,
                return -EINVAL;
        }
 
-       noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
+       noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name,
+                                        IH_PHASE_NONE);
        if (noffset < 0) {
                debug("*  %s: no '%s' in config\n", prop_name, prop_name);
                return -ENOENT;
@@ -1990,9 +2053,10 @@ static const char *fit_get_image_type_property(int type)
 
 int fit_image_load(struct bootm_headers *images, ulong addr,
                   const char **fit_unamep, const char **fit_uname_configp,
-                  int arch, int image_type, int bootstage_id,
+                  int arch, int ph_type, int bootstage_id,
                   enum fit_load_op load_op, ulong *datap, ulong *lenp)
 {
+       int image_type = image_ph_type(ph_type);
        int cfg_noffset, noffset;
        const char *fit_uname;
        const char *fit_uname_config;
@@ -2038,8 +2102,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
                if (IS_ENABLED(CONFIG_FIT_BEST_MATCH) && !fit_uname_config) {
                        cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
                } else {
-                       cfg_noffset = fit_conf_get_node(fit,
-                                                       fit_uname_config);
+                       cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
                }
                if (cfg_noffset < 0) {
                        puts("Could not find configuration node\n");
@@ -2067,8 +2130,8 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
 
                bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
 
-               noffset = fit_conf_get_prop_node(fit, cfg_noffset,
-                                                prop_name);
+               noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name,
+                                                image_ph_phase(ph_type));
                fit_uname = fit_get_name(fit, noffset, NULL);
        }
        if (noffset < 0) {
index 019dda24a081b910f509e1a1b957cbf81bd7be2b..6dbd17dc8ca024308dae006268a0019228474e1e 100644 (file)
@@ -70,6 +70,12 @@ The SPL also records to a DT all additional images (called loadables) which are
 loaded. The information about loadables locations is passed via the DT node with
 fit-images name.
 
+Finally, if there are multiple xPL phases (e.g. SPL, VPL), images can be marked
+as intended for a particular phase using the 'phase' property. For example, if
+fit_image_load() is called with image_ph(IH_PHASE_SPL, IH_TYPE_FIRMWARE), then
+only the image listed into the "firmware" property where phase is set to "spl"
+will be loaded.
+
 Loadables Example
 -----------------
 Consider the following case for an ARM64 platform where U-Boot runs in EL2
index 7c3dcc407c0f3fce9d29ab2ed296495468151065..65d0d4f4387d2dbcdee2f470f02a581d0bf176ad 100644 (file)
@@ -691,9 +691,10 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
  *                     name (e.g. "conf-1") or NULL to use the default. On
  *                     exit points to the selected configuration name.
  * @param arch         Expected architecture (IH_ARCH_...)
- * @param image_type   Required image type (IH_TYPE_...). If this is
+ * @param image_ph_type        Required image type (IH_TYPE_...). If this is
  *                     IH_TYPE_KERNEL then we allow IH_TYPE_KERNEL_NOLOAD
- *                     also.
+ *                     also. If a phase is required, this is included also,
+ *                     see image_phase_and_type()
  * @param bootstage_id ID of starting bootstage to use for progress updates.
  *                     This will be added to the BOOTSTAGE_SUB values when
  *                     calling bootstage_mark()
@@ -704,7 +705,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
  */
 int fit_image_load(struct bootm_headers *images, ulong addr,
                   const char **fit_unamep, const char **fit_uname_configp,
-                  int arch, int image_type, int bootstage_id,
+                  int arch, int image_ph_type, int bootstage_id,
                   enum fit_load_op load_op, ulong *datap, ulong *lenp);
 
 /**
@@ -1349,14 +1350,15 @@ int fit_conf_get_prop_node_index(const void *fit, int noffset,
  * @fit:       FIT to check
  * @noffset:   Offset of conf@xxx node to check
  * @prop_name: Property to read from the conf node
+ * @phase:     Image phase to use, IH_PHASE_NONE for any
  *
  * The conf- nodes contain references to other nodes, using properties
  * like 'kernel = "kernel"'. Given such a property name (e.g. "kernel"),
  * return the offset of the node referred to (e.g. offset of node
  * "/images/kernel".
  */
-int fit_conf_get_prop_node(const void *fit, int noffset,
-               const char *prop_name);
+int fit_conf_get_prop_node(const void *fit, int noffset, const char *prop_name,
+                          enum image_phase_t phase);
 
 int fit_check_ramdisk(const void *fit, int os_noffset,
                uint8_t arch, int verify);