efi: fix allocation problems if ExitBootServices() fails
authorRoss Lagerwall <ross.lagerwall@citrix.com>
Tue, 2 Jun 2015 11:44:24 +0000 (13:44 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 2 Jun 2015 11:44:24 +0000 (13:44 +0200)
If calling ExitBootServices() fails, the required memory map size may
have increased. When initially allocating the memory map, allocate a
slightly larger buffer (by an arbitrary 8 entries) to fix this.

The ARM code path was already allocating a larger buffer than required,
so this moves the code to be common for all architectures.

This was seen on the following machine when using the iscsidxe UEFI
driver. The machine would consistently fail the first call to
ExitBootServices().
System Information
        Manufacturer: Supermicro
        Product Name: X10SLE-F/HF
BIOS Information
        Vendor: American Megatrends Inc.
        Version: 2.00
        Release Date: 04/24/2014

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roy Franz <roy.franz@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
xen/arch/arm/efi/efi-boot.h
xen/arch/x86/efi/efi-boot.h
xen/common/efi/boot.c

index b02cc02e753138e915e68ac44fdf1f460027be1e..3297f276840d9f08374d46e7f1a6d1ef067c3ebd 100644 (file)
@@ -370,16 +370,14 @@ static void __init efi_arch_cfg_file_late(EFI_FILE_HANDLE dir_handle, char *sect
 {
 }
 
-static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size)
+static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
 {
     void *ptr;
     EFI_STATUS status;
-    UINTN map_size_alloc = *map_size + EFI_PAGE_SIZE;
 
-    status = efi_bs->AllocatePool(EfiLoaderData, map_size_alloc, &ptr);
+    status = efi_bs->AllocatePool(EfiLoaderData, map_size, &ptr);
     if ( status != EFI_SUCCESS )
         return NULL;
-    *map_size = map_size_alloc;
     return ptr;
 }
 
index 3a3b4fe3b88a64e5da128f043658b697736454d4..cd14c19bf23a6393a525f9b50b0b6e8331f326c1 100644 (file)
@@ -190,10 +190,10 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
 
 }
 
-static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size)
+static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
 {
     place_string(&mbi.mem_upper, NULL);
-    mbi.mem_upper -= *map_size;
+    mbi.mem_upper -= map_size;
     mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
     if ( mbi.mem_upper < xen_phys_start )
         return NULL;
index ef8476c67646bbb7a05ba91529637d8426eb9ee1..60c1b8dc3257c8396e1b96e69aed3faeb556ea60 100644 (file)
@@ -700,7 +700,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     EFI_STATUS status;
     unsigned int i, argc;
     CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
-    UINTN map_key, info_size, gop_mode = ~0;
+    UINTN map_alloc_size, map_key, info_size, gop_mode = ~0;
     EFI_HANDLE *handles = NULL;
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
     EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
@@ -1053,14 +1053,16 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
             efi_arch_video_init(gop, info_size, mode_info);
     }
 
-    efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key,
+    efi_bs->GetMemoryMap(&map_alloc_size, NULL, &map_key,
                          &efi_mdesc_size, &mdesc_ver);
-    efi_memmap = efi_arch_allocate_mmap_buffer(&efi_memmap_size);
+    map_alloc_size += 8 * efi_mdesc_size;
+    efi_memmap = efi_arch_allocate_mmap_buffer(map_alloc_size);
     if ( !efi_memmap )
         blexit(L"Unable to allocate memory for EFI memory map");
 
     for ( retry = 0; ; retry = 1 )
     {
+        efi_memmap_size = map_alloc_size;
         status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
                                       &efi_mdesc_size, &mdesc_ver);
         if ( EFI_ERROR(status) )