3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #define MAP_ANONYMOUS MAP_ANON
26 EMU_THUNK_PPI mSecEmuThunkPpi
= {
27 GasketSecUnixPeiAutoScan
,
28 GasketSecUnixFdAddress
,
29 GasketSecEmuThunkAddress
32 char *gGdbWorkingFileName
= NULL
;
33 UINTN mScriptSymbolChangesCount
= 0;
37 // Default information about where the FD is located.
38 // This array gets filled in with information from EFI_FIRMWARE_VOLUMES
39 // EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd.
40 // The number of array elements is allocated base on parsing
41 // EFI_FIRMWARE_VOLUMES and the memory is never freed.
43 UINTN gFdInfoCount
= 0;
47 // Array that supports seperate memory rantes.
48 // The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
49 // The number of array elements is allocated base on parsing
50 // EFI_MEMORY_SIZE and the memory is never freed.
52 UINTN gSystemMemoryCount
= 0;
53 EMU_SYSTEM_MEMORY
*gSystemMemory
;
57 UINTN mImageContextModHandleArraySize
= 0;
58 IMAGE_CONTEXT_TO_MOD_HANDLE
*mImageContextModHandleArray
= NULL
;
60 EFI_PEI_PPI_DESCRIPTOR
*gPpiList
;
65 Main entry point to SEC for Unix. This is a unix program
68 Argc - Number of command line arguments
69 Argv - Array of command line argument strings
70 Envp - Array of environmemt variable strings
85 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
86 UINT64 InitialStackMemorySize
;
93 EFI_PEI_FILE_HANDLE FileHandle
;
95 CHAR16
*MemorySizeStr
;
96 CHAR16
*FirmwareVolumesStr
;
103 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdEmuMemorySize
);
104 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdEmuFirmwareVolume
);
106 printf ("\nEDK II UNIX Emulation Environment from edk2.sourceforge.net\n");
109 // PPIs pased into PEI_CORE
111 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI
, &gEmuThunkPpiGuid
, &mSecEmuThunkPpi
);
113 SecInitThunkProtocol ();
116 // Emulator Bus Driver Thunks
118 AddThunkProtocol (&gX11ThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuGop
), TRUE
);
119 AddThunkProtocol (&gPosixFileSystemThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuFileSystem
), TRUE
);
120 AddThunkProtocol (&gBlockIoThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuVirtualDisk
), TRUE
);
121 AddThunkProtocol (&gSnpThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuNetworkInterface
), TRUE
);
124 // Emulator other Thunks
126 AddThunkProtocol (&gPthreadThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuApCount
), FALSE
);
128 // EmuSecLibConstructor ();
130 gPpiList
= GetThunkPpiList ();
133 // If dlopen doesn't work, then we build a gdb script to allow the
134 // symbols to be loaded.
136 Index
= strlen (*Argv
);
137 gGdbWorkingFileName
= AllocatePool (Index
+ strlen(".gdb") + 1);
138 strcpy (gGdbWorkingFileName
, *Argv
);
139 strcat (gGdbWorkingFileName
, ".gdb");
142 // Empty out the gdb symbols script file.
144 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
145 if (GdbTempFile
!= NULL
) {
146 fclose (GdbTempFile
);
150 // Allocate space for gSystemMemory Array
152 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
153 gSystemMemory
= AllocateZeroPool (gSystemMemoryCount
* sizeof (EMU_SYSTEM_MEMORY
));
154 if (gSystemMemory
== NULL
) {
155 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
159 // Allocate space for gSystemMemory Array
161 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
162 gFdInfo
= AllocateZeroPool (gFdInfoCount
* sizeof (EMU_FD_INFO
));
163 if (gFdInfo
== NULL
) {
164 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
168 printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode
));
171 // Open up a 128K file to emulate temp memory for SEC.
172 // on a real platform this would be SRAM, or using the cache as RAM.
173 // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
175 InitialStackMemorySize
= STACK_SIZE
;
176 InitialStackMemory
= (UINTN
)MapMemory (
177 0, (UINT32
) InitialStackMemorySize
,
178 PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_ANONYMOUS
| MAP_PRIVATE
180 if (InitialStackMemory
== 0) {
181 printf ("ERROR : Can not open SecStack Exiting\n");
185 printf (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
186 (unsigned int)(InitialStackMemorySize
/ 1024),
187 (unsigned long)InitialStackMemory
190 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
191 StackPointer
< (UINTN
*)(UINTN
)((UINTN
) InitialStackMemory
+ (UINT64
) InitialStackMemorySize
);
193 *StackPointer
= 0x5AA55AA5;
197 // Open All the firmware volumes and remember the info in the gFdInfo global
199 FileName
= (CHAR8
*) AllocatePool (StrLen (FirmwareVolumesStr
) + 1);
200 if (FileName
== NULL
) {
201 printf ("ERROR : Can not allocate memory for firmware volume string\n");
206 for (Done
= FALSE
, Index
= 0, PeiIndex
= 0, SecFile
= NULL
;
207 FirmwareVolumesStr
[Index2
] != 0;
209 for (Index1
= 0; (FirmwareVolumesStr
[Index2
] != '!') && (FirmwareVolumesStr
[Index2
] != 0); Index2
++) {
210 FileName
[Index1
++] = FirmwareVolumesStr
[Index2
];
212 if (FirmwareVolumesStr
[Index2
] == '!') {
215 FileName
[Index1
] = '\0';
218 // Map FV Recovery Read Only and other areas Read/Write
226 // Open the FD and remmeber where it got mapped into our processes address space
231 &gFdInfo
[Index
].Address
,
235 if (EFI_ERROR (Status
)) {
236 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName
, (unsigned int)Status
);
240 printf (" FD loaded from %s at 0x%08lx",FileName
, (unsigned long)gFdInfo
[Index
].Address
);
242 if (SecFile
== NULL
) {
244 // Assume the beginning of the FD is an FV and look for the SEC Core.
245 // Load the first one we find.
248 Status
= PeiServicesFfsFindNextFile (
249 EFI_FV_FILETYPE_SECURITY_CORE
,
250 (EFI_PEI_FV_HANDLE
)(UINTN
)gFdInfo
[Index
].Address
,
253 if (!EFI_ERROR (Status
)) {
254 Status
= PeiServicesFfsFindSectionData (EFI_SECTION_PE32
, FileHandle
, &SecFile
);
255 if (!EFI_ERROR (Status
)) {
257 printf (" contains SEC Core");
265 // Calculate memory regions and store the information in the gSystemMemory
266 // global for later use. The autosizing code will use this data to
267 // map this memory into the SEC process memory space.
274 // Save the size of the memory.
276 while (MemorySizeStr
[Index1
] >= '0' && MemorySizeStr
[Index1
] <= '9') {
277 val
= val
* 10 + MemorySizeStr
[Index1
] - '0';
280 gSystemMemory
[Index
++].Size
= val
* 0x100000;
281 if (MemorySizeStr
[Index1
] == 0) {
292 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, SecFile
);
295 // If we get here, then the SEC Core returned. This is an error as SEC should
296 // always hand off to PEI Core and then on to DXE Core.
298 printf ("ERROR : SEC returned\n");
303 EFI_PHYSICAL_ADDRESS
*
311 STATIC UINTN base
= 0x40000000;
312 CONST UINTN align
= (1 << 24);
314 BOOLEAN isAligned
= 0;
317 // Try to get an aligned block somewhere in the address space of this
320 while((!isAligned
) && (base
!= 0)) {
321 res
= mmap ((void *)base
, length
, prot
, flags
, fd
, 0);
322 if (res
== MAP_FAILED
) {
325 if ((((UINTN
)res
) & ~(align
-1)) == (UINTN
)res
) {
339 Opens and memory maps a file using Unix services. If BaseAddress is non zero
340 the process will try and allocate the memory starting at BaseAddress.
343 FileName - The name of the file to open and map
344 MapSize - The amount of the file to map in bytes
345 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
346 memory emulation, and exiting files for firmware volume emulation
347 BaseAddress - The base address of the mapped file in the user address space.
348 If passed in as NULL the a new memory region is used.
349 If passed in as non NULL the request memory region is used for
350 the mapping of the file into the process space.
351 Length - The size of the mapped region in bytes
354 EFI_SUCCESS - The file was opened and mapped.
355 EFI_NOT_FOUND - FileName was not found in the current directory
356 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
362 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
370 fd
= open (FileName
, O_RDWR
);
372 return EFI_NOT_FOUND
;
374 FileSize
= lseek (fd
, 0, SEEK_END
);
377 res
= MapMemory (fd
, FileSize
, PROT_READ
| PROT_EXEC
, MAP_PRIVATE
);
382 perror ("MapFile() Failed");
383 return EFI_DEVICE_ERROR
;
386 *Length
= (UINT64
) FileSize
;
387 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
395 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
400 void *res
, *res2
, *res3
;
405 fd
= open (FileName
, O_RDWR
);
407 return EFI_NOT_FOUND
;
409 FileSize
= lseek (fd
, 0, SEEK_END
);
411 FvSize
= FixedPcdGet64 (PcdEmuFlashFvRecoverySize
);
413 // Assume start of FD is Recovery FV, and make it write protected
415 (void *)(UINTN
)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
),
417 PROT_READ
| PROT_EXEC
,
422 if (res
== MAP_FAILED
) {
423 perror ("MapFd0() Failed res =");
425 return EFI_DEVICE_ERROR
;
426 } else if (res
!= (void *)(UINTN
)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
)) {
427 // We could not load at the build address, so we need to allow writes
428 munmap (res
, FvSize
);
430 (void *)(UINTN
)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
),
432 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
437 if (res
== MAP_FAILED
) {
438 perror ("MapFd0() Failed res =");
440 return EFI_DEVICE_ERROR
;
444 // Map the rest of the FD as read/write
446 (void *)(UINTN
)(FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
) + FvSize
),
448 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
454 if (res2
== MAP_FAILED
) {
455 perror ("MapFd0() Failed res2 =");
456 return EFI_DEVICE_ERROR
;
460 // If enabled use the magic page to communicate between modules
461 // This replaces the PI PeiServicesTable pointer mechanism that
462 // deos not work in the emulator. It also allows the removal of
463 // writable globals from SEC, PEI_CORE (libraries), PEIMs
465 EmuMagicPage
= (void *)(UINTN
)FixedPcdGet64 (PcdPeiServicesTablePage
);
466 if (EmuMagicPage
!= NULL
) {
468 (void *)EmuMagicPage
,
470 PROT_READ
| PROT_WRITE
,
471 MAP_PRIVATE
| MAP_ANONYMOUS
,
475 if (res3
!= EmuMagicPage
) {
476 printf ("MapFd0(): Could not allocate PeiServicesTablePage @ %lx\n", (long unsigned int)EmuMagicPage
);
477 return EFI_DEVICE_ERROR
;
481 *Length
= (UINT64
) FileSize
;
482 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
491 This is the service to load the SEC Core from the Firmware Volume
494 LargestRegion - Memory to use for SEC.
495 LargestRegionSize - Size of Memory to use for PEI
496 BootFirmwareVolumeBase - Start of the Boot FV
497 PeiCorePe32File - SEC PE32
500 Success means control is transfered and thus we should never return
505 IN UINTN LargestRegion
,
506 IN UINTN LargestRegionSize
,
507 IN UINTN BootFirmwareVolumeBase
,
508 IN VOID
*PeiCorePe32File
512 EFI_PHYSICAL_ADDRESS TopOfMemory
;
514 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
515 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
519 // Compute Top Of Memory for Stack and PEI Core Allocations
521 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
522 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
525 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
528 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
531 // |-----------| <---- TemporaryRamBase
533 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
534 TopOfMemory
= LargestRegion
+ PeiStackSize
;
537 // Reservet space for storing PeiCore's parament in stack.
539 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
540 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
544 // Bind this information into the SEC hand-off state
546 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
547 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
548 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
549 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32 (PcdEmuFirmwareFdSize
);
550 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
551 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
552 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
553 SecCoreData
->StackSize
= PeiStackSize
;
554 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
555 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
558 // Find the SEC Core Entry Point
560 Status
= SecPeCoffGetEntryPoint (PeiCorePe32File
, (VOID
**)&PeiCoreEntryPoint
);
561 if (EFI_ERROR (Status
)) {
566 // Transfer control to the SEC Core
569 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
575 // If we get here, then the SEC Core returned. This is an error
584 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
585 It allows discontiguous memory regions to be supported by the emulator.
586 It uses gSystemMemory[] and gSystemMemoryCount that were created by
587 parsing the host environment variable EFI_MEMORY_SIZE.
588 The size comes from the varaible and the address comes from the call to
592 Index - Which memory region to use
593 MemoryBase - Return Base address of memory region
594 MemorySize - Return size in bytes of the memory region
597 EFI_SUCCESS - If memory region was mapped
598 EFI_UNSUPPORTED - If Index is not supported
604 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
605 OUT UINT64
*MemorySize
610 if (Index
>= gSystemMemoryCount
) {
611 return EFI_UNSUPPORTED
;
616 0, gSystemMemory
[Index
].Size
,
617 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
618 MAP_PRIVATE
| MAP_ANONYMOUS
620 if (res
== MAP_FAILED
) {
621 return EFI_DEVICE_ERROR
;
623 *MemorySize
= gSystemMemory
[Index
].Size
;
624 *MemoryBase
= (UINTN
)res
;
625 gSystemMemory
[Index
].Memory
= *MemoryBase
;
634 Check to see if an address range is in the EFI GCD memory map.
636 This is all of GCD for system memory passed to DXE Core. FV
637 mapping and other device mapped into system memory are not
638 inlcuded in the check.
641 Index - Which memory region to use
642 MemoryBase - Return Base address of memory region
643 MemorySize - Return size in bytes of the memory region
646 TRUE - Address is in the EFI GCD memory map
647 FALSE - Address is NOT in memory map
651 EfiSystemMemoryRange (
652 IN VOID
*MemoryAddress
656 EFI_PHYSICAL_ADDRESS MemoryBase
;
658 MemoryBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)MemoryAddress
;
659 for (Index
= 0; Index
< gSystemMemoryCount
; Index
++) {
660 if ((MemoryBase
>= gSystemMemory
[Index
].Memory
) &&
661 (MemoryBase
< (gSystemMemory
[Index
].Memory
+ gSystemMemory
[Index
].Size
)) ) {
673 Since the SEC is the only Unix program in stack it must export
674 an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
677 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
678 InterfaceBase - Address of the gUnix global
681 EFI_SUCCESS - Data returned
689 return &gEmuThunkProtocol
;
696 SecPeCoffGetEntryPoint (
698 IN OUT VOID
**EntryPoint
702 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
704 ZeroMem (&ImageContext
, sizeof (ImageContext
));
705 ImageContext
.Handle
= Pe32Data
;
706 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
708 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
709 if (EFI_ERROR (Status
)) {
713 if (ImageContext
.ImageAddress
!= (UINTN
)Pe32Data
) {
715 // Relocate image to match the address where it resides
717 ImageContext
.ImageAddress
= (UINTN
)Pe32Data
;
718 Status
= PeCoffLoaderLoadImage (&ImageContext
);
719 if (EFI_ERROR (Status
)) {
723 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
724 if (EFI_ERROR (Status
)) {
729 // Or just return image entry point
731 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer (Pe32Data
);
732 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, EntryPoint
);
733 if (EFI_ERROR (Status
)) {
736 ImageContext
.EntryPoint
= (UINTN
)*EntryPoint
;
739 // On Unix a dlopen is done that will change the entry point
740 SecPeCoffRelocateImageExtraAction (&ImageContext
);
741 *EntryPoint
= (VOID
*)(UINTN
)ImageContext
.EntryPoint
;
751 Return the FD Size and base address. Since the FD is loaded from a
752 file into host memory only the SEC will know it's address.
755 Index - Which FD, starts at zero.
756 FdSize - Size of the FD in bytes
757 FdBase - Start address of the FD. Assume it points to an FV Header
758 FixUp - Difference between actual FD address and build address
761 EFI_SUCCESS - Return the Base address and size of the FV
762 EFI_UNSUPPORTED - Index does nto map to an FD in the system
768 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
769 IN OUT UINT64
*FdSize
,
770 IN OUT EFI_PHYSICAL_ADDRESS
*FixUp
773 if (Index
>= gFdInfoCount
) {
774 return EFI_UNSUPPORTED
;
777 *FdBase
= gFdInfo
[Index
].Address
;
778 *FdSize
= gFdInfo
[Index
].Size
;
781 if (*FdBase
== 0 && *FdSize
== 0) {
782 return EFI_UNSUPPORTED
;
787 // FD 0 has XIP code and well known PCD values
788 // If the memory buffer could not be allocated at the FD build address
789 // the Fixup is the difference.
791 *FixUp
= *FdBase
- PcdGet64 (PcdEmuFdBaseAddress
);
801 Count the number of seperators in String
804 String - String to process
805 Seperator - Item to count
808 Number of Seperator in String
812 CountSeperatorsInString (
813 IN
const CHAR16
*String
,
819 for (Count
= 0; *String
!= '\0'; String
++) {
820 if (*String
== Seperator
) {
834 IN OUT UINTN
*ReadSize
,
840 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
843 FileHandle - The handle to the PE/COFF file
844 FileOffset - The offset, in bytes, into the file to read
845 ReadSize - The number of bytes to read from the file starting at FileOffset
846 Buffer - A pointer to the buffer to read the data into.
849 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
857 Destination8
= Buffer
;
858 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
861 *(Destination8
++) = *(Source8
++);
871 Store the ModHandle in an array indexed by the Pdb File name.
872 The ModHandle is needed to unload the image.
875 ImageContext - Input data returned from PE Laoder Library. Used to find the
876 .PDB file name of the PE Image.
877 ModHandle - Returned from LoadLibraryEx() and stored for call to
881 EFI_SUCCESS - ModHandle was stored.
886 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
891 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
895 Array
= mImageContextModHandleArray
;
896 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
897 if (Array
->ImageContext
== NULL
) {
899 // Make a copy of the stirng and store the ModHandle
901 Array
->ImageContext
= ImageContext
;
902 Array
->ModHandle
= ModHandle
;
908 // No free space in mImageContextModHandleArray so grow it by
909 // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
910 // copy the old values to the new locaiton. But it does
911 // not zero the new memory area.
913 PreviousSize
= mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
);
914 mImageContextModHandleArraySize
+= MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
;
916 mImageContextModHandleArray
= ReallocatePool (
917 (mImageContextModHandleArraySize
- 1) * sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
),
918 mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
),
919 mImageContextModHandleArray
921 if (mImageContextModHandleArray
== NULL
) {
923 return EFI_OUT_OF_RESOURCES
;
926 memset (mImageContextModHandleArray
+ PreviousSize
, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
928 return AddHandle (ImageContext
, ModHandle
);
935 Return the ModHandle and delete the entry in the array.
938 ImageContext - Input data returned from PE Laoder Library. Used to find the
939 .PDB file name of the PE Image.
942 ModHandle - ModHandle assoicated with ImageContext is returned
943 NULL - No ModHandle associated with ImageContext
948 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
952 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
954 if (ImageContext
->PdbPointer
== NULL
) {
956 // If no PDB pointer there is no ModHandle so return NULL
961 Array
= mImageContextModHandleArray
;
962 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
963 if (Array
->ImageContext
== ImageContext
) {
965 // If you find a match return it and delete the entry
967 Array
->ImageContext
= NULL
;
968 return Array
->ModHandle
;
978 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to source a
979 // add-symbol-file command. Hey what can you say scripting in gdb is not that great....
981 // Put .gdbinit in the CWD where you do gdb SecMain.dll for source level debug
984 // b SecGdbScriptBreak
987 // source SecMain.gdb
1007 IN CHAR8
*PdbFileName
1012 if (PdbFileName
== NULL
) {
1016 Len
= strlen (PdbFileName
);
1017 if ((Len
< 5)|| (PdbFileName
[Len
- 4] != '.')) {
1021 if ((PdbFileName
[Len
- 3] == 'P' || PdbFileName
[Len
- 3] == 'p') &&
1022 (PdbFileName
[Len
- 2] == 'D' || PdbFileName
[Len
- 2] == 'd') &&
1023 (PdbFileName
[Len
- 1] == 'B' || PdbFileName
[Len
- 1] == 'b')) {
1031 #define MAX_SPRINT_BUFFER_SIZE 0x200
1035 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1038 if (ImageContext
->PdbPointer
== NULL
) {
1040 "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
1041 (unsigned long)(ImageContext
->ImageAddress
),
1042 (unsigned long)ImageContext
->EntryPoint
1046 "0x%08lx Loading %s with entry point 0x%08lx\n",
1047 (unsigned long)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
),
1048 ImageContext
->PdbPointer
,
1049 (unsigned long)ImageContext
->EntryPoint
1052 // Keep output synced up
1058 Loads the image using dlopen so symbols will be automatically
1061 @param ImageContext The PE/COFF image context
1063 @retval TRUE - The image was successfully loaded
1064 @retval FALSE - The image was successfully loaded
1069 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1079 void *Handle
= NULL
;
1082 if (ImageContext
->PdbPointer
== NULL
) {
1086 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1092 "Loading %s 0x%08lx - entry point 0x%08lx\n",
1093 ImageContext
->PdbPointer
,
1094 (unsigned long)ImageContext
->ImageAddress
,
1095 (unsigned long)ImageContext
->EntryPoint
1098 Handle
= dlopen (ImageContext
->PdbPointer
, RTLD_NOW
);
1101 Entry
= dlsym (Handle
, "_ModuleEntryPoint");
1103 printf("%s\n", dlerror());
1106 if (Entry
!= NULL
) {
1107 ImageContext
->EntryPoint
= (UINTN
)Entry
;
1108 printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, (unsigned long)Entry
);
1119 Adds the image to a gdb script so it's symbols can be loaded.
1120 The AddFirmwareSymbolFile helper macro is used.
1122 @param ImageContext The PE/COFF image context
1127 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1130 BOOLEAN InterruptsWereEnabled
;
1133 // Disable interrupts to make sure writing of the .gdb file
1134 // is an atomic operation.
1136 if (SecInterruptEanbled ()) {
1137 SecDisableInterrupt ();
1138 InterruptsWereEnabled
= TRUE
;
1140 InterruptsWereEnabled
= FALSE
;
1143 PrintLoadAddress (ImageContext
);
1145 if (ImageContext
->PdbPointer
!= NULL
&& !IsPdbFile (ImageContext
->PdbPointer
)) {
1147 GdbTempFile
= fopen (gGdbWorkingFileName
, "a");
1148 if (GdbTempFile
!= NULL
) {
1149 long unsigned int SymbolsAddr
= (long unsigned int)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
);
1150 mScriptSymbolChangesCount
++;
1153 "AddFirmwareSymbolFile 0x%x %s 0x%08lx\n",
1154 mScriptSymbolChangesCount
,
1155 ImageContext
->PdbPointer
,
1158 fclose (GdbTempFile
);
1163 AddHandle (ImageContext
, ImageContext
->PdbPointer
);
1165 if (InterruptsWereEnabled
) {
1166 SecEnableInterrupt ();
1175 SecPeCoffRelocateImageExtraAction (
1176 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1179 if (!DlLoadImage (ImageContext
)) {
1180 GdbScriptAddImage (ImageContext
);
1186 Adds the image to a gdb script so it's symbols can be unloaded.
1187 The RemoveFirmwareSymbolFile helper macro is used.
1189 @param ImageContext The PE/COFF image context
1193 GdbScriptRemoveImage (
1194 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1198 BOOLEAN InterruptsWereEnabled
;
1201 // Need to skip .PDB files created from VC++
1203 if (IsPdbFile (ImageContext
->PdbPointer
)) {
1207 if (SecInterruptEanbled ()) {
1208 SecDisableInterrupt ();
1209 InterruptsWereEnabled
= TRUE
;
1211 InterruptsWereEnabled
= FALSE
;
1215 // Write the file we need for the gdb script
1217 GdbTempFile
= fopen (gGdbWorkingFileName
, "a");
1218 if (GdbTempFile
!= NULL
) {
1219 mScriptSymbolChangesCount
++;
1222 "RemoveFirmwareSymbolFile 0x%x %s\n",
1223 mScriptSymbolChangesCount
,
1224 ImageContext
->PdbPointer
1226 fclose (GdbTempFile
);
1231 if (InterruptsWereEnabled
) {
1232 SecEnableInterrupt ();
1239 SecPeCoffUnloadImageExtraAction (
1240 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1246 // Check to see if the image symbols were loaded with gdb script, or dlopen
1248 Handle
= RemoveHandle (ImageContext
);
1250 if (Handle
== NULL
) {
1257 GdbScriptRemoveImage (ImageContext
);