]> git.proxmox.com Git - mirror_edk2.git/blobdiff - InOsEmuPkg/Unix/Sec/SecMain.c
InOsEmuPkg/Unix: Auto-load symbols files in gdb
[mirror_edk2.git] / InOsEmuPkg / Unix / Sec / SecMain.c
index 8677ab59382ff3c4f2316fbd7990ca173d2a8ad3..61847b53485a8a3d80e2bcad2aaf69585099167b 100644 (file)
@@ -16,7 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 #ifdef __APPLE__
 #define MAP_ANONYMOUS MAP_ANON
-char *gGdbWorkingFileName = NULL;
 #endif
 
 
@@ -27,14 +26,11 @@ char *gGdbWorkingFileName = NULL;
 EMU_THUNK_PPI mSecEmuThunkPpi = {
   GasketSecUnixPeiAutoScan,
   GasketSecUnixFdAddress,
-  GasketSecEmuThunkAddress,
-  GasketSecUnixPeiLoadFile
-};
-
-EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = { 
-  GasketSecTemporaryRamSupport
+  GasketSecEmuThunkAddress
 };
 
+char *gGdbWorkingFileName = NULL;
+UINTN mScriptSymbolChangesCount = 0;
 
 
 //
@@ -44,8 +40,8 @@ EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {
 //  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.
@@ -53,43 +49,16 @@ EMU_FD_INFO                              *gFdInfo;
 //  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:
@@ -105,6 +74,12 @@ Returns:
   1 - Abnormal exit
 
 **/
+int
+main (
+  IN  int   Argc,
+  IN  char  **Argv,
+  IN  char  **Envp
+  )
 {
   EFI_STATUS            Status;
   EFI_PHYSICAL_ADDRESS  InitialStackMemory;
@@ -115,25 +90,25 @@ Returns:
   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 ();
   
@@ -142,32 +117,40 @@ Returns:
   //
   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);
@@ -176,7 +159,7 @@ Returns:
   // 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);
@@ -185,23 +168,24 @@ Returns:
   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);
@@ -212,47 +196,66 @@ Returns:
   //
   // 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");
+        }
       }
     }
 
@@ -275,32 +278,35 @@ Returns:
       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);
@@ -318,8 +324,7 @@ MapMemory (
     }
     if ((((UINTN)res) & ~(align-1)) == (UINTN)res) {
       isAligned=1;
-    }
-    else {
+    } else {
       munmap(res, length);
       base += align;
     }
@@ -327,12 +332,7 @@ MapMemory (
   return res;
 }
 
-EFI_STATUS
-MapFile (
-  IN  CHAR8                     *FileName,
-  IN OUT  EFI_PHYSICAL_ADDRESS  *BaseAddress,
-  OUT UINT64                    *Length
-  )
+
 /*++
 
 Routine Description:
@@ -356,61 +356,162 @@ Returns:
   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;
 
@@ -442,7 +543,7 @@ Returns:
   //
   // 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);
@@ -454,41 +555,29 @@ Returns:
   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:
@@ -509,6 +598,12 @@ Returns:
   EFI_UNSUPPORTED - If Index is not supported
 
 **/
+EFI_STATUS
+SecUnixPeiAutoScan (
+  IN  UINTN                 Index,
+  OUT EFI_PHYSICAL_ADDRESS  *MemoryBase,
+  OUT UINT64                *MemorySize
+  )
 {
   void *res;
 
@@ -517,11 +612,14 @@ Returns:
   }
 
   *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;
@@ -529,60 +627,82 @@ Returns:
   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);
@@ -590,80 +710,41 @@ Returns:
     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:
@@ -681,6 +762,13 @@ Returns:
   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;
@@ -706,6 +794,38 @@ Returns:
   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 (
@@ -744,42 +864,7 @@ Returns:
   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:
@@ -796,6 +881,11 @@ Returns:
   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;
@@ -823,7 +913,11 @@ Returns:
   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;
@@ -835,10 +929,6 @@ Returns:
 }
 
 
-VOID *
-RemoveHandle (
-  IN  PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext
-  )
 /*++
 
 Routine Description:
@@ -853,6 +943,10 @@ Returns:
   NULL      - No ModHandle associated with ImageContext
 
 **/
+VOID *
+RemoveHandle (
+  IN  PE_COFF_LOADER_IMAGE_CONTEXT         *ImageContext
+  )
 {
   UINTN                        Index;
   IMAGE_CONTEXT_TO_MOD_HANDLE  *Array;
@@ -890,7 +984,7 @@ Returns:
 // b SecGdbScriptBreak
 // command
 // silent
-// source SecMain.dll.gdb
+// source SecMain.gdb
 // c
 // end
 //
@@ -960,127 +1054,183 @@ PrintLoadAddress (
 }
 
 
-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 ();
+  }
 }
 
 
@@ -1092,57 +1242,19 @@ SecPeCoffUnloadImageExtraAction (
 {
   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);
 }