2#ifndef PEDIGREE_UEFI_EXIT_BOOT_SERVICES_H
3#define PEDIGREE_UEFI_EXIT_BOOT_SERVICES_H
6typedef uintptr_t efi_status_t;
7typedef void* efi_handle_t;
8typedef efi_status_t (*efi_get_memory_map_t)(uintptr_t*,
void*, uintptr_t*, uintptr_t*, uint32_t*);
9typedef efi_status_t (*efi_exit_boot_services_t)(efi_handle_t, uintptr_t);
14 uint64_t physical_start;
15 uint64_t virtual_start;
16 uint64_t number_of_pages;
28 "bootstrap memory-map entries must match the kernel ABI");
31#define EFI_ERROR_BIT ((uintptr_t)1 << (sizeof(uintptr_t) * 8 - 1))
32#define EFI_LOAD_ERROR (EFI_ERROR_BIT | 1)
33#define EFI_INVALID_PARAMETER (EFI_ERROR_BIT | 2)
34#define EFI_BUFFER_TOO_SMALL (EFI_ERROR_BIT | 5)
35#define EFI_EXIT_BOOT_SERVICES_ATTEMPTS 4
37static uint32_t normalized_type(uint32_t type) {
47static efi_status_t exit_boot_services_with_map(
48 efi_get_memory_map_t get_map, efi_exit_boot_services_t exit_services, efi_handle_t image,
50 uintptr_t normalized_capacity, uint32_t* normalized_bytes,
int* exit_attempted) {
51 *normalized_bytes = 0;
53 for (
unsigned attempt = 0; attempt < EFI_EXIT_BOOT_SERVICES_ATTEMPTS; ++attempt) {
54 uintptr_t map_size = raw_capacity;
55 uintptr_t map_key = 0;
56 uintptr_t descriptor_size = 0;
57 uint32_t descriptor_version = 0;
59 get_map(&map_size, raw_map, &map_key, &descriptor_size, &descriptor_version);
60 if (status != EFI_SUCCESS)
62 if (!map_size || map_size > raw_capacity || descriptor_version != 1 ||
64 map_size % descriptor_size)
65 return EFI_LOAD_ERROR;
66 const uint64_t count = map_size / descriptor_size;
67 if (count > normalized_capacity /
sizeof(*normalized_map) ||
68 count > UINT32_MAX /
sizeof(*normalized_map))
69 return EFI_LOAD_ERROR;
70 for (uint64_t i = 0; i < count; ++i) {
73 if ((source->physical_start & 4095U) || source->number_of_pages > UINT64_MAX / 4096U ||
74 source->number_of_pages * 4096U > UINT64_MAX - source->physical_start)
75 return EFI_LOAD_ERROR;
77 destination->size =
sizeof(*destination) -
sizeof(destination->size);
78 destination->address = source->physical_start;
79 destination->length = source->number_of_pages * 4096U;
80 destination->type = normalized_type(source->type);
85 status = exit_services(image, map_key);
86 if (status == EFI_SUCCESS) {
87 *normalized_bytes = (uint32_t)(count *
sizeof(*normalized_map));
90 if (status != EFI_INVALID_PARAMETER)
93 return EFI_INVALID_PARAMETER;