#ifdef __APPLE__
#define MAP_ANONYMOUS MAP_ANON
-char *gGdbWorkingFileName = NULL;
#endif
EMU_THUNK_PPI mSecEmuThunkPpi = {
GasketSecUnixPeiAutoScan,
GasketSecUnixFdAddress,
- GasketSecEmuThunkAddress,
- GasketSecUnixPeiLoadFile
-};
-
-EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {
- GasketSecTemporaryRamSupport
+ GasketSecEmuThunkAddress
};
+char *gGdbWorkingFileName = NULL;
+UINTN mScriptSymbolChangesCount = 0;
//
// The number of array elements is allocated base on parsing
// EFI_FIRMWARE_VOLUMES and the memory is never freed.
//
-UINTN gFdInfoCount = 0;
-EMU_FD_INFO *gFdInfo;
+UINTN gFdInfoCount = 0;
+EMU_FD_INFO *gFdInfo;
//
// Array that supports seperate memory rantes.
// The number of array elements is allocated base on parsing
// EFI_MEMORY_SIZE and the memory is never freed.
//
-UINTN gSystemMemoryCount = 0;
-EMU_SYSTEM_MEMORY *gSystemMemory;
+UINTN gSystemMemoryCount = 0;
+EMU_SYSTEM_MEMORY *gSystemMemory;
UINTN mImageContextModHandleArraySize = 0;
IMAGE_CONTEXT_TO_MOD_HANDLE *mImageContextModHandleArray = NULL;
+EFI_PEI_PPI_DESCRIPTOR *gPpiList;
-
-EFI_PHYSICAL_ADDRESS *
-MapMemory (
- INTN fd,
- UINT64 length,
- INTN prot,
- INTN flags);
-
-EFI_STATUS
-MapFile (
- IN CHAR8 *FileName,
- IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
- OUT UINT64 *Length
- );
-
-EFI_STATUS
-EFIAPI
-SecNt32PeCoffRelocateImage (
- IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
- );
-
-
-int
-main (
- IN int Argc,
- IN char **Argv,
- IN char **Envp
- )
/*++
Routine Description:
1 - Abnormal exit
**/
+int
+main (
+ IN int Argc,
+ IN char **Argv,
+ IN char **Envp
+ )
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS InitialStackMemory;
UINTN PeiIndex;
CHAR8 *FileName;
BOOLEAN Done;
- VOID *PeiCoreFile;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ VOID *SecFile;
CHAR16 *MemorySizeStr;
CHAR16 *FirmwareVolumesStr;
UINTN *StackPointer;
+ FILE *GdbTempFile;
- setbuf(stdout, 0);
- setbuf(stderr, 0);
+ setbuf (stdout, 0);
+ setbuf (stderr, 0);
MemorySizeStr = (CHAR16 *) PcdGetPtr (PcdEmuMemorySize);
FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdEmuFirmwareVolume);
- printf ("\nEDK SEC Main UNIX Emulation Environment from edk2.sourceforge.net\n");
+ printf ("\nEDK II UNIX Emulation Environment from edk2.sourceforge.net\n");
//
// PPIs pased into PEI_CORE
//
- AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEfiTemporaryRamSupportPpiGuid, &mSecTemporaryRamSupportPpi);
AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuThunkPpiGuid, &mSecEmuThunkPpi);
- AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI, &gEmuPeiServicesTableUpdatePpiGuid, NULL);
SecInitThunkProtocol ();
//
AddThunkProtocol (&gX11ThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);
AddThunkProtocol (&gPosixFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);
-
+ AddThunkProtocol (&gBlockIoThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuVirtualDisk), TRUE);
+ AddThunkProtocol (&gSnpThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuNetworkInterface), TRUE);
+
//
// Emulator other Thunks
//
AddThunkProtocol (&gPthreadThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuApCount), FALSE);
// EmuSecLibConstructor ();
+
+ gPpiList = GetThunkPpiList ();
-#ifdef __APPLE__
//
- // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb
- // We need to create a temp file that contains gdb commands so we can load
- // symbols when we load every PE/COFF image.
+ // If dlopen doesn't work, then we build a gdb script to allow the
+ // symbols to be loaded.
//
Index = strlen (*Argv);
- gGdbWorkingFileName = malloc (Index + strlen(".gdb") + 1);
+ gGdbWorkingFileName = AllocatePool (Index + strlen(".gdb") + 1);
strcpy (gGdbWorkingFileName, *Argv);
strcat (gGdbWorkingFileName, ".gdb");
-#endif
+ //
+ // Empty out the gdb symbols script file.
+ //
+ GdbTempFile = fopen (gGdbWorkingFileName, "w");
+ if (GdbTempFile != NULL) {
+ fclose (GdbTempFile);
+ }
//
// Allocate space for gSystemMemory Array
//
gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1;
- gSystemMemory = calloc (gSystemMemoryCount, sizeof (EMU_SYSTEM_MEMORY));
+ gSystemMemory = AllocateZeroPool (gSystemMemoryCount * sizeof (EMU_SYSTEM_MEMORY));
if (gSystemMemory == NULL) {
printf ("ERROR : Can not allocate memory for system. Exiting.\n");
exit (1);
// Allocate space for gSystemMemory Array
//
gFdInfoCount = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1;
- gFdInfo = calloc (gFdInfoCount, sizeof (EMU_FD_INFO));
+ gFdInfo = AllocateZeroPool (gFdInfoCount * sizeof (EMU_FD_INFO));
if (gFdInfo == NULL) {
printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
exit (1);
printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode));
//
- // Open up a 128K file to emulate temp memory for PEI.
+ // Open up a 128K file to emulate temp memory for SEC.
// on a real platform this would be SRAM, or using the cache as RAM.
// Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
//
InitialStackMemorySize = STACK_SIZE;
- InitialStackMemory = (UINTN)MapMemory(0,
- (UINT32) InitialStackMemorySize,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_ANONYMOUS | MAP_PRIVATE);
+ InitialStackMemory = (UINTN)MapMemory (
+ 0, (UINT32) InitialStackMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE
+ );
if (InitialStackMemory == 0) {
printf ("ERROR : Can not open SecStack Exiting\n");
exit (1);
}
- printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n",
+ printf (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
(unsigned int)(InitialStackMemorySize / 1024),
- (unsigned long)InitialStackMemory);
+ (unsigned long)InitialStackMemory
+ );
for (StackPointer = (UINTN*) (UINTN) InitialStackMemory;
StackPointer < (UINTN*)(UINTN)((UINTN) InitialStackMemory + (UINT64) InitialStackMemorySize);
//
// Open All the firmware volumes and remember the info in the gFdInfo global
//
- FileName = (CHAR8 *)malloc (StrLen (FirmwareVolumesStr) + 1);
+ FileName = (CHAR8 *) AllocatePool (StrLen (FirmwareVolumesStr) + 1);
if (FileName == NULL) {
printf ("ERROR : Can not allocate memory for firmware volume string\n");
exit (1);
}
Index2 = 0;
- for (Done = FALSE, Index = 0, PeiIndex = 0, PeiCoreFile = NULL;
+ for (Done = FALSE, Index = 0, PeiIndex = 0, SecFile = NULL;
FirmwareVolumesStr[Index2] != 0;
Index++) {
- for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++)
+ for (Index1 = 0; (FirmwareVolumesStr[Index2] != '!') && (FirmwareVolumesStr[Index2] != 0); Index2++) {
FileName[Index1++] = FirmwareVolumesStr[Index2];
- if (FirmwareVolumesStr[Index2] == '!')
+ }
+ if (FirmwareVolumesStr[Index2] == '!') {
Index2++;
+ }
FileName[Index1] = '\0';
- //
- // Open the FD and remmeber where it got mapped into our processes address space
- //
- Status = MapFile (
- FileName,
- &gFdInfo[Index].Address,
- &gFdInfo[Index].Size
- );
+ if (Index == 0) {
+ // Map FV Recovery Read Only and other areas Read/Write
+ Status = MapFd0 (
+ FileName,
+ &gFdInfo[0].Address,
+ &gFdInfo[0].Size
+ );
+ } else {
+ //
+ // Open the FD and remmeber where it got mapped into our processes address space
+ // Maps Read Only
+ //
+ Status = MapFile (
+ FileName,
+ &gFdInfo[Index].Address,
+ &gFdInfo[Index].Size
+ );
+ }
if (EFI_ERROR (Status)) {
printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName, (unsigned int)Status);
exit (1);
}
- printf (" FD loaded from %s at 0x%08lx",
- FileName, (unsigned long)gFdInfo[Index].Address);
+ printf (" FD loaded from %s at 0x%08lx",FileName, (unsigned long)gFdInfo[Index].Address);
- if (PeiCoreFile == NULL) {
+ if (SecFile == NULL) {
//
- // Assume the beginning of the FD is an FV and look for the PEI Core.
+ // Assume the beginning of the FD is an FV and look for the SEC Core.
// Load the first one we find.
//
- Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);
+ FileHandle = NULL;
+ Status = PeiServicesFfsFindNextFile (
+ EFI_FV_FILETYPE_SECURITY_CORE,
+ (EFI_PEI_FV_HANDLE)(UINTN)gFdInfo[Index].Address,
+ &FileHandle
+ );
if (!EFI_ERROR (Status)) {
- PeiIndex = Index;
- printf (" contains SEC Core");
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, &SecFile);
+ if (!EFI_ERROR (Status)) {
+ PeiIndex = Index;
+ printf (" contains SEC Core");
+ }
}
}
Index1++;
}
gSystemMemory[Index++].Size = val * 0x100000;
- if (MemorySizeStr[Index1] == 0)
+ if (MemorySizeStr[Index1] == 0) {
break;
+ }
Index1++;
}
printf ("\n");
//
- // Hand off to PEI Core
+ // Hand off to SEC
//
- SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);
+ SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, SecFile);
//
- // If we get here, then the PEI Core returned. This is an error as PEI should
- // always hand off to DXE.
+ // If we get here, then the SEC Core returned. This is an error as SEC should
+ // always hand off to PEI Core and then on to DXE Core.
//
- printf ("ERROR : PEI Core returned\n");
+ printf ("ERROR : SEC returned\n");
exit (1);
}
+
EFI_PHYSICAL_ADDRESS *
MapMemory (
- INTN fd,
- UINT64 length,
- INTN prot,
- INTN flags)
+ IN INTN fd,
+ IN UINT64 length,
+ IN INTN prot,
+ IN INTN flags
+ )
{
STATIC UINTN base = 0x40000000;
CONST UINTN align = (1 << 24);
}
if ((((UINTN)res) & ~(align-1)) == (UINTN)res) {
isAligned=1;
- }
- else {
+ } else {
munmap(res, length);
base += align;
}
return res;
}
-EFI_STATUS
-MapFile (
- IN CHAR8 *FileName,
- IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
- OUT UINT64 *Length
- )
+
/*++
Routine Description:
EFI_DEVICE_ERROR - An error occured attempting to map the opened file
**/
+EFI_STATUS
+MapFile (
+ IN CHAR8 *FileName,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length
+ )
{
- int fd;
+ int fd;
VOID *res;
UINTN FileSize;
- fd = open (FileName, O_RDONLY);
- if (fd < 0)
+ fd = open (FileName, O_RDWR);
+ if (fd < 0) {
return EFI_NOT_FOUND;
+ }
FileSize = lseek (fd, 0, SEEK_END);
- res = MapMemory(fd, FileSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
+ res = MapMemory (fd, FileSize, PROT_READ | PROT_EXEC, MAP_PRIVATE);
close (fd);
- if (res == MAP_FAILED)
+ if (res == NULL) {
+ perror ("MapFile() Failed");
return EFI_DEVICE_ERROR;
-
+ }
+
*Length = (UINT64) FileSize;
*BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res;
return EFI_SUCCESS;
}
+EFI_STATUS
+MapFd0 (
+ IN CHAR8 *FileName,
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ OUT UINT64 *Length
+ )
+{
+ int fd;
+ void *res, *res2, *res3;
+ UINTN FileSize;
+ UINTN FvSize;
+ void *EmuMagicPage;
+
+ fd = open (FileName, O_RDWR);
+ if (fd < 0) {
+ return EFI_NOT_FOUND;
+ }
+ FileSize = lseek (fd, 0, SEEK_END);
+
+ FvSize = FixedPcdGet64 (PcdEmuFlashFvRecoverySize);
+
+ // Assume start of FD is Recovery FV, and make it write protected
+ res = mmap (
+ (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase),
+ FvSize,
+ PROT_READ | PROT_EXEC,
+ MAP_PRIVATE,
+ fd,
+ 0
+ );
+ if (res == MAP_FAILED) {
+ perror ("MapFd0() Failed res =");
+ close (fd);
+ return EFI_DEVICE_ERROR;
+ } else if (res != (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase)) {
+ // We could not load at the build address, so we need to allow writes
+ munmap (res, FvSize);
+ res = mmap (
+ (void *)(UINTN)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase),
+ FvSize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE,
+ fd,
+ 0
+ );
+ if (res == MAP_FAILED) {
+ perror ("MapFd0() Failed res =");
+ close (fd);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ // Map the rest of the FD as read/write
+ res2 = mmap (
+ (void *)(UINTN)(FixedPcdGet64 (PcdEmuFlashFvRecoveryBase) + FvSize),
+ FileSize - FvSize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED,
+ fd,
+ FvSize
+ );
+ close (fd);
+ if (res2 == MAP_FAILED) {
+ perror ("MapFd0() Failed res2 =");
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If enabled use the magic page to communicate between modules
+ // This replaces the PI PeiServicesTable pointer mechanism that
+ // deos not work in the emulator. It also allows the removal of
+ // writable globals from SEC, PEI_CORE (libraries), PEIMs
+ //
+ EmuMagicPage = (void *)(UINTN)FixedPcdGet64 (PcdPeiServicesTablePage);
+ if (EmuMagicPage != NULL) {
+ res3 = mmap (
+ (void *)EmuMagicPage,
+ 4096,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ 0,
+ 0
+ );
+ if (res3 != EmuMagicPage) {
+ printf ("MapFd0(): Could not allocate PeiServicesTablePage @ %lx\n", (long unsigned int)EmuMagicPage);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ *Length = (UINT64) FileSize;
+ *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) res;
+
+ return EFI_SUCCESS;
+}
-VOID
-SecLoadFromCore (
- IN UINTN LargestRegion,
- IN UINTN LargestRegionSize,
- IN UINTN BootFirmwareVolumeBase,
- IN VOID *PeiCorePe32File
- )
/*++
Routine Description:
- This is the service to load the PEI Core from the Firmware Volume
+ This is the service to load the SEC Core from the Firmware Volume
Arguments:
- LargestRegion - Memory to use for PEI.
+ LargestRegion - Memory to use for SEC.
LargestRegionSize - Size of Memory to use for PEI
BootFirmwareVolumeBase - Start of the Boot FV
- PeiCorePe32File - PEI Core PE32
+ PeiCorePe32File - SEC PE32
Returns:
Success means control is transfered and thus we should never return
**/
+VOID
+SecLoadFromCore (
+ IN UINTN LargestRegion,
+ IN UINTN LargestRegionSize,
+ IN UINTN BootFirmwareVolumeBase,
+ IN VOID *PeiCorePe32File
+ )
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TopOfMemory;
VOID *TopOfStack;
- UINT64 PeiCoreSize;
EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint;
- EFI_PHYSICAL_ADDRESS PeiImageAddress;
EFI_SEC_PEI_HAND_OFF *SecCoreData;
UINTN PeiStackSize;
//
// Bind this information into the SEC hand-off state
//
- SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack;
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack;
SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase;
SecCoreData->BootFirmwareVolumeSize = PcdGet32 (PcdEmuFirmwareFdSize);
SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize;
//
- // Load the PEI Core from a Firmware Volume
+ // Find the SEC Core Entry Point
//
- Status = SecUnixPeiLoadFile (
- PeiCorePe32File,
- &PeiImageAddress,
- &PeiCoreSize,
- &PeiCoreEntryPoint
- );
+ Status = SecPeCoffGetEntryPoint (PeiCorePe32File, (VOID **)&PeiCoreEntryPoint);
if (EFI_ERROR (Status)) {
return ;
}
//
- // Transfer control to the PEI Core
+ // Transfer control to the SEC Core
//
PeiSwitchStacks (
(SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint,
SecCoreData,
- (VOID *)GetThunkPpiList (),
- NULL,
+ (VOID *)gPpiList,
TopOfStack
);
//
- // If we get here, then the PEI Core returned. This is an error
+ // If we get here, then the SEC Core returned. This is an error
//
return ;
}
-EFI_STATUS
-EFIAPI
-SecUnixPeiAutoScan (
- IN UINTN Index,
- OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
- OUT UINT64 *MemorySize
- )
+
/*++
Routine Description:
EFI_UNSUPPORTED - If Index is not supported
**/
+EFI_STATUS
+SecUnixPeiAutoScan (
+ IN UINTN Index,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryBase,
+ OUT UINT64 *MemorySize
+ )
{
void *res;
}
*MemoryBase = 0;
- res = MapMemory(0, gSystemMemory[Index].Size,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS);
- if (res == MAP_FAILED)
+ res = MapMemory (
+ 0, gSystemMemory[Index].Size,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS
+ );
+ if (res == MAP_FAILED) {
return EFI_DEVICE_ERROR;
+ }
*MemorySize = gSystemMemory[Index].Size;
*MemoryBase = (UINTN)res;
gSystemMemory[Index].Memory = *MemoryBase;
return EFI_SUCCESS;
}
-VOID *
-EFIAPI
-SecEmuThunkAddress (
- VOID
- )
+
/*++
Routine Description:
- Since the SEC is the only Unix program in stack it must export
- an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
+ Check to see if an address range is in the EFI GCD memory map.
+
+ This is all of GCD for system memory passed to DXE Core. FV
+ mapping and other device mapped into system memory are not
+ inlcuded in the check.
Arguments:
- InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
- InterfaceBase - Address of the gUnix global
+ Index - Which memory region to use
+ MemoryBase - Return Base address of memory region
+ MemorySize - Return size in bytes of the memory region
Returns:
- EFI_SUCCESS - Data returned
+ TRUE - Address is in the EFI GCD memory map
+ FALSE - Address is NOT in memory map
**/
+BOOLEAN
+EfiSystemMemoryRange (
+ IN VOID *MemoryAddress
+ )
{
- return &gEmuThunkProtocol;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS MemoryBase;
+
+ MemoryBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
+ for (Index = 0; Index < gSystemMemoryCount; Index++) {
+ if ((MemoryBase >= gSystemMemory[Index].Memory) &&
+ (MemoryBase < (gSystemMemory[Index].Memory + gSystemMemory[Index].Size)) ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
}
-EFI_STATUS
-SecUnixPeiLoadFile (
- IN VOID *Pe32Data,
- OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
- OUT UINT64 *ImageSize,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint
- )
/*++
Routine Description:
- Loads and relocates a PE/COFF image into memory.
+ Since the SEC is the only Unix program in stack it must export
+ an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
Arguments:
- Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
- ImageAddress - The base address of the relocated PE/COFF image
- ImageSize - The size of the relocated PE/COFF image
- EntryPoint - The entry point of the relocated PE/COFF image
+ InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
+ InterfaceBase - Address of the gUnix global
Returns:
- EFI_SUCCESS - The file was loaded and relocated
- EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
+ EFI_SUCCESS - Data returned
**/
+VOID *
+SecEmuThunkAddress (
+ VOID
+ )
{
- EFI_STATUS Status;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ return &gEmuThunkProtocol;
+}
+
+
+
+RETURN_STATUS
+EFIAPI
+SecPeCoffGetEntryPoint (
+ IN VOID *Pe32Data,
+ IN OUT VOID **EntryPoint
+ )
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
ZeroMem (&ImageContext, sizeof (ImageContext));
ImageContext.Handle = Pe32Data;
-
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead;
Status = PeCoffLoaderGetImageInfo (&ImageContext);
return Status;
}
+ if (ImageContext.ImageAddress != (UINTN)Pe32Data) {
+ //
+ // Relocate image to match the address where it resides
+ //
+ ImageContext.ImageAddress = (UINTN)Pe32Data;
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
- //
- // Allocate space in UNIX (not emulator) memory. Extra space is for alignment
- //
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) MapMemory (
- 0,
- (UINT32) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)),
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_ANONYMOUS | MAP_PRIVATE
- );
- if (ImageContext.ImageAddress == 0) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Align buffer on section boundry
- //
- ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
- ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1));
-
-
- Status = PeCoffLoaderLoadImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = PeCoffLoaderRelocateImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- return Status;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // Or just return image entry point
+ //
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer (Pe32Data);
+ Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ImageContext.EntryPoint = (UINTN)*EntryPoint;
}
-
+ // On Unix a dlopen is done that will change the entry point
SecPeCoffRelocateImageExtraAction (&ImageContext);
-
- //
- // BugBug: Flush Instruction Cache Here when CPU Lib is ready
- //
-
- *ImageAddress = ImageContext.ImageAddress;
- *ImageSize = ImageContext.ImageSize;
- *EntryPoint = ImageContext.EntryPoint;
-
- return EFI_SUCCESS;
-}
-
-
-RETURN_STATUS
-EFIAPI
-SecPeCoffGetEntryPoint (
- IN VOID *Pe32Data,
- IN OUT VOID **EntryPoint
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS ImageAddress;
- UINT64 ImageSize;
- EFI_PHYSICAL_ADDRESS PhysEntryPoint;
-
- Status = SecUnixPeiLoadFile (Pe32Data, &ImageAddress, &ImageSize, &PhysEntryPoint);
-
- *EntryPoint = (VOID *)(UINTN)PhysEntryPoint;
+ *EntryPoint = (VOID *)(UINTN)ImageContext.EntryPoint;
+
return Status;
}
-EFI_STATUS
-EFIAPI
-SecUnixFdAddress (
- IN UINTN Index,
- IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
- IN OUT UINT64 *FdSize,
- IN OUT EFI_PHYSICAL_ADDRESS *FixUp
- )
/*++
Routine Description:
EFI_UNSUPPORTED - Index does nto map to an FD in the system
**/
+EFI_STATUS
+SecUnixFdAddress (
+ IN UINTN Index,
+ IN OUT EFI_PHYSICAL_ADDRESS *FdBase,
+ IN OUT UINT64 *FdSize,
+ IN OUT EFI_PHYSICAL_ADDRESS *FixUp
+ )
{
if (Index >= gFdInfoCount) {
return EFI_UNSUPPORTED;
return EFI_SUCCESS;
}
+
+/*++
+
+Routine Description:
+ Count the number of seperators in String
+
+Arguments:
+ String - String to process
+ Seperator - Item to count
+
+Returns:
+ Number of Seperator in String
+
+**/
+UINTN
+CountSeperatorsInString (
+ IN const CHAR16 *String,
+ IN CHAR16 Seperator
+ )
+{
+ UINTN Count;
+
+ for (Count = 0; *String != '\0'; String++) {
+ if (*String == Seperator) {
+ Count++;
+ }
+ }
+
+ return Count;
+}
+
+
EFI_STATUS
EFIAPI
SecImageRead (
return EFI_SUCCESS;
}
-UINTN
-CountSeperatorsInString (
- IN const CHAR16 *String,
- IN CHAR16 Seperator
- )
-/*++
-
-Routine Description:
- Count the number of seperators in String
-
-Arguments:
- String - String to process
- Seperator - Item to count
-Returns:
- Number of Seperator in String
-
-**/
-{
- UINTN Count;
-
- for (Count = 0; *String != '\0'; String++) {
- if (*String == Seperator) {
- Count++;
- }
- }
-
- return Count;
-}
-
-
-EFI_STATUS
-AddHandle (
- IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
- IN VOID *ModHandle
- )
/*++
Routine Description:
EFI_SUCCESS - ModHandle was stored.
**/
+EFI_STATUS
+AddHandle (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN VOID *ModHandle
+ )
{
UINTN Index;
IMAGE_CONTEXT_TO_MOD_HANDLE *Array;
PreviousSize = mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE);
mImageContextModHandleArraySize += MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE;
- mImageContextModHandleArray = realloc (mImageContextModHandleArray, mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE));
+ mImageContextModHandleArray = ReallocatePool (
+ (mImageContextModHandleArraySize - 1) * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE),
+ mImageContextModHandleArraySize * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE),
+ mImageContextModHandleArray
+ );
if (mImageContextModHandleArray == NULL) {
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
-VOID *
-RemoveHandle (
- IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
- )
/*++
Routine Description:
NULL - No ModHandle associated with ImageContext
**/
+VOID *
+RemoveHandle (
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
{
UINTN Index;
IMAGE_CONTEXT_TO_MOD_HANDLE *Array;
// b SecGdbScriptBreak
// command
// silent
-// source SecMain.dll.gdb
+// source SecMain.gdb
// c
// end
//
}
-VOID
-EFIAPI
-SecPeCoffRelocateImageExtraAction (
+/**
+ Loads the image using dlopen so symbols will be automatically
+ loaded by gdb.
+
+ @param ImageContext The PE/COFF image context
+
+ @retval TRUE - The image was successfully loaded
+ @retval FALSE - The image was successfully loaded
+
+**/
+BOOLEAN
+DlLoadImage (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
)
{
#ifdef __APPLE__
- BOOLEAN EnabledOnEntry;
+
+ return FALSE;
+
+#else
+
+ void *Handle = NULL;
+ void *Entry = NULL;
+
+ if (ImageContext->PdbPointer == NULL) {
+ return FALSE;
+ }
+
+ if (!IsPdbFile (ImageContext->PdbPointer)) {
+ return FALSE;
+ }
+
+ fprintf (
+ stderr,
+ "Loading %s 0x%08lx - entry point 0x%08lx\n",
+ ImageContext->PdbPointer,
+ (unsigned long)ImageContext->ImageAddress,
+ (unsigned long)ImageContext->EntryPoint
+ );
+
+ Handle = dlopen (ImageContext->PdbPointer, RTLD_NOW);
+
+ if (Handle) {
+ Entry = dlsym (Handle, "_ModuleEntryPoint");
+ } else {
+ printf("%s\n", dlerror());
+ }
+
+ if (Entry != NULL) {
+ ImageContext->EntryPoint = (UINTN)Entry;
+ printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+
+#endif
+}
+
+
+/**
+ Adds the image to a gdb script so it's symbols can be loaded.
+ The AddFirmwareSymbolFile helper macro is used.
+
+ @param ImageContext The PE/COFF image context
+
+**/
+VOID
+GdbScriptAddImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ BOOLEAN InterruptsWereEnabled;
//
- // Make sure writting of the file is an atomic operation
+ // Disable interrupts to make sure writing of the .gdb file
+ // is an atomic operation.
//
if (SecInterruptEanbled ()) {
SecDisableInterrupt ();
- EnabledOnEntry = TRUE;
+ InterruptsWereEnabled = TRUE;
} else {
- EnabledOnEntry = FALSE;
+ InterruptsWereEnabled = FALSE;
}
PrintLoadAddress (ImageContext);
- //
- // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format.
- // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create
- // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging.
- //
- FILE *GdbTempFile;
-
- //
- // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for.
- // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table.
- //
if (ImageContext->PdbPointer != NULL && !IsPdbFile (ImageContext->PdbPointer)) {
- //
- // Now we have a database of the images that are currently loaded
- //
-
- //
- // 'symbol-file' will clear out currnet symbol mappings in gdb.
- // you can do a 'add-symbol-file filename address' for every image we loaded to get source
- // level debug in gdb. Note Sec, being a true application will work differently.
- //
- // We add the PE/COFF header size into the image as the mach-O does not have a header in
- // loaded into system memory.
- //
- // This gives us a data base of gdb commands and after something is unloaded that entry will be
- // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the
- // data base of info ready to roll.
- //
- // We could use qXfer:libraries:read, but OS X GDB does not currently support it.
- // <library-list>
- // <library name="/lib/libc.so.6"> // ImageContext->PdbPointer
- // <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders
- // </library>
- // </library-list>
- //
-
- //
- // Write the file we need for the gdb script
- //
- GdbTempFile = fopen (gGdbWorkingFileName, "w");
+ FILE *GdbTempFile;
+ GdbTempFile = fopen (gGdbWorkingFileName, "a");
if (GdbTempFile != NULL) {
- fprintf (GdbTempFile, "add-symbol-file %s 0x%08lx\n", ImageContext->PdbPointer, (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders));
+ long unsigned int SymbolsAddr = (long unsigned int)(ImageContext->ImageAddress + ImageContext->SizeOfHeaders);
+ mScriptSymbolChangesCount++;
+ fprintf (
+ GdbTempFile,
+ "AddFirmwareSymbolFile 0x%x %s 0x%08lx\n",
+ mScriptSymbolChangesCount,
+ ImageContext->PdbPointer,
+ SymbolsAddr
+ );
fclose (GdbTempFile);
-
- //
- // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
- // Hey what can you say scripting in gdb is not that great....
- //
- SecGdbScriptBreak ();
} else {
ASSERT (FALSE);
}
AddHandle (ImageContext, ImageContext->PdbPointer);
- if (EnabledOnEntry) {
+ if (InterruptsWereEnabled) {
SecEnableInterrupt ();
}
-
}
+}
-#else
-
- void *Handle = NULL;
- void *Entry = NULL;
- if (ImageContext->PdbPointer == NULL) {
- return;
+VOID
+EFIAPI
+SecPeCoffRelocateImageExtraAction (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ if (!DlLoadImage (ImageContext)) {
+ GdbScriptAddImage (ImageContext);
}
+}
- if (!IsPdbFile (ImageContext->PdbPointer)) {
- return;
- }
- fprintf (stderr,
- "Loading %s 0x%08lx - entry point 0x%08lx\n",
- ImageContext->PdbPointer,
- (unsigned long)ImageContext->ImageAddress,
- (unsigned long)ImageContext->EntryPoint);
+/**
+ Adds the image to a gdb script so it's symbols can be unloaded.
+ The RemoveFirmwareSymbolFile helper macro is used.
- Handle = dlopen (ImageContext->PdbPointer, RTLD_NOW);
+ @param ImageContext The PE/COFF image context
- if (Handle) {
- Entry = dlsym (Handle, "_ModuleEntryPoint");
- } else {
- printf("%s\n", dlerror());
- }
+**/
+VOID
+GdbScriptRemoveImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ FILE *GdbTempFile;
+ BOOLEAN InterruptsWereEnabled;
- if (Entry != NULL) {
- ImageContext->EntryPoint = (UINTN)Entry;
- printf("Change %s Entrypoint to :0x%08lx\n", ImageContext->PdbPointer, (unsigned long)Entry);
+ //
+ // Need to skip .PDB files created from VC++
+ //
+ if (IsPdbFile (ImageContext->PdbPointer)) {
+ return;
}
- SecUnixLoaderBreak ();
-
-#endif
+ if (SecInterruptEanbled ()) {
+ SecDisableInterrupt ();
+ InterruptsWereEnabled = TRUE;
+ } else {
+ InterruptsWereEnabled = FALSE;
+ }
- return;
+ //
+ // Write the file we need for the gdb script
+ //
+ GdbTempFile = fopen (gGdbWorkingFileName, "a");
+ if (GdbTempFile != NULL) {
+ mScriptSymbolChangesCount++;
+ fprintf (
+ GdbTempFile,
+ "RemoveFirmwareSymbolFile 0x%x %s\n",
+ mScriptSymbolChangesCount,
+ ImageContext->PdbPointer
+ );
+ fclose (GdbTempFile);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ if (InterruptsWereEnabled) {
+ SecEnableInterrupt ();
+ }
}
{
VOID *Handle;
- Handle = RemoveHandle (ImageContext);
-
-#ifdef __APPLE__
- FILE *GdbTempFile;
- BOOLEAN EnabledOnEntry;
-
- if (Handle != NULL) {
- //
- // Need to skip .PDB files created from VC++
- //
- if (!IsPdbFile (ImageContext->PdbPointer)) {
- if (SecInterruptEanbled ()) {
- SecDisableInterrupt ();
- EnabledOnEntry = TRUE;
- } else {
- EnabledOnEntry = FALSE;
- }
-
- //
- // Write the file we need for the gdb script
- //
- GdbTempFile = fopen (gGdbWorkingFileName, "w");
- if (GdbTempFile != NULL) {
- fprintf (GdbTempFile, "remove-symbol-file %s\n", ImageContext->PdbPointer);
- fclose (GdbTempFile);
-
- //
- // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
- // Hey what can you say scripting in gdb is not that great....
- //
- SecGdbScriptBreak ();
- } else {
- ASSERT (FALSE);
- }
-
- if (EnabledOnEntry) {
- SecEnableInterrupt ();
- }
- }
- }
-
-#else
//
- // Don't want to confuse gdb with symbols for something that got unloaded
+ // Check to see if the image symbols were loaded with gdb script, or dlopen
//
- if (Handle != NULL) {
+ Handle = RemoveHandle (ImageContext);
+
+ if (Handle == NULL) {
+#ifndef __APPLE__
dlclose (Handle);
+#endif
+ return;
}
-#endif
- return;
+ GdbScriptRemoveImage (ImageContext);
}