3 Copyright (c) 2006 - 2011, 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
120 CHAR8 Buffer
[EFI_STATUS_CODE_DATA_MAX_SIZE
];
122 va_start (Marker
, Format
);
124 _vsnprintf (Buffer
, sizeof (Buffer
), Format
, Marker
);
126 CharCount
= strlen (Buffer
);
128 GetStdHandle (STD_OUTPUT_HANDLE
),
146 Main entry point to SEC for WinNt. This is a Windows program
149 Argc - Number of command line arguments
150 Argv - Array of command line argument strings
151 Envp - Array of environmemt variable strings
161 TOKEN_PRIVILEGES TokenPrivileges
;
162 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
163 UINT64 InitialStackMemorySize
;
171 CHAR16
*MemorySizeStr
;
172 CHAR16
*FirmwareVolumesStr
;
176 // Enable the privilege so that RTC driver can successfully run SetTime()
178 OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
|TOKEN_QUERY
, &Token
);
179 if (LookupPrivilegeValue(NULL
, SE_TIME_ZONE_NAME
, &TokenPrivileges
.Privileges
[0].Luid
)) {
180 TokenPrivileges
.PrivilegeCount
= 1;
181 TokenPrivileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
182 AdjustTokenPrivileges(Token
, FALSE
, &TokenPrivileges
, 0, (PTOKEN_PRIVILEGES
) NULL
, 0);
185 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdWinNtMemorySizeForSecMain
);
186 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdWinNtFirmwareVolume
);
188 SecPrint ("\nEDK II SEC Main NT Emulation Environment from www.TianoCore.org\n");
191 // Make some Windows calls to Set the process to the highest priority in the
192 // idle class. We need this to have good performance.
194 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS
);
195 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST
);
198 // Allocate space for gSystemMemory Array
200 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
201 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (NT_SYSTEM_MEMORY
));
202 if (gSystemMemory
== NULL
) {
203 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr
);
207 // Allocate space for gSystemMemory Array
209 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
210 gFdInfo
= calloc (gFdInfoCount
, sizeof (NT_FD_INFO
));
211 if (gFdInfo
== NULL
) {
212 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr
);
216 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
218 SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdWinNtBootMode
));
221 // Allocate 128K memory to emulate temp memory for PEI.
222 // on a real platform this would be SRAM, or using the cache as RAM.
223 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
225 InitialStackMemorySize
= STACK_SIZE
;
226 InitialStackMemory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (InitialStackMemorySize
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
227 if (InitialStackMemory
== 0) {
228 SecPrint ("ERROR : Can not allocate enough space for SecStack\n");
232 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
233 StackPointer
< (UINTN
*) ((UINTN
)InitialStackMemory
+ (SIZE_T
) InitialStackMemorySize
);
235 *StackPointer
= 0x5AA55AA5;
238 SecPrint (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize
);
241 // Open All the firmware volumes and remember the info in the gFdInfo global
243 FileNamePtr
= (CHAR16
*)malloc (StrLen ((CHAR16
*)FirmwareVolumesStr
) * sizeof(CHAR16
));
244 if (FileNamePtr
== NULL
) {
245 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");
249 StrCpy (FileNamePtr
, (CHAR16
*)FirmwareVolumesStr
);
251 for (Done
= FALSE
, Index
= 0, PeiCoreFile
= NULL
; !Done
; Index
++) {
252 FileName
= FileNamePtr
;
253 for (Index1
= 0; (FileNamePtr
[Index1
] != '!') && (FileNamePtr
[Index1
] != 0); Index1
++)
255 if (FileNamePtr
[Index1
] == 0) {
258 FileNamePtr
[Index1
] = '\0';
259 FileNamePtr
= FileNamePtr
+ Index1
+ 1;
263 // Open the FD and remmeber where it got mapped into our processes address space
265 Status
= WinNtOpenFile (
269 &gFdInfo
[Index
].Address
,
272 if (EFI_ERROR (Status
)) {
273 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName
, Status
);
277 SecPrint (" FD loaded from");
279 // printf can't print filenames directly as the \ gets interperted as an
282 for (Index2
= 0; FileName
[Index2
] != '\0'; Index2
++) {
283 SecPrint ("%c", FileName
[Index2
]);
286 if (PeiCoreFile
== NULL
) {
288 // Assume the beginning of the FD is an FV and look for the PEI Core.
289 // Load the first one we find.
291 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
292 if (!EFI_ERROR (Status
)) {
293 SecPrint (" contains SEC Core");
300 // Calculate memory regions and store the information in the gSystemMemory
301 // global for later use. The autosizing code will use this data to
302 // map this memory into the SEC process memory space.
304 for (Index
= 0, Done
= FALSE
; !Done
; Index
++) {
306 // Save the size of the memory and make a Unicode filename SystemMemory00, ...
308 gSystemMemory
[Index
].Size
= _wtoi (MemorySizeStr
) * 0x100000;
311 // Find the next region
313 for (Index1
= 0; MemorySizeStr
[Index1
] != '!' && MemorySizeStr
[Index1
] != 0; Index1
++)
315 if (MemorySizeStr
[Index1
] == 0) {
319 MemorySizeStr
= MemorySizeStr
+ Index1
+ 1;
325 // Hand off to PEI Core
327 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
330 // If we get here, then the PEI Core returned. This is an error as PEI should
331 // always hand off to DXE.
333 SecPrint ("ERROR : PEI Core returned\n");
341 IN DWORD CreationDisposition
,
342 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
348 Opens and memory maps a file using WinNt services. If BaseAddress is non zero
349 the process will try and allocate the memory starting at BaseAddress.
352 FileName - The name of the file to open and map
353 MapSize - The amount of the file to map in bytes
354 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
355 memory emulation, and exiting files for firmware volume emulation
356 BaseAddress - The base address of the mapped file in the user address space.
357 If passed in as NULL the a new memory region is used.
358 If passed in as non NULL the request memory region is used for
359 the mapping of the file into the process space.
360 Length - The size of the mapped region in bytes
363 EFI_SUCCESS - The file was opened and mapped.
364 EFI_NOT_FOUND - FileName was not found in the current directory
365 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
371 VOID
*VirtualAddress
;
375 // Use Win API to open/create a file
377 NtFileHandle
= CreateFile (
379 GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
,
383 FILE_ATTRIBUTE_NORMAL
,
386 if (NtFileHandle
== INVALID_HANDLE_VALUE
) {
387 return EFI_NOT_FOUND
;
390 // Map the open file into a memory range
392 NtMapHandle
= CreateFileMapping (
395 PAGE_EXECUTE_READWRITE
,
400 if (NtMapHandle
== NULL
) {
401 return EFI_DEVICE_ERROR
;
404 // Get the virtual address (address in the emulator) of the mapped file
406 VirtualAddress
= MapViewOfFileEx (
408 FILE_MAP_EXECUTE
| FILE_MAP_ALL_ACCESS
,
412 (LPVOID
) (UINTN
) *BaseAddress
414 if (VirtualAddress
== NULL
) {
415 return EFI_DEVICE_ERROR
;
420 // Seek to the end of the file to figure out the true file size.
422 FileSize
= SetFilePointer (
428 if (FileSize
== -1) {
429 return EFI_DEVICE_ERROR
;
432 *Length
= (UINT64
) FileSize
;
434 *Length
= (UINT64
) MapSize
;
437 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAddress
;
443 #define BYTES_PER_RECORD 512
447 SecPeiReportStatusCode (
448 IN CONST EFI_PEI_SERVICES
**PeiServices
,
449 IN EFI_STATUS_CODE_TYPE CodeType
,
450 IN EFI_STATUS_CODE_VALUE Value
,
452 IN CONST EFI_GUID
*CallerId
,
453 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
459 This routine produces the ReportStatusCode PEI service. It's passed
460 up to the PEI Core via a PPI. T
462 This code currently uses the NT clib printf. This does not work the same way
463 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
466 (see EFI_PEI_REPORT_STATUS_CODE)
469 EFI_SUCCESS - Always return success
472 // TODO: PeiServices - add argument and description to function comment
473 // TODO: CodeType - add argument and description to function comment
474 // TODO: Value - add argument and description to function comment
475 // TODO: Instance - add argument and description to function comment
476 // TODO: CallerId - add argument and description to function comment
477 // TODO: Data - add argument and description to function comment
481 CHAR8 PrintBuffer
[BYTES_PER_RECORD
* 2];
489 } else if (ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
491 // Processes ASSERT ()
493 SecPrint ("ASSERT %s(%d): %s\n", Filename
, (int)LineNumber
, Description
);
495 } else if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
497 // Process DEBUG () macro
499 AsciiBSPrint (PrintBuffer
, BYTES_PER_RECORD
, Format
, Marker
);
500 SecPrint (PrintBuffer
);
507 Transfers control to a function starting with a new stack.
509 Transfers control to the function specified by EntryPoint using the new stack
510 specified by NewStack and passing in the parameters specified by Context1 and
511 Context2. Context1 and Context2 are optional and may be NULL. The function
512 EntryPoint must never return.
514 If EntryPoint is NULL, then ASSERT().
515 If NewStack is NULL, then ASSERT().
517 @param EntryPoint A pointer to function to call with the new stack.
518 @param Context1 A pointer to the context to pass into the EntryPoint
520 @param Context2 A pointer to the context to pass into the EntryPoint
522 @param NewStack A pointer to the new stack to use for the EntryPoint
524 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
525 Reserved on other architectures.
531 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
532 IN VOID
*Context1
, OPTIONAL
533 IN VOID
*Context2
, OPTIONAL
534 IN VOID
*Context3
, OPTIONAL
538 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
540 ASSERT (EntryPoint
!= NULL
);
541 ASSERT (NewStack
!= NULL
);
544 // Stack should be aligned with CPU_STACK_ALIGNMENT
546 ASSERT (((UINTN
)NewStack
& (CPU_STACK_ALIGNMENT
- 1)) == 0);
548 JumpBuffer
.Eip
= (UINTN
)EntryPoint
;
549 JumpBuffer
.Esp
= (UINTN
)NewStack
- sizeof (VOID
*);
550 JumpBuffer
.Esp
-= sizeof (Context1
) + sizeof (Context2
) + sizeof(Context3
);
551 ((VOID
**)JumpBuffer
.Esp
)[1] = Context1
;
552 ((VOID
**)JumpBuffer
.Esp
)[2] = Context2
;
553 ((VOID
**)JumpBuffer
.Esp
)[3] = Context3
;
555 LongJump (&JumpBuffer
, (UINTN
)-1);
559 // InternalSwitchStack () will never return
566 IN UINTN LargestRegion
,
567 IN UINTN LargestRegionSize
,
568 IN UINTN BootFirmwareVolumeBase
,
569 IN VOID
*PeiCorePe32File
574 This is the service to load the PEI Core from the Firmware Volume
577 LargestRegion - Memory to use for PEI.
578 LargestRegionSize - Size of Memory to use for PEI
579 BootFirmwareVolumeBase - Start of the Boot FV
580 PeiCorePe32File - PEI Core PE32
583 Success means control is transfered and thus we should never return
590 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
591 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
592 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
596 // Compute Top Of Memory for Stack and PEI Core Allocations
598 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
601 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
604 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
607 // |-----------| <---- TemporaryRamBase
609 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
612 // Reservet space for storing PeiCore's parament in stack.
614 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
615 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
618 // Bind this information into the SEC hand-off state
620 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
621 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
622 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
623 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32(PcdWinNtFirmwareFdSize
);
624 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
625 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
626 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
627 SecCoreData
->StackSize
= PeiStackSize
;
628 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
629 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
632 // Load the PEI Core from a Firmware Volume
634 Status
= SecWinNtPeiLoadFile (
640 if (EFI_ERROR (Status
)) {
645 // Transfer control to the PEI Core
648 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
650 (VOID
*) (UINTN
) ((EFI_PEI_PPI_DESCRIPTOR
*) &gPrivateDispatchTable
),
655 // If we get here, then the PEI Core returned. This is an error
662 SecWinNtPeiAutoScan (
664 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
665 OUT UINT64
*MemorySize
670 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
671 It allows discontiguous memory regions to be supported by the emulator.
672 It uses gSystemMemory[] and gSystemMemoryCount that were created by
673 parsing PcdWinNtMemorySizeForSecMain value.
674 The size comes from the Pcd value and the address comes from the memory space
675 with ReadWrite and Execute attributes allocated by VirtualAlloc() API.
678 Index - Which memory region to use
679 MemoryBase - Return Base address of memory region
680 MemorySize - Return size in bytes of the memory region
683 EFI_SUCCESS - If memory region was mapped
684 EFI_UNSUPPORTED - If Index is not supported
688 if (Index
>= gSystemMemoryCount
) {
689 return EFI_UNSUPPORTED
;
693 // Allocate enough memory space for emulator
695 gSystemMemory
[Index
].Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (gSystemMemory
[Index
].Size
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
696 if (gSystemMemory
[Index
].Memory
== 0) {
697 return EFI_OUT_OF_RESOURCES
;
700 *MemoryBase
= gSystemMemory
[Index
].Memory
;
701 *MemorySize
= gSystemMemory
[Index
].Size
;
708 SecWinNtWinNtThunkAddress (
714 Since the SEC is the only Windows program in stack it must export
715 an interface to do Win API calls. That's what the WinNtThunk address
716 is for. gWinNt is initailized in WinNtThunk.c.
719 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
720 InterfaceBase - Address of the gWinNt global
723 EFI_SUCCESS - Data returned
733 SecWinNtPeiLoadFile (
735 IN EFI_PHYSICAL_ADDRESS
*ImageAddress
,
736 IN UINT64
*ImageSize
,
737 IN EFI_PHYSICAL_ADDRESS
*EntryPoint
742 Loads and relocates a PE/COFF image into memory.
745 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
746 ImageAddress - The base address of the relocated PE/COFF image
747 ImageSize - The size of the relocated PE/COFF image
748 EntryPoint - The entry point of the relocated PE/COFF image
751 EFI_SUCCESS - The file was loaded and relocated
752 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
757 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
759 ZeroMem (&ImageContext
, sizeof (ImageContext
));
760 ImageContext
.Handle
= Pe32Data
;
762 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
764 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
765 if (EFI_ERROR (Status
)) {
769 // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribue.
770 // Extra space is for alignment
772 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
773 if (ImageContext
.ImageAddress
== 0) {
774 return EFI_OUT_OF_RESOURCES
;
777 // Align buffer on section boundry
779 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
780 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
782 Status
= PeCoffLoaderLoadImage (&ImageContext
);
783 if (EFI_ERROR (Status
)) {
787 Status
= SecNt32PeCoffRelocateImage (&ImageContext
);
788 if (EFI_ERROR (Status
)) {
793 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
796 *ImageAddress
= ImageContext
.ImageAddress
;
797 *ImageSize
= ImageContext
.ImageSize
;
798 *EntryPoint
= ImageContext
.EntryPoint
;
807 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
808 IN OUT UINT64
*FdSize
813 Return the FD Size and base address. Since the FD is loaded from a
814 file into Windows memory only the SEC will know it's address.
817 Index - Which FD, starts at zero.
818 FdSize - Size of the FD in bytes
819 FdBase - Start address of the FD. Assume it points to an FV Header
822 EFI_SUCCESS - Return the Base address and size of the FV
823 EFI_UNSUPPORTED - Index does nto map to an FD in the system
827 if (Index
>= gFdInfoCount
) {
828 return EFI_UNSUPPORTED
;
831 *FdBase
= gFdInfo
[Index
].Address
;
832 *FdSize
= gFdInfo
[Index
].Size
;
834 if (*FdBase
== 0 && *FdSize
== 0) {
835 return EFI_UNSUPPORTED
;
846 IN OUT UINTN
*ReadSize
,
852 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
855 FileHandle - The handle to the PE/COFF file
856 FileOffset - The offset, in bytes, into the file to read
857 ReadSize - The number of bytes to read from the file starting at FileOffset
858 Buffer - A pointer to the buffer to read the data into.
861 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
869 Destination8
= Buffer
;
870 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
873 *(Destination8
++) = *(Source8
++);
882 IN UINTN
*StrLen OPTIONAL
887 Convert the passed in Ascii string to Unicode.
888 Optionally return the length of the strings.
891 Ascii - Ascii string to convert
892 StrLen - Length of string
895 Pointer to malloc'ed Unicode version of Ascii
903 // Allocate a buffer for unicode string
905 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++)
907 Unicode
= malloc ((Index
+ 1) * sizeof (CHAR16
));
908 if (Unicode
== NULL
) {
912 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++) {
913 Unicode
[Index
] = (CHAR16
) Ascii
[Index
];
916 Unicode
[Index
] = '\0';
918 if (StrLen
!= NULL
) {
926 CountSeperatorsInString (
927 IN CONST CHAR16
*String
,
933 Count the number of seperators in String
936 String - String to process
937 Seperator - Item to count
940 Number of Seperator in String
946 for (Count
= 0; *String
!= '\0'; String
++) {
947 if (*String
== Seperator
) {
957 SecNt32PeCoffRelocateImage (
958 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
968 Status
= PeCoffLoaderRelocateImage (ImageContext
);
969 if (EFI_ERROR (Status
)) {
971 // We could not relocated the image in memory properly
977 // If we load our own PE COFF images the Windows debugger can not source
978 // level debug our code. If a valid PDB pointer exists usw it to load
979 // the *.dll file as a library using Windows* APIs. This allows
980 // source level debug. The image is still loaded and reloaced
981 // in the Framework memory space like on a real system (by the code above),
982 // but the entry point points into the DLL loaded by the code bellow.
985 DllEntryPoint
= NULL
;
988 // Load the DLL if it's not an EBC image.
990 if ((ImageContext
->PdbPointer
!= NULL
) &&
991 (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
)) {
993 // Convert filename from ASCII to Unicode
995 DllFileName
= AsciiToUnicode (ImageContext
->PdbPointer
, &Index
);
998 // Check that we have a valid filename
1000 if (Index
< 5 || DllFileName
[Index
- 4] != '.') {
1004 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1005 // The image will run, but we just can't source level debug. If we
1006 // return an error the image will not run.
1011 // Replace .PDB with .DLL on the filename
1013 DllFileName
[Index
- 3] = 'D';
1014 DllFileName
[Index
- 2] = 'L';
1015 DllFileName
[Index
- 1] = 'L';
1018 // Load the .DLL file into the user process's address space for source
1021 Library
= LoadLibraryEx (DllFileName
, NULL
, DONT_RESOLVE_DLL_REFERENCES
);
1022 if (Library
!= NULL
) {
1024 // InitializeDriver is the entry point we put in all our EFI DLL's. The
1025 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() supresses the
1026 // normal DLL entry point of DllMain, and prevents other modules that are
1027 // referenced in side the DllFileName from being loaded. There is no error
1028 // checking as the we can point to the PE32 image loaded by Tiano. This
1029 // step is only needed for source level debuging
1031 DllEntryPoint
= (VOID
*) (UINTN
) GetProcAddress (Library
, "InitializeDriver");
1035 if ((Library
!= NULL
) && (DllEntryPoint
!= NULL
)) {
1036 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) DllEntryPoint
;
1037 SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName
);
1039 SecPrint ("WARNING: No source level debug %S. \n", DllFileName
);
1046 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1047 // The image will run, but we just can't source level debug. If we
1048 // return an error the image will not run.
1065 SecTemporaryRamSupport (
1066 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1067 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1068 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1073 // Migrate the whole temporary memory to permenent memory.
1076 (VOID
*)(UINTN
)PermanentMemoryBase
,
1077 (VOID
*)(UINTN
)TemporaryMemoryBase
,
1082 // SecSwitchStack function must be invoked after the memory migration
1083 // immediatly, also we need fixup the stack change caused by new call into
1084 // permenent memory.
1087 (UINT32
) TemporaryMemoryBase
,
1088 (UINT32
) PermanentMemoryBase
1092 // We need *not* fix the return address because currently,
1093 // The PeiCore is excuted in flash.
1097 // Simulate to invalid temporary memory, terminate temporary memory
1099 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);