diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index c63cbc0..dc7d2d9 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -237,7 +237,8 @@ int fd, ret, swap = 0; struct zimage_header __header, *header; void *zimage; - u32 end; + u32 end, start; + size_t image_size; unsigned long load_address = data->os_address; unsigned long mem_start, mem_size, mem_free; @@ -245,23 +246,6 @@ if (ret) return ret; - if (load_address == UIMAGE_INVALID_ADDRESS) { - /* - * The kernel should stay in the first 128MiB of RAM, recommended - * is 32MiB into RAM so that relocation prior to decompression - * can be avoided. - */ - if (mem_size > SZ_64M) - data->os_address = mem_start + SZ_32M; - else - data->os_address = mem_start + SZ_8M; - - load_address = data->os_address; - if (bootm_verbose(data)) - printf("no os load address, defaulting to 0x%08lx\n", - load_address); - } - fd = open(data->os_file, O_RDONLY); if (fd < 0) { perror("open"); @@ -288,14 +272,33 @@ } end = header->end; + start = header->start; - if (swap) + if (swap) { end = swab32(end); + start = swab32(start); + } - data->os_res = request_sdram_region("zimage", load_address, end); + image_size = end - start; + + if (load_address == UIMAGE_INVALID_ADDRESS) { + /* + * Just use a conservative default of 4 times the size of the + * compressed image, to avoid the need for the kernel to + * relocate itself before decompression. + */ + data->os_address = mem_start + PAGE_ALIGN(image_size * 4); + + load_address = data->os_address; + if (bootm_verbose(data)) + printf("no os load address, defaulting to 0x%08lx\n", + load_address); + } + + data->os_res = request_sdram_region("zimage", load_address, image_size); if (!data->os_res) { pr_err("bootm/zImage: failed to request memory at 0x%lx to 0x%lx (%d).\n", - load_address, load_address + end, end); + load_address, load_address + image_size, image_size); ret = -ENOMEM; goto err_out; } @@ -304,7 +307,8 @@ memcpy(zimage, header, sizeof(*header)); - ret = read_full(fd, zimage + sizeof(*header), end - sizeof(*header)); + ret = read_full(fd, zimage + sizeof(*header), + image_size - sizeof(*header)); if (ret < 0) goto err_out; if (ret < end - sizeof(*header)) { @@ -326,13 +330,10 @@ close(fd); /* - * Put devicetree/initrd at maximum to 128MiB into RAM to not - * risk to put it outside of lowmem. + * put oftree/initrd close behind compressed kernel image to avoid + * placing it outside of the kernels lowmem. */ - if (mem_size > SZ_256M) - mem_free = mem_start + SZ_128M; - else - mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M); + mem_free = PAGE_ALIGN(data->os_res->end + SZ_1M); return __do_bootm_linux(data, mem_free, swap);