uboot以tag方式给内核传参

本文详细介绍了Linux内核启动时通过tag方式传递参数的方法,包括tag的数据结构、tag_header的作用、不同类型的tag结构以及如何构建和接收tag参数。重点讲解了structtag_header和structtag的组成,以及uboot与kernel如何配合使用这种传参机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、tag方式传参

(1)struct tag,tag是一个数据结构,在uboot和linux kernel中都有定义tag数据机构,而且定义是一样的。
(2)tag_header和tag_xxx。tag_header中有这个tag的size和类型编码,kernel拿到一个tag后先分析tag_header得到tag的类型和大小,然后将tag中剩余部分当作一个tag_xxx来处理。
(3)tag_start与tag_end。kernel接收到的传参是若干个tag构成的,这些tag由ATAG_CORE类型的tag起始,到ATAG_NONE类型的tag结束。
(4)tag传参的方式是由linux kernel发明的,kernel定义了这种向我传参的方式,uboot只是实现了这种传参方式从而可以支持给kernel传参。

2、内核如何接收tag参数

启动内核的代码:theKernel (0, machid, bd->bi_boot_params);其中bd->bi_boot_params就是所有tag结构体所在的首地址,这个地址是保存在全局变量gd->bd中的,在uboot启动的前期会指定内存地址用于存放tag结构体,然后在启动内核的时候传给内核,内核拿到地址就会从该地址去遍历tag结构体,内核会判断tag的类型,如果是ATAG_CORE类型的tag则是起始的tag,如果是ATAG_NONE则是最后一个tag结构体,不用再往后遍历。

3、tag结构体

struct tag_header {
		u32 size;	//结构体的大小
		u32 tag;	//结构体的类型
	};

struct tag {
       struct tag_header hdr;
		union { 	//此枚举体包含了uboot传给内核参数的所有类型
				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_revision     revision;
				struct tag_videolfb     videolfb;
				struct tag_cmdline      cmdline;
				
				/*
				* Acorn specific
				*/
				struct tag_acorn        acorn;
				
				/*
				 * DC21285 specific
				 */
				struct tag_memclk       memclk;
				
				struct tag_mtdpart      mtdpart_info;
		} u;
};

4、构建tag结构体

	/* The list must start with an ATAG_CORE node */
	#define ATAG_CORE	0x54410001
	
	/* The list ends with an ATAG_NONE node. */
	#define ATAG_NONE	0x00000000
	
	#define tag_size(type)	((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
	#define tag_next(t)	((struct tag *)((u32 *)(t) + (t)->hdr.size))
	
	static struct tag *params;
	
	static void setup_start_tag (bd_t *bd)
	{
		params = (struct tag *) bd->bi_boot_params;//bd->bi_boot_params是专门用于保存tag结构体的内存首地址

		params->hdr.tag = ATAG_CORE;	//ATAG_CORE类型是tag结构体的开始
		params->hdr.size = tag_size (tag_core);	//结构体的大小

		params->u.core.flags = 0;
		params->u.core.pagesize = 0;
		params->u.core.rootdev = 0;

		params = tag_next (params);	//将指针偏移params->hdr.size个字节,让params指向下一个可用的内存地址
	}
	
	`````````中间省略掉其他类型tag结构体的构建
	
	static void setup_end_tag (bd_t *bd)
	{
		params->hdr.tag = ATAG_NONE;
		params->hdr.size = 0;
	}
在U-Boot中,`bootz` 和 `bootm` 指令都是用于启动操作系统的命令,但是它们分别针对不同类型的内核镜像设计。 ### bootm `bootm` 命令主要用于启动压缩或未压缩的Linux Kernel镜像(通常是`.bin` 或 `.uImage` 格式)。它支持多种架构,并能够处理各种情况下的内核加载过程,例如解压、设置ATAG等。对于老版本的ARM Linux系统来说,使用的是ATAG机制传递启动参数给Kernel,此时我们会选择使用`bootm`。 语法示例: ``` bootm [addr [arg ...]] ``` 其中 addr 表示存放kernel映像的位置地址(一般位于RAM);如果需要传参,则可以继续添加后面的args部分表示额外附加信息如initrd位置及根文件系统所在等等内容。 ### bootz 而随着设备树(Device Tree Blob, DTB) 的引入,在较新的ARM平台下更倾向于采用device tree替代传统atags的方式描述硬件配置细节。于是有了专门适用于这种场景需求的新指令——即`bootz` 。该命令专为未经压缩的纯文本形式(zImage/xImage)以及与其关联联立使用的dtb文件准备而成。 语法结构类似于下面这样: ``` bootz zimage_addr [initrd_addr:initrd_size] [fdt_blob_addr] ``` 可以看到这里除了指定核心映象外还可以同时指明初始化ramdisk(initrd) 及其大小还有最终实际运行环境所依赖的具体板级描述符(devicetree blob). 总结起来说就是:`bootm` 更加通用一些, 它能适应更多种情形包括旧式的基于tags的数据交流模式; 而当面对现代化依靠devicetrees来表达全部必要属性设定值之时则应优先考虑运用`bootz`.
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值