1 /* 2 * EFI image loader 3 * 4 * based partly on wine code 5 * 6 * Copyright (c) 2016 Alexander Graf 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <efi_loader.h> 13 #include <pe.h> 14 #include <asm/global_data.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; 19 const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID; 20 const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID; 21 const efi_guid_t efi_simple_file_system_protocol_guid = 22 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; 23 const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID; 24 25 static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, 26 unsigned long rel_size, void *efi_reloc) 27 { 28 const IMAGE_BASE_RELOCATION *end; 29 int i; 30 31 end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size); 32 while (rel < end - 1 && rel->SizeOfBlock) { 33 const uint16_t *relocs = (const uint16_t *)(rel + 1); 34 i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t); 35 while (i--) { 36 uint32_t offset = (uint32_t)(*relocs & 0xfff) + 37 rel->VirtualAddress; 38 int type = *relocs >> EFI_PAGE_SHIFT; 39 unsigned long delta = (unsigned long)efi_reloc; 40 uint64_t *x64 = efi_reloc + offset; 41 uint32_t *x32 = efi_reloc + offset; 42 uint16_t *x16 = efi_reloc + offset; 43 44 switch (type) { 45 case IMAGE_REL_BASED_ABSOLUTE: 46 break; 47 case IMAGE_REL_BASED_HIGH: 48 *x16 += ((uint32_t)delta) >> 16; 49 break; 50 case IMAGE_REL_BASED_LOW: 51 *x16 += (uint16_t)delta; 52 break; 53 case IMAGE_REL_BASED_HIGHLOW: 54 *x32 += (uint32_t)delta; 55 break; 56 case IMAGE_REL_BASED_DIR64: 57 *x64 += (uint64_t)delta; 58 break; 59 default: 60 printf("Unknown Relocation off %x type %x\n", 61 offset, type); 62 return EFI_LOAD_ERROR; 63 } 64 relocs++; 65 } 66 rel = (const IMAGE_BASE_RELOCATION *)relocs; 67 } 68 return EFI_SUCCESS; 69 } 70 71 void __weak invalidate_icache_all(void) 72 { 73 /* If the system doesn't support icache_all flush, cross our fingers */ 74 } 75 76 /* 77 * Determine the memory types to be used for code and data. 78 * 79 * @loaded_image_info image descriptor 80 * @image_type field Subsystem of the optional header for 81 * Windows specific field 82 */ 83 static void efi_set_code_and_data_type( 84 struct efi_loaded_image *loaded_image_info, 85 uint16_t image_type) 86 { 87 switch (image_type) { 88 case IMAGE_SUBSYSTEM_EFI_APPLICATION: 89 loaded_image_info->image_code_type = EFI_LOADER_CODE; 90 loaded_image_info->image_data_type = EFI_LOADER_DATA; 91 break; 92 case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: 93 loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE; 94 loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA; 95 break; 96 case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: 97 case IMAGE_SUBSYSTEM_EFI_ROM: 98 loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE; 99 loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA; 100 break; 101 default: 102 printf("%s: invalid image type: %u\n", __func__, image_type); 103 /* Let's assume it is an application */ 104 loaded_image_info->image_code_type = EFI_LOADER_CODE; 105 loaded_image_info->image_data_type = EFI_LOADER_DATA; 106 break; 107 } 108 } 109 110 /* 111 * This function loads all sections from a PE binary into a newly reserved 112 * piece of memory. On successful load it then returns the entry point for 113 * the binary. Otherwise NULL. 114 */ 115 void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) 116 { 117 IMAGE_NT_HEADERS32 *nt; 118 IMAGE_DOS_HEADER *dos; 119 IMAGE_SECTION_HEADER *sections; 120 int num_sections; 121 void *efi_reloc; 122 int i; 123 const IMAGE_BASE_RELOCATION *rel; 124 unsigned long rel_size; 125 int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC; 126 void *entry; 127 uint64_t image_size; 128 unsigned long virt_size = 0; 129 bool can_run_nt64 = true; 130 bool can_run_nt32 = true; 131 132 #if defined(CONFIG_ARM64) 133 can_run_nt32 = false; 134 #elif defined(CONFIG_ARM) 135 can_run_nt64 = false; 136 #endif 137 138 dos = efi; 139 if (dos->e_magic != IMAGE_DOS_SIGNATURE) { 140 printf("%s: Invalid DOS Signature\n", __func__); 141 return NULL; 142 } 143 144 nt = (void *) ((char *)efi + dos->e_lfanew); 145 if (nt->Signature != IMAGE_NT_SIGNATURE) { 146 printf("%s: Invalid NT Signature\n", __func__); 147 return NULL; 148 } 149 150 /* Calculate upper virtual address boundary */ 151 num_sections = nt->FileHeader.NumberOfSections; 152 sections = (void *)&nt->OptionalHeader + 153 nt->FileHeader.SizeOfOptionalHeader; 154 155 for (i = num_sections - 1; i >= 0; i--) { 156 IMAGE_SECTION_HEADER *sec = §ions[i]; 157 virt_size = max_t(unsigned long, virt_size, 158 sec->VirtualAddress + sec->Misc.VirtualSize); 159 } 160 161 /* Read 32/64bit specific header bits */ 162 if (can_run_nt64 && 163 (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)) { 164 IMAGE_NT_HEADERS64 *nt64 = (void *)nt; 165 IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader; 166 image_size = opt->SizeOfImage; 167 efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); 168 efi_reloc = efi_alloc(virt_size, 169 loaded_image_info->image_code_type); 170 if (!efi_reloc) { 171 printf("%s: Could not allocate %lu bytes\n", 172 __func__, virt_size); 173 return NULL; 174 } 175 entry = efi_reloc + opt->AddressOfEntryPoint; 176 rel_size = opt->DataDirectory[rel_idx].Size; 177 rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; 178 } else if (can_run_nt32 && 179 (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) { 180 IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; 181 image_size = opt->SizeOfImage; 182 efi_set_code_and_data_type(loaded_image_info, opt->Subsystem); 183 efi_reloc = efi_alloc(virt_size, 184 loaded_image_info->image_code_type); 185 if (!efi_reloc) { 186 printf("%s: Could not allocate %lu bytes\n", 187 __func__, virt_size); 188 return NULL; 189 } 190 entry = efi_reloc + opt->AddressOfEntryPoint; 191 rel_size = opt->DataDirectory[rel_idx].Size; 192 rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; 193 } else { 194 printf("%s: Invalid optional header magic %x\n", __func__, 195 nt->OptionalHeader.Magic); 196 return NULL; 197 } 198 199 /* Load sections into RAM */ 200 for (i = num_sections - 1; i >= 0; i--) { 201 IMAGE_SECTION_HEADER *sec = §ions[i]; 202 memset(efi_reloc + sec->VirtualAddress, 0, 203 sec->Misc.VirtualSize); 204 memcpy(efi_reloc + sec->VirtualAddress, 205 efi + sec->PointerToRawData, 206 sec->SizeOfRawData); 207 } 208 209 /* Run through relocations */ 210 if (efi_loader_relocate(rel, rel_size, efi_reloc) != EFI_SUCCESS) { 211 efi_free_pages((uintptr_t) efi_reloc, 212 (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); 213 return NULL; 214 } 215 216 /* Flush cache */ 217 flush_cache((ulong)efi_reloc, 218 ALIGN(virt_size, CONFIG_SYS_CACHELINE_SIZE)); 219 invalidate_icache_all(); 220 221 /* Populate the loaded image interface bits */ 222 loaded_image_info->image_base = efi; 223 loaded_image_info->image_size = image_size; 224 225 return entry; 226 } 227