uboot以tag方式给内核传参

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;
	}

おすすめ

転載: blog.csdn.net/weixin_42031299/article/details/121239507