efi_loader: Expose U-Boot addresses in memory map for sandbox
authorAlexander Graf <agraf@suse.de>
Mon, 18 Jun 2018 15:23:15 +0000 (17:23 +0200)
committerAlexander Graf <agraf@suse.de>
Wed, 25 Jul 2018 12:57:44 +0000 (14:57 +0200)
We currently expose host addresses in the EFI memory map. That can be
bad if we ever want to use sandbox to boot strap a real kernel, because
then the kernel would fetch its memory table from our host virtual address
map. But to make that use case work, we would need to have full control
over the address space the EFI application sees.

So let's expose only U-Boot addresses to the guest until we get to the
point of allocation. EFI's allocation functions are fun - they can take
U-Boot addresses as input values for hints and return host addresses as
allocation results through the same uint64_t * parameter. So we need to
be extra careful on what to pass in when.

With this patch I am successfully able to run the efi selftest suite as
well as grub.efi on aarch64.

Signed-off-by: Alexander Graf <agraf@suse.de>
lib/efi_loader/efi_memory.c

index d533aeeab730a453c7c830eabab7dac091d6ba6a..86edfc95f421c0195fd6a8f218dec98f080b2c9d 100644 (file)
@@ -9,6 +9,7 @@
 #include <efi_loader.h>
 #include <inttypes.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <watchdog.h>
 #include <linux/list_sort.h>
 
@@ -325,7 +326,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 = addr;
+                       *memory = (uintptr_t)map_sysmem(addr, len);
                } else {
                        /* Map would overlap, bail out */
                        r = EFI_OUT_OF_RESOURCES;
@@ -359,11 +360,12 @@ 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(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+       r = efi_add_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, false);
        /* Merging of adjacent free regions is missing */
 
-       if (r == memory)
+       if (r == addr)
                return EFI_SUCCESS;
 
        return EFI_NOT_FOUND;
@@ -380,7 +382,7 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
 efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
 {
        efi_status_t r;
-       efi_physical_addr_t t;
+       struct efi_pool_allocation *alloc;
        u64 num_pages = (size + sizeof(struct efi_pool_allocation) +
                         EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
 
@@ -390,10 +392,9 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
        }
 
        r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, pool_type, num_pages,
-                              &t);
+                              (uint64_t *)&alloc);
 
        if (r == EFI_SUCCESS) {
-               struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
                alloc->num_pages = num_pages;
                *buffer = alloc->data;
        }