From: Simon Glass <simon.glass@canonical.com> Per the syslinux specification, the 'say' directive should print its message when the label is selected for booting, not during parsing. Store the 'say' message in struct pxe_label so it can be printed at the appropriate time. Print the message in label_boot() before displaying the label information. Update the test to verify the say field instead of expecting console output during parsing. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- boot/pxe_parse.c | 6 ++++-- boot/pxe_utils.c | 5 +++-- include/pxe_utils.h | 2 ++ test/boot/pxe.c | 42 +++++++++++++++++++----------------------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/boot/pxe_parse.c b/boot/pxe_parse.c index 633b218a7cd..e3412166a63 100644 --- a/boot/pxe_parse.c +++ b/boot/pxe_parse.c @@ -121,6 +121,7 @@ void label_destroy(struct pxe_label *label) free(label->fdt); free(label->fdtdir); free(label->fdtoverlays); + free(label->say); free(label); } @@ -553,8 +554,9 @@ static int parse_label(char **c, struct pxe_menu *cfg) char *p = strchr(s, '\n'); if (p) { - printf("%.*s\n", (int)(p - *c) - 1, *c + 1); - + label->say = strndup(*c + 1, p - *c - 1); + if (!label->say) + return -ENOMEM; *c = p; } break; diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 3c48b0ac51b..1516065a467 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -812,6 +812,9 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) char ip_str[68] = ""; int ret; + if (label->say) + printf("%s\n", label->say); + label_print(label); label->attempted = 1; @@ -897,8 +900,6 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) return 1; } -/* - */ void destroy_pxe_menu(struct pxe_menu *cfg) { struct list_head *pos, *n; diff --git a/include/pxe_utils.h b/include/pxe_utils.h index f910ea9d284..c0d2167cc25 100644 --- a/include/pxe_utils.h +++ b/include/pxe_utils.h @@ -39,6 +39,7 @@ * @fdt: path to FDT to use * @fdtdir: path to FDT directory to use * @fdtoverlays: space-separated list of paths of FDT overlays to apply + * @say: message to print when this label is selected for booting * @ipappend: flags for appending IP address (0x1) and MAC address (0x3) * @attempted: 0 if we haven't tried to boot this label, 1 if we have * @localboot: 1 if this label specified 'localboot', 0 otherwise @@ -58,6 +59,7 @@ struct pxe_label { char *fdt; char *fdtdir; char *fdtoverlays; + char *say; int ipappend; int attempted; int localboot; diff --git a/test/boot/pxe.c b/test/boot/pxe.c index af45c1fbffd..4ac0d6c6fa6 100644 --- a/test/boot/pxe.c +++ b/test/boot/pxe.c @@ -81,25 +81,20 @@ static int pxe_test_getfile(struct pxe_context *ctx, const char *file_path, * * This helper checks all the console output lines from loading and displaying * the PXE menu, including config file retrieval, include files, background - * image attempt, and the menu itself. + * image attempt, and the menu itself. Note: 'say' messages are now printed + * when the label is booted, not during parsing. * * @uts: Unit test state - * @say_msg: Expected 'say' message (shown before menu), or NULL if none * @error_msg: Expected error message after background image, or NULL if none * Return: 0 if OK, -ve on error */ -static int pxe_check_menu(struct unit_test_state *uts, const char *say_msg, - const char *error_msg) +static int pxe_check_menu(struct unit_test_state *uts, const char *error_msg) { int i; /* Config file retrieval */ ut_assert_nextline("Retrieving file: /extlinux/extlinux.conf"); - /* Say message appears before includes are processed */ - if (say_msg) - ut_assert_nextline(say_msg); - /* Include file retrievals */ ut_assert_nextline("Retrieving file: /extlinux/extra.conf"); for (i = 3; i <= 16; i++) @@ -169,11 +164,7 @@ static int pxe_test_parse_norun(struct unit_test_state *uts) cfg = parse_pxefile(&ctx, addr); ut_assertnonnull(cfg); - /* - * Verify 'say' keyword printed its message during parsing (quiet - * suppresses file messages) - */ - ut_assert_nextline("Booting default Linux kernel"); + /* Verify no console output during parsing (say is printed on boot) */ ut_assert_console_end(); /* Verify menu properties */ @@ -198,6 +189,7 @@ static int pxe_test_parse_norun(struct unit_test_state *uts) ut_assertnull(label->fdtdir); ut_asserteq_str("/dtb/overlay1.dtbo /dtb/overlay2.dtbo", label->fdtoverlays); + ut_asserteq_str("Booting default Linux kernel", label->say); ut_asserteq(0, label->ipappend); ut_asserteq(0, label->attempted); ut_asserteq(0, label->localboot); @@ -217,6 +209,7 @@ static int pxe_test_parse_norun(struct unit_test_state *uts) ut_assertnull(label->fdt); ut_asserteq_str("/dtb/", label->fdtdir); ut_assertnull(label->fdtoverlays); + ut_assertnull(label->say); ut_asserteq(3, label->ipappend); ut_asserteq(0, label->attempted); ut_asserteq(0, label->localboot); @@ -236,6 +229,7 @@ static int pxe_test_parse_norun(struct unit_test_state *uts) ut_assertnull(label->fdt); ut_assertnull(label->fdtdir); ut_assertnull(label->fdtoverlays); + ut_assertnull(label->say); ut_asserteq(0, label->ipappend); ut_asserteq(0, label->attempted); ut_asserteq(1, label->localboot); @@ -255,6 +249,7 @@ static int pxe_test_parse_norun(struct unit_test_state *uts) ut_assertnull(label->fdt); ut_assertnull(label->fdtdir); ut_assertnull(label->fdtoverlays); + ut_assertnull(label->say); ut_asserteq(0, label->ipappend); ut_asserteq(0, label->attempted); ut_asserteq(0, label->localboot); @@ -337,9 +332,9 @@ static int pxe_test_sysboot_norun(struct unit_test_state *uts) ut_assertok(run_commandf("sysboot host 0:0 any %x %s", PXE_LOAD_ADDR, cfg_path)); - /* Check menu output */ - ut_assertok(pxe_check_menu(uts, "Booting default Linux kernel", NULL)); - ut_assert_nextline("Enter choice: 1:\tBoot Linux"); + /* Skip menu output and find the first label boot attempt */ + ut_assert_skip_to_line("Enter choice: Booting default Linux kernel"); + ut_assert_nextline("1:\tBoot Linux"); /* Verify files were loaded in order */ ut_assert_nextline("Retrieving file: /vmlinuz"); @@ -646,9 +641,8 @@ static int pxe_test_overlay_no_addr_norun(struct unit_test_state *uts) cfg = parse_pxefile(&ctx, addr); ut_assertnonnull(cfg); - /* Consume parsing output */ + /* Consume parsing output (say message is printed on boot, not parsing) */ ut_assert_nextline("Retrieving file: %s", cfg_path); - ut_assert_nextline("Booting default Linux kernel"); ut_assert_nextline("Retrieving file: /extlinux/extra.conf"); for (i = 3; i <= 16; i++) ut_assert_nextline("Retrieving file: /extlinux/nest%d.conf", i); @@ -842,7 +836,7 @@ static int pxe_test_ipappend_norun(struct unit_test_state *uts) PXE_LOAD_ADDR, cfg_path)); /* Check menu output */ - ut_assertok(pxe_check_menu(uts, "Booting default Linux kernel", NULL)); + ut_assertok(pxe_check_menu(uts, NULL)); ut_assert_nextline("Enter choice: 2:\tRescue Mode"); /* Rescue label boot attempt */ @@ -962,7 +956,7 @@ static int pxe_test_label_override_norun(struct unit_test_state *uts) PXE_LOAD_ADDR, cfg_path)); /* Check menu output - say message is from default label */ - ut_assertok(pxe_check_menu(uts, "Booting default Linux kernel", NULL)); + ut_assertok(pxe_check_menu(uts, NULL)); /* Should boot 'local' label instead of default 'linux' */ ut_assert_nextline("Enter choice: 3:\tLocal Boot"); @@ -982,9 +976,11 @@ static int pxe_test_label_override_norun(struct unit_test_state *uts) PXE_LOAD_ADDR, cfg_path)); /* Check menu with error message before it */ - ut_assertok(pxe_check_menu(uts, "Booting default Linux kernel", - "Missing override pxe label: nonexistent")); - ut_assert_nextline("Enter choice: 1:\tBoot Linux"); + ut_assertok(pxe_check_menu(uts, "Missing override pxe label: nonexistent")); + + /* Say message is printed when label is selected (after "Enter choice:") */ + ut_assert_nextline("Enter choice: Booting default Linux kernel"); + ut_assert_nextline("1:\tBoot Linux"); /* Default label boot attempt - FDT/overlays loaded before append */ ut_assert_nextline("Retrieving file: /vmlinuz"); -- 2.43.0