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
136 EFI_PHYSICAL_ADDRESS
*
146 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
161 Main entry point to SEC for WinNt. This is a unix program
164 Argc - Number of command line arguments
165 Argv - Array of command line argument strings
166 Envp - Array of environmemt variable strings
175 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
176 UINT64 InitialStackMemorySize
;
184 CHAR16
*MemorySizeStr
;
185 CHAR16
*FirmwareVolumesStr
;
191 MemorySizeStr
= (CHAR16
*) FixedPcdGetPtr (PcdUnixMemorySizeForSecMain
);
192 FirmwareVolumesStr
= (CHAR16
*) FixedPcdGetPtr (PcdUnixFirmwareVolume
);
194 printf ("\nEDK SEC Main UNIX Emulation Environment from www.TianoCore.org\n");
197 // Allocate space for gSystemMemory Array
199 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
200 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (UNIX_SYSTEM_MEMORY
));
201 if (gSystemMemory
== NULL
) {
202 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
206 // Allocate space for gSystemMemory Array
208 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
209 gFdInfo
= calloc (gFdInfoCount
, sizeof (UNIX_FD_INFO
));
210 if (gFdInfo
== NULL
) {
211 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
215 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)
217 printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdUnixBootMode
));
220 // Open up a 128K file to emulate temp memory for PEI.
221 // on a real platform this would be SRAM, or using the cache as RAM.
222 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping
224 InitialStackMemorySize
= STACK_SIZE
;
225 InitialStackMemory
= (UINTN
)MapMemory(0,
226 (UINT32
) InitialStackMemorySize
,
227 PROT_READ
| PROT_WRITE
,
228 MAP_ANONYMOUS
| MAP_PRIVATE
);
229 if (InitialStackMemory
== 0) {
230 printf ("ERROR : Can not open SecStack Exiting\n");
234 printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n",
235 (UINTN
)(InitialStackMemorySize
/ 1024),
236 (unsigned long)InitialStackMemory
);
238 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
239 StackPointer
< (UINTN
*) ((UINTN
) InitialStackMemory
+ (UINT64
) InitialStackMemorySize
);
241 *StackPointer
= 0x5AA55AA5;
245 // Open All the firmware volumes and remember the info in the gFdInfo global
247 FileName
= (CHAR8
*)malloc (StrLen (FirmwareVolumesStr
) + 1);
248 if (FileName
== NULL
) {
249 printf ("ERROR : Can not allocate memory for firmware volume string\n");
254 for (Done
= FALSE
, Index
= 0, PeiIndex
= 0, PeiCoreFile
= NULL
;
255 FirmwareVolumesStr
[Index2
] != 0;
257 for (Index1
= 0; (FirmwareVolumesStr
[Index2
] != '!') && (FirmwareVolumesStr
[Index2
] != 0); Index2
++)
258 FileName
[Index1
++] = FirmwareVolumesStr
[Index2
];
259 if (FirmwareVolumesStr
[Index2
] == '!')
261 FileName
[Index1
] = '\0';
264 // Open the FD and remmeber where it got mapped into our processes address space
268 &gFdInfo
[Index
].Address
,
271 if (EFI_ERROR (Status
)) {
272 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName
, Status
);
276 printf (" FD loaded from %s at 0x%08lx",
277 FileName
, (unsigned long)gFdInfo
[Index
].Address
);
279 if (PeiCoreFile
== NULL
) {
281 // Assume the beginning of the FD is an FV and look for the PEI Core.
282 // Load the first one we find.
284 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
285 if (!EFI_ERROR (Status
)) {
287 printf (" contains SEC Core");
294 // Calculate memory regions and store the information in the gSystemMemory
295 // global for later use. The autosizing code will use this data to
296 // map this memory into the SEC process memory space.
303 // Save the size of the memory.
305 while (MemorySizeStr
[Index1
] >= '0' && MemorySizeStr
[Index1
] <= '9') {
306 val
= val
* 10 + MemorySizeStr
[Index1
] - '0';
309 gSystemMemory
[Index
++].Size
= val
* 0x100000;
310 if (MemorySizeStr
[Index1
] == 0)
318 // Hand off to PEI Core
320 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
323 // If we get here, then the PEI Core returned. This is an error as PEI should
324 // always hand off to DXE.
326 printf ("ERROR : PEI Core returned\n");
330 EFI_PHYSICAL_ADDRESS
*
337 STATIC UINTN base
= 0x40000000;
338 CONST UINTN align
= (1 << 24);
340 BOOLEAN isAligned
= 0;
343 // Try to get an aligned block somewhere in the address space of this
346 while((!isAligned
) && (base
!= 0)) {
347 res
= mmap ((void *)base
, length
, prot
, flags
, fd
, 0);
348 if (res
== MAP_FAILED
) {
351 if ((((UINTN
)res
) & ~(align
-1)) == (UINTN
)res
) {
365 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
371 Opens and memory maps a file using WinNt services. If BaseAddress is non zero
372 the process will try and allocate the memory starting at BaseAddress.
375 FileName - The name of the file to open and map
376 MapSize - The amount of the file to map in bytes
377 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
378 memory emulation, and exiting files for firmware volume emulation
379 BaseAddress - The base address of the mapped file in the user address space.
380 If passed in as NULL the a new memory region is used.
381 If passed in as non NULL the request memory region is used for
382 the mapping of the file into the process space.
383 Length - The size of the mapped region in bytes
386 EFI_SUCCESS - The file was opened and mapped.
387 EFI_NOT_FOUND - FileName was not found in the current directory
388 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
396 fd
= open (FileName
, O_RDONLY
);
398 return EFI_NOT_FOUND
;
399 FileSize
= lseek (fd
, 0, SEEK_END
);
404 /* Read entry address. */
405 lseek (fd
, FileSize
- 0x20, SEEK_SET
);
406 if (read (fd
, &EntryAddress
, 4) != 4)
409 return EFI_DEVICE_ERROR
;
414 res
= MapMemory(fd
, FileSize
, PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_PRIVATE
);
418 if (res
== MAP_FAILED
)
419 return EFI_DEVICE_ERROR
;
421 *Length
= (UINT64
) FileSize
;
422 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
427 #define BYTES_PER_RECORD 512
431 SecPeiReportStatusCode (
432 IN EFI_PEI_SERVICES
**PeiServices
,
433 IN EFI_STATUS_CODE_TYPE CodeType
,
434 IN EFI_STATUS_CODE_VALUE Value
,
436 IN EFI_GUID
* CallerId
,
437 IN EFI_STATUS_CODE_DATA
* Data OPTIONAL
443 This routine produces the ReportStatusCode PEI service. It's passed
444 up to the PEI Core via a PPI. T
446 This code currently uses the UNIX clib printf. This does not work the same way
447 as the EFI Print (), as %t, %g, %s as Unicode are not supported.
450 (see EFI_PEI_REPORT_STATUS_CODE)
453 EFI_SUCCESS - Always return success
456 // TODO: PeiServices - add argument and description to function comment
457 // TODO: CodeType - add argument and description to function comment
458 // TODO: Value - add argument and description to function comment
459 // TODO: Instance - add argument and description to function comment
460 // TODO: CallerId - add argument and description to function comment
461 // TODO: Data - add argument and description to function comment
465 CHAR8 PrintBuffer
[BYTES_PER_RECORD
* 2];
473 } else if (ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
475 // Processes ASSERT ()
477 printf ("ASSERT %s(%d): %s\n", Filename
, LineNumber
, Description
);
479 } else if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
481 // Process DEBUG () macro
483 AsciiVSPrint (PrintBuffer
, BYTES_PER_RECORD
, Format
, Marker
);
484 printf (PrintBuffer
);
491 Transfers control to a function starting with a new stack.
493 Transfers control to the function specified by EntryPoint using the new stack
494 specified by NewStack and passing in the parameters specified by Context1 and
495 Context2. Context1 and Context2 are optional and may be NULL. The function
496 EntryPoint must never return.
498 If EntryPoint is NULL, then ASSERT().
499 If NewStack is NULL, then ASSERT().
501 @param EntryPoint A pointer to function to call with the new stack.
502 @param Context1 A pointer to the context to pass into the EntryPoint
504 @param Context2 A pointer to the context to pass into the EntryPoint
506 @param NewStack A pointer to the new stack to use for the EntryPoint
508 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's
509 Reserved on other architectures.
515 IN SWITCH_STACK_ENTRY_POINT EntryPoint
,
516 IN VOID
*Context1
, OPTIONAL
517 IN VOID
*Context2
, OPTIONAL
518 IN VOID
*Context3
, OPTIONAL
522 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
524 ASSERT (EntryPoint
!= NULL
);
525 ASSERT (NewStack
!= NULL
);
528 // Stack should be aligned with CPU_STACK_ALIGNMENT
530 ASSERT (((UINTN
)NewStack
& (CPU_STACK_ALIGNMENT
- 1)) == 0);
532 JumpBuffer
.Eip
= (UINTN
)EntryPoint
;
533 JumpBuffer
.Esp
= (UINTN
)NewStack
- sizeof (VOID
*);
534 JumpBuffer
.Esp
-= sizeof (Context1
) + sizeof (Context2
) + sizeof(Context3
);
535 ((VOID
**)JumpBuffer
.Esp
)[1] = Context1
;
536 ((VOID
**)JumpBuffer
.Esp
)[2] = Context2
;
537 ((VOID
**)JumpBuffer
.Esp
)[3] = Context3
;
539 LongJump (&JumpBuffer
, (UINTN
)-1);
543 // InternalSwitchStack () will never return
550 IN UINTN LargestRegion
,
551 IN UINTN LargestRegionSize
,
552 IN UINTN BootFirmwareVolumeBase
,
553 IN VOID
*PeiCorePe32File
558 This is the service to load the PEI Core from the Firmware Volume
561 LargestRegion - Memory to use for PEI.
562 LargestRegionSize - Size of Memory to use for PEI
563 BootFirmwareVolumeBase - Start of the Boot FV
564 PeiCorePe32File - PEI Core PE32
567 Success means control is transfered and thus we should never return
572 EFI_PHYSICAL_ADDRESS TopOfMemory
;
575 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
576 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
577 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
581 // Compute Top Of Memory for Stack and PEI Core Allocations
583 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
584 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
587 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
590 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
593 // |-----------| <---- TemporaryRamBase
595 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
596 TopOfMemory
= LargestRegion
+ PeiStackSize
;
599 // Reservet space for storing PeiCore's parament in stack.
601 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
602 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
605 // Patch value in dispatch table values
607 gPrivateDispatchTable
[0].Ppi
= gPeiEfiPeiPeCoffLoader
;
610 // Bind this information into the SEC hand-off state
612 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
613 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
614 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
615 SecCoreData
->BootFirmwareVolumeSize
= FixedPcdGet32(PcdUnixFirmwareFdSize
);
616 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
617 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
618 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
619 SecCoreData
->StackSize
= PeiStackSize
;
620 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
621 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
624 // Load the PEI Core from a Firmware Volume
626 Status
= SecWinNtPeiLoadFile (
632 if (EFI_ERROR (Status
)) {
637 // Transfer control to the PEI Core
640 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
642 (VOID
*) (UINTN
) ((EFI_PEI_PPI_DESCRIPTOR
*) &gPrivateDispatchTable
),
647 // If we get here, then the PEI Core returned. This is an error
654 SecWinNtPeiAutoScan (
656 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
657 OUT UINT64
*MemorySize
662 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
663 It allows discontiguous memory regions to be supported by the emulator.
664 It uses gSystemMemory[] and gSystemMemoryCount that were created by
665 parsing the host environment variable EFI_MEMORY_SIZE.
666 The size comes from the varaible and the address comes from the call to
670 Index - Which memory region to use
671 MemoryBase - Return Base address of memory region
672 MemorySize - Return size in bytes of the memory region
675 EFI_SUCCESS - If memory region was mapped
676 EFI_UNSUPPORTED - If Index is not supported
682 if (Index
>= gSystemMemoryCount
) {
683 return EFI_UNSUPPORTED
;
687 res
= MapMemory(0, gSystemMemory
[Index
].Size
,
688 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
689 MAP_PRIVATE
| MAP_ANONYMOUS
);
690 if (res
== MAP_FAILED
)
691 return EFI_DEVICE_ERROR
;
692 *MemorySize
= gSystemMemory
[Index
].Size
;
693 *MemoryBase
= (UINTN
)res
;
694 gSystemMemory
[Index
].Memory
= *MemoryBase
;
701 SecWinNtWinNtThunkAddress (
707 Since the SEC is the only Unix program in stack it must export
708 an interface to do Win API calls. That's what the WinNtThunk address
709 is for. gWinNt is initailized in WinNtThunk.c.
712 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
713 InterfaceBase - Address of the gWinNt global
716 EFI_SUCCESS - Data returned
726 SecWinNtPeiLoadFile (
728 IN EFI_PHYSICAL_ADDRESS
*ImageAddress
,
729 IN UINT64
*ImageSize
,
730 IN EFI_PHYSICAL_ADDRESS
*EntryPoint
735 Loads and relocates a PE/COFF image into memory.
738 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
739 ImageAddress - The base address of the relocated PE/COFF image
740 ImageSize - The size of the relocated PE/COFF image
741 EntryPoint - The entry point of the relocated PE/COFF image
744 EFI_SUCCESS - The file was loaded and relocated
745 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
750 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
752 ZeroMem (&ImageContext
, sizeof (ImageContext
));
753 ImageContext
.Handle
= Pe32Data
;
755 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
757 Status
= gPeiEfiPeiPeCoffLoader
->GetImageInfo (gPeiEfiPeiPeCoffLoader
, &ImageContext
);
758 if (EFI_ERROR (Status
)) {
762 // Allocate space in UNIX (not emulator) memory. Extra space is for alignment
764 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) malloc ((UINTN
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)));
765 if (ImageContext
.ImageAddress
== 0) {
766 return EFI_OUT_OF_RESOURCES
;
769 // Align buffer on section boundry
771 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
;
772 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
775 Status
= gPeiEfiPeiPeCoffLoader
->LoadImage (gPeiEfiPeiPeCoffLoader
, &ImageContext
);
776 if (EFI_ERROR (Status
)) {
780 Status
= gPeiEfiPeiPeCoffLoader
->RelocateImage (gPeiEfiPeiPeCoffLoader
, &ImageContext
);
781 if (EFI_ERROR (Status
)) {
786 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
789 *ImageAddress
= ImageContext
.ImageAddress
;
790 *ImageSize
= ImageContext
.ImageSize
;
791 *EntryPoint
= ImageContext
.EntryPoint
;
800 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
801 IN OUT UINT64
*FdSize
806 Return the FD Size and base address. Since the FD is loaded from a
807 file into host memory only the SEC will know it's address.
810 Index - Which FD, starts at zero.
811 FdSize - Size of the FD in bytes
812 FdBase - Start address of the FD. Assume it points to an FV Header
815 EFI_SUCCESS - Return the Base address and size of the FV
816 EFI_UNSUPPORTED - Index does nto map to an FD in the system
820 if (Index
>= gFdInfoCount
) {
821 return EFI_UNSUPPORTED
;
824 *FdBase
= gFdInfo
[Index
].Address
;
825 *FdSize
= gFdInfo
[Index
].Size
;
827 if (*FdBase
== 0 && *FdSize
== 0) {
828 return EFI_UNSUPPORTED
;
839 IN OUT UINTN
*ReadSize
,
845 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
848 FileHandle - The handle to the PE/COFF file
849 FileOffset - The offset, in bytes, into the file to read
850 ReadSize - The number of bytes to read from the file starting at FileOffset
851 Buffer - A pointer to the buffer to read the data into.
854 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
862 Destination8
= Buffer
;
863 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
866 *(Destination8
++) = *(Source8
++);
873 CountSeperatorsInString (
874 IN
const CHAR16
*String
,
880 Count the number of seperators in String
883 String - String to process
884 Seperator - Item to count
887 Number of Seperator in String
893 for (Count
= 0; *String
!= '\0'; String
++) {
894 if (*String
== Seperator
) {
906 SecNt32PeCoffGetImageInfo (
907 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
908 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
913 Status
= PeCoffLoaderGetImageInfo (ImageContext
);
914 if (EFI_ERROR (Status
)) {
918 switch (ImageContext
->ImageType
) {
920 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
:
921 ImageContext
->ImageCodeMemoryType
= EfiLoaderCode
;
922 ImageContext
->ImageDataMemoryType
= EfiLoaderData
;
925 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
:
926 ImageContext
->ImageCodeMemoryType
= EfiBootServicesCode
;
927 ImageContext
->ImageDataMemoryType
= EfiBootServicesData
;
930 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
:
931 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
:
932 ImageContext
->ImageCodeMemoryType
= EfiRuntimeServicesCode
;
933 ImageContext
->ImageDataMemoryType
= EfiRuntimeServicesData
;
937 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
938 return RETURN_UNSUPPORTED
;
946 SecNt32PeCoffLoadImage (
947 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
948 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
953 Status
= PeCoffLoaderLoadImage (ImageContext
);
966 SecNt32PeCoffRelocateImage (
967 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
968 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
977 Status
= PeCoffLoaderRelocateImage (ImageContext
);
979 "Loading %s 0x%08lx - entry point 0x%08lx\n",
980 ImageContext
->PdbPointer
,
981 (unsigned long)ImageContext
->ImageAddress
,
982 (unsigned long)ImageContext
->EntryPoint
);
984 Handle
= dlopen(ImageContext
->PdbPointer
, RTLD_NOW
);
987 Entry
= dlsym(Handle
, "_ModuleEntryPoint");
989 printf("%s\n", dlerror());
993 ImageContext
->EntryPoint
= Entry
;
994 printf("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, Entry
);
997 SecUnixLoaderBreak ();
1005 SecNt32PeCoffUnloadimage (
1006 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*This
,
1007 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1022 SecTemporaryRamSupport (
1023 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1024 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1025 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1030 // Migrate the whole temporary memory to permenent memory.
1033 (VOID
*)(UINTN
)PermanentMemoryBase
,
1034 (VOID
*)(UINTN
)TemporaryMemoryBase
,
1039 // SecSwitchStack function must be invoked after the memory migration
1040 // immediatly, also we need fixup the stack change caused by new call into
1041 // permenent memory.
1044 (UINT32
) TemporaryMemoryBase
,
1045 (UINT32
) PermanentMemoryBase
1049 // We need *not* fix the return address because currently,
1050 // The PeiCore is excuted in flash.
1054 // Simulate to invalid CAR, terminate CAR
1056 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);