[U-Boot] [PATCH 1/2] efi_loader: Put fdt into convenient location

The uEFI spec doesn't dictate where the device tree should live at, but legacy 32bit ARM grub2 has some assumptions that it may stay at its place when it's already loaded by the firmware.
So let's put it somewhere where Linux that comes after would happily find it - around the recommended 128MB line.
Signed-off-by: Alexander Graf agraf@suse.de --- cmd/bootefi.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 9b8af65..b213ef1 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -12,7 +12,7 @@ #include <errno.h> #include <libfdt.h> #include <libfdt_env.h> -#include <malloc.h> +#include <memalign.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR; @@ -104,12 +104,34 @@ static struct efi_object bootefi_device_obj = { static void *copy_fdt(void *fdt) { u64 fdt_size = fdt_totalsize(fdt); + unsigned long fdt_ram_start = -1L, fdt_pages; + u64 new_fdt_addr; void *new_fdt; + int i;
- /* Give us 64kb breathing room */ - fdt_size += 64 * 1024; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + u64 ram_start = gd->bd->bi_dram[i].start; + u64 ram_size = gd->bd->bi_dram[i].size;
- new_fdt = malloc(fdt_size); + if (!ram_size) + continue; + + if (ram_start < fdt_ram_start) + fdt_ram_start = ram_start; + } + + /* Give us at least 4kb breathing room */ + fdt_size = ALIGN(fdt_size + 4096, 4096); + fdt_pages = fdt_size >> EFI_PAGE_SHIFT; + + /* Safe fdt location is at 128MB */ + new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size; + if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages, + &new_fdt_addr) != EFI_SUCCESS) { + /* If we can't put it there, put it somewhere */ + new_fdt_addr = (ulong)memalign(4096, fdt_size); + } + new_fdt = (void*)(ulong)new_fdt_addr; memcpy(new_fdt, fdt, fdt_totalsize(fdt)); fdt_set_totalsize(new_fdt, fdt_size);

The EFI memory map does not need to be in a strict order, but 32bit grub2 does expect it to be ascending. If it's not, it may try to allocate memory inside the U-Boot data memory region.
We already sort the memory map in descending order, so let's just reverse it when we pass it to a payload.
Signed-off-by: Alexander Graf agraf@suse.de --- lib/efi_loader/efi_memory.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 8a1e249..df99585 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -286,10 +286,13 @@ efi_status_t efi_get_memory_map(unsigned long *memory_map_size, uint32_t *descriptor_version) { ulong map_size = 0; + int map_entries = 0; struct list_head *lhandle;
list_for_each(lhandle, &efi_mem) - map_size += sizeof(struct efi_mem_desc); + map_entries++; + + map_size = map_entries * sizeof(struct efi_mem_desc);
*memory_map_size = map_size;
@@ -301,12 +304,14 @@ efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
/* Copy list into array */ if (memory_map) { + /* Return the list in ascending order */ + memory_map = &memory_map[map_entries - 1]; list_for_each(lhandle, &efi_mem) { struct efi_mem_list *lmem;
lmem = list_entry(lhandle, struct efi_mem_list, link); *memory_map = lmem->desc; - memory_map++; + memory_map--; } }

Am 11.04.2016 um 23:51 schrieb Alexander Graf:
The EFI memory map does not need to be in a strict order, but 32bit grub2 does expect it to be ascending. If it's not, it may try to allocate memory inside the U-Boot data memory region.
We already sort the memory map in descending order, so let's just reverse it when we pass it to a payload.
Signed-off-by: Alexander Graf agraf@suse.de
Tested-by: Andreas Färber afaerber@suse.de
This fixed clearfog for me.
Thanks, Andreas

On Mon, Apr 11, 2016 at 11:51:02PM +0200, Alexander Graf wrote:
The EFI memory map does not need to be in a strict order, but 32bit grub2 does expect it to be ascending. If it's not, it may try to allocate memory inside the U-Boot data memory region.
We already sort the memory map in descending order, so let's just reverse it when we pass it to a payload.
Signed-off-by: Alexander Graf agraf@suse.de Tested-by: Andreas Färber afaerber@suse.de
Applied to u-boot/master, thanks!

Am 11.04.2016 um 23:51 schrieb Alexander Graf:
The uEFI spec doesn't dictate where the device tree should live at, but legacy 32bit ARM grub2 has some assumptions that it may stay at its place when it's already loaded by the firmware.
So let's put it somewhere where Linux that comes after would happily find it - around the recommended 128MB line.
Signed-off-by: Alexander Graf agraf@suse.de
Tested-by: Andreas Färber afaerber@suse.de
It definitely avoids a warning message. However, it does not always allow Linux to actually boot, e.g. on jetson-tk1 (patch sent).
Regards, Andreas

Am 13.04.2016 um 14:51 schrieb Andreas Färber:
Am 11.04.2016 um 23:51 schrieb Alexander Graf:
The uEFI spec doesn't dictate where the device tree should live at, but legacy 32bit ARM grub2 has some assumptions that it may stay at its place when it's already loaded by the firmware.
So let's put it somewhere where Linux that comes after would happily find it - around the recommended 128MB line.
Signed-off-by: Alexander Graf agraf@suse.de
Tested-by: Andreas Färber afaerber@suse.de
It definitely avoids a warning message. However, it does not always allow Linux to actually boot, e.g. on jetson-tk1 (patch sent).
Err, wrong patch for comment but still tested. :)
Andreas

On Mon, Apr 11, 2016 at 11:51:01PM +0200, Alexander Graf wrote:
The uEFI spec doesn't dictate where the device tree should live at, but legacy 32bit ARM grub2 has some assumptions that it may stay at its place when it's already loaded by the firmware.
So let's put it somewhere where Linux that comes after would happily find it - around the recommended 128MB line.
Signed-off-by: Alexander Graf agraf@suse.de Tested-by: Andreas Färber afaerber@suse.de
Applied to u-boot/master, thanks!
participants (3)
-
Alexander Graf
-
Andreas Färber
-
Tom Rini