summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/Makefile.version2
-rw-r--r--usr/src/boot/sys/boot/common/multiboot2.c48
2 files changed, 34 insertions, 16 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version
index 21a55e3451..3e19a7125b 100644
--- a/usr/src/boot/Makefile.version
+++ b/usr/src/boot/Makefile.version
@@ -33,4 +33,4 @@ LOADER_VERSION = 1.1
# Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes.
# The version is processed from left to right, the version number can only
# be increased.
-BOOT_VERSION = $(LOADER_VERSION)-2019.12.16.2
+BOOT_VERSION = $(LOADER_VERSION)-2019.12.16.3
diff --git a/usr/src/boot/sys/boot/common/multiboot2.c b/usr/src/boot/sys/boot/common/multiboot2.c
index f63c44c503..1139258200 100644
--- a/usr/src/boot/sys/boot/common/multiboot2.c
+++ b/usr/src/boot/sys/boot/common/multiboot2.c
@@ -54,6 +54,7 @@
#include "loader_efi.h"
static void (*trampoline)(uint32_t, struct relocator *, uint64_t);
+static UINTN efi_map_size; /* size of efi memory map */
#endif
#include "platform/acfreebsd.h"
@@ -682,6 +683,8 @@ module_size(struct preloaded_file *fp)
/*
* Calculate size for UEFI memory map tag.
*/
+#define EFI_EXTRA_PAGES 3
+
static int
efimemmap_size(void)
{
@@ -708,8 +711,9 @@ efimemmap_size(void)
}
/* EFI MMAP will grow when we allocate MBI, set some buffer. */
- size += (3 << EFI_PAGE_SHIFT);
- size = roundup(size, desc_size);
+ size += (EFI_EXTRA_PAGES << EFI_PAGE_SHIFT);
+ size = roundup2(size, EFI_PAGE_SIZE);
+ efi_map_size = size; /* Record the calculated size. */
return (sizeof (multiboot_tag_efi_mmap_t) + size);
}
#endif
@@ -1198,28 +1202,42 @@ multiboot2_exec(struct preloaded_file *fp)
error = EINVAL;
goto error;
}
- status = BS->GetMemoryMap(&map_size,
- (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
- &desc_size, &tag->mb_descr_vers);
- if (EFI_ERROR(status)) {
+ map_size = roundup2(map_size, EFI_PAGE_SIZE);
+
+ i = 2; /* Attempts to ExitBootServices() */
+ while (map_size <= efi_map_size && i > 0) {
+ status = BS->GetMemoryMap(&map_size,
+ (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
+ &desc_size, &tag->mb_descr_vers);
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ /* Still too small? */
+ map_size += EFI_PAGE_SIZE;
+ continue;
+ }
+ if (EFI_ERROR(status)) {
+ error = EINVAL;
+ goto error;
+ }
+
+ if (keep_bs != 0)
+ break;
+
+ status = BS->ExitBootServices(IH, key);
+ if (status == EFI_SUCCESS)
+ break;
+ i--;
+ }
+ if (status != EFI_SUCCESS) {
error = EINVAL;
goto error;
}
+
tag->mb_type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
tag->mb_size = sizeof (*tag) + map_size;
tag->mb_descr_size = (uint32_t)desc_size;
map = (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap;
- if (keep_bs == 0) {
- status = BS->ExitBootServices(IH, key);
- if (EFI_ERROR(status)) {
- printf("Call to ExitBootServices failed\n");
- error = EINVAL;
- goto error;
- }
- }
-
last_addr += map_size;
last_addr = roundup2(last_addr, MULTIBOOT_TAG_ALIGN);
}