[Concept,01/12] extlinux: Use pxe_parse() to extract bootflow info

Message ID 20260324221911.3678307-2-sjg@u-boot.org
State New
Headers
Series bootstd: Support multiple bootflows per partition |

Commit Message

Simon Glass March 24, 2026, 10:18 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Replace the hand-rolled line-by-line parser in extlinux_fill_info()
with the pxe_parse() API. This gives a fully parsed menu structure
instead of ad-hoc string matching, and is a first step towards
supporting multiple bootflows per partition (e.g. when an extlinux
config defines several labels).

The first label's menu name is used if available, falling back to the
label name, matching the previous behaviour.

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

 boot/bootmeth_extlinux.c | 60 ++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 33 deletions(-)
  

Patch

diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c
index 286d176ae20..3ffe21d96a3 100644
--- a/boot/bootmeth_extlinux.c
+++ b/boot/bootmeth_extlinux.c
@@ -117,48 +117,42 @@  static int extlinux_check_luks(struct bootflow *bflow)
 /**
  * extlinux_fill_info() - Decode the extlinux file to find out its info
  *
+ * Uses pxe_parse() to parse the configuration file and extract the first
+ * label's name to use as the bootflow OS name.
+ *
  * @bflow: Bootflow to process
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
  */
 static int extlinux_fill_info(struct bootflow *bflow)
 {
-	struct membuf mb;
-	char line[200];
-	char *data;
-	int len;
+	struct pxe_context *ctx;
+	struct pxe_label *label;
+	const char *name;
+	ulong addr;
 
 	log_debug("parsing bflow file size %x\n", bflow->size);
-	membuf_init(&mb, bflow->buf, bflow->size);
-	membuf_putraw(&mb, bflow->size, true, &data);
-	while (len = membuf_readline(&mb, line, sizeof(line) - 1, 0, true), len) {
-		char *tok, *p = line;
-		const char *name = NULL;
-
-		if (*p == '#')
-			continue;
-		while (*p == ' ' || *p == '\t')
-			p++;
-		tok = strsep(&p, " ");
-		if (p) {
-			if (!strcmp("label", tok)) {
-				name = p;
-				if (bflow->os_name)
-					break;	/* just find the first */
-			} else if (!strcmp("menu", tok)) {
-				tok = strsep(&p, " ");
-				if (!strcmp("label", tok)) {
-					name = p;
-				}
-			}
-			if (name) {
-				free(bflow->os_name);
-				bflow->os_name = strdup(name);
-				if (!bflow->os_name)
-					return log_msg_ret("os", -ENOMEM);
-			}
+	addr = map_to_sysmem(bflow->buf);
+	ctx = pxe_parse(addr, bflow->size, bflow->fname);
+	if (!ctx)
+		return log_msg_ret("prs", -EINVAL);
+
+	if (list_empty(&ctx->cfg->labels)) {
+		pxe_cleanup(ctx);
+		return log_msg_ret("lab", -ENOENT);
+	}
+
+	label = list_first_entry(&ctx->cfg->labels, struct pxe_label, list);
+	name = label->menu ? label->menu : label->name;
+	if (name) {
+		bflow->os_name = strdup(name);
+		if (!bflow->os_name) {
+			pxe_cleanup(ctx);
+			return log_msg_ret("os", -ENOMEM);
 		}
 	}
 
+	pxe_cleanup(ctx);
+
 	return 0;
 }