bootm引导内核过程详解之二

//文件名:u-boot-1.3.1/lib_arm/armlinux.c
//bootm引导内核过程详解之二

 

//由cmd_bootm.c中的do_bootm函数调用该函数来最终引导内核启动
/*
该函数的主要功能:
1. 设置传递内核参数,并将这些参数存储在内存指定位置(0x30000100)
2. 跳转到内核入口点执行,将控制权交给内核
*/

 

DECLARE_GLOBAL_DATA_PTR;
/*cmd_boot.c*/
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
//下面为传递内核参数相关函数的声明
#if defined (CONFIG_SETUP_MEMORY_TAGS) || /
    defined (CONFIG_CMDLINE_TAG) || /
    defined (CONFIG_INITRD_TAG) || /
    defined (CONFIG_SERIAL_TAG) || /
    defined (CONFIG_REVISION_TAG) || /
    defined (CONFIG_VFD) || /
    defined (CONFIG_LCD)
static void setup_start_tag (bd_t *bd);

# ifdef CONFIG_SETUP_MEMORY_TAGS
static void setup_memory_tags (bd_t *bd);
# endif
static void setup_commandline_tag (bd_t *bd, char *commandline);

# ifdef CONFIG_INITRD_TAG
static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
                  ulong initrd_end);
# endif
static void setup_end_tag (bd_t *bd);

# if defined (CONFIG_VFD) || defined (CONFIG_LCD)
static void setup_videolfb_tag (gd_t *gd);
# endif

#ifdef CONFIG_ETH_TAG
static void setup_eth_tag (bd_t *bd);
#endif


static struct tag *params;
#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */

extern image_header_t header;    /* from cmd_bootm.c */

void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
             ulong addr, ulong *len_ptr, int verify)
{
    ulong len = 0, checksum;
    ulong initrd_start, initrd_end;
    ulong data;
    void (*theKernel)(int zero, int arch, uint params);
    image_header_t *hdr = &header;
    bd_t *bd = gd->bd;

#ifdef CONFIG_CMDLINE_TAG
    char *commandline = getenv ("bootargs");  //读取命令行参数
#endif

    theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); //将image 头中定义的内核入口点地址(hdr->ih_ep)强制转换为函数指针类型
                            //hdr->ih_ep----Entry Point Address

    /*
     * Check if there is an initrd image
     */
    if (argc >= 3)
     {   //Ramdisk启动方式:bootm $kerneladdr $ramdisk
        /*
         * Now check if we have a multifile image
         */
    } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1]))
    {
       
    } else //我们的image执行该段代码
    {
        len = data = 0;
    }
//=============需传递给内核的参数,转换为TAGS================
//这些参数或者为板子配置文件默认的参数,或者为u-boot命令行设置的参数,并saveenv
//保存到gd,bd结构体中,这里将这些参数保存为ATAG格式的结构中,并存储在
//内存中的某一位置,我们这里用的是30000100,然后将这个地址通过thekernel传递给内核
#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) || /
    defined (CONFIG_ETH_TAG)
    //下面为传递内核参数相关函数的声明
    setup_start_tag (bd);
#ifdef CONFIG_SERIAL_TAG
    setup_serial_tag (&params);
#endif
#ifdef CONFIG_REVISION_TAG
    setup_revision_tag (&params);
#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
#ifdef CONFIG_ETH_TAG
    setup_eth_tag (bd);
#endif

    setup_end_tag (bd);

#endif
//============================================================
    /* we assume that the kernel is in place */
    printf ("/nStarting kernel .../n/n");
    cleanup_before_linux ();  //进入内核前进行相关的清理工作
    theKernel (0, bd->bi_arch_number, bd->bi_boot_params);//跳转到内核入口点执行,将控制权交给内核
}
//下面是传递内核参数相关函数的实现
#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) || /
    defined (CONFIG_ETH_TAG)
   
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);
}
//中间省略...........
#ifdef CONFIG_ETH_TAG
static void setup_eth_tag (bd_t *bd)
{

    params->hdr.tag = ATAG_ETH;
    params->hdr.size = tag_size (tag_eth);

    memcpy(params->u.eth.mac_addr,bd->bi_enetaddr, 6);
    params->u.eth.ip_addr = bd->bi_ip_addr;
    params = tag_next (params);
}
#endif /* CONFIG_ETH_TAG */

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

#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG ||CONFIG_ETH_TAG */

你可能感兴趣的:(linux,image,struct,header,cmd,tags)