diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/boot/Makefile.version | 2 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/common/multiboot2.c | 48 |
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); } |
