Stefan Reinauer | cc5b344 | 2013-01-15 17:02:58 -0800 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the TianoCoreBoot project. |
| 3 | * |
| 4 | * Copyright (C) 2013 Google Inc. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
Paul Menzel | a46a712 | 2013-02-23 18:37:27 +0100 | [diff] [blame] | 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
Stefan Reinauer | cc5b344 | 2013-01-15 17:02:58 -0800 | [diff] [blame] | 18 | */ |
| 19 | |
| 20 | #include <libpayload.h> |
| 21 | #include <endian.h> |
| 22 | #include <cbfs.h> |
| 23 | #include <efi.h> |
| 24 | #include <coff.h> |
| 25 | |
| 26 | #define DXE_CORE_SIZE (256*1024) |
| 27 | #define UEFI_STACK_SIZE (128*1024) |
| 28 | #define HOB_LIST_SIZE (16*1024) |
| 29 | |
| 30 | #undef VERBOSE |
| 31 | #undef INVENTORY |
| 32 | |
| 33 | static void print_guid(EFI_GUID *guid) |
| 34 | { |
| 35 | printf("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
| 36 | guid->Data1, guid->Data2, guid->Data3, |
| 37 | guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], |
| 38 | guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); |
| 39 | } |
| 40 | |
| 41 | static void dump_uefi_firmware_volume_header(EFI_FIRMWARE_VOLUME_HEADER *fvh) |
| 42 | { |
| 43 | printf("Found UEFI firmware volume.\n"); |
| 44 | printf(" GUID: "); |
| 45 | print_guid(&(fvh->FileSystemGuid)); |
| 46 | printf("\n"); |
| 47 | printf(" length: 0x%016llx\n", fvh->FvLength); |
| 48 | #ifdef VERBOSE |
| 49 | printf(" signature: 0x%08x\n", fvh->Signature); |
| 50 | printf(" attributes: 0x%08x\n", fvh->Attributes); |
| 51 | printf(" header length: 0x%04x\n", fvh->HeaderLength); |
| 52 | printf(" checksum: 0x%04x\n", fvh->Checksum); |
| 53 | printf(" revision: 0x%02x\n", fvh->Revision); |
| 54 | printf(" block map:\n"); |
| 55 | int i = 0; |
| 56 | EFI_FV_BLOCK_MAP_ENTRY *fbm = &(fvh->FvBlockMap[0]); |
| 57 | while (fbm[i].NumBlocks || fbm[i].BlockLength) { |
| 58 | printf(" %2d. numblocks = 0x%08x length = 0x%08x\n", |
| 59 | i+1, fbm[i].NumBlocks, fbm[i].BlockLength); |
| 60 | i++; |
| 61 | } |
| 62 | #endif |
| 63 | printf("\n"); |
| 64 | } |
| 65 | |
| 66 | #ifdef INVENTORY |
| 67 | static void dump_uefi_ffs_file_header(EFI_FFS_FILE_HEADER *file) |
| 68 | { |
| 69 | int size; |
| 70 | |
| 71 | #ifdef VERBOSE |
| 72 | printf("Found FFS file:\n GUID: "); |
| 73 | #endif |
| 74 | print_guid(&(file->Name)); |
| 75 | #ifdef VERBOSE |
| 76 | printf("\n integrity check: %02x %02x\n", |
| 77 | file->IntegrityCheck.Checksum.Header, |
| 78 | file->IntegrityCheck.Checksum.File); |
| 79 | printf(" file type: "); |
| 80 | #else |
| 81 | printf(" "); |
| 82 | #endif |
| 83 | switch (file->Type) { |
| 84 | case EFI_FV_FILETYPE_RAW: printf("raw"); break; |
| 85 | case EFI_FV_FILETYPE_FREEFORM: printf("free form"); break; |
| 86 | case EFI_FV_FILETYPE_SECURITY_CORE: printf("security core"); break; |
| 87 | case EFI_FV_FILETYPE_PEI_CORE: printf("PEIM core"); break; |
| 88 | case EFI_FV_FILETYPE_DXE_CORE: printf("DXE core"); break; |
| 89 | case EFI_FV_FILETYPE_PEIM: printf("PEIM"); break; |
| 90 | case EFI_FV_FILETYPE_DRIVER: printf("driver"); break; |
| 91 | case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: printf("combined PEIM driver"); break; |
| 92 | case EFI_FV_FILETYPE_APPLICATION: printf("application"); break; |
| 93 | case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: printf("firmware volume image"); break; |
| 94 | case EFI_FV_FILETYPE_FFS_PAD: printf("FFS pad"); break; |
| 95 | default: printf("unknown"); |
| 96 | } |
| 97 | #ifdef VERBOSE |
| 98 | printf("\n"); |
| 99 | printf(" attributes: 0x%02x\n", file->Attributes); |
| 100 | #endif |
| 101 | size = file->Size[0] | (file->Size[1] << 8) | (file->Size[2] << 16); |
| 102 | #ifdef VERBOSE |
| 103 | printf(" size: 0x%06x\n", size); |
| 104 | printf(" state: 0x%02x\n", file->State); |
| 105 | #else |
| 106 | printf(" (%d bytes)\n", size); |
| 107 | #endif |
| 108 | } |
| 109 | #endif |
| 110 | |
| 111 | void *load_dxe_core(void *pe, void *target) |
| 112 | { |
| 113 | dos_header_t *dos_hdr = (dos_header_t *)pe; |
| 114 | |
| 115 | #if VERBOSE |
| 116 | printf("Loading DXE core at %p\n", pe); |
| 117 | #endif |
| 118 | |
| 119 | if (*(uint16_t *)pe != 0x5a4d) { |
| 120 | printf("DXE core not a PE binary.\n"); |
| 121 | return NULL; |
| 122 | } |
| 123 | |
| 124 | #ifdef VERBOSE |
| 125 | printf("e_lfanew = 0x%08x\n", dos_hdr->e_lfanew); |
| 126 | #endif |
| 127 | |
| 128 | coff_header_t *coff_hdr = (coff_header_t *)(pe + dos_hdr->e_lfanew); |
| 129 | #ifdef VERBOSE |
| 130 | printf("Machine: %x\n", coff_hdr->Machine); |
| 131 | printf("NumberOfSections: %x\n", coff_hdr->NumberOfSections); |
| 132 | printf("TimeDateStamp: %x\n", coff_hdr->TimeDateStamp); |
| 133 | printf("PointerToSymbolTable: %x\n", coff_hdr->PointerToSymbolTable); |
| 134 | printf("NumberOfSymbols: %x\n", coff_hdr->NumberOfSymbols); |
| 135 | printf("SizeOfOptionalHeader: %x\n", coff_hdr->SizeOfOptionalHeader); |
| 136 | printf("Characteristics: %x\n", coff_hdr->Characteristics); |
| 137 | #endif |
| 138 | if (coff_hdr->Machine != 0x14c) { |
| 139 | printf("Only x86 supported right now.\n"); |
| 140 | return NULL; |
| 141 | } |
| 142 | |
| 143 | /* Right after the coff header */ |
| 144 | pe_opt_header_t *pe_hdr = (pe_opt_header_t *)(&coff_hdr[1]); |
| 145 | if (pe_hdr->signature != 267) { |
| 146 | printf("No valid PE opt header\n"); |
| 147 | return NULL; |
| 148 | } |
| 149 | |
| 150 | #ifdef VERBOSE |
| 151 | printf("\n"); |
| 152 | printf("MajorLinkerVersion: %x\n", pe_hdr->MajorLinkerVersion); |
| 153 | printf("MinorLinkerVersion: %x\n", pe_hdr->MinorLinkerVersion); |
| 154 | printf("SizeOfCode: %x\n", pe_hdr->SizeOfCode); |
| 155 | printf("SizeOfInitializedData: %x\n", pe_hdr->SizeOfInitializedData); |
| 156 | printf("SizeOfUninitializedData: %x\n", pe_hdr->SizeOfUninitializedData); |
| 157 | printf("AddressOfEntryPoint: %x\n", pe_hdr->AddressOfEntryPoint); |
| 158 | printf("BaseOfCode: %x\n", pe_hdr->BaseOfCode); |
| 159 | printf("BaseOfData: %x\n", pe_hdr->BaseOfData); |
| 160 | printf("ImageBase: %x\n", pe_hdr->ImageBase); |
| 161 | printf("SectionAlignment: %x\n", pe_hdr->SectionAlignment); |
| 162 | printf("FileAlignment: %x\n", pe_hdr->FileAlignment); |
| 163 | printf("MajorOSVersion: %x\n", pe_hdr->MajorOSVersion); |
| 164 | printf("MinorOSVersion: %x\n", pe_hdr->MinorOSVersion); |
| 165 | printf("MajorImageVersion: %x\n", pe_hdr->MajorImageVersion); |
| 166 | printf("MinorImageVersion: %x\n", pe_hdr->MinorImageVersion); |
| 167 | printf("MajorSubsystemVersion: %x\n", pe_hdr->MajorSubsystemVersion); |
| 168 | printf("MinorSubsystemVersion: %x\n", pe_hdr->MinorSubsystemVersion); |
| 169 | printf("Reserved: %x\n", pe_hdr->Reserved); |
| 170 | printf("SizeOfImage: %x\n", pe_hdr->SizeOfImage); |
| 171 | printf("SizeOfHeaders: %x\n", pe_hdr->SizeOfHeaders); |
| 172 | printf("Checksum: %x\n", pe_hdr->Checksum); |
| 173 | printf("Subsystem: %x\n", pe_hdr->Subsystem); |
| 174 | printf("DLLCharacteristics: %x\n", pe_hdr->DLLCharacteristics); |
| 175 | printf("SizeOfStackReserve: %x\n", pe_hdr->SizeOfStackReserve); |
| 176 | printf("SizeOfStackCommit: %x\n", pe_hdr->SizeOfStackCommit); |
| 177 | printf("SizeOfHeapReserve: %x\n", pe_hdr->SizeOfHeapReserve); |
| 178 | printf("SizeOfHeapCommit: %x\n", pe_hdr->SizeOfHeapCommit); |
| 179 | printf("LoaderFlags: %x\n", pe_hdr->LoaderFlags); |
| 180 | printf("NumberOfRvaAndSizes: %x\n", pe_hdr->NumberOfRvaAndSizes); |
| 181 | #endif |
| 182 | |
| 183 | if(pe_hdr->Subsystem != 0xb) { |
| 184 | printf("Not an EFI binary.\n"); |
| 185 | return NULL; |
| 186 | } |
| 187 | |
| 188 | int i; |
| 189 | #ifdef VERBOSE |
| 190 | for (i = 0; i < pe_hdr->NumberOfRvaAndSizes; i++) { |
| 191 | if (!pe_hdr->DataDirectory[i].Size) |
| 192 | continue; |
| 193 | printf("Data Directory %d\n", i+1); |
| 194 | printf(" VirtualAddress %x\n", pe_hdr->DataDirectory[i].VirtualAddress); |
| 195 | printf(" Size %x\n", pe_hdr->DataDirectory[i].Size); |
| 196 | } |
| 197 | #endif |
| 198 | |
| 199 | pe_section_t *sections = (pe_section_t *)(&pe_hdr[1]); |
| 200 | |
| 201 | int offset = 0; |
| 202 | |
| 203 | for (i = 0; i < coff_hdr->NumberOfSections; i++) { |
| 204 | int j; |
| 205 | printf(" Section %d: ", i); |
| 206 | for (j = 0; j < 8; j++) |
| 207 | printf("%c", sections[i].SectionName[j] ? sections[i].SectionName[j] : ' '); |
| 208 | |
| 209 | printf(" size=%08x rva=%08x in file=%08x/%08x flags=%08x\n", |
| 210 | sections[i].Size, sections[i].RVA, sections[i].PhysicalSizeOnDisk, |
| 211 | sections[i].PhysicalLocationOnDisk, sections[i].SectionFlags); |
| 212 | |
| 213 | if (!strncmp((char *)sections[i].SectionName, ".text", 6)) { |
| 214 | // .text section |
| 215 | // size=157a0 rva=240 size on disk=157a0 location on disk=240 flags=60000020 |
| 216 | memcpy(target, pe + sections[i].PhysicalLocationOnDisk, |
| 217 | sections[i].PhysicalSizeOnDisk); |
| 218 | offset = sections[i].RVA; |
| 219 | } else |
| 220 | if (!strncmp((char *)sections[i].SectionName, ".data", 6)) { |
| 221 | // .data section |
| 222 | // size=6820 rva=159e0 size on disk=6820 location on disk=159e0 flags=c0000040 |
| 223 | memcpy(target + sections[i].RVA - offset, pe + sections[i].PhysicalLocationOnDisk, |
| 224 | sections[i].PhysicalSizeOnDisk); |
| 225 | } else |
| 226 | if (!strncmp((char *)sections[i].SectionName, ".reloc", 7)) { |
| 227 | // .reloc section |
| 228 | // section 2: .reloc |
| 229 | // size=1080 rva=1c200 size on disk=1080 location on disk=1c200 flags=42000040 |
| 230 | relocation_t *reloc = (relocation_t *) |
| 231 | (pe + sections[i].PhysicalLocationOnDisk); |
| 232 | while (reloc && reloc->SizeOfBlock) { |
| 233 | #ifdef VERBOSE |
| 234 | printf("Relocation Block Virtual %08x Size %08x\n", |
| 235 | reloc->VirtualAddress, reloc->SizeOfBlock); |
| 236 | #endif |
| 237 | for (i = sizeof(relocation_t); i < reloc->SizeOfBlock; i+= 2) { |
| 238 | uint16_t r = *(uint16_t *)((void *)reloc + i); |
| 239 | switch (r>>12) { |
| 240 | case 3: |
| 241 | #ifdef VERBOSE |
| 242 | printf(" HIGHLOW %08x\n", |
| 243 | reloc->VirtualAddress + (r & 0xfff)); |
| 244 | #endif |
| 245 | *(uint32_t *)(target - offset + reloc->VirtualAddress + (r & 0xfff)) |
| 246 | += (unsigned long)target - offset; |
| 247 | break; |
| 248 | case 0: |
| 249 | #ifdef VERBOSE |
| 250 | printf(" ABSOLUTE %08x\n", r & 0xfff); |
| 251 | #endif |
| 252 | break; |
| 253 | default: |
| 254 | printf("Unknown relocation type %x\n", r); |
| 255 | return NULL; |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | reloc = (relocation_t *)(((void *)reloc) + reloc->SizeOfBlock); |
| 260 | } |
| 261 | } else |
| 262 | if (!strncmp((char *)sections[i].SectionName, ".debug", 7)) { |
| 263 | // debug section, silently ignored. |
| 264 | } else { |
| 265 | printf("section type "); |
| 266 | for (j = 0; j < 8; j++) |
| 267 | if (sections[i].SectionName[j]) |
| 268 | printf("%c", sections[i].SectionName[j]); |
| 269 | printf(" unknown. ignored.\n"); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | return (target + pe_hdr->AddressOfEntryPoint - offset); |
| 274 | } |
| 275 | |
| 276 | void start_dxe_core(void *entry, void *stack, void *hoblist) |
| 277 | { |
| 278 | printf("\nJumping to DXE core at %p\n", entry); |
| 279 | asm volatile( |
| 280 | "movl %1, %%esp\n" |
| 281 | "pushl %2\n" |
| 282 | "call *%0\n" |
| 283 | : : "r"(entry), "r"(stack), "r"(hoblist) : "esp" |
| 284 | ); |
| 285 | } |
| 286 | |
| 287 | static const EFI_HOB_HANDOFF_INFO_TABLE HandoffInformationTable = { |
| 288 | { EFI_HOB_TYPE_HANDOFF, sizeof(EFI_HOB_HANDOFF_INFO_TABLE), 0 }, |
| 289 | EFI_HOB_HANDOFF_TABLE_VERSION, |
| 290 | BOOT_WITH_FULL_CONFIGURATION, |
| 291 | 0 /* EfiMemoryTop */, |
| 292 | 0 /* EfiMemoryBottom */, |
| 293 | 0 /* EfiFreeMemoryTop */, |
| 294 | 0 /* EfiFreeMemoryBottom */, |
| 295 | 0 /* EfiEndOfHobList */ |
| 296 | }; |
| 297 | |
| 298 | static const EFI_HOB_FIRMWARE_VOLUME FirmwareVolume = { |
| 299 | { EFI_HOB_TYPE_FV, sizeof(EFI_HOB_FIRMWARE_VOLUME), 0 }, |
| 300 | 0 /* BaseAddress */, |
| 301 | 0 /* Length */ |
| 302 | }; |
| 303 | |
| 304 | /* 1..n */ |
| 305 | static const EFI_HOB_RESOURCE_DESCRIPTOR ResourceDescriptor = { |
| 306 | { EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof(EFI_HOB_RESOURCE_DESCRIPTOR), 0 }, |
| 307 | { 0 }, // owner EFI_GUID |
| 308 | EFI_RESOURCE_SYSTEM_MEMORY, |
| 309 | EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | |
| 310 | EFI_RESOURCE_ATTRIBUTE_TESTED, |
| 311 | 0, /* PhysicalStart */ |
| 312 | 0 /* ResourceLength */ |
| 313 | }; |
| 314 | |
| 315 | static const EFI_HOB_MEMORY_ALLOCATION_MODULE MemoryAllocationModule = { |
| 316 | { EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof(EFI_HOB_MEMORY_ALLOCATION_MODULE), 0 }, |
| 317 | { EFI_HOB_MEMORY_ALLOC_MODULE_GUID, 0 /* MemoryBaseAddress */, 0 /* MemoryLength */, EfiBootServicesCode, {0,0,0,0} }, |
| 318 | EFI_DXE_FILE_GUID, |
| 319 | 0x0 // ADDR EntryPoint |
| 320 | }; |
| 321 | |
| 322 | static const EFI_HOB_CPU Cpu = { |
| 323 | { EFI_HOB_TYPE_CPU, sizeof(EFI_HOB_CPU), 0 }, |
| 324 | 32, /* SizeOfMemorySpace, u8 */ |
| 325 | 16, /* SizeOfIoSpace */ |
| 326 | { 0,0,0,0,0,0 } |
| 327 | }; |
| 328 | |
| 329 | static const EFI_HOB_GENERIC_HEADER End = |
| 330 | { EFI_HOB_TYPE_END_OF_HOB_LIST, sizeof(EFI_HOB_GENERIC_HEADER), 0 }; |
| 331 | |
| 332 | |
| 333 | static void prepare_handoff_blocks(void *hoblist, EFI_FIRMWARE_VOLUME_HEADER *fvh, |
| 334 | unsigned long EfiMemoryTop, unsigned long EfiMemoryBottom, |
| 335 | unsigned long EfiFreeMemoryTop, unsigned long EfiFreeMemoryBottom, |
| 336 | unsigned long dxecore_base) |
| 337 | { |
| 338 | void *ptr = hoblist; |
| 339 | int i; |
| 340 | |
| 341 | EFI_HOB_HANDOFF_INFO_TABLE *hit = (EFI_HOB_HANDOFF_INFO_TABLE *)ptr; |
| 342 | memcpy(ptr, &HandoffInformationTable, sizeof(HandoffInformationTable)); |
| 343 | ptr += sizeof(HandoffInformationTable); |
| 344 | |
| 345 | EFI_HOB_FIRMWARE_VOLUME *fv = (EFI_HOB_FIRMWARE_VOLUME *)ptr; |
| 346 | memcpy(ptr, &FirmwareVolume, sizeof(FirmwareVolume)); |
| 347 | ptr += sizeof(FirmwareVolume); |
| 348 | |
| 349 | for (i = 0; i < lib_sysinfo.n_memranges; i++) { |
| 350 | EFI_HOB_RESOURCE_DESCRIPTOR *resource; |
| 351 | if (lib_sysinfo.memrange[i].type != CB_MEM_RAM) |
| 352 | continue; |
| 353 | resource = (EFI_HOB_RESOURCE_DESCRIPTOR *)ptr; |
| 354 | memcpy(ptr, &ResourceDescriptor, sizeof(ResourceDescriptor)); |
| 355 | ptr += sizeof(ResourceDescriptor); |
| 356 | resource->PhysicalStart = lib_sysinfo.memrange[i].base; |
| 357 | resource->ResourceLength = lib_sysinfo.memrange[i].size; |
| 358 | } |
| 359 | |
| 360 | EFI_HOB_MEMORY_ALLOCATION_MODULE *allocation = (EFI_HOB_MEMORY_ALLOCATION_MODULE *)ptr; |
| 361 | memcpy(ptr, &MemoryAllocationModule, sizeof(MemoryAllocationModule)); |
| 362 | ptr += sizeof(MemoryAllocationModule); |
| 363 | |
| 364 | memcpy(ptr, &Cpu, sizeof(Cpu)); |
| 365 | ptr += sizeof(Cpu); |
| 366 | |
| 367 | memcpy(ptr, &End, sizeof(End)); |
| 368 | ptr += sizeof(Cpu); |
| 369 | |
| 370 | /* Handoff Information Table HOB */ |
| 371 | hit->EfiMemoryTop = EfiMemoryTop; |
| 372 | hit->EfiMemoryBottom = EfiMemoryBottom; |
| 373 | hit->EfiFreeMemoryTop = EfiFreeMemoryTop; |
| 374 | hit->EfiFreeMemoryBottom = EfiFreeMemoryBottom; |
| 375 | hit->EfiEndOfHobList = (unsigned long)ptr; |
| 376 | |
| 377 | /* Firmware Volume HOB */ |
| 378 | fv->BaseAddress = (unsigned long)fvh; |
| 379 | fv->Length = fvh->FvLength; |
| 380 | |
| 381 | allocation->MemoryAllocationHeader.MemoryBaseAddress = dxecore_base; |
| 382 | allocation->MemoryAllocationHeader.MemoryLength = DXE_CORE_SIZE; |
| 383 | } |
| 384 | |
| 385 | int main(void) |
| 386 | { |
| 387 | int i; |
| 388 | struct cbfs_file *file; |
| 389 | void *tiano; |
| 390 | unsigned long long ram_seg_base = 0, ram_seg_size = 0; |
| 391 | EFI_FIRMWARE_VOLUME_HEADER *fvh = NULL; |
| 392 | EFI_PEI_HOB_POINTERS hoblist; |
| 393 | EFI_COMMON_SECTION_HEADER *dxecore = NULL; |
| 394 | |
| 395 | printf("\nTiano Core Loader v1.0\n"); |
| 396 | printf("Copyright (C) 2013 Google Inc. All rights reserved.\n\n"); |
| 397 | |
| 398 | printf("Memory Map (%d entries):\n", lib_sysinfo.n_memranges); |
| 399 | for (i = 0; i < lib_sysinfo.n_memranges; i++) { |
| 400 | printf(" %d. %016llx - %016llx [%02x]\n", i + 1, |
| 401 | lib_sysinfo.memrange[i].base, |
| 402 | lib_sysinfo.memrange[i].base + |
| 403 | lib_sysinfo.memrange[i].size - 1, |
| 404 | lib_sysinfo.memrange[i].type); |
| 405 | |
| 406 | /* Look for the last chunk of memory below 4G */ |
| 407 | if (lib_sysinfo.memrange[i].type == CB_MEM_RAM && |
| 408 | lib_sysinfo.memrange[i].base < 0xffffffff) { |
| 409 | ram_seg_base = lib_sysinfo.memrange[i].base; |
| 410 | ram_seg_size = lib_sysinfo.memrange[i].size; |
| 411 | } |
| 412 | } |
| 413 | printf("\n"); |
| 414 | |
| 415 | if (!ram_seg_base || ram_seg_size < (1024*1024)) { |
| 416 | printf("No usable RAM found.\n"); |
| 417 | halt(); |
| 418 | } |
| 419 | |
| 420 | /* Find the end of our memory block, align to 4K */ |
| 421 | unsigned long memory = (ram_seg_base + ram_seg_size) & 0xfffff000; |
| 422 | |
| 423 | /* 256K for DXE core. It's 116K on my system but you never know. */ |
| 424 | memory -= DXE_CORE_SIZE; |
| 425 | unsigned long dxecore_base = memory; |
| 426 | memory -= UEFI_STACK_SIZE; |
| 427 | unsigned long uefi_stack = memory; |
| 428 | |
| 429 | memory -= 1024*1024; // FIXME this should go away |
| 430 | unsigned long free_memory = memory; // FIXME this should go away |
| 431 | |
| 432 | memory -= HOB_LIST_SIZE; |
| 433 | unsigned long hoblist_base = memory; |
| 434 | |
| 435 | printf("DXE code: %08lx\n", dxecore_base); |
| 436 | printf("DXE stack: %08lx\n", uefi_stack); |
| 437 | printf("HOB list: %08lx\n\n", hoblist_base); |
| 438 | |
| 439 | /* Find UEFI firmware volume in CBFS */ |
| 440 | file = cbfs_find("fallback/tianocore.fd"); |
| 441 | if (!file) { |
| 442 | printf("Could not find fallback/tianocore.fd in CBFS.\n"); |
| 443 | halt(); |
| 444 | } |
| 445 | |
| 446 | tiano = CBFS_SUBHEADER(file); |
| 447 | while (tiano < (void *)CBFS_SUBHEADER(file) + ntohl(file->len)) { |
| 448 | /* Verify UEFI firmware volume consistency */ |
| 449 | fvh = (EFI_FIRMWARE_VOLUME_HEADER *)tiano; |
| 450 | if (fvh->Signature != 0x4856465f) { |
| 451 | printf("Not an UEFI firmware volume.\n"); |
| 452 | halt(); |
| 453 | } |
| 454 | |
| 455 | /* Dump UEFI firmware volume header */ |
| 456 | dump_uefi_firmware_volume_header(fvh); |
| 457 | |
| 458 | /* Dump UEFI firmware file headers */ |
| 459 | for (i = fvh->HeaderLength; i < fvh->FvLength;) { |
| 460 | int size; |
| 461 | EFI_FFS_FILE_HEADER *ffs; |
| 462 | |
| 463 | ffs = (EFI_FFS_FILE_HEADER *)(tiano + i); |
| 464 | |
| 465 | size = ffs->Size[0] | (ffs->Size[1] << 8) | (ffs->Size[2] << 16); |
| 466 | if (size == 0xffffff) |
| 467 | break; |
| 468 | #ifdef INVENTORY |
| 469 | printf("%08x - ", i); |
| 470 | dump_uefi_ffs_file_header(ffs); |
| 471 | #endif |
| 472 | |
| 473 | if (ffs->Type == EFI_FV_FILETYPE_DXE_CORE) { |
| 474 | dxecore = (EFI_COMMON_SECTION_HEADER *)&ffs[1]; |
| 475 | #ifndef INVENTORY |
| 476 | break; |
| 477 | #endif |
| 478 | } |
| 479 | |
| 480 | i = ALIGN(i + size, 8); |
| 481 | } |
| 482 | |
| 483 | tiano += fvh->FvLength; |
| 484 | #ifdef INVENTORY |
| 485 | printf("\n"); |
| 486 | #endif |
| 487 | } |
| 488 | |
| 489 | /* Prepare Hand Off Blocks */ |
| 490 | prepare_handoff_blocks((void *)hoblist_base, fvh, |
| 491 | // FIXME memory top, memory bottom |
| 492 | (ram_seg_base + ram_seg_size) & 0xfffff000, ram_seg_base, |
| 493 | // FIXME free memory top, free memory bottom |
| 494 | uefi_stack, free_memory, |
| 495 | dxecore_base); |
| 496 | hoblist.Raw = (void *)hoblist_base; |
| 497 | |
| 498 | if (!dxecore) { |
| 499 | printf("No DXE core found.\n"); |
| 500 | halt(); |
| 501 | } |
| 502 | |
| 503 | printf("Found DXE core at %p\n", &dxecore[1]); |
| 504 | #ifdef VERBOSE |
| 505 | int size = dxecore->Size[0] | (dxecore->Size[1] << 8) | (dxecore->Size[2] << 16); |
| 506 | printf(" size = %d, type = %x\n", size, dxecore->Type); |
| 507 | #endif |
| 508 | |
| 509 | void *pe = (void *)&dxecore[1]; |
| 510 | |
| 511 | void *entry; |
| 512 | entry = load_dxe_core(pe, (void *)dxecore_base); |
| 513 | |
| 514 | if (!entry) { |
| 515 | printf("Could not load DXE code.\n"); |
| 516 | halt(); |
| 517 | } |
| 518 | |
| 519 | start_dxe_core(entry, (void *)(uefi_stack + UEFI_STACK_SIZE - 4), hoblist.Raw); |
| 520 | |
| 521 | printf("The end.\n"); |
| 522 | halt(); |
| 523 | |
| 524 | return 0; |
| 525 | } |
| 526 | |
| 527 | PAYLOAD_INFO(name, "TianoCoreBoot"); |
| 528 | PAYLOAD_INFO(listname, "Tiano Core"); |
| 529 | PAYLOAD_INFO(desc, "Tiano Core Loader"); |