3 Copyright (c) 2006 - 2012, 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
);
128 CharCount
= strlen (Buffer
);
130 GetStdHandle (STD_OUTPUT_HANDLE
),
148 Main entry point to SEC for WinNt. This is a Windows program
151 Argc - Number of command line arguments
152 Argv - Array of command line argument strings
153 Envp - Array of environmemt variable strings
163 TOKEN_PRIVILEGES TokenPrivileges
;
164 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
165 UINT64 InitialStackMemorySize
;
173 CHAR16
*MemorySizeStr
;
174 CHAR16
*FirmwareVolumesStr
;
178 // Enable the privilege so that RTC driver can successfully run SetTime()
180 OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
|TOKEN_QUERY
, &Token
);
181 if (LookupPrivilegeValue(NULL
, SE_TIME_ZONE_NAME
, &TokenPrivileges
.Privileges
[0].Luid
)) {
182 TokenPrivileges
.PrivilegeCount
= 1;
183 TokenPrivileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
184 AdjustTokenPrivileges(Token
, FALSE
, &TokenPrivileges
, 0, (PTOKEN_PRIVILEGES
) NULL
, 0);
187 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdWinNtMemorySizeForSecMain
);
188 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdWinNtFirmwareVolume
);
190 SecPrint ("\nEDK II SEC Main NT Emulation Environment from www.TianoCore.org\n");
193 // Make some Windows calls to Set the process to the highest priority in the
194 // idle class. We need this to have good performance.
196 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS
);
197 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST
);
200 // Allocate space for gSystemMemory Array
202 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
203 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (NT_SYSTEM_MEMORY
));
204 if (gSystemMemory
== NULL
) {
205 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr
);
209 // Allocate space for gSystemMemory Array
211 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
212 gFdInfo
= calloc (gFdInfoCount
, sizeof (NT_FD_INFO
));
213 if (gFdInfo
== NULL
) {
214 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr
);
218 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
220 SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdWinNtBootMode
));
223 // Allocate 128K memory to emulate temp memory for PEI.
224 // on a real platform this would be SRAM, or using the cache as RAM.
225 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
227 InitialStackMemorySize
= STACK_SIZE
;
228 InitialStackMemory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (InitialStackMemorySize
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
229 if (InitialStackMemory
== 0) {
230 SecPrint ("ERROR : Can not allocate enough space for SecStack\n");
234 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
235 StackPointer
< (UINTN
*) ((UINTN
)InitialStackMemory
+ (SIZE_T
) InitialStackMemorySize
);
237 *StackPointer
= 0x5AA55AA5;
240 SecPrint (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize
);
243 // Open All the firmware volumes and remember the info in the gFdInfo global
245 FileNamePtr
= (CHAR16
*)malloc (StrLen ((CHAR16
*)FirmwareVolumesStr
) * sizeof(CHAR16
));
246 if (FileNamePtr
== NULL
) {
247 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");
251 StrCpy (FileNamePtr
, (CHAR16
*)FirmwareVolumesStr
);
253 for (Done
= FALSE
, Index
= 0, PeiCoreFile
= NULL
; !Done
; Index
++) {
254 FileName
= FileNamePtr
;
255 for (Index1
= 0; (FileNamePtr
[Index1
] != '!') && (FileNamePtr
[Index1
] != 0); Index1
++)
257 if (FileNamePtr
[Index1
] == 0) {
260 FileNamePtr
[Index1
] = '\0';
261 FileNamePtr
= FileNamePtr
+ Index1
+ 1;
265 // Open the FD and remmeber where it got mapped into our processes address space
267 Status
= WinNtOpenFile (
271 &gFdInfo
[Index
].Address
,
274 if (EFI_ERROR (Status
)) {
275 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName
, Status
);
279 SecPrint (" FD loaded from");
281 // printf can't print filenames directly as the \ gets interperted as an
284 for (Index2
= 0; FileName
[Index2
] != '\0'; Index2
++) {
285 SecPrint ("%c", FileName
[Index2
]);
288 if (PeiCoreFile
== NULL
) {
290 // Assume the beginning of the FD is an FV and look for the PEI Core.
291 // Load the first one we find.
293 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
294 if (!EFI_ERROR (Status
)) {
295 SecPrint (" contains SEC Core");
302 // Calculate memory regions and store the information in the gSystemMemory
303 // global for later use. The autosizing code will use this data to
304 // map this memory into the SEC process memory space.
306 for (Index
= 0, Done
= FALSE
; !Done
; Index
++) {
308 // Save the size of the memory and make a Unicode filename SystemMemory00, ...
310 gSystemMemory
[Index
].Size
= _wtoi (MemorySizeStr
) * 0x100000;
313 // Find the next region
315 for (Index1
= 0; MemorySizeStr
[Index1
] != '!' && MemorySizeStr
[Index1
] != 0; Index1
++)
317 if (MemorySizeStr
[Index1
] == 0) {
321 MemorySizeStr
= MemorySizeStr
+ Index1
+ 1;
327 // Hand off to PEI Core
329 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
332 // If we get here, then the PEI Core returned. This is an error as PEI should
333 // always hand off to DXE.
335 SecPrint ("ERROR : PEI Core returned\n");
343 IN DWORD CreationDisposition
,
344 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
350 Opens and memory maps a file using WinNt services. If BaseAddress is non zero
351 the process will try and allocate the memory starting at BaseAddress.
354 FileName - The name of the file to open and map
355 MapSize - The amount of the file to map in bytes
356 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
357 memory emulation, and exiting files for firmware volume emulation
358 BaseAddress - The base address of the mapped file in the user address space.
359 If passed in as NULL the a new memory region is used.
360 If passed in as non NULL the request memory region is used for
361 the mapping of the file into the process space.
362 Length - The size of the mapped region in bytes
365 EFI_SUCCESS - The file was opened and mapped.
366 EFI_NOT_FOUND - FileName was not found in the current directory
367 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
373 VOID
*VirtualAddress
;
377 // Use Win API to open/create a file
379 NtFileHandle
= CreateFile (
381 GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
,
385 FILE_ATTRIBUTE_NORMAL
,
388 if (NtFileHandle
== INVALID_HANDLE_VALUE
) {
389 return EFI_NOT_FOUND
;
392 // Map the open file into a memory range
394 NtMapHandle
= CreateFileMapping (
397 PAGE_EXECUTE_READWRITE
,
402 if (NtMapHandle
== NULL
) {
403 return EFI_DEVICE_ERROR
;
406 // Get the virtual address (address in the emulator) of the mapped file
408 VirtualAddress
= MapViewOfFileEx (
410 FILE_MAP_EXECUTE
| FILE_MAP_ALL_ACCESS
,
414 (LPVOID
) (UINTN
) *BaseAddress
416 if (VirtualAddress
== NULL
) {
417 return EFI_DEVICE_ERROR
;
422 // Seek to the end of the file to figure out the true file size.
424 FileSize
= SetFilePointer (
430 if (FileSize
== -1) {
431 return EFI_DEVICE_ERROR
;
434 *Length
= (UINT64
) FileSize
;
436 *Length
= (UINT64
) MapSize
;
439 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAddress
;
445 #define BYTES_PER_RECORD 512
449 SecPeiReportStatusCode (
450 IN CONST EFI_PEI_SERVICES
**PeiServices
,
451 IN EFI_STATUS_CODE_TYPE CodeType
,
452 IN EFI_STATUS_CODE_VALUE Value
,
454 IN CONST EFI_GUID
*CallerId
,
455 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
461 This routine produces the ReportStatusCode PEI service. It's passed
462 up to the PEI Core via a PPI. T
464 This code currently uses the NT clib printf. This does not work the same way
465 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
468 (see EFI_PEI_REPORT_STATUS_CODE)
471 EFI_SUCCESS - Always return success
474 // TODO: PeiServices - add argument and description to function comment
475 // TODO: CodeType - add argument and description to function comment
476 // TODO: Value - add argument and description to function comment
477 // TODO: Instance - add argument and description to function comment
478 // TODO: CallerId - add argument and description to function comment
479 // TODO: Data - add argument and description to function comment
483 CHAR8 PrintBuffer
[BYTES_PER_RECORD
* 2];
491 } else if (ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
493 // Processes ASSERT ()
495 SecPrint ("ASSERT %s(%d): %s\n", Filename
, (int)LineNumber
, Description
);
497 } else if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
499 // Process DEBUG () macro
501 AsciiBSPrint (PrintBuffer
, BYTES_PER_RECORD
, Format
, Marker
);
502 SecPrint (PrintBuffer
);
509 Transfers control to a function starting with a new stack.
511 Transfers control to the function specified by EntryPoint using the new stack
512 specified by NewStack and passing in the parameters specified by Context1 and
513 Context2. Context1 and Context2 are optional and may be NULL. The function
514 EntryPoint must never return.
516 If EntryPoint is NULL, then ASSERT().
517 If NewStack is NULL, then ASSERT().
519 @param EntryPoint A pointer to function to call with the new stack.
520 @param Context1 A pointer to the context to pass into the EntryPoint
522 @param Context2 A pointer to the context to pass into the EntryPoint
524 @param NewStack A pointer to the new stack to use for the EntryPoint
526 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
527 Reserved on other architectures.
533 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
534 IN VOID
*Context1
, OPTIONAL
535 IN VOID
*Context2
, OPTIONAL
536 IN VOID
*Context3
, OPTIONAL
540 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
542 ASSERT (EntryPoint
!= NULL
);
543 ASSERT (NewStack
!= NULL
);
546 // Stack should be aligned with CPU_STACK_ALIGNMENT
548 ASSERT (((UINTN
)NewStack
& (CPU_STACK_ALIGNMENT
- 1)) == 0);
550 JumpBuffer
.Eip
= (UINTN
)EntryPoint
;
551 JumpBuffer
.Esp
= (UINTN
)NewStack
- sizeof (VOID
*);
552 JumpBuffer
.Esp
-= sizeof (Context1
) + sizeof (Context2
) + sizeof(Context3
);
553 ((VOID
**)JumpBuffer
.Esp
)[1] = Context1
;
554 ((VOID
**)JumpBuffer
.Esp
)[2] = Context2
;
555 ((VOID
**)JumpBuffer
.Esp
)[3] = Context3
;
557 LongJump (&JumpBuffer
, (UINTN
)-1);
561 // InternalSwitchStack () will never return
568 IN UINTN LargestRegion
,
569 IN UINTN LargestRegionSize
,
570 IN UINTN BootFirmwareVolumeBase
,
571 IN VOID
*PeiCorePe32File
576 This is the service to load the PEI Core from the Firmware Volume
579 LargestRegion - Memory to use for PEI.
580 LargestRegionSize - Size of Memory to use for PEI
581 BootFirmwareVolumeBase - Start of the Boot FV
582 PeiCorePe32File - PEI Core PE32
585 Success means control is transfered and thus we should never return
592 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
593 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
594 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
598 // Compute Top Of Memory for Stack and PEI Core Allocations
600 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
603 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
606 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
609 // |-----------| <---- TemporaryRamBase
611 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
614 // Reservet space for storing PeiCore's parament in stack.
616 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
617 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
620 // Bind this information into the SEC hand-off state
622 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
623 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
624 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
625 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32(PcdWinNtFirmwareFdSize
);
626 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
627 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
628 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
629 SecCoreData
->StackSize
= PeiStackSize
;
630 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
631 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
634 // Load the PEI Core from a Firmware Volume
636 Status
= SecWinNtPeiLoadFile (
642 if (EFI_ERROR (Status
)) {
647 // Transfer control to the PEI Core
650 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
652 (VOID
*) (UINTN
) ((EFI_PEI_PPI_DESCRIPTOR
*) &gPrivateDispatchTable
),
657 // If we get here, then the PEI Core returned. This is an error
664 SecWinNtPeiAutoScan (
666 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
667 OUT UINT64
*MemorySize
672 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
673 It allows discontiguous memory regions to be supported by the emulator.
674 It uses gSystemMemory[] and gSystemMemoryCount that were created by
675 parsing PcdWinNtMemorySizeForSecMain value.
676 The size comes from the Pcd value and the address comes from the memory space
677 with ReadWrite and Execute attributes allocated by VirtualAlloc() API.
680 Index - Which memory region to use
681 MemoryBase - Return Base address of memory region
682 MemorySize - Return size in bytes of the memory region
685 EFI_SUCCESS - If memory region was mapped
686 EFI_UNSUPPORTED - If Index is not supported
690 if (Index
>= gSystemMemoryCount
) {
691 return EFI_UNSUPPORTED
;
695 // Allocate enough memory space for emulator
697 gSystemMemory
[Index
].Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (gSystemMemory
[Index
].Size
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
698 if (gSystemMemory
[Index
].Memory
== 0) {
699 return EFI_OUT_OF_RESOURCES
;
702 *MemoryBase
= gSystemMemory
[Index
].Memory
;
703 *MemorySize
= gSystemMemory
[Index
].Size
;
710 SecWinNtWinNtThunkAddress (
716 Since the SEC is the only Windows program in stack it must export
717 an interface to do Win API calls. That's what the WinNtThunk address
718 is for. gWinNt is initailized in WinNtThunk.c.
721 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
722 InterfaceBase - Address of the gWinNt global
725 EFI_SUCCESS - Data returned
735 SecWinNtPeiLoadFile (
737 IN EFI_PHYSICAL_ADDRESS
*ImageAddress
,
738 IN UINT64
*ImageSize
,
739 IN EFI_PHYSICAL_ADDRESS
*EntryPoint
744 Loads and relocates a PE/COFF image into memory.
747 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
748 ImageAddress - The base address of the relocated PE/COFF image
749 ImageSize - The size of the relocated PE/COFF image
750 EntryPoint - The entry point of the relocated PE/COFF image
753 EFI_SUCCESS - The file was loaded and relocated
754 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
759 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
761 ZeroMem (&ImageContext
, sizeof (ImageContext
));
762 ImageContext
.Handle
= Pe32Data
;
764 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
766 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
767 if (EFI_ERROR (Status
)) {
771 // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribue.
772 // Extra space is for alignment
774 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) VirtualAlloc (NULL
, (SIZE_T
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
775 if (ImageContext
.ImageAddress
== 0) {
776 return EFI_OUT_OF_RESOURCES
;
779 // Align buffer on section boundry
781 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
782 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
784 Status
= PeCoffLoaderLoadImage (&ImageContext
);
785 if (EFI_ERROR (Status
)) {
789 Status
= SecNt32PeCoffRelocateImage (&ImageContext
);
790 if (EFI_ERROR (Status
)) {
795 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
798 *ImageAddress
= ImageContext
.ImageAddress
;
799 *ImageSize
= ImageContext
.ImageSize
;
800 *EntryPoint
= ImageContext
.EntryPoint
;
809 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
810 IN OUT UINT64
*FdSize
815 Return the FD Size and base address. Since the FD is loaded from a
816 file into Windows memory only the SEC will know it's address.
819 Index - Which FD, starts at zero.
820 FdSize - Size of the FD in bytes
821 FdBase - Start address of the FD. Assume it points to an FV Header
824 EFI_SUCCESS - Return the Base address and size of the FV
825 EFI_UNSUPPORTED - Index does nto map to an FD in the system
829 if (Index
>= gFdInfoCount
) {
830 return EFI_UNSUPPORTED
;
833 *FdBase
= gFdInfo
[Index
].Address
;
834 *FdSize
= gFdInfo
[Index
].Size
;
836 if (*FdBase
== 0 && *FdSize
== 0) {
837 return EFI_UNSUPPORTED
;
848 IN OUT UINTN
*ReadSize
,
854 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
857 FileHandle - The handle to the PE/COFF file
858 FileOffset - The offset, in bytes, into the file to read
859 ReadSize - The number of bytes to read from the file starting at FileOffset
860 Buffer - A pointer to the buffer to read the data into.
863 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
871 Destination8
= Buffer
;
872 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
875 *(Destination8
++) = *(Source8
++);
884 IN UINTN
*StrLen OPTIONAL
889 Convert the passed in Ascii string to Unicode.
890 Optionally return the length of the strings.
893 Ascii - Ascii string to convert
894 StrLen - Length of string
897 Pointer to malloc'ed Unicode version of Ascii
905 // Allocate a buffer for unicode string
907 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++)
909 Unicode
= malloc ((Index
+ 1) * sizeof (CHAR16
));
910 if (Unicode
== NULL
) {
914 for (Index
= 0; Ascii
[Index
] != '\0'; Index
++) {
915 Unicode
[Index
] = (CHAR16
) Ascii
[Index
];
918 Unicode
[Index
] = '\0';
920 if (StrLen
!= NULL
) {
928 CountSeperatorsInString (
929 IN CONST CHAR16
*String
,
935 Count the number of seperators in String
938 String - String to process
939 Seperator - Item to count
942 Number of Seperator in String
948 for (Count
= 0; *String
!= '\0'; String
++) {
949 if (*String
== Seperator
) {
959 SecNt32PeCoffRelocateImage (
960 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
970 Status
= PeCoffLoaderRelocateImage (ImageContext
);
971 if (EFI_ERROR (Status
)) {
973 // We could not relocated the image in memory properly
979 // If we load our own PE COFF images the Windows debugger can not source
980 // level debug our code. If a valid PDB pointer exists usw it to load
981 // the *.dll file as a library using Windows* APIs. This allows
982 // source level debug. The image is still loaded and reloaced
983 // in the Framework memory space like on a real system (by the code above),
984 // but the entry point points into the DLL loaded by the code bellow.
987 DllEntryPoint
= NULL
;
990 // Load the DLL if it's not an EBC image.
992 if ((ImageContext
->PdbPointer
!= NULL
) &&
993 (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
)) {
995 // Convert filename from ASCII to Unicode
997 DllFileName
= AsciiToUnicode (ImageContext
->PdbPointer
, &Index
);
1000 // Check that we have a valid filename
1002 if (Index
< 5 || DllFileName
[Index
- 4] != '.') {
1006 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1007 // The image will run, but we just can't source level debug. If we
1008 // return an error the image will not run.
1013 // Replace .PDB with .DLL on the filename
1015 DllFileName
[Index
- 3] = 'D';
1016 DllFileName
[Index
- 2] = 'L';
1017 DllFileName
[Index
- 1] = 'L';
1020 // Load the .DLL file into the user process's address space for source
1023 Library
= LoadLibraryEx (DllFileName
, NULL
, DONT_RESOLVE_DLL_REFERENCES
);
1024 if (Library
!= NULL
) {
1026 // InitializeDriver is the entry point we put in all our EFI DLL's. The
1027 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() supresses the
1028 // normal DLL entry point of DllMain, and prevents other modules that are
1029 // referenced in side the DllFileName from being loaded. There is no error
1030 // checking as the we can point to the PE32 image loaded by Tiano. This
1031 // step is only needed for source level debuging
1033 DllEntryPoint
= (VOID
*) (UINTN
) GetProcAddress (Library
, "InitializeDriver");
1037 if ((Library
!= NULL
) && (DllEntryPoint
!= NULL
)) {
1038 ImageContext
->EntryPoint
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) DllEntryPoint
;
1039 SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName
);
1041 SecPrint ("WARNING: No source level debug %S. \n", DllFileName
);
1048 // Never return an error if PeCoffLoaderRelocateImage() succeeded.
1049 // The image will run, but we just can't source level debug. If we
1050 // return an error the image will not run.
1067 SecTemporaryRamSupport (
1068 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1069 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1070 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1075 // Migrate the whole temporary memory to permenent memory.
1078 (VOID
*)(UINTN
)PermanentMemoryBase
,
1079 (VOID
*)(UINTN
)TemporaryMemoryBase
,
1084 // SecSwitchStack function must be invoked after the memory migration
1085 // immediatly, also we need fixup the stack change caused by new call into
1086 // permenent memory.
1089 (UINT32
) TemporaryMemoryBase
,
1090 (UINT32
) PermanentMemoryBase
1094 // We need *not* fix the return address because currently,
1095 // The PeiCore is excuted in flash.
1099 // Simulate to invalid temporary memory, terminate temporary memory
1101 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);