1、U-Boot 启动引导内核分析( 二) 2011-03-23 09:20:00| 分类: 默认分类 |字号大中小 订阅也许细心的你会问:我在用 UBoot 的时候并没有直接进入用户命令界面呀,而是在倒计时结束后自动引导 kernel。这是怎么回事呢?在 main_loop()函数当中有如下一段代码:#if defined(CONFIG_BOOTDELAY) /*获取 bootcmd 的内容*/*bootcmd=nand read 0x22000000 0xB0000 0x200000; bootm */?# ifndef CFG_HUSH_PARSERrun_command (s, 0);/*
2、运行 s 包含的命令*/*运行 nand read 0x22000000 0xB0000 0x200000表示将 NANDFLASH0xB0000处数据读取放于0x22000000 处,读取长度为0x200000*/*运行 bootm 命令,引导内核启动*/# elseparse_string_outer(s, FLAG_PARSE_SEMICOLON |FLAG_EXIT_FROM_LOOP);# endif?#endif /* CONFIG_BOOTDELAY */bootm 命令是什么?它是怎样引导内核的?要知道想解决这个问题,就要分析 common/cmd_bootm.c 中的函数 d
3、o_bootm,因为引导 kernel 就是 bootm 这条命令的工作,do_bootm 是命令 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, o
4、s_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.verify = getenv_yesno (“verify“);images.lmb = lmb_init(mem_start = getenv_bootm_low();mem_size = getenv_bootm_size();lmb_add(board_lmb_reserve(/* get kernel image h
5、eader, start address and length */* 获取内核镜像头信息 */* 打印 “# Booting kernel from Legacy Image at 22000000 .Image Name: Linux-2.6.30Image Type: ARM Linux Kernel Image (uncompressed)Data Size: 1507760 Bytes = 1.4 MBLoad Address: 20008000Entry Point: 20008000Verifying Checksum . OK”*/os_hdr = boot_get_kerne
6、l (cmdtp, flag, argc, argv,if (os_len = 0) puts (“ERROR: cant 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_
7、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/* Weve possible left the caches enabled during* bios emulation, so turn t
8、hem off again*/icache_disable();invalidate_l1_instruction_cache();flush_data_cache();dcache_disable();#endifswitch (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);memmov
9、e_wd (void *)load_start,(void *)os_data, os_len, CHUNKSZ);load_end = load_start + os_len;puts(“OKn“);break;puts (“OKn“);debug (“ kernel loaded at 0x%08lx, end = 0x%08lxn“, load_start, load_end);show_boot_progress (7);/* 加载错误 */if (load_start image_start) debug (“image_start = 0x%lX, image_end = 0x%l
10、xn“, image_start, image_end);debug (“load_start = 0x%lx, load_end = 0x%lxn“, load_start, load_end);if (images.legacy_hdr_valid) if (image_get_type ( else puts (“ERROR: new format image overwritten - “must RESET the board to recovern“);show_boot_progress (-113);do_reset (cmdtp, flag, argc, argv);show
11、_boot_progress (8);lmb_reserve(switch (os) default: /* handled by (original) Linux case */case IH_OS_LINUX:#ifdef CONFIG_SILENT_CONSOLEfixup_silent_linux();#endif/* 引导内核启动函数 */do_bootm_linux (cmdtp, flag, argc, argv, break;show_boot_progress (-9);#ifdef DEBUGputs (“n# Control returned to monitor - resetting.n“);do_reset (cmdtp, flag, argc, argv);#endifif (iflag)enable_interrupts();return 1;至此 do_bootm 函数完成引导内核前的准备任务了。引导内核启动函数将由 do_bootm_linux()函数执行。