2 Implementation for S3 Boot Script Save thunk driver.
3 This thunk driver consumes PI S3SaveState protocol to produce framework S3BootScriptSave Protocol
5 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "ScriptSave.h"
18 EFI_BOOT_SCRIPT_SAVE_PROTOCOL mS3ScriptSave
= {
22 EFI_S3_SAVE_STATE_PROTOCOL
*mS3SaveState
;
25 Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
28 @param Function The 32bit code entry to be executed.
29 @param Param1 The first parameter to pass to 32bit code
30 @param Param2 The second parameter to pass to 32bit code
31 @retval EFI_SUCCESS Execute 32bit code successfully.
32 @retval other Something wrong when execute the 32bit code
43 A stub to convert framework boot script dispatch to PI boot script dispatch.
45 @param ImageHandle It should be is NULL.
46 @param Context The first parameter to pass to 32bit code
48 @return dispatch value.
53 FrameworkBootScriptDispatchStub (
54 IN EFI_HANDLE ImageHandle
,
59 DISPATCH_ENTRYPOINT_FUNC EntryFunc
;
63 DEBUG ((EFI_D_ERROR
, "FrameworkBootScriptDispatchStub - 0x%08x\n", (UINTN
)Context
));
65 EntryFunc
= (DISPATCH_ENTRYPOINT_FUNC
) (UINTN
) (Context
);
67 PeiServices
= (VOID
*)(UINTN
)(*(UINT32
*)(Idtr
.Base
- sizeof (UINT32
)));
70 // ECP assumes first parameter is NULL, and second parameter is PeiServices.
72 Status
= Execute32BitCode ((UINT64
)(UINTN
)EntryFunc
, 0, (UINT64
)(UINTN
)PeiServices
);
78 Internal function to add IO write opcode to the table.
80 @param Marker The variable argument list to get the opcode
81 and associated attributes.
83 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
84 @retval EFI_SUCCESS Opcode is added.
92 EFI_BOOT_SCRIPT_WIDTH Width
;
97 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
98 Address
= VA_ARG (Marker
, UINT64
);
99 Count
= VA_ARG (Marker
, UINTN
);
100 Buffer
= VA_ARG (Marker
, UINT8
*);
102 return mS3SaveState
->Write (
104 EFI_BOOT_SCRIPT_IO_WRITE_OPCODE
,
112 Internal function to add IO read/write opcode to the table.
114 @param Marker The variable argument list to get the opcode
115 and associated attributes.
117 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
118 @retval EFI_SUCCESS Opcode is added.
122 BootScriptIoReadWrite (
126 EFI_BOOT_SCRIPT_WIDTH Width
;
131 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
132 Address
= VA_ARG (Marker
, UINT64
);
133 Data
= VA_ARG (Marker
, UINT8
*);
134 DataMask
= VA_ARG (Marker
, UINT8
*);
136 return mS3SaveState
->Write (
138 EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE
,
147 Internal function to add memory write opcode to the table.
149 @param Marker The variable argument list to get the opcode
150 and associated attributes.
152 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
153 @retval EFI_SUCCESS Opcode is added.
161 EFI_BOOT_SCRIPT_WIDTH Width
;
166 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
167 Address
= VA_ARG (Marker
, UINT64
);
168 Count
= VA_ARG (Marker
, UINTN
);
169 Buffer
= VA_ARG (Marker
, UINT8
*);
171 return mS3SaveState
->Write (
173 EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE
,
182 Internal function to add memory read/write opcode to the table.
184 @param Marker The variable argument list to get the opcode
185 and associated attributes.
187 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
188 @retval EFI_SUCCESS Opcode is added.
192 BootScriptMemReadWrite (
196 EFI_BOOT_SCRIPT_WIDTH Width
;
201 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
202 Address
= VA_ARG (Marker
, UINT64
);
203 Data
= VA_ARG (Marker
, UINT8
*);
204 DataMask
= VA_ARG (Marker
, UINT8
*);
206 return mS3SaveState
->Write (
208 EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE
,
217 Internal function to add PciCfg write opcode to the table.
219 @param Marker The variable argument list to get the opcode
220 and associated attributes.
222 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
223 @retval EFI_SUCCESS Opcode is added.
227 BootScriptPciCfgWrite (
231 EFI_BOOT_SCRIPT_WIDTH Width
;
236 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
237 Address
= VA_ARG (Marker
, UINT64
);
238 Count
= VA_ARG (Marker
, UINTN
);
239 Buffer
= VA_ARG (Marker
, UINT8
*);
241 return mS3SaveState
->Write (
243 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE
,
252 Internal function to PciCfg read/write opcode to the table.
254 @param Marker The variable argument list to get the opcode
255 and associated attributes.
257 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
258 @retval EFI_SUCCESS Opcode is added.
262 BootScriptPciCfgReadWrite (
266 EFI_BOOT_SCRIPT_WIDTH Width
;
271 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
272 Address
= VA_ARG (Marker
, UINT64
);
273 Data
= VA_ARG (Marker
, UINT8
*);
274 DataMask
= VA_ARG (Marker
, UINT8
*);
276 return mS3SaveState
->Write (
278 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE
,
286 Internal function to add PciCfg2 write opcode to the table.
288 @param Marker The variable argument list to get the opcode
289 and associated attributes.
291 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
292 @retval EFI_SUCCESS Opcode is added.
296 BootScriptPciCfg2Write (
300 EFI_BOOT_SCRIPT_WIDTH Width
;
306 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
307 Address
= VA_ARG (Marker
, UINT64
);
308 Count
= VA_ARG (Marker
, UINTN
);
309 Buffer
= VA_ARG (Marker
, UINT8
*);
310 Segment
= VA_ARG (Marker
, UINT16
);
312 return mS3SaveState
->Write (
314 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
,
324 Internal function to PciCfg2 read/write opcode to the table.
326 @param Marker The variable argument list to get the opcode
327 and associated attributes.
329 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
330 @retval EFI_SUCCESS Opcode is added.
334 BootScriptPciCfg2ReadWrite (
338 EFI_BOOT_SCRIPT_WIDTH Width
;
344 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
345 Address
= VA_ARG (Marker
, UINT64
);
346 Segment
= VA_ARG (Marker
, UINT16
);
347 Data
= VA_ARG (Marker
, UINT8
*);
348 DataMask
= VA_ARG (Marker
, UINT8
*);
350 return mS3SaveState
->Write (
352 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE
,
361 Internal function to add smbus excute opcode to the table.
363 @param Marker The variable argument list to get the opcode
364 and associated attributes.
366 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
367 @retval EFI_SUCCESS Opcode is added.
371 BootScriptSmbusExecute (
375 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress
;
376 EFI_SMBUS_DEVICE_COMMAND Command
;
377 EFI_SMBUS_OPERATION Operation
;
382 SlaveAddress
.SmbusDeviceAddress
= VA_ARG (Marker
, UINTN
);
383 Command
= VA_ARG (Marker
, EFI_SMBUS_DEVICE_COMMAND
);
384 Operation
= VA_ARG (Marker
, EFI_SMBUS_OPERATION
);
385 PecCheck
= VA_ARG (Marker
, BOOLEAN
);
386 DataSize
= VA_ARG (Marker
, UINTN
*);
387 Buffer
= VA_ARG (Marker
, VOID
*);
389 return mS3SaveState
->Write (
391 EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE
,
401 Internal function to add stall opcode to the table.
403 @param Marker The variable argument list to get the opcode
404 and associated attributes.
406 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
407 @retval EFI_SUCCESS Opcode is added.
417 Duration
= VA_ARG (Marker
, UINT32
);
419 return mS3SaveState
->Write (
421 EFI_BOOT_SCRIPT_STALL_OPCODE
,
427 Internal function to add Save jmp address according to DISPATCH_OPCODE.
428 We ignore "Context" parameter
430 @param Marker The variable argument list to get the opcode
431 and associated attributes.
433 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
434 @retval EFI_SUCCESS Opcode is added.
444 EntryPoint
= (VOID
*)(UINTN
)VA_ARG (Marker
, EFI_PHYSICAL_ADDRESS
);
445 return mS3SaveState
->Write (
447 EFI_BOOT_SCRIPT_DISPATCH_OPCODE
,
453 Internal function to add Save jmp address according to DISPATCH_OPCODE.
454 We ignore "Context" parameter.
455 We need create thunk stub to convert PEI entrypoint (used in Framework version)
456 to DXE entrypoint (defined in PI spec).
458 @param Marker The variable argument list to get the opcode
459 and associated attributes.
461 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
462 @retval EFI_SUCCESS Opcode is added.
466 FrameworkBootScriptDispatch (
473 EntryPoint
= (VOID
*)(UINTN
)VA_ARG (Marker
, EFI_PHYSICAL_ADDRESS
);
478 Context
= EntryPoint
;
479 EntryPoint
= (VOID
*)(UINTN
)FrameworkBootScriptDispatchStub
;
480 return mS3SaveState
->Write (
482 EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE
,
489 Internal function to add memory pool operation to the table.
491 @param Marker The variable argument list to get the opcode
492 and associated attributes.
494 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
495 @retval EFI_SUCCESS Opcode is added.
503 EFI_BOOT_SCRIPT_WIDTH Width
;
511 Width
= VA_ARG (Marker
, EFI_BOOT_SCRIPT_WIDTH
);
512 Address
= VA_ARG (Marker
, UINT64
);
513 BitMask
= VA_ARG (Marker
, UINT8
*);
514 BitValue
= VA_ARG (Marker
, UINT8
*);
515 Duration
= (UINT64
)VA_ARG (Marker
, UINT64
);
516 LoopTimes
= (UINT64
)VA_ARG (Marker
, UINT64
);
518 // Framework version: Duration is used for Stall(), which is Microseconds.
519 // Total time is: Duration(Microseconds) * LoopTimes.
520 // PI version: Duration is always 100ns. Delay is LoopTimes.
521 // Total time is: 100ns * Delay.
522 // So Delay = Duration(Microseconds) * LoopTimes / 100ns
523 // = Duration * 1000ns * LoopTimes / 100ns
524 // = Duration * 10 * LoopTimes
526 Delay
= MultU64x64 (MultU64x32 (Duration
, 10), LoopTimes
);
529 // Framework version: First BitMask, then BitValue
530 // PI version: First Data, then DataMask
531 // So we revert their order in function call
533 return mS3SaveState
->Write (
535 EFI_BOOT_SCRIPT_MEM_POLL_OPCODE
,
545 Internal function to add Save jmp address according to DISPATCH_OPCODE2.
546 The "Context" parameter is not ignored.
548 @param Marker The variable argument list to get the opcode
549 and associated attributes.
551 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
552 @retval EFI_SUCCESS Opcode is added.
556 BootScriptDispatch2 (
563 EntryPoint
= (VOID
*)(UINTN
)VA_ARG (Marker
, EFI_PHYSICAL_ADDRESS
);
564 Context
= (VOID
*)(UINTN
)VA_ARG (Marker
, EFI_PHYSICAL_ADDRESS
);
566 return mS3SaveState
->Write (
568 EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE
,
574 Internal function to add the opcode link node to the link
576 @param Marker The variable argument list to get the opcode
577 and associated attributes.
579 @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
580 @retval EFI_SUCCESS The opcode entry is added to the link list
584 BootScriptInformation (
588 UINT32 InformationLength
;
589 EFI_PHYSICAL_ADDRESS Information
;
591 InformationLength
= VA_ARG (Marker
, UINT32
);
592 Information
= VA_ARG (Marker
, EFI_PHYSICAL_ADDRESS
);
594 return mS3SaveState
->Write (
596 EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
598 (VOID
*)(UINTN
)Information
603 Adds a record into a specified Framework boot script table.
605 This function is used to store a boot script record into a given boot
606 script table. If the table specified by TableName is nonexistent in the
607 system, a new table will automatically be created and then the script record
608 will be added into the new table. A boot script table can add new script records
609 until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only
610 meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is
611 responsible for allocating necessary memory for the script.
613 This function has a variable parameter list. The exact parameter list depends on
614 the OpCode that is passed into the function. If an unsupported OpCode or illegal
615 parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
616 If there are not enough resources available for storing more scripts, this function returns
617 EFI_OUT_OF_RESOURCES.
619 @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
620 @param TableName Name of the script table. Currently, the only meaningful value is
621 EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
622 @param OpCode The operation code (opcode) number.
623 @param ... Argument list that is specific to each opcode.
625 @retval EFI_SUCCESS The operation succeeded. A record was added into the
626 specified script table.
627 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
628 If the opcode is unknow or not supported because of the PCD
630 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
636 IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL
*This
,
645 if (TableName
!= FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE
) {
647 // Only S3 boot script is supported for now
649 return EFI_OUT_OF_RESOURCES
;
652 // Build script according to opcode
656 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE
:
657 VA_START (Marker
, OpCode
);
658 Status
= BootScriptIoWrite (Marker
);
662 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE
:
663 VA_START (Marker
, OpCode
);
664 Status
= BootScriptIoReadWrite (Marker
);
668 case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE
:
669 VA_START (Marker
, OpCode
);
670 Status
= BootScriptMemWrite (Marker
);
674 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE
:
675 VA_START (Marker
, OpCode
);
676 Status
= BootScriptMemReadWrite (Marker
);
680 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE
:
681 VA_START (Marker
, OpCode
);
682 Status
= BootScriptPciCfgWrite (Marker
);
686 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE
:
687 VA_START (Marker
, OpCode
);
688 Status
= BootScriptPciCfgReadWrite (Marker
);
692 case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE
:
693 VA_START (Marker
, OpCode
);
694 Status
= BootScriptSmbusExecute (Marker
);
698 case EFI_BOOT_SCRIPT_STALL_OPCODE
:
699 VA_START (Marker
, OpCode
);
700 Status
= BootScriptStall (Marker
);
705 case EFI_BOOT_SCRIPT_DISPATCH_OPCODE
:
706 VA_START (Marker
, OpCode
);
707 Status
= FrameworkBootScriptDispatch (Marker
);
711 case FRAMEWORK_EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE
:
712 VA_START (Marker
, OpCode
);
713 Status
= BootScriptDispatch2 (Marker
);
717 case EFI_BOOT_SCRIPT_INFORMATION_OPCODE
:
718 VA_START (Marker
, OpCode
);
719 Status
= BootScriptInformation (Marker
);
723 case FRAMEWORK_EFI_BOOT_SCRIPT_MEM_POLL_OPCODE
:
724 VA_START (Marker
, OpCode
);
725 Status
= BootScriptMemPoll (Marker
);
729 case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
:
730 VA_START (Marker
, OpCode
);
731 Status
= BootScriptPciCfg2Write (Marker
);
735 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE
:
736 VA_START (Marker
, OpCode
);
737 Status
= BootScriptPciCfg2ReadWrite (Marker
);
742 Status
= EFI_INVALID_PARAMETER
;
750 Closes the specified script table.
752 This function closes the specified boot script table and returns the base address
753 of the table. It allocates a new pool to duplicate all the boot scripts in the specified
754 table. Once this function is called, the specified table will be destroyed after it is
755 copied into the allocated pool. As a result, any attempts to add a script record into a
756 closed table will cause a new table to be created. The base address of the allocated pool
757 will be returned in Address. After using the boot script table, the caller is responsible
758 for freeing the pool that is allocated by this function. If the boot script table,
759 such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed
760 memory region, the caller should copy the table into the nonperturbed memory region by itself.
762 @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
763 @param TableName Name of the script table. Currently, the only meaningful value is
764 EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
765 @param Address A pointer to the physical address where the table begins.
767 @retval EFI_SUCCESS The table was successfully returned.
768 @retval EFI_NOT_FOUND The specified table was not created previously.
769 @retval EFI_OUT_OF_RESOURCE Memory is insufficient to hold the reorganized boot script table.
770 @retval EFI_UNSUPPORTED the table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE
775 BootScriptCloseTable (
776 IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL
*This
,
778 OUT EFI_PHYSICAL_ADDRESS
*Address
781 if (TableName
!= FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE
) {
783 // Only S3 boot script is supported for now
785 return EFI_NOT_FOUND
;
788 // Here the close table is not implemented.
791 return EFI_UNSUPPORTED
;
795 Register image to memory profile.
797 @param FileName File name of the image.
798 @param ImageBase Image base address.
799 @param ImageSize Image size.
800 @param FileType File type of the image.
804 RegisterMemoryProfileImage (
805 IN EFI_GUID
*FileName
,
806 IN PHYSICAL_ADDRESS ImageBase
,
808 IN EFI_FV_FILETYPE FileType
812 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
813 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
814 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
816 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT0
) != 0) {
818 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
819 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
**) &ProfileProtocol
);
820 if (!EFI_ERROR (Status
)) {
821 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
822 SetDevicePathEndNode (FilePath
+ 1);
824 Status
= ProfileProtocol
->RegisterImage (
826 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
836 This routine is entry point of ScriptSave driver.
838 @param ImageHandle Handle for this drivers loaded image protocol.
839 @param SystemTable EFI system table.
841 @retval EFI_OUT_OF_RESOURCES No enough resource
842 @retval EFI_SUCCESS Succesfully installed the ScriptSave driver.
843 @retval other Errors occured.
848 InitializeScriptSaveOnS3SaveState (
849 IN EFI_HANDLE ImageHandle
,
850 IN EFI_SYSTEM_TABLE
*SystemTable
855 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
856 BOOT_SCRIPT_THUNK_DATA
*BootScriptThunkData
;
859 EFI_PHYSICAL_ADDRESS MemoryAddress
;
861 EFI_HANDLE NewImageHandle
;
864 // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
865 // point is loaded by DXE code which is the first time loaded. or else, it is already
866 // be reloaded be itself.This is a work-around
868 Status
= gBS
->LocateProtocol (&gEfiCallerIdGuid
, NULL
, &DevicePath
);
869 if (EFI_ERROR (Status
)) {
871 // This is the first-time loaded by DXE core. reload itself to RESERVED mem
874 // A workaround: Here we install a dummy handle
876 NewImageHandle
= NULL
;
877 Status
= gBS
->InstallProtocolInterface (
880 EFI_NATIVE_INTERFACE
,
883 ASSERT_EFI_ERROR (Status
);
885 Status
= GetSectionFromAnyFv (
892 ASSERT_EFI_ERROR (Status
);
893 ImageContext
.Handle
= Buffer
;
894 ImageContext
.ImageRead
= PeCoffLoaderImageReadFromMemory
;
896 // Get information about the image being loaded
898 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
899 ASSERT_EFI_ERROR (Status
);
901 MemoryAddress
= SIZE_4GB
- 1;
902 if (ImageContext
.SectionAlignment
> EFI_PAGE_SIZE
) {
903 PageNumber
= EFI_SIZE_TO_PAGES ((UINTN
) (ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
));
905 PageNumber
= EFI_SIZE_TO_PAGES ((UINTN
) ImageContext
.ImageSize
);
907 Status
= gBS
->AllocatePages (
909 EfiReservedMemoryType
,
913 ASSERT_EFI_ERROR (Status
);
914 ImageContext
.ImageAddress
= (PHYSICAL_ADDRESS
)(UINTN
)MemoryAddress
;
916 // Align buffer on section boundry
918 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
919 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
921 // Load the image to our new buffer
923 Status
= PeCoffLoaderLoadImage (&ImageContext
);
924 ASSERT_EFI_ERROR (Status
);
927 // Relocate the image in our new buffer
929 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
930 ASSERT_EFI_ERROR (Status
);
933 // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
935 gBS
->FreePool (Buffer
);
938 // Flush the instruction cache so the image data is written before we execute it
940 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
942 RegisterMemoryProfileImage (
944 ImageContext
.ImageAddress
,
945 ImageContext
.ImageSize
,
946 EFI_FV_FILETYPE_DRIVER
949 Status
= ((EFI_IMAGE_ENTRY_POINT
)(UINTN
)(ImageContext
.EntryPoint
)) (NewImageHandle
, SystemTable
);
950 ASSERT_EFI_ERROR (Status
);
953 // Additional step for BootScriptThunk integrity
957 // Allocate BootScriptThunkData
959 BootScriptThunkData
= AllocatePool (sizeof (BOOT_SCRIPT_THUNK_DATA
));
960 ASSERT (BootScriptThunkData
!= NULL
);
962 BootScriptThunkData
->BootScriptThunkBase
= ImageContext
.ImageAddress
;
963 BootScriptThunkData
->BootScriptThunkLength
= ImageContext
.ImageSize
;
965 // Set BootScriptThunkData
967 PcdSet64 (BootScriptThunkDataPtr
, (UINT64
)(UINTN
)BootScriptThunkData
);
971 // the entry point is invoked after reloading. following code only run in RESERVED mem
975 // Locate and cache PI S3 Save State Protocol.
977 Status
= gBS
->LocateProtocol (
978 &gEfiS3SaveStateProtocolGuid
,
980 (VOID
**) &mS3SaveState
982 ASSERT_EFI_ERROR (Status
);
984 return gBS
->InstallProtocolInterface (
986 &gEfiBootScriptSaveProtocolGuid
,
987 EFI_NATIVE_INTERFACE
,