/* * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>() routines. */ structbootm_headers { /* * Legacy os image header, if it is a multi component image * then boot_get_ramdisk() and get_fdt() will attempt to get * data from second and third component accordingly. */ structlegacy_img_hdr *legacy_hdr_os;/* image header pointer */ structlegacy_img_hdrlegacy_hdr_os_copy;/* header copy */ ulong legacy_hdr_valid;
/* * The fit_ members are only used with FIT, but it involves a lot of * #ifdefs to avoid compiling that code. Since FIT is the standard * format, even for SPL, this extra data size seems worth it. */ constchar *fit_uname_cfg; /* configuration node unit name */
void *fit_hdr_os; /* os FIT image header */ constchar *fit_uname_os; /* os subimage node unit name */ int fit_noffset_os; /* os subimage node offset */
void *fit_hdr_rd; /* init ramdisk FIT image header */ constchar *fit_uname_rd; /* init ramdisk subimage node unit name */ int fit_noffset_rd; /* init ramdisk subimage node offset */
void *fit_hdr_fdt; /* FDT blob FIT image header */ constchar *fit_uname_fdt; /* FDT blob subimage node unit name */ int fit_noffset_fdt;/* FDT blob subimage node offset */
void *fit_hdr_setup; /* x86 setup FIT image header */ constchar *fit_uname_setup; /* x86 setup subimage node name */ int fit_noffset_setup;/* x86 setup subimage node offset */
#ifndef USE_HOSTCC structimage_infoos;/* os image info */ ulong ep; /* entry point of OS */
ulong rd_start, rd_end;/* ramdisk start/end */
char *ft_addr; /* flat dev tree address */ ulong ft_len; /* length of flat device tree */
intdo_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { structbootm_infobmi; int states; int ret;
/* Consume 'booti' */ argc--; argv++;
bootm_init(&bmi); //初始化bmi结构体,设置为空 if (argc) bmi.addr_img = argv[0]; if (argc > 1) bmi.conf_ramdisk = argv[1]; if (argc > 2) bmi.conf_fdt = argv[2]; bmi.boot_progress = true; bmi.cmd_name = "booti"; /* do not set up argc and argv[] since nothing uses them */
if (booti_start(&bmi)) //booti_start运行成功,返回0 return1;
/* * We are doing the BOOTM_STATE_LOADOS state ourselves, so must * disable interrupts ourselves */ bootm_disable_interrupts();
states = BOOTM_STATE_MEASURE | BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO; if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH)) states |= BOOTM_STATE_RAMDISK;
/* * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not * have a header that provide this informaiton. */ if (bootm_find_images(image_load_addr, bmi->conf_ramdisk, bmi->conf_fdt, relocated_addr, image_size)) //加载image、ramdisk、fdt,如果加载成功,返回0 return1;
if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret && (states & BOOTM_STATE_MEASURE)) bootm_measure(images);
/* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) { iflag = bootm_disable_interrupts(); //加载image镜像,由于之前已经加载过了,因此没有设置BOOTM_STATE_LOADOS,不会执行到这一步 ret = bootm_load_os(images, 0); if (ret && ret != BOOTM_ERR_OVERLAP) goto err; elseif (ret == BOOTM_ERR_OVERLAP) ret = 0; }
/* Relocate the ramdisk */ #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH if (!ret && (states & BOOTM_STATE_RAMDISK)) { ulong rd_len = images->rd_end - images->rd_start; //加载ramdisk,由于之前已经加载过了,因此没有设置BOOTM_STATE_RAMDISK,不会执行到这一步 ret = boot_ramdisk_high(&images->lmb, images->rd_start, rd_len, &images->initrd_start, &images->initrd_end); if (!ret) { env_set_hex("initrd_start", images->initrd_start); env_set_hex("initrd_end", images->initrd_end); } } #endif #if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB) if (!ret && (states & BOOTM_STATE_FDT)) { //加载设备树,由于之前已经加载过了,因此没有设置BOOTM_STATE_FDT,不会执行到这一步 boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr); ret = boot_relocate_fdt(&images->lmb, &images->ft_addr, &images->ft_len); } #endif
/* From now on, we need the OS boot function */ if (ret) return ret; boot_fn = bootm_os_get_boot_func(images->os.os); need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE | BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO); if (boot_fn == NULL && need_boot_fn) { 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); return1; }
/* Call various other states that are not generally used */ if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) ret = boot_fn(BOOTM_STATE_OS_CMDLINE, bmi); if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, bmi); if (!ret && (states & BOOTM_STATE_OS_PREP)) { int flags = 0; /* For Linux OS do all substitutions at console processing */ if (images->os.os == IH_OS_LINUX) flags = BOOTM_CL_ALL; ret = bootm_process_cmdline_env(flags); if (ret) { printf("Cmdline setup failed (err=%d)\n", ret); ret = CMD_RET_FAILURE; goto err; } ret = boot_fn(BOOTM_STATE_OS_PREP, bmi); }
#ifdef CONFIG_TRACE /* Pretend to run the OS, then run a user command */ if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) { char *cmd_list = env_get("fakegocmd");
ret = boot_selected_os(BOOTM_STATE_OS_FAKE_GO, bmi, boot_fn); if (!ret && cmd_list) ret = run_command_list(cmd_list, -1, 0); } #endif
/* Check for unsupported subcommand. */ if (ret) { printf("subcommand failed (err=%d)\n", ret); return ret; }
/* Now run the OS! We hope this doesn't return */ if (!ret && (states & BOOTM_STATE_OS_GO)) //启动系统 ret = boot_selected_os(BOOTM_STATE_OS_GO, bmi, boot_fn);
/* Deal with any fallout */ err: if (iflag) enable_interrupts();
if (ret == BOOTM_ERR_UNIMPLEMENTED) { bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); } elseif (ret == BOOTM_ERR_RESET) { printf("Resetting the board...\n"); reset_cpu(); }
/* Stand-alone may return when 'autostart' is 'no' */ if (bmi->images->os.type == IH_TYPE_STANDALONE || IS_ENABLED(CONFIG_SANDBOX) || state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */ return0; bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED); debug("\n## Control returned to monitor - resetting...\n");
if (CONFIG_IS_ENABLED(OF_LIBFDT) && IS_ENABLED(CONFIG_LMB) && images->ft_len) { debug("using: FDT\n"); if (image_setup_linux(images)) { panic("FDT creation failed!"); } } elseif (BOOTM_ENABLE_TAGS) { debug("using: ATAGS\n"); setup_start_tag(gd->bd); if (BOOTM_ENABLE_SERIAL_TAG) setup_serial_tag(¶ms); if (BOOTM_ENABLE_CMDLINE_TAG) setup_commandline_tag(gd->bd, commandline); if (BOOTM_ENABLE_REVISION_TAG) setup_revision_tag(¶ms); if (BOOTM_ENABLE_MEMORY_TAGS) setup_memory_tags(gd->bd); if (BOOTM_ENABLE_INITRD_TAG) { /* * In boot_ramdisk_high(), it may relocate ramdisk to * a specified location. And set images->initrd_start & * images->initrd_end to relocated ramdisk's start/end * addresses. So use them instead of images->rd_start & * images->rd_end when possible. */ if (images->initrd_start && images->initrd_end) { setup_initrd_tag(gd->bd, images->initrd_start, images->initrd_end); } elseif (images->rd_start && images->rd_end) { setup_initrd_tag(gd->bd, images->rd_start, images->rd_end); } } setup_board_tags(¶ms); setup_end_tag(gd->bd); } else { panic("FDT and ATAGS support not compiled in\n"); }
/** * Set up the FDT to use for booting a kernel * * This performs ramdisk setup, sets up the FDT if required, and adds * paramters to the FDT if libfdt is available. * * @param images Images information * Return: 0 if ok, <0 on failure */ intimage_setup_linux(struct bootm_headers *images) { ulong of_size = images->ft_len; char **of_flat_tree = &images->ft_addr; structlmb *lmb = images_lmb(images); int ret;
/* This function cannot be called without lmb support */ if (!IS_ENABLED(CONFIG_LMB)) return -EFAULT; if (CONFIG_IS_ENABLED(OF_LIBFDT)) boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
if (IS_ENABLED(CONFIG_SYS_BOOT_GET_CMDLINE)) { ret = boot_get_cmdline(lmb, &images->cmdline_start, &images->cmdline_end); if (ret) { puts("ERROR with allocation of cmdline\n"); return ret; } }
if (CONFIG_IS_ENABLED(OF_LIBFDT)) { ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); if (ret) return ret; }
if (CONFIG_IS_ENABLED(OF_LIBFDT) && of_size) { ret = image_setup_libfdt(images, *of_flat_tree, lmb); if (ret) return ret; }
fdt_ret = optee_copy_fdt_nodes(blob); if (fdt_ret) { printf("ERROR: transfer of optee nodes to new fdt failed: %s\n", fdt_strerror(fdt_ret)); goto err; }
/* Store name of configuration node as u-boot,bootconf in /chosen node */ if (images->fit_uname_cfg) fdt_find_and_setprop(blob, "/chosen", "u-boot,bootconf", images->fit_uname_cfg, strlen(images->fit_uname_cfg) + 1, 1);
/** * board_fdt_chosen_bootargs - boards may override this function to use * alternative kernel command line arguments */ __weak char *board_fdt_chosen_bootargs(void) { return env_get("bootargs"); }
intfdt_chosen(void *fdt) { structabufbuf = {}; int nodeoffset; int err; char *str; /* used to set string properties */