linux __setup(str, fn)

文章详细解释了在LinuxKernel5.10版本中,如何通过宏定义`__setup_param`和`__setup`在ARM64架构下解析U-Boot传递给内核的command_line。这些宏定义创建了初始化时使用的全局变量,并将它们放入特定的内存段`.init.setup`。内核通过`do_early_param`函数遍历这些变量来执行相应的设置函数,如`console_setup`。

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。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值