Commit ad0c1a3d2cea03011091b07e9e066bf261d1556e

Authored by Alexander Graf
Committed by Tom Rini
1 parent 36c37a8481

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>
Tested-by: Andreas Färber <afaerber@suse.de>

Showing 1 changed file with 26 additions and 4 deletions Side-by-side Diff

... ... @@ -12,7 +12,7 @@
12 12 #include <errno.h>
13 13 #include <libfdt.h>
14 14 #include <libfdt_env.h>
15   -#include <malloc.h>
  15 +#include <memalign.h>
16 16 #include <asm/global_data.h>
17 17  
18 18 DECLARE_GLOBAL_DATA_PTR;
19 19  
20 20  
21 21  
... ... @@ -104,12 +104,34 @@
104 104 static void *copy_fdt(void *fdt)
105 105 {
106 106 u64 fdt_size = fdt_totalsize(fdt);
  107 + unsigned long fdt_ram_start = -1L, fdt_pages;
  108 + u64 new_fdt_addr;
107 109 void *new_fdt;
  110 + int i;
108 111  
109   - /* Give us 64kb breathing room */
110   - fdt_size += 64 * 1024;
  112 + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
  113 + u64 ram_start = gd->bd->bi_dram[i].start;
  114 + u64 ram_size = gd->bd->bi_dram[i].size;
111 115  
112   - new_fdt = malloc(fdt_size);
  116 + if (!ram_size)
  117 + continue;
  118 +
  119 + if (ram_start < fdt_ram_start)
  120 + fdt_ram_start = ram_start;
  121 + }
  122 +
  123 + /* Give us at least 4kb breathing room */
  124 + fdt_size = ALIGN(fdt_size + 4096, 4096);
  125 + fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
  126 +
  127 + /* Safe fdt location is at 128MB */
  128 + new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size;
  129 + if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages,
  130 + &new_fdt_addr) != EFI_SUCCESS) {
  131 + /* If we can't put it there, put it somewhere */
  132 + new_fdt_addr = (ulong)memalign(4096, fdt_size);
  133 + }
  134 + new_fdt = (void*)(ulong)new_fdt_addr;
113 135 memcpy(new_fdt, fdt, fdt_totalsize(fdt));
114 136 fdt_set_totalsize(new_fdt, fdt_size);
115 137