[Concept,7/8] bls: Add 'fit' field for FIT image support

Message ID 20260213202417.223068-8-sjg@u-boot.org
State New
Headers
Series Add BLS Type #1 bootmethod with FIT and multi-initrd support |

Commit Message

Simon Glass Feb. 13, 2026, 8:24 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

The BLS parser only accepts 'linux' as the kernel field. This
does not distinguish between a plain kernel image and a FIT
image, making it harder for the bootmethod to handle them
differently.

Add a 'fit' field as an alternative to 'linux' for specifying
a FIT image path. The parser now accepts either 'linux' or
'fit' as the required kernel field. When both are present, 'fit'
takes priority in the bootmethod.

Add a parser unit test for a fit-only entry.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 boot/bls_parse.c      | 12 +++++++++---
 boot/bootmeth_bls.c   |  7 ++++++-
 include/bls.h         |  7 +++++--
 test/boot/bls_parse.c | 24 ++++++++++++++++++++++++
 4 files changed, 44 insertions(+), 6 deletions(-)
  

Patch

diff --git a/boot/bls_parse.c b/boot/bls_parse.c
index 9a067736655..1e4f6330430 100644
--- a/boot/bls_parse.c
+++ b/boot/bls_parse.c
@@ -26,6 +26,7 @@  enum bls_token_t {
 	TOK_TITLE = 0,
 	TOK_VERSION,
 	TOK_LINUX,
+	TOK_FIT,
 	TOK_OPTIONS,
 	TOK_INITRD,
 	TOK_DEVICETREE,
@@ -42,6 +43,7 @@  static const char *const bls_token_names[] = {
 	[TOK_TITLE]		= "title",
 	[TOK_VERSION]		= "version",
 	[TOK_LINUX]		= "linux",
+	[TOK_FIT]		= "fit",
 	[TOK_OPTIONS]		= "options",
 	[TOK_INITRD]		= "initrd",
 	[TOK_DEVICETREE]	= "devicetree",
@@ -224,6 +226,10 @@  int bls_parse_entry(const char *buf, size_t size, struct bls_entry *entry)
 			/* Point into buffer */
 			entry->kernel = value;
 			break;
+		case TOK_FIT:
+			/* Point into buffer */
+			entry->fit = value;
+			break;
 		case TOK_OPTIONS:
 			/* Multiple times - allocate and concatenate */
 			if (bls_append_str(&entry->options, value))
@@ -267,10 +273,10 @@  int bls_parse_entry(const char *buf, size_t size, struct bls_entry *entry)
 
 	/*
 	 * Validate required fields: BLS spec requires at least one of
-	 * 'linux' or 'efi'. We only support 'linux' for Type #1 entries.
+	 * 'linux' or 'efi'. We also accept 'fit' for FIT images.
 	 */
-	if (!entry->kernel) {
-		log_err("BLS entry missing required 'linux' field\n");
+	if (!entry->kernel && !entry->fit) {
+		log_err("BLS entry missing required 'linux' or 'fit' field\n");
 		return -EINVAL;
 	}
 
diff --git a/boot/bootmeth_bls.c b/boot/bootmeth_bls.c
index 2c66e14c641..13353906fff 100644
--- a/boot/bootmeth_bls.c
+++ b/boot/bootmeth_bls.c
@@ -202,7 +202,12 @@  static int bls_entry_init(struct bls_entry *entry, struct bootflow *bflow,
 	}
 
 	/* Register discovered images (not yet loaded, addr=0) */
-	if (entry->kernel) {
+	if (entry->fit) {
+		if (!bootflow_img_add(bflow, entry->fit,
+				      (enum bootflow_img_t)IH_TYPE_KERNEL,
+				      0, 0))
+			return log_msg_ret("imf", -ENOMEM);
+	} else if (entry->kernel) {
 		if (!bootflow_img_add(bflow, entry->kernel,
 				      (enum bootflow_img_t)IH_TYPE_KERNEL,
 				      0, 0))
diff --git a/include/bls.h b/include/bls.h
index eb32b323f1a..e00b5998999 100644
--- a/include/bls.h
+++ b/include/bls.h
@@ -24,8 +24,9 @@ 
  *
  * @title: Human-readable name (points into buffer)
  * @version: OS version string (points into buffer)
- * @kernel: Kernel path or FIT image - required (points into buffer)
+ * @kernel: Kernel path - required unless @fit is set (points into buffer)
  *          Can include FIT config syntax: path#config
+ * @fit: FIT image path - required unless @kernel is set (points into buffer)
  * @options: Kernel command line - ALLOCATED, must be freed
  *           Multiple options lines are concatenated with spaces
  * @initrds: List of initrd paths (alist of char * pointing into buffer)
@@ -41,6 +42,7 @@  struct bls_entry {
 	char *title;
 	char *version;
 	char *kernel;
+	char *fit;
 	char *options;		/* Allocated */
 	struct alist initrds;	/* list of char * into buffer */
 	char *devicetree;
@@ -70,7 +72,8 @@  struct bls_entry {
  * Supported fields:
  *   title       - Human-readable name
  *   version     - OS version string
- *   linux       - Kernel path (required)
+ *   linux       - Kernel path (required unless 'fit' is present)
+ *   fit         - FIT image path (required unless 'linux' is present)
  *   options     - Kernel command line (allocated, can appear multiple times)
  *   initrd      - Initramfs path (can appear multiple times)
  *   devicetree  - Device tree blob path
diff --git a/test/boot/bls_parse.c b/test/boot/bls_parse.c
index 01da816aee8..63ae60d6091 100644
--- a/test/boot/bls_parse.c
+++ b/test/boot/bls_parse.c
@@ -137,6 +137,30 @@  static int bls_test_parse_unknown_field(struct unit_test_state *uts)
 }
 UNIT_TEST(bls_test_parse_unknown_field, 0, bootstd);
 
+/* Test FIT-only entry (no linux field) */
+static int bls_test_parse_fit(struct unit_test_state *uts)
+{
+	struct bls_entry entry;
+	char buf[] =
+		"title FIT Test\n"
+		"version 1.0\n"
+		"fit /boot/image.fit\n"
+		"options root=/dev/sda\n"
+		"initrd /initrd.img\n";
+
+	ut_assertok(bls_parse_entry(buf, sizeof(buf) - 1, &entry));
+	ut_asserteq_str("FIT Test", entry.title);
+	ut_assertnull(entry.kernel);
+	ut_asserteq_str("/boot/image.fit", entry.fit);
+	ut_asserteq_str("root=/dev/sda", entry.options);
+	ut_asserteq(1, entry.initrds.count);
+
+	bls_entry_uninit(&entry);
+
+	return 0;
+}
+UNIT_TEST(bls_test_parse_fit, 0, bootstd);
+
 /* Test all supported fields */
 static int bls_test_parse_all_fields(struct unit_test_state *uts)
 {