U-Boot启动引导内核分析(二)
2010-09-13 20:50
549 查看
标签:ARM bootloader U-Boot 代码分析 抵岸科技
也许细心的你会问:我在用UBoot的时候并没有直接进入用户命令界面呀,而是在倒计时结束后自动引导kernel。这是怎么回事呢?
在 main_loop()函数当中有如下一段代码:
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
•
•
•
s = getenv ("bootcmd");
/*获取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这条命令的工作,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, 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 ("verify");
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 ("ERROR: 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("OK/n");
break;
}
puts ("OK/n");
debug (" kernel loaded at 0x%08lx, end = 0x%08lx/n", load_start, load_end);
show_boot_progress (7);
/* 加载错误 */
if ((load_start < image_end) && (load_end > image_start)) {
debug ("image_start = 0x%lX, image_end = 0x%lx/n", image_start, image_end);
debug ("load_start = 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 ("WARNING: legacy format multi component "
"image overwritten/n");
} else {
puts ("ERROR: new format image overwritten - "
"must 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 ("/n## Control returned to monitor - resetting.../n");
do_reset (cmdtp, flag, argc, argv);
#endif
if (iflag)
enable_interrupts();
return 1;
}
至此do_bootm函数完成引导内核前的准备任务了。引导内核启动函数将由do_bootm_linux()函数执行。
也许细心的你会问:我在用UBoot的时候并没有直接进入用户命令界面呀,而是在倒计时结束后自动引导kernel。这是怎么回事呢?
在 main_loop()函数当中有如下一段代码:
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
•
•
•
s = getenv ("bootcmd");
/*获取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这条命令的工作,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, 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 ("verify");
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 ("ERROR: 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("OK/n");
break;
}
puts ("OK/n");
debug (" kernel loaded at 0x%08lx, end = 0x%08lx/n", load_start, load_end);
show_boot_progress (7);
/* 加载错误 */
if ((load_start < image_end) && (load_end > image_start)) {
debug ("image_start = 0x%lX, image_end = 0x%lx/n", image_start, image_end);
debug ("load_start = 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 ("WARNING: legacy format multi component "
"image overwritten/n");
} else {
puts ("ERROR: new format image overwritten - "
"must 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 ("/n## Control returned to monitor - resetting.../n");
do_reset (cmdtp, flag, argc, argv);
#endif
if (iflag)
enable_interrupts();
return 1;
}
至此do_bootm函数完成引导内核前的准备任务了。引导内核启动函数将由do_bootm_linux()函数执行。
相关文章推荐
- U-Boot启动引导内核分析
- 转: U-Boot启动引导内核分析
- Linux0.11内核--启动引导代码分析bootsect.s
- Linux0.11内核--启动引导代码分析bootsect.s
- Linux0.11内核--启动引导代码分析bootsect.s
- U-Boot启动引导内核分析(一)
- 学习笔记--- U-BOOT从启动到引导内核过程分析
- U-Boot启动引导内核分析(三)
- u-boot2013.01 smdk2410 启动第二阶段分析之引导内核
- U-boot引导内核流程分析
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之四--U-boot如何引导Linux内核启动?
- U-boot 2011.09 启动内核分析
- Linux0.11内核--启动引导代码分析setup.s
- [Linux内核完全剖析]第六章 引导启动程序(boot)总结
- u-boot分析(三)---boot命令实现以及内核的启动
- u-boot.lds分析(u-boot-1.3.4 nandflash启动 引导linux内核)
- Linux0.11内核--启动引导代码分析setup.s
- u-boot2011.09启动内核分析
- U-Boot启动内核分析
- Exynos4412 Uboot 移植(四)—— Uboot引导内核过程分析