U-Boot启动引导内核分析(二) 联系客服

发布时间 : 星期二 文章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()函数执行。