3 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 WinNt emulator of SEC phase. It's really a Win32 application, but this is
18 Ok since all the other modules for NT32 are NOT Win32 applications.
20 This program gets NT32 PCD setting and figures out what the memory layout
21 will be, how may FD's will be loaded and also what the boot mode is.
23 The SEC registers a set of services with the SEC core. gPrivateDispatchTable
24 is a list of PPI's produced by the SEC that are availble for usage in PEI.
26 This code produces 128 K of temporary memory for the PEI stack by directly
27 allocate memory space with ReadWrite and Execute attribute.
33 #ifndef SE_TIME_ZONE_NAME
34 #define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")
37 NT_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi
= { SecWinNtPeiLoadFile
};
39 PEI_NT_AUTOSCAN_PPI mSecNtAutoScanPpi
= { SecWinNtPeiAutoScan
};
41 PEI_NT_THUNK_PPI mSecWinNtThunkPpi
= { SecWinNtWinNtThunkAddress
};
43 EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi
= { SecPeiReportStatusCode
};
45 NT_FWH_PPI mSecFwhInformationPpi
= { SecWinNtFdAddress
};
47 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi
= {SecTemporaryRamSupport
};
49 EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable
[] = {
51 EFI_PEI_PPI_DESCRIPTOR_PPI
,
52 &gNtPeiLoadFilePpiGuid
,
56 EFI_PEI_PPI_DESCRIPTOR_PPI
,
57 &gPeiNtAutoScanPpiGuid
,
61 EFI_PEI_PPI_DESCRIPTOR_PPI
,
66 EFI_PEI_PPI_DESCRIPTOR_PPI
,
67 &gEfiPeiStatusCodePpiGuid
,
71 EFI_PEI_PPI_DESCRIPTOR_PPI
,
72 &gEfiTemporaryRamSupportPpiGuid
,
73 &mSecTemporaryRamSupportPpi
76 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
78 &mSecFwhInformationPpi
84 // Default information about where the FD is located.
85 // This array gets filled in with information from PcdWinNtFirmwareVolume
86 // The number of array elements is allocated base on parsing
87 // PcdWinNtFirmwareVolume and the memory is never freed.
89 UINTN gFdInfoCount
= 0;
93 // Array that supports seperate memory rantes.
94 // The memory ranges are set by PcdWinNtMemorySizeForSecMain.
95 // The number of array elements is allocated base on parsing
96 // PcdWinNtMemorySizeForSecMain value and the memory is never freed.
98 UINTN gSystemMemoryCount
= 0;
99 NT_SYSTEM_MEMORY
*gSystemMemory
;
104 UINT32 TemporaryMemoryBase
,
105 UINT32 PermenentMemoryBase
108 SecNt32PeCoffRelocateImage (
109 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
115 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
116 IN VOID
*Context1
, OPTIONAL
117 IN VOID
*Context2
, OPTIONAL
118 IN VOID
*Context3
, OPTIONAL
130 CHAR8 Buffer
[EFI_STATUS_CODE_DATA_MAX_SIZE
];
132 va_start (Marker
, Format
);
134 _vsnprintf (Buffer
, sizeof (Buffer
), Format
, Marker
);
138 CharCount
= strlen (Buffer
);
140 GetStdHandle (STD_OUTPUT_HANDLE
),
158 Main entry point to SEC for WinNt. This is a Windows program
161 Argc - Number of command line arguments
162 Argv - Array of command line argument strings
163 Envp - Array of environmemt variable strings
173 TOKEN_PRIVILEGES TokenPrivileges
;
174 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
175 UINT64 InitialStackMemorySize
;
183 CHAR16
*MemorySizeStr
;
184 CHAR16
*FirmwareVolumesStr
;
186 UINT32 ProcessAffinityMask
;
187 UINT32 SystemAffinityMask
;
192 // Enable the privilege so that RTC driver can successfully run SetTime()
194 OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
|TOKEN_QUERY
, &Token
);
195 if (LookupPrivilegeValue(NULL
, SE_TIME_ZONE_NAME
, &TokenPrivileges
.Privileges
[0].Luid
)) {
196 TokenPrivileges
.PrivilegeCount
= 1;
197 TokenPrivileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
198 AdjustTokenPrivileges(Token
, FALSE
, &TokenPrivileges
, 0, (PTOKEN_PRIVILEGES
) NULL
, 0);
201 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdWinNtMemorySizeForSecMain
);
202 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdWinNtFirmwareVolume
);
204 SecPrint ("\nEDK II SEC Main NT Emulation Environment from www.TianoCore.org\n");
207 // Determine the first thread available to this process.
209 if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask
, &SystemAffinityMask
)) {
210 LowBit
= (INT32
)LowBitSet32 (ProcessAffinityMask
);
213 // Force the system to bind the process to a single thread to work
214 // around odd semaphore type crashes.
216 SetProcessAffinityMask (GetCurrentProcess (), (INTN
)(BIT0
<< LowBit
));
221 // Make some Windows calls to Set the process to the highest priority in the
222 // idle class. We need this to have good performance.
224 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS
);
225 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST
);
228 // Allocate space for gSystemMemory Array
230 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
231 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (NT_SYSTEM_MEMORY
));
232 if (gSystemMemory
== NULL
) {
233 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr
);
237 // Allocate space for gSystemMemory Array
239 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
240 gFdInfo
= calloc (gFdInfoCount
, sizeof (NT_FD_INFO
));
241 if (gFdInfo
== NULL
) {
242 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr
);
246 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
248 SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdWinNtBootMode
));
251 // Allocate 128K memory to emulate temp memory for PEI.
252 // on a real platform this would be SRAM, or using the cache as RAM.
253 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
255 InitialStackMemorySize
= STACK_SIZE
;
256 InitialStackMemory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (InitialStackMemorySize
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
257 if (InitialStackMemory
== 0) {
258 SecPrint ("ERROR : Can not allocate enough space for SecStack\n");
262 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
263 StackPointer
< (UINTN
*) ((UINTN
)InitialStackMemory
+ (SIZE_T
) InitialStackMemorySize
);
265 *StackPointer
= 0x5AA55AA5;
268 SecPrint (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize
);
271 // Open All the firmware volumes and remember the info in the gFdInfo global
273 FileNamePtr
= (CHAR16
*)malloc (StrLen ((CHAR16
*)FirmwareVolumesStr
) * sizeof(CHAR16
));
274 if (FileNamePtr
== NULL
) {
275 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");
279 StrCpy (FileNamePtr
, (CHAR16
*)FirmwareVolumesStr
);
281 for (Done
= FALSE
, Index
= 0, PeiCoreFile
= NULL
; !Done
; Index
++) {
282 FileName
= FileNamePtr
;
283 for (Index1
= 0; (FileNamePtr
[Index1
] != '!') && (FileNamePtr
[Index1
] != 0); Index1
++)
285 if (FileNamePtr
[Index1
] == 0) {
288 FileNamePtr
[Index1
] = '\0';
289 FileNamePtr
= FileNamePtr
+ Index1
+ 1;
293 // Open the FD and remmeber where it got mapped into our processes address space
295 Status
= WinNtOpenFile (
299 &gFdInfo
[Index
].Address
,
302 if (EFI_ERROR (Status
)) {
303 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName
, Status
);
307 SecPrint (" FD loaded from");
309 // printf can't print filenames directly as the \ gets interperted as an
312 for (Index2
= 0; FileName
[Index2
] != '\0'; Index2
++) {
313 SecPrint ("%c", FileName
[Index2
]);
316 if (PeiCoreFile
== NULL
) {
318 // Assume the beginning of the FD is an FV and look for the PEI Core.
319 // Load the first one we find.
321 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
322 if (!EFI_ERROR (Status
)) {
323 SecPrint (" contains SEC Core");
330 // Calculate memory regions and store the information in the gSystemMemory
331 // global for later use. The autosizing code will use this data to
332 // map this memory into the SEC process memory space.
334 for (Index
= 0, Done
= FALSE
; !Done
; Index
++) {
336 // Save the size of the memory and make a Unicode filename SystemMemory00, ...
338 gSystemMemory
[Index
].Size
= _wtoi (MemorySizeStr
) * 0x100000;
341 // Find the next region
343 for (Index1
= 0; MemorySizeStr
[Index1
] != '!' && MemorySizeStr
[Index1
] != 0; Index1
++)
345 if (MemorySizeStr
[Index1
] == 0) {
349 MemorySizeStr
= MemorySizeStr
+ Index1
+ 1;
355 // Hand off to PEI Core
357 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
360 // If we get here, then the PEI Core returned. This is an error as PEI should
361 // always hand off to DXE.
363 SecPrint ("ERROR : PEI Core returned\n");
371 IN DWORD CreationDisposition
,
372 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
378 Opens and memory maps a file using WinNt services. If BaseAddress is non zero
379 the process will try and allocate the memory starting at BaseAddress.
382 FileName - The name of the file to open and map
383 MapSize - The amount of the file to map in bytes
384 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
385 memory emulation, and exiting files for firmware volume emulation
386 BaseAddress - The base address of the mapped file in the user address space.
387 If passed in as NULL the a new memory region is used.
388 If passed in as non NULL the request memory region is used for
389 the mapping of the file into the process space.
390 Length - The size of the mapped region in bytes
393 EFI_SUCCESS - The file was opened and mapped.
394 EFI_NOT_FOUND - FileName was not found in the current directory
395 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
401 VOID
*VirtualAddress
;
405 // Use Win API to open/create a file
407 NtFileHandle
= CreateFile (
409 GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
,
413 FILE_ATTRIBUTE_NORMAL
,
416 if (NtFileHandle
== INVALID_HANDLE_VALUE
) {
417 return EFI_NOT_FOUND
;
420 // Map the open file into a memory range
422 NtMapHandle
= CreateFileMapping (
425 PAGE_EXECUTE_READWRITE
,
430 if (NtMapHandle
== NULL
) {
431 return EFI_DEVICE_ERROR
;
434 // Get the virtual address (address in the emulator) of the mapped file
436 VirtualAddress
= MapViewOfFileEx (
438 FILE_MAP_EXECUTE
| FILE_MAP_ALL_ACCESS
,
442 (LPVOID
) (UINTN
) *BaseAddress
444 if (VirtualAddress
== NULL
) {
445 return EFI_DEVICE_ERROR
;
450 // Seek to the end of the file to figure out the true file size.
452 FileSize
= SetFilePointer (
458 if (FileSize
== -1) {
459 return EFI_DEVICE_ERROR
;
462 *Length
= (UINT64
) FileSize
;
464 *Length
= (UINT64
) MapSize
;
467 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAddress
;
473 #define BYTES_PER_RECORD 512
477 SecPeiReportStatusCode (
478 IN CONST EFI_PEI_SERVICES
**PeiServices
,
479 IN EFI_STATUS_CODE_TYPE CodeType
,
480 IN EFI_STATUS_CODE_VALUE Value
,
482 IN CONST EFI_GUID
*CallerId
,
483 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
489 This routine produces the ReportStatusCode PEI service. It's passed
490 up to the PEI Core via a PPI. T
492 This code currently uses the NT clib printf. This does not work the same way
493 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
496 (see EFI_PEI_REPORT_STATUS_CODE)
499 EFI_SUCCESS - Always return success
502 // TODO: PeiServices - add argument and description to function comment
503 // TODO: CodeType - add argument and description to function comment
504 // TODO: Value - add argument and description to function comment
505 // TODO: Instance - add argument and description to function comment
506 // TODO: CallerId - add argument and description to function comment
507 // TODO: Data - add argument and description to function comment
511 CHAR8 PrintBuffer
[BYTES_PER_RECORD
* 2];
519 } else if (ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
521 // Processes ASSERT ()
523 SecPrint ("ASSERT %s(%d): %s\n", Filename
, (int)LineNumber
, Description
);
525 } else if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
527 // Process DEBUG () macro
529 AsciiBSPrint (PrintBuffer
, BYTES_PER_RECORD
, Format
, Marker
);
530 SecPrint (PrintBuffer
);
536 #if defined (MDE_CPU_IA32)
538 Transfers control to a function starting with a new stack.
540 Transfers control to the function specified by EntryPoint using the new stack
541 specified by NewStack and passing in the parameters specified by Context1 and
542 Context2. Context1 and Context2 are optional and may be NULL. The function
543 EntryPoint must never return.
545 If EntryPoint is NULL, then ASSERT().
546 If NewStack is NULL, then ASSERT().
548 @param EntryPoint A pointer to function to call with the new stack.
549 @param Context1 A pointer to the context to pass into the EntryPoint
551 @param Context2 A pointer to the context to pass into the EntryPoint
553 @param NewStack A pointer to the new stack to use for the EntryPoint
555 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
556 Reserved on other architectures.
562 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
563 IN VOID
*Context1
, OPTIONAL
564 IN VOID
*Context2
, OPTIONAL
565 IN VOID
*Context3
, OPTIONAL
569 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
571 ASSERT (EntryPoint
!= NULL
);
572 ASSERT (NewStack
!= NULL
);
575 // Stack should be aligned with CPU_STACK_ALIGNMENT
577 ASSERT (((UINTN
)NewStack
& (CPU_STACK_ALIGNMENT
- 1)) == 0);
579 JumpBuffer
.Eip
= (UINTN
)EntryPoint
;
580 JumpBuffer
.Esp
= (UINTN
)NewStack
- sizeof (VOID
*);
581 JumpBuffer
.Esp
-= sizeof (Context1
) + sizeof (Context2
) + sizeof(Context3
);
582 ((VOID
**)JumpBuffer
.Esp
)[1] = Context1
;
583 ((VOID
**)JumpBuffer
.Esp
)[2] = Context2
;
584 ((VOID
**)JumpBuffer
.Esp
)[3] = Context3
;
586 LongJump (&JumpBuffer
, (UINTN
)-1);
590 // InternalSwitchStack () will never return
598 IN UINTN LargestRegion
,
599 IN UINTN LargestRegionSize
,
600 IN UINTN BootFirmwareVolumeBase
,
601 IN VOID
*PeiCorePe32File
606 This is the service to load the PEI Core from the Firmware Volume
609 LargestRegion - Memory to use for PEI.
610 LargestRegionSize - Size of Memory to use for PEI
611 BootFirmwareVolumeBase - Start of the Boot FV
612 PeiCorePe32File - PEI Core PE32
615 Success means control is transfered and thus we should never return
622 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
623 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
624 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
628 // Compute Top Of Memory for Stack and PEI Core Allocations
630 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
633 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
636 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
639 // |-----------| <---- TemporaryRamBase
641 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
644 // Reservet space for storing PeiCore's parament in stack.
646 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
647 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
650 // Bind this information into the SEC hand-off state
652 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
653 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
654 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
655 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32(PcdWinNtFirmwareFdSize
);
656 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
657 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
658 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
659 SecCoreData
->StackSize
= PeiStackSize
;
660 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
661 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
664 // Load the PEI Core from a Firmware Volume
666 Status
= SecWinNtPeiLoadFile (
672 if (EFI_ERROR (Status
)) {
677 // Transfer control to the PEI Core
680 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
682 (VOID
*) (UINTN
) ((EFI_PEI_PPI_DESCRIPTOR
*) &gPrivateDispatchTable
),
687 // If we get here, then the PEI Core returned. This is an error
694 SecWinNtPeiAutoScan (
696 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
697 OUT UINT64
*MemorySize
702 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
703 It allows discontiguous memory regions to be supported by the emulator.
704 It uses gSystemMemory[] and gSystemMemoryCount that were created by
705 parsing PcdWinNtMemorySizeForSecMain value.
706 The size comes from the Pcd value and the address comes from the memory space
707 with ReadWrite and Execute attributes allocated by VirtualAlloc() API.
710 Index - Which memory region to use
711 MemoryBase - Return Base address of memory region
712 MemorySize - Return size in bytes of the memory region
715 EFI_SUCCESS - If memory region was mapped
716 EFI_UNSUPPORTED - If Index is not supported
720 if (Index
>= gSystemMemoryCount
) {
721 return EFI_UNSUPPORTED
;
725 // Allocate enough memory space for emulator
727 gSystemMemory
[Index
].Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (gSystemMemory
[Index
].Size
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
728 if (gSystemMemory
[Index
].Memory
== 0) {
729 return EFI_OUT_OF_RESOURCES
;
732 *MemoryBase
= gSystemMemory
[Index
].Memory
;
733 *MemorySize
= gSystemMemory
[Index
].Size
;
740 SecWinNtWinNtThunkAddress (
746 Since the SEC is the only Windows program in stack it must export
747 an interface to do Win API calls. That's what the WinNtThunk address
748 is for. gWinNt is initailized in WinNtThunk.c.
751 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
752 InterfaceBase - Address of the gWinNt global
755 EFI_SUCCESS - Data returned
765 SecWinNtPeiLoadFile (
767 IN EFI_PHYSICAL_ADDRESS
*ImageAddress
,
768 IN UINT64
*ImageSize
,
769 IN EFI_PHYSICAL_ADDRESS
*EntryPoint
774 Loads and relocates a PE/COFF image into memory.
777 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
778 ImageAddress - The base address of the relocated PE/COFF image
779 ImageSize - The size of the relocated PE/COFF image
780 EntryPoint - The entry point of the relocated PE/COFF image
783 EFI_SUCCESS - The file was loaded and relocated
784 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
789 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
791 ZeroMem (&ImageContext
, sizeof (ImageContext
));
792 ImageContext
.Handle
= Pe32Data
;
794 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
796 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
797 if (EFI_ERROR (Status
)) {
801 // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribue.
802 // Extra space is for alignment
804 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
805 if (ImageContext
.ImageAddress
== 0) {
806 return EFI_OUT_OF_RESOURCES
;
809 // Align buffer on section boundry
811 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
812 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
814 Status
= PeCoffLoaderLoadImage (&ImageContext
);
815 if (EFI_ERROR (Status
)) {
819 Status
= SecNt32PeCoffRelocateImage (&ImageContext
);
820 if (EFI_ERROR (Status
)) {
825 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
828 *ImageAddress
= ImageContext
.ImageAddress
;
829 *ImageSize
= ImageContext
.ImageSize
;
830 *EntryPoint
= ImageContext
.EntryPoint
;
839 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
840 IN OUT UINT64
*FdSize
845 Return the FD Size and base address. Since the FD is loaded from a
846 file into Windows memory only the SEC will know it's address.
849 Index - Which FD, starts at zero.
850 FdSize - Size of the FD in bytes
851 FdBase - Start address of the FD. Assume it points to an FV Header
854 EFI_SUCCESS - Return the Base address and size of the FV
855 EFI_UNSUPPORTED - Index does nto map to an FD in the system
859 if (Index
>= gFdInfoCount
) {
860 return EFI_UNSUPPORTED
;
863 *FdBase
= gFdInfo
[Index
].Address
;
864 *FdSize
= gFdInfo
[Index
].Size
;
866 if (*FdBase
== 0 && *FdSize
== 0) {
867 return EFI_UNSUPPORTED
;
878 IN OUT UINTN
*ReadSize
,
884 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
887 FileHandle - The handle to the PE/COFF file
888 FileOffset - The offset, in bytes, into the file to read
889 ReadSize - The number of bytes to read from the file starting at FileOffset
890 Buffer - A pointer to the buffer to read the data into.
893 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
901 Destination8
= Buffer
;
902 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
905 *(Destination8
++) = *(Source8
++);
914 IN UINTN
*StrLen OPTIONAL
919 Convert the passed in Ascii string to Unicode.
920 Optionally return the length of the strings.
923 Ascii - Ascii string to convert
924 StrLen - Length of string
927 Pointer to malloc'ed Unicode version of Ascii
935 // Allocate a buffer for unicode string
937 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++)
939 Unicode
= malloc ((Index
+ 1) * sizeof (CHAR16
));
940 if (Unicode
== NULL
) {
944 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++) {
945 Unicode
[Index
] = (CHAR16
) Ascii
[Index
];
948 Unicode
[Index
] = '\0';
950 if (StrLen
!= NULL
) {
958 CountSeperatorsInString (
959 IN CONST CHAR16
*String
,
965 Count the number of seperators in String
968 String - String to process
969 Seperator - Item to count
972 Number of Seperator in String
978 for (Count
= 0; *String
!= '\0'; String
++) {
979 if (*String
== Seperator
) {
989 SecNt32PeCoffRelocateImage (
990 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1000 Status
= PeCoffLoaderRelocateImage (ImageContext
);
1001 if (EFI_ERROR (Status
)) {
1003 // We could not relocated the image in memory properly
1009 // If we load our own PE COFF images the Windows debugger can not source
1010 // level debug our code. If a valid PDB pointer exists usw it to load
1011 // the *.dll file as a library using Windows* APIs. This allows
1012 // source level debug. The image is still loaded and reloaced
1013 // in the Framework memory space like on a real system (by the code above),
1014 // but the entry point points into the DLL loaded by the code bellow.
1017 DllEntryPoint
= NULL
;
1020 // Load the DLL if it's not an EBC image.
1022 if ((ImageContext
->PdbPointer
!= NULL
) &&
1023 (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
)) {
1025 // Convert filename from ASCII to Unicode
1027 DllFileName
= AsciiToUnicode (ImageContext
->PdbPointer
, &Index
);
1030 // Check that we have a valid filename
1032 if (Index
< 5 || DllFileName
[Index
- 4] != '.') {
1036 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1037 // The image will run, but we just can't source level debug. If we
1038 // return an error the image will not run.
1043 // Replace .PDB with .DLL on the filename
1045 DllFileName
[Index
- 3] = 'D';
1046 DllFileName
[Index
- 2] = 'L';
1047 DllFileName
[Index
- 1] = 'L';
1050 // Load the .DLL file into the user process's address space for source
1053 Library
= LoadLibraryEx (DllFileName
, NULL
, DONT_RESOLVE_DLL_REFERENCES
);
1054 if (Library
!= NULL
) {
1056 // InitializeDriver is the entry point we put in all our EFI DLL's. The
1057 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() supresses the
1058 // normal DLL entry point of DllMain, and prevents other modules that are
1059 // referenced in side the DllFileName from being loaded. There is no error
1060 // checking as the we can point to the PE32 image loaded by Tiano. This
1061 // step is only needed for source level debuging
1063 DllEntryPoint
= (VOID
*) (UINTN
) GetProcAddress (Library
, "InitializeDriver");
1067 if ((Library
!= NULL
) && (DllEntryPoint
!= NULL
)) {
1068 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) DllEntryPoint
;
1069 SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName
);
1071 SecPrint ("WARNING: No source level debug %S. \n", DllFileName
);
1078 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1079 // The image will run, but we just can't source level debug. If we
1080 // return an error the image will not run.
1097 SecTemporaryRamSupport (
1098 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1099 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1100 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1105 // Migrate the whole temporary memory to permenent memory.
1108 (VOID
*)(UINTN
)PermanentMemoryBase
,
1109 (VOID
*)(UINTN
)TemporaryMemoryBase
,
1114 // SecSwitchStack function must be invoked after the memory migration
1115 // immediatly, also we need fixup the stack change caused by new call into
1116 // permenent memory.
1119 (UINT32
) TemporaryMemoryBase
,
1120 (UINT32
) PermanentMemoryBase
1124 // We need *not* fix the return address because currently,
1125 // The PeiCore is excuted in flash.
1129 // Simulate to invalid temporary memory, terminate temporary memory
1131 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);