image: Add the concept of a phase to FIT
authorSimon Glass <sjg@chromium.org>
Fri, 21 Oct 2022 00:23:03 +0000 (18:23 -0600)
committerTom Rini <trini@konsulko.com>
Mon, 31 Oct 2022 15:02:44 +0000 (11:02 -0400)
We want to be able to mark an image as related to a phase, so we can
easily load all the images for SPL or for U-Boot proper.

Add this to the FIT specification, along with some access functions.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/image.c
doc/uImage.FIT/source_file_format.txt
include/image.h
test/boot/Makefile
test/boot/image.c [new file with mode: 0644]

index 9f95b32..b33d1df 100644 (file)
@@ -194,6 +194,13 @@ static const table_entry_t uimage_comp[] = {
        {       -1,             "",             "",                     },
 };
 
+static const table_entry_t uimage_phase[] = {
+       {       IH_PHASE_NONE,  "none",         "any",          },
+       {       IH_PHASE_U_BOOT, "u-boot",      "U-Boot phase", },
+       {       IH_PHASE_SPL,   "spl",          "SPL Phase",    },
+       {       -1,             "",             "",             },
+};
+
 struct table_info {
        const char *desc;
        int count;
@@ -215,6 +222,7 @@ static const struct table_info table_info[IH_COUNT] = {
        { "compression", IH_COMP_COUNT, uimage_comp },
        { "operating system", IH_OS_COUNT, uimage_os },
        { "image type", IH_TYPE_COUNT, uimage_type },
+       { "phase", IH_PHASE_COUNT, uimage_phase },
 };
 
 /*****************************************************************************/
@@ -656,6 +664,11 @@ const char *genimg_get_comp_name(uint8_t comp)
                                        comp));
 }
 
+const char *genimg_get_phase_name(enum image_phase_t phase)
+{
+       return get_table_entry_name(uimage_phase, "Unknown Phase", phase);
+}
+
 static const char *genimg_get_short_name(const table_entry_t *table, int val)
 {
        table = get_table_entry(table, val);
@@ -731,3 +744,8 @@ int genimg_get_comp_id(const char *name)
 {
        return (get_table_entry_id(uimage_comp, "Compression", name));
 }
+
+int genimg_get_phase_id(const char *name)
+{
+       return get_table_entry_id(uimage_phase, "Phase", name);
+}
index 0a03c94..4640e38 100644 (file)
@@ -190,6 +190,9 @@ the '/images' node should have the following layout:
     Xilinx Zynq UltraScale+ (ZymqMP) device.
     "u-boot,zynqmp-fpga-enc" - encrypted FPGA bitstream for Xilinx Zynq
     UltraScale+ (ZynqMP) device.
+  - phase : U-Boot phase for which the image is intended.
+    "spl" - image is an SPL image
+    "u-boot" - image is a U-Boot image
 
   Optional nodes:
   - hash-1 : Each hash sub-node represents separate hash or checksum
index 92efec0..7c3dcc4 100644 (file)
@@ -58,6 +58,7 @@ enum ih_category {
        IH_COMP,
        IH_OS,
        IH_TYPE,
+       IH_PHASE,
 
        IH_COUNT,
 };
@@ -184,8 +185,7 @@ enum {
  * New IDs *MUST* be appended at the end of the list and *NEVER*
  * inserted for backward compatibility.
  */
-
-enum {
+enum image_type_t {
        IH_TYPE_INVALID         = 0,    /* Invalid Image                */
        IH_TYPE_STANDALONE,             /* Standalone Program           */
        IH_TYPE_KERNEL,                 /* OS Kernel Image              */
@@ -252,6 +252,59 @@ enum {
        IH_COMP_COUNT,
 };
 
+/**
+ * Phases - images intended for particular U-Boot phases (SPL, etc.)
+ *
+ * @IH_PHASE_NONE: No phase information, can be loaded by any phase
+ * @IH_PHASE_U_BOOT: Only for U-Boot proper
+ * @IH_PHASE_SPL: Only for SPL
+ */
+enum image_phase_t {
+       IH_PHASE_NONE           = 0,
+       IH_PHASE_U_BOOT,
+       IH_PHASE_SPL,
+
+       IH_PHASE_COUNT,
+};
+
+#define IMAGE_PHASE_SHIFT      8
+#define IMAGE_PHASE_MASK       (0xff << IMAGE_PHASE_SHIFT)
+#define IMAGE_TYPE_MASK                0xff
+
+/**
+ * image_ph() - build a composite value combining and type
+ *
+ * @phase: Image phase value
+ * @type: Image type value
+ * Returns: Composite value containing both
+ */
+static inline int image_ph(enum image_phase_t phase, enum image_type_t type)
+{
+       return type | (phase << IMAGE_PHASE_SHIFT);
+}
+
+/**
+ * image_ph_phase() - obtain the phase from a composite phase/type value
+ *
+ * @image_ph_type: Composite value to convert
+ * Returns: Phase value taken from the composite value
+ */
+static inline int image_ph_phase(int image_ph_type)
+{
+       return (image_ph_type & IMAGE_PHASE_MASK) >> IMAGE_PHASE_SHIFT;
+}
+
+/**
+ * image_ph_type() - obtain the type from a composite phase/type value
+ *
+ * @image_ph_type: Composite value to convert
+ * Returns: Type value taken from the composite value
+ */
+static inline int image_ph_type(int image_ph_type)
+{
+       return image_ph_type & IMAGE_TYPE_MASK;
+}
+
 #define LZ4F_MAGIC     0x184D2204      /* LZ4 Magic Number             */
 #define IH_MAGIC       0x27051956      /* Image Magic Number           */
 #define IH_NMLEN               32      /* Image Name Length            */
@@ -438,6 +491,22 @@ const char *genimg_get_os_short_name(uint8_t comp);
 const char *genimg_get_arch_name(uint8_t arch);
 
 /**
+ * genimg_get_phase_name() - Get the friendly name for a phase
+ *
+ * @phase: Phase value to look up
+ * Returns: Friendly name for the phase (e.g. "U-Boot phase")
+ */
+const char *genimg_get_phase_name(enum image_phase_t phase);
+
+/**
+ * genimg_get_phase_id() - Convert a phase name to an ID
+ *
+ * @name: Name to convert (e.g. "u-boot")
+ * Returns: ID for that phase (e.g. IH_PHASE_U_BOOT)
+ */
+int genimg_get_phase_id(const char *name);
+
+/**
  * genimg_get_arch_short_name() - get the short name for an architecture
  *
  * @param arch Architecture type (IH_ARCH_...)
@@ -955,6 +1024,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size,
 #define FIT_FPGA_PROP          "fpga"
 #define FIT_FIRMWARE_PROP      "firmware"
 #define FIT_STANDALONE_PROP    "standalone"
+#define FIT_PHASE_PROP         "phase"
 
 #define FIT_MAX_HASH_LEN       HASH_MAX_DIGEST_SIZE
 
index 5bb3f88..d724629 100644 (file)
@@ -3,6 +3,7 @@
 # Copyright 2021 Google LLC
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
+obj-$(CONFIG_FIT) += image.o
 
 ifdef CONFIG_OF_LIVE
 obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o
diff --git a/test/boot/image.c b/test/boot/image.c
new file mode 100644 (file)
index 0000000..2844b05
--- /dev/null
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for vbe-simple bootmeth. All start with 'vbe_simple'
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include "bootstd_common.h"
+
+/* Test of image phase */
+static int test_image_phase(struct unit_test_state *uts)
+{
+       int val;
+
+       ut_asserteq_str("U-Boot phase", genimg_get_phase_name(IH_PHASE_U_BOOT));
+       ut_asserteq_str("SPL Phase", genimg_get_phase_name(IH_PHASE_SPL));
+       ut_asserteq_str("any", genimg_get_phase_name(IH_PHASE_NONE));
+       ut_asserteq_str("Unknown Phase", genimg_get_phase_name(-1));
+
+       ut_asserteq(IH_PHASE_U_BOOT, genimg_get_phase_id("u-boot"));
+       ut_asserteq(IH_PHASE_SPL, genimg_get_phase_id("spl"));
+       ut_asserteq(IH_PHASE_NONE, genimg_get_phase_id("none"));
+       ut_asserteq(-1, genimg_get_phase_id("fred"));
+
+       val = image_ph(IH_PHASE_SPL, IH_TYPE_FIRMWARE);
+       ut_asserteq(IH_PHASE_SPL, image_ph_phase(val));
+       ut_asserteq(IH_TYPE_FIRMWARE, image_ph_type(val));
+
+       return 0;
+}
+BOOTSTD_TEST(test_image_phase, 0);