Merge branch 'master' of git://git.denx.de/u-boot-spi
[platform/kernel/u-boot.git] / lib / efi_loader / efi_memory.c
index f225a90..4bb5174 100644 (file)
@@ -11,6 +11,7 @@
 #include <mapmem.h>
 #include <watchdog.h>
 #include <linux/list_sort.h>
+#include <linux/sizes.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -384,7 +385,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type,
                /* Reserve that map in our memory maps */
                ret = efi_add_memory_map(addr, pages, memory_type, true);
                if (ret == addr) {
-                       *memory = (uintptr_t)map_sysmem(addr, len);
+                       *memory = addr;
                } else {
                        /* Map would overlap, bail out */
                        r = EFI_OUT_OF_RESOURCES;
@@ -397,7 +398,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type,
 void *efi_alloc(uint64_t len, int memory_type)
 {
        uint64_t ret = 0;
-       uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+       uint64_t pages = efi_size_in_pages(len);
        efi_status_t r;
 
        r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages,
@@ -418,12 +419,11 @@ void *efi_alloc(uint64_t len, int memory_type)
 efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
 {
        uint64_t r = 0;
-       uint64_t addr = map_to_sysmem((void *)(uintptr_t)memory);
 
-       r = efi_add_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, false);
+       r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
        /* Merging of adjacent free regions is missing */
 
-       if (r == addr)
+       if (r == memory)
                return EFI_SUCCESS;
 
        return EFI_NOT_FOUND;
@@ -441,8 +441,8 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
 {
        efi_status_t r;
        struct efi_pool_allocation *alloc;
-       u64 num_pages = (size + sizeof(struct efi_pool_allocation) +
-                        EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+       u64 num_pages = efi_size_in_pages(size +
+                                         sizeof(struct efi_pool_allocation));
 
        if (!buffer)
                return EFI_INVALID_PARAMETER;
@@ -551,24 +551,50 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 
 __weak void efi_add_known_memory(void)
 {
+       u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK;
        int i;
 
+       /* Fix for 32bit targets with ram_top at 4G */
+       if (!ram_top)
+               ram_top = 0x100000000ULL;
+
        /* Add RAM */
        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
                u64 ram_end, ram_start, pages;
 
-               ram_start = gd->bd->bi_dram[i].start;
+               ram_start = (uintptr_t)map_sysmem(gd->bd->bi_dram[i].start, 0);
                ram_end = ram_start + gd->bd->bi_dram[i].size;
 
                /* Remove partial pages */
                ram_end &= ~EFI_PAGE_MASK;
                ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
 
-               if (ram_end > ram_start) {
-                       pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
+               if (ram_end <= ram_start) {
+                       /* Invalid mapping, keep going. */
+                       continue;
+               }
+
+               pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
 
+               efi_add_memory_map(ram_start, pages,
+                                  EFI_CONVENTIONAL_MEMORY, false);
+
+               /*
+                * Boards may indicate to the U-Boot memory core that they
+                * can not support memory above ram_top. Let's honor this
+                * in the efi_loader subsystem too by declaring any memory
+                * above ram_top as "already occupied by firmware".
+                */
+               if (ram_top < ram_start) {
+                       /* ram_top is before this region, reserve all */
                        efi_add_memory_map(ram_start, pages,
-                                          EFI_CONVENTIONAL_MEMORY, false);
+                                          EFI_BOOT_SERVICES_DATA, true);
+               } else if ((ram_top >= ram_start) && (ram_top < ram_end)) {
+                       /* ram_top is inside this region, reserve parts */
+                       pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
+
+                       efi_add_memory_map(ram_top, pages,
+                                          EFI_BOOT_SERVICES_DATA, true);
                }
        }
 }
@@ -577,6 +603,7 @@ __weak void efi_add_known_memory(void)
 static void add_u_boot_and_runtime(void)
 {
        unsigned long runtime_start, runtime_end, runtime_pages;
+       unsigned long runtime_mask = EFI_PAGE_MASK;
        unsigned long uboot_start, uboot_pages;
        unsigned long uboot_stack_size = 16 * 1024 * 1024;
 
@@ -585,10 +612,22 @@ static void add_u_boot_and_runtime(void)
        uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT;
        efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false);
 
-       /* Add Runtime Services */
-       runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK;
+#if defined(__aarch64__)
+       /*
+        * Runtime Services must be 64KiB aligned according to the
+        * "AArch64 Platforms" section in the UEFI spec (2.7+).
+        */
+
+       runtime_mask = SZ_64K - 1;
+#endif
+
+       /*
+        * Add Runtime Services. We mark surrounding boottime code as runtime as
+        * well to fulfill the runtime alignment constraints but avoid padding.
+        */
+       runtime_start = (ulong)&__efi_runtime_start & ~runtime_mask;
        runtime_end = (ulong)&__efi_runtime_stop;
-       runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+       runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
        runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
        efi_add_memory_map(runtime_start, runtime_pages,
                           EFI_RUNTIME_SERVICES_CODE, false);