Skip to content
Snippets Groups Projects
image.c 40.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		} 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)
    
    			else if (rd_noffset < 0)
    				return 1;
    
    
    		/*
    		 * 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,
    
    			rd_data = image_get_data(rd_hdr);
    			rd_len = image_get_data_size(rd_hdr);
    			rd_load = image_get_load(rd_hdr);
    
    			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)
    
    			images->fit_hdr_rd = map_sysmem(rd_addr, 0);
    
    			images->fit_uname_rd = fit_uname_ramdisk;
    
    #endif
    #ifdef CONFIG_ANDROID_BOOT_IMAGE
    		case IMAGE_FORMAT_ANDROID:
    			android_image_get_ramdisk((void *)images->os.start,
    				&rd_data, &rd_len);
    			break;
    
    #ifdef CONFIG_SUPPORT_RAW_INITRD
    
    Simon Glass's avatar
    Simon Glass committed
    			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 "
    
    				(ulong)images->legacy_hdr_os);
    
    
    		image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
    
    		bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK);
    
    		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",
    
    #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
    
     * boot_ramdisk_high - relocate init ramdisk
    
     * @lmb: pointer to lmb handle, will be used for memory mgmt
    
     * @rd_data: ramdisk data start address
     * @rd_len: ramdisk data length
     * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
     *      start address (after possible relocation)
     * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
     *      end address (after possible relocation)
     *
    
     * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment
    
     * variable and if requested ramdisk data is moved to a specified location.
     *
    
     * Initrd_start and initrd_end are set to final (after relocation) ramdisk
     * start/end addresses if ramdisk image start and len were provided,
     * otherwise set initrd_start and initrd_end set to zeros.
     *
    
    int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len,
    
    		  ulong *initrd_start, ulong *initrd_end)
    
    {
    	char	*s;
    	ulong	initrd_high;
    	int	initrd_copy_to_ram = 1;
    
    
    	s = env_get("initrd_high");
    	if (s) {
    
    		/* a value of "no" or a similar string will act like 0,
    		 * turning the "load high" feature off. This is intentional.
    		 */
    
    		initrd_high = simple_strtoul(s, NULL, 16);
    
    		if (initrd_high == ~0)
    			initrd_copy_to_ram = 0;
    	} else {
    
    		initrd_high = env_get_bootm_mapsize() + env_get_bootm_low();
    
    	debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
    
    			initrd_high, initrd_copy_to_ram);
    
    	if (rd_data) {
    		if (!initrd_copy_to_ram) {	/* zero-copy ramdisk support */
    
    			debug("   in-place initrd\n");
    
    			*initrd_start = rd_data;
    			*initrd_end = rd_data + rd_len;
    
    			lmb_reserve(lmb, rd_data, rd_len);
    
    			if (initrd_high)
    
    				*initrd_start = (ulong)lmb_alloc_base(lmb,
    						rd_len, 0x1000, initrd_high);
    
    				*initrd_start = (ulong)lmb_alloc(lmb, rd_len,
    								 0x1000);
    
    
    			if (*initrd_start == 0) {
    
    				puts("ramdisk - allocation error\n");
    
    			bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
    
    
    			*initrd_end = *initrd_start + rd_len;
    
    			printf("   Loading Ramdisk to %08lx, end %08lx ... ",
    
    			memmove_wd((void *)*initrd_start,
    
    					(void *)rd_data, rd_len, CHUNKSZ);
    
    
    #ifdef CONFIG_MP
    			/*
    			 * Ensure the image is flushed to memory to handle
    			 * AMP boot scenarios in which we might not be
    			 * HW cache coherent
    			 */
    
    			flush_cache((unsigned long)*initrd_start,
    				    ALIGN(rd_len, ARCH_DMA_MINALIGN));
    
    			puts("OK\n");
    
    		}
    	} else {
    		*initrd_start = 0;
    		*initrd_end = 0;
    	}
    
    	debug("   ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
    
    			*initrd_start, *initrd_end);
    
    #endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */
    
    int boot_get_setup(bootm_headers_t *images, uint8_t arch,
    		   ulong *setup_start, ulong *setup_len)
    {
    
    	return boot_get_setup_fit(images, arch, setup_start, setup_len);
    #else
    	return -ENOENT;
    #endif
    }
    
    
    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 */
    
    	/* 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
    	 */
    	tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
    	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 (!fpga_is_partial_data(devnum, img_len)) {
    
    			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;
    }
    #endif
    
    
    static void fit_loadable_process(uint8_t img_type,
    				 ulong img_data,
    				 ulong img_len)
    {
    	int i;
    	const unsigned int count =
    			ll_entry_count(struct fit_loadable_tbl, fit_loadable);
    	struct fit_loadable_tbl *fit_loadable_handler =
    			ll_entry_start(struct fit_loadable_tbl, fit_loadable);
    	/* For each loadable handler */
    	for (i = 0; i < count; i++, fit_loadable_handler++)
    		/* matching this type */
    		if (fit_loadable_handler->type == img_type)
    			/* call that handler with this image data */
    			fit_loadable_handler->handler(img_data, img_len);
    }
    
    
    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;
    
    
    	/* 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
    	 */
    	tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
    	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,
    
    				&(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;
    }
    #endif
    
    
    #ifdef CONFIG_SYS_BOOT_GET_CMDLINE
    
     * boot_get_cmdline - allocate and initialize kernel cmdline
    
     * @lmb: pointer to lmb handle, will be used for memory mgmt
    
     * @cmd_start: pointer to a ulong variable, will hold cmdline start
     * @cmd_end: pointer to a ulong variable, will hold cmdline end
     *
    
     * boot_get_cmdline() allocates space for kernel command line below
    
     * BOOTMAPSZ + env_get_bootm_low() address. If "bootargs" U-Boot environemnt
    
     * variable is present its contents is copied to allocated kernel
     * command line.
     *
     * returns:
    
     *      0 - success
     *     -1 - failure
    
    int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end)
    
    	cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf,
    
    				env_get_bootm_mapsize() + env_get_bootm_low());
    
    
    	if (cmdline == NULL)
    		return -1;
    
    	s = env_get("bootargs");
    	if (!s)
    
    		s = "";
    
    	strcpy(cmdline, s);
    
    	*cmd_start = (ulong) & cmdline[0];
    	*cmd_end = *cmd_start + strlen(cmdline);
    
    
    	debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
    
    #endif /* CONFIG_SYS_BOOT_GET_CMDLINE */
    
    #ifdef CONFIG_SYS_BOOT_GET_KBD
    
     * boot_get_kbd - allocate and initialize kernel copy of board info
    
     * @lmb: pointer to lmb handle, will be used for memory mgmt
    
     * @kbd: double pointer to board info data
     *
    
     * boot_get_kbd() allocates space for kernel copy of board info data below
    
     * BOOTMAPSZ + env_get_bootm_low() address and kernel board info is initialized
    
     * with the current u-boot board info data.
    
     *      0 - success
     *     -1 - failure
    
    int boot_get_kbd(struct lmb *lmb, bd_t **kbd)
    
    	*kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
    
    				env_get_bootm_mapsize() + env_get_bootm_low());
    
    	if (*kbd == NULL)
    		return -1;
    
    
    	debug("## kernel board info at 0x%08lx\n", (ulong)*kbd);
    
    
    #if defined(DEBUG) && defined(CONFIG_CMD_BDI)
    	do_bdinfo(NULL, 0, 0, NULL);
    #endif
    
    
    #endif /* CONFIG_SYS_BOOT_GET_KBD */
    
    
    #ifdef CONFIG_LMB
    int image_setup_linux(bootm_headers_t *images)
    {
    	ulong of_size = images->ft_len;
    	char **of_flat_tree = &images->ft_addr;
    	struct lmb *lmb = &images->lmb;
    	int ret;
    
    	if (IMAGE_ENABLE_OF_LIBFDT)
    		boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
    
    	if (IMAGE_BOOT_GET_CMDLINE) {
    		ret = boot_get_cmdline(lmb, &images->cmdline_start,
    				&images->cmdline_end);
    		if (ret) {
    			puts("ERROR with allocation of cmdline\n");
    			return ret;
    		}
    	}
    
    	if (IMAGE_ENABLE_OF_LIBFDT) {
    		ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
    		if (ret)
    			return ret;
    	}
    
    	if (IMAGE_ENABLE_OF_LIBFDT && of_size) {
    		ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb);
    		if (ret)
    			return ret;
    	}
    
    	return 0;
    }
    #endif /* CONFIG_LMB */
    
    #endif /* !USE_HOSTCC */