/*******************************************************************/
/* bootm - boot application image from image in memory */
/*******************************************************************/
int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
ulong iflag;
ulong load_end = 0;
int ret;
boot_os_fn *boot_fn;
#ifdef CONFIG_NEEDS_MANUAL_RELOC //手动从定位
static int relocated = 0;
if (!relocated) {
int i;
/* relocate boot function table */
for (i = 0; i < ARRAY_SIZE(boot_os); i++)
if (boot_os[i] != NULL)
boot_os[i] += gd->reloc_off;
/* relocate names of sub-command table */
for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
cmd_bootm_sub[i].name += gd->reloc_off;
relocated = 1;
}
#endif
/* determine if we have a sub command */
if (argc > 1) {
char *endp;
simple_strtoul(argv[1], &endp, 16);
/* endp pointing to NULL means that argv[1] was just a
* valid number, pass it along to the normal bootm processing
*
* If endp is ':' or '#' assume a FIT identifier so pass
* along for normal processing.
*
* Right now we assume the first arg should never be '-'
*/
if ((*endp != 0) && (*endp != ':') && (*endp != '#'))//是否有子命令。一般不会有,所以这个路径不会执行。
return do_bootm_subcommand(cmdtp, flag, argc, argv);
}
if (bootm_start(cmdtp, flag, argc, argv))//这个函数执行成功返回0,失败返回1。这个函数主要用于获取镜像的信息并存入images。
return 1;
/*
* We have reached the point of no return: we are going to
* overwrite all exception vector code, so we cannot easily
* recover from any failures any more...
*/
iflag = disable_interrupts();
#ifdef CONFIG_NETCONSOLE
/* Stop the ethernet stack if NetConsole could have left it up */
eth_halt();
#endif
#if defined(CONFIG_CMD_USB)
/*
* turn off USB to prevent the host controller from writing to the
* SDRAM while Linux is booting. This could happen (at least for OHCI
* controller), because the HCCA (Host Controller Communication Area)
* lies within the SDRAM and the host controller writes continously to
* this area (as busmaster!). The HccaFrameNumber is for example
* updated every 1 ms within the HCCA structure in SDRAM! For more
* details see the OpenHCI specification.
*/
usb_stop();
#endif
ret = bootm_load_os(images.os, &load_end, 1);////将镜像的数据从images.os.image_start复制到images.os.load 打印:Loading Kernel Image ...
if (ret < 0) {//上个函数调用失败才会进入这个路径
if (ret == BOOTM_ERR_RESET)
do_reset(cmdtp, flag, argc, argv);
if (ret == BOOTM_ERR_OVERLAP) {
if (images.legacy_hdr_valid) {
image_header_t *hdr;
hdr = &images.legacy_hdr_os_copy;
if (image_get_type(hdr) == 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");
bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
do_reset(cmdtp, flag, argc, argv);
}
}
if (ret == BOOTM_ERR_UNIMPLEMENTED) {
if (iflag)
enable_interrupts();
bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
return 1;
}
}
lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
if (images.os.type == IH_TYPE_STANDALONE) {//处理单独的程序镜像。显然引导内核时不会进入这个路径。
if (iflag)
enable_interrupts();
/* This may return when 'autostart' is 'no' */
bootm_start_standalone(iflag, argc, argv);
return 0;
}
bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS);
#ifdef CONFIG_SILENT_CONSOLE
if (images.os.os == IH_OS_LINUX)
fixup_silent_linux();
#endif
boot_fn = boot_os[images.os.os];//根据操作系统的类型获取引导操作系统的函数
if (boot_fn == NULL) {
if (iflag)
enable_interrupts();
printf("ERROR: booting os '%s' (%d) is not supported\n",
genimg_get_os_name(images.os.os), images.os.os);
bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
return 1;
}
arch_preboot_os();//禁用中断,重设中断向量
boot_fn(0, argc, argv, &images);//调用do_bootm_linux
bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
#ifdef DEBUG
puts("\n## Control returned to monitor - resetting...\n");
#endif
do_reset(cmdtp, flag, argc, argv);
return 1;
}
do_bootm()函数分析
最新推荐文章于 2021-11-14 20:35:12 发布