10eaa5176SVarad Gautam /* 20eaa5176SVarad Gautam * EFI-related functions to set up and run test cases in EFI 30eaa5176SVarad Gautam * 40eaa5176SVarad Gautam * Copyright (c) 2021, SUSE, Varad Gautam <varad.gautam@suse.com> 5ad5fb883SZixuan Wang * Copyright (c) 2021, Google Inc, Zixuan Wang <zixuanwang@google.com> 60eaa5176SVarad Gautam * 70eaa5176SVarad Gautam * SPDX-License-Identifier: LGPL-2.0-or-later 80eaa5176SVarad Gautam */ 90eaa5176SVarad Gautam 10ad5fb883SZixuan Wang #include "efi.h" 11ad5fb883SZixuan Wang #include <libcflat.h> 12ad5fb883SZixuan Wang #include <asm/setup.h> 13ad5fb883SZixuan Wang 14ad5fb883SZixuan Wang /* From lib/argv.c */ 15ad5fb883SZixuan Wang extern int __argc, __envc; 16ad5fb883SZixuan Wang extern char *__argv[100]; 17ad5fb883SZixuan Wang extern char *__environ[200]; 18ad5fb883SZixuan Wang 19ad5fb883SZixuan Wang extern int main(int argc, char **argv, char **envp); 20ad5fb883SZixuan Wang 210eaa5176SVarad Gautam efi_system_table_t *efi_system_table = NULL; 220eaa5176SVarad Gautam 230eaa5176SVarad Gautam static void efi_free_pool(void *ptr) 240eaa5176SVarad Gautam { 250eaa5176SVarad Gautam efi_bs_call(free_pool, ptr); 260eaa5176SVarad Gautam } 270eaa5176SVarad Gautam 28ad5fb883SZixuan Wang efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) 290eaa5176SVarad Gautam { 300eaa5176SVarad Gautam efi_memory_desc_t *m = NULL; 310eaa5176SVarad Gautam efi_status_t status; 320eaa5176SVarad Gautam unsigned long key = 0, map_size = 0, desc_size = 0; 33*1ae9072eSZixuan Wang u32 desc_ver; 340eaa5176SVarad Gautam 350eaa5176SVarad Gautam status = efi_bs_call(get_memory_map, &map_size, 36*1ae9072eSZixuan Wang NULL, &key, &desc_size, &desc_ver); 370eaa5176SVarad Gautam if (status != EFI_BUFFER_TOO_SMALL || map_size == 0) 380eaa5176SVarad Gautam goto out; 390eaa5176SVarad Gautam 400eaa5176SVarad Gautam /* 410eaa5176SVarad Gautam * Pad map_size with additional descriptors so we don't need to 420eaa5176SVarad Gautam * retry. 430eaa5176SVarad Gautam */ 440eaa5176SVarad Gautam map_size += 4 * desc_size; 450eaa5176SVarad Gautam *map->buff_size = map_size; 460eaa5176SVarad Gautam status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, 470eaa5176SVarad Gautam map_size, (void **)&m); 480eaa5176SVarad Gautam if (status != EFI_SUCCESS) 490eaa5176SVarad Gautam goto out; 500eaa5176SVarad Gautam 510eaa5176SVarad Gautam /* Get the map. */ 520eaa5176SVarad Gautam status = efi_bs_call(get_memory_map, &map_size, 53*1ae9072eSZixuan Wang m, &key, &desc_size, &desc_ver); 540eaa5176SVarad Gautam if (status != EFI_SUCCESS) { 550eaa5176SVarad Gautam efi_free_pool(m); 560eaa5176SVarad Gautam goto out; 570eaa5176SVarad Gautam } 580eaa5176SVarad Gautam 59*1ae9072eSZixuan Wang *map->desc_ver = desc_ver; 600eaa5176SVarad Gautam *map->desc_size = desc_size; 610eaa5176SVarad Gautam *map->map_size = map_size; 620eaa5176SVarad Gautam *map->key_ptr = key; 630eaa5176SVarad Gautam out: 640eaa5176SVarad Gautam *map->map = m; 650eaa5176SVarad Gautam return status; 660eaa5176SVarad Gautam } 670eaa5176SVarad Gautam 68*1ae9072eSZixuan Wang efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey) 690eaa5176SVarad Gautam { 70*1ae9072eSZixuan Wang return efi_bs_call(exit_boot_services, handle, mapkey); 710eaa5176SVarad Gautam } 720eaa5176SVarad Gautam 73ad5fb883SZixuan Wang efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) 740eaa5176SVarad Gautam { 75ad5fb883SZixuan Wang int ret; 76*1ae9072eSZixuan Wang unsigned long mapkey = 0; 77*1ae9072eSZixuan Wang efi_status_t status; 78*1ae9072eSZixuan Wang efi_bootinfo_t efi_bootinfo; 79ad5fb883SZixuan Wang 800eaa5176SVarad Gautam efi_system_table = sys_tab; 810eaa5176SVarad Gautam 82*1ae9072eSZixuan Wang setup_efi_bootinfo(&efi_bootinfo); 83*1ae9072eSZixuan Wang status = setup_efi_pre_boot(&mapkey, &efi_bootinfo); 84*1ae9072eSZixuan Wang if (status != EFI_SUCCESS) { 85*1ae9072eSZixuan Wang printf("Failed to set up before ExitBootServices, exiting.\n"); 86*1ae9072eSZixuan Wang return status; 87*1ae9072eSZixuan Wang } 88*1ae9072eSZixuan Wang 89*1ae9072eSZixuan Wang status = efi_exit_boot_services(handle, mapkey); 90*1ae9072eSZixuan Wang if (status != EFI_SUCCESS) { 91*1ae9072eSZixuan Wang printf("Failed to exit boot services\n"); 92*1ae9072eSZixuan Wang return status; 93*1ae9072eSZixuan Wang } 94*1ae9072eSZixuan Wang 95*1ae9072eSZixuan Wang setup_efi(&efi_bootinfo); 96ad5fb883SZixuan Wang ret = main(__argc, __argv, __environ); 97ad5fb883SZixuan Wang exit(ret); 98ad5fb883SZixuan Wang 99ad5fb883SZixuan Wang /* Shutdown the guest VM in case exit() fails */ 100ad5fb883SZixuan Wang efi_rs_call(reset_system, EFI_RESET_SHUTDOWN, ret, 0, NULL); 101ad5fb883SZixuan Wang 102ad5fb883SZixuan Wang /* Unreachable */ 103ad5fb883SZixuan Wang return EFI_UNSUPPORTED; 1040eaa5176SVarad Gautam } 105