/* * EFI-related functions to set up and run test cases in EFI * * Copyright (c) 2021, SUSE, Varad Gautam * Copyright (c) 2021, Google Inc, Zixuan Wang * * SPDX-License-Identifier: LGPL-2.0-or-later */ #include "efi.h" #include #include /* From lib/argv.c */ extern int __argc, __envc; extern char *__argv[100]; extern char *__environ[200]; extern int main(int argc, char **argv, char **envp); efi_system_table_t *efi_system_table = NULL; static void efi_free_pool(void *ptr) { efi_bs_call(free_pool, ptr); } efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) { efi_memory_desc_t *m = NULL; efi_status_t status; unsigned long key = 0, map_size = 0, desc_size = 0; u32 desc_ver; status = efi_bs_call(get_memory_map, &map_size, NULL, &key, &desc_size, &desc_ver); if (status != EFI_BUFFER_TOO_SMALL || map_size == 0) goto out; /* * Pad map_size with additional descriptors so we don't need to * retry. */ map_size += 4 * desc_size; *map->buff_size = map_size; status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, map_size, (void **)&m); if (status != EFI_SUCCESS) goto out; /* Get the map. */ status = efi_bs_call(get_memory_map, &map_size, m, &key, &desc_size, &desc_ver); if (status != EFI_SUCCESS) { efi_free_pool(m); goto out; } *map->desc_ver = desc_ver; *map->desc_size = desc_size; *map->map_size = map_size; *map->key_ptr = key; out: *map->map = m; return status; } efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey) { return efi_bs_call(exit_boot_services, handle, mapkey); } efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) { int ret; unsigned long mapkey = 0; efi_status_t status; efi_bootinfo_t efi_bootinfo; efi_system_table = sys_tab; setup_efi_bootinfo(&efi_bootinfo); status = setup_efi_pre_boot(&mapkey, &efi_bootinfo); if (status != EFI_SUCCESS) { printf("Failed to set up before ExitBootServices, exiting.\n"); return status; } status = efi_exit_boot_services(handle, mapkey); if (status != EFI_SUCCESS) { printf("Failed to exit boot services\n"); return status; } setup_efi(&efi_bootinfo); ret = main(__argc, __argv, __environ); exit(ret); /* Shutdown the guest VM in case exit() fails */ efi_rs_call(reset_system, EFI_RESET_SHUTDOWN, ret, 0, NULL); /* Unreachable */ return EFI_UNSUPPORTED; }