U-boot给Kernel传参数


约定俗称tag标记(参数)。

在u-boot-1.1.6\include\asm-avr32\setup.h文件中

struct tag {
	struct tag_header hdr;    //结构体
	union {    //联合体
		struct tag_core core;
		struct tag_mem_range mem_range;
		struct tag_cmdline cmdline;
		struct tag_clock clock;
		struct tag_ethernet ethernet;
	} u;
};



在u-boot-1.1.6\lib_arm\armlinux.c中:

#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
    defined (CONFIG_CMDLINE_TAG) || \
    defined (CONFIG_INITRD_TAG) || \
    defined (CONFIG_SERIAL_TAG) || \
    defined (CONFIG_REVISION_TAG) || \
    defined (CONFIG_LCD) || \
    defined (CONFIG_VFD)
	setup_start_tag (bd);    //初始化tag结构体
#ifdef CONFIG_SERIAL_TAG
	setup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAG
	setup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
	setup_memory_tags (bd);    //设置RAM参数。告诉内核,内存从哪里开始,内存有多大
#endif
#ifdef CONFIG_CMDLINE_TAG
	setup_commandline_tag (bd, commandline);    //命令行参数
#endif
#ifdef CONFIG_INITRD_TAG
	if (initrd_start && initrd_end)
		setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
	setup_videolfb_tag ((gd_t *) gd);
#endif
	setup_end_tag (bd);    //初始化tag结构体结束
#endif


函数setup_start_tag也在此文件中armlinux.c定义,如下:

static void setup_start_tag (bd_t *bd)
{
	params = (struct tag *) bd->bi_boot_params;    //bd->bi_boot_params=0x30000100,在此地址开始放参数,
                                                       //双方约定(bootloader和linux内核)的地址
	params->hdr.tag = ATAG_CORE;    //struct tag_header hdr结构体,ATAG_CORE=0x54410001,表示一个参数的开始
	params->hdr.size = tag_size (tag_core);    //tag_size(tag_core)=5

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

	params = tag_next (params);    //下一个tag = 当前位置+5*4
}

①对上述的bi_boot_params进行搜索,从u-boot-1.1.6\board\100ask24x0\100ask24x0.c  发现到  gd->bd->bi_boot_params = 0x30000100;

② hdr.tag:        struct tag_header {

                        u32 size;
                        u32 tag;

                            };

   从u-boot-1.1.6\include\asm-avr32\setup.h中,可知ATAG_CORE=0x54410001。

③ struct tag_core {
 u32 flags;
 u32 pagesize;
 u32 rootdev;
     };

④ tag_size

    #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

    (sizeof(struct tag_header):头部的大小,从上面的结构体tag_header可知,u32 + u32 = 64位,8字节

    sizeof(struct type)=sizeof(tag_core) = u32 + u32 + u32 = 96位,12字节

    ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) = ((8+12)>>2) = 20 / 4 = 5

    所以tag_size=5。

u.core:

struct tag {
	struct tag_header hdr;    //结构体
	union {    //联合体
		struct tag_core core;
		…… …… ……
};
struct tag_core {
	u32 flags;		/* bit 0 = read-only */
	u32 pagesize;
	u32 rootdev;
};

⑥ #define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)),当前位置+头部的size,u32 *指针相加,指针加1,相当于加4。指针加5,相当于4*5,等于20



函数setup_memory_tags也在此文件中armlinux.c定义,如下:

static void setup_memory_tags (bd_t *bd)
{
	int i;

	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
		params->hdr.tag = ATAG_MEM;    //hdr.tag=0x54410002
		params->hdr.size = tag_size (tag_mem32);

		params->u.mem.start = bd->bi_dram[i].start;    //起始地址=0x3000 0000
		params->u.mem.size = bd->bi_dram[i].size;   //大小等于64M,64*1024*1024
                                                           //所以u.mem.size=0x400 0000
		params = tag_next (params);
	}
}
#endif /* CONFIG_SETUP_MEMORY_TAGS */

hdr.tag=0x54410002,当内核过来取参数时,根据这个值,知道这些参数代表什么意思

② #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) 

    tag_mem32=u32+u32=64位=8字节

    (8字节+8字节) / 4 = 4字节

③ u.mem.start = 0x30000000

u.mem.size = 0x4000000



函数setup_commandline_tag也在此文件中armlinux.c定义,如下:

static void setup_commandline_tag (bd_t *bd, char *commandline)
{
	char *p;

	if (!commandline)
		return;

	/* eat leading white space */
	for (p = commandline; *p == ' '; p++);

	/* skip non-existent command lines so the kernel will still
	 * use its default command line.
	 */
	if (*p == '\0')
		return;

	params->hdr.tag = ATAG_CMDLINE;    //hdr.tag=0x54410009
	params->hdr.size =
		(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;

	strcpy (params->u.cmdline.cmdline, p);

	params = tag_next (params);
}

① hdr.tag=0x54410009,当内核过来取参数时,根据这个值,知道这些参数代表什么意思



函数setup_end_tag也在此文件中armlinux.c定义,如下:

static void setup_end_tag (bd_t *bd)
{
	params->hdr.tag = ATAG_NONE;
	params->hdr.size = 0;
}

两个都是0。



最后写成:

#include "setup.h"

static struct tag *params;


void setup_start_tag(void)
{
	params = (struct tag *) 0x30000100;

	params->hdr.tag = ATAG_CORE;
	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);
}

void setup_memory_tags(void)
{
	params->hdr.tag = ATAG_MEM;
	params->hdr.size = tag_size (tag_mem32);

	params->u.mem.start = 0x30000000;
	params->u.mem.size = 0x4000000;

	params = tag_next (params);

}

int strlen(char *str)
{
	int i = 0;
	while (str[i])
	{
		i++;
	}
	return i;
}

void strcpy(char *dest, char *src)
{
	char *tmp = dest;
	while ((*dest++ = *src++) != '\0')
}

void setup_commandline_tag(char *cmdline)
{
	int len = strlen(cmdline) + 1;
	
	params->hdr.tag = ATAG_CMDLINE;
	params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;

	strcpy (params->u.cmdline.cmdline, cmdline);

	params = tag_next (params);

}

void setup_end_tag(void)
{
	params->hdr.tag = ATAG_NONE;
	params->hdr.size = 0;
}

void main(void)
{
	void (*theKernel)(int zero, int arch, unsigned int params);

	/* 0. 帮内核设置串口 : 内核启动开始的部分会从串口打印一些信息,但是内核一开始没有初始化串口 */
	uart0_init();

	/* 1. 从NAND FLASH里把内核读入内存 */
	puts("Copy kernel from nand\n\r");
	nand_read(0x60000+64, 0x30008000, 0x200000);

	/* 2. 设置参数 */
	puts("Set boot params\n\r");
	setup_start_tag();	//参数的开始
	setup_memory_tags();	//告诉内核我的内存有多大
	setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");	//命令行参数
	setup_end_tag();	//参数的结束
	

	/* 3. 跳转执行 */
	puts("Boot kernel\n\r");
	theKernel = (void (*)(int, int, unsigned int))0x30008000;
	theKernel(0, 362, 0x30000100);
	/*
	 * mov r0, #0
	 * ldr r1, =362
	 * ldr r2, =0x30000100
	 * mov pc, #0x30008000 */

	
	puts("Error\n\r");
	/* 如果一切正常,不会执行到这里 */
}



参考:https://blog.csdn.net/lanmanck/article/details/4294685


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值