u-boot向linux内核传递启动参数

本文介绍U-Boot如何使用struct tag结构体向Linux内核传递启动参数,包括内存信息、命令行参数等,并解释了这些参数对内核启动的重要性。

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

U-BOOT 在启动内核时,会向内核传递一些参数.而这些参数是通过 structtag来传递的。 U-boot 把要传递给 kernel 的东西保存在 struct tag数据结构中,启动 kernel 时,把这个结构体的物理地址传给 kernelLinux kernel通过这个地址分析出u-boot传递的参数。
 
    例如u-boot-1.3.4在arm平台下,该函数的实现位于:lib_arm\Bootm.c文件中.
   在文件中有如下代码:(可以参照《完全手册》的244页)
#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)
static void setup_start_tag (bd_t *bd)
{
    params =(struct tag *) bd->bi_boot_params;

   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);
}
   上面是初始化tag链表(在SDRAM里),最后一句是作为链表的最关键部分,它的定义是:
#definetag_next(t)   ((struct tag *)((u32 *)(t) +(t)->hdr.size)) 作用是指向下一个tag结构体。
其中 defined (CONFIG_SETUP_MEMORY_TAGS) 和defined (CONFIG_CMDLINE_TAG) 是必不可少的。前者是标记内存的信息,而后者是设置命令行标记(比如 “root=/dev/mtdblock2init=/linuxrc console=ttySAC0”)
        /common/cmd_bootm.c文件中, bootm 命令对应的do_bootm函数,当分析 uImage 中信息发现 OS Linux 调用./lib_arm/bootm.c文件中的 do_bootm_linux函数来启动 Linuxkernel

       do_bootm_linux函数中:

voiddo_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char*argv[],

                 ulong addr, ulong *len_ptr, int verify)

{

......

#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 结构体开始

#ifdefCONFIG_SERIAL_TAG

      setup_serial_tag(&params);

#endif

#ifdefCONFIG_REVISION_TAG

      setup_revision_tag(&params);

#endif

#ifdefCONFIG_SETUP_MEMORY_TAGS

      setup_memory_tags(bd);     // 设置 RAM 参数

#endif

#ifdefCONFIG_CMDLINE_TAG

      setup_commandline_tag (bd, commandline);

#endif

#ifdefCONFIG_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

......

......

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

// 传给 Kernel 的参数=(struct tag*) 型的 bd->bi_boot_params

当然,有很多的宏来选择是否传递相应的tag到linuxkenel.实际是这些所以针对于 bd->bi_boot_params这个变量.这个变量是个整形变量,代表存放所有tag的buffer的地址.
例如,在 smdk2410.c 中的 board_init() 函数中,对于这个变量进行了如下赋值:
   
   gd->bd->bi_boot_params = 0x30000100;
0x30000100这个值可以随意指定, 但是要保证和内核中相应的mach_type 一致.以smdk2410为例:
在内核中始终这个值的地方是: arch\arm\mach-s3c2410\mach-smdk2410.c的最后
MACHINE_START(SMDK2410, "SMDK2410")
   
   .phys_ram    =S3C2410_SDRAM_PA,
   .phys_io    =S3C2410_PA_UART,
   .io_pg_offst   = (((u32)S3C24XX_VA_UART) >> 18)& 0xfffc,
    .boot_params   = S3C2410_SDRAM_PA + 0x100,
   .map_io       =smdk2410_map_io,
   .init_irq    =smdk2410_init_irq,
   .timer       =&s3c24xx_timer,
MACHINE_END
红色部分的值, 必须等于0x30000100, 否者将会出现无法启动的问题.
内核启动后,会读取0x300000100位置的值, 当然,内核会把这个地址转换成逻辑地址在操作. 因为内核跑起来后,MMU已经工作,必须要把
0x300000100这个物理地址转成逻辑地址然后在操作.
对于u- boot传给内核的参数中(tag), 内核比较关系memory的信息,比如memory地址的起始,大小等.
如果没有得到,那么内核无法启 动,内核会进入BUG()函数,然后死在那里.
memory的信息是由
CONFIG_SETUP_MEMORY_TAGS宏决定的. 因此当这个宏没有被定义时,内核跑不起来. 初始化meminfo时会失败.现象就是: 
Starting Kernel ...
死掉.
一般需要定义:
#defineCONFIG_SETUP_MEMORY_TAGS
#defineCONFIG_CMDLINE_TAG
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值