//文件名: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 (¶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
#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 */