kernel5.10
source: include/linux/init.h
以arm64架构实现为例
作用:可用于解析uboot传递给kernel的command_line
定义如下:
#define __setup_param(str, unique_id, fn, early) \
static const char __setup_str_##unique_id[] __initconst \
__aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__used __section(".init.setup") \
__attribute__((aligned((sizeof(long))))) \
= { __setup_str_##unique_id, fn, early }
#define __setup(str, fn) \
__setup_param(str, fn, fn, 0)
以printk.c中的例子__setup("console=", console_setup)进行说明:
__setup("console=", console_setup);
__
__setup_param("console=", console_setup, console_setup, 0);
__
static const char __setup_str_console_setup[] __initconst __aligned(1) = "console=";
static struct obs_kernel_param __setup_console_setup __used __section(".init.setup") __attribute__((aligned((sizeof(long))))) = { __setup_str_console_setup, console_setup, 0};
即定义了2个全局变量,
char类型的__setup_str_console_setup,__initconst,__aligned(1)均为属性
#define __initconst __section(".init.rodata") //表明该变量放置到.init.rodata地址段,由链接脚本定义
#define __aligned(x) __attribute__((__aligned__(x))) //表明该变量地址需1Byte对齐 https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-aligned-type-attribute
obs_kernel_param类型的__setup_console_setup,__used __section(".init.setup") __attribute__((aligned((sizeof(long)))))均为属性
__used__section(".init.setup")表明该变量放置到.init.setup地址段;
__attribute__((aligned((sizeof(long)))))表明该变量的地址的对齐要求
.init.setup段在链接脚本的定义如下:
#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
__setup_start = .; \
KEEP(*(.init.setup)) \
__setup_end = .;
变量__setup_start表明.init.setup段的起始地址;变量__setup_end表明.init.setup段的结束地址;代码中可以使用这两个变量;
extern const struct obs_kernel_param __setup_start[], __setup_end[];
kernel中的do_early_param函数会访问变量__setup_start[], __setup_end[],其函数调用路径如下:

do_early_param函数定义如下:
/* Check for early params. */
static int __init do_early_param(char *param, char *val,
const char *unused, void *arg)
{
const struct obs_kernel_param *p;
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && parameq(param, p->str)) ||
(strcmp(param, "console") == 0 &&
strcmp(p->str, "earlycon") == 0)
) {
if (p->setup_func(val) != 0)
pr_warn("Malformed early option '%s'\n", param);
}
}
/* We accept everything at this stage. */
return 0;
}
即轮询从__setup_start开始的obs_kernel_param类型的数组,并调用p->setup_func,对于__setup("console=", console_setup)即为函数console_setup。
文章详细解释了在LinuxKernel5.10版本中,如何通过宏定义`__setup_param`和`__setup`在ARM64架构下解析U-Boot传递给内核的command_line。这些宏定义创建了初始化时使用的全局变量,并将它们放入特定的内存段`.init.setup`。内核通过`do_early_param`函数遍历这些变量来执行相应的设置函数,如`console_setup`。
844





