Request low-memory from UEFI and relocate.
Signed-off-by: Varad Gautam varadgautam@gmail.com --- A couple problems with the patch: * accessing `linux_banner` in `libstub/fdt.c:update_fdt` causes a Data Abort; need a better place to define it. * arch/arm/boot/compressed/head.S: jump to zImage `mov pc, r3` fails, although jump to hard-coded relocated address (`ldr pc, =0x80008000`) works, 0x80008000 being the new zImage location. Need help with calling convention - am I setting *image_addr correctly?
Thanks, Varad
arch/arm/boot/compressed/efi-stub.c | 64 ++++++++----------------------------- 1 file changed, 14 insertions(+), 50 deletions(-)
diff --git a/arch/arm/boot/compressed/efi-stub.c b/arch/arm/boot/compressed/efi-stub.c index 1341229..0364e95 100644 --- a/arch/arm/boot/compressed/efi-stub.c +++ b/arch/arm/boot/compressed/efi-stub.c @@ -21,10 +21,8 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, unsigned long dram_base, efi_loaded_image_t *image) { - unsigned long nr_pages; efi_status_t status; - /* Use alloc_addr to tranlsate between types */ - efi_physical_addr_t alloc_addr; + unsigned long kernel_size;
/* * Verify that the DRAM base address is compatible the the ARM @@ -38,55 +36,21 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, return EFI_LOAD_ERROR; }
- /* - * Reserve memory for the uncompressed kernel image. This is - * all that prevents any future allocations from conflicting - * with the kernel. Since we can't tell from the compressed - * image how much DRAM the kernel actually uses (due to BSS - * size uncertainty) we allocate the maximum possible size. - * Do this very early, as prints can cause memory allocations - * that may conflict with this. - */ - alloc_addr = dram_base; - *reserve_size = MAX_UNCOMP_KERNEL_SIZE; - nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; - status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, - EFI_LOADER_DATA, - nr_pages, &alloc_addr); - if (status != EFI_SUCCESS) { - *reserve_size = 0; - pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); - return status; - } - *reserve_addr = alloc_addr; - - /* - * Relocate the zImage, if required. ARM doesn't have a - * preferred address, so we set it to 0, as we want to allocate - * as low in memory as possible. - */ + /* Relocate the image, if required. */ *image_size = image->image_size; - status = efi_relocate_kernel(sys_table, image_addr, *image_size, - *image_size, 0, 0); - if (status != EFI_SUCCESS) { - pr_efi_err(sys_table, "Failed to relocate kernel.\n"); - efi_free(sys_table, *reserve_size, *reserve_addr); - *reserve_size = 0; - return status; + if (*image_addr != (dram_base + TEXT_OFFSET)) { + kernel_size = *image_size; + status = efi_low_alloc(sys_table, kernel_size + TEXT_OFFSET, + EFI_PAGE_SIZE, reserve_addr); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Failed to relocate kernel\n"); + return status; + } + memcpy((void *)(*reserve_addr + TEXT_OFFSET), image->image_base, + kernel_size); + *image_addr = *reserve_addr + TEXT_OFFSET; + *reserve_size = kernel_size + TEXT_OFFSET; }
- /* - * Check to see if we were able to allocate memory low enough - * in memory. The kernel determines the base of DRAM from the - * address at which the zImage is loaded. - */ - if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { - pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); - efi_free(sys_table, *reserve_size, *reserve_addr); - *reserve_size = 0; - efi_free(sys_table, *image_size, *image_addr); - *image_size = 0; - return EFI_LOAD_ERROR; - } return EFI_SUCCESS; }
On 11 January 2015 at 17:23, Varad Gautam varadgautam@gmail.com wrote:
Request low-memory from UEFI and relocate.
Signed-off-by: Varad Gautam varadgautam@gmail.com
A couple problems with the patch:
- accessing `linux_banner` in `libstub/fdt.c:update_fdt` causes a Data Abort; need a
better place to define it.
This is undoubtedly caused by the fact that the decompressor is built with -fPIC. This results in external references to go via a Global Offset Table (GOT) entry, which requires load time relocations as the GOT contains absolute addresses. You can try to work around this by adding a forward declaration
extern __attribute__((visibility("hidden"))) char const linux_banner[];
This will tell the compiler that the dependency will be fulfilled at link time (i.e., not by a shared library) so the emitted symbol reference will be PC relative.
- arch/arm/boot/compressed/head.S: jump to zImage `mov pc, r3` fails, although jump
to hard-coded relocated address (`ldr pc, =0x80008000`) works, 0x80008000 being the new zImage location. Need help with calling convention - am I setting *image_addr correctly?
I am not sure if I understand the purpose of this patch: the decompressor is position independent, so the best place to load it is between 32 MB and 128 MB from the base of DRAM. If you load it way at the beginning, the first thing zImage needs to do when executed is relocate itself /again/ so it can make room for its uncompressed self at the base of DRAM.
On 01/12/15 at 08:06 AM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 11 January 2015 at 17:23, Varad Gautam varadgautam@gmail.com wrote:
A couple problems with the patch:
- accessing `linux_banner` in `libstub/fdt.c:update_fdt` causes a Data
Abort; need a better place to define it.
This is undoubtedly caused by the fact that the decompressor is built with -fPIC. This results in external references to go via a Global Offset Table (GOT) entry, which requires load time relocations as the GOT contains absolute addresses. You can try to work around this by adding a forward declaration
extern __attribute__((visibility("hidden"))) char const linux_banner[];
This will tell the compiler that the dependency will be fulfilled at link time (i.e., not by a shared library) so the emitted symbol reference will be PC relative.
Thanks, that fixed it.
- arch/arm/boot/compressed/head.S: jump to zImage `mov pc, r3` fails,
although jump to hard-coded relocated address (`ldr pc, =0x80008000`) works, 0x80008000 being the new zImage location. Need help with calling convention - am I setting *image_addr correctly?
I am not sure if I understand the purpose of this patch: the decompressor is position independent, so the best place to load it is between 32 MB and 128 MB from the base of DRAM. If you load it way at the beginning, the first thing zImage needs to do when executed is relocate itself /again/ so it can make room for its uncompressed self at the base of DRAM.
The current implementation fails in `handle_kernel_image()` when UEFI finds a discontinuity in the memory map during `allocate_pages()`[1]. This patch reserves a low / available memory range for the uncompressed image and copies zImage, similar to the arm64 stub; but I see that this could cause problems during decompression and that zImage would need to be relocated once again.
How does the decompressor identify the memory region it must write to? Is it set to ZRELADDR?
Thanks, Varad
On 19 January 2015 at 17:09, Varad Gautam varadgautam@gmail.com wrote:
On 01/12/15 at 08:06 AM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 11 January 2015 at 17:23, Varad Gautam varadgautam@gmail.com wrote:
A couple problems with the patch:
- accessing `linux_banner` in `libstub/fdt.c:update_fdt` causes a Data
Abort; need a better place to define it.
This is undoubtedly caused by the fact that the decompressor is built with -fPIC. This results in external references to go via a Global Offset Table (GOT) entry, which requires load time relocations as the GOT contains absolute addresses. You can try to work around this by adding a forward declaration
extern __attribute__((visibility("hidden"))) char const linux_banner[];
This will tell the compiler that the dependency will be fulfilled at link time (i.e., not by a shared library) so the emitted symbol reference will be PC relative.
Thanks, that fixed it.
Good!
- arch/arm/boot/compressed/head.S: jump to zImage `mov pc, r3` fails,
although jump to hard-coded relocated address (`ldr pc, =0x80008000`) works, 0x80008000 being the new zImage location. Need help with calling convention - am I setting *image_addr correctly?
I am not sure if I understand the purpose of this patch: the decompressor is position independent, so the best place to load it is between 32 MB and 128 MB from the base of DRAM. If you load it way at the beginning, the first thing zImage needs to do when executed is relocate itself /again/ so it can make room for its uncompressed self at the base of DRAM.
The current implementation fails in `handle_kernel_image()` when UEFI finds a discontinuity in the memory map during `allocate_pages()`[1]. This patch
Footnote?
reserves a low / available memory range for the uncompressed image and copies zImage, similar to the arm64 stub; but I see that this could cause problems during decompression and that zImage would need to be relocated once again.
How does the decompressor identify the memory region it must write to? Is it set to ZRELADDR?
I am not exactly sure, but as far as I know it just rounds down from its current offset, hence the requirement to load in the first 128 megs (or you will lose 128 megs of memory)
On 01/19/15 at 05:21 PM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
The current implementation fails in `handle_kernel_image()` when UEFI finds a discontinuity in the memory map during `allocate_pages()`[1]. This patch
Footnote?
:) http://lists.linaro.org/pipermail/linaro-uefi/2015-January/000645.html
Thanks, Varad
On 19 January 2015 at 17:28, Varad Gautam varadgautam@gmail.com wrote:
On 01/19/15 at 05:21 PM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
The current implementation fails in `handle_kernel_image()` when UEFI finds a discontinuity in the memory map during `allocate_pages()`[1]. This patch
Footnote?
:) http://lists.linaro.org/pipermail/linaro-uefi/2015-January/000645.html
The current ARM port in Tianocore does not deal very well with a flash device in RAM. It assumes you are shadowing from flash if it detects that PrePi is running from RAM.
I hit something similar here https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/commit/470ecd1480...
So how do you load the UEFI image?
On 01/19/15 at 05:33 PM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
The current ARM port in Tianocore does not deal very well with a flash device in RAM. It assumes you are shadowing from flash if it detects that PrePi is running from RAM.
I hit something similar here https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/commit/470ecd1480 880a80bbb29077a22a3e640d9633f7
So how do you load the UEFI image?
I'm using U-Boot's SPL as the primary loader which places UEFI image at 0x80800000, making this set of addresses unavailable to the OS loader.
Would exempting this shadowed memory from initial allocation to let the kernel decompress someplace else and takeover the entire RAM work?
Thanks, Varad
On 19 January 2015 at 17:57, Varad Gautam varadgautam@gmail.com wrote:
On 01/19/15 at 05:33 PM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
The current ARM port in Tianocore does not deal very well with a flash device in RAM. It assumes you are shadowing from flash if it detects that PrePi is running from RAM.
I hit something similar here https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/commit/470ecd1480 880a80bbb29077a22a3e640d9633f7
So how do you load the UEFI image?
I'm using U-Boot's SPL as the primary loader which places UEFI image at 0x80800000, making this set of addresses unavailable to the OS loader.
Well, the point is that once the DXE phase executes, the original FD is not used anymore, so it should be safe to release that memory.
Would exempting this shadowed memory from initial allocation to let the kernel decompress someplace else and takeover the entire RAM work?
No, because it will still be missing from the memory map, so the kernel would not be able to use it.
On 01/20/15 at 10:34 AM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 19 January 2015 at 17:57, Varad Gautam varadgautam@gmail.com wrote:
On 01/19/15 at 05:33 PM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
The current ARM port in Tianocore does not deal very well with a flash device in RAM. It assumes you are shadowing from flash if it detects that PrePi is running from RAM.
I hit something similar here https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/commit/470ecd1 480 880a80bbb29077a22a3e640d9633f7
So how do you load the UEFI image?
I'm using U-Boot's SPL as the primary loader which places UEFI image at 0x80800000, making this set of addresses unavailable to the OS loader.
Well, the point is that once the DXE phase executes, the original FD is not used anymore, so it should be safe to release that memory.
I'm going ahead with using the non-shadowing MemoryInitPeiLib implementation for BeagleBone Black. Do you plan to make it a part of ArmPlatformPkg?
Thanks, Varad
On 22 January 2015 at 08:30, Varad Gautam varadgautam@gmail.com wrote:
On 01/20/15 at 10:34 AM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 19 January 2015 at 17:57, Varad Gautam varadgautam@gmail.com wrote:
On 01/19/15 at 05:33 PM Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
The current ARM port in Tianocore does not deal very well with a flash device in RAM. It assumes you are shadowing from flash if it detects that PrePi is running from RAM.
I hit something similar here https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/commit/470ecd1 480 880a80bbb29077a22a3e640d9633f7
So how do you load the UEFI image?
I'm using U-Boot's SPL as the primary loader which places UEFI image at 0x80800000, making this set of addresses unavailable to the OS loader.
Well, the point is that once the DXE phase executes, the original FD is not used anymore, so it should be safe to release that memory.
I'm going ahead with using the non-shadowing MemoryInitPeiLib implementation for BeagleBone Black. Do you plan to make it a part of ArmPlatformPkg?
I plan to propose it upstream, as I need it for the Xen port myself, but whether it will be accepted is tbd. It also depends on whether my observation above (that the FD is not referenced anymore once DXE starts) is correct.
I guess the reason why I initially did this 'hack' (mark the DRAM occupied by the FD as non-present) is because the DXE (or something else) was copying over the FD during the dispatching of the UEFI drivers. You might not see this issue with your implementation of MemoryInitPeiLib because UEFI drivers will be loaded way above the FD file. But the risk might still exist - except if the DXE core now takes care of this case.
-----Original Message----- From: linaro-uefi-bounces@lists.linaro.org [mailto:linaro-uefi- bounces@lists.linaro.org] On Behalf Of Ard Biesheuvel Sent: 19 January 2015 17:34 To: Varad Gautam Cc: Linaro UEFI Mailman List Subject: Re: [Linaro-uefi] [RFC] arm: efi: handle zImage relocation
On 19 January 2015 at 17:28, Varad Gautam varadgautam@gmail.com wrote:
On 01/19/15 at 05:21 PM Ard Biesheuvel ard.biesheuvel@linaro.org
wrote:
The current implementation fails in `handle_kernel_image()` when
UEFI
finds a discontinuity in the memory map during
`allocate_pages()`[1].
This patch
Footnote?
January/000645.html
The current ARM port in Tianocore does not deal very well with a flash device in RAM. It assumes you are shadowing from flash if it detects that PrePi is running from RAM.
I hit something similar here https://git.linaro.org/people/ard.biesheuvel/uefi- next.git/commit/470ecd1480880a80bbb29077a22a3e640d9633f7
So how do you load the UEFI image?
Linaro-uefi mailing list Linaro-uefi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-uefi