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(-) 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) { -- 2.43.0