/** * genimg_get_image - get image from special storage (if necessary) * @img_addr: image start address * * genimg_get_image() checks if provided image start address is located * in a dataflash storage. If so, image is moved to a system RAM memory. * * returns: * image start address after possible relocation from special storage */ ulong genimg_get_image(ulong img_addr) { ulong ram_addr = img_addr; #ifdef CONFIG_HAS_DATAFLASH ulong h_size, d_size; if (addr_dataflash(img_addr)) { void *buf; /* ger RAM address */ ram_addr = CONFIG_SYS_LOAD_ADDR; /* get header size */ h_size = image_get_header_size(); #if IMAGE_ENABLE_FIT if (sizeof(struct fdt_header) > h_size) h_size = sizeof(struct fdt_header); #endif /* read in header */ debug(" Reading image header from dataflash address " "%08lx to RAM address %08lx\n", img_addr, ram_addr); buf = map_sysmem(ram_addr, 0); read_dataflash(img_addr, h_size, buf); /* get data size */ switch (genimg_get_format(buf)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: d_size = image_get_data_size(buf); debug(" Legacy format image found at 0x%08lx, " "size 0x%08lx\n", ram_addr, d_size); break; #endif #if IMAGE_ENABLE_FIT case IMAGE_FORMAT_FIT: d_size = fit_get_size(buf) - h_size; debug(" FIT/FDT format image found at 0x%08lx, " "size 0x%08lx\n", ram_addr, d_size); break; #endif default: printf(" No valid image found at 0x%08lx\n", img_addr); return ram_addr; } /* read in image data */ debug(" Reading image remaining data from dataflash address " "%08lx to RAM address %08lx\n", img_addr + h_size, ram_addr + h_size); read_dataflash(img_addr + h_size, d_size, (char *)(buf + h_size)); } #endif /* CONFIG_HAS_DATAFLASH */ return ram_addr; }
int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, const ulong *ld_start, ulong * const ld_len) { ulong tmp_img_addr, img_data, img_len; void *buf; int conf_noffset; int fit_img_result; const char *uname, *name; int err; int devnum = 0; /* TODO support multi fpga platforms */ const fpga_desc * const desc = fpga_get_desc(devnum); xilinx_desc *desc_xilinx = desc->devdesc; /* 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); uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0, NULL); if (!uname) { debug("## FPGA image is not specified\n"); return 0; } fit_img_result = fit_image_load(images, tmp_img_addr, (const char **)&uname, &(images->fit_uname_cfg), arch, IH_TYPE_FPGA, BOOTSTAGE_ID_FPGA_INIT, FIT_LOAD_OPTIONAL_NON_ZERO, &img_data, &img_len); debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n", uname, img_data, img_len); if (fit_img_result < 0) { /* Something went wrong! */ return fit_img_result; } if (img_len >= desc_xilinx->size) { name = "full"; err = fpga_loadbitstream(devnum, (char *)img_data, img_len, BIT_FULL); if (err) err = fpga_load(devnum, (const void *)img_data, img_len, BIT_FULL); } else { name = "partial"; err = fpga_loadbitstream(devnum, (char *)img_data, img_len, BIT_PARTIAL); if (err) err = fpga_load(devnum, (const void *)img_data, img_len, BIT_PARTIAL); } if (err) return err; printf(" Programming %s bitstream... OK\n", name); break; default: printf("The given image format is not supported (corrupt?)\n"); return 1; } 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; }
/** * boot_get_fdt - main fdt handling routine * @argc: command argument count * @argv: command argument list * @arch: architecture (IH_ARCH_...) * @images: pointer to the bootm images structure * @of_flat_tree: pointer to a char* variable, will hold fdt start address * @of_size: pointer to a ulong variable, will hold fdt length * * boot_get_fdt() is responsible for finding a valid flat device tree image. * Curently supported are the following ramdisk sources: * - multicomponent kernel/ramdisk image, * - commandline provided address of decicated ramdisk image. * * returns: * 0, if fdt image was found and valid, or skipped * of_flat_tree and of_size are set to fdt start address and length if * fdt image is found and valid * * 1, if fdt image is found but corrupted * of_flat_tree and of_size are set to 0 if no fdt exists */ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, bootm_headers_t *images, char **of_flat_tree, ulong *of_size) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) const image_header_t *fdt_hdr; ulong load, load_end; ulong image_start, image_data, image_end; #endif ulong fdt_addr; char *fdt_blob = NULL; void *buf; #if defined(CONFIG_FIT) const char *fit_uname_config = images->fit_uname_cfg; const char *fit_uname_fdt = NULL; ulong default_addr; int fdt_noffset; #endif const char *select = NULL; int ok_no_fdt = 0; *of_flat_tree = NULL; *of_size = 0; if (argc > 2) select = argv[2]; if (select || genimg_has_config(images)) { #if defined(CONFIG_FIT) if (select) { /* * If the FDT blob comes from the FIT image and the * FIT image address is omitted in the command line * argument, try to use ramdisk or os FIT image * address or default load address. */ if (images->fit_uname_rd) default_addr = (ulong)images->fit_hdr_rd; else if (images->fit_uname_os) default_addr = (ulong)images->fit_hdr_os; else default_addr = load_addr; if (fit_parse_conf(select, default_addr, &fdt_addr, &fit_uname_config)) { debug("* fdt: config '%s' from image at 0x%08lx\n", fit_uname_config, fdt_addr); } else if (fit_parse_subimage(select, default_addr, &fdt_addr, &fit_uname_fdt)) { debug("* fdt: subimage '%s' from image at 0x%08lx\n", fit_uname_fdt, fdt_addr); } else #endif { fdt_addr = simple_strtoul(select, NULL, 16); debug("* fdt: cmdline image address = 0x%08lx\n", fdt_addr); } #if defined(CONFIG_FIT) } else { /* use FIT configuration provided in first bootm * command argument */ fdt_addr = map_to_sysmem(images->fit_hdr_os); fdt_noffset = fit_get_node_from_config(images, FIT_FDT_PROP, fdt_addr); if (fdt_noffset == -ENOLINK) return 0; else if (fdt_noffset < 0) return 1; } #endif debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", fdt_addr); /* copy from dataflash if needed */ fdt_addr = genimg_get_image(fdt_addr); /* * Check if there is an FDT image at the * address provided in the second bootm argument * check image type, for FIT images get a FIT node. */ buf = map_sysmem(fdt_addr, 0); switch (genimg_get_format(buf)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: /* verify fdt_addr points to a valid image header */ printf("## Flattened Device Tree from Legacy Image at %08lx\n", fdt_addr); fdt_hdr = image_get_fdt(fdt_addr); if (!fdt_hdr) goto no_fdt; /* * move image data to the load address, * make sure we don't overwrite initial image */ image_start = (ulong)fdt_hdr; image_data = (ulong)image_get_data(fdt_hdr); image_end = image_get_image_end(fdt_hdr); load = image_get_load(fdt_hdr); load_end = load + image_get_data_size(fdt_hdr); if (load == image_start || load == image_data) { fdt_blob = (char *)image_data; break; } if ((load < image_end) && (load_end > image_start)) { fdt_error("fdt overwritten"); goto error; } debug(" Loading FDT from 0x%08lx to 0x%08lx\n", image_data, load); memmove((void *)load, (void *)image_data, image_get_data_size(fdt_hdr)); fdt_addr = load; break; #endif case IMAGE_FORMAT_FIT: /* * This case will catch both: new uImage format * (libfdt based) and raw FDT blob (also libfdt * based). */ #if defined(CONFIG_FIT) /* check FDT blob vs FIT blob */ if (fit_check_format(buf)) { ulong load, len; fdt_noffset = fit_image_load(images, fdt_addr, &fit_uname_fdt, &fit_uname_config, arch, IH_TYPE_FLATDT, BOOTSTAGE_ID_FIT_FDT_START, FIT_LOAD_OPTIONAL, &load, &len); images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; images->fit_noffset_fdt = fdt_noffset; fdt_addr = load; break; } else #endif { /* * FDT blob */ debug("* fdt: raw FDT blob\n"); printf("## Flattened Device Tree blob at %08lx\n", (long)fdt_addr); } break; default: puts("ERROR: Did not find a cmdline Flattened Device Tree\n"); goto no_fdt; } printf(" Booting using the fdt blob at %#08lx\n", fdt_addr); fdt_blob = map_sysmem(fdt_addr, 0); } else if (images->legacy_hdr_valid && image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { ulong fdt_data, fdt_len; /* * Now check if we have a legacy multi-component image, * get second entry data start address and len. */ printf("## Flattened Device Tree from multi component Image at %08lX\n", (ulong)images->legacy_hdr_os); image_multi_getimg(images->legacy_hdr_os, 2, &fdt_data, &fdt_len); if (fdt_len) { fdt_blob = (char *)fdt_data; printf(" Booting using the fdt at 0x%p\n", fdt_blob); if (fdt_check_header(fdt_blob) != 0) { fdt_error("image is not a fdt"); goto error; } if (fdt_totalsize(fdt_blob) != fdt_len) { fdt_error("fdt size != image size"); goto error; } } else { debug("## No Flattened Device Tree\n"); goto no_fdt; } } else { debug("## No Flattened Device Tree\n"); goto no_fdt; } *of_flat_tree = fdt_blob; *of_size = fdt_totalsize(fdt_blob); debug(" of_flat_tree at 0x%08lx size 0x%08lx\n", (ulong)*of_flat_tree, *of_size); return 0; no_fdt: ok_no_fdt = 1; error: *of_flat_tree = NULL; *of_size = 0; if (!select && ok_no_fdt) { debug("Continuing to boot without FDT\n"); return 0; } return 1; }
/** * boot_get_ramdisk - main ramdisk handling routine * @argc: command argument count * @argv: command argument list * @images: pointer to the bootm images structure * @arch: expected ramdisk architecture * @rd_start: pointer to a ulong variable, will hold ramdisk start address * @rd_end: pointer to a ulong variable, will hold ramdisk end * * boot_get_ramdisk() is responsible for finding a valid ramdisk image. * Curently supported are the following ramdisk sources: * - multicomponent kernel/ramdisk image, * - commandline provided address of decicated ramdisk image. * * returns: * 0, if ramdisk image was found and valid, or skiped * rd_start and rd_end are set to ramdisk start/end addresses if * ramdisk image is found and valid * * 1, if ramdisk image is found but corrupted, or invalid * rd_start and rd_end are set to 0 if no ramdisk exists */ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end) { ulong rd_addr, rd_load; ulong rd_data, rd_len; #if defined(CONFIG_IMAGE_FORMAT_LEGACY) const image_header_t *rd_hdr; #endif void *buf; #ifdef CONFIG_SUPPORT_RAW_INITRD char *end; #endif #if IMAGE_ENABLE_FIT const char *fit_uname_config = images->fit_uname_cfg; const char *fit_uname_ramdisk = NULL; ulong default_addr; int rd_noffset; #endif const char *select = NULL; *rd_start = 0; *rd_end = 0; #ifdef CONFIG_ANDROID_BOOT_IMAGE /* * Look for an Android boot image. */ buf = map_sysmem(images->os.start, 0); if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) select = argv[0]; #endif if (argc >= 2) select = argv[1]; /* * Look for a '-' which indicates to ignore the * ramdisk argument */ if (select && strcmp(select, "-") == 0) { debug("## Skipping init Ramdisk\n"); rd_len = rd_data = 0; } else if (select || genimg_has_config(images)) { #if IMAGE_ENABLE_FIT if (select) { /* * If the init ramdisk comes from the FIT image and * the FIT image address is omitted in the command * line argument, try to use os FIT image address or * default load address. */ if (images->fit_uname_os) default_addr = (ulong)images->fit_hdr_os; else default_addr = load_addr; if (fit_parse_conf(select, default_addr, &rd_addr, &fit_uname_config)) { debug("* ramdisk: config '%s' from image at " "0x%08lx\n", fit_uname_config, rd_addr); } else if (fit_parse_subimage(select, default_addr, &rd_addr, &fit_uname_ramdisk)) { debug("* ramdisk: subimage '%s' from image at " "0x%08lx\n", fit_uname_ramdisk, rd_addr); } else #endif { rd_addr = simple_strtoul(select, NULL, 16); debug("* ramdisk: cmdline image address = " "0x%08lx\n", rd_addr); } #if IMAGE_ENABLE_FIT } else { /* use FIT configuration provided in first bootm * command argument. If the property is not defined, * quit silently. */ rd_addr = map_to_sysmem(images->fit_hdr_os); rd_noffset = fit_get_node_from_config(images, FIT_RAMDISK_PROP, rd_addr); if (rd_noffset == -ENOENT) return 0; else if (rd_noffset < 0) return 1; } #endif /* copy from dataflash if needed */ rd_addr = genimg_get_image(rd_addr); /* * Check if there is an initrd image at the * address provided in the second bootm argument * check image type, for FIT images get FIT node. */ buf = map_sysmem(rd_addr, 0); switch (genimg_get_format(buf)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: printf("## Loading init Ramdisk from Legacy " "Image at %08lx ...\n", rd_addr); bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK); rd_hdr = image_get_ramdisk(rd_addr, arch, images->verify); if (rd_hdr == NULL) return 1; rd_data = image_get_data(rd_hdr); rd_len = image_get_data_size(rd_hdr); rd_load = image_get_load(rd_hdr); break; #endif #if IMAGE_ENABLE_FIT case IMAGE_FORMAT_FIT: rd_noffset = fit_image_load(images, rd_addr, &fit_uname_ramdisk, &fit_uname_config, arch, IH_TYPE_RAMDISK, BOOTSTAGE_ID_FIT_RD_START, FIT_LOAD_OPTIONAL_NON_ZERO, &rd_data, &rd_len); if (rd_noffset < 0) return 1; images->fit_hdr_rd = map_sysmem(rd_addr, 0); images->fit_uname_rd = fit_uname_ramdisk; images->fit_noffset_rd = rd_noffset; break; #endif #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: android_image_get_ramdisk((void *)images->os.start, &rd_data, &rd_len); break; #endif default: #ifdef CONFIG_SUPPORT_RAW_INITRD end = NULL; if (select) end = strchr(select, ':'); if (end) { rd_len = simple_strtoul(++end, NULL, 16); rd_data = rd_addr; } else #endif { puts("Wrong Ramdisk Image Format\n"); rd_data = rd_len = rd_load = 0; return 1; } } } else if (images->legacy_hdr_valid && image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { /* * Now check if we have a legacy mult-component image, * get second entry data start address and len. */ bootstage_mark(BOOTSTAGE_ID_RAMDISK); printf("## Loading init Ramdisk from multi component " "Legacy Image at %08lx ...\n", (ulong)images->legacy_hdr_os); image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len); } else { /* * no initrd image */ bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK); rd_len = rd_data = 0; } if (!rd_data) { debug("## No init Ramdisk\n"); } else { *rd_start = rd_data; *rd_end = rd_data + rd_len; } debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", *rd_start, *rd_end); return 0; }
static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end, int boot_progress) { image_info_t os = images->os; uint8_t comp = os.comp; ulong load = os.load; ulong blob_start = os.start; ulong blob_end = os.end; ulong image_start = os.image_start; ulong image_len = os.image_len; __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN; int no_overlap = 0; void *load_buf, *image_buf; #if defined(CONFIG_LZMA) || defined(CONFIG_LZO) int ret; #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ const char *type_name = genimg_get_type_name(os.type); load_buf = map_sysmem(load, unc_len); image_buf = map_sysmem(image_start, image_len); switch (comp) { case IH_COMP_NONE: if (load == blob_start || load == image_start) { printf(" XIP %s ... ", type_name); no_overlap = 1; } else { printf(" Loading %s ... ", type_name); memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); } *load_end = load + image_len; break; #ifdef CONFIG_GZIP case IH_COMP_GZIP: printf(" Uncompressing %s ... ", type_name); if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) { puts("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n"); if (boot_progress) bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } *load_end = load + image_len; break; #endif /* CONFIG_GZIP */ #ifdef CONFIG_BZIP2 case IH_COMP_BZIP2: printf(" Uncompressing %s ... ", type_name); /* * If we've got less than 4 MB of malloc() space, * use slower decompression algorithm which requires * at most 2300 KB of memory. */ int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len, image_buf, image_len, CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n", i); if (boot_progress) bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } *load_end = load + unc_len; break; #endif /* CONFIG_BZIP2 */ #ifdef CONFIG_LZMA case IH_COMP_LZMA: { SizeT lzma_len = unc_len; printf(" Uncompressing %s ... ", type_name); ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, image_buf, image_len); unc_len = lzma_len; if (ret != SZ_OK) { printf("LZMA: uncompress or overwrite error %d " "- must RESET board to recover\n", ret); bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } *load_end = load + unc_len; break; } #endif /* CONFIG_LZMA */ #ifdef CONFIG_LZO case IH_COMP_LZO: { size_t size; printf(" Uncompressing %s ... ", type_name); ret = lzop_decompress(image_buf, image_len, load_buf, &size); if (ret != LZO_E_OK) { printf("LZO: uncompress or overwrite error %d " "- must RESET board to recover\n", ret); if (boot_progress) bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } *load_end = load + size; break; } #endif /* CONFIG_LZO */ default: printf("Unimplemented compression type %d\n", comp); return BOOTM_ERR_UNIMPLEMENTED; } flush_cache(load, (*load_end - load) * sizeof(ulong)); puts("OK\n"); debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end); bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED); if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) { debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end); debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load, *load_end); /* Check what type of image this is. */ 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"); return BOOTM_ERR_OVERLAP; } else { puts("ERROR: new format image overwritten - must RESET the board to recover\n"); bootstage_error(BOOTSTAGE_ID_OVERWRITTEN); return BOOTM_ERR_RESET; } } return 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 char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; int os_noffset; #endif /* find out kernel image address */ if (argc < 1) { 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[0], 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[0], 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[0], 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: os_noffset = fit_image_load(images, FIT_KERNEL_PROP, img_addr, &fit_uname_kernel, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_KERNEL, BOOTSTAGE_ID_FIT_KERNEL_START, FIT_LOAD_IGNORED, os_data, os_len); if (os_noffset < 0) return NULL; images->fit_hdr_os = map_sysmem(img_addr, 0); images->fit_uname_os = fit_uname_kernel; images->fit_uname_cfg = fit_uname_config; 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 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; #ifndef USE_HOSTCC uint8_t os_arch; #endif 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 #ifndef USE_HOSTCC fit_image_get_arch(fit, noffset, &os_arch); images->os.arch = os_arch; #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) || fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) || (image_type == IH_TYPE_KERNEL && fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); os_ok = image_type == IH_TYPE_FLATDT || image_type == IH_TYPE_FPGA || fit_image_check_os(fit, noffset, IH_OS_LINUX) || fit_image_check_os(fit, noffset, IH_OS_U_BOOT) || 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 uniphier_sd_probe(struct udevice *dev) { struct uniphier_sd_priv *priv = dev_get_priv(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); fdt_addr_t base; struct udevice *clk_dev; int clk_id; int ret; priv->dev = dev; base = dev_get_addr(dev); if (base == FDT_ADDR_T_NONE) return -EINVAL; priv->regbase = map_sysmem(base, SZ_2K); if (!priv->regbase) return -ENOMEM; clk_id = clk_get_by_index(dev, 0, &clk_dev); if (clk_id < 0) { dev_err(dev, "failed to get host clock\n"); return clk_id; } /* set to max rate */ priv->mclk = clk_set_periph_rate(clk_dev, clk_id, ULONG_MAX); if (IS_ERR_VALUE(priv->mclk)) { dev_err(dev, "failed to set rate for host clock\n"); return priv->mclk; } ret = clk_enable(clk_dev, clk_id); if (ret) { dev_err(dev, "failed to enable host clock\n"); return ret; } priv->cfg.name = dev->name; priv->cfg.ops = &uniphier_sd_ops; priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) { case 8: priv->cfg.host_caps |= MMC_MODE_8BIT; break; case 4: priv->cfg.host_caps |= MMC_MODE_4BIT; break; case 1: break; default: dev_err(dev, "Invalid \"bus-width\" value\n"); return -EINVAL; } if (fdt_get_property(gd->fdt_blob, dev->of_offset, "non-removable", NULL)) priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE; priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) & UNIPHIER_SD_VERSION_IP; dev_dbg(dev, "version %x\n", priv->version); if (priv->version >= 0x10) { priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL; priv->caps |= UNIPHIER_SD_CAP_DIV1024; } priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; priv->cfg.f_min = priv->mclk / (priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512); priv->cfg.f_max = priv->mclk; priv->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */ priv->mmc = mmc_create(&priv->cfg, priv); if (!priv->mmc) return -EIO; upriv->mmc = priv->mmc; return 0; }
/* * env import [-d] [-t [-r] | -b | -c] addr [size] * -d: delete existing environment before importing; * otherwise overwrite / append to existion definitions * -t: assume text format; either "size" must be given or the * text data must be '\0' terminated * -r: handle CRLF like LF, that means exported variables with * a content which ends with \r won't get imported. Used * to import text files created with editors which are using CRLF * for line endings. Only effective in addition to -t. * -b: assume binary format ('\0' separated, "\0\0" terminated) * -c: assume checksum protected environment format * addr: memory address to read from * size: length of input data; if missing, proper '\0' * termination is mandatory */ static int do_env_import(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr; char *cmd, *ptr; char sep = '\n'; int chk = 0; int fmt = 0; int del = 0; int crlf_is_lf = 0; size_t size; cmd = *argv; while (--argc > 0 && **++argv == '-') { char *arg = *argv; while (*++arg) { switch (*arg) { case 'b': /* raw binary format */ if (fmt++) goto sep_err; sep = '\0'; break; case 'c': /* external checksum format */ if (fmt++) goto sep_err; sep = '\0'; chk = 1; break; case 't': /* text format */ if (fmt++) goto sep_err; sep = '\n'; break; case 'r': /* handle CRLF like LF */ crlf_is_lf = 1; break; case 'd': del = 1; break; default: return CMD_RET_USAGE; } } } if (argc < 1) return CMD_RET_USAGE; if (!fmt) printf("## Warning: defaulting to text format\n"); if (sep != '\n' && crlf_is_lf ) crlf_is_lf = 0; addr = simple_strtoul(argv[0], NULL, 16); ptr = map_sysmem(addr, 0); if (argc == 2) { size = simple_strtoul(argv[1], NULL, 16); } else if (argc == 1 && chk) { puts("## Error: external checksum format must pass size\n"); return CMD_RET_FAILURE; } else { char *s = ptr; size = 0; while (size < MAX_ENV_SIZE) { if ((*s == sep) && (*(s+1) == '\0')) break; ++s; ++size; } if (size == MAX_ENV_SIZE) { printf("## Warning: Input data exceeds %d bytes" " - truncated\n", MAX_ENV_SIZE); } size += 2; printf("## Info: input data size = %zu = 0x%zX\n", size, size); } if (chk) { uint32_t crc; env_t *ep = (env_t *)ptr; size -= offsetof(env_t, data); memcpy(&crc, &ep->crc, sizeof(crc)); if (crc32(0, ep->data, size) != crc) { puts("## Error: bad CRC, import failed\n"); return 1; } ptr = (char *)ep->data; } if (himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR, crlf_is_lf, 0, NULL) == 0) { error("Environment import failed: errno = %d\n", errno); return 1; } gd->flags |= GD_FLG_ENV_READY; return 0; sep_err: printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", cmd); return 1; }
/* * env export [-t | -b | -c] [-s size] addr [var ...] * -t: export as text format; if size is given, data will be * padded with '\0' bytes; if not, one terminating '\0' * will be added (which is included in the "filesize" * setting so you can for exmple copy this to flash and * keep the termination). * -b: export as binary format (name=value pairs separated by * '\0', list end marked by double "\0\0") * -c: export as checksum protected environment format as * used for example by "saveenv" command * -s size: * size of output buffer * addr: memory address where environment gets stored * var... List of variable names that get included into the * export. Without arguments, the whole environment gets * exported. * * With "-c" and size is NOT given, then the export command will * format the data as currently used for the persistent storage, * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and * prepend a valid CRC32 checksum and, in case of resundant * environment, a "current" redundancy flag. If size is given, this * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 * checksum and redundancy flag will be inserted. * * With "-b" and "-t", always only the real data (including a * terminating '\0' byte) will be written; here the optional size * argument will be used to make sure not to overflow the user * provided buffer; the command will abort if the size is not * sufficient. Any remainign space will be '\0' padded. * * On successful return, the variable "filesize" will be set. * Note that filesize includes the trailing/terminating '\0' byte(s). * * Usage szenario: create a text snapshot/backup of the current settings: * * => env export -t 100000 * => era ${backup_addr} +${filesize} * => cp.b 100000 ${backup_addr} ${filesize} * * Re-import this snapshot, deleting all other settings: * * => env import -d -t ${backup_addr} */ static int do_env_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char buf[32]; ulong addr; char *ptr, *cmd, *res; size_t size = 0; ssize_t len; env_t *envp; char sep = '\n'; int chk = 0; int fmt = 0; cmd = *argv; while (--argc > 0 && **++argv == '-') { char *arg = *argv; while (*++arg) { switch (*arg) { case 'b': /* raw binary format */ if (fmt++) goto sep_err; sep = '\0'; break; case 'c': /* external checksum format */ if (fmt++) goto sep_err; sep = '\0'; chk = 1; break; case 's': /* size given */ if (--argc <= 0) return cmd_usage(cmdtp); size = simple_strtoul(*++argv, NULL, 16); goto NXTARG; case 't': /* text format */ if (fmt++) goto sep_err; sep = '\n'; break; default: return CMD_RET_USAGE; } } NXTARG: ; } if (argc < 1) return CMD_RET_USAGE; addr = simple_strtoul(argv[0], NULL, 16); ptr = map_sysmem(addr, size); if (size) memset(ptr, '\0', size); argc--; argv++; if (sep) { /* export as text file */ len = hexport_r(&env_htab, sep, H_MATCH_KEY | H_MATCH_IDENT, &ptr, size, argc, argv); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; } sprintf(buf, "%zX", (size_t)len); setenv("filesize", buf); return 0; } envp = (env_t *)ptr; if (chk) /* export as checksum protected block */ res = (char *)envp->data; else /* export as raw binary data */ res = ptr; len = hexport_r(&env_htab, '\0', H_MATCH_KEY | H_MATCH_IDENT, &res, ENV_SIZE, argc, argv); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; } if (chk) { envp->crc = crc32(0, envp->data, ENV_SIZE); #ifdef CONFIG_ENV_ADDR_REDUND envp->flags = ACTIVE_FLAG; #endif } setenv_hex("filesize", len + offsetof(env_t, data)); return 0; sep_err: printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", cmd); return 1; }
static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) { uint8_t comp = os.comp; ulong load = os.load; ulong blob_start = os.start; ulong blob_end = os.end; ulong image_start = os.image_start; ulong image_len = os.image_len; __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN; int no_overlap = 0; void *load_buf, *image_buf; const char *type_name = genimg_get_type_name(os.type); load_buf = map_sysmem(load, image_len); image_buf = map_sysmem(image_start, image_len); switch (comp) { case IH_COMP_NONE: if (load == blob_start || load == image_start) { printf(" XIP %s ... ", type_name); no_overlap = 1; } else { printf(" Loading %s ... ", type_name); memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); } *load_end = load + image_len; puts("OK\n"); break; #ifdef CONFIG_GZIP case IH_COMP_GZIP: printf(" Uncompressing %s ... ", type_name); if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) { puts("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n"); if (boot_progress) bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } *load_end = load + image_len; break; #endif /* CONFIG_GZIP */ default: printf("Unimplemented compression type %d\n", comp); return BOOTM_ERR_UNIMPLEMENTED; } flush_cache(load, (*load_end - load) * sizeof(ulong)); puts("OK\n"); debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end); bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED); if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) { debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end); debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load, *load_end); return BOOTM_ERR_OVERLAP; } return 0; }
/* * Flattened Device Tree command, see the help for parameter definitions. */ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (argc < 2) return CMD_RET_USAGE; /* * Set the address of the fdt */ if (argv[1][0] == 'a') { unsigned long addr; int control = 0; struct fdt_header *blob; /* * Set the address [and length] of the fdt. */ argc -= 2; argv += 2; /* Temporary #ifdef - some archs don't have fdt_blob yet */ #ifdef CONFIG_OF_CONTROL if (argc && !strcmp(*argv, "-c")) { control = 1; argc--; argv++; } #endif if (argc == 0) { if (control) blob = (struct fdt_header *)gd->fdt_blob; else blob = working_fdt; if (!blob || !fdt_valid(&blob)) return 1; printf("The address of the fdt is %#08lx\n", control ? (ulong)map_to_sysmem(blob) : getenv_hex("fdtaddr", 0)); return 0; } addr = simple_strtoul(argv[0], NULL, 16); blob = map_sysmem(addr, 0); if (!fdt_valid(&blob)) return 1; if (control) gd->fdt_blob = blob; else set_working_fdt_addr(addr); if (argc >= 2) { int len; int err; /* * Optional new length */ len = simple_strtoul(argv[1], NULL, 16); if (len < fdt_totalsize(blob)) { printf ("New length %d < existing length %d, " "ignoring.\n", len, fdt_totalsize(blob)); } else { /* * Open in place with a new length. */ err = fdt_open_into(blob, blob, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); } } } return CMD_RET_SUCCESS; } if (!working_fdt) { puts( "No FDT memory address configured. Please configure\n" "the FDT address via \"fdt addr <address>\" command.\n" "Aborting!\n"); return CMD_RET_FAILURE; } /* * Move the working_fdt */ if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; if (argc < 4) return CMD_RET_USAGE; /* * Set the address and length of the fdt. */ working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid(&working_fdt)) return 1; newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); /* * If the user specifies a length, use that. Otherwise use the * current length. */ if (argc <= 4) { len = fdt_totalsize(working_fdt); } else { len = simple_strtoul(argv[4], NULL, 16); if (len < fdt_totalsize(working_fdt)) { printf ("New length 0x%X < existing length " "0x%X, aborting.\n", len, fdt_totalsize(working_fdt)); return 1; } } /* * Copy to the new location. */ err = fdt_open_into(working_fdt, newaddr, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } working_fdt = newaddr; /* * Make a new node */ } else if (strncmp(argv[1], "mk", 2) == 0) { char *pathp; /* path */ char *nodep; /* new node to add */ int nodeoffset; /* node offset from libfdt */ int err; /* * Parameters: Node path, new node to be appended to the path. */ if (argc < 4) return CMD_RET_USAGE; pathp = argv[2]; nodep = argv[3]; nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } err = fdt_add_subnode(working_fdt, nodeoffset, nodep); if (err < 0) { printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); return 1; } /* * Set the value of a property in the working_fdt. */ } else if (argv[1][0] == 's') { char *pathp; /* path */ char *prop; /* property */ int nodeoffset; /* node offset from libfdt */ static char data[SCRATCHPAD]; /* storage for the property */ int len; /* new length of the property */ int ret; /* return value */ /* * Parameters: Node path, property, optional value. */ if (argc < 4) return CMD_RET_USAGE; pathp = argv[2]; prop = argv[3]; if (argc == 4) { len = 0; } else { ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); if (ret != 0) return ret; } nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len); if (ret < 0) { printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); return 1; } /******************************************************************** * Get the value of a property in the working_fdt. ********************************************************************/ } else if (argv[1][0] == 'g') { char *subcmd; /* sub-command */ char *pathp; /* path */ char *prop; /* property */ char *var; /* variable to store result */ int nodeoffset; /* node offset from libfdt */ const void *nodep; /* property node pointer */ int len = 0; /* new length of the property */ /* * Parameters: Node path, property, optional value. */ if (argc < 5) return CMD_RET_USAGE; subcmd = argv[2]; if (argc < 6 && subcmd[0] != 's') return CMD_RET_USAGE; var = argv[3]; pathp = argv[4]; prop = argv[5]; nodeoffset = fdt_path_offset(working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { int reqIndex = -1; int startDepth = fdt_node_depth( working_fdt, nodeoffset); int curDepth = startDepth; int curIndex = -1; int nextNodeOffset = fdt_next_node( working_fdt, nodeoffset, &curDepth); if (subcmd[0] == 'n') reqIndex = simple_strtoul(argv[5], NULL, 16); while (curDepth > startDepth) { if (curDepth == startDepth + 1) curIndex++; if (subcmd[0] == 'n' && curIndex == reqIndex) { const char *nodeName = fdt_get_name( working_fdt, nextNodeOffset, NULL); setenv(var, (char *)nodeName); return 0; } nextNodeOffset = fdt_next_node( working_fdt, nextNodeOffset, &curDepth); if (nextNodeOffset < 0) break; } if (subcmd[0] == 's') { /* get the num nodes at this level */ setenv_ulong(var, curIndex + 1); } else { /* node index not found */ printf("libfdt node not found\n"); return 1; } } else { nodep = fdt_getprop( working_fdt, nodeoffset, prop, &len); if (len == 0) { /* no property value */ setenv(var, ""); return 0; } else if (len > 0) { if (subcmd[0] == 'v') { int ret; ret = fdt_value_setenv(nodep, len, var); if (ret != 0) return ret; } else if (subcmd[0] == 'a') { /* Get address */ char buf[11]; sprintf(buf, "0x%p", nodep); setenv(var, buf); } else if (subcmd[0] == 's') { /* Get size */ char buf[11]; sprintf(buf, "0x%08X", len); setenv(var, buf); } else return CMD_RET_USAGE; return 0; } else { printf("libfdt fdt_getprop(): %s\n", fdt_strerror(len)); return 1; } } /* * Print (recursive) / List (single level) */ } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ char *prop; /* property */ int ret; /* return value */ static char root[2] = "/"; /* * list is an alias for print, but limited to 1 level */ if (argv[1][0] == 'l') { depth = 1; } /* * Get the starting path. The root node is an oddball, * the offset is zero and has no name. */ if (argc == 2) pathp = root; else pathp = argv[2]; if (argc > 3) prop = argv[3]; else prop = NULL; ret = fdt_print(pathp, prop, depth); if (ret != 0) return ret; /* * Remove a property/node */ } else if (strncmp(argv[1], "rm", 2) == 0) { int nodeoffset; /* node offset from libfdt */ int err; /* * Get the path. The root node is an oddball, the offset * is zero and has no name. */ nodeoffset = fdt_path_offset (working_fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } /* * Do the delete. A fourth parameter means delete a property, * otherwise delete the node. */ if (argc > 3) { err = fdt_delprop(working_fdt, nodeoffset, argv[3]); if (err < 0) { printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { err = fdt_del_node(working_fdt, nodeoffset); if (err < 0) { printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); return err; } } /* * Display header info */ } else if (argv[1][0] == 'h') { u32 version = fdt_version(working_fdt); printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), fdt_totalsize(working_fdt)); printf("off_dt_struct:\t\t0x%x\n", fdt_off_dt_struct(working_fdt)); printf("off_dt_strings:\t\t0x%x\n", fdt_off_dt_strings(working_fdt)); printf("off_mem_rsvmap:\t\t0x%x\n", fdt_off_mem_rsvmap(working_fdt)); printf("version:\t\t%d\n", version); printf("last_comp_version:\t%d\n", fdt_last_comp_version(working_fdt)); if (version >= 2) printf("boot_cpuid_phys:\t0x%x\n", fdt_boot_cpuid_phys(working_fdt)); if (version >= 3) printf("size_dt_strings:\t0x%x\n", fdt_size_dt_strings(working_fdt)); if (version >= 17) printf("size_dt_struct:\t\t0x%x\n", fdt_size_dt_struct(working_fdt)); printf("number mem_rsv:\t\t0x%x\n", fdt_num_mem_rsv(working_fdt)); printf("\n"); /* * Set boot cpu id */ } else if (strncmp(argv[1], "boo", 3) == 0) { unsigned long tmp = simple_strtoul(argv[2], NULL, 16); fdt_set_boot_cpuid_phys(working_fdt, tmp); /* * memory command */ } else if (strncmp(argv[1], "me", 2) == 0) { uint64_t addr, size; int err; addr = simple_strtoull(argv[2], NULL, 16); size = simple_strtoull(argv[3], NULL, 16); err = fdt_fixup_memory(working_fdt, addr, size); if (err < 0) return err; /* * mem reserve commands */ } else if (strncmp(argv[1], "rs", 2) == 0) { if (argv[2][0] == 'p') { uint64_t addr, size; int total = fdt_num_mem_rsv(working_fdt); int j, err; printf("index\t\t start\t\t size\n"); printf("-------------------------------" "-----------------\n"); for (j = 0; j < total; j++) { err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); if (err < 0) { printf("libfdt fdt_get_mem_rsv(): %s\n", fdt_strerror(err)); return err; } printf(" %x\t%08x%08x\t%08x%08x\n", j, (u32)(addr >> 32), (u32)(addr & 0xffffffff), (u32)(size >> 32), (u32)(size & 0xffffffff)); } } else if (argv[2][0] == 'a') {
/* Set up the display ready for use */ static int video_post_probe(struct udevice *dev) { struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_priv *priv = dev_get_uclass_priv(dev); char name[30], drv[15], *str; const char *drv_name = drv; struct udevice *cons; int ret; /* Set up the line and display size */ priv->fb = map_sysmem(plat->base, plat->size); priv->line_length = priv->xsize * VNBYTES(priv->bpix); priv->fb_size = priv->line_length * priv->ysize; /* Set up colours - we could in future support other colours */ #ifdef CONFIG_SYS_WHITE_ON_BLACK priv->colour_fg = 0xffffff; #else priv->colour_bg = 0xffffff; #endif video_clear(dev); /* * Create a text console device. For now we always do this, although * it might be useful to support only bitmap drawing on the device * for boards that don't need to display text. We create a TrueType * console if enabled, a rotated console if the video driver requests * it, otherwise a normal console. * * The console can be override by setting vidconsole_drv_name before * probing this video driver, or in the probe() method. * * TrueType does not support rotation at present so fall back to the * rotated console in that case. */ if (!priv->rot && IS_ENABLED(CONFIG_CONSOLE_TRUETYPE)) { snprintf(name, sizeof(name), "%s.vidconsole_tt", dev->name); strcpy(drv, "vidconsole_tt"); } else { snprintf(name, sizeof(name), "%s.vidconsole%d", dev->name, priv->rot); snprintf(drv, sizeof(drv), "vidconsole%d", priv->rot); } str = strdup(name); if (!str) return -ENOMEM; if (priv->vidconsole_drv_name) drv_name = priv->vidconsole_drv_name; ret = device_bind_driver(dev, drv_name, str, &cons); if (ret) { debug("%s: Cannot bind console driver\n", __func__); return ret; } ret = device_probe(cons); if (ret) { debug("%s: Cannot probe console driver\n", __func__); return ret; } return 0; };