Chinaunix首页 | 论坛 | 博客
  • 博客访问: 90069
  • 博文数量: 22
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 240
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-03 11:02
文章分类

全部博文(22)

文章存档

2011年(1)

2010年(21)

我的朋友

分类: LINUX

2010-03-30 15:41:06

U-BOOT 在启动内核时,会向内核传递一些列的参数.
启动内核从函数: void do_bootm_linux();开始. 每一个平台都有对应的这个函数的实现.例如在arm平台下, 该函数的实现位于: armlinux.c 文件中.


在do_bootm_linux() 的最后有如下代码:


#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);
#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);
#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);
#endif

    /* we assume that the kernel is in place */
    printf ("\nStarting kernel ...\n\n");

#ifdef CONFIG_USB_DEVICE
    {
        extern void udc_disconnect (void);
                //udc_disconnect (); // cancled by
    }
#endif

    cleanup_before_linux ();

    //从这里启动内核.
    theKernel (0, bd->bi_arch_number, bd->bi_boot_params);



我们可以看到顺序的有以下几个函数的调用:
setup_start_tag (bd);
 setup_serial_tag (¶ms);
setup_revision_tag (¶ms);
setup_memory_tags (bd);
setup_commandline_tag (bd, commandline);
setup_initrd_tag();
setup_end_tag (bd);

当然, 有很多的宏来选择是否传递相应的tag到linux kenel. 实际是这些所以针对于 bd->bi_boot_params 这个变量. 这个变量是个整形变量,代表存放所有tag的buffer的地址.

例如,在smdk2410.c 中的 board_init() 函数中,对于这个变量进行了如下赋值:

    /* adress of boot parameters */
    gd->bd->bi_boot_params = 0x30000100;


0x30000100这个值可以随意指定, 但是要保证和内核中相应的mach_type 一致.以smdk2410为例:
在内核中始终这个值的地方是: arch\arm\mach-s3c2410\mach-smdk2410.c的最后

MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
                    * to SMDK2410 */
    /* Maintainer: Jonas Dietsche */
    .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 ...
死掉.



一般需要定义:
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_CMDLINE_TAG




 

阅读(2079) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-08-26 16:40:09

很有启发