uboot如何向内核传参

本文介绍boot在向内核跳转的时候如何传参数的

uboot的环境变量

bootargs=earlyprintk console=ttyS0,115200 rootwait nprofile_irq_duration=on root=/dev/ram0 rootfstype=ramfs rdinit=/linuxrc 
bootcmd=run tftploadk
bootdelay=3
  1. uboot 往内核携带的参数就是bootargs携带的。

uboot跳转命令

  1. bootz zimage
    bootm booti 引导uimage image booti引导arm64的image
    语法 bootx kernel rootfs dtb

  2. bootefi, bootp, nboot
    这些启动的介质不一样先从某个地方加载完了后再跳转
    efi分区 网络 nand
    有些uboot支持文件系统,把内核、dtb打包进文件系统,uboot起来后先挂载文件系统吧内核读取出来到内存执行,这样升级直接uboot挂载文件U盘,pc上覆盖内核文件就可以。

  3. 我们常用的是uimage 用的最多也是bootm
    bootm --》uimage内部包含dtb的话就可以直接bootm kernel地址 也能起来

bootm 命令解析

我们一般使用bootm 0x5800000 - 0x56000000 或者直接bootm 0x580000
uboot\cmd\bootm.c

U_BOOT_CMD(
	bootm,	CONFIG_SYS_MAXARGS,	1,	do_bootm,
	"boot application image from memory", bootm_help_text
);
do_bootm-> 
	//判断有没有子命令这里发现并没有使用返回值 拿endp判断,因为bootm 0x5800000 后面带数字的话endp返回0 且simple_strtoul返回数值0x5800000 
	simple_strtoul(argv[0], &endp, 16);
	//所以bootm最终调用do_bootm_states函数
int do_bootm_states {
	ret = bootm_find_os(cmdtp, flag, argc, argv);//发现kernel判断kernel是什么类型的
}

----------------------------------
typedef struct image_header {
	__be32		ih_magic;	/* Image Header Magic Number	*/
	__be32		ih_hcrc;	/* Image Header CRC Checksum	*/
	__be32		ih_time;	/* Image Creation Timestamp	*/
	__be32		ih_size;	/* Image Data Size		*/
	__be32		ih_load;	/* Data	 Load  Address		*/
	__be32		ih_ep;		/* Entry Point Address		*/
	__be32		ih_dcrc;	/* Image Data CRC Checksum	*/
	uint8_t		ih_os;		/* Operating System		*/
	uint8_t		ih_arch;	/* CPU architecture		*/
	uint8_t		ih_type;	/* Image Type			*/
	uint8_t		ih_comp;	/* Compression Type		*/
	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
} image_header_t;
do_bootm
do_bootm_states
ret = bootm_start(cmdtp, flag, argc, argv)
ret = bootm_find_os(cmdtp, flag, argc, argv)
ret = bootm_find_other(cmdtp, flag, argc, argv)
lag = bootm_disable_interrupts();ret = bootm_load_os(images, 0)
根据uimage的64字节头,判断image类型合法性以及获取一些信息
  1. image_header_t 64字节的头
  2. 一般kernel类型IMAGE_FORMAT_LEGACY 可以看image 的第一个int 0x27051956
  3. 安卓类型magic ANDR_BOOT_MAGIC “ANDROID!”
  4. 校验magic,校验crc

bootm 的调用关系

在这里插入图片描述

static void boot_jump_linux(bootm_headers_t *images, int flag)
{
...
	unsigned long machid = gd->bd->bi_arch_number;
	char *s;
	void (*kernel_entry)(int zero, int arch, uint params);
	unsigned long r2;
	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
	s = env_get("machid");
	if (strict_strtoul(s, 16, &machid) 
	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
		r2 = (unsigned long)images->ft_addr;
	else
		r2 = gd->bd->bi_boot_params;
	kernel_entry(0, machid, r2);
...
}

struct tag *params

从上面的分析的流程来看最终传给kernek的三个参数r2等于gd->bd->bi_boot_params
而这个参数是一个地址,这个地址是保存了一个struct tag *类型。
在函数setup_start_tag(gd->bd);对其进行了赋值
从函数中得知gd->bd->bi_boot_params的值是个地址,有点类似struct tag 数组的首params总是指向一块新的struct tag空间。

struct tag {
	struct tag_header hdr;
	union {
		struct tag_core		core;
		struct tag_mem32	mem;
		struct tag_videotext	videotext;
		struct tag_ramdisk	ramdisk;
		struct tag_initrd	initrd;
		struct tag_serialnr	serialnr;
		...
	}
}
struct tag_header {
	u32 size;
	u32 tag;  //各种标识
};
eg:
setup_commandline_tag(gd->bd, commandline); -》params->hdr.tag = ATAG_CMDLINE;
setup_revision_tag(&params); -》params->hdr.tag = ATAG_REVISION;

/* board revision */
#define ATAG_REVISION	0x54410007
/* command line: \0 terminated string */
#define ATAG_CMDLINE	0x54410009
所以r2在内核看来是设么?
r2是指向一块块struct tag类型的首地址
每一块大小不定,
但每一块中的struct tag_header hdr;成员变量记录了这个块的大小以及块(tag)的类型

内核对bootargs的处理

查看内核cmdline

内核启动打印有体现
在这里插入图片描述
或者proc
在这里插入图片描述

cmd来源

  1. 来源于uboot
  2. 来自于内核自身配置—变量
  3. 来源于dts 的chose选项

在这里插入图片描述

赋值处理

start_kernel-》setup_arch-》mdesc = setup_machine_fdt(__atags_pointer);
-》early_init_dt_scan_nodes();-》of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-》
early_init_dt_scan_chosen-》p = of_get_flat_dt_prop(node, “bootargs”, &l);
在这里插入图片描述

内核对uboot传进来的tag的函数处理

setup_arch->setup_machine_tags

__atags_pointer-->汇编文件中指定等于r2的值
mdesc = setup_machine_fdt(__atags_pointer);   假如config_OF使能走这块
if (!mdesc)
		mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);,无dtb走这块
//我们采用dtb只分析setup_machine_fdt

  1. 经过测试boot_command_line的值setup_machine_fdt处理后便有了
  2. boot_command_line先存dtb中的bootargs 在然后uboot中的bootargs

early_init_dt_scan_chosen

early_init_dt_scan_chosen{
p = of_get_flat_dt_prop(node, "bootargs", &l);//取dtb中的bootargs
	if (p != NULL && l > 0)
		strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
#ifdef CONFIG_CMDLINE   //这块是对CONFIG_CMDLINE 宏的处理
#if defined(CONFIG_CMDLINE_EXTEND)//在dtb中的bootargs追加CONFIG_CMDLINE   
	strlcat(data, " ", COMMAND_LINE_SIZE);
	strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)//完全替换  用CONFIG_CMDLINE(dtb不生效了)  
	strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#else
	/* No arguments from boot loader, use kernel's  cmdl*/
	if (!((char *)data)[0])
		strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif
#endif /* CONFIG_CMDLINE */
}
遗留问题
1.setup_machine_fdt处理后boot_command_line里面有值了,且等于dtb的bootargs + uboot的bootargs
2. 我uboot是不带dtb的,dtb是和kernel绑定的,在接续dtb的时候咋体现的ubootbootargs的
3. p = of_get_flat_dt_prop(node, "bootargs", &l);得到的东西就是含uboot的bootargs不理解

bootargs的应用

取bootargs的一个参数console=
kernel\kernel\printk\printk.c
在这里插入图片描述
mtdparts=fc000000.nor_flash:1920k(linux),128k(fdt),20M(ramdisk),4M(jffs2),38272k(user),256k(env),384k(uboot)
在这里插入图片描述

这块内容参考linux内核模块化机制
,当我的cmdline中有console=的字符串是,内核自动调用console_setup函数,在这个函数中你对后面的参数解析啥的,就可以进行配置了。

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值