int fit_conf_get_prop_node(const void *fit, int noffset, const char *prop_name) { char *uname; int len; /* get kernel image unit name from configuration kernel property */ uname = (char *)fdt_getprop(fit, noffset, prop_name, &len); if (uname == NULL) return len; return fit_image_get_node(fit, uname); }
/** * MC firmware FIT image parser checks if the image is in FIT * format, verifies integrity of the image and calculates * raw image address and size values. * Returns 0 on success and a negative errno on error. * task fail. **/ int parse_mc_firmware_fit_image(const void **raw_image_addr, size_t *raw_image_size) { int format; void *fit_hdr; int node_offset; const void *data; size_t size; const char *uname = "firmware"; /* Check if the image is in NOR flash */ #ifdef CONFIG_SYS_LS_MC_FW_IN_NOR fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR; #else #error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined" #endif /* Check if Image is in FIT format */ format = genimg_get_format(fit_hdr); if (format != IMAGE_FORMAT_FIT) { printf("fsl-mc: ERROR: Bad firmware image (not a FIT image)\n"); return -EINVAL; } if (!fit_check_format(fit_hdr)) { printf("fsl-mc: ERROR: Bad firmware image (bad FIT header)\n"); return -EINVAL; } node_offset = fit_image_get_node(fit_hdr, uname); if (node_offset < 0) { printf("fsl-mc: ERROR: Bad firmware image (missing subimage)\n"); return -ENOENT; } /* Verify MC firmware image */ if (!(fit_image_verify(fit_hdr, node_offset))) { printf("fsl-mc: ERROR: Bad firmware image (bad CRC)\n"); return -EINVAL; } /* Get address and size of raw image */ fit_image_get_data(fit_hdr, node_offset, &data, &size); *raw_image_addr = data; *raw_image_size = size; return 0; }
/** * MC firmware FIT image parser checks if the image is in FIT * format, verifies integrity of the image and calculates * raw image address and size values. * Returns 0 on success and a negative errno on error. * task fail. **/ int parse_mc_firmware_fit_image(u64 mc_fw_addr, const void **raw_image_addr, size_t *raw_image_size) { int format; void *fit_hdr; int node_offset; const void *data; size_t size; const char *uname = "firmware"; fit_hdr = (void *)mc_fw_addr; /* Check if Image is in FIT format */ format = genimg_get_format(fit_hdr); if (format != IMAGE_FORMAT_FIT) { printf("fsl-mc: ERR: Bad firmware image (not a FIT image)\n"); return -EINVAL; } if (!fit_check_format(fit_hdr)) { printf("fsl-mc: ERR: Bad firmware image (bad FIT header)\n"); return -EINVAL; } node_offset = fit_image_get_node(fit_hdr, uname); if (node_offset < 0) { printf("fsl-mc: ERR: Bad firmware image (missing subimage)\n"); return -ENOENT; } /* Verify MC firmware image */ if (!(fit_image_verify(fit_hdr, node_offset))) { printf("fsl-mc: ERR: Bad firmware image (bad CRC)\n"); return -EINVAL; } /* Get address and size of raw image */ fit_image_get_data(fit_hdr, node_offset, &data, &size); *raw_image_addr = data; *raw_image_size = size; return 0; }
int fit_image_load(bootm_headers_t *images, const char *prop_name, 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; int ret; fit = map_sysmem(addr, 0); fit_uname = fit_unamep ? *fit_unamep : NULL; fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; 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 ramdisk 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 (!fit_image_check_target_arch(fit, noffset)) { puts("Unsupported Architecture\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); return -ENOEXEC; } 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); if (!type_ok || !os_ok) { printf("No Linux %s %s Image\n", 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((char *)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 * case 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 { 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; }
/** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length * * boot_get_kernel() tries to find a kernel image, verifies its integrity * and locates kernel data. * * returns: * pointer to image header if valid image was found, plus kernel start * address and length, otherwise NULL */ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len) { image_header_t *hdr; ulong img_addr; #if defined(CONFIG_FIT) void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; const void *data; size_t len; int cfg_noffset; int os_noffset; #endif /* find out kernel image address */ if (argc < 2) { img_addr = load_addr; debug ("* kernel: default image load address = 0x%08lx\n", load_addr); #if defined(CONFIG_FIT) } else if (fit_parse_conf (argv[1], load_addr, &img_addr, &fit_uname_config)) { debug ("* kernel: config '%s' from image at 0x%08lx\n", fit_uname_config, img_addr); } else if (fit_parse_subimage (argv[1], load_addr, &img_addr, &fit_uname_kernel)) { debug ("* kernel: subimage '%s' from image at 0x%08lx\n", fit_uname_kernel, img_addr); #endif } else { img_addr = simple_strtoul(argv[1], NULL, 16); debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr); } show_boot_progress (1); /* copy from dataflash if needed */ img_addr = genimg_get_image (img_addr); /* check image type, for FIT images get FIT kernel node */ *os_data = *os_len = 0; switch (genimg_get_format ((void *)img_addr)) { case IMAGE_FORMAT_LEGACY: printf ("## Booting kernel from Legacy Image at %08lx ...\n", img_addr); hdr = image_get_kernel (img_addr, images->verify); if (!hdr) return NULL; show_boot_progress (5); /* get os_data and os_len */ switch (image_get_type (hdr)) { case IH_TYPE_KERNEL: *os_data = image_get_data (hdr); *os_len = image_get_data_size (hdr); break; case IH_TYPE_MULTI: image_multi_getimg (hdr, 0, os_data, os_len); break; case IH_TYPE_STANDALONE: if (argc >2) { hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16)); } *os_data = image_get_data (hdr); *os_len = image_get_data_size (hdr); break; default: printf ("Wrong Image Type for %s command\n", cmdtp->name); show_boot_progress (-5); return NULL; } /* * copy image header to allow for image overwrites during kernel * decompression. */ 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; show_boot_progress (6); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (void *)img_addr; printf ("## Booting kernel from FIT Image at %08lx ...\n", img_addr); if (!fit_check_format (fit_hdr)) { puts ("Bad FIT kernel image format!\n"); show_boot_progress (-100); return NULL; } show_boot_progress (100); if (!fit_uname_kernel) { /* * no kernel 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 */ show_boot_progress (101); cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); if (cfg_noffset < 0) { show_boot_progress (-101); return NULL; } /* save configuration uname provided in the first * bootm argument */ images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL); printf (" Using '%s' configuration\n", images->fit_uname_cfg); show_boot_progress (103); os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset); fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); } else { /* get kernel component image node offset */ show_boot_progress (102); os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); } if (os_noffset < 0) { show_boot_progress (-103); return NULL; } printf (" Trying '%s' kernel subimage\n", fit_uname_kernel); show_boot_progress (104); if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) return NULL; /* get kernel image data address and length */ if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) { puts ("Could not find kernel subimage data!\n"); show_boot_progress (-107); return NULL; } show_boot_progress (108); *os_len = len; *os_data = (ulong)data; images->fit_hdr_os = fit_hdr; images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset; break; #endif default: printf ("Wrong Image Format for %s command\n", cmdtp->name); show_boot_progress (-108); return NULL; } debug (" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", *os_data, *os_len, *os_len); return (void *)img_addr; }
/* command form: * fpga <op> <device number> <data addr> <datasize> * where op is 'load', 'dump', or 'info' * If there is no device number field, the fpga environment variable is used. * If there is no data addr field, the fpgadata environment variable is used. * The info command requires no data address field. */ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int op, dev = FPGA_INVALID_DEVICE; size_t data_size = 0; void *fpga_data = NULL; char *devstr = getenv("fpga"); char *datastr = getenv("fpgadata"); int rc = FPGA_FAIL; int wrong_parms = 0; #if defined(CONFIG_FIT) const char *fit_uname = NULL; ulong fit_addr; #endif #if defined(CONFIG_CMD_FPGA_LOADFS) fpga_fs_info fpga_fsinfo; fpga_fsinfo.fstype = FS_TYPE_ANY; #endif if (devstr) dev = (int) simple_strtoul(devstr, NULL, 16); if (datastr) fpga_data = (void *)simple_strtoul(datastr, NULL, 16); switch (argc) { #if defined(CONFIG_CMD_FPGA_LOADFS) case 9: fpga_fsinfo.blocksize = (unsigned int) simple_strtoul(argv[5], NULL, 16); fpga_fsinfo.interface = argv[6]; fpga_fsinfo.dev_part = argv[7]; fpga_fsinfo.filename = argv[8]; #endif case 5: /* fpga <op> <dev> <data> <datasize> */ data_size = simple_strtoul(argv[4], NULL, 16); case 4: /* fpga <op> <dev> <data> */ #if defined(CONFIG_FIT) if (fit_parse_subimage(argv[3], (ulong)fpga_data, &fit_addr, &fit_uname)) { fpga_data = (void *)fit_addr; debug("* fpga: subimage '%s' from FIT image ", fit_uname); debug("at 0x%08lx\n", fit_addr); } else #endif { fpga_data = (void *)simple_strtoul(argv[3], NULL, 16); debug("* fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); } debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data); case 3: /* fpga <op> <dev | data addr> */ dev = (int)simple_strtoul(argv[2], NULL, 16); debug("%s: device = %d\n", __func__, dev); /* FIXME - this is a really weak test */ if ((argc == 3) && (dev > fpga_count())) { /* must be buffer ptr */ debug("%s: Assuming buffer pointer in arg 3\n", __func__); #if defined(CONFIG_FIT) if (fit_parse_subimage(argv[2], (ulong)fpga_data, &fit_addr, &fit_uname)) { fpga_data = (void *)fit_addr; debug("* fpga: subimage '%s' from FIT image ", fit_uname); debug("at 0x%08lx\n", fit_addr); } else #endif { fpga_data = (void *)(uintptr_t)dev; debug("* fpga: cmdline image addr = 0x%08lx\n", (ulong)fpga_data); } debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data); dev = FPGA_INVALID_DEVICE; /* reset device num */ } case 2: /* fpga <op> */ op = (int)fpga_get_op(argv[1]); break; default: debug("%s: Too many or too few args (%d)\n", __func__, argc); op = FPGA_NONE; /* force usage display */ break; } if (dev == FPGA_INVALID_DEVICE) { puts("FPGA device not specified\n"); op = FPGA_NONE; } switch (op) { case FPGA_NONE: case FPGA_INFO: break; #if defined(CONFIG_CMD_FPGA_LOADFS) case FPGA_LOADFS: /* Blocksize can be zero */ if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || !fpga_fsinfo.filename) wrong_parms = 1; #endif case FPGA_LOAD: case FPGA_LOADP: case FPGA_LOADB: case FPGA_LOADBP: case FPGA_DUMP: if (!fpga_data || !data_size) wrong_parms = 1; break; #if defined(CONFIG_CMD_FPGA_LOADMK) case FPGA_LOADMK: if (!fpga_data) wrong_parms = 1; break; #endif } if (wrong_parms) { puts("Wrong parameters for FPGA request\n"); op = FPGA_NONE; } switch (op) { case FPGA_NONE: return CMD_RET_USAGE; case FPGA_INFO: rc = fpga_info(dev); break; case FPGA_LOAD: rc = fpga_load(dev, fpga_data, data_size, BIT_FULL); break; #if defined(CONFIG_CMD_FPGA_LOADP) case FPGA_LOADP: rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL); break; #endif case FPGA_LOADB: rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL); break; #if defined(CONFIG_CMD_FPGA_LOADBP) case FPGA_LOADBP: rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL); break; #endif #if defined(CONFIG_CMD_FPGA_LOADFS) case FPGA_LOADFS: rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); break; #endif #if defined(CONFIG_CMD_FPGA_LOADMK) case FPGA_LOADMK: switch (genimg_get_format(fpga_data)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: { image_header_t *hdr = (image_header_t *)fpga_data; ulong data; uint8_t comp; comp = image_get_comp(hdr); if (comp == IH_COMP_GZIP) { #if defined(CONFIG_GZIP) ulong image_buf = image_get_data(hdr); data = image_get_load(hdr); ulong image_size = ~0UL; if (gunzip((void *)data, ~0UL, (void *)image_buf, &image_size) != 0) { puts("GUNZIP: error\n"); return 1; } data_size = image_size; #else puts("Gunzip image is not supported\n"); return 1; #endif } else { data = (ulong)image_get_data(hdr); data_size = image_get_data_size(hdr); } rc = fpga_load(dev, (void *)data, data_size, BIT_FULL); } break; #endif #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: { const void *fit_hdr = (const void *)fpga_data; int noffset; const void *fit_data; if (fit_uname == NULL) { puts("No FIT subimage unit name\n"); return 1; } if (!fit_check_format(fit_hdr)) { puts("Bad FIT image format\n"); return 1; } /* get fpga component image node offset */ noffset = fit_image_get_node(fit_hdr, fit_uname); if (noffset < 0) { printf("Can't find '%s' FIT subimage\n", fit_uname); return 1; } /* verify integrity */ if (!fit_image_verify(fit_hdr, noffset)) { puts ("Bad Data Hash\n"); return 1; } /* get fpga subimage data address and length */ if (fit_image_get_data(fit_hdr, noffset, &fit_data, &data_size)) { puts("Fpga subimage data not found\n"); return 1; } rc = fpga_load(dev, fit_data, data_size, BIT_FULL); } break; #endif default: puts("** Unknown image type\n"); rc = FPGA_FAIL; break; } break; #endif case FPGA_DUMP: rc = fpga_dump(dev, fpga_data, data_size); break; default: printf("Unknown operation\n"); return CMD_RET_USAGE; } return rc; }
int source (ulong addr, const char *fit_uname) { ulong len; #if defined(CONFIG_IMAGE_FORMAT_LEGACY) const image_header_t *hdr; #endif ulong *data; int verify; void *buf; #if defined(CONFIG_FIT) const void* fit_hdr; int noffset; const void *fit_data; size_t fit_len; #endif verify = getenv_yesno ("verify"); buf = map_sysmem(addr, 0); switch (genimg_get_format(buf)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: hdr = buf; if (!image_check_magic (hdr)) { puts ("Bad magic number\n"); return 1; } if (!image_check_hcrc (hdr)) { puts ("Bad header crc\n"); return 1; } if (verify) { if (!image_check_dcrc (hdr)) { puts ("Bad data crc\n"); return 1; } } if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { puts ("Bad image type\n"); return 1; } /* get length of script */ data = (ulong *)image_get_data (hdr); if ((len = uimage_to_cpu (*data)) == 0) { puts ("Empty Script\n"); return 1; } /* * scripts are just multi-image files with one component, seek * past the zero-terminated sequence of image lengths to get * to the actual image data */ while (*data++); break; #endif #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: if (fit_uname == NULL) { puts ("No FIT subimage unit name\n"); return 1; } fit_hdr = buf; if (!fit_check_format (fit_hdr)) { puts ("Bad FIT image format\n"); return 1; } /* get script component image node offset */ noffset = fit_image_get_node (fit_hdr, fit_uname); if (noffset < 0) { printf ("Can't find '%s' FIT subimage\n", fit_uname); return 1; } if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { puts ("Not a image image\n"); return 1; } /* verify integrity */ if (verify) { if (!fit_image_verify(fit_hdr, noffset)) { puts ("Bad Data Hash\n"); return 1; } } /* get script subimage data address and length */ if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { puts ("Could not find script subimage data\n"); return 1; } data = (ulong *)fit_data; len = (ulong)fit_len; break; #endif default: puts ("Wrong image format for \"source\" command\n"); return 1; } debug ("** Script length: %ld\n", len); return run_command_list((char *)data, len, 0); }
/** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length * * boot_get_kernel() tries to find a kernel image, verifies its integrity * and locates kernel data. * * returns: * pointer to image header if valid image was found, plus kernel start * address and length, otherwise NULL */ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len) { image_header_t *hdr; ulong img_addr; const void *buf; #if defined(CONFIG_FIT) const void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; const void *data; size_t len; int cfg_noffset; int os_noffset; #endif /* find out kernel image address */ if (argc < 2) { img_addr = load_addr; debug("* kernel: default image load address = 0x%08lx\n", load_addr); #if defined(CONFIG_FIT) } else if (fit_parse_conf(argv[1], load_addr, &img_addr, &fit_uname_config)) { debug("* kernel: config '%s' from image at 0x%08lx\n", fit_uname_config, img_addr); } else if (fit_parse_subimage(argv[1], load_addr, &img_addr, &fit_uname_kernel)) { debug("* kernel: subimage '%s' from image at 0x%08lx\n", fit_uname_kernel, img_addr); #endif } else { img_addr = simple_strtoul(argv[1], NULL, 16); debug("* kernel: cmdline image address = 0x%08lx\n", img_addr); } bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC); /* copy from dataflash if needed */ img_addr = genimg_get_image(img_addr); /* check image type, for FIT images get FIT kernel node */ *os_data = *os_len = 0; buf = map_sysmem(img_addr, 0); switch (genimg_get_format(buf)) { case IMAGE_FORMAT_LEGACY: printf("## Booting kernel from Legacy Image at %08lx ...\n", img_addr); hdr = image_get_kernel(img_addr, images->verify); if (!hdr) return NULL; bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE); /* get os_data and os_len */ switch (image_get_type(hdr)) { case IH_TYPE_KERNEL: case IH_TYPE_KERNEL_NOLOAD: *os_data = image_get_data(hdr); *os_len = image_get_data_size(hdr); break; case IH_TYPE_MULTI: image_multi_getimg(hdr, 0, os_data, os_len); break; case IH_TYPE_STANDALONE: *os_data = image_get_data(hdr); *os_len = image_get_data_size(hdr); break; default: printf("Wrong Image Type for %s command\n", cmdtp->name); bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE); return NULL; } /* * copy image header to allow for image overwrites during * kernel decompression. */ 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; bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = buf; printf("## Booting kernel from FIT Image at %08lx ...\n", img_addr); if (!fit_check_format(fit_hdr)) { puts("Bad FIT kernel image format!\n"); bootstage_error(BOOTSTAGE_ID_FIT_FORMAT); return NULL; } bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT); if (!fit_uname_kernel) { /* * no kernel 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_FIT_NO_UNIT_NAME); #ifdef CONFIG_FIT_BEST_MATCH if (fit_uname_config) cfg_noffset = fit_conf_get_node(fit_hdr, fit_uname_config); else cfg_noffset = fit_conf_find_compat(fit_hdr, gd->fdt_blob); #else cfg_noffset = fit_conf_get_node(fit_hdr, fit_uname_config); #endif if (cfg_noffset < 0) { bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); return NULL; } /* save configuration uname provided in the first * bootm argument */ images->fit_uname_cfg = fdt_get_name(fit_hdr, cfg_noffset, NULL); printf(" Using '%s' configuration\n", images->fit_uname_cfg); bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); os_noffset = fit_conf_get_kernel_node(fit_hdr, cfg_noffset); fit_uname_kernel = fit_get_name(fit_hdr, os_noffset, NULL); } else { /* get kernel component image node offset */ bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME); os_noffset = fit_image_get_node(fit_hdr, fit_uname_kernel); } if (os_noffset < 0) { bootstage_error(BOOTSTAGE_ID_FIT_CONFIG); return NULL; } printf(" Trying '%s' kernel subimage\n", fit_uname_kernel); bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE); if (!fit_check_kernel(fit_hdr, os_noffset, images->verify)) return NULL; /* get kernel image data address and length */ if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) { puts("Could not find kernel subimage data!\n"); bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR); return NULL; } bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO); *os_len = len; *os_data = (ulong)data; images->fit_hdr_os = (void *)fit_hdr; images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset; break; #endif default: printf("Wrong Image Format for %s command\n", cmdtp->name); bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO); return NULL; } debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", *os_data, *os_len, *os_len); return buf; }
int autoscript (ulong addr, const char *fit_uname) { ulong len; image_header_t *hdr; ulong *data; char *cmd; int rcode = 0; int verify; #if defined(CONFIG_FIT) const void* fit_hdr; int noffset; const void *fit_data; size_t fit_len; #endif verify = getenv_yesno ("verify"); switch (genimg_get_format ((void *)addr)) { case IMAGE_FORMAT_LEGACY: hdr = (image_header_t *)addr; if (!image_check_magic (hdr)) { puts ("Bad magic number\n"); return 1; } if (!image_check_hcrc (hdr)) { puts ("Bad header crc\n"); return 1; } if (verify) { if (!image_check_dcrc (hdr)) { puts ("Bad data crc\n"); return 1; } } if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { puts ("Bad image type\n"); return 1; } /* get length of script */ data = (ulong *)image_get_data (hdr); if ((len = uimage_to_cpu (*data)) == 0) { puts ("Empty Script\n"); return 1; } /* * scripts are just multi-image files with one component, seek * past the zero-terminated sequence of image lengths to get * to the actual image data */ while (*data++); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: if (fit_uname == NULL) { puts ("No FIT subimage unit name\n"); return 1; } fit_hdr = (const void *)addr; if (!fit_check_format (fit_hdr)) { puts ("Bad FIT image format\n"); return 1; } /* get script component image node offset */ noffset = fit_image_get_node (fit_hdr, fit_uname); if (noffset < 0) { printf ("Can't find '%s' FIT subimage\n", fit_uname); return 1; } if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { puts ("Not a image image\n"); return 1; } /* verify integrity */ if (verify) { if (!fit_image_check_hashes (fit_hdr, noffset)) { puts ("Bad Data Hash\n"); return 1; } } /* get script subimage data address and length */ if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { puts ("Could not find script subimage data\n"); return 1; } data = (ulong *)fit_data; len = (ulong)fit_len; break; #endif default: puts ("Wrong image format for autoscript\n"); return 1; } debug ("** Script length: %ld\n", len); if ((cmd = malloc (len + 1)) == NULL) { return 1; } /* make sure cmd is null terminated */ memmove (cmd, (char *)data, len); *(cmd + len) = 0; #ifdef CONFIG_SYS_HUSH_PARSER /*?? */ rcode = parse_string_outer (cmd, FLAG_PARSE_SEMICOLON); #else { char *line = cmd; char *next = cmd; /* * break into individual lines, * and execute each line; * terminate on error. */ while (*next) { if (*next == '\n') { *next = '\0'; /* run only non-empty commands */ if (*line) { debug ("** exec: \"%s\"\n", line); if (run_command (line, 0) < 0) { rcode = 1; break; } } line = next + 1; } ++next; } if (rcode == 0 && *line) rcode = (run_command(line, 0) >= 0); } #endif free (cmd); return rcode; }
/* command form: * fpga <op> <device number> <data addr> <datasize> * where op is 'load', 'dump', or 'info' * If there is no device number field, the fpga environment variable is used. * If there is no data addr field, the fpgadata environment variable is used. * The info command requires no data address field. */ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int op, dev = FPGA_INVALID_DEVICE; size_t data_size = 0; void *fpga_data = NULL; char *devstr = getenv ("fpga"); char *datastr = getenv ("fpgadata"); int rc = FPGA_FAIL; int wrong_parms = 0; #if defined (CONFIG_FIT) const char *fit_uname = NULL; ulong fit_addr; #endif if (devstr) dev = (int) simple_strtoul (devstr, NULL, 16); if (datastr) fpga_data = (void *) simple_strtoul (datastr, NULL, 16); switch (argc) { case 5: /* fpga <op> <dev> <data> <datasize> */ data_size = simple_strtoul (argv[4], NULL, 16); case 4: /* fpga <op> <dev> <data> */ #if defined(CONFIG_FIT) if (fit_parse_subimage (argv[3], (ulong)fpga_data, &fit_addr, &fit_uname)) { fpga_data = (void *)fit_addr; debug("* fpga: subimage '%s' from FIT image " "at 0x%08lx\n", fit_uname, fit_addr); } else #endif { fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); debug("* fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); } debug("%s: fpga_data = 0x%x\n", __func__, (uint) fpga_data); case 3: /* fpga <op> <dev | data addr> */ dev = (int) simple_strtoul (argv[2], NULL, 16); debug("%s: device = %d\n", __func__, dev); /* FIXME - this is a really weak test */ if ((argc == 3) && (dev > fpga_count ())) { /* must be buffer ptr */ debug("%s: Assuming buffer pointer in arg 3\n", __func__); #if defined(CONFIG_FIT) if (fit_parse_subimage (argv[2], (ulong)fpga_data, &fit_addr, &fit_uname)) { fpga_data = (void *)fit_addr; debug("* fpga: subimage '%s' from FIT image " "at 0x%08lx\n", fit_uname, fit_addr); } else #endif { fpga_data = (void *) dev; debug("* fpga: cmdline image address = " "0x%08lx\n", (ulong)fpga_data); } debug("%s: fpga_data = 0x%x\n", __func__, (uint) fpga_data); dev = FPGA_INVALID_DEVICE; /* reset device num */ } case 2: /* fpga <op> */ op = (int) fpga_get_op (argv[1]); break; default: debug("%s: Too many or too few args (%d)\n", __func__, argc); op = FPGA_NONE; /* force usage display */ break; } if (dev == FPGA_INVALID_DEVICE) { puts("FPGA device not specified\n"); op = FPGA_NONE; } switch (op) { case FPGA_NONE: case FPGA_INFO: break; case FPGA_LOAD: case FPGA_LOADB: case FPGA_DUMP: if (!fpga_data || !data_size) wrong_parms = 1; break; case FPGA_LOADMK: if (!fpga_data) wrong_parms = 1; break; } if (wrong_parms) { puts("Wrong parameters for FPGA request\n"); op = FPGA_NONE; } switch (op) { case FPGA_NONE: return CMD_RET_USAGE; case FPGA_INFO: rc = fpga_info (dev); break; case FPGA_LOAD: rc = fpga_load (dev, fpga_data, data_size); break; case FPGA_LOADB: rc = fpga_loadbitstream(dev, fpga_data, data_size); break; case FPGA_LOADMK: switch (genimg_get_format (fpga_data)) { case IMAGE_FORMAT_LEGACY: { image_header_t *hdr = (image_header_t *)fpga_data; ulong data; data = (ulong)image_get_data (hdr); data_size = image_get_data_size (hdr); rc = fpga_load (dev, (void *)data, data_size); } break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: { const void *fit_hdr = (const void *)fpga_data; int noffset; const void *fit_data; if (fit_uname == NULL) { puts ("No FIT subimage unit name\n"); return 1; } if (!fit_check_format (fit_hdr)) { puts ("Bad FIT image format\n"); return 1; } /* get fpga component image node offset */ noffset = fit_image_get_node (fit_hdr, fit_uname); if (noffset < 0) { printf ("Can't find '%s' FIT subimage\n", fit_uname); return 1; } /* verify integrity */ if (!fit_image_verify(fit_hdr, noffset)) { puts ("Bad Data Hash\n"); return 1; } /* get fpga subimage data address and length */ if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) { puts ("Could not find fpga subimage data\n"); return 1; } rc = fpga_load (dev, fit_data, data_size); } break; #endif default: puts ("** Unknown image type\n"); rc = FPGA_FAIL; break; } break; case FPGA_DUMP: rc = fpga_dump (dev, fpga_data, data_size); break; default: printf ("Unknown operation\n"); return CMD_RET_USAGE; } return (rc); }
static int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { ulong addr = load_addr; ulong dest = 0; ulong data, len; int verify; int part = 0; #if defined(CONFIG_IMAGE_FORMAT_LEGACY) ulong count; image_header_t *hdr = NULL; #endif #if defined(CONFIG_FIT) const char *uname = NULL; const void* fit_hdr; int noffset; const void *fit_data; size_t fit_len; #endif #ifdef CONFIG_GZIP uint unc_len = CONFIG_SYS_XIMG_LEN; #endif uint8_t comp; verify = env_get_yesno("verify"); if (argc > 1) { addr = simple_strtoul(argv[1], NULL, 16); } if (argc > 2) { part = simple_strtoul(argv[2], NULL, 16); #if defined(CONFIG_FIT) uname = argv[2]; #endif } if (argc > 3) { dest = simple_strtoul(argv[3], NULL, 16); } switch (genimg_get_format((void *)addr)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: printf("## Copying part %d from legacy image " "at %08lx ...\n", part, addr); hdr = (image_header_t *)addr; if (!image_check_magic(hdr)) { printf("Bad Magic Number\n"); return 1; } if (!image_check_hcrc(hdr)) { printf("Bad Header Checksum\n"); return 1; } #ifdef DEBUG image_print_contents(hdr); #endif if (!image_check_type(hdr, IH_TYPE_MULTI) && !image_check_type(hdr, IH_TYPE_SCRIPT)) { printf("Wrong Image Type for %s command\n", cmdtp->name); return 1; } comp = image_get_comp(hdr); if ((comp != IH_COMP_NONE) && (argc < 4)) { printf("Must specify load address for %s command " "with compressed image\n", cmdtp->name); return 1; } if (verify) { printf(" Verifying Checksum ... "); if (!image_check_dcrc(hdr)) { printf("Bad Data CRC\n"); return 1; } printf("OK\n"); } count = image_multi_count(hdr); if (part >= count) { printf("Bad Image Part\n"); return 1; } image_multi_getimg(hdr, part, &data, &len); break; #endif #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: if (uname == NULL) { puts("No FIT subimage unit name\n"); return 1; } printf("## Copying '%s' subimage from FIT image " "at %08lx ...\n", uname, addr); fit_hdr = (const void *)addr; if (!fit_check_format(fit_hdr)) { puts("Bad FIT image format\n"); return 1; } /* get subimage node offset */ noffset = fit_image_get_node(fit_hdr, uname); if (noffset < 0) { printf("Can't find '%s' FIT subimage\n", uname); return 1; } if (!fit_image_check_comp(fit_hdr, noffset, IH_COMP_NONE) && (argc < 4)) { printf("Must specify load address for %s command " "with compressed image\n", cmdtp->name); return 1; } /* verify integrity */ if (verify) { if (!fit_image_verify(fit_hdr, noffset)) { puts("Bad Data Hash\n"); return 1; } } /* get subimage/external data address and length */ if (fit_image_get_data_and_size(fit_hdr, noffset, &fit_data, &fit_len)) { puts("Could not find script subimage data\n"); return 1; } if (fit_image_get_comp(fit_hdr, noffset, &comp)) { puts("Could not find script subimage " "compression type\n"); return 1; } data = (ulong)fit_data; len = (ulong)fit_len; break; #endif default: puts("Invalid image type for imxtract\n"); return 1; } if (argc > 3) { switch (comp) { case IH_COMP_NONE: #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) { size_t l = len; size_t tail; void *to = (void *) dest; void *from = (void *)data; printf(" Loading part %d ... ", part); while (l > 0) { tail = (l > CHUNKSZ) ? CHUNKSZ : l; WATCHDOG_RESET(); memmove(to, from, tail); to += tail; from += tail; l -= tail; } } #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ printf(" Loading part %d ... ", part); memmove((char *) dest, (char *)data, len); #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ break; #ifdef CONFIG_GZIP case IH_COMP_GZIP: printf(" Uncompressing part %d ... ", part); if (gunzip((void *) dest, unc_len, (uchar *) data, &len) != 0) { puts("GUNZIP ERROR - image not loaded\n"); return 1; } break; #endif #if defined(CONFIG_BZIP2) && defined(CONFIG_IMAGE_FORMAT_LEGACY) case IH_COMP_BZIP2: { int i; printf(" Uncompressing part %d ... ", part); /* * If we've got less than 4 MB of malloc() * space, use slower decompression algorithm * which requires at most 2300 KB of memory. */ i = BZ2_bzBuffToBuffDecompress( map_sysmem(ntohl(hdr->ih_load), 0), &unc_len, (char *)data, len, CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf("BUNZIP2 ERROR %d - " "image not loaded\n", i); return 1; } } break; #endif /* CONFIG_BZIP2 */ default: printf("Unimplemented compression type %d\n", comp); return 1; } puts("OK\n"); } flush_cache(dest, ALIGN(len, ARCH_DMA_MINALIGN)); env_set_hex("fileaddr", data); env_set_hex("filesize", len); return 0; }
int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, const ulong *ld_start, ulong * const ld_len) { /* * These variables are used to hold the current image location * in system memory. */ ulong tmp_img_addr; /* * These two variables are requirements for fit_image_load, but * their values are not used */ ulong img_data, img_len; void *buf; int loadables_index; int conf_noffset; int fit_img_result; const char *uname; uint8_t img_type; /* Check to see if the images struct has a FIT configuration */ if (!genimg_has_config(images)) { debug("## FIT configuration was not specified\n"); return 0; } /* * Obtain the os FIT header from the images struct * copy from dataflash if needed */ tmp_img_addr = map_to_sysmem(images->fit_hdr_os); tmp_img_addr = genimg_get_image(tmp_img_addr); buf = map_sysmem(tmp_img_addr, 0); /* * Check image type. For FIT images get FIT node * and attempt to locate a generic binary. */ switch (genimg_get_format(buf)) { case IMAGE_FORMAT_FIT: conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg); for (loadables_index = 0; uname = fdt_stringlist_get(buf, conf_noffset, FIT_LOADABLE_PROP, loadables_index, NULL), uname; loadables_index++) { fit_img_result = fit_image_load(images, tmp_img_addr, &uname, &(images->fit_uname_cfg), arch, IH_TYPE_LOADABLE, BOOTSTAGE_ID_FIT_LOADABLE_START, FIT_LOAD_OPTIONAL_NON_ZERO, &img_data, &img_len); if (fit_img_result < 0) { /* Something went wrong! */ return fit_img_result; } fit_img_result = fit_image_get_node(buf, uname); if (fit_img_result < 0) { /* Something went wrong! */ return fit_img_result; } fit_img_result = fit_image_get_type(buf, fit_img_result, &img_type); if (fit_img_result < 0) { /* Something went wrong! */ return fit_img_result; } fit_loadable_process(img_type, img_data, img_len); } break; default: printf("The given image format is not supported (corrupt?)\n"); return 1; } return 0; }
static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) { int res; int node_offset; int splash_offset; int splash_size; struct image_header *img_header; const u32 *fit_header; u32 fit_size; const size_t header_size = sizeof(struct image_header); /* Read in image header */ res = splash_storage_read_raw(location, bmp_load_addr, header_size); if (res < 0) return res; img_header = (struct image_header *)bmp_load_addr; fit_size = fdt_totalsize(img_header); /* Read in entire FIT */ fit_header = (const u32 *)(bmp_load_addr + header_size); res = splash_storage_read_raw(location, (u32)fit_header, fit_size); if (res < 0) return res; res = fit_check_format(fit_header); if (!res) { debug("Could not find valid FIT image\n"); return -EINVAL; } node_offset = fit_image_get_node(fit_header, location->name); if (node_offset < 0) { debug("Could not find splash image '%s' in FIT\n", location->name); return -ENOENT; } res = fit_image_get_data_offset(fit_header, node_offset, &splash_offset); if (res < 0) { printf("Failed to load splash image (err=%d)\n", res); return res; } res = fit_image_get_data_size(fit_header, node_offset, &splash_size); if (res < 0) { printf("Failed to load splash image (err=%d)\n", res); return res; } /* Align data offset to 4-byte boundrary */ fit_size = fdt_totalsize(fit_header); fit_size = (fit_size + 3) & ~3; /* Read in the splash data */ location->offset = (location->offset + fit_size + splash_offset); res = splash_storage_read_raw(location, bmp_load_addr , splash_size); if (res < 0) return res; return 0; }