uboot给linux传递参数流程

本文详细介绍了U-Boot如何使用ATAG向Linux内核传递参数,并阐述了Linux内核如何解析这些参数的过程。包括ATAG的定义、传递方式及Linux内核中的解析流程。

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

是用mindmanager转的,格式有点不太好。

1 ATAG

1.1 为什么用ATAG

         ubootatagkernel传递信息

         atag的定义可以在ubootinclude/asm/setup.h 中找到对应linux中的定义位于arch/arm/include/asm/setup.h中。两者的定义要相同。

         参数链表必须以ATAG_CORE 开始,以ATAG_NONE 结束。这里的ATAG_CORE,ATAG_NONE 是各个参数的标记,本身是一个32 位值,例如在setup.h中的定义:

         /* The list must start with an ATAG_CORE node */

          #define ATAG_CORE0x54410001

 

         其它的参数标记还包括: ATAG_MEM32 , ATAG_INITRD , ATAG_RAMDISK ,ATAG_COMDLINE 等。每个参数标记就代表一个参数结构体由各个参数结构体构成了参数链表。参数链表的结构体为:

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

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

  } u;

};

参数结构体包括两个部分,一个是 tag_header 结构体,一个是u 联合体。

 

tag_header 结构体的定义如下

struct tag_header 

{

u32 size;

u32 tag;

};

 

                其中 size表示整个tag 结构体的大小(用字的个数来表示而不是字节的个数)等于tag_header 的大小加上u 联合体的大小例如参数结构体ATAG_CORE size= (sizeof(tag->tag_header)+sizeof(tag->u.core))>>2一般通过函数 tag_size(struct * tag_xxx)来获得每个参数结构体的size。其中tag:表示整个tag 结构体的标记,如:ATAG_CORE等。

 

1.2 uboot传递ATAG

        在uboot下的do_bootm_linux函数中,调用:

        theKernel (0, machid, bd->bi_boot_params);

        来启动内核。

        将bi_boot_paramsATAG作为参数传递给linux内核。

       调用的时候,R00R1machidR2ATAG的地址。

 

       同时在该函数中,会看到一堆的setup_xxx_tag的函数。cmdline就是这样传的。

 

1.3 linux接收ATAG

       在arch/arm/kernel/head.S中的stext中有这么一句:

  /*

   * r1 = machine no, r2 = atags or dtb,

   * r8 = phys_offset, r9 = cpuid, r10 = procinfo

   */

  bl __vet_atags

       与uboottheKernel 的参数是对应的。

       __vet_atags是读r2地址上的sizetag看是否是正确的ATAG_CORE

 

 

2 linux接收ATAG流程

2.1 stext (arch/arm/kernel/head.S)

 

2.2 __mmap_switched (arch/arm/kernel/head-common.S)

str  r2, [r6]

.long  __atags_pointer       @ r6

ATAG指针存到__atags_pointer变量中。

 

2.3 start_kernel init/mai.c

2.3.1 setup_arch(&command_line); 在这里面将command_line指向static char __initdata cmd_line[COMMAND_LINE_SIZE];

setup_machine_tags

 

   __atags_pointer得到tags

  if (__atags_pointer)

     tags = phys_to_virt(__atags_pointer);

  else if (mdesc->atag_offset)

     tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);

   。。。。 

   if (tags->hdr.tag == ATAG_CORE) {

     if (meminfo.nr_banks != 0)

       squash_mem_tags(tags);

     save_atags(tags);

     parse_tags(tags);解析tags

  }

parse_tags 解析tags

 

static int __init parse_tag(const struct tag *tag)

{

  extern struct tagtable __tagtable_begin, __tagtable_end;

  struct tagtable *t;

 

  for (t = &__tagtable_begin; t < &__tagtable_end; t++)

     if (tag->hdr.tag == t->tag) {

       t->parse(tag);

       break;

     }

 

  return t < &__tagtable_end;

}

 

/arch/arm/kernel/vmlinux.lds中有__tagtable_begin

 .init.tagtable : { 

  __tagtable_begin = .;

  *(.taglist.init)

  __tagtable_end = .;

 }

 

所有的解析函数用__tagtable声明:

__tagtable(ATAG_CORE, parse_tag_core);

#define __tag __used __attribute__((__section__(".taglist.init")))

#define __tagtable(tag, fn) \

static const struct tagtable __tagtable_##fn __tag = { tag, fn }

所以所有的解析函数都是放在了taglist.init区域。

 

parse_tag_cmdline函数中,将cmdline复制到default_command_line变量中。

strlcat(default_command_line, tag->u.cmdline.cmdline,

 

保存到boot_command_line

setup_machine_tags中:

strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);

保存到command_line

setup_arch中,将参数command_line指向cmd_line

 

  /* populate cmd_line too for later use, preserving boot_command_line */

  strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);

  *cmdline_p = cmd_line;

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值