发布时间 : 星期二 文章U-Boot启动引导内核分析(二)更新完毕开始阅读faa7cd3d6c85ec3a87c2c5c2
U-Boot启动引导内核分析(二)
2011-03-23 09:20:00| 分类: 默认分类 |字号大中小 订阅
也许细心的你会问:我在用UBoot的时候并没有直接进入用户命令界面呀,而是在倒计时结束后自动引导kern在 main_loop()函数当中有如下一段代码:
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) ? ? ?
s = getenv (\);
/*获取bootcmd 的内容*/
/*bootcmd=nand read 0x22000000 0xB0000 0x200000; bootm */ ? ?
# ifndef CFG_HUSH_PARSER run_command (s, 0); /*运行s包含的命令*/
/*运行nand read 0x22000000 0xB0000 0x200000表示将NANDFLASH 0xB0000处数据读取放于0x22000000处,读取长度为0x200000 */
/*运行bootm命令,引导内核启动*/ # else
parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); # endif ? ? ?
#endif /* CONFIG_BOOTDELAY */
bootm命令是什么?它是怎样引导内核的?
要知道想解决这个问题,就要分析common/cmd_bootm.c中的函数do_bootm,因为引导kernel就是bootm这条命数。
现在我们来分析一下common/cmd_bootm.c中的函数do_bootm,这是bootm命令的处理函数。 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
ulong iflag;
const char *type_name;
uint unc_len = CFG_BOOTM_LEN; uint8_t comp, type, os;
void *os_hdr;
ulong os_data, os_len; ulong image_start, image_end; ulong load_start, load_end; ulong mem_start; phys_size_t mem_size;
struct lmb lmb;
memset ((void *)&images, 0, sizeof (images)); images.verify = getenv_yesno (\); images.lmb = &lmb;
lmb_init(&lmb);
mem_start = getenv_bootm_low(); mem_size = getenv_bootm_size();
lmb_add(&lmb, (phys_addr_t)mem_start, mem_size);
board_lmb_reserve(&lmb);
/* get kernel image header, start address and length */ /* 获取内核镜像头信息 */
/* 打印 “## Booting kernel from Legacy Image at 22000000 ... Image Name: Linux-2.6.30
Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1507760 Bytes = 1.4 MB Load Address: 20008000 Entry Point: 20008000 Verifying Checksum ... OK”*/
os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, &images, &os_data, &os_len); if (os_len == 0) {
puts (\can't get kernel image!\\n\); return 1; }
/* get image parameters */ /* 获取内核镜像格式 */
switch (genimg_get_format (os_hdr)) { case IMAGE_FORMAT_LEGACY: /* 获取内核镜像参数 */
type = image_get_type (os_hdr); comp = image_get_comp (os_hdr); os = image_get_os (os_hdr);
image_end = image_get_image_end (os_hdr); load_start = image_get_load (os_hdr); break; }
image_start = (ulong)os_hdr; load_end = 0;
type_name = genimg_get_type_name (type);
/* 禁止所有中断 */ iflag = disable_interrupts();
#ifdef CONFIG_AMIGAONEG3SE /*
* We've possible left the caches enabled during * bios emulation, so turn them off again
*/
icache_disable();
invalidate_l1_instruction_cache(); flush_data_cache(); dcache_disable(); #endif
switch (comp) { case IH_COMP_NONE: /* 加载内核镜像 */
/* 打印“Loading Kernel Image ... OK” */ if (load_start == (ulong)os_hdr) { printf (\ XIP %s ... \ type_name); } else {
printf (\ Loading %s ... \ type_name);
memmove_wd ((void *)load_start,
(void *)os_data, os_len, CHUNKSZ); }
load_end = load_start + os_len; puts(\); break; }
puts (\);
debug (\ kernel loaded at 0xlx, end = 0xlx\\n\ load_start, load_end); show_boot_progress (7);
/* 加载错误 */
if ((load_start < image_end) && (load_end > image_start)) {
debug (\= 0x%lX, image_end = 0x%lx\\n\ image_start, image_end); debug (\= 0x%lx, load_end = 0x%lx\\n\ load_start, load_end);
if (images.legacy_hdr_valid) {
if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI) puts (\legacy format multi component \ \overwritten\\n\); } else {
puts (\new format image overwritten - \ \RESET the board to recover\\n\); show_boot_progress (-113); do_reset (cmdtp, flag, argc, argv); } }
show_boot_progress (8);
lmb_reserve(&lmb, load_start, (load_end - load_start));
switch (os) {
default: /* handled by (original) Linux case */ case IH_OS_LINUX:
#ifdef CONFIG_SILENT_CONSOLE fixup_silent_linux(); #endif
/* 引导内核启动函数 */
do_bootm_linux (cmdtp, flag, argc, argv, &images); break; }
show_boot_progress (-9); #ifdef DEBUG
puts (\Control returned to monitor - resetting...\\n\); do_reset (cmdtp, flag, argc, argv); #endif if (iflag)
enable_interrupts();
return 1; }
至此do_bootm函数完成引导内核前的准备任务了。引导内核启动函数将由do_bootm_linux()函数执行。