[PATCH 0/7] SPL: FIT: Bring the SPL_LOAD_FIT path in line with documentation

When I wrote commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax"), I did not expect it to go through without objection. I didn't also write the code to go along with it. This series fixes that by updating one of the three FIT code paths to be compliant.
There are three code paths that deal with loading a FIT: * 'bootm' command * SPL_LOAD_FIT * SPL_LOAD_FIT_FULL
I chose to start with SPL_LOAD_FIT, because that's the code I'm most familiar with. Also, by its simplicity, it is the most generic FIT loading code, and the easiest to make compliant.
I also chose not to fix every nook and cranny because nobody is using those corner cases -- as evidenced by the lack of support. Instead, I chose to document known limitations.
Alexandru Gagniuc (7): spl: fit: Don't overwrite previous loadable if "load" is missing doc: FIT image: Introduce "u-boot,fpga-legacy" property spl: fit: Move FPGA loading code to separate functions spl: fit: Warn if FIT contains "fpga" property in config node spl: fit: Support loading FPGA images from list of "loadables" Kconfig: Document the limitations of the simple SPL_LOAD_FIT path doc: FIT image: Update FPGA example to make use of "loadables"
common/Kconfig.boot | 10 +++ common/spl/spl_fit.c | 113 ++++++++++++++++++++------ doc/uImage.FIT/multi-with-fpga.its | 3 +- doc/uImage.FIT/source_file_format.txt | 1 + 4 files changed, 99 insertions(+), 28 deletions(-)

spl_load_fit_image() will try to load an image at the address given in the "load" property. Absent such property, it uses
image_info->load_addr
Correct use of this is demonstrated in spl_fit_append_fdt(), which resets the 'load_addr' before each spl_load_fit_image() call.
On the other hand loading "loadables" loop in spl_load_simple_fit() completely ignores this. It re-uses the same structure, but doesn't reset load_addr. If loadable [i] does not have a "load" property, its load address defaults to load_addr, which still contains the address of loadable [i - 1].
A simple solution is to treat NULL as an invalid load address. The caller can set load_addr = 0 to request an abort if the "load" property is absent.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- common/spl/spl_fit.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 75c8ff065b..43fc43cf2b 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -223,7 +223,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, * @image_info: will be filled with information about the loaded image * If the FIT node does not contain a "load" (address) property, * the image gets loaded to the address pointed to by the - * load_addr member in this struct. + * load_addr member in this struct, if load_addr is not NULL * * Return: 0 on success or a negative error number. */ @@ -258,8 +258,14 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, debug("%s ", genimg_get_comp_name(image_comp)); }
- if (fit_image_get_load(fit, node, &load_addr)) + if (fit_image_get_load(fit, node, &load_addr)) { + if (!image_info->load_addr) { + printf("Can't load %s: No load address and no buffer\n", + fit_get_name(fit, node, NULL)); + return -ENOBUFS; + } load_addr = image_info->load_addr; + }
if (!fit_image_get_data_position(fit, node, &offset)) { external_data = true; @@ -697,6 +703,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (firmware_node == node) continue;
+ image_info.load_addr = 0; ret = spl_load_fit_image(info, sector, &ctx, node, &image_info); if (ret < 0) { printf("%s: can't load image loadables index %d (ret = %d)\n",

Hi Alexandru,
On Wed, 10 Mar 2021 at 11:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
spl_load_fit_image() will try to load an image at the address given in the "load" property. Absent such property, it uses
image_info->load_addr
Correct use of this is demonstrated in spl_fit_append_fdt(), which resets the 'load_addr' before each spl_load_fit_image() call.
On the other hand loading "loadables" loop in spl_load_simple_fit() completely ignores this. It re-uses the same structure, but doesn't reset load_addr. If loadable [i] does not have a "load" property, its load address defaults to load_addr, which still contains the address of loadable [i - 1].
A simple solution is to treat NULL as an invalid load address. The caller can set load_addr = 0 to request an abort if the "load" property is absent.
Another way would be to add a load_valid bool or flag to the struct.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 75c8ff065b..43fc43cf2b 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -223,7 +223,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size,
- @image_info: will be filled with information about the loaded image
If the FIT node does not contain a "load" (address) property,
the image gets loaded to the address pointed to by the
load_addr member in this struct.
load_addr member in this struct, if load_addr is not NULL
s/NULL/0/
This is not a pointer, but an address.
- Return: 0 on success or a negative error number.
*/ @@ -258,8 +258,14 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, debug("%s ", genimg_get_comp_name(image_comp)); }
if (fit_image_get_load(fit, node, &load_addr))
if (fit_image_get_load(fit, node, &load_addr)) {
if (!image_info->load_addr) {
printf("Can't load %s: No load address and no buffer\n",
fit_get_name(fit, node, NULL));
return -ENOBUFS;
} load_addr = image_info->load_addr;
} if (!fit_image_get_data_position(fit, node, &offset)) { external_data = true;
@@ -697,6 +703,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (firmware_node == node) continue;
image_info.load_addr = 0; ret = spl_load_fit_image(info, sector, &ctx, node, &image_info); if (ret < 0) { printf("%s: can't load image loadables index %d (ret = %d)\n",
-- 2.26.2
Reviewed-by: Simon Glass sjg@chromium.org
Regards, Simon

Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") introduced a "compatible" property for loadable images. It did not define its contents. Use "u-boot,fpga-legacy" compatible string to specify that fpga_load() should be used to load the image.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- doc/uImage.FIT/source_file_format.txt | 1 + 1 file changed, 1 insertion(+)
diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt index 00ed3ebe93..f93ac6d1c7 100644 --- a/doc/uImage.FIT/source_file_format.txt +++ b/doc/uImage.FIT/source_file_format.txt @@ -184,6 +184,7 @@ the '/images' node should have the following layout: Mandatory for types: "firmware", and "kernel". - compatible : compatible method for loading image. Mandatory for types: "fpga", and images that do not specify a load address. + To use the generic fpga loading routine, use "u-boot,fpga-legacy".
Optional nodes: - hash-1 : Each hash sub-node represents separate hash or checksum

The FPGA loading code in spl_simple_fit_read() can easily be separated from the rest of the logic. It is split into two functions instead of one because spl_fit_upload_fpga() is used in a subsequent patch.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- common/spl/spl_fit.c | 69 ++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 25 deletions(-)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 43fc43cf2b..55fca9f399 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -526,6 +526,48 @@ __weak bool spl_load_simple_fit_skip_processing(void) return false; }
+static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, + struct spl_image_info *fpga_image) +{ + int ret; + + debug("FPGA bitstream at: %x, size: %x\n", + (u32)fpga_image->load_addr, fpga_image->size); + + ret = fpga_load(0, (void *)fpga_image->load_addr, fpga_image->size, + BIT_FULL); + if (ret) { + printf("%s: Cannot load the image to the FPGA\n", __func__); + return ret; + } + + puts("FPGA image loaded from FIT\n"); + return 0; +} + +static int spl_fit_load_fpga(struct spl_fit_info *ctx, + struct spl_load_info *info, ulong sector) +{ + int node, ret; + + struct spl_image_info fpga_image = { + .load_addr = 0, + }; + + node = spl_fit_get_image_node(ctx, "fpga", 0); + if (node < 0) + return node; + + /* Load the image and set up the fpga_image structure */ + ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image); + if (ret) { + printf("%s: Cannot load the FPGA: %i\n", __func__, ret); + return ret; + } + + return spl_fit_upload_fpga(ctx, node, &fpga_image); +} + static int spl_simple_fit_read(struct spl_fit_info *ctx, struct spl_load_info *info, ulong sector, const void *fit_header) @@ -609,31 +651,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (ret < 0) return ret;
-#ifdef CONFIG_SPL_FPGA - node = spl_fit_get_image_node(&ctx, "fpga", 0); - if (node >= 0) { - /* Load the image and set up the spl_image structure */ - ret = spl_load_fit_image(info, sector, &ctx, node, spl_image); - if (ret) { - printf("%s: Cannot load the FPGA: %i\n", __func__, ret); - return ret; - } - - debug("FPGA bitstream at: %x, size: %x\n", - (u32)spl_image->load_addr, spl_image->size); - - ret = fpga_load(0, (const void *)spl_image->load_addr, - spl_image->size, BIT_FULL); - if (ret) { - printf("%s: Cannot load the image to the FPGA\n", - __func__); - return ret; - } - - puts("FPGA image loaded from FIT\n"); - node = -1; - } -#endif + if (IS_ENABLED(CONFIG_SPL_FPGA)) + spl_fit_load_fpga(&ctx, info, sector);
/* * Find the U-Boot image using the following search order:

Hi Alexandru,
On Wed, 10 Mar 2021 at 11:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
The FPGA loading code in spl_simple_fit_read() can easily be separated from the rest of the logic. It is split into two functions instead of one because spl_fit_upload_fpga() is used in a subsequent patch.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 69 ++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 25 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 43fc43cf2b..55fca9f399 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -526,6 +526,48 @@ __weak bool spl_load_simple_fit_skip_processing(void) return false; }
+static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node,
struct spl_image_info *fpga_image)
+{
int ret;
debug("FPGA bitstream at: %x, size: %x\n",
(u32)fpga_image->load_addr, fpga_image->size);
ret = fpga_load(0, (void *)fpga_image->load_addr, fpga_image->size,
BIT_FULL);
if (ret) {
printf("%s: Cannot load the image to the FPGA\n", __func__);
return ret;
}
puts("FPGA image loaded from FIT\n");
Please add a blank line before last return in a function
return 0;
+}
+static int spl_fit_load_fpga(struct spl_fit_info *ctx,
struct spl_load_info *info, ulong sector)
+{
int node, ret;
struct spl_image_info fpga_image = {
.load_addr = 0,
};
node = spl_fit_get_image_node(ctx, "fpga", 0);
if (node < 0)
return node;
/* Load the image and set up the fpga_image structure */
ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image);
if (ret) {
printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
return ret;
}
return spl_fit_upload_fpga(ctx, node, &fpga_image);
+}
static int spl_simple_fit_read(struct spl_fit_info *ctx, struct spl_load_info *info, ulong sector, const void *fit_header) @@ -609,31 +651,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (ret < 0) return ret;
-#ifdef CONFIG_SPL_FPGA
node = spl_fit_get_image_node(&ctx, "fpga", 0);
if (node >= 0) {
/* Load the image and set up the spl_image structure */
ret = spl_load_fit_image(info, sector, &ctx, node, spl_image);
if (ret) {
printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
return ret;
}
debug("FPGA bitstream at: %x, size: %x\n",
(u32)spl_image->load_addr, spl_image->size);
ret = fpga_load(0, (const void *)spl_image->load_addr,
spl_image->size, BIT_FULL);
if (ret) {
printf("%s: Cannot load the image to the FPGA\n",
__func__);
return ret;
}
puts("FPGA image loaded from FIT\n");
node = -1;
}
-#endif
if (IS_ENABLED(CONFIG_SPL_FPGA))
spl_fit_load_fpga(&ctx, info, sector); /* * Find the U-Boot image using the following search order:
-- 2.26.2
Regards, Simon

Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") requires that FPGA images be referenced through the "loadables" in the config node. This means that "fpga" properties in config nodes are deprecated.
Given that there are likely FIT images which use "fpga", let's not break those right away. Print a warning message that such use is deprecated, and give users a couple of releases to update their
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- common/spl/spl_fit.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 55fca9f399..68f29c0026 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -526,6 +526,13 @@ __weak bool spl_load_simple_fit_skip_processing(void) return false; }
+static void warn_deprecated(const char *msg) +{ + printf("DEPRECATED: %s\n", msg); + printf("\tThis will stop working in a future u-boot release\n"); + printf("\tSee doc/uImage.FIT/source_file_format.txt\n"); +} + static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, struct spl_image_info *fpga_image) { @@ -558,6 +565,8 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, if (node < 0) return node;
+ warn_deprecated("'fpga' property in config node. Use 'loadables'"); + /* Load the image and set up the fpga_image structure */ ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image); if (ret) {

Hi Alexandru,
On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") requires that FPGA images be referenced through the "loadables" in the config node. This means that "fpga" properties in config nodes are deprecated.
Given that there are likely FIT images which use "fpga", let's not break those right away. Print a warning message that such use is deprecated, and give users a couple of releases to update their
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 55fca9f399..68f29c0026 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -526,6 +526,13 @@ __weak bool spl_load_simple_fit_skip_processing(void) return false; }
+static void warn_deprecated(const char *msg) +{
printf("DEPRECATED: %s\n", msg);
printf("\tThis will stop working in a future u-boot release\n");
printf("\tSee doc/uImage.FIT/source_file_format.txt\n");
That is a lot of text to add...can it be shorter?
+}
static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, struct spl_image_info *fpga_image) { @@ -558,6 +565,8 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, if (node < 0) return node;
warn_deprecated("'fpga' property in config node. Use 'loadables'");
/* Load the image and set up the fpga_image structure */ ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image); if (ret) {
-- 2.26.2
Regards, Simon

On 3/18/21 1:44 AM, Simon Glass wrote:
Hi Alexandru,
On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") requires that FPGA images be referenced through the "loadables" in the config node. This means that "fpga" properties in config nodes are deprecated.
Given that there are likely FIT images which use "fpga", let's not break those right away. Print a warning message that such use is deprecated, and give users a couple of releases to update their
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 55fca9f399..68f29c0026 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -526,6 +526,13 @@ __weak bool spl_load_simple_fit_skip_processing(void) return false; }
+static void warn_deprecated(const char *msg) +{
printf("DEPRECATED: %s\n", msg);
printf("\tThis will stop working in a future u-boot release\n");
printf("\tSee doc/uImage.FIT/source_file_format.txt\n");
That is a lot of text to add...can it be shorter?
Sure. The idea was that we'd remove this message in a couple of releases anyway, and we want it very loud until then. If I remove the middle printf(), will thgat work ?
Alex
+}
- static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, struct spl_image_info *fpga_image) {
@@ -558,6 +565,8 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx, if (node < 0) return node;
warn_deprecated("'fpga' property in config node. Use 'loadables'");
/* Load the image and set up the fpga_image structure */ ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image); if (ret) {
-- 2.26.2
Regards, Simon

Hi Alex,
On Sat, 20 Mar 2021 at 03:53, Alex G. mr.nuke.me@gmail.com wrote:
On 3/18/21 1:44 AM, Simon Glass wrote:
Hi Alexandru,
On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") requires that FPGA images be referenced through the "loadables" in the config node. This means that "fpga" properties in config nodes are deprecated.
Given that there are likely FIT images which use "fpga", let's not break those right away. Print a warning message that such use is deprecated, and give users a couple of releases to update their
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 55fca9f399..68f29c0026 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -526,6 +526,13 @@ __weak bool spl_load_simple_fit_skip_processing(void) return false; }
+static void warn_deprecated(const char *msg) +{
printf("DEPRECATED: %s\n", msg);
printf("\tThis will stop working in a future u-boot release\n");
printf("\tSee doc/uImage.FIT/source_file_format.txt\n");
That is a lot of text to add...can it be shorter?
Sure. The idea was that we'd remove this message in a couple of releases anyway, and we want it very loud until then. If I remove the middle printf(), will thgat work ?
Sounds good, people can always look at the code for a message.
Regards, Simon

Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") and delegated FPGA images to be added via the list of "loadables" in lieu of the "fpga" property. Now actually implement this in code.
Note that the "compatible" property is ignored for the time being, as implementing "compatible" loading is beyond the scope of this change. However, "u-boot,fpga-legacy" is accepted without warning.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- common/spl/spl_fit.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 68f29c0026..ca6be6a839 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -477,6 +477,20 @@ static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, return ret; }
+static int spl_fit_image_is_fpga(const void *fit, int node) +{ + const char *type; + + if (!IS_ENABLED(CONFIG_SPL_FPGA)) + return 0; + + type = fdt_getprop(fit, node, FIT_TYPE_PROP, NULL); + if (!type) + return 0; + + return !strcmp(type, "fpga"); +} + static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) { if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) || CONFIG_IS_ENABLED(OS_BOOT)) @@ -536,11 +550,18 @@ static void warn_deprecated(const char *msg) static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, struct spl_image_info *fpga_image) { + const char *compatible; int ret;
debug("FPGA bitstream at: %x, size: %x\n", (u32)fpga_image->load_addr, fpga_image->size);
+ compatible = fdt_getprop(ctx->fit, node, "compatible", NULL); + if (!compatible) + warn_deprecated("'fpga' image without 'compatible' property"); + else if (strcmp(compatible, "u-boot,fpga-legacy")) + printf("Ignoring compatible = %s property\n", compatible); + ret = fpga_load(0, (void *)fpga_image->load_addr, fpga_image->size, BIT_FULL); if (ret) { @@ -739,6 +760,9 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, return ret; }
+ if (spl_fit_image_is_fpga(ctx.fit, node)) + spl_fit_upload_fpga(&ctx, node, &image_info); + if (!spl_fit_image_get_os(ctx.fit, node, &os_type)) debug("Loadable is %s\n", genimg_get_os_name(os_type));

Hi Alexandru,
On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") and delegated FPGA images to be added via the list of "loadables" in lieu of the "fpga" property. Now actually implement this in code.
Note that the "compatible" property is ignored for the time being, as implementing "compatible" loading is beyond the scope of this change. However, "u-boot,fpga-legacy" is accepted without warning.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 68f29c0026..ca6be6a839 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -477,6 +477,20 @@ static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, return ret; }
+static int spl_fit_image_is_fpga(const void *fit, int node) +{
const char *type;
if (!IS_ENABLED(CONFIG_SPL_FPGA))
return 0;
type = fdt_getprop(fit, node, FIT_TYPE_PROP, NULL);
if (!type)
return 0;
return !strcmp(type, "fpga");
+}
static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) { if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) || CONFIG_IS_ENABLED(OS_BOOT)) @@ -536,11 +550,18 @@ static void warn_deprecated(const char *msg) static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, struct spl_image_info *fpga_image) {
const char *compatible; int ret; debug("FPGA bitstream at: %x, size: %x\n", (u32)fpga_image->load_addr, fpga_image->size);
compatible = fdt_getprop(ctx->fit, node, "compatible", NULL);
if (!compatible)
warn_deprecated("'fpga' image without 'compatible' property");
else if (strcmp(compatible, "u-boot,fpga-legacy"))
printf("Ignoring compatible = %s property\n", compatible);
ret = fpga_load(0, (void *)fpga_image->load_addr, fpga_image->size, BIT_FULL); if (ret) {
@@ -739,6 +760,9 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, return ret; }
if (spl_fit_image_is_fpga(ctx.fit, node))
spl_fit_upload_fpga(&ctx, node, &image_info);
Given the code-size increase I think a new Kconfig option for SPL FPGA FIT support would be useful.
if (!spl_fit_image_get_os(ctx.fit, node, &os_type)) debug("Loadable is %s\n", genimg_get_os_name(os_type));
-- 2.26.2
Regards, Simon

On 3/29/21 2:43 AM, Simon Glass wrote:
Hi Alexandru,
On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
Commit 4afc4f37c70e ("doc: FIT image: Clarify format and simplify syntax") and delegated FPGA images to be added via the list of "loadables" in lieu of the "fpga" property. Now actually implement this in code.
Note that the "compatible" property is ignored for the time being, as implementing "compatible" loading is beyond the scope of this change. However, "u-boot,fpga-legacy" is accepted without warning.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/spl/spl_fit.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 68f29c0026..ca6be6a839 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -477,6 +477,20 @@ static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, return ret; }
+static int spl_fit_image_is_fpga(const void *fit, int node) +{
const char *type;
if (!IS_ENABLED(CONFIG_SPL_FPGA))
return 0;
type = fdt_getprop(fit, node, FIT_TYPE_PROP, NULL);
if (!type)
return 0;
return !strcmp(type, "fpga");
+}
- static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) { if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) || CONFIG_IS_ENABLED(OS_BOOT))
@@ -536,11 +550,18 @@ static void warn_deprecated(const char *msg) static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, struct spl_image_info *fpga_image) {
const char *compatible; int ret; debug("FPGA bitstream at: %x, size: %x\n", (u32)fpga_image->load_addr, fpga_image->size);
compatible = fdt_getprop(ctx->fit, node, "compatible", NULL);
if (!compatible)
warn_deprecated("'fpga' image without 'compatible' property");
else if (strcmp(compatible, "u-boot,fpga-legacy"))
printf("Ignoring compatible = %s property\n", compatible);
ret = fpga_load(0, (void *)fpga_image->load_addr, fpga_image->size, BIT_FULL); if (ret) {
@@ -739,6 +760,9 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, return ret; }
if (spl_fit_image_is_fpga(ctx.fit, node))
spl_fit_upload_fpga(&ctx, node, &image_info);
Given the code-size increase I think a new Kconfig option for SPL FPGA FIT support would be useful.
The "if !IS_ENABLED(CONFIG_SPL_FPGA))" makes spl_fit_image_is_fpga() a no-op, with no size increase when "# CONFIG_SPL_FPGA is not set". This is also confirmed by comparing the size of .text ( "objdump -h spl/u-boot-spl" ). So there isn't a size increase for non-FPGA use cases.
Also, FPGA support in SPL is only possible through FIT images. So SPL_FPGA vs SPL_FIT_FPGA distinction doesn't make sense.
Alex
if (!spl_fit_image_get_os(ctx.fit, node, &os_type)) debug("Loadable is %s\n", genimg_get_os_name(os_type));
-- 2.26.2
Regards, Simon

The "simple" SPL_LOAD_FIT path is the most compliant with the format documented in doc/uImage.FIT/source_file_format.txt. The other two paths to load a FIT are SPL_LOAD_FIT_FULL and the "bootm" command.
Since the Kconfig menu is the most likely place for a new user to see these options, it seems like the most logical candidate to document the limitations. This documents the _know_ issues, and is not intended to be a complete list of all follies.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- common/Kconfig.boot | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/common/Kconfig.boot b/common/Kconfig.boot index 9c335f4f8c..f77e59a22a 100644 --- a/common/Kconfig.boot +++ b/common/Kconfig.boot @@ -202,6 +202,16 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot.
+ This path has the following limitations: + + 1. "loadables" images, other than FTDs, which do not have a "load" + will not be loaded. This limitation also applies to FPGA images + with the correct "compatible" string. + 2. For FPGA images, only the "compatible" = "u-boot,fpga-legacy" + loading method is supported. + 3. FDTs are only loaded for images with an "os" property of "u-boot". + "linux" images are also supported with Falcon boot mode. + config SPL_LOAD_FIT_ADDRESS hex "load address of fit image" depends on SPL_LOAD_FIT

Hi Alexandru,
On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
The "simple" SPL_LOAD_FIT path is the most compliant with the format documented in doc/uImage.FIT/source_file_format.txt. The other two paths to load a FIT are SPL_LOAD_FIT_FULL and the "bootm" command.
Since the Kconfig menu is the most likely place for a new user to see these options, it seems like the most logical candidate to document the limitations. This documents the _know_ issues, and is not intended
known
to be a complete list of all follies.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
common/Kconfig.boot | 10 ++++++++++ 1 file changed, 10 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/common/Kconfig.boot b/common/Kconfig.boot index 9c335f4f8c..f77e59a22a 100644 --- a/common/Kconfig.boot +++ b/common/Kconfig.boot @@ -202,6 +202,16 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot.
This path has the following limitations:
1. "loadables" images, other than FTDs, which do not have a "load"
property
will not be loaded. This limitation also applies to FPGA images
with the correct "compatible" string.
2. For FPGA images, only the "compatible" = "u-boot,fpga-legacy"
loading method is supported.
3. FDTs are only loaded for images with an "os" property of "u-boot".
"linux" images are also supported with Falcon boot mode.
config SPL_LOAD_FIT_ADDRESS hex "load address of fit image" depends on SPL_LOAD_FIT -- 2.26.2
Regards, Simon

The new correct way to load an FPGA image is to declare it in the list of "loadables". multi-with-fpga.its used the now deprecated "fpga" property. Since this example most likely intended to use u-boot's generic FPGA loading code, compatible = "u-boot,fpga-legacy" is also appropriate here.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- doc/uImage.FIT/multi-with-fpga.its | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/uImage.FIT/multi-with-fpga.its b/doc/uImage.FIT/multi-with-fpga.its index 47ee5760c4..021cbc7cf4 100644 --- a/doc/uImage.FIT/multi-with-fpga.its +++ b/doc/uImage.FIT/multi-with-fpga.its @@ -29,6 +29,7 @@ arch = "arm"; compression = "none"; load = <0x30000000>; + compatible = "u-boot,fpga-legacy" hash-1 { algo = "md5"; }; @@ -61,7 +62,7 @@ description = "Linux with fpga"; kernel = "linux_kernel"; fdt = "fdt-1"; - fpga = "fpga"; + loadables = "fpga"; }; }; };

On Thu, 11 Mar 2021 at 07:04, Alexandru Gagniuc mr.nuke.me@gmail.com wrote:
The new correct way to load an FPGA image is to declare it in the list of "loadables". multi-with-fpga.its used the now deprecated "fpga" property. Since this example most likely intended to use u-boot's generic FPGA loading code, compatible = "u-boot,fpga-legacy" is also appropriate here.
Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com
doc/uImage.FIT/multi-with-fpga.its | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
participants (3)
-
Alex G.
-
Alexandru Gagniuc
-
Simon Glass