* [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string
@ 2026-05-08 13:55 Breno Leitao
2026-05-08 13:55 ` [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Breno Leitao
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Breno Leitao @ 2026-05-08 13:55 UTC (permalink / raw)
To: Masami Hiramatsu, Andrew Morton
Cc: linux-kernel, linux-trace-kernel, paulmck, oss, Breno Leitao,
kernel-team
Add a bootconfig -> kernel cmdline rendering capability shared between
the kernel parser library and the userspace tools/bootconfig binary.
The new userspace mode "tools/bootconfig -C <file>" walks a bootconfig
file's "kernel" subtree and prints it as a flat, space-separated
cmdline string suitable for direct use as (or appending to) a kernel
command line.
This series prepares tools/bootconfig and lib/bootconfig.c for an
upcoming feature that lets the kernel build render an embedded
bootconfig file's "kernel" subtree to a flat cmdline string and embed
it in the kernel image.
The follow-up series (sent separately) wires this into setup_arch() so
early_param() handlers see values supplied via CONFIG_BOOT_CONFIG_EMBED_FILE,
following Masami suggestion in [1]
These two patches are pure groundwork. They add no kernel feature,
change no runtime behavior, and are useful on their own (the new
"tools/bootconfig -C" mode lets anyone render a .bootconfig file to
a cmdline string from the shell).
Landing them independently lets the follow-up series focus on the
kernel-side plumbing without dragging the refactor and tool addition
through the same review cycle.
Patch 1 lifts xbc_snprint_cmdline() from init/main.c into
lib/bootconfig.c so both the kernel runtime path
(xbc_make_cmdline -> extra_command_line) and the userspace tool can
share a single renderer.
- tools/bootconfig already compiles lib/bootconfig.c directly, so no
new shared-code mechanism is introduced.
Patch 2 adds a -C option to tools/bootconfig that walks the "kernel"
subtree of a bootconfig file and prints it as a flat, space-separated
cmdline string. Missing or empty kernel.* produces empty output and
exits 0.
- This is the renderer the kernel build will invoke.
Once this lands, the follow up patches will use it in the following way:
1) Render at build time.
The kernel build invokes the userspace bootconfig tool — using the -C mode
prep added — to convert the embedded bootconfig file into a flat kernel cmdline
string.
2) Bake the string into the kernel image.
A small assembly stub embeds the rendered file into the kernel's discardable
read-only init data, bracketed by two markers so the runtime can locate it.
3) Add a runtime helper to consume it.
A new helper in the shared bootconfig source — sitting next to the renderer
prep moved there — prepends the embedded blob to a cmdline buffer, panicking
rather than truncating if it overflows. The public header declares it with a
no-op stub when the feature is off.
4) Plumb it at architecture early setup.
The arch's early setup calls the helper after the existing builtin-cmdline
merge but before early-param parsing, so values from the embedded bootconfig
influence early-param handlers (console, log level, memory overrides) right
when architecture setup runs — not later in
Background: the v1 attempt at this feature moved bootconfig parsing
before setup_arch() with ~96KB of static __initdata buffers [1].
Masami suggested doing the conversion at build time instead [2], which
avoids the early-boot allocator dance and the start_kernel() reordering.
This series, plus the follow-up, aims to implement that approach.
[1] https://lore.kernel.org/all/20260415-bootconfig_earlier-v1-0-cf160175de5e@debian.org/
[2] https://lore.kernel.org/all/20260417104436.ece29fd5e2cb7a59c8cf8ac1@kernel.org/
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Breno Leitao (2):
bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c
tools/bootconfig: render kernel.* subtree as cmdline string with -C
include/linux/bootconfig.h | 3 +++
init/main.c | 45 ----------------------------------
lib/bootconfig.c | 56 +++++++++++++++++++++++++++++++++++++++++++
tools/bootconfig/main.c | 60 +++++++++++++++++++++++++++++++++++++++-------
4 files changed, 111 insertions(+), 53 deletions(-)
---
base-commit: 17c7841d09ee7d33557fd075562d9289b6018c90
change-id: 20260508-bootconfig_using_tools-cfa7aa9d6a5a
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c
2026-05-08 13:55 [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Breno Leitao
@ 2026-05-08 13:55 ` Breno Leitao
2026-05-12 0:00 ` Masami Hiramatsu
2026-05-08 13:55 ` [PATCH 2/2] tools/bootconfig: render kernel.* subtree as cmdline string with -C Breno Leitao
2026-05-08 21:56 ` [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Andrew Morton
2 siblings, 1 reply; 8+ messages in thread
From: Breno Leitao @ 2026-05-08 13:55 UTC (permalink / raw)
To: Masami Hiramatsu, Andrew Morton
Cc: linux-kernel, linux-trace-kernel, paulmck, oss, Breno Leitao,
kernel-team
Move xbc_snprint_cmdline() from init/main.c to lib/bootconfig.c so the
function (and its xbc_namebuf scratch buffer) becomes part of the shared
parser library. tools/bootconfig already compiles lib/bootconfig.c
directly, which lets a follow-up patch reuse the same renderer in the
userspace tool to convert a bootconfig file into a flat cmdline string
at build time.
No functional change.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
include/linux/bootconfig.h | 3 +++
init/main.c | 45 -------------------------------------
lib/bootconfig.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+), 45 deletions(-)
diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h
index 692a5acc2ffc4..1c7f3b74ffcf3 100644
--- a/include/linux/bootconfig.h
+++ b/include/linux/bootconfig.h
@@ -265,6 +265,9 @@ static inline struct xbc_node * __init xbc_node_get_subkey(struct xbc_node *node
int __init xbc_node_compose_key_after(struct xbc_node *root,
struct xbc_node *node, char *buf, size_t size);
+/* Render key/value pairs under @root as a flat cmdline string */
+int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root);
+
/**
* xbc_node_compose_key() - Compose full key string of the XBC node
* @node: An XBC node.
diff --git a/init/main.c b/init/main.c
index 96f93bb06c490..e363232b428b4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -324,51 +324,6 @@ static void * __init get_boot_config_from_initrd(size_t *_size)
#ifdef CONFIG_BOOT_CONFIG
-static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
-
-#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
-
-static int __init xbc_snprint_cmdline(char *buf, size_t size,
- struct xbc_node *root)
-{
- struct xbc_node *knode, *vnode;
- char *end = buf + size;
- const char *val, *q;
- int ret;
-
- xbc_node_for_each_key_value(root, knode, val) {
- ret = xbc_node_compose_key_after(root, knode,
- xbc_namebuf, XBC_KEYLEN_MAX);
- if (ret < 0)
- return ret;
-
- vnode = xbc_node_get_child(knode);
- if (!vnode) {
- ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
- if (ret < 0)
- return ret;
- buf += ret;
- continue;
- }
- xbc_array_for_each_value(vnode, val) {
- /*
- * For prettier and more readable /proc/cmdline, only
- * quote the value when necessary, i.e. when it contains
- * whitespace.
- */
- q = strpbrk(val, " \t\r\n") ? "\"" : "";
- ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
- xbc_namebuf, q, val, q);
- if (ret < 0)
- return ret;
- buf += ret;
- }
- }
-
- return buf - (end - size);
-}
-#undef rest
-
/* Make an extra command line under given key word */
static char * __init xbc_make_cmdline(const char *key)
{
diff --git a/lib/bootconfig.c b/lib/bootconfig.c
index c470b93d5dbc2..f445b7703fdd9 100644
--- a/lib/bootconfig.c
+++ b/lib/bootconfig.c
@@ -408,6 +408,62 @@ const char * __init xbc_node_find_next_key_value(struct xbc_node *root,
return ""; /* No value key */
}
+static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
+
+#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
+
+/**
+ * xbc_snprint_cmdline() - Render bootconfig keys under @root as a cmdline string
+ * @buf: Destination buffer (may be NULL when @size is 0 to query the length)
+ * @size: Size of @buf in bytes
+ * @root: Subtree root whose key=value pairs should be rendered
+ *
+ * Walk all key/value pairs under @root and emit them as a space-separated
+ * cmdline string into @buf. Values containing whitespace are quoted with
+ * double quotes. Returns the number of bytes that would be written if @buf
+ * were large enough (matching snprintf semantics), or a negative errno on
+ * failure.
+ */
+int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
+{
+ struct xbc_node *knode, *vnode;
+ char *end = buf + size;
+ const char *val, *q;
+ int ret;
+
+ xbc_node_for_each_key_value(root, knode, val) {
+ ret = xbc_node_compose_key_after(root, knode,
+ xbc_namebuf, XBC_KEYLEN_MAX);
+ if (ret < 0)
+ return ret;
+
+ vnode = xbc_node_get_child(knode);
+ if (!vnode) {
+ ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
+ if (ret < 0)
+ return ret;
+ buf += ret;
+ continue;
+ }
+ xbc_array_for_each_value(vnode, val) {
+ /*
+ * For prettier and more readable /proc/cmdline, only
+ * quote the value when necessary, i.e. when it contains
+ * whitespace.
+ */
+ q = strpbrk(val, " \t\r\n") ? "\"" : "";
+ ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
+ xbc_namebuf, q, val, q);
+ if (ret < 0)
+ return ret;
+ buf += ret;
+ }
+ }
+
+ return buf - (end - size);
+}
+#undef rest
+
/* XBC parse and tree build */
static int __init xbc_init_node(struct xbc_node *node, char *data, uint16_t flag)
--
2.53.0-Meta
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] tools/bootconfig: render kernel.* subtree as cmdline string with -C
2026-05-08 13:55 [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Breno Leitao
2026-05-08 13:55 ` [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Breno Leitao
@ 2026-05-08 13:55 ` Breno Leitao
2026-05-12 0:00 ` Masami Hiramatsu
2026-05-08 21:56 ` [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Andrew Morton
2 siblings, 1 reply; 8+ messages in thread
From: Breno Leitao @ 2026-05-08 13:55 UTC (permalink / raw)
To: Masami Hiramatsu, Andrew Morton
Cc: linux-kernel, linux-trace-kernel, paulmck, oss, Breno Leitao,
kernel-team
Add a -C option that finds the "kernel" subtree of a bootconfig file
and prints it as a flat, space-separated cmdline string by calling the
shared xbc_snprint_cmdline() renderer. An empty or absent kernel.*
subtree produces empty output and exits successfully.
This lets the kernel build embed a bootconfig file as a plain cmdline
string at build time, so embedded bootconfig values can reach
parse_early_param() during architecture setup without parsing the
bootconfig at runtime.
The renderer is intentionally limited to the kernel.* subtree: that is
the only thing the kernel build needs to embed; init.* and other
subtrees keep going through the runtime parser.
Example of this new mode:
# cat /tmp/test.bconf
kernel {
foo = bar
baz = "hello world"
arr = 1, 2
}
init.foo = nope
# ./tools/bootconfig/bootconfig -C /tmp/test.bconf
foo=bar baz="hello world" arr=1 arr=2 %
Signed-off-by: Breno Leitao <leitao@debian.org>
---
tools/bootconfig/main.c | 60 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 52 insertions(+), 8 deletions(-)
diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
index 643f707b8f1da..e1bfab044fbcb 100644
--- a/tools/bootconfig/main.c
+++ b/tools/bootconfig/main.c
@@ -286,7 +286,41 @@ static int init_xbc_with_error(char *buf, int len)
return ret;
}
-static int show_xbc(const char *path, bool list)
+static int show_xbc_kernel_cmdline(void)
+{
+ struct xbc_node *root;
+ char *buf = NULL;
+ int len, ret;
+
+ root = xbc_find_node("kernel");
+ if (!root)
+ return 0; /* no kernel.* keys: emit empty output */
+
+ len = xbc_snprint_cmdline(NULL, 0, root);
+ if (len < 0) {
+ pr_err("Failed to size cmdline output: %d\n", len);
+ return len;
+ }
+ if (len == 0)
+ return 0;
+
+ buf = malloc(len + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = xbc_snprint_cmdline(buf, len + 1, root);
+ if (ret < 0) {
+ pr_err("Failed to render cmdline output: %d\n", ret);
+ free(buf);
+ return ret;
+ }
+
+ fputs(buf, stdout);
+ free(buf);
+ return 0;
+}
+
+static int show_xbc(const char *path, bool list, bool render_cmdline)
{
int ret, fd;
char *buf = NULL;
@@ -322,11 +356,14 @@ static int show_xbc(const char *path, bool list)
if (init_xbc_with_error(buf, ret) < 0)
goto out;
}
- if (list)
+ if (render_cmdline)
+ ret = show_xbc_kernel_cmdline();
+ else if (list)
xbc_show_list();
else
xbc_show_compact_tree();
- ret = 0;
+ if (ret > 0)
+ ret = 0;
out:
free(buf);
@@ -486,7 +523,10 @@ static int usage(void)
" Options:\n"
" -a <config>: Apply boot config to initrd\n"
" -d : Delete boot config file from initrd\n"
- " -l : list boot config in initrd or file\n\n"
+ " -l : list boot config in initrd or file\n"
+ " -C : render the kernel.* subtree as a flat cmdline\n"
+ " string (suitable for embedding in a kernel image)\n"
+ " and print it to stdout\n\n"
" If no option is given, show the bootconfig in the given file.\n");
return -1;
}
@@ -495,10 +535,11 @@ int main(int argc, char **argv)
{
char *path = NULL;
char *apply = NULL;
+ bool render_cmdline = false;
bool delete = false, list = false;
int opt;
- while ((opt = getopt(argc, argv, "hda:l")) != -1) {
+ while ((opt = getopt(argc, argv, "hda:lC")) != -1) {
switch (opt) {
case 'd':
delete = true;
@@ -509,14 +550,17 @@ int main(int argc, char **argv)
case 'l':
list = true;
break;
+ case 'C':
+ render_cmdline = true;
+ break;
case 'h':
default:
return usage();
}
}
- if ((apply && delete) || (delete && list) || (apply && list)) {
- pr_err("Error: You can give one of -a, -d or -l at once.\n");
+ if ((!!apply + !!delete + !!list + !!render_cmdline) > 1) {
+ pr_err("Error: You can give one of -a, -d, -l or -C at once.\n");
return usage();
}
@@ -532,5 +576,5 @@ int main(int argc, char **argv)
else if (delete)
return delete_xbc(path);
- return show_xbc(path, list);
+ return show_xbc(path, list, render_cmdline);
}
--
2.53.0-Meta
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string
2026-05-08 13:55 [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Breno Leitao
2026-05-08 13:55 ` [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Breno Leitao
2026-05-08 13:55 ` [PATCH 2/2] tools/bootconfig: render kernel.* subtree as cmdline string with -C Breno Leitao
@ 2026-05-08 21:56 ` Andrew Morton
2026-05-11 16:38 ` Breno Leitao
2 siblings, 1 reply; 8+ messages in thread
From: Andrew Morton @ 2026-05-08 21:56 UTC (permalink / raw)
To: Breno Leitao
Cc: Masami Hiramatsu, linux-kernel, linux-trace-kernel, paulmck, oss,
kernel-team
On Fri, 08 May 2026 06:55:02 -0700 Breno Leitao <leitao@debian.org> wrote:
> Add a bootconfig -> kernel cmdline rendering capability shared between
> the kernel parser library and the userspace tools/bootconfig binary.
>
> The new userspace mode "tools/bootconfig -C <file>" walks a bootconfig
> file's "kernel" subtree and prints it as a flat, space-separated
> cmdline string suitable for direct use as (or appending to) a kernel
> command line.
>
> This series prepares tools/bootconfig and lib/bootconfig.c for an
> upcoming feature that lets the kernel build render an embedded
> bootconfig file's "kernel" subtree to a flat cmdline string and embed
> it in the kernel image.
>
> The follow-up series (sent separately) wires this into setup_arch() so
> early_param() handlers see values supplied via CONFIG_BOOT_CONFIG_EMBED_FILE,
> following Masami suggestion in [1]
>
> These two patches are pure groundwork. They add no kernel feature,
> change no runtime behavior, and are useful on their own (the new
> "tools/bootconfig -C" mode lets anyone render a .bootconfig file to
> a cmdline string from the shell).
>
> Landing them independently lets the follow-up series focus on the
> kernel-side plumbing without dragging the refactor and tool addition
> through the same review cycle.
I'll assume that Masami will process this, although
`scripts/get_maintainer.pl lib/bootconfig.c' doesn't mention a git
tree.
https://sashiko.dev/#/patchset/20260508-bootconfig_using_tools-v1-0-1132219aa773@debian.org
says a bunch of picky things which seem pretty ignorable to me. Your
call ;)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string
2026-05-08 21:56 ` [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Andrew Morton
@ 2026-05-11 16:38 ` Breno Leitao
2026-05-12 0:43 ` Masami Hiramatsu
0 siblings, 1 reply; 8+ messages in thread
From: Breno Leitao @ 2026-05-11 16:38 UTC (permalink / raw)
To: Andrew Morton
Cc: Masami Hiramatsu, linux-kernel, linux-trace-kernel, paulmck, oss,
kernel-team
On Fri, May 08, 2026 at 02:56:41PM -0700, Andrew Morton wrote:
> On Fri, 08 May 2026 06:55:02 -0700 Breno Leitao <leitao@debian.org> wrote:
>
> > Add a bootconfig -> kernel cmdline rendering capability shared between
> > the kernel parser library and the userspace tools/bootconfig binary.
> >
> > The new userspace mode "tools/bootconfig -C <file>" walks a bootconfig
> > file's "kernel" subtree and prints it as a flat, space-separated
> > cmdline string suitable for direct use as (or appending to) a kernel
> > command line.
> >
> > This series prepares tools/bootconfig and lib/bootconfig.c for an
> > upcoming feature that lets the kernel build render an embedded
> > bootconfig file's "kernel" subtree to a flat cmdline string and embed
> > it in the kernel image.
> >
> > The follow-up series (sent separately) wires this into setup_arch() so
> > early_param() handlers see values supplied via CONFIG_BOOT_CONFIG_EMBED_FILE,
> > following Masami suggestion in [1]
> >
> > These two patches are pure groundwork. They add no kernel feature,
> > change no runtime behavior, and are useful on their own (the new
> > "tools/bootconfig -C" mode lets anyone render a .bootconfig file to
> > a cmdline string from the shell).
> >
> > Landing them independently lets the follow-up series focus on the
> > kernel-side plumbing without dragging the refactor and tool addition
> > through the same review cycle.
>
> I'll assume that Masami will process this, although
> `scripts/get_maintainer.pl lib/bootconfig.c' doesn't mention a git
> tree.
>
> https://sashiko.dev/#/patchset/20260508-bootconfig_using_tools-v1-0-1132219aa773@debian.org
> says a bunch of picky things which seem pretty ignorable to me. Your
> call ;)
Well, these are some warnings about not checking that the output was
properly set. From my view, these are not new to this patch, it is just the
pattern we see, which is fire-and-forget writes to stdout, which seems
quite reasonable.
If we decide to fix this, it would make more sense to do it file-wide
instead of just in this patch code.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] tools/bootconfig: render kernel.* subtree as cmdline string with -C
2026-05-08 13:55 ` [PATCH 2/2] tools/bootconfig: render kernel.* subtree as cmdline string with -C Breno Leitao
@ 2026-05-12 0:00 ` Masami Hiramatsu
0 siblings, 0 replies; 8+ messages in thread
From: Masami Hiramatsu @ 2026-05-12 0:00 UTC (permalink / raw)
To: Breno Leitao
Cc: Andrew Morton, linux-kernel, linux-trace-kernel, paulmck, oss,
kernel-team
On Fri, 08 May 2026 06:55:04 -0700
Breno Leitao <leitao@debian.org> wrote:
> Add a -C option that finds the "kernel" subtree of a bootconfig file
> and prints it as a flat, space-separated cmdline string by calling the
> shared xbc_snprint_cmdline() renderer. An empty or absent kernel.*
> subtree produces empty output and exits successfully.
>
> This lets the kernel build embed a bootconfig file as a plain cmdline
> string at build time, so embedded bootconfig values can reach
> parse_early_param() during architecture setup without parsing the
> bootconfig at runtime.
>
> The renderer is intentionally limited to the kernel.* subtree: that is
> the only thing the kernel build needs to embed; init.* and other
> subtrees keep going through the runtime parser.
>
> Example of this new mode:
> # cat /tmp/test.bconf
> kernel {
> foo = bar
> baz = "hello world"
> arr = 1, 2
> }
> init.foo = nope
>
> # ./tools/bootconfig/bootconfig -C /tmp/test.bconf
> foo=bar baz="hello world" arr=1 arr=2 %
>
Nice! Looks good to me. Let me pick it.
Thanks,
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> tools/bootconfig/main.c | 60 ++++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 52 insertions(+), 8 deletions(-)
>
> diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
> index 643f707b8f1da..e1bfab044fbcb 100644
> --- a/tools/bootconfig/main.c
> +++ b/tools/bootconfig/main.c
> @@ -286,7 +286,41 @@ static int init_xbc_with_error(char *buf, int len)
> return ret;
> }
>
> -static int show_xbc(const char *path, bool list)
> +static int show_xbc_kernel_cmdline(void)
> +{
> + struct xbc_node *root;
> + char *buf = NULL;
> + int len, ret;
> +
> + root = xbc_find_node("kernel");
> + if (!root)
> + return 0; /* no kernel.* keys: emit empty output */
> +
> + len = xbc_snprint_cmdline(NULL, 0, root);
> + if (len < 0) {
> + pr_err("Failed to size cmdline output: %d\n", len);
> + return len;
> + }
> + if (len == 0)
> + return 0;
> +
> + buf = malloc(len + 1);
> + if (!buf)
> + return -ENOMEM;
> +
> + ret = xbc_snprint_cmdline(buf, len + 1, root);
> + if (ret < 0) {
> + pr_err("Failed to render cmdline output: %d\n", ret);
> + free(buf);
> + return ret;
> + }
> +
> + fputs(buf, stdout);
> + free(buf);
> + return 0;
> +}
> +
> +static int show_xbc(const char *path, bool list, bool render_cmdline)
> {
> int ret, fd;
> char *buf = NULL;
> @@ -322,11 +356,14 @@ static int show_xbc(const char *path, bool list)
> if (init_xbc_with_error(buf, ret) < 0)
> goto out;
> }
> - if (list)
> + if (render_cmdline)
> + ret = show_xbc_kernel_cmdline();
> + else if (list)
> xbc_show_list();
> else
> xbc_show_compact_tree();
> - ret = 0;
> + if (ret > 0)
> + ret = 0;
> out:
> free(buf);
>
> @@ -486,7 +523,10 @@ static int usage(void)
> " Options:\n"
> " -a <config>: Apply boot config to initrd\n"
> " -d : Delete boot config file from initrd\n"
> - " -l : list boot config in initrd or file\n\n"
> + " -l : list boot config in initrd or file\n"
> + " -C : render the kernel.* subtree as a flat cmdline\n"
> + " string (suitable for embedding in a kernel image)\n"
> + " and print it to stdout\n\n"
> " If no option is given, show the bootconfig in the given file.\n");
> return -1;
> }
> @@ -495,10 +535,11 @@ int main(int argc, char **argv)
> {
> char *path = NULL;
> char *apply = NULL;
> + bool render_cmdline = false;
> bool delete = false, list = false;
> int opt;
>
> - while ((opt = getopt(argc, argv, "hda:l")) != -1) {
> + while ((opt = getopt(argc, argv, "hda:lC")) != -1) {
> switch (opt) {
> case 'd':
> delete = true;
> @@ -509,14 +550,17 @@ int main(int argc, char **argv)
> case 'l':
> list = true;
> break;
> + case 'C':
> + render_cmdline = true;
> + break;
> case 'h':
> default:
> return usage();
> }
> }
>
> - if ((apply && delete) || (delete && list) || (apply && list)) {
> - pr_err("Error: You can give one of -a, -d or -l at once.\n");
> + if ((!!apply + !!delete + !!list + !!render_cmdline) > 1) {
> + pr_err("Error: You can give one of -a, -d, -l or -C at once.\n");
> return usage();
> }
>
> @@ -532,5 +576,5 @@ int main(int argc, char **argv)
> else if (delete)
> return delete_xbc(path);
>
> - return show_xbc(path, list);
> + return show_xbc(path, list, render_cmdline);
> }
>
> --
> 2.53.0-Meta
>
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c
2026-05-08 13:55 ` [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Breno Leitao
@ 2026-05-12 0:00 ` Masami Hiramatsu
0 siblings, 0 replies; 8+ messages in thread
From: Masami Hiramatsu @ 2026-05-12 0:00 UTC (permalink / raw)
To: Breno Leitao
Cc: Andrew Morton, linux-kernel, linux-trace-kernel, paulmck, oss,
kernel-team
On Fri, 08 May 2026 06:55:03 -0700
Breno Leitao <leitao@debian.org> wrote:
> Move xbc_snprint_cmdline() from init/main.c to lib/bootconfig.c so the
> function (and its xbc_namebuf scratch buffer) becomes part of the shared
> parser library. tools/bootconfig already compiles lib/bootconfig.c
> directly, which lets a follow-up patch reuse the same renderer in the
> userspace tool to convert a bootconfig file into a flat cmdline string
> at build time.
>
> No functional change.
Yeah, this should be under lib/bootconfig.c
Thanks,
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> include/linux/bootconfig.h | 3 +++
> init/main.c | 45 -------------------------------------
> lib/bootconfig.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 59 insertions(+), 45 deletions(-)
>
> diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h
> index 692a5acc2ffc4..1c7f3b74ffcf3 100644
> --- a/include/linux/bootconfig.h
> +++ b/include/linux/bootconfig.h
> @@ -265,6 +265,9 @@ static inline struct xbc_node * __init xbc_node_get_subkey(struct xbc_node *node
> int __init xbc_node_compose_key_after(struct xbc_node *root,
> struct xbc_node *node, char *buf, size_t size);
>
> +/* Render key/value pairs under @root as a flat cmdline string */
> +int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root);
> +
> /**
> * xbc_node_compose_key() - Compose full key string of the XBC node
> * @node: An XBC node.
> diff --git a/init/main.c b/init/main.c
> index 96f93bb06c490..e363232b428b4 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -324,51 +324,6 @@ static void * __init get_boot_config_from_initrd(size_t *_size)
>
> #ifdef CONFIG_BOOT_CONFIG
>
> -static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
> -
> -#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
> -
> -static int __init xbc_snprint_cmdline(char *buf, size_t size,
> - struct xbc_node *root)
> -{
> - struct xbc_node *knode, *vnode;
> - char *end = buf + size;
> - const char *val, *q;
> - int ret;
> -
> - xbc_node_for_each_key_value(root, knode, val) {
> - ret = xbc_node_compose_key_after(root, knode,
> - xbc_namebuf, XBC_KEYLEN_MAX);
> - if (ret < 0)
> - return ret;
> -
> - vnode = xbc_node_get_child(knode);
> - if (!vnode) {
> - ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
> - if (ret < 0)
> - return ret;
> - buf += ret;
> - continue;
> - }
> - xbc_array_for_each_value(vnode, val) {
> - /*
> - * For prettier and more readable /proc/cmdline, only
> - * quote the value when necessary, i.e. when it contains
> - * whitespace.
> - */
> - q = strpbrk(val, " \t\r\n") ? "\"" : "";
> - ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
> - xbc_namebuf, q, val, q);
> - if (ret < 0)
> - return ret;
> - buf += ret;
> - }
> - }
> -
> - return buf - (end - size);
> -}
> -#undef rest
> -
> /* Make an extra command line under given key word */
> static char * __init xbc_make_cmdline(const char *key)
> {
> diff --git a/lib/bootconfig.c b/lib/bootconfig.c
> index c470b93d5dbc2..f445b7703fdd9 100644
> --- a/lib/bootconfig.c
> +++ b/lib/bootconfig.c
> @@ -408,6 +408,62 @@ const char * __init xbc_node_find_next_key_value(struct xbc_node *root,
> return ""; /* No value key */
> }
>
> +static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
> +
> +#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
> +
> +/**
> + * xbc_snprint_cmdline() - Render bootconfig keys under @root as a cmdline string
> + * @buf: Destination buffer (may be NULL when @size is 0 to query the length)
> + * @size: Size of @buf in bytes
> + * @root: Subtree root whose key=value pairs should be rendered
> + *
> + * Walk all key/value pairs under @root and emit them as a space-separated
> + * cmdline string into @buf. Values containing whitespace are quoted with
> + * double quotes. Returns the number of bytes that would be written if @buf
> + * were large enough (matching snprintf semantics), or a negative errno on
> + * failure.
> + */
> +int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
> +{
> + struct xbc_node *knode, *vnode;
> + char *end = buf + size;
> + const char *val, *q;
> + int ret;
> +
> + xbc_node_for_each_key_value(root, knode, val) {
> + ret = xbc_node_compose_key_after(root, knode,
> + xbc_namebuf, XBC_KEYLEN_MAX);
> + if (ret < 0)
> + return ret;
> +
> + vnode = xbc_node_get_child(knode);
> + if (!vnode) {
> + ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
> + if (ret < 0)
> + return ret;
> + buf += ret;
> + continue;
> + }
> + xbc_array_for_each_value(vnode, val) {
> + /*
> + * For prettier and more readable /proc/cmdline, only
> + * quote the value when necessary, i.e. when it contains
> + * whitespace.
> + */
> + q = strpbrk(val, " \t\r\n") ? "\"" : "";
> + ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
> + xbc_namebuf, q, val, q);
> + if (ret < 0)
> + return ret;
> + buf += ret;
> + }
> + }
> +
> + return buf - (end - size);
> +}
> +#undef rest
> +
> /* XBC parse and tree build */
>
> static int __init xbc_init_node(struct xbc_node *node, char *data, uint16_t flag)
>
> --
> 2.53.0-Meta
>
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string
2026-05-11 16:38 ` Breno Leitao
@ 2026-05-12 0:43 ` Masami Hiramatsu
0 siblings, 0 replies; 8+ messages in thread
From: Masami Hiramatsu @ 2026-05-12 0:43 UTC (permalink / raw)
To: Breno Leitao
Cc: Andrew Morton, Masami Hiramatsu, linux-kernel, linux-trace-kernel,
paulmck, oss, kernel-team
On Mon, 11 May 2026 09:38:25 -0700
Breno Leitao <leitao@debian.org> wrote:
> On Fri, May 08, 2026 at 02:56:41PM -0700, Andrew Morton wrote:
> > On Fri, 08 May 2026 06:55:02 -0700 Breno Leitao <leitao@debian.org> wrote:
> >
> > > Add a bootconfig -> kernel cmdline rendering capability shared between
> > > the kernel parser library and the userspace tools/bootconfig binary.
> > >
> > > The new userspace mode "tools/bootconfig -C <file>" walks a bootconfig
> > > file's "kernel" subtree and prints it as a flat, space-separated
> > > cmdline string suitable for direct use as (or appending to) a kernel
> > > command line.
> > >
> > > This series prepares tools/bootconfig and lib/bootconfig.c for an
> > > upcoming feature that lets the kernel build render an embedded
> > > bootconfig file's "kernel" subtree to a flat cmdline string and embed
> > > it in the kernel image.
> > >
> > > The follow-up series (sent separately) wires this into setup_arch() so
> > > early_param() handlers see values supplied via CONFIG_BOOT_CONFIG_EMBED_FILE,
> > > following Masami suggestion in [1]
> > >
> > > These two patches are pure groundwork. They add no kernel feature,
> > > change no runtime behavior, and are useful on their own (the new
> > > "tools/bootconfig -C" mode lets anyone render a .bootconfig file to
> > > a cmdline string from the shell).
> > >
> > > Landing them independently lets the follow-up series focus on the
> > > kernel-side plumbing without dragging the refactor and tool addition
> > > through the same review cycle.
> >
> > I'll assume that Masami will process this, although
> > `scripts/get_maintainer.pl lib/bootconfig.c' doesn't mention a git
> > tree.
> >
> > https://sashiko.dev/#/patchset/20260508-bootconfig_using_tools-v1-0-1132219aa773@debian.org
> > says a bunch of picky things which seem pretty ignorable to me. Your
> > call ;)
>
> Well, these are some warnings about not checking that the output was
> properly set. From my view, these are not new to this patch, it is just the
> pattern we see, which is fire-and-forget writes to stdout, which seems
> quite reasonable.
I confirmed there was no problem with UBSAN.
"NULL + 1" is undefined, yes, but "(char *)NULL + 1" is sane.
>
> If we decide to fix this, it would make more sense to do it file-wide
> instead of just in this patch code.
So no need to fix it. Let me pick this series.
Thanks!
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-05-12 0:43 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-08 13:55 [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Breno Leitao
2026-05-08 13:55 ` [PATCH 1/2] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Breno Leitao
2026-05-12 0:00 ` Masami Hiramatsu
2026-05-08 13:55 ` [PATCH 2/2] tools/bootconfig: render kernel.* subtree as cmdline string with -C Breno Leitao
2026-05-12 0:00 ` Masami Hiramatsu
2026-05-08 21:56 ` [PATCH 0/2] tools/bootconfig: render kernel.* subtree as a cmdline string Andrew Morton
2026-05-11 16:38 ` Breno Leitao
2026-05-12 0:43 ` Masami Hiramatsu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox