3 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
4 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 WinNt emulator of SEC phase. It's really a Win32 application, but this is
13 Ok since all the other modules for NT32 are NOT Win32 applications.
15 This program gets NT32 PCD setting and figures out what the memory layout
16 will be, how may FD's will be loaded and also what the boot mode is.
18 The SEC registers a set of services with the SEC core. gPrivateDispatchTable
19 is a list of PPI's produced by the SEC that are available for usage in PEI.
21 This code produces 128 K of temporary memory for the PEI stack by directly
22 allocate memory space with ReadWrite and Execute attribute.
28 #ifndef SE_TIME_ZONE_NAME
29 #define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")
32 NT_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi
= { SecWinNtPeiLoadFile
};
34 PEI_NT_AUTOSCAN_PPI mSecNtAutoScanPpi
= { SecWinNtPeiAutoScan
};
36 PEI_NT_THUNK_PPI mSecWinNtThunkPpi
= { SecWinNtWinNtThunkAddress
};
38 EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi
= { SecPeiReportStatusCode
};
40 NT_FWH_PPI mSecFwhInformationPpi
= { SecWinNtFdAddress
};
42 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi
= {SecTemporaryRamSupport
};
44 EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable
[] = {
46 EFI_PEI_PPI_DESCRIPTOR_PPI
,
47 &gNtPeiLoadFilePpiGuid
,
51 EFI_PEI_PPI_DESCRIPTOR_PPI
,
52 &gPeiNtAutoScanPpiGuid
,
56 EFI_PEI_PPI_DESCRIPTOR_PPI
,
61 EFI_PEI_PPI_DESCRIPTOR_PPI
,
62 &gEfiPeiStatusCodePpiGuid
,
66 EFI_PEI_PPI_DESCRIPTOR_PPI
,
67 &gEfiTemporaryRamSupportPpiGuid
,
68 &mSecTemporaryRamSupportPpi
71 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
73 &mSecFwhInformationPpi
79 // Default information about where the FD is located.
80 // This array gets filled in with information from PcdWinNtFirmwareVolume
81 // The number of array elements is allocated base on parsing
82 // PcdWinNtFirmwareVolume and the memory is never freed.
84 UINTN gFdInfoCount
= 0;
88 // Array that supports seperate memory rantes.
89 // The memory ranges are set by PcdWinNtMemorySizeForSecMain.
90 // The number of array elements is allocated base on parsing
91 // PcdWinNtMemorySizeForSecMain value and the memory is never freed.
93 UINTN gSystemMemoryCount
= 0;
94 NT_SYSTEM_MEMORY
*gSystemMemory
;
99 UINT32 TemporaryMemoryBase
,
100 UINT32 PermenentMemoryBase
103 SecNt32PeCoffRelocateImage (
104 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
110 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
111 IN VOID
*Context1
, OPTIONAL
112 IN VOID
*Context2
, OPTIONAL
113 IN VOID
*Context3
, OPTIONAL
125 CHAR8 Buffer
[EFI_STATUS_CODE_DATA_MAX_SIZE
];
127 va_start (Marker
, Format
);
129 _vsnprintf (Buffer
, sizeof (Buffer
), Format
, Marker
);
133 CharCount
= strlen (Buffer
);
135 GetStdHandle (STD_OUTPUT_HANDLE
),
153 Main entry point to SEC for WinNt. This is a Windows program
156 Argc - Number of command line arguments
157 Argv - Array of command line argument strings
158 Envp - Array of environment variable strings
168 TOKEN_PRIVILEGES TokenPrivileges
;
169 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
170 UINT64 InitialStackMemorySize
;
178 CHAR16
*MemorySizeStr
;
179 CHAR16
*FirmwareVolumesStr
;
181 UINT32 ProcessAffinityMask
;
182 UINT32 SystemAffinityMask
;
187 // Enable the privilege so that RTC driver can successfully run SetTime()
189 OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
|TOKEN_QUERY
, &Token
);
190 if (LookupPrivilegeValue(NULL
, SE_TIME_ZONE_NAME
, &TokenPrivileges
.Privileges
[0].Luid
)) {
191 TokenPrivileges
.PrivilegeCount
= 1;
192 TokenPrivileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
193 AdjustTokenPrivileges(Token
, FALSE
, &TokenPrivileges
, 0, (PTOKEN_PRIVILEGES
) NULL
, 0);
196 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdWinNtMemorySizeForSecMain
);
197 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdWinNtFirmwareVolume
);
199 SecPrint ("\nEDK II SEC Main NT Emulation Environment from www.TianoCore.org\n");
202 // Determine the first thread available to this process.
204 if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask
, &SystemAffinityMask
)) {
205 LowBit
= (INT32
)LowBitSet32 (ProcessAffinityMask
);
208 // Force the system to bind the process to a single thread to work
209 // around odd semaphore type crashes.
211 SetProcessAffinityMask (GetCurrentProcess (), (INTN
)(BIT0
<< LowBit
));
216 // Make some Windows calls to Set the process to the highest priority in the
217 // idle class. We need this to have good performance.
219 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS
);
220 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST
);
223 // Allocate space for gSystemMemory Array
225 gSystemMemoryCount
= CountSeparatorsInString (MemorySizeStr
, '!') + 1;
226 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (NT_SYSTEM_MEMORY
));
227 if (gSystemMemory
== NULL
) {
228 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr
);
232 // Allocate space for gSystemMemory Array
234 gFdInfoCount
= CountSeparatorsInString (FirmwareVolumesStr
, '!') + 1;
235 gFdInfo
= calloc (gFdInfoCount
, sizeof (NT_FD_INFO
));
236 if (gFdInfo
== NULL
) {
237 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr
);
241 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
243 SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdWinNtBootMode
));
246 // Allocate 128K memory to emulate temp memory for PEI.
247 // on a real platform this would be SRAM, or using the cache as RAM.
248 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
250 InitialStackMemorySize
= STACK_SIZE
;
251 InitialStackMemory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (InitialStackMemorySize
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
252 if (InitialStackMemory
== 0) {
253 SecPrint ("ERROR : Can not allocate enough space for SecStack\n");
257 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
258 StackPointer
< (UINTN
*) ((UINTN
)InitialStackMemory
+ (SIZE_T
) InitialStackMemorySize
);
260 *StackPointer
= PcdGet32 (PcdInitValueInTempStack
);
263 SecPrint (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize
);
266 // Open All the firmware volumes and remember the info in the gFdInfo global
268 FileNamePtr
= (CHAR16
*)malloc (StrLen ((CHAR16
*)FirmwareVolumesStr
) * sizeof(CHAR16
));
269 if (FileNamePtr
== NULL
) {
270 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");
274 StrCpy (FileNamePtr
, (CHAR16
*)FirmwareVolumesStr
);
276 for (Done
= FALSE
, Index
= 0, PeiCoreFile
= NULL
; !Done
; Index
++) {
277 FileName
= FileNamePtr
;
278 for (Index1
= 0; (FileNamePtr
[Index1
] != '!') && (FileNamePtr
[Index1
] != 0); Index1
++)
280 if (FileNamePtr
[Index1
] == 0) {
283 FileNamePtr
[Index1
] = '\0';
284 FileNamePtr
= FileNamePtr
+ Index1
+ 1;
288 // Open the FD and remember where it got mapped into our processes address space
290 Status
= WinNtOpenFile (
294 &gFdInfo
[Index
].Address
,
297 if (EFI_ERROR (Status
)) {
298 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName
, Status
);
302 SecPrint (" FD loaded from");
304 // printf can't print filenames directly as the \ gets interpreted as an
307 for (Index2
= 0; FileName
[Index2
] != '\0'; Index2
++) {
308 SecPrint ("%c", FileName
[Index2
]);
311 if (PeiCoreFile
== NULL
) {
313 // Assume the beginning of the FD is an FV and look for the PEI Core.
314 // Load the first one we find.
316 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
317 if (!EFI_ERROR (Status
)) {
318 SecPrint (" contains SEC Core");
325 // Calculate memory regions and store the information in the gSystemMemory
326 // global for later use. The autosizing code will use this data to
327 // map this memory into the SEC process memory space.
329 for (Index
= 0, Done
= FALSE
; !Done
; Index
++) {
331 // Save the size of the memory and make a Unicode filename SystemMemory00, ...
333 gSystemMemory
[Index
].Size
= _wtoi (MemorySizeStr
) * 0x100000;
336 // Find the next region
338 for (Index1
= 0; MemorySizeStr
[Index1
] != '!' && MemorySizeStr
[Index1
] != 0; Index1
++)
340 if (MemorySizeStr
[Index1
] == 0) {
344 MemorySizeStr
= MemorySizeStr
+ Index1
+ 1;
350 // Hand off to PEI Core
352 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
355 // If we get here, then the PEI Core returned. This is an error as PEI should
356 // always hand off to DXE.
358 SecPrint ("ERROR : PEI Core returned\n");
366 IN DWORD CreationDisposition
,
367 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
373 Opens and memory maps a file using WinNt services. If BaseAddress is non zero
374 the process will try and allocate the memory starting at BaseAddress.
377 FileName - The name of the file to open and map
378 MapSize - The amount of the file to map in bytes
379 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
380 memory emulation, and exiting files for firmware volume emulation
381 BaseAddress - The base address of the mapped file in the user address space.
382 If passed in as NULL the new memory region is used.
383 If passed in as non NULL the request memory region is used for
384 the mapping of the file into the process space.
385 Length - The size of the mapped region in bytes
388 EFI_SUCCESS - The file was opened and mapped.
389 EFI_NOT_FOUND - FileName was not found in the current directory
390 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
396 VOID
*VirtualAddress
;
400 // Use Win API to open/create a file
402 NtFileHandle
= CreateFile (
404 GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
,
408 FILE_ATTRIBUTE_NORMAL
,
411 if (NtFileHandle
== INVALID_HANDLE_VALUE
) {
412 return EFI_NOT_FOUND
;
415 // Map the open file into a memory range
417 NtMapHandle
= CreateFileMapping (
420 PAGE_EXECUTE_READWRITE
,
425 if (NtMapHandle
== NULL
) {
426 return EFI_DEVICE_ERROR
;
429 // Get the virtual address (address in the emulator) of the mapped file
431 VirtualAddress
= MapViewOfFileEx (
433 FILE_MAP_EXECUTE
| FILE_MAP_ALL_ACCESS
,
437 (LPVOID
) (UINTN
) *BaseAddress
439 if (VirtualAddress
== NULL
) {
440 return EFI_DEVICE_ERROR
;
445 // Seek to the end of the file to figure out the true file size.
447 FileSize
= SetFilePointer (
453 if (FileSize
== -1) {
454 return EFI_DEVICE_ERROR
;
457 *Length
= (UINT64
) FileSize
;
459 *Length
= (UINT64
) MapSize
;
462 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAddress
;
468 #define BYTES_PER_RECORD 512
472 SecPeiReportStatusCode (
473 IN CONST EFI_PEI_SERVICES
**PeiServices
,
474 IN EFI_STATUS_CODE_TYPE CodeType
,
475 IN EFI_STATUS_CODE_VALUE Value
,
477 IN CONST EFI_GUID
*CallerId
,
478 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
484 This routine produces the ReportStatusCode PEI service. It's passed
485 up to the PEI Core via a PPI. T
487 This code currently uses the NT clib printf. This does not work the same way
488 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
491 (see EFI_PEI_REPORT_STATUS_CODE)
494 EFI_SUCCESS - Always return success
497 // TODO: PeiServices - add argument and description to function comment
498 // TODO: CodeType - add argument and description to function comment
499 // TODO: Value - add argument and description to function comment
500 // TODO: Instance - add argument and description to function comment
501 // TODO: CallerId - add argument and description to function comment
502 // TODO: Data - add argument and description to function comment
506 CHAR8 PrintBuffer
[BYTES_PER_RECORD
* 2];
514 } else if (ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
516 // Processes ASSERT ()
518 SecPrint ("ASSERT %s(%d): %s\n", Filename
, (int)LineNumber
, Description
);
520 } else if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
522 // Process DEBUG () macro
524 AsciiBSPrint (PrintBuffer
, BYTES_PER_RECORD
, Format
, Marker
);
525 SecPrint (PrintBuffer
);
531 #if defined (MDE_CPU_IA32)
533 Transfers control to a function starting with a new stack.
535 Transfers control to the function specified by EntryPoint using the new stack
536 specified by NewStack and passing in the parameters specified by Context1 and
537 Context2. Context1 and Context2 are optional and may be NULL. The function
538 EntryPoint must never return.
540 If EntryPoint is NULL, then ASSERT().
541 If NewStack is NULL, then ASSERT().
543 @param EntryPoint A pointer to function to call with the new stack.
544 @param Context1 A pointer to the context to pass into the EntryPoint
546 @param Context2 A pointer to the context to pass into the EntryPoint
548 @param NewStack A pointer to the new stack to use for the EntryPoint
550 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
551 Reserved on other architectures.
557 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
558 IN VOID
*Context1
, OPTIONAL
559 IN VOID
*Context2
, OPTIONAL
560 IN VOID
*Context3
, OPTIONAL
564 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
566 ASSERT (EntryPoint
!= NULL
);
567 ASSERT (NewStack
!= NULL
);
570 // Stack should be aligned with CPU_STACK_ALIGNMENT
572 ASSERT (((UINTN
)NewStack
& (CPU_STACK_ALIGNMENT
- 1)) == 0);
574 JumpBuffer
.Eip
= (UINTN
)EntryPoint
;
575 JumpBuffer
.Esp
= (UINTN
)NewStack
- sizeof (VOID
*);
576 JumpBuffer
.Esp
-= sizeof (Context1
) + sizeof (Context2
) + sizeof(Context3
);
577 ((VOID
**)JumpBuffer
.Esp
)[1] = Context1
;
578 ((VOID
**)JumpBuffer
.Esp
)[2] = Context2
;
579 ((VOID
**)JumpBuffer
.Esp
)[3] = Context3
;
581 LongJump (&JumpBuffer
, (UINTN
)-1);
585 // InternalSwitchStack () will never return
593 IN UINTN LargestRegion
,
594 IN UINTN LargestRegionSize
,
595 IN UINTN BootFirmwareVolumeBase
,
596 IN VOID
*PeiCorePe32File
601 This is the service to load the PEI Core from the Firmware Volume
604 LargestRegion - Memory to use for PEI.
605 LargestRegionSize - Size of Memory to use for PEI
606 BootFirmwareVolumeBase - Start of the Boot FV
607 PeiCorePe32File - PEI Core PE32
610 Success means control is transfered and thus we should never return
617 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
618 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
619 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
623 // Compute Top Of Memory for Stack and PEI Core Allocations
625 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
628 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
631 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
634 // |-----------| <---- TemporaryRamBase
636 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
639 // Reservet space for storing PeiCore's parament in stack.
641 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
642 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
645 // Bind this information into the SEC hand-off state
647 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
648 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
649 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
650 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32(PcdWinNtFirmwareFdSize
);
651 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
652 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
653 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
654 SecCoreData
->StackSize
= PeiStackSize
;
655 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
656 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
659 // Load the PEI Core from a Firmware Volume
661 Status
= SecWinNtPeiLoadFile (
667 if (EFI_ERROR (Status
)) {
672 // Transfer control to the PEI Core
675 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
677 (VOID
*) (UINTN
) ((EFI_PEI_PPI_DESCRIPTOR
*) &gPrivateDispatchTable
),
682 // If we get here, then the PEI Core returned. This is an error
689 SecWinNtPeiAutoScan (
691 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
692 OUT UINT64
*MemorySize
697 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
698 It allows discontinuous memory regions to be supported by the emulator.
699 It uses gSystemMemory[] and gSystemMemoryCount that were created by
700 parsing PcdWinNtMemorySizeForSecMain value.
701 The size comes from the Pcd value and the address comes from the memory space
702 with ReadWrite and Execute attributes allocated by VirtualAlloc() API.
705 Index - Which memory region to use
706 MemoryBase - Return Base address of memory region
707 MemorySize - Return size in bytes of the memory region
710 EFI_SUCCESS - If memory region was mapped
711 EFI_UNSUPPORTED - If Index is not supported
715 if (Index
>= gSystemMemoryCount
) {
716 return EFI_UNSUPPORTED
;
720 // Allocate enough memory space for emulator
722 gSystemMemory
[Index
].Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (gSystemMemory
[Index
].Size
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
723 if (gSystemMemory
[Index
].Memory
== 0) {
724 return EFI_OUT_OF_RESOURCES
;
727 *MemoryBase
= gSystemMemory
[Index
].Memory
;
728 *MemorySize
= gSystemMemory
[Index
].Size
;
735 SecWinNtWinNtThunkAddress (
741 Since the SEC is the only Windows program in stack it must export
742 an interface to do Win API calls. That's what the WinNtThunk address
743 is for. gWinNt is initialized in WinNtThunk.c.
746 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
747 InterfaceBase - Address of the gWinNt global
750 EFI_SUCCESS - Data returned
760 SecWinNtPeiLoadFile (
762 IN EFI_PHYSICAL_ADDRESS
*ImageAddress
,
763 IN UINT64
*ImageSize
,
764 IN EFI_PHYSICAL_ADDRESS
*EntryPoint
769 Loads and relocates a PE/COFF image into memory.
772 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
773 ImageAddress - The base address of the relocated PE/COFF image
774 ImageSize - The size of the relocated PE/COFF image
775 EntryPoint - The entry point of the relocated PE/COFF image
778 EFI_SUCCESS - The file was loaded and relocated
779 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
784 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
786 ZeroMem (&ImageContext
, sizeof (ImageContext
));
787 ImageContext
.Handle
= Pe32Data
;
789 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
791 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
792 if (EFI_ERROR (Status
)) {
796 // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribute.
797 // Extra space is for alignment
799 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
800 if (ImageContext
.ImageAddress
== 0) {
801 return EFI_OUT_OF_RESOURCES
;
804 // Align buffer on section boundary
806 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
807 ImageContext
.ImageAddress
&= ~((EFI_PHYSICAL_ADDRESS
)ImageContext
.SectionAlignment
- 1);
809 Status
= PeCoffLoaderLoadImage (&ImageContext
);
810 if (EFI_ERROR (Status
)) {
814 Status
= SecNt32PeCoffRelocateImage (&ImageContext
);
815 if (EFI_ERROR (Status
)) {
820 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
823 *ImageAddress
= ImageContext
.ImageAddress
;
824 *ImageSize
= ImageContext
.ImageSize
;
825 *EntryPoint
= ImageContext
.EntryPoint
;
834 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
835 IN OUT UINT64
*FdSize
840 Return the FD Size and base address. Since the FD is loaded from a
841 file into Windows memory only the SEC will know it's address.
844 Index - Which FD, starts at zero.
845 FdSize - Size of the FD in bytes
846 FdBase - Start address of the FD. Assume it points to an FV Header
849 EFI_SUCCESS - Return the Base address and size of the FV
850 EFI_UNSUPPORTED - Index does not map to an FD in the system
854 if (Index
>= gFdInfoCount
) {
855 return EFI_UNSUPPORTED
;
858 *FdBase
= gFdInfo
[Index
].Address
;
859 *FdSize
= gFdInfo
[Index
].Size
;
861 if (*FdBase
== 0 && *FdSize
== 0) {
862 return EFI_UNSUPPORTED
;
873 IN OUT UINTN
*ReadSize
,
879 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
882 FileHandle - The handle to the PE/COFF file
883 FileOffset - The offset, in bytes, into the file to read
884 ReadSize - The number of bytes to read from the file starting at FileOffset
885 Buffer - A pointer to the buffer to read the data into.
888 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
896 Destination8
= Buffer
;
897 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
900 *(Destination8
++) = *(Source8
++);
909 IN UINTN
*StrLen OPTIONAL
914 Convert the passed in Ascii string to Unicode.
915 Optionally return the length of the strings.
918 Ascii - Ascii string to convert
919 StrLen - Length of string
922 Pointer to malloc'ed Unicode version of Ascii
930 // Allocate a buffer for unicode string
932 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++)
934 Unicode
= malloc ((Index
+ 1) * sizeof (CHAR16
));
935 if (Unicode
== NULL
) {
939 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++) {
940 Unicode
[Index
] = (CHAR16
) Ascii
[Index
];
943 Unicode
[Index
] = '\0';
945 if (StrLen
!= NULL
) {
953 CountSeparatorsInString (
954 IN CONST CHAR16
*String
,
960 Count the number of separators in String
963 String - String to process
964 Separator - Item to count
967 Number of Separator in String
973 for (Count
= 0; *String
!= '\0'; String
++) {
974 if (*String
== Separator
) {
984 SecNt32PeCoffRelocateImage (
985 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
995 Status
= PeCoffLoaderRelocateImage (ImageContext
);
996 if (EFI_ERROR (Status
)) {
998 // We could not relocated the image in memory properly
1004 // If we load our own PE COFF images the Windows debugger can not source
1005 // level debug our code. If a valid PDB pointer exists usw it to load
1006 // the *.dll file as a library using Windows* APIs. This allows
1007 // source level debug. The image is still loaded and relocated
1008 // in the Framework memory space like on a real system (by the code above),
1009 // but the entry point points into the DLL loaded by the code bellow.
1012 DllEntryPoint
= NULL
;
1015 // Load the DLL if it's not an EBC image.
1017 if ((ImageContext
->PdbPointer
!= NULL
) &&
1018 (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
)) {
1020 // Convert filename from ASCII to Unicode
1022 DllFileName
= AsciiToUnicode (ImageContext
->PdbPointer
, &Index
);
1025 // Check that we have a valid filename
1027 if (Index
< 5 || DllFileName
[Index
- 4] != '.') {
1031 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1032 // The image will run, but we just can't source level debug. If we
1033 // return an error the image will not run.
1038 // Replace .PDB with .DLL on the filename
1040 DllFileName
[Index
- 3] = 'D';
1041 DllFileName
[Index
- 2] = 'L';
1042 DllFileName
[Index
- 1] = 'L';
1045 // Load the .DLL file into the user process's address space for source
1048 Library
= LoadLibraryEx (DllFileName
, NULL
, DONT_RESOLVE_DLL_REFERENCES
);
1049 if (Library
!= NULL
) {
1051 // InitializeDriver is the entry point we put in all our EFI DLL's. The
1052 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() suppresses the
1053 // normal DLL entry point of DllMain, and prevents other modules that are
1054 // referenced in side the DllFileName from being loaded. There is no error
1055 // checking as the we can point to the PE32 image loaded by Tiano. This
1056 // step is only needed for source level debugging
1058 DllEntryPoint
= (VOID
*) (UINTN
) GetProcAddress (Library
, "InitializeDriver");
1062 if ((Library
!= NULL
) && (DllEntryPoint
!= NULL
)) {
1063 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) DllEntryPoint
;
1064 SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName
);
1066 SecPrint ("WARNING: No source level debug %S. \n", DllFileName
);
1073 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1074 // The image will run, but we just can't source level debug. If we
1075 // return an error the image will not run.
1092 SecTemporaryRamSupport (
1093 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1094 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1095 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1100 // Migrate the whole temporary memory to permanent memory.
1103 (VOID
*)(UINTN
)PermanentMemoryBase
,
1104 (VOID
*)(UINTN
)TemporaryMemoryBase
,
1109 // SecSwitchStack function must be invoked after the memory migration
1110 // immediately, also we need fixup the stack change caused by new call into
1111 // permanent memory.
1114 (UINT32
) TemporaryMemoryBase
,
1115 (UINT32
) PermanentMemoryBase
1119 // We need *not* fix the return address because currently,
1120 // The PeiCore is executed in flash.
1124 // Simulate to invalid temporary memory, terminate temporary memory
1126 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);