From: Simon Glass <sjg@chromium.org>
Add pxe_boot_entry() which parses a PXE config, walks to the Nth label,
loads its files and boots it. This is used by multi-entry bootmeths to
boot the specific label that was selected during scanning, rather than
presenting the full menu.
Update extlinux_boot() to always use pxe_boot_entry(), so that each
entry (including entry 0) boots its label directly without a menu.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
boot/ext_pxe_common.c | 3 ++-
boot/pxe_utils.c | 30 ++++++++++++++++++++++++++++++
include/pxe_utils.h | 14 ++++++++++++++
test/boot/bootflow.c | 6 ++++++
4 files changed, 52 insertions(+), 1 deletion(-)
@@ -136,7 +136,8 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow,
return log_msg_ret("elb", ret);
ctx->restart = restart;
addr = map_to_sysmem(bflow->buf);
- ret = pxe_process_str(ctx, addr, false);
+
+ ret = pxe_boot_entry(ctx, addr, bflow->entry);
}
if (ret)
return log_msg_ret("elb", -EFAULT);
@@ -1510,3 +1510,33 @@ int pxe_boot(struct pxe_context *ctx)
return 0;
}
+
+int pxe_boot_entry(struct pxe_context *ctx, ulong addr, int entry)
+{
+ struct pxe_label *label;
+ struct pxe_menu *cfg;
+ int ret, i = 0;
+ void *ptr;
+
+ ptr = map_sysmem(addr, 0);
+ ctx->pxe_file_size = strnlen(ptr, SZ_64K);
+ unmap_sysmem(ptr);
+
+ cfg = pxe_prepare(ctx, addr, false);
+ if (!cfg)
+ return log_msg_ret("prp", -EINVAL);
+
+ list_for_each_entry(label, &cfg->labels, list) {
+ if (i == entry)
+ goto found;
+ i++;
+ }
+ pxe_menu_uninit(cfg);
+ return log_msg_ret("lab", -ENOENT);
+
+found:
+ ret = label_boot(ctx, label);
+ pxe_menu_uninit(cfg);
+
+ return ret;
+}
@@ -611,4 +611,18 @@ void pxe_load(struct pxe_file *file, ulong addr, ulong size);
*/
void pxe_cleanup(struct pxe_context *ctx);
+/**
+ * pxe_boot_entry() - Parse a PXE config and boot a specific entry by index
+ *
+ * This parses the config file, walks to the Nth label, loads its files and
+ * boots it. Used by multi-entry bootmeths to boot a specific label that was
+ * selected during scanning.
+ *
+ * @ctx: PXE context (must be set up with pxe_setup_ctx())
+ * @addr: Address where config file is loaded
+ * @entry: Entry index (0 for first label, 1 for second, etc.)
+ * Return: Does not return on success, -ve on error
+ */
+int pxe_boot_entry(struct pxe_context *ctx, ulong addr, int entry);
+
#endif /* __PXE_UTILS_H */
@@ -1962,6 +1962,12 @@ static int bootflow_multi(struct unit_test_state *uts)
bflow->os_name);
ut_asserteq(1, bflow->entry);
+ /* Try booting the second entry (rescue) - exercises pxe_boot_entry() */
+ ut_assertok(env_set("kernel_addr_r", "1000000"));
+ ut_assertok(env_set("ramdisk_addr_r", "2000000"));
+ std->cur_bootflow = bflow;
+ ut_asserteq(-EFAULT, bootflow_boot(bflow));
+
return 0;
}
BOOTSTD_TEST(bootflow_multi, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);