3 Copyright (c) 2006 - 2007 Intel Corporation.
4 All rights reserved. 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 Posix application, but this is
18 Ok since all the other modules for NT32 are NOT Posix applications.
20 This program processes host environment variables and figures out
21 what the memory layout will be, how may FD's will be loaded and also
22 what the boot mode is.
24 The SEC registers a set of services with the SEC core. gPrivateDispatchTable
25 is a list of PPI's produced by the SEC that are availble for usage in PEI.
27 This code produces 128 K of temporary memory for the PEI stack by opening a
28 host file and mapping it directly to memory addresses.
30 The system.cmd script is used to set host environment variables that drive
31 the configuration opitons of the SEC.
37 #include <Ppi/UnixPeiLoadFile.h>
38 #include <Framework/StatusCode.h>
39 #include <Ppi/TemporaryRamSupport.h>
44 EFI_PEI_PE_COFF_LOADER_PROTOCOL_INSTANCE mPeiEfiPeiPeCoffLoaderInstance
= {
46 SecNt32PeCoffGetImageInfo
,
47 SecNt32PeCoffLoadImage
,
48 SecNt32PeCoffRelocateImage
,
49 SecNt32PeCoffUnloadimage
56 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*gPeiEfiPeiPeCoffLoader
= &mPeiEfiPeiPeCoffLoaderInstance
.PeCoff
;
58 UNIX_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi
= { SecWinNtPeiLoadFile
};
60 PEI_UNIX_AUTOSCAN_PPI mSecNtAutoScanPpi
= { SecWinNtPeiAutoScan
};
62 PEI_UNIX_THUNK_PPI mSecWinNtThunkPpi
= { SecWinNtWinNtThunkAddress
};
64 EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi
= { SecPeiReportStatusCode
};
66 UNIX_FWH_PPI mSecFwhInformationPpi
= { SecWinNtFdAddress
};
68 TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi
= {SecTemporaryRamSupport
};
70 EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable
[] = {
72 EFI_PEI_PPI_DESCRIPTOR_PPI
,
73 &gEfiPeiPeCoffLoaderGuid
,
77 EFI_PEI_PPI_DESCRIPTOR_PPI
,
78 &gUnixPeiLoadFilePpiGuid
,
82 EFI_PEI_PPI_DESCRIPTOR_PPI
,
83 &gPeiUnixAutoScanPpiGuid
,
87 EFI_PEI_PPI_DESCRIPTOR_PPI
,
88 &gPeiUnixThunkPpiGuid
,
92 EFI_PEI_PPI_DESCRIPTOR_PPI
,
93 &gEfiPeiStatusCodePpiGuid
,
97 EFI_PEI_PPI_DESCRIPTOR_PPI
,
98 &gEfiTemporaryRamSupportPpiGuid
,
99 &mSecTemporaryRamSupportPpi
103 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
105 &mSecFwhInformationPpi
111 // Default information about where the FD is located.
112 // This array gets filled in with information from EFI_FIRMWARE_VOLUMES
113 // EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd.
114 // The number of array elements is allocated base on parsing
115 // EFI_FIRMWARE_VOLUMES and the memory is never freed.
117 UINTN gFdInfoCount
= 0;
118 UNIX_FD_INFO
*gFdInfo
;
121 // Array that supports seperate memory rantes.
122 // The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
123 // The number of array elements is allocated base on parsing
124 // EFI_MEMORY_SIZE and the memory is never freed.
126 UINTN gSystemMemoryCount
= 0;
127 UNIX_SYSTEM_MEMORY
*gSystemMemory
;
132 UINT32 TemporaryMemoryBase
,
133 UINT32 PermenentMemoryBase
137 EFI_PHYSICAL_ADDRESS
*
148 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
163 Main entry point to SEC for WinNt. This is a unix program
166 Argc - Number of command line arguments
167 Argv - Array of command line argument strings
168 Envp - Array of environmemt variable strings
177 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
178 UINT64 InitialStackMemorySize
;
186 CHAR16
*MemorySizeStr
;
187 CHAR16
*FirmwareVolumesStr
;
193 MemorySizeStr
= (CHAR16
*) FixedPcdGetPtr (PcdUnixMemorySizeForSecMain
);
194 FirmwareVolumesStr
= (CHAR16
*) FixedPcdGetPtr (PcdUnixFirmwareVolume
);
196 printf ("\nEDK SEC Main UNIX Emulation Environment from www.TianoCore.org\n");
199 // Allocate space for gSystemMemory Array
201 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
202 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (UNIX_SYSTEM_MEMORY
));
203 if (gSystemMemory
== NULL
) {
204 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
208 // Allocate space for gSystemMemory Array
210 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
211 gFdInfo
= calloc (gFdInfoCount
, sizeof (UNIX_FD_INFO
));
212 if (gFdInfo
== NULL
) {
213 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
217 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
219 printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdUnixBootMode
));
222 // Open up a 128K file to emulate temp memory for PEI.
223 // on a real platform this would be SRAM, or using the cache as RAM.
224 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
226 InitialStackMemorySize
= STACK_SIZE
;
227 InitialStackMemory
= (UINTN
)MapMemory(0,
228 (UINT32
) InitialStackMemorySize
,
229 PROT_READ
| PROT_WRITE
,
230 MAP_ANONYMOUS
| MAP_PRIVATE
);
231 if (InitialStackMemory
== 0) {
232 printf ("ERROR : Can not open SecStack Exiting\n");
236 printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n",
237 (UINTN
)(InitialStackMemorySize
/ 1024),
238 (unsigned long)InitialStackMemory
);
240 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
241 StackPointer
< (UINTN
*) ((UINTN
) InitialStackMemory
+ (UINT64
) InitialStackMemorySize
);
243 *StackPointer
= 0x5AA55AA5;
247 // Open All the firmware volumes and remember the info in the gFdInfo global
249 FileName
= (CHAR8
*)malloc (StrLen (FirmwareVolumesStr
) + 1);
250 if (FileName
== NULL
) {
251 printf ("ERROR : Can not allocate memory for firmware volume string\n");
256 for (Done
= FALSE
, Index
= 0, PeiIndex
= 0, PeiCoreFile
= NULL
;
257 FirmwareVolumesStr
[Index2
] != 0;
259 for (Index1
= 0; (FirmwareVolumesStr
[Index2
] != '!') && (FirmwareVolumesStr
[Index2
] != 0); Index2
++)
260 FileName
[Index1
++] = FirmwareVolumesStr
[Index2
];
261 if (FirmwareVolumesStr
[Index2
] == '!')
263 FileName
[Index1
] = '\0';
266 // Open the FD and remmeber where it got mapped into our processes address space
270 &gFdInfo
[Index
].Address
,
273 if (EFI_ERROR (Status
)) {
274 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName
, Status
);
278 printf (" FD loaded from %s at 0x%08lx",
279 FileName
, (unsigned long)gFdInfo
[Index
].Address
);
281 if (PeiCoreFile
== NULL
) {
283 // Assume the beginning of the FD is an FV and look for the PEI Core.
284 // Load the first one we find.
286 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
287 if (!EFI_ERROR (Status
)) {
289 printf (" contains SEC Core");
296 // Calculate memory regions and store the information in the gSystemMemory
297 // global for later use. The autosizing code will use this data to
298 // map this memory into the SEC process memory space.
305 // Save the size of the memory.
307 while (MemorySizeStr
[Index1
] >= '0' && MemorySizeStr
[Index1
] <= '9') {
308 val
= val
* 10 + MemorySizeStr
[Index1
] - '0';
311 gSystemMemory
[Index
++].Size
= val
* 0x100000;
312 if (MemorySizeStr
[Index1
] == 0)
320 // Hand off to PEI Core
322 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
325 // If we get here, then the PEI Core returned. This is an error as PEI should
326 // always hand off to DXE.
328 printf ("ERROR : PEI Core returned\n");
332 EFI_PHYSICAL_ADDRESS
*
339 STATIC UINTN base
= 0x40000000;
340 CONST UINTN align
= (1 << 24);
342 BOOLEAN isAligned
= 0;
345 // Try to get an aligned block somewhere in the address space of this
348 while((!isAligned
) && (base
!= 0)) {
349 res
= mmap ((void *)base
, length
, prot
, flags
, fd
, 0);
350 if (res
== MAP_FAILED
) {
353 if ((((UINTN
)res
) & ~(align
-1)) == (UINTN
)res
) {
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 a 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
398 fd
= open (FileName
, O_RDONLY
);
400 return EFI_NOT_FOUND
;
401 FileSize
= lseek (fd
, 0, SEEK_END
);
406 /* Read entry address. */
407 lseek (fd
, FileSize
- 0x20, SEEK_SET
);
408 if (read (fd
, &EntryAddress
, 4) != 4)
411 return EFI_DEVICE_ERROR
;
416 res
= MapMemory(fd
, FileSize
, PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_PRIVATE
);
420 if (res
== MAP_FAILED
)
421 return EFI_DEVICE_ERROR
;
423 *Length
= (UINT64
) FileSize
;
424 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
429 #define BYTES_PER_RECORD 512
433 SecPeiReportStatusCode (
434 IN EFI_PEI_SERVICES
**PeiServices
,
435 IN EFI_STATUS_CODE_TYPE CodeType
,
436 IN EFI_STATUS_CODE_VALUE Value
,
438 IN EFI_GUID
* CallerId
,
439 IN EFI_STATUS_CODE_DATA
* Data OPTIONAL
445 This routine produces the ReportStatusCode PEI service. It's passed
446 up to the PEI Core via a PPI. T
448 This code currently uses the UNIX clib printf. This does not work the same way
449 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
452 (see EFI_PEI_REPORT_STATUS_CODE)
455 EFI_SUCCESS - Always return success
458 // TODO: PeiServices - add argument and description to function comment
459 // TODO: CodeType - add argument and description to function comment
460 // TODO: Value - add argument and description to function comment
461 // TODO: Instance - add argument and description to function comment
462 // TODO: CallerId - add argument and description to function comment
463 // TODO: Data - add argument and description to function comment
467 CHAR8 PrintBuffer
[BYTES_PER_RECORD
* 2];
475 } else if (ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
477 // Processes ASSERT ()
479 printf ("ASSERT %s(%d): %s\n", Filename
, LineNumber
, Description
);
481 } else if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
483 // Process DEBUG () macro
485 AsciiVSPrint (PrintBuffer
, BYTES_PER_RECORD
, Format
, Marker
);
486 printf (PrintBuffer
);
493 Transfers control to a function starting with a new stack.
495 Transfers control to the function specified by EntryPoint using the new stack
496 specified by NewStack and passing in the parameters specified by Context1 and
497 Context2. Context1 and Context2 are optional and may be NULL. The function
498 EntryPoint must never return.
500 If EntryPoint is NULL, then ASSERT().
501 If NewStack is NULL, then ASSERT().
503 @param EntryPoint A pointer to function to call with the new stack.
504 @param Context1 A pointer to the context to pass into the EntryPoint
506 @param Context2 A pointer to the context to pass into the EntryPoint
508 @param NewStack A pointer to the new stack to use for the EntryPoint
510 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
511 Reserved on other architectures.
517 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
518 IN VOID
*Context1
, OPTIONAL
519 IN VOID
*Context2
, OPTIONAL
520 IN VOID
*Context3
, OPTIONAL
524 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
526 ASSERT (EntryPoint
!= NULL
);
527 ASSERT (NewStack
!= NULL
);
530 // Stack should be aligned with CPU_STACK_ALIGNMENT
532 ASSERT (((UINTN
)NewStack
& (CPU_STACK_ALIGNMENT
- 1)) == 0);
534 JumpBuffer
.Eip
= (UINTN
)EntryPoint
;
535 JumpBuffer
.Esp
= (UINTN
)NewStack
- sizeof (VOID
*);
536 JumpBuffer
.Esp
-= sizeof (Context1
) + sizeof (Context2
) + sizeof(Context3
);
537 ((VOID
**)JumpBuffer
.Esp
)[1] = Context1
;
538 ((VOID
**)JumpBuffer
.Esp
)[2] = Context2
;
539 ((VOID
**)JumpBuffer
.Esp
)[3] = Context3
;
541 LongJump (&JumpBuffer
, (UINTN
)-1);
545 // InternalSwitchStack () will never return
552 IN UINTN LargestRegion
,
553 IN UINTN LargestRegionSize
,
554 IN UINTN BootFirmwareVolumeBase
,
555 IN VOID
*PeiCorePe32File
560 This is the service to load the PEI Core from the Firmware Volume
563 LargestRegion - Memory to use for PEI.
564 LargestRegionSize - Size of Memory to use for PEI
565 BootFirmwareVolumeBase - Start of the Boot FV
566 PeiCorePe32File - PEI Core PE32
569 Success means control is transfered and thus we should never return
574 EFI_PHYSICAL_ADDRESS TopOfMemory
;
577 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
578 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
579 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
583 // Compute Top Of Memory for Stack and PEI Core Allocations
585 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
586 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
589 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
592 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
595 // |-----------| <---- TemporaryRamBase
597 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
598 TopOfMemory
= LargestRegion
+ PeiStackSize
;
601 // Reservet space for storing PeiCore's parament in stack.
603 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
604 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
607 // Patch value in dispatch table values
609 gPrivateDispatchTable
[0].Ppi
= gPeiEfiPeiPeCoffLoader
;
612 // Bind this information into the SEC hand-off state
614 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
615 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
616 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
617 SecCoreData
->BootFirmwareVolumeSize
= FixedPcdGet32(PcdUnixFirmwareFdSize
);
618 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
619 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
620 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
621 SecCoreData
->StackSize
= PeiStackSize
;
622 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
623 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
626 // Load the PEI Core from a Firmware Volume
628 Status
= SecWinNtPeiLoadFile (
634 if (EFI_ERROR (Status
)) {
639 // Transfer control to the PEI Core
642 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
644 (VOID
*) (UINTN
) ((EFI_PEI_PPI_DESCRIPTOR
*) &gPrivateDispatchTable
),
649 // If we get here, then the PEI Core returned. This is an error
656 SecWinNtPeiAutoScan (
658 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
659 OUT UINT64
*MemorySize
664 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
665 It allows discontiguous memory regions to be supported by the emulator.
666 It uses gSystemMemory[] and gSystemMemoryCount that were created by
667 parsing the host environment variable EFI_MEMORY_SIZE.
668 The size comes from the varaible and the address comes from the call to
672 Index - Which memory region to use
673 MemoryBase - Return Base address of memory region
674 MemorySize - Return size in bytes of the memory region
677 EFI_SUCCESS - If memory region was mapped
678 EFI_UNSUPPORTED - If Index is not supported
684 if (Index
>= gSystemMemoryCount
) {
685 return EFI_UNSUPPORTED
;
689 res
= MapMemory(0, gSystemMemory
[Index
].Size
,
690 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
691 MAP_PRIVATE
| MAP_ANONYMOUS
);
692 if (res
== MAP_FAILED
)
693 return EFI_DEVICE_ERROR
;
694 *MemorySize
= gSystemMemory
[Index
].Size
;
695 *MemoryBase
= (UINTN
)res
;
696 gSystemMemory
[Index
].Memory
= *MemoryBase
;
703 SecWinNtWinNtThunkAddress (
709 Since the SEC is the only Unix program in stack it must export
710 an interface to do Win API calls. That's what the WinNtThunk address
711 is for. gWinNt is initailized in WinNtThunk.c.
714 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
715 InterfaceBase - Address of the gWinNt global
718 EFI_SUCCESS - Data returned
728 SecWinNtPeiLoadFile (
730 IN EFI_PHYSICAL_ADDRESS
*ImageAddress
,
731 IN UINT64
*ImageSize
,
732 IN EFI_PHYSICAL_ADDRESS
*EntryPoint
737 Loads and relocates a PE/COFF image into memory.
740 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
741 ImageAddress - The base address of the relocated PE/COFF image
742 ImageSize - The size of the relocated PE/COFF image
743 EntryPoint - The entry point of the relocated PE/COFF image
746 EFI_SUCCESS - The file was loaded and relocated
747 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
752 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
754 ZeroMem (&ImageContext
, sizeof (ImageContext
));
755 ImageContext
.Handle
= Pe32Data
;
757 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
759 Status
= gPeiEfiPeiPeCoffLoader
->GetImageInfo (gPeiEfiPeiPeCoffLoader
, &ImageContext
);
760 if (EFI_ERROR (Status
)) {
764 // Allocate space in UNIX (not emulator) memory. Extra space is for alignment
766 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) malloc ((UINTN
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)));
767 if (ImageContext
.ImageAddress
== 0) {
768 return EFI_OUT_OF_RESOURCES
;
771 // Align buffer on section boundry
773 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
;
774 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
777 Status
= gPeiEfiPeiPeCoffLoader
->LoadImage (gPeiEfiPeiPeCoffLoader
, &ImageContext
);
778 if (EFI_ERROR (Status
)) {
782 Status
= gPeiEfiPeiPeCoffLoader
->RelocateImage (gPeiEfiPeiPeCoffLoader
, &ImageContext
);
783 if (EFI_ERROR (Status
)) {
788 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
791 *ImageAddress
= ImageContext
.ImageAddress
;
792 *ImageSize
= ImageContext
.ImageSize
;
793 *EntryPoint
= ImageContext
.EntryPoint
;
802 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
803 IN OUT UINT64
*FdSize
808 Return the FD Size and base address. Since the FD is loaded from a
809 file into host memory only the SEC will know it's address.
812 Index - Which FD, starts at zero.
813 FdSize - Size of the FD in bytes
814 FdBase - Start address of the FD. Assume it points to an FV Header
817 EFI_SUCCESS - Return the Base address and size of the FV
818 EFI_UNSUPPORTED - Index does nto map to an FD in the system
822 if (Index
>= gFdInfoCount
) {
823 return EFI_UNSUPPORTED
;
826 *FdBase
= gFdInfo
[Index
].Address
;
827 *FdSize
= gFdInfo
[Index
].Size
;
829 if (*FdBase
== 0 && *FdSize
== 0) {
830 return EFI_UNSUPPORTED
;
841 IN OUT UINTN
*ReadSize
,
847 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
850 FileHandle - The handle to the PE/COFF file
851 FileOffset - The offset, in bytes, into the file to read
852 ReadSize - The number of bytes to read from the file starting at FileOffset
853 Buffer - A pointer to the buffer to read the data into.
856 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
864 Destination8
= Buffer
;
865 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
868 *(Destination8
++) = *(Source8
++);
875 CountSeperatorsInString (
876 IN
const CHAR16
*String
,
882 Count the number of seperators in String
885 String - String to process
886 Seperator - Item to count
889 Number of Seperator in String
895 for (Count
= 0; *String
!= '\0'; String
++) {
896 if (*String
== Seperator
) {
908 SecNt32PeCoffGetImageInfo (
909 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
910 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
915 Status
= PeCoffLoaderGetImageInfo (ImageContext
);
916 if (EFI_ERROR (Status
)) {
920 switch (ImageContext
->ImageType
) {
922 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
923 ImageContext
->ImageCodeMemoryType
= EfiLoaderCode
;
924 ImageContext
->ImageDataMemoryType
= EfiLoaderData
;
927 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
928 ImageContext
->ImageCodeMemoryType
= EfiBootServicesCode
;
929 ImageContext
->ImageDataMemoryType
= EfiBootServicesData
;
932 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
933 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
934 ImageContext
->ImageCodeMemoryType
= EfiRuntimeServicesCode
;
935 ImageContext
->ImageDataMemoryType
= EfiRuntimeServicesData
;
939 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
940 return RETURN_UNSUPPORTED
;
948 SecNt32PeCoffLoadImage (
949 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
950 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
955 Status
= PeCoffLoaderLoadImage (ImageContext
);
968 SecNt32PeCoffRelocateImage (
969 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
970 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
979 Status
= PeCoffLoaderRelocateImage (ImageContext
);
981 "Loading %s 0x%08lx - entry point 0x%08lx\n",
982 ImageContext
->PdbPointer
,
983 (unsigned long)ImageContext
->ImageAddress
,
984 (unsigned long)ImageContext
->EntryPoint
);
986 Handle
= dlopen(ImageContext
->PdbPointer
, RTLD_NOW
);
989 Entry
= dlsym(Handle
, "_ModuleEntryPoint");
991 printf("%s\n", dlerror());
995 ImageContext
->EntryPoint
= Entry
;
996 printf("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, Entry
);
998 printf("Could not find _ModuleEntryPoint Entry, Module may be built error\n");
1001 SecUnixLoaderBreak ();
1009 SecNt32PeCoffUnloadimage (
1010 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
1011 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1026 SecTemporaryRamSupport (
1027 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1028 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1029 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1034 // Migrate the whole temporary memory to permenent memory.
1037 (VOID
*)(UINTN
)PermanentMemoryBase
,
1038 (VOID
*)(UINTN
)TemporaryMemoryBase
,
1043 // SecSwitchStack function must be invoked after the memory migration
1044 // immediatly, also we need fixup the stack change caused by new call into
1045 // permenent memory.
1048 (UINT32
) TemporaryMemoryBase
,
1049 (UINT32
) PermanentMemoryBase
1053 // We need *not* fix the return address because currently,
1054 // The PeiCore is excuted in flash.
1058 // Simulate to invalid CAR, terminate CAR
1060 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);