If calling ExitBootServices() fails, the memory map size may increase.
Allocate an extra page the first time around so that we hopefully
shouldn't have to reallocate the memory map. Allocate a new memory map
if needed, although this only a fallback, because some arches may use
boot services to allocate memory which may not work after the first call
to ExitBootServices().

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.lagerw...@citrix.com>
---
 xen/common/efi/boot.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index ef8476c..7d09b39 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 memmap_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,23 @@ 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_mdesc_size, &mdesc_ver);
-    efi_memmap = efi_arch_allocate_mmap_buffer(&efi_memmap_size);
-    if ( !efi_memmap )
-        blexit(L"Unable to allocate memory for EFI memory map");
-
     for ( retry = 0; ; retry = 1 )
     {
+        efi_bs->GetMemoryMap(&memmap_size, NULL, &map_key,
+                             &efi_mdesc_size, &mdesc_ver);
+        if ( memmap_size > efi_memmap_size )
+        {
+            efi_memmap_size = memmap_size + EFI_PAGE_SIZE;
+            efi_memmap = efi_arch_allocate_mmap_buffer(&efi_memmap_size);
+            if ( !efi_memmap )
+            {
+                if ( retry )
+                    PrintErr(L"Unable to allocate memory for EFI memory map");
+                else
+                    blexit(L"Unable to allocate memory for EFI memory map");
+            }
+        }
+
         status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key,
                                       &efi_mdesc_size, &mdesc_ver);
         if ( EFI_ERROR(status) )
-- 
2.1.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to