From patchwork Sat Jan 10 20:28:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1469 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768077068; bh=ZIVsjToa9h/3bRWhf5djCxqUKEgOSBUss85HW62NcsM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iaP2PoiL+7fHKAS3duhZcHDulSYq+Ui8xQA31Obp8jPqUnUaA7fUFXZ+aFrN2KMTZ jPfguXRVmB/YuBoXMY8Gmk3OMvYNiGCvtG5HLx8+E0lKjbfHkNYST6QpixzAa2JTJI ++rNOuA+UfYCWSf/lbUPApQKAsnlT18lGmI8ymzSdPAl3DidX+lj4tBLs5Ex+j94pT kcSaI8XzgHicHcmO9JcwgWJbd9uhGKcgAP/keirLKM5qA9LUBbbkR1WcpcOy4Kp5UU alK/GqMPDneSySqEQ1Wb4tl6jKm4+nJd5fqnDj+068KoAAvA/9rhznIfZZ9HP9wWQ+ d8KL6JYGmXf4A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id D4ABC69186 for ; Sat, 10 Jan 2026 13:31:08 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id tu691x1qHOhz for ; Sat, 10 Jan 2026 13:31:08 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768077068; bh=ZIVsjToa9h/3bRWhf5djCxqUKEgOSBUss85HW62NcsM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iaP2PoiL+7fHKAS3duhZcHDulSYq+Ui8xQA31Obp8jPqUnUaA7fUFXZ+aFrN2KMTZ jPfguXRVmB/YuBoXMY8Gmk3OMvYNiGCvtG5HLx8+E0lKjbfHkNYST6QpixzAa2JTJI ++rNOuA+UfYCWSf/lbUPApQKAsnlT18lGmI8ymzSdPAl3DidX+lj4tBLs5Ex+j94pT kcSaI8XzgHicHcmO9JcwgWJbd9uhGKcgAP/keirLKM5qA9LUBbbkR1WcpcOy4Kp5UU alK/GqMPDneSySqEQ1Wb4tl6jKm4+nJd5fqnDj+068KoAAvA/9rhznIfZZ9HP9wWQ+ d8KL6JYGmXf4A== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C19B96927E for ; Sat, 10 Jan 2026 13:31:08 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768077066; bh=OVcuTYwyiOVe85kSIR2BpF8tJW1XXcydwrPBCl9HzeI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ndvmaOILhlw9m5gwJ1060kbXceJ9brgiIV7cjF2w9JBlg5nadXVcUj8+aw2u1/++H lQtrDCJ05hXAxwtzul9pQQpUDXXcSJrzSt+i/fxX7WLh7RHecJ6PvargC8thjDovYY 9MBjhTA4+ki1ueqlP28oYl/1IX9N+WCPVJri7kv6oMzIpsO7EUHSA0CifoV5cXAp6e cDf1BhJWaDW0j1tA9YxPGYPRVA2Ps03tbGWgZBRfxrvWaaDHaonhMvMvExdTTNfs+m 4S2LSHr23I6Qjslrv06Vp5lmVcUhCT3djkR+TpOpCgP3cBKkf2lykflLAIGXUrA5j4 MB0MmBbSirW/w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C40996927E; Sat, 10 Jan 2026 13:31:06 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 4dvg_IJPK_bt; Sat, 10 Jan 2026 13:31:06 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1768077060; bh=Q+DbmnEVf2wx83xFyfnjrqD6n8sW+/SlA7bB7n8qEtc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eOQU1tIgKqeCo9/k9z4+Rkhi2YgW5bgiCx0ngOm/uWXODCi4YT3tdy0pqUollWLlF +RJHLXPqecIvBs4F3g2+swPlDOynhw9Y6bHoi9Ft/VbL0P3Hw+a3KrMeXomzPREZr5 crSZ5DmFE57/+LWIRv9lmuFoktL0d2kQw29+n5//2MXxZXGhcTUg2ZUh6gwuxO7Aur xGzWNaACIWVMyWklmTsEA5KIcK0qndLZlkiyO9Xt4vG6SBE81T4robOtTA63yWIWo8 XqzSpeqeL2VjWV3/bEBE180+Z1Qqwbzo4lgnuuAQwKEWYWAb00pxCe9PlnyMnmSZPW VcvOrw/B51/pQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 9508269186; Sat, 10 Jan 2026 13:31:00 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sat, 10 Jan 2026 13:28:55 -0700 Message-ID: <20260110202906.187370-24-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260110202906.187370-1-sjg@u-boot.org> References: <20260110202906.187370-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 2WPI7GP6GQRQL57ERAEUROUNAMBRSXJV X-Message-ID-Hash: 2WPI7GP6GQRQL57ERAEUROUNAMBRSXJV X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 23/26] boot: pxe: Add a callback-free PXE API List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Add functions for a callback-free PXE API: - pxe_parse() - Parse a PXE config file and return an allocated context - pxe_load() - Record file load address and size - pxe_cleanup() - Free menu and destroy context Also rename pxe_do_boot() to pxe_boot() for consistency. This API allows callers to parse PXE files, load files manually without callbacks, and boot the selected label. Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- boot/ext_pxe_common.c | 2 +- boot/pxe_utils.c | 45 +++++++++++++++++++++++++++++- include/pxe_utils.h | 64 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 5 deletions(-) diff --git a/boot/ext_pxe_common.c b/boot/ext_pxe_common.c index 2bc76a4d0fb..59d878883bf 100644 --- a/boot/ext_pxe_common.c +++ b/boot/ext_pxe_common.c @@ -107,7 +107,7 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow, /* if we have already selected a label, just boot it */ if (plat->ctx.label) { plat->ctx.fake_go = bflow->flags & BOOTFLOWF_FAKE_GO; - ret = pxe_do_boot(&plat->ctx); + ret = pxe_boot(&plat->ctx); } else { ret = extlinux_setup(dev, bflow, getfile, allow_abs_path, bootfile, &plat->ctx); diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 45f4d365878..5c1d08feebf 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -1326,6 +1326,49 @@ static struct pxe_menu *pxe_prepare(struct pxe_context *ctx, return cfg; } +struct pxe_context *pxe_parse(ulong addr, ulong size, const char *bootfile) +{ + struct pxe_context *ctx; + struct abuf buf; + int ret; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return NULL; + + ret = pxe_setup_ctx(ctx, NULL, NULL, true, bootfile, false, false, + NULL); + if (ret) { + free(ctx); + return NULL; + } + ctx->pxe_file_size = size; + + abuf_init_addr(&buf, addr, size); + ctx->cfg = parse_pxefile(ctx, &buf); + if (!ctx->cfg) { + pxe_destroy_ctx(ctx); + free(ctx); + return NULL; + } + + return ctx; +} + +void pxe_load(struct pxe_file *file, ulong addr, ulong size) +{ + file->addr = addr; + file->size = size; +} + +void pxe_cleanup(struct pxe_context *ctx) +{ + if (ctx->cfg) + pxe_menu_uninit(ctx->cfg); + pxe_destroy_ctx(ctx); + free(ctx); +} + int pxe_process(struct pxe_context *ctx, ulong addr, ulong size, bool prompt) { struct pxe_menu *cfg; @@ -1366,7 +1409,7 @@ int pxe_probe(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt) return 0; } -int pxe_do_boot(struct pxe_context *ctx) +int pxe_boot(struct pxe_context *ctx) { int ret; diff --git a/include/pxe_utils.h b/include/pxe_utils.h index 6f2ac604d6e..bc9e3f29417 100644 --- a/include/pxe_utils.h +++ b/include/pxe_utils.h @@ -428,7 +428,7 @@ 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. + * boot. Then pxe_boot() can be called to boot it. * * @ctx: PXE context created with pxe_setup_ctx() * @pxefile_addr_r: Address to load file @@ -438,13 +438,13 @@ int pxe_get(ulong pxefile_addr_r, char **bootdirp, ulong *sizep, bool use_ipv6); int pxe_probe(struct pxe_context *ctx, ulong pxefile_addr_r, bool prompt); /** - * pxe_do_boot() - Boot the selected label + * pxe_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); +int pxe_boot(struct pxe_context *ctx); /** * pxe_select_label() - Select a label from a parsed menu @@ -539,6 +539,16 @@ void label_destroy(struct pxe_label *label); * to parse it and merge any labels into the target menu. This may add * more entries to cfg->includes if the included file has its own includes. * + * Example usage:: + * + * ctx = pxe_parse(addr, size, bootfile); + * + * // Load and process any includes + * alist_for_each(inc, &ctx->cfg->includes) { + * // read file inc->path to address 'addr', getting 'size' + * pxe_parse_include(ctx, inc, addr, size); + * } + * * @ctx: PXE context * @inc: Include info with path and target menu * @addr: Memory address where file is located @@ -548,4 +558,52 @@ void label_destroy(struct pxe_label *label); int pxe_parse_include(struct pxe_context *ctx, const struct pxe_include *inc, ulong addr, ulong size); +/** + * pxe_parse() - Parse a PXE config file and return an allocated context + * + * This allocates a PXE context, sets it up, and parses the config file at the + * given address. The menu is stored in ctx->cfg and can be used to inspect + * labels or select one for loading. + * + * Use pxe_cleanup() to clean up when done. + * + * Note: This does not process include files. Call pxe_process_includes() + * after this if needed. + * + * @addr: Address where config file is loaded + * @size: Size of config file in bytes + * @bootfile: Path to config file (for relative path resolution) + * Return: Allocated context on success, NULL on error + */ +struct pxe_context *pxe_parse(ulong addr, ulong size, const char *bootfile); + +/** + * pxe_load() - Report that a file has been loaded + * + * After loading a file from a label's files list, call this to record + * the load address and size. This information is used later during boot. + * + * Example:: + * + * alist_for_each(file, &label->files) { + * // choose 'addr', load file->path there, getting 'size' + * pxe_load(file, addr, size); + * } + * + * @file: File that was loaded + * @addr: Address where file was loaded + * @size: Size of loaded file + */ +void pxe_load(struct pxe_file *file, ulong addr, ulong size); + +/** + * pxe_cleanup() - Free PXE menu and destroy context + * + * This combines pxe_menu_uninit() and pxe_destroy_ctx() for convenience + * when cleaning up after using the callback-free API. + * + * @ctx: Context to destroy (ctx->cfg is freed if set) + */ +void pxe_cleanup(struct pxe_context *ctx); + #endif /* __PXE_UTILS_H */