Skip to content

Commit

Permalink
bootconfig: Support embedding a bootconfig file in kernel
Browse files Browse the repository at this point in the history
This allows kernel developer to embed a default bootconfig file in
the kernel instead of embedding it in the initrd. This will be good
for who are using the kernel without initrd, or who needs a default
bootconfigs.
This needs to set two kconfigs: CONFIG_BOOT_CONFIG_EMBED=y and set
the file path to CONFIG_BOOT_CONFIG_EMBED_FILE.

Note that you still need 'bootconfig' command line option to load the
embedded bootconfig. Also if you boot using an initrd with a different
bootconfig, the kernel will use the bootconfig in the initrd, instead
of the default bootconfig.

Link: https://lkml.kernel.org/r/164921227943.1090670.14035119557571329218.stgit@devnote2

Cc: Padmanabha Srinivasaiah <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Nick Desaulniers <[email protected]>
Cc: Sami Tolvanen <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Masahiro Yamada <[email protected]>
Cc: Linux Kbuild mailing list <[email protected]>
Signed-off-by: Masami Hiramatsu <[email protected]>
Signed-off-by: Steven Rostedt (Google) <[email protected]>
  • Loading branch information
mhiramat authored and rostedt committed Apr 26, 2022
1 parent 765b855 commit a2a9d67
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 11 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7457,6 +7457,7 @@ S: Maintained
F: Documentation/admin-guide/bootconfig.rst
F: fs/proc/bootconfig.c
F: include/linux/bootconfig.h
F: lib/bootconfig-data.S
F: lib/bootconfig.c
F: tools/bootconfig/*
F: tools/bootconfig/scripts/*
Expand Down
10 changes: 10 additions & 0 deletions include/linux/bootconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,14 @@ int __init xbc_get_info(int *node_size, size_t *data_size);
/* XBC cleanup data structures */
void __init xbc_exit(void);

/* XBC embedded bootconfig data in kernel */
#ifdef CONFIG_BOOT_CONFIG_EMBED
const char * __init xbc_get_embedded_bootconfig(size_t *size);
#else
static inline const char *xbc_get_embedded_bootconfig(size_t *size)
{
return NULL;
}
#endif

#endif
21 changes: 20 additions & 1 deletion init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ endif

config BOOT_CONFIG
bool "Boot config support"
select BLK_DEV_INITRD
select BLK_DEV_INITRD if !BOOT_CONFIG_EMBED
help
Extra boot config allows system admin to pass a config file as
complemental extension of kernel cmdline when booting.
Expand All @@ -1361,6 +1361,25 @@ config BOOT_CONFIG

If unsure, say Y.

config BOOT_CONFIG_EMBED
bool "Embed bootconfig file in the kernel"
depends on BOOT_CONFIG
help
Embed a bootconfig file given by BOOT_CONFIG_EMBED_FILE in the
kernel. Usually, the bootconfig file is loaded with the initrd
image. But if the system doesn't support initrd, this option will
help you by embedding a bootconfig file while building the kernel.

If unsure, say N.

config BOOT_CONFIG_EMBED_FILE
string "Embedded bootconfig file path"
depends on BOOT_CONFIG_EMBED
help
Specify a bootconfig file which will be embedded to the kernel.
This bootconfig will be used if there is no initrd or no other
bootconfig in the initrd.

choice
prompt "Compiler optimization level"
default CC_OPTIMIZE_FOR_PERFORMANCE
Expand Down
22 changes: 12 additions & 10 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ static int __init loglevel(char *str)
early_param("loglevel", loglevel);

#ifdef CONFIG_BLK_DEV_INITRD
static void * __init get_boot_config_from_initrd(u32 *_size)
static void * __init get_boot_config_from_initrd(size_t *_size)
{
u32 size, csum;
char *data;
Expand Down Expand Up @@ -313,7 +313,7 @@ static void * __init get_boot_config_from_initrd(u32 *_size)
return data;
}
#else
static void * __init get_boot_config_from_initrd(u32 *_size)
static void * __init get_boot_config_from_initrd(size_t *_size)
{
return NULL;
}
Expand Down Expand Up @@ -410,14 +410,16 @@ static int __init warn_bootconfig(char *str)
static void __init setup_boot_config(void)
{
static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
const char *msg;
int pos;
u32 size;
char *data, *err;
int ret;
const char *msg, *data;
int pos, ret;
size_t size;
char *err;

/* Cut out the bootconfig data even if we have no bootconfig option */
data = get_boot_config_from_initrd(&size);
/* If there is no bootconfig in initrd, try embedded one. */
if (!data)
data = xbc_get_embedded_bootconfig(&size);

strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
Expand All @@ -436,8 +438,8 @@ static void __init setup_boot_config(void)
}

if (size >= XBC_DATA_MAX) {
pr_err("bootconfig size %d greater than max size %d\n",
size, XBC_DATA_MAX);
pr_err("bootconfig size %ld greater than max size %d\n",
(long)size, XBC_DATA_MAX);
return;
}

Expand All @@ -450,7 +452,7 @@ static void __init setup_boot_config(void)
msg, pos);
} else {
xbc_get_info(&ret, NULL);
pr_info("Load bootconfig: %d bytes %d nodes\n", size, ret);
pr_info("Load bootconfig: %ld bytes %d nodes\n", (long)size, ret);
/* keys starting with "kernel." are passed via cmdline */
extra_command_line = xbc_make_cmdline("kernel");
/* Also, "init." keys are init arguments */
Expand Down
1 change: 1 addition & 0 deletions lib/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
/crc32table.h
/crc64table.h
/default.bconf
/gen_crc32table
/gen_crc64table
/oid_registry_data.c
Expand Down
8 changes: 8 additions & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ $(foreach file, $(libfdt_files), \
lib-$(CONFIG_LIBFDT) += $(libfdt_files)

obj-$(CONFIG_BOOT_CONFIG) += bootconfig.o
obj-$(CONFIG_BOOT_CONFIG_EMBED) += bootconfig-data.o

$(obj)/bootconfig-data.o: $(obj)/default.bconf

targets += default.bconf
filechk_defbconf = cat $(or $(real-prereqs), /dev/null)
$(obj)/default.bconf: $(CONFIG_BOOT_CONFIG_EMBED_FILE) FORCE
$(call filechk,defbconf)

obj-$(CONFIG_RBTREE_TEST) += rbtree_test.o
obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o
Expand Down
10 changes: 10 additions & 0 deletions lib/bootconfig-data.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Embed default bootconfig in the kernel.
*/
.section .init.rodata, "aw"
.global embedded_bootconfig_data
embedded_bootconfig_data:
.incbin "lib/default.bconf"
.global embedded_bootconfig_data_end
embedded_bootconfig_data_end:
13 changes: 13 additions & 0 deletions lib/bootconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
#include <linux/kernel.h>
#include <linux/memblock.h>
#include <linux/string.h>

#ifdef CONFIG_BOOT_CONFIG_EMBED
/* embedded_bootconfig_data is defined in bootconfig-data.S */
extern __visible const char embedded_bootconfig_data[];
extern __visible const char embedded_bootconfig_data_end[];

const char * __init xbc_get_embedded_bootconfig(size_t *size)
{
*size = embedded_bootconfig_data_end - embedded_bootconfig_data;
return (*size) ? embedded_bootconfig_data : NULL;
}
#endif

#else /* !__KERNEL__ */
/*
* NOTE: This is only for tools/bootconfig, because tools/bootconfig will
Expand Down

0 comments on commit a2a9d67

Please sign in to comment.