static void image_print_type(const image_header_t *hdr) { const char *os, *arch, *type, *comp; os = genimg_get_os_name(image_get_os(hdr)); arch = genimg_get_arch_name(image_get_arch(hdr)); type = genimg_get_type_name(image_get_type(hdr)); comp = genimg_get_comp_name(image_get_comp(hdr)); printf("%s %s %s (%s)\n", arch, os, type, comp); }
/** * fit_image_print - prints out the FIT component image details * @fit: pointer to the FIT format image header * @image_noffset: offset of the component image node * @p: pointer to prefix string * * fit_image_print() lists all mandatory properies for the processed component * image. If present, hash nodes are printed out as well. Load * address for images of type firmware is also printed out. Since the load * address is not mandatory for firmware images, it will be output as * "unavailable" when not present. * * returns: * no returned results */ void fit_image_print(const void *fit, int image_noffset, const char *p) { char *desc; uint8_t type, arch, os, comp; size_t size; ulong load, entry; const void *data; int noffset; int ndepth; int ret; /* Mandatory properties */ ret = fit_get_desc(fit, image_noffset, &desc); printf("%s Description: ", p); if (ret) printf("unavailable\n"); else printf("%s\n", desc); fit_image_get_type(fit, image_noffset, &type); printf("%s Type: %s\n", p, genimg_get_type_name(type)); fit_image_get_comp(fit, image_noffset, &comp); printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); ret = fit_image_get_data(fit, image_noffset, &data, &size); #ifndef USE_HOSTCC printf("%s Data Start: ", p); if (ret) { printf("unavailable\n"); } else { void *vdata = (void *)data; printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); } #endif printf("%s Data Size: ", p); if (ret) printf("unavailable\n"); else genimg_print_size(size); /* Remaining, type dependent properties */ if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_FLATDT)) { fit_image_get_arch(fit, image_noffset, &arch); printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { fit_image_get_os(fit, image_noffset, &os); printf("%s OS: %s\n", p, genimg_get_os_name(os)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) printf("unavailable\n"); else printf("0x%08lx\n", load); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK)) { fit_image_get_entry(fit, image_noffset, &entry); printf("%s Entry Point: ", p); if (ret) printf("unavailable\n"); else printf("0x%08lx\n", entry); } /* Process all hash subnodes of the component image node */ for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { if (ndepth == 1) { /* Direct child node of the component image node */ fit_image_print_verification_data(fit, noffset, p); } } }
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong iflag; ulong load_end = 0; int ret; boot_os_fn *boot_fn; /* relocate boot function table */ if (!relocated) { int i; for (i = 0; i < ARRAY_SIZE(boot_os); i++) if (boot_os[i] != NULL) boot_os[i] += gd->reloc_off; relocated = 1; } /* 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)) 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(); #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 #ifdef CONFIG_AMIGAONEG3SE /* * We've possible left the caches enabled during * bios emulation, so turn them off again */ icache_disable(); dcache_disable(); #endif ret = bootm_load_os(images.os, &load_end, 1); if (ret < 0) { if (ret == BOOTM_ERR_RESET) do_reset (cmdtp, flag, argc, argv); if (ret == BOOTM_ERR_OVERLAP) { 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); } } if (ret == BOOTM_ERR_UNIMPLEMENTED) { if (iflag) enable_interrupts(); show_boot_progress (-7); 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; } show_boot_progress (8); #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); show_boot_progress (-8); return 1; } boot_fn(0, argc, argv, &images); show_boot_progress (-9); #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); #endif do_reset (cmdtp, flag, argc, argv); return 1; }
int fit_image_load(bootm_headers_t *images, ulong addr, const char **fit_unamep, const char **fit_uname_configp, int arch, int image_type, int bootstage_id, enum fit_load_op load_op, ulong *datap, ulong *lenp) { int cfg_noffset, noffset; const char *fit_uname; const char *fit_uname_config; const void *fit; const void *buf; size_t size; int type_ok, os_ok; ulong load, data, len; uint8_t os; const char *prop_name; int ret; fit = map_sysmem(addr, 0); fit_uname = fit_unamep ? *fit_unamep : NULL; fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; prop_name = fit_get_image_type_property(image_type); printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); if (!fit_check_format(fit)) { printf("Bad FIT %s image format!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); return -ENOEXEC; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); if (fit_uname) { /* get FIT component image node offset */ bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); noffset = fit_image_get_node(fit, fit_uname); } else { /* * no image node unit name, try to get config * node first. If config unit node name is NULL * fit_conf_get_node() will try to find default config node */ bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); } else { cfg_noffset = fit_conf_get_node(fit, fit_uname_config); } if (cfg_noffset < 0) { puts("Could not find configuration node\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); return -ENOENT; } fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); printf(" Using '%s' configuration\n", fit_uname_config); if (image_type == IH_TYPE_KERNEL) { /* Remember (and possibly verify) this config */ images->fit_uname_cfg = fit_uname_config; if (IMAGE_ENABLE_VERIFY && images->verify) { puts(" Verifying Hash Integrity ... "); if (fit_config_verify(fit, cfg_noffset)) { puts("Bad Data Hash\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); return -EACCES; } puts("OK\n"); } bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); } noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name); fit_uname = fit_get_name(fit, noffset, NULL); } if (noffset < 0) { puts("Could not find subimage node\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); return -ENOENT; } printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); ret = fit_image_select(fit, noffset, images->verify); if (ret) { bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); return ret; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); #if !defined(USE_HOSTCC) && !defined(CONFIG_SANDBOX) if (!fit_image_check_target_arch(fit, noffset)) { puts("Unsupported Architecture\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); return -ENOEXEC; } #endif if (image_type == IH_TYPE_FLATDT && !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { puts("FDT image is compressed"); return -EPROTONOSUPPORT; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); type_ok = fit_image_check_type(fit, noffset, image_type) || (image_type == IH_TYPE_KERNEL && fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); os_ok = image_type == IH_TYPE_FLATDT || fit_image_check_os(fit, noffset, IH_OS_LINUX) || fit_image_check_os(fit, noffset, IH_OS_OPENRTOS); /* * If either of the checks fail, we should report an error, but * if the image type is coming from the "loadables" field, we * don't care what it is */ if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) { fit_image_get_os(fit, noffset, &os); printf("No %s %s %s Image\n", genimg_get_os_name(os), genimg_get_arch_name(arch), genimg_get_type_name(image_type)); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); return -EIO; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); /* get image data address and length */ if (fit_image_get_data(fit, noffset, &buf, &size)) { printf("Could not find %s subimage data!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); return -ENOENT; } len = (ulong)size; /* verify that image data is a proper FDT blob */ if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) { puts("Subimage data is not a FDT"); return -ENOEXEC; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); /* * Work-around for eldk-4.2 which gives this warning if we try to * cast in the unmap_sysmem() call: * warning: initialization discards qualifiers from pointer target type */ { void *vbuf = (void *)buf; data = map_to_sysmem(vbuf); } if (load_op == FIT_LOAD_IGNORED) { /* Don't load */ } else if (fit_image_get_load(fit, noffset, &load)) { if (load_op == FIT_LOAD_REQUIRED) { printf("Can't get %s subimage load address!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); return -EBADF; } } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) { ulong image_start, image_end; ulong load_end; void *dst; /* * move image data to the load address, * make sure we don't overwrite initial image */ image_start = addr; image_end = addr + fit_get_size(fit); load_end = load + len; if (image_type != IH_TYPE_KERNEL && load < image_end && load_end > image_start) { printf("Error: %s overwritten\n", prop_name); return -EXDEV; } printf(" Loading %s from 0x%08lx to 0x%08lx\n", prop_name, data, load); dst = map_sysmem(load, len); memmove(dst, buf, len); data = load; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); *datap = data; *lenp = len; if (fit_unamep) *fit_unamep = (char *)fit_uname; if (fit_uname_configp) *fit_uname_configp = (char *)fit_uname_config; return noffset; }
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)) 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); 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); #if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) 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); 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; }
/** * Execute selected states of the bootm command. * * Note the arguments to this state must be the first argument, Any 'bootm' * or sub-command arguments must have already been taken. * * Note that if states contains more than one flag it MUST contain * BOOTM_STATE_START, since this handles and consumes the command line args. * * Also note that aside from boot_os_fn functions and bootm_load_os no other * functions we store the return value of in 'ret' may use a negative return * value, without special handling. * * @param cmdtp Pointer to bootm command table entry * @param flag Command flags (CMD_FLAG_...) * @param argc Number of subcommand arguments (0 = no arguments) * @param argv Arguments * @param states Mask containing states to run (BOOTM_STATE_...) * @param images Image header information * @param boot_progress 1 to show boot progress, 0 to not do this * @return 0 if ok, something else on error. Some errors will cause this * function to perform a reboot! If states contains BOOTM_STATE_OS_GO * then the intent is to boot an OS, so this function will not return * unless the image type is standalone. */ static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int states, bootm_headers_t *images, int boot_progress) { boot_os_fn *boot_fn; ulong iflag = 0; int ret = 0, need_boot_fn; images->state |= states; /* * Work through the states and see how far we get. We stop on * any error. */ if (states & BOOTM_STATE_START) ret = bootm_start(cmdtp, flag, argc, argv); if (!ret && (states & BOOTM_STATE_FINDOS)) ret = bootm_find_os(cmdtp, flag, argc, argv); if (!ret && (states & BOOTM_STATE_FINDOTHER)) { ret = bootm_find_other(cmdtp, flag, argc, argv); argc = 0; /* consume the args */ } /* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) { ulong load_end; iflag = bootm_disable_interrupts(); ret = bootm_load_os(images, &load_end, 0); if (ret == 0) lmb_reserve(&images->lmb, images->os.load, (load_end - images->os.load)); else if (ret && ret != BOOTM_ERR_OVERLAP) goto err; else if (ret == BOOTM_ERR_OVERLAP) ret = 0; #if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) if (images->os.os == IH_OS_LINUX) fixup_silent_linux(); #endif } /* Relocate the ramdisk */ #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH if (!ret && (states & BOOTM_STATE_RAMDISK)) { ulong rd_len = images->rd_end - images->rd_start; ret = boot_ramdisk_high(&images->lmb, images->rd_start, rd_len, &images->initrd_start, &images->initrd_end); if (!ret) { setenv_hex("initrd_start", images->initrd_start); setenv_hex("initrd_end", images->initrd_end); } } #endif #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB) if (!ret && (states & 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 = boot_os[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); return 1; } /* Call various other states that are not generally used */ if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_PREP)) ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images); #ifdef CONFIG_TRACE /* Pretend to run the OS, then run a user command */ if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) { char *cmd_list = getenv("fakegocmd"); ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO, images, boot_fn); if (!ret && cmd_list) ret = run_command_list(cmd_list, -1, flag); } #endif /* Check for unsupported subcommand. */ if (ret) { puts("subcommand not supported\n"); return ret; } /* Now run the OS! We hope this doesn't return */ if (!ret && (states & BOOTM_STATE_OS_GO)) ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO, images, boot_fn); /* Deal with any fallout */ err: if (iflag) enable_interrupts(); if (ret == BOOTM_ERR_UNIMPLEMENTED) bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); else if (ret == BOOTM_ERR_RESET) do_reset(cmdtp, flag, argc, argv); return ret; }
int spl_load_simple_fit(struct spl_image_info *spl_image, struct spl_load_info *info, ulong sector, void *fit) { int sectors; ulong size; unsigned long count; struct spl_image_info image_info; int node = -1; int images, ret; int base_offset, align_len = ARCH_DMA_MINALIGN - 1; int index = 0; /* * For FIT with external data, figure out where the external images * start. This is the base for the data-offset properties in each * image. */ size = fdt_totalsize(fit); size = (size + 3) & ~3; base_offset = (size + 3) & ~3; /* * So far we only have one block of data from the FIT. Read the entire * thing, including that first block, placing it so it finishes before * where we will load the image. * * Note that we will load the image such that its first byte will be * at the load address. Since that byte may be part-way through a * block, we may load the image up to one block before the load * address. So take account of that here by subtracting an addition * block length from the FIT start position. * * In fact the FIT has its own load address, but we assume it cannot * be before CONFIG_SYS_TEXT_BASE. * * For FIT with data embedded, data is loaded as part of FIT image. * For FIT with external data, data is not loaded in this step. */ fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len - align_len) & ~align_len); sectors = get_aligned_image_size(info, size, 0); count = info->read(info, sector, sectors, fit); debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n", sector, sectors, fit, count); if (count == 0) return -EIO; /* find the node holding the images information */ images = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images < 0) { debug("%s: Cannot find /images node: %d\n", __func__, images); return -1; } /* * Find the U-Boot image using the following search order: * - start at 'firmware' (e.g. an ARM Trusted Firmware) * - fall back 'kernel' (e.g. a Falcon-mode OS boot * - fall back to using the first 'loadables' entry */ if (node < 0) node = spl_fit_get_image_node(fit, images, "firmware", 0); #ifdef CONFIG_SPL_OS_BOOT if (node < 0) node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0); #endif if (node < 0) { debug("could not find firmware image, trying loadables...\n"); node = spl_fit_get_image_node(fit, images, "loadables", 0); /* * If we pick the U-Boot image from "loadables", start at * the second image when later loading additional images. */ index = 1; } if (node < 0) { debug("%s: Cannot find u-boot image node: %d\n", __func__, node); return -1; } /* Load the image and set up the spl_image structure */ ret = spl_load_fit_image(info, sector, fit, base_offset, node, spl_image); if (ret) return ret; /* * For backward compatibility, we treat the first node that is * as a U-Boot image, if no OS-type has been declared. */ if (!spl_fit_image_get_os(fit, node, &spl_image->os)) debug("Image OS is %s\n", genimg_get_os_name(spl_image->os)); #if !defined(CONFIG_SPL_OS_BOOT) else spl_image->os = IH_OS_U_BOOT; #endif /* * Booting a next-stage U-Boot may require us to append the FDT. * We allow this to fail, as the U-Boot image might embed its FDT. */ if (spl_image->os == IH_OS_U_BOOT) spl_fit_append_fdt(spl_image, info, sector, fit, images, base_offset); /* Now check if there are more images for us to load */ for (; ; index++) { uint8_t os_type = IH_OS_INVALID; node = spl_fit_get_image_node(fit, images, "loadables", index); if (node < 0) break; ret = spl_load_fit_image(info, sector, fit, base_offset, node, &image_info); if (ret < 0) continue; if (!spl_fit_image_get_os(fit, node, &os_type)) debug("Loadable is %s\n", genimg_get_os_name(os_type)); if (os_type == IH_OS_U_BOOT) { spl_fit_append_fdt(&image_info, info, sector, fit, images, base_offset); spl_image->fdt_addr = image_info.fdt_addr; } /* * If the "firmware" image did not provide an entry point, * use the first valid entry point from the loadables. */ if (spl_image->entry_point == FDT_ERROR && image_info.entry_point != FDT_ERROR) spl_image->entry_point = image_info.entry_point; /* Record our loadables into the FDT */ if (spl_image->fdt_addr) spl_fit_record_loadable(fit, images, index, spl_image->fdt_addr, &image_info); } /* * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's * Makefile will set it to 0 and it will end up as the entry point * here. What it actually means is: use the load address. */ if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0) spl_image->entry_point = spl_image->load_addr; return 0; }
/** * Execute selected states of the bootm command. * * Note the arguments to this state must be the first argument, Any 'bootm' * or sub-command arguments must have already been taken. * * Note that if states contains more than one flag it MUST contain * BOOTM_STATE_START, since this handles and consumes the command line args. * * Also note that aside from boot_os_fn functions and bootm_load_os no other * functions we store the return value of in 'ret' may use a negative return * value, without special handling. * * @param cmdtp Pointer to bootm command table entry * @param flag Command flags (CMD_FLAG_...) * @param argc Number of subcommand arguments (0 = no arguments) * @param argv Arguments * @param states Mask containing states to run (BOOTM_STATE_...) * @param images Image header information * @param boot_progress 1 to show boot progress, 0 to not do this * @return 0 if ok, something else on error. Some errors will cause this * function to perform a reboot! If states contains BOOTM_STATE_OS_GO * then the intent is to boot an OS, so this function will not return * unless the image type is standalone. */ static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int states, bootm_headers_t *images, int boot_progress) { boot_os_fn *boot_fn; ulong iflag = 0; int ret = 0; images->state |= states; /* * Work through the states and see how far we get. We stop on * any error. */ if (states & BOOTM_STATE_START) ret = bootm_start(cmdtp, flag, argc, argv); if (!ret && (states & BOOTM_STATE_FINDOS)) ret = bootm_find_os(cmdtp, flag, argc, argv); if (!ret && (states & BOOTM_STATE_FINDOTHER)) { ret = bootm_find_other(cmdtp, flag, argc, argv); argc = 0; /* consume the args */ } /* * 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 /* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) { ulong load_end; ret = bootm_load_os(images, &load_end, 0); if (ret && ret != BOOTM_ERR_OVERLAP) goto err; if (ret == 0) lmb_reserve(&images->lmb, images->os.load, (load_end - images->os.load)); else if (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; ret = boot_ramdisk_high(&images->lmb, images->rd_start, rd_len, &images->initrd_start, &images->initrd_end); if (!ret) { setenv_hex("initrd_start", images->initrd_start); setenv_hex("initrd_end", images->initrd_end); } } #endif #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB) if (!ret && (states & 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 = 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; } /* Call various other states that are not generally used */ if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_PREP)) ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images); #ifdef CONFIG_TRACE /* Pretend to run the OS, then run a user command */ if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) { char *cmd_list = getenv("fakegocmd"); ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO, images, boot_fn); if (!ret && cmd_list) ret = run_command_list(cmd_list, -1, flag); } #endif /* Now run the OS! We hope this doesn't return */ if (!ret && (states & BOOTM_STATE_OS_GO)) { ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO, images, boot_fn); if (ret) goto err; } return ret; /* Deal with any fallout */ err: if (iflag) enable_interrupts(); if (ret == BOOTM_ERR_UNIMPLEMENTED) bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); else if (ret == BOOTM_ERR_RESET) do_reset(cmdtp, flag, argc, argv); else puts("subcommand not supported\n"); return ret; }
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_SECURE_BOOT #ifndef CONFIG_SECURE_BL1_ONLY security_check(); #endif #endif char cmdbuffer[64]; sprintf(cmdbuffer,"sdfuse autocheck"); run_command(cmdbuffer, 0); exynos4412_screen_backlight(0); #ifdef CONFIG_ZIMAGE_BOOT #define LINUX_ZIMAGE_MAGIC 0x016f2818 image_header_t *hdr; ulong addr; /* find out kernel image address */ if (argc < 2) { addr = load_addr; debug ("* kernel: default image load address = 0x%08lx\n", load_addr); } else { addr = simple_strtoul(argv[1], NULL, 16); } if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) { u32 val; printf("Boot with zImage\n"); //addr = virt_to_phys(addr); hdr = (image_header_t *)addr; hdr->ih_os = IH_OS_LINUX; hdr->ih_ep = ntohl(addr); memmove (&images.legacy_hdr_os_copy, hdr, sizeof(image_header_t)); /* save pointer to image header */ images.legacy_hdr_os = hdr; images.legacy_hdr_valid = 1; goto after_header_check; } #endif #ifdef CONFIG_NEEDS_MANUAL_RELOC static int relocated = 0; /* relocate boot function table */ if (!relocated) { int i; for (i = 0; i < ARRAY_SIZE(boot_os); i++) if (boot_os[i] != NULL) boot_os[i] += 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)) 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(); #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); if (ret < 0) { if (ret == BOOTM_ERR_RESET) do_reset (cmdtp, flag, argc, argv); if (ret == BOOTM_ERR_OVERLAP) { 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); } } if (ret == BOOTM_ERR_UNIMPLEMENTED) { if (iflag) enable_interrupts(); show_boot_progress (-7); 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; } show_boot_progress (8); #if defined(CONFIG_ZIMAGE_BOOT) after_header_check: images.os.os = hdr->ih_os; images.ep = image_get_ep (&images.legacy_hdr_os_copy); #endif #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); show_boot_progress (-8); return 1; } arch_preboot_os(); boot_fn(0, argc, argv, &images); show_boot_progress (-9); #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); #endif do_reset (cmdtp, flag, argc, argv); return 1; }
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong iflag; ulong load_end = 0; int ret = 0; boot_os_fn *boot_fn; AML_LOG_INIT("cmd_bootm"); AML_LOG_TE("cmd_bootm"); #ifdef TEST_UBOOT_BOOT_SPEND_TIME bootm_start_time = get_utimer(0); #endif #ifdef CONFIG_NEEDS_MANUAL_RELOC static int relocated = 0; /* relocate boot function table */ if (!relocated) { int i; for (i = 0; i < ARRAY_SIZE(boot_os); i++) if (boot_os[i] != NULL) boot_os[i] += gd->reloc_off; relocated = 1; } #endif AML_LOG_TE("cmd_bootm"); #ifdef CONFIG_RESET_TO_SYSTEM struct aml_pmu_driver *pmu_driver = NULL; pmu_driver = aml_pmu_get_driver(); if (pmu_driver && pmu_driver->pmu_reset_flag_operation) { pmu_driver->pmu_reset_flag_operation(RESET_FLAG_SET); } #endif AML_LOG_TE("cmd_bootm"); #ifdef CONFIG_M6_SECU_BOOT #ifdef CONFIG_MESON_TRUSTZONE extern int meson_trustzone_boot_check(unsigned char *addr); ret = meson_trustzone_boot_check((unsigned char*)load_addr); #else extern int aml_decrypt_kernel_image(void* kernel_image_address); ret = aml_decrypt_kernel_image((void*)load_addr); #endif if(ret != 0) { printf("Error! Illegal kernel image, please check!\n"); return ret; } #endif //CONFIG_M6_SECU_BOOT AML_LOG_TE("cmd_bootm"); #ifdef CONFIG_AML_SECU_BOOT_V2 #ifdef CONFIG_MESON_TRUSTZONE extern int meson_trustzone_boot_check(unsigned char *addr); if(!g_nIMGReadFlag) ret = meson_trustzone_boot_check(aml_get_kernel_crypto_addr(argc < 2 ? NULL : argv[1])); #else extern int aml_sec_boot_check(unsigned char *pSRC); if(!g_nIMGReadFlag) ret = aml_sec_boot_check(aml_get_kernel_crypto_addr(argc < 2 ? NULL : argv[1])); #endif if(0 != ret) return ret; #endif //CONFIG_AML_SECU_BOOT_V2 AML_LOG_TE("cmd_bootm"); #ifdef CONFIG_AML_GATE_INIT extern void gate_init(void); gate_init(); #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); } AML_LOG_TE("cmd_bootm"); if (bootm_start(cmdtp, flag, argc, argv)) return 1; AML_LOG_TE("cmd_bootm"); /* * 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(); #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 AML_LOG_TE("cmd_bootm"); ret = bootm_load_os(images.os, &load_end, 1); AML_LOG_TE("cmd_bootm"); if (ret < 0) { if (ret == BOOTM_ERR_RESET) do_reset (cmdtp, flag, argc, argv); if (ret == BOOTM_ERR_OVERLAP) { 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); } } if (ret == BOOTM_ERR_UNIMPLEMENTED) { if (iflag) enable_interrupts(); show_boot_progress (-7); return 1; } } AML_LOG_TE("cmd_bootm"); lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load)); AML_LOG_TE("cmd_bootm"); 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; } show_boot_progress (8); #if defined(CONFIG_SILENT_CONSOLE) && \ (defined(CONFIG_SILENT_CONSOLE_LINUX_QUIET) || defined(CONFIG_DEPRECATED_SILENT_LINUX_CONSOLE)) if (images.os.os == IH_OS_LINUX) fixup_silent_linux(); #endif AML_LOG_TE("cmd_bootm"); #ifdef CONFIG_AUTO_SET_BOOTARGS_MEM mem_size_arg_process(); #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); show_boot_progress (-8); return 1; } AML_LOG_TE("cmd_bootm"); arch_preboot_os(); #ifdef TEST_UBOOT_BOOT_SPEND_TIME { int boot_kernel_start; boot_kernel_start = get_utimer(0); printf("bootm start to prepare boot kernel time:%dus\n",boot_kernel_start-bootm_start_time); printf("from main_loop start to kernel decompress finished time:%dus\n",boot_kernel_start-main_loop_start); } #endif ulong temp_img_addr; AML_LOG_TE("cmd_bootm"); /* use fprintf to always show this print even if console is silenced with GD_FLG_SILENT */ fprintf(stderr, "uboot time: %d us.\n", get_utimer(0)); boot_fn(0, argc, argv, &images); show_boot_progress (-9); #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); #endif do_reset (cmdtp, flag, argc, argv); return 1; }