[PATCH 04/15] bootm: give bootm_load_ functions an end address

Ahmad Fatoum a.fatoum at pengutronix.de
Tue Jan 27 07:31:58 PST 2026


Hi,

On 1/27/26 9:39 AM, Ahmad Fatoum wrote:
> So far we expected that a load operation will not overflow, but there
> was actually no way for the callee to check this.
> 
> As the architecture-specific bootm handlers are tasked with allocating
> memory for boot artifacts have them pass along not only the start of the
> load region, but also its end, so the callee can check that it didn't
> overflow.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

Please dismiss this one patch. I got at least one end offset wrong and I
will just redo it separate from this series.

Thanks,
Ahmad

> ---
>  arch/arm/lib32/bootm.c              | 24 +++++---
>  arch/arm/lib64/armlinux.c           |  7 ++-
>  arch/arm/mach-at91/bootm-barebox.c  |  7 ++-
>  arch/arm/mach-imx/imx-v3-image.c    |  7 ++-
>  arch/arm/mach-layerscape/pblimage.c |  7 ++-
>  arch/arm/mach-rockchip/bootm.c      | 13 ++--
>  arch/arm/mach-zynq/bootm-zynqimg.c  |  7 ++-
>  arch/kvx/lib/bootm.c                | 17 ++++--
>  arch/powerpc/lib/ppclinux.c         | 13 +++-
>  common/booti.c                      | 30 +++++----
>  common/bootm-mock.c                 |  0
>  common/bootm.c                      | 95 ++++++++++++++++++-----------
>  efi/loader/bootm.c                  |  9 ++-
>  include/bootm.h                     | 13 ++--
>  14 files changed, 158 insertions(+), 91 deletions(-)
>  create mode 100644 common/bootm-mock.c
> 
> diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c
> index e659d3c1a554..3641dbbdbe61 100644
> --- a/arch/arm/lib32/bootm.c
> +++ b/arch/arm/lib32/bootm.c
> @@ -236,12 +236,17 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
>  {
>  	unsigned long kernel;
>  	unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0;
> -	const struct resource *initrd_res;
> +	const struct resource *initrd_res, *sdram;
> +	struct resource gap;
>  	void *tee;
>  	enum arm_security_state state = bootm_arm_security_state();
>  	void *fdt_load_address = NULL;
>  	int ret;
>  
> +	sdram = memory_bank_lookup_region(free_mem, &gap);
> +	if (sdram != &gap)
> +		return sdram ? -EBUSY : -EINVAL;
> +
>  	kernel = data->os_res->start + data->os_entry;
>  
>  	initrd_start = data->initrd_address;
> @@ -255,7 +260,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
>  		}
>  	}
>  
> -	initrd_res = bootm_load_initrd(data, initrd_start);
> +	initrd_res = bootm_load_initrd(data, initrd_start, gap.end);
>  	if (IS_ERR(initrd_res)) {
>  		return PTR_ERR(initrd_res);
>  	} else if (initrd_res) {
> @@ -277,13 +282,15 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
>  	}
>  
>  	if (fdt) {
> +		const struct resource *fdt_res;
> +
>  		fdt_load_address = (void *)free_mem;
> -		ret = bootm_load_devicetree(data, fdt, free_mem);
> +		fdt_res = bootm_load_devicetree(data, fdt, free_mem, gap.end);
>  
>  		free(fdt);
>  
> -		if (ret)
> -			return ret;
> +		if (IS_ERR(fdt_res))
> +			return PTR_ERR(fdt_res);
>  	}
>  
>  	if (IS_ENABLED(CONFIG_BOOTM_OPTEE)) {
> @@ -339,6 +346,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
>  
>  static int do_bootm_linux(struct image_data *data)
>  {
> +	const struct resource *os_res;
>  	unsigned long load_address, mem_free;
>  	int ret;
>  
> @@ -349,9 +357,9 @@ static int do_bootm_linux(struct image_data *data)
>  	if (ret)
>  		return ret;
>  
> -	ret = bootm_load_os(data, load_address);
> -	if (ret)
> -		return ret;
> +	os_res = bootm_load_os(data, load_address, mem_free - 1);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	return __do_bootm_linux(data, mem_free, 0, NULL);
>  }
> diff --git a/arch/arm/lib64/armlinux.c b/arch/arm/lib64/armlinux.c
> index e40b61a26b07..febffb6c858b 100644
> --- a/arch/arm/lib64/armlinux.c
> +++ b/arch/arm/lib64/armlinux.c
> @@ -43,6 +43,7 @@ static int do_bootm_barebox(struct image_data *data)
>  {
>  	void (*fn)(unsigned long x0, unsigned long x1, unsigned long x2,
>  		       unsigned long x3);
> +	const struct resource *os_res;
>  	resource_size_t start, end;
>  	unsigned long barebox;
>  	int ret;
> @@ -53,9 +54,9 @@ static int do_bootm_barebox(struct image_data *data)
>  
>  	barebox = PAGE_ALIGN(start);
>  
> -	ret = bootm_load_os(data, barebox);
> -	if (ret)
> -		goto out;
> +	os_res = bootm_load_os(data, barebox, end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	printf("Loaded barebox image to 0x%08lx\n", barebox);
>  
> diff --git a/arch/arm/mach-at91/bootm-barebox.c b/arch/arm/mach-at91/bootm-barebox.c
> index 5540b8fad35e..f4894f247d11 100644
> --- a/arch/arm/mach-at91/bootm-barebox.c
> +++ b/arch/arm/mach-at91/bootm-barebox.c
> @@ -13,6 +13,7 @@ EXPORT_SYMBOL(at91_bootsource);
>  
>  static int do_bootm_at91_barebox_image(struct image_data *data)
>  {
> +	const struct resource *os_res;
>  	resource_size_t start, end;
>  	int ret;
>  
> @@ -20,9 +21,9 @@ static int do_bootm_at91_barebox_image(struct image_data *data)
>  	if (ret)
>  		return ret;
>  
> -	ret = bootm_load_os(data, start);
> -	if (ret)
> -		return ret;
> +	os_res = bootm_load_os(data, start, end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	if (data->verbose)
>  		printf("Loaded barebox image to 0x%08zx\n", start);
> diff --git a/arch/arm/mach-imx/imx-v3-image.c b/arch/arm/mach-imx/imx-v3-image.c
> index e5df5fdb81d9..5cce846f867f 100644
> --- a/arch/arm/mach-imx/imx-v3-image.c
> +++ b/arch/arm/mach-imx/imx-v3-image.c
> @@ -8,6 +8,7 @@
>  
>  static int do_bootm_imx_image_v3(struct image_data *data)
>  {
> +	const struct resource *os_res;
>  	void (*bb)(void);
>  	resource_size_t start, end;
>  	struct flash_header_v3 *hdr;
> @@ -18,9 +19,9 @@ static int do_bootm_imx_image_v3(struct image_data *data)
>  	if (ret)
>  		return ret;
>  
> -	ret = bootm_load_os(data, start);
> -	if (ret)
> -		return ret;
> +	os_res = bootm_load_os(data, start, end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	hdr = (void *)start;
>  	offset = hdr->img[0].offset;
> diff --git a/arch/arm/mach-layerscape/pblimage.c b/arch/arm/mach-layerscape/pblimage.c
> index 5a525f0933d5..31783f18c74d 100644
> --- a/arch/arm/mach-layerscape/pblimage.c
> +++ b/arch/arm/mach-layerscape/pblimage.c
> @@ -15,6 +15,7 @@ static int do_bootm_layerscape_pblimage(struct image_data *data)
>  {
>  	void (*barebox)(unsigned long x0, unsigned long x1, unsigned long x2,
>  		       unsigned long x3);
> +	const struct resource *os_res;
>  	resource_size_t start, end;
>  	int ret;
>  
> @@ -22,9 +23,9 @@ static int do_bootm_layerscape_pblimage(struct image_data *data)
>  	if (ret)
>  		return ret;
>  
> -	ret = bootm_load_os(data, start);
> -	if (ret)
> -		return ret;
> +	os_res = bootm_load_os(data, start, end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	barebox = (void*)start + BAREBOX_STAGE2_OFFSET;
>  
> diff --git a/arch/arm/mach-rockchip/bootm.c b/arch/arm/mach-rockchip/bootm.c
> index ff3d9a2db3a0..2e068b05cefd 100644
> --- a/arch/arm/mach-rockchip/bootm.c
> +++ b/arch/arm/mach-rockchip/bootm.c
> @@ -40,6 +40,7 @@ static int do_bootm_rkns_barebox_image(struct image_data *data)
>  {
>  	void (*barebox)(unsigned long x0, unsigned long x1, unsigned long x2,
>  			unsigned long x3);
> +	const struct resource *os_res;
>  	resource_size_t start, end;
>  	struct newidb *idb;
>  	int ret, i, n_files;
> @@ -50,14 +51,14 @@ static int do_bootm_rkns_barebox_image(struct image_data *data)
>  	if (ret)
>  		return ret;
>  
> -	ret = bootm_load_os(data, start);
> -	if (ret)
> -		return ret;
> +	os_res = bootm_load_os(data, start, end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
> -	idb = (void *)data->os_res->start;
> -	buf = (void *)data->os_res->start;
> +	idb = (void *)os_res->start;
> +	buf = (void *)os_res->start;
>  
> -	image_size = resource_size(data->os_res);
> +	image_size = resource_size(os_res);
>  
>  	if (image_size < SECTOR_SIZE)
>  		return -EINVAL;
> diff --git a/arch/arm/mach-zynq/bootm-zynqimg.c b/arch/arm/mach-zynq/bootm-zynqimg.c
> index 77ed6880e4b6..ebd2d621520b 100644
> --- a/arch/arm/mach-zynq/bootm-zynqimg.c
> +++ b/arch/arm/mach-zynq/bootm-zynqimg.c
> @@ -8,6 +8,7 @@
>  static int do_bootm_zynqimage(struct image_data *data)
>  {
>  	resource_size_t start, end;
> +	const struct resource *os_res;
>  	void (*barebox)(void);
>  	u32 *header;
>  	int ret;
> @@ -16,9 +17,9 @@ static int do_bootm_zynqimage(struct image_data *data)
>  	if (ret)
>  		return ret;
>  
> -	ret = bootm_load_os(data, start);
> -	if (ret)
> -		return ret;
> +	os_res = bootm_load_os(data, start, end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	header = (u32*)start;
>  	barebox = (void*)start + header[12];
> diff --git a/arch/kvx/lib/bootm.c b/arch/kvx/lib/bootm.c
> index 6eba4054e500..c464b5006fa2 100644
> --- a/arch/kvx/lib/bootm.c
> +++ b/arch/kvx/lib/bootm.c
> @@ -13,6 +13,7 @@
>  #include <bootm.h>
>  #include <binfmt.h>
>  #include <common.h>
> +#include <memory.h>
>  #include <libfile.h>
>  #include <linux/kernel.h>
>  
> @@ -54,7 +55,8 @@ static int do_boot_entry(struct image_data *data, boot_func_entry entry,
>  
>  static int do_boot_elf(struct image_data *data, struct elf_image *elf)
>  {
> -	const struct resource *initrd_res;
> +	const struct resource *sdram, *initrd_res, *fdt_res;
> +	struct resource gap;
>  	int ret;
>  	void *fdt;
>  	boot_func_entry entry;
> @@ -71,7 +73,11 @@ static int do_boot_elf(struct image_data *data, struct elf_image *elf)
>  	else
>  		initrd_address = load_addr;
>  
> -	initrd_res = bootm_load_initrd(data, initrd_address);
> +	sdram = memory_bank_lookup_region(initrd_address, &gap);
> +	if (sdram != &gap)
> +		return sdram ? -EBUSY : -EINVAL;
> +
> +	initrd_res = bootm_load_initrd(data, initrd_address, gap.end);
>  	if (IS_ERR(initrd_res)) {
>  		printf("Failed to load initrd\n");
>  		return PTR_ERR(initrd_res);
> @@ -93,9 +99,10 @@ static int do_boot_elf(struct image_data *data, struct elf_image *elf)
>  
>  	printf("Loading device tree at %lx\n", load_addr);
>  	/* load device tree after the initrd if any */
> -	ret = bootm_load_devicetree(data, fdt, load_addr);
> -	if (ret) {
> -		printf("Failed to load device tree: %d\n", ret);
> +	fdt_res = bootm_load_devicetree(data, fdt, load_addr, gap.end);
> +	if (IS_ERR(fdt_res)) {
> +		printf("Failed to load device tree: %pe\n", fdt_res);
> +		ret = PTR_ERR(fdt_res);
>  		goto err_free_fdt;
>  	}
>  
> diff --git a/arch/powerpc/lib/ppclinux.c b/arch/powerpc/lib/ppclinux.c
> index 564086482e5f..eda2539e6125 100644
> --- a/arch/powerpc/lib/ppclinux.c
> +++ b/arch/powerpc/lib/ppclinux.c
> @@ -7,6 +7,7 @@
>  #include <image.h>
>  #include <init.h>
>  #include <malloc.h>
> +#include <memory.h>
>  #include <environment.h>
>  #include <asm/bitops.h>
>  #include <asm/processor.h>
> @@ -53,12 +54,18 @@ static int do_bootm_linux(struct image_data *data)
>  {
>  	void	(*kernel)(void *, void *, unsigned long,
>  			unsigned long, unsigned long);
> +	const struct resource *os_res, *sdram;
> +	struct resource gap;
>  	int ret;
>  	struct fdt_header *fdt;
>  
> -	ret = bootm_load_os(data, data->os_address);
> -	if (ret)
> -		return ret;
> +	sdram = memory_bank_lookup_region(data->os_address, &gap);
> +	if (sdram != &gap)
> +		return sdram ? -EBUSY : -EINVAL;
> +
> +	os_res = bootm_load_os(data, data->os_address, gap.end);
> +	if (IS_ERR(os_res))
> +		return PTR_ERR(os_res);
>  
>  	fdt = of_get_fixed_tree_for_boot(data->of_root_node);
>  	if (!fdt) {
> diff --git a/common/booti.c b/common/booti.c
> index 6a87b84c0308..67f31b793517 100644
> --- a/common/booti.c
> +++ b/common/booti.c
> @@ -10,13 +10,14 @@
>  #include <linux/sizes.h>
>  
>  static unsigned long get_kernel_address(unsigned long os_address,
> -					unsigned long text_offset)
> +					unsigned long text_offset,
> +					resource_size_t *end)
>  {
> -	resource_size_t start, end;
> +	resource_size_t start;
>  	int ret;
>  
>  	if (!UIMAGE_IS_ADDRESS_VALID(os_address)) {
> -		ret = memory_bank_first_find_space(&start, &end);
> +		ret = memory_bank_first_find_space(&start, end);
>  		if (ret)
>  			return UIMAGE_INVALID_ADDRESS;
>  
> @@ -33,9 +34,10 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
>  {
>  	const void *kernel_header =
>  			data->os_fit ? data->fit_kernel : data->os_header;
> +	const struct resource *os_res;
>  	unsigned long text_offset, image_size, kernel;
>  	unsigned long image_end;
> -	int ret;
> +	resource_size_t end;
>  	void *fdt;
>  
>  	print_hex_dump_bytes("header ", DUMP_PREFIX_OFFSET, kernel_header, 80);
> @@ -49,24 +51,26 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
>  	text_offset = le64_to_cpup(kernel_header + 8);
>  	image_size = le64_to_cpup(kernel_header + 16);
>  
> -	kernel = get_kernel_address(data->os_address, text_offset);
> +	kernel = get_kernel_address(data->os_address, text_offset, &end);
>  
>  	pr_debug("Kernel to be loaded to %lx+%lx\n", kernel, image_size);
>  
>  	if (kernel == UIMAGE_INVALID_ADDRESS)
>  		return ERR_PTR(-ENOENT);
> +	if (kernel + image_size - 1 > end)
> +		return ERR_PTR(-ENOSPC);
>  
> -	ret = bootm_load_os(data, kernel);
> -	if (ret)
> -		return ERR_PTR(ret);
> +	os_res = bootm_load_os(data, kernel, end);
> +	if (IS_ERR(os_res))
> +		return ERR_CAST(os_res);
>  
>  	image_end = PAGE_ALIGN(kernel + image_size);
>  
>  	if (oftree) {
>  		unsigned long devicetree;
> -		const struct resource *initrd_res;
> +		const struct resource *initrd_res, *dt_res;
>  
> -		initrd_res = bootm_load_initrd(data, image_end);
> +		initrd_res = bootm_load_initrd(data, image_end, end);
>  		if (IS_ERR(initrd_res)) {
>  			return ERR_CAST(initrd_res);
>  		} else if (initrd_res) {
> @@ -85,11 +89,11 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
>  			goto out;
>  		}
>  
> -		ret = bootm_load_devicetree(data, fdt, devicetree);
> +		dt_res = bootm_load_devicetree(data, fdt, devicetree, end);
>  		free(fdt);
>  
> -		if (ret)
> -			return ERR_PTR(ret);
> +		if (IS_ERR(dt_res))
> +			return ERR_CAST(dt_res);
>  
>  		*oftree = devicetree;
>  	}
> diff --git a/common/bootm-mock.c b/common/bootm-mock.c
> new file mode 100644
> index 000000000000..e69de29bb2d1
> diff --git a/common/bootm.c b/common/bootm.c
> index 35305f25375a..fcf7868a5d75 100644
> --- a/common/bootm.c
> +++ b/common/bootm.c
> @@ -228,57 +228,69 @@ static bool bootm_get_override(char **oldpath, const char *newpath)
>  	return true;
>  }
>  
> -/*
> +/**
>   * bootm_load_os() - load OS to RAM
> - *
>   * @data:		image data context
>   * @load_address:	The address where the OS should be loaded to
> + * @end_address:	The end address of the load buffer (inclusive)
>   *
>   * This loads the OS to a RAM location. load_address must be a valid
> - * address. If the image_data doesn't have a OS specified it's considered
> + * address. If the image_data doesn't have an OS specified it's considered
>   * an error.
>   *
> - * Return: 0 on success, negative error code otherwise
> + * Return: the OS resource on success, or an error pointer on failure
>   */
> -int bootm_load_os(struct image_data *data, unsigned long load_address)
> +const struct resource *bootm_load_os(struct image_data *data,
> +		ulong load_address, ulong end_address)
>  {
> +	int err;
> +
>  	if (data->os_res)
> -		return 0;
> +		return data->os_res;
>  
>  	if (load_address == UIMAGE_INVALID_ADDRESS)
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
> +	if (end_address <= load_address)
> +		return ERR_PTR(-EINVAL);
>  
> -	if (data->os_fit)
> -		return bootm_load_fit_os(data, load_address);
> +	if (data->os_fit) {
> +		err = bootm_load_fit_os(data, load_address);
> +	} else if (image_is_uimage(data)) {
> +		err = bootm_load_uimage_os(data, load_address);
> +	} else if (data->os_file) {
> +		data->os_res = file_to_sdram(data->os_file, load_address, MEMTYPE_LOADER_CODE);
> +		err = data->os_res ? 0 : -EBUSY;
> +	} else {
> +		err = -EINVAL;
> +	}
>  
> -	if (image_is_uimage(data))
> -		return bootm_load_uimage_os(data, load_address);
> +	if (err)
> +		return ERR_PTR(err);
>  
> -	if (!data->os_file)
> -		return -EINVAL;
> +	/* FIXME: We need some more rework to be able to detect this overflow
> +	 * before it happens, but for now, let's at least detect it.
> +	 */
> +	if (WARN_ON(data->os_res->end > end_address))
> +		return ERR_PTR(-ENOSPC);
>  
> -	data->os_res = file_to_sdram(data->os_file, load_address, MEMTYPE_LOADER_CODE);
> -	if (!data->os_res)
> -		return -ENOMEM;
> -
> -	return 0;
> +	return data->os_res;
>  }
>  
> -/*
> +/**
>   * bootm_load_initrd() - load initrd to RAM
> - *
>   * @data:		image data context
>   * @load_address:	The address where the initrd should be loaded to
> + * @end_address:	The end address of the load buffer (inclusive)
>   *
>   * This loads the initrd to a RAM location. load_address must be a valid
> - * address. If the image_data doesn't have a initrd specified this function
> - * still returns successful as an initrd is optional. Check data->initrd_res
> - * to see if an initrd has been loaded.
> + * address. If the image_data doesn't have an initrd specified this function
> + * still returns successful as an initrd is optional.
>   *
> - * Return: 0 on success, negative error code otherwise
> + * Return: the initrd resource if one was loaded, NULL if no initrd was
> + *         specified, or an error pointer on failure
>   */
>  const struct resource *
> -bootm_load_initrd(struct image_data *data, unsigned long load_address)
> +bootm_load_initrd(struct image_data *data, ulong load_address, ulong end_address)
>  {
>  	struct resource *res = NULL;
>  	const char *initrd, *initrd_part = NULL;
> @@ -293,6 +305,8 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
>  	 */
>  	if (WARN_ON(data->initrd_res))
>  		return data->initrd_res;
> +	if (end_address <= load_address)
> +		return ERR_PTR(-EINVAL);
>  
>  	bootm_get_override(&data->initrd_file, bootm_overrides.initrd_file);
>  
> @@ -313,7 +327,7 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
>  
>  	} else if (initrd) {
>  		res = file_to_sdram(initrd, load_address, MEMTYPE_LOADER_DATA)
> -			?: ERR_PTR(-ENOMEM);
> +			?: ERR_PTR(-EBUSY);
>  
>  	} else if (data->os_fit) {
>  		res = bootm_load_fit_initrd(data, load_address);
> @@ -324,6 +338,12 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
>  	if (IS_ERR_OR_NULL(res))
>  		return res;
>  
> +	/* FIXME: We need some more rework to be able to detect this overflow
> +	 * before it happens, but for now, let's at least detect it.
> +	 */
> +	if (WARN_ON(data->initrd_res->end > end_address))
> +		return ERR_PTR(-ENOSPC);
> +
>  	pr_info("Loaded initrd from %s %s%s%s to %pa-%pa\n",
>  		file_type_to_string(type), initrd,
>  		initrd_part ? "@" : "", initrd_part ?: "",
> @@ -425,33 +445,38 @@ void *bootm_get_devicetree(struct image_data *data)
>  	return oftree;
>  }
>  
> -/*
> - * bootm_load_devicetree() - load devicetree
> - *
> +/**
> + * bootm_load_devicetree() - load devicetree into specified memory range
>   * @data:		image data context
>   * @fdt:		The flat device tree to load
>   * @load_address:	The address where the devicetree should be loaded to
> + * @end_address:	The end address of the load buffer (inclusive)
>   *
>   * This loads the devicetree to a RAM location. load_address must be a valid
>   * address which is requested with request_sdram_region. The associated region
>   * is released automatically in the bootm error path.
>   *
> - * Return: 0 on success, negative error code otherwise
> + * Return: the devicetree resource on success, or an error pointer on failure
>   */
> -int bootm_load_devicetree(struct image_data *data, void *fdt,
> -			    unsigned long load_address)
> +const struct resource *
> +bootm_load_devicetree(struct image_data *data, void *fdt,
> +		      ulong load_address, ulong end_address)
>  {
>  	int fdt_size;
>  
>  	if (!IS_ENABLED(CONFIG_OFTREE))
> -		return -ENOSYS;
> +		return ERR_PTR(-ENOSYS);
> +	if (end_address <= load_address)
> +		return ERR_PTR(-EINVAL);
>  
>  	fdt_size = be32_to_cpu(((struct fdt_header *)fdt)->totalsize);
> +	if (load_address + fdt_size - 1 > end_address)
> +		return ERR_PTR(-ENOSPC);
>  
>  	data->oftree_res = request_sdram_region("oftree", load_address,
>  			fdt_size, MEMTYPE_LOADER_DATA, MEMATTRS_RW);
>  	if (!data->oftree_res)
> -		return -ENOMEM;
> +		return ERR_PTR(-EBUSY);
>  
>  	memcpy((void *)data->oftree_res->start, fdt, fdt_size);
>  
> @@ -461,7 +486,7 @@ int bootm_load_devicetree(struct image_data *data, void *fdt,
>  		fdt_print_reserve_map(fdt);
>  	}
>  
> -	return 0;
> +	return data->oftree_res;
>  }
>  
>  int bootm_get_os_size(struct image_data *data)
> diff --git a/efi/loader/bootm.c b/efi/loader/bootm.c
> index da664847def8..b40263ce6eb3 100644
> --- a/efi/loader/bootm.c
> +++ b/efi/loader/bootm.c
> @@ -171,7 +171,8 @@ static efi_status_t efi_install_fdt(void *fdt)
>  static efi_status_t efi_install_initrd(struct image_data *data,
>  				       struct resource *source)
>  {
> -	const struct resource *initrd_res;
> +	const struct resource *initrd_res, *sdram;
> +	struct resource gap;
>  	unsigned long initrd_start;
>  
>  	if (!IS_ENABLED(CONFIG_BOOTM_INITRD))
> @@ -182,7 +183,11 @@ static efi_status_t efi_install_initrd(struct image_data *data,
>  	else
>  		initrd_start = EFI_PAGE_ALIGN(source->end + 1);
>  
> -	initrd_res = bootm_load_initrd(data, initrd_start);
> +	sdram = memory_bank_lookup_region(data->os_address, &gap);
> +	if (sdram != &gap)
> +		return sdram ? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER;
> +
> +	initrd_res = bootm_load_initrd(data, initrd_start, gap.end);
>  	if (IS_ERR(initrd_res))
>  		return PTR_ERR(initrd_res);
>  	if (initrd_res)
> diff --git a/include/bootm.h b/include/bootm.h
> index e56a999f0b11..1c3bb8899b38 100644
> --- a/include/bootm.h
> +++ b/include/bootm.h
> @@ -150,14 +150,19 @@ static inline int bootm_verbose(struct image_data *data)
>  void bootm_data_init_defaults(struct bootm_data *data);
>  void bootm_data_restore_defaults(const struct bootm_data *data);
>  
> -int bootm_load_os(struct image_data *data, unsigned long load_address);
> +const struct resource *
> +bootm_load_os(struct image_data *data,
> +	      ulong load_address, ulong end_address);
>  
>  const struct resource *
> -bootm_load_initrd(struct image_data *data, unsigned long load_address);
> +bootm_load_initrd(struct image_data *data,
> +		  ulong load_address, ulong end_address);
>  
>  void *bootm_get_devicetree(struct image_data *data);
> -int bootm_load_devicetree(struct image_data *data, void *fdt,
> -			  unsigned long load_address);
> +
> +const struct resource *
> +bootm_load_devicetree(struct image_data *data, void *fdt,
> +		      ulong load_address, ulong end_address);
>  int bootm_get_os_size(struct image_data *data);
>  
>  enum bootm_verify bootm_get_verify_mode(void);

-- 
Pengutronix e.K.                  |                             |
Steuerwalder Str. 21              | http://www.pengutronix.de/  |
31137 Hildesheim, Germany         | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |




More information about the barebox mailing list