It is useful to be able to select a bootflow and read its images,
without actually doing the boot. This allows adjusting the bootargs, for
example.

Provide support for this in the pxe_utils module, by adding a 'probe'
method which selects a label and saves its settings, so it can be booted
later, if desired.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 boot/pxe_utils.c    | 72 +++++++++++++++++++++++++++++++++++++++++----
 include/pxe_utils.h | 41 ++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 5 deletions(-)

diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 99c968a1202..01fff350f1b 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -802,8 +802,31 @@ static int label_boot(struct pxe_context *ctx, struct 
pxe_label *label)
        if (ctx->bflow)
                ctx->bflow->fdt_addr = hextoul(conf_fdt, NULL);
 
-       if (ctx->no_boot)
+       if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && ctx->no_boot) {
+               ctx->label = label;
+               ctx->kernel_addr = strdup(kernel_addr);
+               if (initrd_addr_str) {
+                       ctx->initrd_addr_str = strdup(initrd_addr_str);
+                       ctx->initrd_filesize = strdup(initrd_filesize);
+                       ctx->initrd_str = strdup(initrd_str);
+               }
+               ctx->conf_fdt = strdup(conf_fdt);
+               log_debug("Saving label '%s':\n", label->name);
+               log_debug("- kernel_addr '%s' conf_fdt '%s'\n",
+                         ctx->kernel_addr, ctx->conf_fdt);
+               if (initrd_addr_str) {
+                       log_debug("- initrd addr '%s' filesize '%s' str '%s'\n",
+                                 ctx->initrd_addr_str, ctx->initrd_filesize,
+                                 ctx->initrd_str);
+               }
+               if (!ctx->kernel_addr || !ctx->conf_fdt ||
+                   (initrd_addr_str && (!ctx->initrd_addr_str ||
+                    !ctx->initrd_filesize || !ctx->initrd_str))) {
+                       printf("malloc fail (saving label)\n");
+                       return 1;
+               }
                return 0;
+       }
 
        label_run_boot(ctx, label, kernel_addr, initrd_addr_str,
                       initrd_filesize, initrd_str, conf_fdt);
@@ -1695,18 +1718,29 @@ void pxe_destroy_ctx(struct pxe_context *ctx)
        free(ctx->bootdir);
 }
 
-int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt)
+struct pxe_menu *pxe_prepare(struct pxe_context *ctx, ulong pxefile_addr_r,
+                            bool prompt)
 {
        struct pxe_menu *cfg;
 
        cfg = parse_pxefile(ctx, pxefile_addr_r);
        if (!cfg) {
                printf("Error parsing config file\n");
-               return 1;
+               return NULL;
        }
 
-       if (prompt)
-               cfg->prompt = 1;
+       cfg->prompt = prompt;
+
+       return cfg;
+}
+
+int pxe_process(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt)
+{
+       struct pxe_menu *cfg;
+
+       cfg = pxe_prepare(ctx, pxefile_addr_r, prompt);
+       if (!cfg)
+               return 1;
 
        handle_pxe_menu(ctx, cfg);
 
@@ -1714,3 +1748,31 @@ int pxe_process(struct pxe_context *ctx, ulong 
pxefile_addr_r, bool prompt)
 
        return 0;
 }
+
+int pxe_probe(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt)
+{
+       ctx->cfg = pxe_prepare(ctx, pxefile_addr_r, prompt);
+       if (!ctx->cfg)
+               return -EINVAL;
+       ctx->no_boot = true;
+
+       handle_pxe_menu(ctx, ctx->cfg);
+
+       return 0;
+}
+
+int pxe_do_boot(struct pxe_context *ctx)
+{
+       int ret;
+
+       if (!ctx->label)
+               return log_msg_ret("pxb", -ENOENT);
+
+       ret = label_run_boot(ctx, ctx->label, ctx->kernel_addr,
+                            ctx->initrd_addr_str, ctx->initrd_filesize,
+                            ctx->initrd_str, ctx->conf_fdt);
+       if (ret)
+               return log_msg_ret("lrb", ret);
+
+       return 0;
+}
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index beadd221475..6425e349d19 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -111,6 +111,16 @@ typedef int (*pxe_getfile_func)(struct pxe_context *ctx, 
const char *file_path,
  *     "default" option as default
  * @no_boot: Stop show of actually booting and just return
  * @bflow: Bootflow being booted, or NULL if none (must be valid if @no_boot)
+ * @cfg: PXE menu (NULL if not yet probed)
+ *
+ * The following are only used when probing for a label
+ * @label: Label to process
+ * @kernel_addr: String containing kernel address (cannot be NULL)
+ * @initrd_addr_str: String containing initaddr address (NULL if none)
+ * @initrd_filesize: String containing initrd size (only used if
+ *     @initrd_addr_str)
+ * @initrd_str: initrd string to process (only used if @initrd_addr_str)
+ * @conf_fdt: string containing the FDT address
  */
 struct pxe_context {
        /**
@@ -133,6 +143,15 @@ struct pxe_context {
        bool use_fallback;
        bool no_boot;
        struct bootflow *bflow;
+       struct pxe_menu *cfg;
+
+       /* information on the selected label to boot */
+       struct pxe_label *label;
+       char *kernel_addr;
+       char *initrd_addr_str;
+       char *initrd_filesize;
+       char *initrd_str;
+       char *conf_fdt;
 };
 
 /**
@@ -283,4 +302,26 @@ int pxe_get_file_size(ulong *sizep);
  */
 int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool 
use_ipv6);
 
+/**
+ * pxe_probe() - Process a PXE file to find the label to boot
+ *
+ * This fills in the label, etc. fields in @ctx, assuming it funds something to
+ * boot. Then pxe_do_boot() can be called to boot it.
+ *
+ * @ctx: PXE context created with pxe_setup_ctx()
+ * @pxefile_addr_r: Address to load file
+ * @prompt: Force a prompt for the user
+ * Return: 0 if OK, -ve on error
+ */
+int pxe_probe(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt);
+
+/**
+ * pxe_do_boot() - Boot the selected label
+ *
+ * This boots the label discovered by pxe_probe()
+ *
+ * Return: Does not return, on success, otherwise returns a -ve error code
+ */
+int pxe_do_boot(struct pxe_context *ctx);
+
 #endif /* __PXE_UTILS_H */
-- 
2.34.1

Reply via email to