From 8a753b3f1cf5e4714974196df9517849bf174324 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Tue, 2 Jun 2015 13:44:24 +0200 Subject: [PATCH] efi: fix allocation problems if ExitBootServices() fails 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 Acked-by: Jan Beulich Reviewed-by: Roy Franz Acked-by: Ian Campbell --- xen/arch/arm/efi/efi-boot.h | 6 ++---- xen/arch/x86/efi/efi-boot.h | 4 ++-- xen/common/efi/boot.c | 8 +++++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h index b02cc02e75..3297f27684 100644 --- a/xen/arch/arm/efi/efi-boot.h +++ b/xen/arch/arm/efi/efi-boot.h @@ -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; } diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index 3a3b4fe3b8..cd14c19bf2 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -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; diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index ef8476c676..60c1b8dc32 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -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) ) -- 2.39.5