1 /* 2 * EFI-related functions to set up and run test cases in EFI 3 * 4 * Copyright (c) 2021, SUSE, Varad Gautam <varad.gautam@suse.com> 5 * Copyright (c) 2021, Google Inc, Zixuan Wang <zixuanwang@google.com> 6 * 7 * SPDX-License-Identifier: LGPL-2.0-or-later 8 */ 9 10 #include "efi.h" 11 #include <libcflat.h> 12 #include <asm/setup.h> 13 14 /* From lib/argv.c */ 15 extern int __argc, __envc; 16 extern char *__argv[100]; 17 extern char *__environ[200]; 18 19 extern int main(int argc, char **argv, char **envp); 20 21 efi_system_table_t *efi_system_table = NULL; 22 23 static void efi_free_pool(void *ptr) 24 { 25 efi_bs_call(free_pool, ptr); 26 } 27 28 efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) 29 { 30 efi_memory_desc_t *m = NULL; 31 efi_status_t status; 32 unsigned long key = 0, map_size = 0, desc_size = 0; 33 u32 desc_ver; 34 35 status = efi_bs_call(get_memory_map, &map_size, 36 NULL, &key, &desc_size, &desc_ver); 37 if (status != EFI_BUFFER_TOO_SMALL || map_size == 0) 38 goto out; 39 40 /* 41 * Pad map_size with additional descriptors so we don't need to 42 * retry. 43 */ 44 map_size += 4 * desc_size; 45 *map->buff_size = map_size; 46 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, 47 map_size, (void **)&m); 48 if (status != EFI_SUCCESS) 49 goto out; 50 51 /* Get the map. */ 52 status = efi_bs_call(get_memory_map, &map_size, 53 m, &key, &desc_size, &desc_ver); 54 if (status != EFI_SUCCESS) { 55 efi_free_pool(m); 56 goto out; 57 } 58 59 *map->desc_ver = desc_ver; 60 *map->desc_size = desc_size; 61 *map->map_size = map_size; 62 *map->key_ptr = key; 63 out: 64 *map->map = m; 65 return status; 66 } 67 68 efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey) 69 { 70 return efi_bs_call(exit_boot_services, handle, mapkey); 71 } 72 73 efi_status_t efi_get_system_config_table(efi_guid_t table_guid, void **table) 74 { 75 size_t i; 76 efi_config_table_t *tables; 77 78 tables = (efi_config_table_t *)efi_system_table->tables; 79 for (i = 0; i < efi_system_table->nr_tables; i++) { 80 if (!memcmp(&table_guid, &tables[i].guid, sizeof(efi_guid_t))) { 81 *table = tables[i].table; 82 return EFI_SUCCESS; 83 } 84 } 85 return EFI_NOT_FOUND; 86 } 87 88 efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) 89 { 90 int ret; 91 unsigned long mapkey = 0; 92 efi_status_t status; 93 efi_bootinfo_t efi_bootinfo; 94 95 efi_system_table = sys_tab; 96 97 setup_efi_bootinfo(&efi_bootinfo); 98 status = setup_efi_pre_boot(&mapkey, &efi_bootinfo); 99 if (status != EFI_SUCCESS) { 100 printf("Failed to set up before ExitBootServices, exiting.\n"); 101 return status; 102 } 103 104 status = efi_exit_boot_services(handle, mapkey); 105 if (status != EFI_SUCCESS) { 106 printf("Failed to exit boot services\n"); 107 return status; 108 } 109 110 setup_efi(&efi_bootinfo); 111 ret = main(__argc, __argv, __environ); 112 exit(ret); 113 114 /* Shutdown the guest VM in case exit() fails */ 115 efi_rs_call(reset_system, EFI_RESET_SHUTDOWN, ret, 0, NULL); 116 117 /* Unreachable */ 118 return EFI_UNSUPPORTED; 119 } 120