Skip to content

Commit

Permalink
bootconfig: init: Allow admin to use bootconfig for kernel command line
Browse files Browse the repository at this point in the history
Since the current kernel command line is too short to describe
many options which supported by kernel, allow user to use boot
config to setup (add) the command line options.

All kernel parameters under "kernel." keywords will be used
for setting up extra kernel command line.

For example,

kernel {
	audit = on
	audit_backlog_limit = 256
}

Note that you can not specify some early parameters
(like console etc.) by this method, since it is
loaded after early parameters parsed.

Link: http://lkml.kernel.org/r/157867228333.17873.11962796367032622466.stgit@devnote2

Signed-off-by: Masami Hiramatsu <[email protected]>
Signed-off-by: Steven Rostedt (VMware) <[email protected]>
  • Loading branch information
mhiramat authored and rostedt committed Jan 13, 2020
1 parent 0068c92 commit 51887d0
Showing 1 changed file with 101 additions and 5 deletions.
106 changes: 101 additions & 5 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ char __initdata boot_command_line[COMMAND_LINE_SIZE];
char *saved_command_line;
/* Command line for parameter parsing */
static char *static_command_line;
/* Untouched extra command line */
static char *extra_command_line;

static char *execute_command;
static char *ramdisk_execute_command;
Expand Down Expand Up @@ -245,6 +247,83 @@ static int __init loglevel(char *str)
early_param("loglevel", loglevel);

#ifdef CONFIG_BOOT_CONFIG

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;
char c = '\"';
const char *val;
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);
ret = snprintf(buf, rest(buf, end), "%s%c", xbc_namebuf,
vnode ? '=' : ' ');
if (ret < 0)
return ret;
buf += ret;
if (!vnode)
continue;

c = '\"';
xbc_array_for_each_value(vnode, val) {
ret = snprintf(buf, rest(buf, end), "%c%s", c, val);
if (ret < 0)
return ret;
buf += ret;
c = ',';
}
if (rest(buf, end) > 2)
strcpy(buf, "\" ");
buf += 2;
}

return buf - (end - size);
}
#undef rest

/* Make an extra command line under given key word */
static char * __init xbc_make_cmdline(const char *key)
{
struct xbc_node *root;
char *new_cmdline;
int ret, len = 0;

root = xbc_find_node(key);
if (!root)
return NULL;

/* Count required buffer size */
len = xbc_snprint_cmdline(NULL, 0, root);
if (len <= 0)
return NULL;

new_cmdline = memblock_alloc(len + 1, SMP_CACHE_BYTES);
if (!new_cmdline) {
pr_err("Failed to allocate memory for extra kernel cmdline.\n");
return NULL;
}

ret = xbc_snprint_cmdline(new_cmdline, len + 1, root);
if (ret < 0 || ret > len) {
pr_err("Failed to print extra kernel cmdline.\n");
return NULL;
}

return new_cmdline;
}

u32 boot_config_checksum(unsigned char *p, u32 size)
{
u32 ret = 0;
Expand Down Expand Up @@ -289,8 +368,11 @@ static void __init setup_boot_config(void)

if (xbc_init(copy) < 0)
pr_err("Failed to parse boot config\n");
else
else {
pr_info("Load boot config: %d bytes\n", size);
/* keys starting with "kernel." are passed via cmdline */
extra_command_line = xbc_make_cmdline("kernel");
}
}
#else
#define setup_boot_config() do { } while (0)
Expand Down Expand Up @@ -425,7 +507,12 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
*/
static void __init setup_command_line(char *command_line)
{
size_t len = strlen(boot_command_line) + 1;
size_t len, xlen = 0;

if (extra_command_line)
xlen = strlen(extra_command_line);

len = xlen + strlen(boot_command_line) + 1;

saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
if (!saved_command_line)
Expand All @@ -435,8 +522,17 @@ static void __init setup_command_line(char *command_line)
if (!static_command_line)
panic("%s: Failed to allocate %zu bytes\n", __func__, len);

strcpy(saved_command_line, boot_command_line);
strcpy(static_command_line, command_line);
if (xlen) {
/*
* We have to put extra_command_line before boot command
* lines because there could be dashes (separator of init
* command line) in the command lines.
*/
strcpy(saved_command_line, extra_command_line);
strcpy(static_command_line, extra_command_line);
}
strcpy(saved_command_line + xlen, boot_command_line);
strcpy(static_command_line + xlen, command_line);
}

/*
Expand Down Expand Up @@ -652,7 +748,7 @@ asmlinkage __visible void __init start_kernel(void)
build_all_zonelists(NULL);
page_alloc_init();

pr_notice("Kernel command line: %s\n", boot_command_line);
pr_notice("Kernel command line: %s\n", saved_command_line);
/* parameters may set static keys */
jump_label_init();
parse_early_param();
Expand Down

0 comments on commit 51887d0

Please sign in to comment.