coreboot-kgpe-d16/payloads/tianocoreboot/tianocoreboot.c

530 lines
16 KiB
C
Raw Normal View History

Project PIANO aka tianocoreboot This is a Tiano Core loader payload based on libpayload. It will load a Tiano Core DXE core from an UEFI firmware volume stored in CBFS. Currently Tiano Core dies because it does not find all the UEFI services it needs: coreboot-4.0-3316-gc5c9ff8-dirty Mon Jan 28 15:37:12 PST 2013 starting... [..] Tiano Core Loader v1.0 Copyright (C) 2013 Google Inc. All rights reserved. Memory Map (5 entries): 1. 0000000000000000 - 0000000000000fff [10] 2. 0000000000001000 - 000000000009ffff [01] 3. 00000000000c0000 - 0000000003ebffff [01] 4. 0000000003ec0000 - 0000000003ffffff [10] 5. 00000000ff800000 - 00000000ffffffff [02] DXE code: 03e80000 DXE stack: 03e60000 HOB list: 03d5c000 Found UEFI firmware volume. GUID: 8c8ce578-8a3d-4f1c-9935-896185c32dd3 length: 0x0000000000260000 Found DXE core at 0xffc14e0c Section 0: .text size=000158a0 rva=00000240 in file=000158a0/00000240 flags=60000020 Section 1: .data size=00006820 rva=00015ae0 in file=00006820/00015ae0 flags=c0000040 Section 2: .reloc size=000010a0 rva=0001c300 in file=000010a0/0001c300 flags=42000040 Jumping to DXE core at 0x3e80000 InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 3E96708 HOBLIST address in DXE = 0x3E56010 Memory Allocation 0x00000003 0x3E80000 - 0x3EBFFFF FV Hob 0xFFC14D78 - 0xFFE74D77 InstallProtocolInterface: D8117CFE-94A6-11D4-9A3A-0090273FC14D 3E95EA0 InstallProtocolInterface: EE4E5898-3914-4259-9D6E-DC7BD79403CF 3E9630C Security Arch Protocol not present!! CPU Arch Protocol not present!! Metronome Arch Protocol not present!! Timer Arch Protocol not present!! Bds Arch Protocol not present!! Watchdog Timer Arch Protocol not present!! Runtime Arch Protocol not present!! Variable Arch Protocol not present!! Variable Write Arch Protocol not present!! Capsule Arch Protocol not present!! Monotonic Counter Arch Protocol not present!! Reset Arch Protocol not present!! Real Time Clock Arch Protocol not present!! ASSERT_EFI_ERROR (Status = Not Found) ASSERT /home/reinauer/svn/Tiano/edk2/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c(461): !EFI_ERROR (Status) Change-Id: I14068e9a28ff67ab1bf03105d56dab2e8be7b230 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/2154 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
2013-01-16 02:02:58 +01:00
/*
* This file is part of the TianoCoreBoot project.
*
* Copyright (C) 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <libpayload.h>
#include <endian.h>
#include <cbfs.h>
#include <efi.h>
#include <coff.h>
#define DXE_CORE_SIZE (256*1024)
#define UEFI_STACK_SIZE (128*1024)
#define HOB_LIST_SIZE (16*1024)
#undef VERBOSE
#undef INVENTORY
static void print_guid(EFI_GUID *guid)
{
printf("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
static void dump_uefi_firmware_volume_header(EFI_FIRMWARE_VOLUME_HEADER *fvh)
{
printf("Found UEFI firmware volume.\n");
printf(" GUID: ");
print_guid(&(fvh->FileSystemGuid));
printf("\n");
printf(" length: 0x%016llx\n", fvh->FvLength);
#ifdef VERBOSE
printf(" signature: 0x%08x\n", fvh->Signature);
printf(" attributes: 0x%08x\n", fvh->Attributes);
printf(" header length: 0x%04x\n", fvh->HeaderLength);
printf(" checksum: 0x%04x\n", fvh->Checksum);
printf(" revision: 0x%02x\n", fvh->Revision);
printf(" block map:\n");
int i = 0;
EFI_FV_BLOCK_MAP_ENTRY *fbm = &(fvh->FvBlockMap[0]);
while (fbm[i].NumBlocks || fbm[i].BlockLength) {
printf(" %2d. numblocks = 0x%08x length = 0x%08x\n",
i+1, fbm[i].NumBlocks, fbm[i].BlockLength);
i++;
}
#endif
printf("\n");
}
#ifdef INVENTORY
static void dump_uefi_ffs_file_header(EFI_FFS_FILE_HEADER *file)
{
int size;
#ifdef VERBOSE
printf("Found FFS file:\n GUID: ");
#endif
print_guid(&(file->Name));
#ifdef VERBOSE
printf("\n integrity check: %02x %02x\n",
file->IntegrityCheck.Checksum.Header,
file->IntegrityCheck.Checksum.File);
printf(" file type: ");
#else
printf(" ");
#endif
switch (file->Type) {
case EFI_FV_FILETYPE_RAW: printf("raw"); break;
case EFI_FV_FILETYPE_FREEFORM: printf("free form"); break;
case EFI_FV_FILETYPE_SECURITY_CORE: printf("security core"); break;
case EFI_FV_FILETYPE_PEI_CORE: printf("PEIM core"); break;
case EFI_FV_FILETYPE_DXE_CORE: printf("DXE core"); break;
case EFI_FV_FILETYPE_PEIM: printf("PEIM"); break;
case EFI_FV_FILETYPE_DRIVER: printf("driver"); break;
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: printf("combined PEIM driver"); break;
case EFI_FV_FILETYPE_APPLICATION: printf("application"); break;
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: printf("firmware volume image"); break;
case EFI_FV_FILETYPE_FFS_PAD: printf("FFS pad"); break;
default: printf("unknown");
}
#ifdef VERBOSE
printf("\n");
printf(" attributes: 0x%02x\n", file->Attributes);
#endif
size = file->Size[0] | (file->Size[1] << 8) | (file->Size[2] << 16);
#ifdef VERBOSE
printf(" size: 0x%06x\n", size);
printf(" state: 0x%02x\n", file->State);
#else
printf(" (%d bytes)\n", size);
#endif
}
#endif
void *load_dxe_core(void *pe, void *target)
{
dos_header_t *dos_hdr = (dos_header_t *)pe;
#if VERBOSE
printf("Loading DXE core at %p\n", pe);
#endif
if (*(uint16_t *)pe != 0x5a4d) {
printf("DXE core not a PE binary.\n");
return NULL;
}
#ifdef VERBOSE
printf("e_lfanew = 0x%08x\n", dos_hdr->e_lfanew);
#endif
coff_header_t *coff_hdr = (coff_header_t *)(pe + dos_hdr->e_lfanew);
#ifdef VERBOSE
printf("Machine: %x\n", coff_hdr->Machine);
printf("NumberOfSections: %x\n", coff_hdr->NumberOfSections);
printf("TimeDateStamp: %x\n", coff_hdr->TimeDateStamp);
printf("PointerToSymbolTable: %x\n", coff_hdr->PointerToSymbolTable);
printf("NumberOfSymbols: %x\n", coff_hdr->NumberOfSymbols);
printf("SizeOfOptionalHeader: %x\n", coff_hdr->SizeOfOptionalHeader);
printf("Characteristics: %x\n", coff_hdr->Characteristics);
#endif
if (coff_hdr->Machine != 0x14c) {
printf("Only x86 supported right now.\n");
return NULL;
}
/* Right after the coff header */
pe_opt_header_t *pe_hdr = (pe_opt_header_t *)(&coff_hdr[1]);
if (pe_hdr->signature != 267) {
printf("No valid PE opt header\n");
return NULL;
}
#ifdef VERBOSE
printf("\n");
printf("MajorLinkerVersion: %x\n", pe_hdr->MajorLinkerVersion);
printf("MinorLinkerVersion: %x\n", pe_hdr->MinorLinkerVersion);
printf("SizeOfCode: %x\n", pe_hdr->SizeOfCode);
printf("SizeOfInitializedData: %x\n", pe_hdr->SizeOfInitializedData);
printf("SizeOfUninitializedData: %x\n", pe_hdr->SizeOfUninitializedData);
printf("AddressOfEntryPoint: %x\n", pe_hdr->AddressOfEntryPoint);
printf("BaseOfCode: %x\n", pe_hdr->BaseOfCode);
printf("BaseOfData: %x\n", pe_hdr->BaseOfData);
printf("ImageBase: %x\n", pe_hdr->ImageBase);
printf("SectionAlignment: %x\n", pe_hdr->SectionAlignment);
printf("FileAlignment: %x\n", pe_hdr->FileAlignment);
printf("MajorOSVersion: %x\n", pe_hdr->MajorOSVersion);
printf("MinorOSVersion: %x\n", pe_hdr->MinorOSVersion);
printf("MajorImageVersion: %x\n", pe_hdr->MajorImageVersion);
printf("MinorImageVersion: %x\n", pe_hdr->MinorImageVersion);
printf("MajorSubsystemVersion: %x\n", pe_hdr->MajorSubsystemVersion);
printf("MinorSubsystemVersion: %x\n", pe_hdr->MinorSubsystemVersion);
printf("Reserved: %x\n", pe_hdr->Reserved);
printf("SizeOfImage: %x\n", pe_hdr->SizeOfImage);
printf("SizeOfHeaders: %x\n", pe_hdr->SizeOfHeaders);
printf("Checksum: %x\n", pe_hdr->Checksum);
printf("Subsystem: %x\n", pe_hdr->Subsystem);
printf("DLLCharacteristics: %x\n", pe_hdr->DLLCharacteristics);
printf("SizeOfStackReserve: %x\n", pe_hdr->SizeOfStackReserve);
printf("SizeOfStackCommit: %x\n", pe_hdr->SizeOfStackCommit);
printf("SizeOfHeapReserve: %x\n", pe_hdr->SizeOfHeapReserve);
printf("SizeOfHeapCommit: %x\n", pe_hdr->SizeOfHeapCommit);
printf("LoaderFlags: %x\n", pe_hdr->LoaderFlags);
printf("NumberOfRvaAndSizes: %x\n", pe_hdr->NumberOfRvaAndSizes);
#endif
if(pe_hdr->Subsystem != 0xb) {
printf("Not an EFI binary.\n");
return NULL;
}
int i;
#ifdef VERBOSE
for (i = 0; i < pe_hdr->NumberOfRvaAndSizes; i++) {
if (!pe_hdr->DataDirectory[i].Size)
continue;
printf("Data Directory %d\n", i+1);
printf(" VirtualAddress %x\n", pe_hdr->DataDirectory[i].VirtualAddress);
printf(" Size %x\n", pe_hdr->DataDirectory[i].Size);
}
#endif
pe_section_t *sections = (pe_section_t *)(&pe_hdr[1]);
int offset = 0;
for (i = 0; i < coff_hdr->NumberOfSections; i++) {
int j;
printf(" Section %d: ", i);
for (j = 0; j < 8; j++)
printf("%c", sections[i].SectionName[j] ? sections[i].SectionName[j] : ' ');
printf(" size=%08x rva=%08x in file=%08x/%08x flags=%08x\n",
sections[i].Size, sections[i].RVA, sections[i].PhysicalSizeOnDisk,
sections[i].PhysicalLocationOnDisk, sections[i].SectionFlags);
if (!strncmp((char *)sections[i].SectionName, ".text", 6)) {
// .text section
// size=157a0 rva=240 size on disk=157a0 location on disk=240 flags=60000020
memcpy(target, pe + sections[i].PhysicalLocationOnDisk,
sections[i].PhysicalSizeOnDisk);
offset = sections[i].RVA;
} else
if (!strncmp((char *)sections[i].SectionName, ".data", 6)) {
// .data section
// size=6820 rva=159e0 size on disk=6820 location on disk=159e0 flags=c0000040
memcpy(target + sections[i].RVA - offset, pe + sections[i].PhysicalLocationOnDisk,
sections[i].PhysicalSizeOnDisk);
} else
if (!strncmp((char *)sections[i].SectionName, ".reloc", 7)) {
// .reloc section
// section 2: .reloc
// size=1080 rva=1c200 size on disk=1080 location on disk=1c200 flags=42000040
relocation_t *reloc = (relocation_t *)
(pe + sections[i].PhysicalLocationOnDisk);
while (reloc && reloc->SizeOfBlock) {
#ifdef VERBOSE
printf("Relocation Block Virtual %08x Size %08x\n",
reloc->VirtualAddress, reloc->SizeOfBlock);
#endif
for (i = sizeof(relocation_t); i < reloc->SizeOfBlock; i+= 2) {
uint16_t r = *(uint16_t *)((void *)reloc + i);
switch (r>>12) {
case 3:
#ifdef VERBOSE
printf(" HIGHLOW %08x\n",
reloc->VirtualAddress + (r & 0xfff));
#endif
*(uint32_t *)(target - offset + reloc->VirtualAddress + (r & 0xfff))
+= (unsigned long)target - offset;
break;
case 0:
#ifdef VERBOSE
printf(" ABSOLUTE %08x\n", r & 0xfff);
#endif
break;
default:
printf("Unknown relocation type %x\n", r);
return NULL;
}
}
reloc = (relocation_t *)(((void *)reloc) + reloc->SizeOfBlock);
}
} else
if (!strncmp((char *)sections[i].SectionName, ".debug", 7)) {
// debug section, silently ignored.
} else {
printf("section type ");
for (j = 0; j < 8; j++)
if (sections[i].SectionName[j])
printf("%c", sections[i].SectionName[j]);
printf(" unknown. ignored.\n");
}
}
return (target + pe_hdr->AddressOfEntryPoint - offset);
}
void start_dxe_core(void *entry, void *stack, void *hoblist)
{
printf("\nJumping to DXE core at %p\n", entry);
asm volatile(
"movl %1, %%esp\n"
"pushl %2\n"
"call *%0\n"
: : "r"(entry), "r"(stack), "r"(hoblist) : "esp"
);
}
static const EFI_HOB_HANDOFF_INFO_TABLE HandoffInformationTable = {
{ EFI_HOB_TYPE_HANDOFF, sizeof(EFI_HOB_HANDOFF_INFO_TABLE), 0 },
EFI_HOB_HANDOFF_TABLE_VERSION,
BOOT_WITH_FULL_CONFIGURATION,
0 /* EfiMemoryTop */,
0 /* EfiMemoryBottom */,
0 /* EfiFreeMemoryTop */,
0 /* EfiFreeMemoryBottom */,
0 /* EfiEndOfHobList */
};
static const EFI_HOB_FIRMWARE_VOLUME FirmwareVolume = {
{ EFI_HOB_TYPE_FV, sizeof(EFI_HOB_FIRMWARE_VOLUME), 0 },
0 /* BaseAddress */,
0 /* Length */
};
/* 1..n */
static const EFI_HOB_RESOURCE_DESCRIPTOR ResourceDescriptor = {
{ EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof(EFI_HOB_RESOURCE_DESCRIPTOR), 0 },
{ 0 }, // owner EFI_GUID
EFI_RESOURCE_SYSTEM_MEMORY,
EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED,
0, /* PhysicalStart */
0 /* ResourceLength */
};
static const EFI_HOB_MEMORY_ALLOCATION_MODULE MemoryAllocationModule = {
{ EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof(EFI_HOB_MEMORY_ALLOCATION_MODULE), 0 },
{ EFI_HOB_MEMORY_ALLOC_MODULE_GUID, 0 /* MemoryBaseAddress */, 0 /* MemoryLength */, EfiBootServicesCode, {0,0,0,0} },
EFI_DXE_FILE_GUID,
0x0 // ADDR EntryPoint
};
static const EFI_HOB_CPU Cpu = {
{ EFI_HOB_TYPE_CPU, sizeof(EFI_HOB_CPU), 0 },
32, /* SizeOfMemorySpace, u8 */
16, /* SizeOfIoSpace */
{ 0,0,0,0,0,0 }
};
static const EFI_HOB_GENERIC_HEADER End =
{ EFI_HOB_TYPE_END_OF_HOB_LIST, sizeof(EFI_HOB_GENERIC_HEADER), 0 };
static void prepare_handoff_blocks(void *hoblist, EFI_FIRMWARE_VOLUME_HEADER *fvh,
unsigned long EfiMemoryTop, unsigned long EfiMemoryBottom,
unsigned long EfiFreeMemoryTop, unsigned long EfiFreeMemoryBottom,
unsigned long dxecore_base)
{
void *ptr = hoblist;
int i;
EFI_HOB_HANDOFF_INFO_TABLE *hit = (EFI_HOB_HANDOFF_INFO_TABLE *)ptr;
memcpy(ptr, &HandoffInformationTable, sizeof(HandoffInformationTable));
ptr += sizeof(HandoffInformationTable);
EFI_HOB_FIRMWARE_VOLUME *fv = (EFI_HOB_FIRMWARE_VOLUME *)ptr;
memcpy(ptr, &FirmwareVolume, sizeof(FirmwareVolume));
ptr += sizeof(FirmwareVolume);
for (i = 0; i < lib_sysinfo.n_memranges; i++) {
EFI_HOB_RESOURCE_DESCRIPTOR *resource;
if (lib_sysinfo.memrange[i].type != CB_MEM_RAM)
continue;
resource = (EFI_HOB_RESOURCE_DESCRIPTOR *)ptr;
memcpy(ptr, &ResourceDescriptor, sizeof(ResourceDescriptor));
ptr += sizeof(ResourceDescriptor);
resource->PhysicalStart = lib_sysinfo.memrange[i].base;
resource->ResourceLength = lib_sysinfo.memrange[i].size;
}
EFI_HOB_MEMORY_ALLOCATION_MODULE *allocation = (EFI_HOB_MEMORY_ALLOCATION_MODULE *)ptr;
memcpy(ptr, &MemoryAllocationModule, sizeof(MemoryAllocationModule));
ptr += sizeof(MemoryAllocationModule);
memcpy(ptr, &Cpu, sizeof(Cpu));
ptr += sizeof(Cpu);
memcpy(ptr, &End, sizeof(End));
ptr += sizeof(Cpu);
/* Handoff Information Table HOB */
hit->EfiMemoryTop = EfiMemoryTop;
hit->EfiMemoryBottom = EfiMemoryBottom;
hit->EfiFreeMemoryTop = EfiFreeMemoryTop;
hit->EfiFreeMemoryBottom = EfiFreeMemoryBottom;
hit->EfiEndOfHobList = (unsigned long)ptr;
/* Firmware Volume HOB */
fv->BaseAddress = (unsigned long)fvh;
fv->Length = fvh->FvLength;
allocation->MemoryAllocationHeader.MemoryBaseAddress = dxecore_base;
allocation->MemoryAllocationHeader.MemoryLength = DXE_CORE_SIZE;
}
int main(void)
{
int i;
struct cbfs_file *file;
void *tiano;
unsigned long long ram_seg_base = 0, ram_seg_size = 0;
EFI_FIRMWARE_VOLUME_HEADER *fvh = NULL;
EFI_PEI_HOB_POINTERS hoblist;
EFI_COMMON_SECTION_HEADER *dxecore = NULL;
printf("\nTiano Core Loader v1.0\n");
printf("Copyright (C) 2013 Google Inc. All rights reserved.\n\n");
printf("Memory Map (%d entries):\n", lib_sysinfo.n_memranges);
for (i = 0; i < lib_sysinfo.n_memranges; i++) {
printf(" %d. %016llx - %016llx [%02x]\n", i + 1,
lib_sysinfo.memrange[i].base,
lib_sysinfo.memrange[i].base +
lib_sysinfo.memrange[i].size - 1,
lib_sysinfo.memrange[i].type);
/* Look for the last chunk of memory below 4G */
if (lib_sysinfo.memrange[i].type == CB_MEM_RAM &&
lib_sysinfo.memrange[i].base < 0xffffffff) {
ram_seg_base = lib_sysinfo.memrange[i].base;
ram_seg_size = lib_sysinfo.memrange[i].size;
}
}
printf("\n");
if (!ram_seg_base || ram_seg_size < (1024*1024)) {
printf("No usable RAM found.\n");
halt();
}
/* Find the end of our memory block, align to 4K */
unsigned long memory = (ram_seg_base + ram_seg_size) & 0xfffff000;
/* 256K for DXE core. It's 116K on my system but you never know. */
memory -= DXE_CORE_SIZE;
unsigned long dxecore_base = memory;
memory -= UEFI_STACK_SIZE;
unsigned long uefi_stack = memory;
memory -= 1024*1024; // FIXME this should go away
unsigned long free_memory = memory; // FIXME this should go away
memory -= HOB_LIST_SIZE;
unsigned long hoblist_base = memory;
printf("DXE code: %08lx\n", dxecore_base);
printf("DXE stack: %08lx\n", uefi_stack);
printf("HOB list: %08lx\n\n", hoblist_base);
/* Find UEFI firmware volume in CBFS */
file = cbfs_find("fallback/tianocore.fd");
if (!file) {
printf("Could not find fallback/tianocore.fd in CBFS.\n");
halt();
}
tiano = CBFS_SUBHEADER(file);
while (tiano < (void *)CBFS_SUBHEADER(file) + ntohl(file->len)) {
/* Verify UEFI firmware volume consistency */
fvh = (EFI_FIRMWARE_VOLUME_HEADER *)tiano;
if (fvh->Signature != 0x4856465f) {
printf("Not an UEFI firmware volume.\n");
halt();
}
/* Dump UEFI firmware volume header */
dump_uefi_firmware_volume_header(fvh);
/* Dump UEFI firmware file headers */
for (i = fvh->HeaderLength; i < fvh->FvLength;) {
int size;
EFI_FFS_FILE_HEADER *ffs;
ffs = (EFI_FFS_FILE_HEADER *)(tiano + i);
size = ffs->Size[0] | (ffs->Size[1] << 8) | (ffs->Size[2] << 16);
if (size == 0xffffff)
break;
#ifdef INVENTORY
printf("%08x - ", i);
dump_uefi_ffs_file_header(ffs);
#endif
if (ffs->Type == EFI_FV_FILETYPE_DXE_CORE) {
dxecore = (EFI_COMMON_SECTION_HEADER *)&ffs[1];
#ifndef INVENTORY
break;
#endif
}
i = ALIGN(i + size, 8);
}
tiano += fvh->FvLength;
#ifdef INVENTORY
printf("\n");
#endif
}
/* Prepare Hand Off Blocks */
prepare_handoff_blocks((void *)hoblist_base, fvh,
// FIXME memory top, memory bottom
(ram_seg_base + ram_seg_size) & 0xfffff000, ram_seg_base,
// FIXME free memory top, free memory bottom
uefi_stack, free_memory,
dxecore_base);
hoblist.Raw = (void *)hoblist_base;
if (!dxecore) {
printf("No DXE core found.\n");
halt();
}
printf("Found DXE core at %p\n", &dxecore[1]);
#ifdef VERBOSE
int size = dxecore->Size[0] | (dxecore->Size[1] << 8) | (dxecore->Size[2] << 16);
printf(" size = %d, type = %x\n", size, dxecore->Type);
#endif
void *pe = (void *)&dxecore[1];
void *entry;
entry = load_dxe_core(pe, (void *)dxecore_base);
if (!entry) {
printf("Could not load DXE code.\n");
halt();
}
start_dxe_core(entry, (void *)(uefi_stack + UEFI_STACK_SIZE - 4), hoblist.Raw);
printf("The end.\n");
halt();
return 0;
}
PAYLOAD_INFO(name, "TianoCoreBoot");
PAYLOAD_INFO(listname, "Tiano Core");
PAYLOAD_INFO(desc, "Tiano Core Loader");