- /* terminate bootservices */
- status = BS->ExitBootServices(image, cookie);
- if (EFI_ERROR(status)) goto bad_exit;
+ /* terminate bootservices
+ * efi ExitBootSvcs spec: *note, get_memmap is called by create_boot_params()
+ * An EFI OS loader must ensure that it has the system's current memory map at the time
+ * it calls ExitBootServices(). This is done by passing in the current memory map's
+ * MapKey value as returned by GetMemoryMap(). Care must be taken to ensure that the
+ * memory map does not change between these two calls. It is suggested that
+ * GetMemoryMap()be called immediately before calling ExitBootServices(). */
+
+retry:
+ status = uefi_call_wrapper(BS->ExitBootServices, 2, image, cookie);
+ if (EFI_ERROR(status))
+ {
+ ERR_PRT((L"\nExitBootSvcs: failed, memory map has changed.\n"));
+ if (retries < 2)
+ {
+ ERR_PRT((L"Main_Loop: Retrying,... have to rebuild boot params"));
+ retries++;
+ free_boot_params(bp);
+ if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
+ goto retry;
+ } else {
+ ERR_PRT((L"\nMain_Loop: tried ExitBootSvcs 3 times... retries exceeded.... giving up\n"));
+ goto bad_exit;
+ }
+ }
+