diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Core/Pei | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Core/Pei')
20 files changed, 11955 insertions, 11955 deletions
diff --git a/MdeModulePkg/Core/Pei/BootMode/BootMode.c b/MdeModulePkg/Core/Pei/BootMode/BootMode.c index 100942ecd0..fb09f87c8d 100644 --- a/MdeModulePkg/Core/Pei/BootMode/BootMode.c +++ b/MdeModulePkg/Core/Pei/BootMode/BootMode.c @@ -1,75 +1,75 @@ -/** @file
- This module provide function for ascertaining and updating the boot mode:
- GetBootMode()
- SetBootMode()
- See PI Specification volume I, chapter 9 Boot Paths for additional information
- on the boot mode.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
- This service enables PEIMs to ascertain the present value of the boot mode.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param BootMode A pointer to contain the value of the boot mode.
-
- @retval EFI_SUCCESS The boot mode was returned successfully.
- @retval EFI_INVALID_PARAMETER BootMode is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiGetBootMode (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN OUT EFI_BOOT_MODE *BootMode
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
-
- if (BootMode == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- HandOffHob = (PrivateData->HobList.HandoffInformationTable);
-
- *BootMode = HandOffHob->BootMode;
-
- return EFI_SUCCESS;
-}
-
-/**
- This service enables PEIMs to update the boot mode variable.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param BootMode The value of the boot mode to set.
-
- @return EFI_SUCCESS The value was successfully updated
-
-**/
-EFI_STATUS
-EFIAPI
-PeiSetBootMode (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_BOOT_MODE BootMode
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- HandOffHob = (PrivateData->HobList.HandoffInformationTable);
-
- HandOffHob->BootMode = BootMode;
-
- return EFI_SUCCESS;
-}
+/** @file + This module provide function for ascertaining and updating the boot mode: + GetBootMode() + SetBootMode() + See PI Specification volume I, chapter 9 Boot Paths for additional information + on the boot mode. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ) +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + if (BootMode == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + *BootMode = HandOffHob->BootMode; + + return EFI_SUCCESS; +} + +/** + This service enables PEIMs to update the boot mode variable. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode The value of the boot mode to set. + + @return EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + HandOffHob->BootMode = BootMode; + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Pei/CpuIo/CpuIo.c b/MdeModulePkg/Core/Pei/CpuIo/CpuIo.c index 8b48a0122c..77585569af 100644 --- a/MdeModulePkg/Core/Pei/CpuIo/CpuIo.c +++ b/MdeModulePkg/Core/Pei/CpuIo/CpuIo.c @@ -1,535 +1,535 @@ -/** @file
- The default version of EFI_PEI_CPU_IO_PPI support published by PeiServices in
- PeiCore initialization phase.
-
- EFI_PEI_CPU_IO_PPI is installed by some platform or chipset-specific PEIM that
- abstracts the processor-visible I/O operations. When PeiCore is started, the
- default version of EFI_PEI_CPU_IO_PPI will be assigned to PeiServices table.
-
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-///
-/// This default instance of EFI_PEI_CPU_IO_PPI install assigned to EFI_PEI_SERVICE.CpuIo
-/// when PeiCore's initialization.
-///
-EFI_PEI_CPU_IO_PPI gPeiDefaultCpuIoPpi = {
- {
- PeiDefaultMemRead,
- PeiDefaultMemWrite
- },
- {
- PeiDefaultIoRead,
- PeiDefaultIoWrite
- },
- PeiDefaultIoRead8,
- PeiDefaultIoRead16,
- PeiDefaultIoRead32,
- PeiDefaultIoRead64,
- PeiDefaultIoWrite8,
- PeiDefaultIoWrite16,
- PeiDefaultIoWrite32,
- PeiDefaultIoWrite64,
- PeiDefaultMemRead8,
- PeiDefaultMemRead16,
- PeiDefaultMemRead32,
- PeiDefaultMemRead64,
- PeiDefaultMemWrite8,
- PeiDefaultMemWrite16,
- PeiDefaultMemWrite32,
- PeiDefaultMemWrite64
-};
-
-/**
- Memory-based read services.
-
- This function is to perform the Memory Access Read service based on installed
- instance of the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultMemRead (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- Memory-based write services.
-
- This function is to perform the Memory Access Write service based on installed
- instance of the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultMemWrite (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- IO-based read services.
-
- This function is to perform the IO-base read service for the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultIoRead (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- IO-based write services.
-
- This function is to perform the IO-base write service for the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultIoWrite (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- 8-bit I/O read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 8-bit value returned from the I/O space.
-**/
-UINT8
-EFIAPI
-PeiDefaultIoRead8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- Reads an 16-bit I/O port.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return A 16-bit value returned from the I/O space.
-**/
-UINT16
-EFIAPI
-PeiDefaultIoRead16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- Reads an 32-bit I/O port.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return A 32-bit value returned from the I/O space.
-**/
-UINT32
-EFIAPI
-PeiDefaultIoRead32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- Reads an 64-bit I/O port.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return A 64-bit value returned from the I/O space.
-**/
-UINT64
-EFIAPI
-PeiDefaultIoRead64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- 8-bit I/O write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT8 Data
- )
-{
-}
-
-/**
- 16-bit I/O write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT16 Data
- )
-{
-}
-
-/**
- 32-bit I/O write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT32 Data
- )
-{
-}
-
-/**
- 64-bit I/O write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT64 Data
- )
-{
-}
-
-/**
- 8-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 8-bit value returned from the memory space.
-
-**/
-UINT8
-EFIAPI
-PeiDefaultMemRead8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- 16-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 16-bit value returned from the memory space.
-
-**/
-UINT16
-EFIAPI
-PeiDefaultMemRead16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- 32-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 32-bit value returned from the memory space.
-
-**/
-UINT32
-EFIAPI
-PeiDefaultMemRead32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- 64-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 64-bit value returned from the memory space.
-
-**/
-UINT64
-EFIAPI
-PeiDefaultMemRead64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- )
-{
- return 0;
-}
-
-/**
- 8-bit memory write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT8 Data
- )
-{
-}
-
-/**
- 16-bit memory write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT16 Data
- )
-{
-}
-
-/**
- 32-bit memory write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT32 Data
- )
-{
-}
-
-/**
- 64-bit memory write operations.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do
- nothing.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT64 Data
- )
-{
-}
+/** @file + The default version of EFI_PEI_CPU_IO_PPI support published by PeiServices in + PeiCore initialization phase. + + EFI_PEI_CPU_IO_PPI is installed by some platform or chipset-specific PEIM that + abstracts the processor-visible I/O operations. When PeiCore is started, the + default version of EFI_PEI_CPU_IO_PPI will be assigned to PeiServices table. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/// +/// This default instance of EFI_PEI_CPU_IO_PPI install assigned to EFI_PEI_SERVICE.CpuIo +/// when PeiCore's initialization. +/// +EFI_PEI_CPU_IO_PPI gPeiDefaultCpuIoPpi = { + { + PeiDefaultMemRead, + PeiDefaultMemWrite + }, + { + PeiDefaultIoRead, + PeiDefaultIoWrite + }, + PeiDefaultIoRead8, + PeiDefaultIoRead16, + PeiDefaultIoRead32, + PeiDefaultIoRead64, + PeiDefaultIoWrite8, + PeiDefaultIoWrite16, + PeiDefaultIoWrite32, + PeiDefaultIoWrite64, + PeiDefaultMemRead8, + PeiDefaultMemRead16, + PeiDefaultMemRead32, + PeiDefaultMemRead64, + PeiDefaultMemWrite8, + PeiDefaultMemWrite16, + PeiDefaultMemWrite32, + PeiDefaultMemWrite64 +}; + +/** + Memory-based read services. + + This function is to perform the Memory Access Read service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Memory-based write services. + + This function is to perform the Memory Access Write service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + IO-based read services. + + This function is to perform the IO-base read service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + IO-based write services. + + This function is to perform the IO-base write service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + 8-bit I/O read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the I/O space. +**/ +UINT8 +EFIAPI +PeiDefaultIoRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + Reads an 16-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 16-bit value returned from the I/O space. +**/ +UINT16 +EFIAPI +PeiDefaultIoRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + Reads an 32-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 32-bit value returned from the I/O space. +**/ +UINT32 +EFIAPI +PeiDefaultIoRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + Reads an 64-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 64-bit value returned from the I/O space. +**/ +UINT64 +EFIAPI +PeiDefaultIoRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 8-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ) +{ +} + +/** + 16-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ) +{ +} + +/** + 32-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ) +{ +} + +/** + 64-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ) +{ +} + +/** + 8-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the memory space. + +**/ +UINT8 +EFIAPI +PeiDefaultMemRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 16-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 16-bit value returned from the memory space. + +**/ +UINT16 +EFIAPI +PeiDefaultMemRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 32-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 32-bit value returned from the memory space. + +**/ +UINT32 +EFIAPI +PeiDefaultMemRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 64-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 64-bit value returned from the memory space. + +**/ +UINT64 +EFIAPI +PeiDefaultMemRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 8-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ) +{ +} + +/** + 16-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ) +{ +} + +/** + 32-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ) +{ +} + +/** + 64-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ) +{ +} diff --git a/MdeModulePkg/Core/Pei/Dependency/Dependency.c b/MdeModulePkg/Core/Pei/Dependency/Dependency.c index 9982167635..3ca9349dcd 100644 --- a/MdeModulePkg/Core/Pei/Dependency/Dependency.c +++ b/MdeModulePkg/Core/Pei/Dependency/Dependency.c @@ -1,252 +1,252 @@ -/** @file
- PEI Dispatcher Dependency Evaluator
-
- This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
- if a driver can be scheduled for execution. The criteria to be scheduled is
- that the dependency expression is satisfied.
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-#include "Dependency.h"
-
-/**
-
- This routine determines if a PPI has been installed.
- The truth value of a GUID is determined by if the PPI has
- been published and can be queried from the PPI database.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param Stack Reference to EVAL_STACK_ENTRY that contains PPI GUID to check
-
- @retval TRUE if the PPI is already installed.
- @retval FALSE if the PPI has yet to be installed.
-
-**/
-BOOLEAN
-IsPpiInstalled (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EVAL_STACK_ENTRY *Stack
- )
-{
- VOID *PeiInstance;
- EFI_STATUS Status;
- EFI_GUID PpiGuid;
-
- //
- // If there is no GUID to evaluate, just return current result on stack.
- //
- if (Stack->Operator == NULL) {
- return Stack->Result;
- }
-
- //
- // Copy the GUID into a local variable so that there are no
- // possibilities of alignment faults for cross-compilation
- // environments such as Intel?Itanium(TM).
- //
- CopyMem (&PpiGuid, Stack->Operator, sizeof (EFI_GUID));
-
- //
- // Check if the PPI is installed.
- //
- Status = PeiServicesLocatePpi (
- &PpiGuid, // GUID
- 0, // INSTANCE
- NULL, // EFI_PEI_PPI_DESCRIPTOR
- &PeiInstance // PPI
- );
-
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
-
- This is the POSTFIX version of the dependency evaluator. When a
- PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on
- the evaluation stack. When that entry is popped from the evaluation
- stack, the PPI is checked if it is installed. This method allows
- some time savings as not all PPIs must be checked for certain
- operation types (AND, OR).
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to
- the BNF described above and is stored in postfix notation.
-
- @retval TRUE if it is a well-formed Grammar
- @retval FALSE if the dependency expression overflows the evaluation stack
- if the dependency expression underflows the evaluation stack
- if the dependency expression is not a well-formed Grammar.
-
-**/
-BOOLEAN
-PeimDispatchReadiness (
- IN EFI_PEI_SERVICES **PeiServices,
- IN VOID *DependencyExpression
- )
-{
- DEPENDENCY_EXPRESSION_OPERAND *Iterator;
- EVAL_STACK_ENTRY *StackPtr;
- EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];
-
- Iterator = DependencyExpression;
-
- StackPtr = EvalStack;
-
- while (TRUE) {
- switch (*(Iterator++)) {
- //
- // For performance reason we put the frequently used items in front of
- // the rarely used items
- //
-
- case (EFI_DEP_PUSH):
- //
- // Check to make sure the dependency grammar doesn't overflow the
- // EvalStack on the push
- //
- if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
- DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
- return FALSE;
- }
-
- //
- // Push the pointer to the PUSH opcode operator (pointer to PPI GUID)
- // We will evaluate if the PPI is installed on the POP operation.
- //
- StackPtr->Operator = (VOID *)Iterator;
- Iterator = Iterator + sizeof (EFI_GUID);
- DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) = %a\n", StackPtr->Operator, IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE"));
- StackPtr++;
- break;
-
- case (EFI_DEP_AND):
- case (EFI_DEP_OR):
- if (*(Iterator - 1) == EFI_DEP_AND) {
- DEBUG ((DEBUG_DISPATCH, " AND\n"));
- } else {
- DEBUG ((DEBUG_DISPATCH, " OR\n"));
- }
-
- //
- // Check to make sure the dependency grammar doesn't underflow the
- // EvalStack on the two POPs for the AND operation. Don't need to
- // check for the overflow on PUSHing the result since we already
- // did two POPs.
- //
- if (StackPtr < &EvalStack[2]) {
- DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
- return FALSE;
- }
-
- //
- // Evaluate the first POPed operator only. If the operand is
- // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the
- // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE,
- // we don't need to check the second operator, and the result will be
- // evaluation of the POPed operator. Otherwise, don't POP the second
- // operator since it will now evaluate to the final result on the
- // next operand that causes a POP.
- //
- StackPtr--;
- //
- // Iterator has increased by 1 after we retrieve the operand, so here we
- // should get the value pointed by (Iterator - 1), in order to obtain the
- // same operand.
- //
- if (*(Iterator - 1) == EFI_DEP_AND) {
- if (!(IsPpiInstalled (PeiServices, StackPtr))) {
- (StackPtr-1)->Result = FALSE;
- (StackPtr-1)->Operator = NULL;
- }
- } else {
- if (IsPpiInstalled (PeiServices, StackPtr)) {
- (StackPtr-1)->Result = TRUE;
- (StackPtr-1)->Operator = NULL;
- }
- }
-
- break;
-
- case (EFI_DEP_END):
- DEBUG ((DEBUG_DISPATCH, " END\n"));
- StackPtr--;
- //
- // Check to make sure EvalStack is balanced. If not, then there is
- // an error in the dependency grammar, so return EFI_INVALID_PARAMETER.
- //
- if (StackPtr != &EvalStack[0]) {
- DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
- return FALSE;
- }
-
- DEBUG ((DEBUG_DISPATCH, " RESULT = %a\n", IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE"));
- return IsPpiInstalled (PeiServices, StackPtr);
-
- case (EFI_DEP_NOT):
- DEBUG ((DEBUG_DISPATCH, " NOT\n"));
- //
- // Check to make sure the dependency grammar doesn't underflow the
- // EvalStack on the POP for the NOT operation. Don't need to
- // check for the overflow on PUSHing the result since we already
- // did a POP.
- //
- if (StackPtr < &EvalStack[1]) {
- DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
- return FALSE;
- }
-
- (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1));
- (StackPtr-1)->Operator = NULL;
- break;
-
- case (EFI_DEP_TRUE):
- case (EFI_DEP_FALSE):
- if (*(Iterator - 1) == EFI_DEP_TRUE) {
- DEBUG ((DEBUG_DISPATCH, " TRUE\n"));
- } else {
- DEBUG ((DEBUG_DISPATCH, " FALSE\n"));
- }
-
- //
- // Check to make sure the dependency grammar doesn't overflow the
- // EvalStack on the push
- //
- if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
- DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
- return FALSE;
- }
-
- //
- // Iterator has increased by 1 after we retrieve the operand, so here we
- // should get the value pointed by (Iterator - 1), in order to obtain the
- // same operand.
- //
- if (*(Iterator - 1) == EFI_DEP_TRUE) {
- StackPtr->Result = TRUE;
- } else {
- StackPtr->Result = FALSE;
- }
-
- StackPtr->Operator = NULL;
- StackPtr++;
- break;
-
- default:
- DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Invalid opcode)\n"));
- //
- // The grammar should never arrive here
- //
- return FALSE;
- }
- }
-}
+/** @file + PEI Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria to be scheduled is + that the dependency expression is satisfied. + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" +#include "Dependency.h" + +/** + + This routine determines if a PPI has been installed. + The truth value of a GUID is determined by if the PPI has + been published and can be queried from the PPI database. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param Stack Reference to EVAL_STACK_ENTRY that contains PPI GUID to check + + @retval TRUE if the PPI is already installed. + @retval FALSE if the PPI has yet to be installed. + +**/ +BOOLEAN +IsPpiInstalled ( + IN EFI_PEI_SERVICES **PeiServices, + IN EVAL_STACK_ENTRY *Stack + ) +{ + VOID *PeiInstance; + EFI_STATUS Status; + EFI_GUID PpiGuid; + + // + // If there is no GUID to evaluate, just return current result on stack. + // + if (Stack->Operator == NULL) { + return Stack->Result; + } + + // + // Copy the GUID into a local variable so that there are no + // possibilities of alignment faults for cross-compilation + // environments such as Intel?Itanium(TM). + // + CopyMem (&PpiGuid, Stack->Operator, sizeof (EFI_GUID)); + + // + // Check if the PPI is installed. + // + Status = PeiServicesLocatePpi ( + &PpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &PeiInstance // PPI + ); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + return TRUE; +} + +/** + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is popped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + + @retval TRUE if it is a well-formed Grammar + @retval FALSE if the dependency expression overflows the evaluation stack + if the dependency expression underflows the evaluation stack + if the dependency expression is not a well-formed Grammar. + +**/ +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ) +{ + DEPENDENCY_EXPRESSION_OPERAND *Iterator; + EVAL_STACK_ENTRY *StackPtr; + EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; + + Iterator = DependencyExpression; + + StackPtr = EvalStack; + + while (TRUE) { + switch (*(Iterator++)) { + // + // For performance reason we put the frequently used items in front of + // the rarely used items + // + + case (EFI_DEP_PUSH): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n")); + return FALSE; + } + + // + // Push the pointer to the PUSH opcode operator (pointer to PPI GUID) + // We will evaluate if the PPI is installed on the POP operation. + // + StackPtr->Operator = (VOID *)Iterator; + Iterator = Iterator + sizeof (EFI_GUID); + DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) = %a\n", StackPtr->Operator, IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE")); + StackPtr++; + break; + + case (EFI_DEP_AND): + case (EFI_DEP_OR): + if (*(Iterator - 1) == EFI_DEP_AND) { + DEBUG ((DEBUG_DISPATCH, " AND\n")); + } else { + DEBUG ((DEBUG_DISPATCH, " OR\n")); + } + + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the two POPs for the AND operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did two POPs. + // + if (StackPtr < &EvalStack[2]) { + DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n")); + return FALSE; + } + + // + // Evaluate the first POPed operator only. If the operand is + // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the + // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE, + // we don't need to check the second operator, and the result will be + // evaluation of the POPed operator. Otherwise, don't POP the second + // operator since it will now evaluate to the final result on the + // next operand that causes a POP. + // + StackPtr--; + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_AND) { + if (!(IsPpiInstalled (PeiServices, StackPtr))) { + (StackPtr-1)->Result = FALSE; + (StackPtr-1)->Operator = NULL; + } + } else { + if (IsPpiInstalled (PeiServices, StackPtr)) { + (StackPtr-1)->Result = TRUE; + (StackPtr-1)->Operator = NULL; + } + } + + break; + + case (EFI_DEP_END): + DEBUG ((DEBUG_DISPATCH, " END\n")); + StackPtr--; + // + // Check to make sure EvalStack is balanced. If not, then there is + // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. + // + if (StackPtr != &EvalStack[0]) { + DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n")); + return FALSE; + } + + DEBUG ((DEBUG_DISPATCH, " RESULT = %a\n", IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE")); + return IsPpiInstalled (PeiServices, StackPtr); + + case (EFI_DEP_NOT): + DEBUG ((DEBUG_DISPATCH, " NOT\n")); + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the POP for the NOT operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did a POP. + // + if (StackPtr < &EvalStack[1]) { + DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n")); + return FALSE; + } + + (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); + (StackPtr-1)->Operator = NULL; + break; + + case (EFI_DEP_TRUE): + case (EFI_DEP_FALSE): + if (*(Iterator - 1) == EFI_DEP_TRUE) { + DEBUG ((DEBUG_DISPATCH, " TRUE\n")); + } else { + DEBUG ((DEBUG_DISPATCH, " FALSE\n")); + } + + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n")); + return FALSE; + } + + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_TRUE) { + StackPtr->Result = TRUE; + } else { + StackPtr->Result = FALSE; + } + + StackPtr->Operator = NULL; + StackPtr++; + break; + + default: + DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Invalid opcode)\n")); + // + // The grammar should never arrive here + // + return FALSE; + } + } +} diff --git a/MdeModulePkg/Core/Pei/Dependency/Dependency.h b/MdeModulePkg/Core/Pei/Dependency/Dependency.h index c025863f71..e118ebac5b 100644 --- a/MdeModulePkg/Core/Pei/Dependency/Dependency.h +++ b/MdeModulePkg/Core/Pei/Dependency/Dependency.h @@ -1,25 +1,25 @@ -/** @file
- This module contains data specific to dependency expressions
- and local function prototypes.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _PEI_DEPENDENCY_H_
-#define _PEI_DEPENDENCY_H_
-
-#define MAX_GRAMMAR_SIZE 64
-
-//
-// type definitions
-//
-typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND;
-
-typedef struct {
- BOOLEAN Result;
- VOID *Operator;
-} EVAL_STACK_ENTRY;
-
-#endif
+/** @file + This module contains data specific to dependency expressions + and local function prototypes. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PEI_DEPENDENCY_H_ +#define _PEI_DEPENDENCY_H_ + +#define MAX_GRAMMAR_SIZE 64 + +// +// type definitions +// +typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND; + +typedef struct { + BOOLEAN Result; + VOID *Operator; +} EVAL_STACK_ENTRY; + +#endif diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c index ca37bde482..26d5a18fad 100644 --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -1,1823 +1,1823 @@ -/** @file
- EFI PEI Core dispatch services
-
-Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
-
- Discover all PEIMs and optional Apriori file in one FV. There is at most one
- Apriori file in one FV.
-
-
- @param Private Pointer to the private data passed in from caller
- @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.
-
-**/
-VOID
-DiscoverPeimsAndOrderWithApriori (
- IN PEI_CORE_INSTANCE *Private,
- IN PEI_CORE_FV_HANDLE *CoreFileHandle
- )
-{
- EFI_STATUS Status;
- EFI_PEI_FILE_HANDLE FileHandle;
- EFI_PEI_FILE_HANDLE AprioriFileHandle;
- EFI_GUID *Apriori;
- UINTN Index;
- UINTN Index2;
- UINTN PeimIndex;
- UINTN PeimCount;
- EFI_GUID *Guid;
- EFI_PEI_FILE_HANDLE *TempFileHandles;
- EFI_GUID *TempFileGuid;
- EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
- EFI_FV_FILE_INFO FileInfo;
-
- FvPpi = CoreFileHandle->FvPpi;
-
- //
- // Walk the FV and find all the PEIMs and the Apriori file.
- //
- AprioriFileHandle = NULL;
- Private->CurrentFvFileHandles = NULL;
- Guid = NULL;
-
- //
- // If the current FV has been scanned, directly get its cached records.
- //
- if (CoreFileHandle->ScanFv) {
- Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;
- return;
- }
-
- TempFileHandles = Private->TempFileHandles;
- TempFileGuid = Private->TempFileGuid;
-
- //
- // Go ahead to scan this FV, get PeimCount and cache FileHandles within it to TempFileHandles.
- //
- PeimCount = 0;
- FileHandle = NULL;
- do {
- Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);
- if (!EFI_ERROR (Status)) {
- if (PeimCount >= Private->TempPeimCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempFileHandles = AllocatePool (
- sizeof (EFI_PEI_FILE_HANDLE) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP)
- );
- ASSERT (TempFileHandles != NULL);
- CopyMem (
- TempFileHandles,
- Private->TempFileHandles,
- sizeof (EFI_PEI_FILE_HANDLE) * Private->TempPeimCount
- );
- Private->TempFileHandles = TempFileHandles;
- TempFileGuid = AllocatePool (
- sizeof (EFI_GUID) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP)
- );
- ASSERT (TempFileGuid != NULL);
- CopyMem (
- TempFileGuid,
- Private->TempFileGuid,
- sizeof (EFI_GUID) * Private->TempPeimCount
- );
- Private->TempFileGuid = TempFileGuid;
- Private->TempPeimCount = Private->TempPeimCount + TEMP_FILE_GROWTH_STEP;
- }
-
- TempFileHandles[PeimCount++] = FileHandle;
- }
- } while (!EFI_ERROR (Status));
-
- DEBUG ((
- DEBUG_INFO,
- "%a(): Found 0x%x PEI FFS files in the %dth FV\n",
- __func__,
- PeimCount,
- Private->CurrentPeimFvCount
- ));
-
- if (PeimCount == 0) {
- //
- // No PEIM FFS file is found, set ScanFv flag and return.
- //
- CoreFileHandle->ScanFv = TRUE;
- return;
- }
-
- //
- // Record PeimCount, allocate buffer for PeimState and FvFileHandles.
- //
- CoreFileHandle->PeimCount = PeimCount;
- CoreFileHandle->PeimState = AllocateZeroPool (sizeof (UINT8) * PeimCount);
- ASSERT (CoreFileHandle->PeimState != NULL);
- CoreFileHandle->FvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);
- ASSERT (CoreFileHandle->FvFileHandles != NULL);
-
- //
- // Get Apriori File handle
- //
- Private->AprioriCount = 0;
- Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);
- if (!EFI_ERROR (Status) && (AprioriFileHandle != NULL)) {
- //
- // Read the Apriori file
- //
- Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **)&Apriori);
- if (!EFI_ERROR (Status)) {
- //
- // Calculate the number of PEIMs in the Apriori file
- //
- Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);
- ASSERT_EFI_ERROR (Status);
- Private->AprioriCount = FileInfo.BufferSize;
- if (IS_SECTION2 (FileInfo.Buffer)) {
- Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2);
- } else {
- Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);
- }
-
- Private->AprioriCount /= sizeof (EFI_GUID);
-
- for (Index = 0; Index < PeimCount; Index++) {
- //
- // Make an array of file name GUIDs that matches the FileHandle array so we can convert
- // quickly from file name to file handle
- //
- Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);
- ASSERT_EFI_ERROR (Status);
- CopyMem (&TempFileGuid[Index], &FileInfo.FileName, sizeof (EFI_GUID));
- }
-
- //
- // Walk through TempFileGuid array to find out who is invalid PEIM GUID in Apriori file.
- // Add available PEIMs in Apriori file into FvFileHandles array.
- //
- Index = 0;
- for (Index2 = 0; Index2 < Private->AprioriCount; Index2++) {
- Guid = ScanGuid (TempFileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2]);
- if (Guid != NULL) {
- PeimIndex = ((UINTN)Guid - (UINTN)&TempFileGuid[0])/sizeof (EFI_GUID);
- CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[PeimIndex];
-
- //
- // Since we have copied the file handle we can remove it from this list.
- //
- TempFileHandles[PeimIndex] = NULL;
- }
- }
-
- //
- // Update valid AprioriCount
- //
- Private->AprioriCount = Index;
-
- //
- // Add in any PEIMs not in the Apriori file
- //
- for (Index2 = 0; Index2 < PeimCount; Index2++) {
- if (TempFileHandles[Index2] != NULL) {
- CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[Index2];
- TempFileHandles[Index2] = NULL;
- }
- }
-
- ASSERT (Index == PeimCount);
- }
- } else {
- CopyMem (CoreFileHandle->FvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);
- }
-
- //
- // The current FV File Handles have been cached. So that we don't have to scan the FV again.
- // Instead, we can retrieve the file handles within this FV from cached records.
- //
- CoreFileHandle->ScanFv = TRUE;
- Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;
-}
-
-//
-// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
-// This part of memory still need reserved on the very top of memory so that the DXE Core could
-// use these memory for data initialization. This macro should be sync with the same marco
-// defined in DXE Core.
-//
-#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
-
-/**
- This function is to test if the memory range described in resource HOB is available or not.
-
- This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the
- memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is
- available or not.
-
- @param PrivateData Pointer to the private data passed in from caller
- @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB
-**/
-BOOLEAN
-PeiLoadFixAddressIsMemoryRangeAvailable (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob
- )
-{
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
- BOOLEAN IsAvailable;
- EFI_PEI_HOB_POINTERS Hob;
-
- IsAvailable = TRUE;
- if ((PrivateData == NULL) || (ResourceHob == NULL)) {
- return FALSE;
- }
-
- //
- // test if the memory range describe in the HOB is already allocated.
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // See if this is a memory allocation HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
- MemoryHob = Hob.MemoryAllocation;
- if ((MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart) &&
- (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength))
- {
- IsAvailable = FALSE;
- break;
- }
- }
- }
-
- return IsAvailable;
-}
-
-/**
- Hook function for Loading Module at Fixed Address feature
-
- This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is
- configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When
- feature is configured as Load Modules at Fixed Offset, the function is to find the top address which is TOLM-TSEG in general.
- And also the function will re-install PEI memory.
-
- @param PrivateData Pointer to the private data passed in from caller
-
-**/
-VOID
-PeiLoadFixAddressHook (
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- EFI_PHYSICAL_ADDRESS TopLoadingAddress;
- UINT64 PeiMemorySize;
- UINT64 TotalReservedMemorySize;
- UINT64 MemoryRangeEnd;
- EFI_PHYSICAL_ADDRESS HighAddress;
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
- EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;
- EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;
- EFI_PEI_HOB_POINTERS CurrentHob;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_PEI_HOB_POINTERS NextHob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
-
- //
- // Initialize Local Variables
- //
- CurrentResourceHob = NULL;
- ResourceHob = NULL;
- NextResourceHob = NULL;
- HighAddress = 0;
- TopLoadingAddress = 0;
- MemoryRangeEnd = 0;
- CurrentHob.Raw = PrivateData->HobList.Raw;
- PeiMemorySize = PrivateData->PhysicalMemoryLength;
- //
- // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE
- // then RuntimeCodePage range and Boot time code range.
- //
- TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber));
- TotalReservedMemorySize += EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber));
- //
- // PEI memory range lies below the top reserved memory
- //
- TotalReservedMemorySize += PeiMemorySize;
-
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber)));
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber)));
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)));
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));
- //
- // Loop through the system memory typed HOB to merge the adjacent memory range
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- ResourceHob = Hob.ResourceDescriptor;
- //
- // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
- //
- if ((ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) ||
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS))
- {
- continue;
- }
-
- for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) {
- if (NextHob.Raw == Hob.Raw) {
- continue;
- }
-
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- NextResourceHob = NextHob.ResourceDescriptor;
- //
- // test if range described in this NextResourceHob is system memory and have the same attribute.
- // Note: Here is a assumption that system memory should always be healthy even without test.
- //
- if ((NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0))
- {
- //
- // See if the memory range described in ResourceHob and NextResourceHob is adjacent
- //
- if (((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart) &&
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)) ||
- ((ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart) &&
- (ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)))
- {
- MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) : (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);
-
- ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?
- ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;
-
- ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);
-
- ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);
- //
- // Delete the NextResourceHob by marking it as unused.
- //
- GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
- }
- }
- }
- }
- }
- }
-
- //
- // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe
- // the allocated memory range
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // See if this is a memory allocation HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
- MemoryHob = Hob.MemoryAllocation;
- for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) {
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- NextResourceHob = NextHob.ResourceDescriptor;
- //
- // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
- //
- if ((NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) || (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS)) {
- continue;
- }
-
- //
- // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB
- //
- if ((MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart) &&
- (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength))
- {
- //
- // Build separate resource HOB for this allocated range
- //
- if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- NextResourceHob->ResourceAttribute,
- NextResourceHob->PhysicalStart,
- (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart)
- );
- }
-
- if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- NextResourceHob->ResourceAttribute,
- MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength,
- (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength))
- );
- }
-
- NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;
- NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;
- break;
- }
- }
- }
- }
- }
-
- //
- // Try to find and validate the TOP address.
- //
- if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0 ) {
- //
- // The LMFA feature is enabled as load module at fixed absolute address.
- //
- TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdLoadModuleAtFixAddressEnable);
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
- //
- // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
- //
- if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress));
- ASSERT (FALSE);
- }
-
- //
- // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- ResourceHob = Hob.ResourceDescriptor;
- //
- // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
- //
- if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS))
- {
- //
- // See if Top address specified by user is valid.
- //
- if ((ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress) &&
- ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) &&
- PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob))
- {
- CurrentResourceHob = ResourceHob;
- CurrentHob = Hob;
- break;
- }
- }
- }
- }
-
- if (CurrentResourceHob != NULL) {
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));
- TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;
- } else {
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress));
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));
- //
- // Print the recommended Top address range.
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- ResourceHob = Hob.ResourceDescriptor;
- //
- // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
- //
- if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS))
- {
- //
- // See if Top address specified by user is valid.
- //
- if ((ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob)) {
- DEBUG ((
- DEBUG_INFO,
- "(0x%lx, 0x%lx)\n",
- (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)
- ));
- }
- }
- }
- }
-
- //
- // Assert here
- //
- ASSERT (FALSE);
- return;
- }
- } else {
- //
- // The LMFA feature is enabled as load module at fixed offset relative to TOLM
- // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
- //
- //
- // Search for a tested memory region that is below MAX_ADDRESS
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- ResourceHob = Hob.ResourceDescriptor;
- //
- // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
- //
- if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) &&
- (ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob))
- {
- //
- // See if this is the highest largest system memory region below MaxAddress
- //
- if (ResourceHob->PhysicalStart > HighAddress) {
- CurrentResourceHob = ResourceHob;
- CurrentHob = Hob;
- HighAddress = CurrentResourceHob->PhysicalStart;
- }
- }
- }
- }
-
- if (CurrentResourceHob == NULL) {
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
- //
- // Assert here
- //
- ASSERT (FALSE);
- return;
- } else {
- TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength;
- }
- }
-
- if (CurrentResourceHob != NULL) {
- //
- // rebuild resource HOB for PEI memory and reserved memory
- //
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_TESTED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- (TopLoadingAddress - TotalReservedMemorySize),
- TotalReservedMemorySize
- );
- //
- // rebuild resource for the remain memory if necessary
- //
- if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- CurrentResourceHob->PhysicalStart,
- (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)
- );
- }
-
- if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- TopLoadingAddress,
- (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)
- );
- }
-
- //
- // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt.
- //
- GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;
- }
-
- //
- // Cache the top address for Loading Module at Fixed Address feature
- //
- PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));
- //
- // reinstall the PEI memory relative to TopLoadingAddress
- //
- PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;
- PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
-}
-
-/**
- This routine is invoked in switch stack as PeiCore Entry.
-
- @param SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
- @param Private Pointer to old core data that is used to initialize the
- core's data areas.
-**/
-VOID
-EFIAPI
-PeiCoreEntry (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *Private
- )
-{
- //
- // Entry PEI Phase 2
- //
- PeiCore (SecCoreData, NULL, Private);
-}
-
-/**
- Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
-
- @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
- @param[in] Private Pointer to the private data passed in from caller.
-
-**/
-VOID
-PeiCheckAndSwitchStack (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *Private
- )
-{
- VOID *LoadFixPeiCodeBegin;
- EFI_STATUS Status;
- CONST EFI_PEI_SERVICES **PeiServices;
- UINT64 NewStackSize;
- EFI_PHYSICAL_ADDRESS TopOfOldStack;
- EFI_PHYSICAL_ADDRESS TopOfNewStack;
- UINTN StackOffset;
- BOOLEAN StackOffsetPositive;
- EFI_PHYSICAL_ADDRESS TemporaryRamBase;
- UINTN TemporaryRamSize;
- UINTN TemporaryStackSize;
- VOID *TemporaryStackBase;
- UINTN PeiTemporaryRamSize;
- VOID *PeiTemporaryRamBase;
- EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
- EFI_PHYSICAL_ADDRESS BaseOfNewHeap;
- EFI_PHYSICAL_ADDRESS HoleMemBase;
- UINTN HoleMemSize;
- UINTN HeapTemporaryRamSize;
- EFI_PHYSICAL_ADDRESS TempBase1;
- UINTN TempSize1;
- EFI_PHYSICAL_ADDRESS TempBase2;
- UINTN TempSize2;
- UINTN Index;
-
- PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps;
-
- if (Private->SwitchStackSignal) {
- //
- // Before switch stack from temporary memory to permanent memory, calculate the heap and stack
- // usage in temporary memory for debugging.
- //
- DEBUG_CODE_BEGIN ();
- UINT32 *StackPointer;
- EFI_PEI_HOB_POINTERS Hob;
-
- for ( StackPointer = (UINT32 *)SecCoreData->StackBase;
- (StackPointer < (UINT32 *)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
- && (*StackPointer == PcdGet32 (PcdInitValueInTempStack));
- StackPointer++)
- {
- }
-
- DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));
- DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));
- DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
- DEBUG ((
- DEBUG_INFO,
- " temporary memory stack ever used: %d bytes.\n",
- (UINT32)(SecCoreData->StackSize - ((UINTN)StackPointer - (UINTN)SecCoreData->StackBase))
- ));
- DEBUG ((
- DEBUG_INFO,
- " temporary memory heap used for HobList: %d bytes.\n",
- (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)
- ));
- DEBUG ((
- DEBUG_INFO,
- " temporary memory heap occupied by memory pages: %d bytes.\n",
- (UINT32)(UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - Private->HobList.HandoffInformationTable->EfiFreeMemoryTop)
- ));
- for (Hob.Raw = Private->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
- DEBUG ((
- DEBUG_INFO,
- "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
- Hob.MemoryAllocation->AllocDescriptor.MemoryType, \
- Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, \
- Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1
- ));
- }
- }
-
- DEBUG_CODE_END ();
-
- if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
- //
- // Loading Module at Fixed Address is enabled
- //
- PeiLoadFixAddressHook (Private);
-
- //
- // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.
- //
- LoadFixPeiCodeBegin = AllocatePages ((UINTN)PcdGet32 (PcdLoadFixAddressPeiCodePageNumber));
- DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)(UINTN)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32 (PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE)));
- }
-
- //
- // Reserve the size of new stack at bottom of physical memory
- //
- // The size of new stack in permanent memory must be the same size
- // or larger than the size of old stack in temporary memory.
- // But if new stack is smaller than the size of old stack, we also reserve
- // the size of old stack at bottom of permanent memory.
- //
- NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);
- NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);
- NewStackSize = MIN (PcdGet32 (PcdPeiCoreMaxPeiStackSize), NewStackSize);
- DEBUG ((DEBUG_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));
- ASSERT (NewStackSize >= SecCoreData->StackSize);
-
- //
- // Calculate stack offset and heap offset between temporary memory and new permanent
- // memory separately.
- //
- TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;
- TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;
- if (TopOfNewStack >= TopOfOldStack) {
- StackOffsetPositive = TRUE;
- StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);
- } else {
- StackOffsetPositive = FALSE;
- StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);
- }
-
- Private->StackOffsetPositive = StackOffsetPositive;
- Private->StackOffset = StackOffset;
-
- //
- // Build Stack HOB that describes the permanent memory stack
- //
- DEBUG ((DEBUG_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));
- BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);
-
- //
- // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address
- //
- TemporaryRamBase = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;
- TemporaryRamSize = SecCoreData->TemporaryRamSize;
- TemporaryStackSize = SecCoreData->StackSize;
- TemporaryStackBase = SecCoreData->StackBase;
- PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;
- PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;
-
- //
- // TemporaryRamSupportPpi is produced by platform's SEC
- //
- Status = PeiServicesLocatePpi (
- &gEfiTemporaryRamSupportPpiGuid,
- 0,
- NULL,
- (VOID **)&TemporaryRamSupportPpi
- );
- if (!EFI_ERROR (Status)) {
- //
- // Heap Offset
- //
- BaseOfNewHeap = TopOfNewStack;
- if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
- Private->HeapOffsetPositive = TRUE;
- Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
- } else {
- Private->HeapOffsetPositive = FALSE;
- Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
- }
-
- DEBUG ((DEBUG_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64)Private->HeapOffset, (UINT64)Private->StackOffset));
-
- //
- // Calculate new HandOffTable and PrivateData address in permanent memory's stack
- //
- if (StackOffsetPositive) {
- SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);
- Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);
- } else {
- SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);
- Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);
- }
-
- //
- // Temporary Ram Support PPI is provided by platform, it will copy
- // temporary memory to permanent memory and do stack switching.
- // After invoking Temporary Ram Support PPI, the following code's
- // stack is in permanent memory.
- //
- TemporaryRamSupportPpi->TemporaryRamMigration (
- PeiServices,
- TemporaryRamBase,
- (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),
- TemporaryRamSize
- );
-
- //
- // Migrate memory pages allocated in pre-memory phase.
- // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()
- // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().
- //
- MigrateMemoryPages (Private, TRUE);
-
- //
- // Entry PEI Phase 2
- //
- PeiCore (SecCoreData, NULL, Private);
- } else {
- //
- // Migrate memory pages allocated in pre-memory phase.
- //
- MigrateMemoryPages (Private, FALSE);
-
- //
- // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
- //
- MigratePeiServicesTablePointer ();
-
- //
- // Heap Offset
- //
- BaseOfNewHeap = TopOfNewStack;
- HoleMemBase = TopOfNewStack;
- HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;
- if (HoleMemSize != 0) {
- //
- // Make sure HOB List start address is 8 byte alignment.
- //
- BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);
- }
-
- if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
- Private->HeapOffsetPositive = TRUE;
- Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
- } else {
- Private->HeapOffsetPositive = FALSE;
- Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
- }
-
- DEBUG ((DEBUG_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64)Private->HeapOffset, (UINT64)Private->StackOffset));
-
- //
- // Migrate Heap
- //
- HeapTemporaryRamSize = (UINTN)(Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
- ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
- CopyMem ((UINT8 *)(UINTN)BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);
-
- //
- // Migrate Stack
- //
- CopyMem ((UINT8 *)(UINTN)(TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);
-
- //
- // Copy Hole Range Data
- //
- if (HoleMemSize != 0) {
- //
- // Prepare Hole
- //
- if (PeiTemporaryRamBase < TemporaryStackBase) {
- TempBase1 = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiTemporaryRamBase;
- TempSize1 = PeiTemporaryRamSize;
- TempBase2 = (EFI_PHYSICAL_ADDRESS)(UINTN)TemporaryStackBase;
- TempSize2 = TemporaryStackSize;
- } else {
- TempBase1 = (EFI_PHYSICAL_ADDRESS)(UINTN)TemporaryStackBase;
- TempSize1 = TemporaryStackSize;
- TempBase2 = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiTemporaryRamBase;
- TempSize2 = PeiTemporaryRamSize;
- }
-
- if (TemporaryRamBase < TempBase1) {
- Private->HoleData[0].Base = TemporaryRamBase;
- Private->HoleData[0].Size = (UINTN)(TempBase1 - TemporaryRamBase);
- }
-
- if (TempBase1 + TempSize1 < TempBase2) {
- Private->HoleData[1].Base = TempBase1 + TempSize1;
- Private->HoleData[1].Size = (UINTN)(TempBase2 - TempBase1 - TempSize1);
- }
-
- if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {
- Private->HoleData[2].Base = TempBase2 + TempSize2;
- Private->HoleData[2].Size = (UINTN)(TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);
- }
-
- //
- // Copy Hole Range data.
- //
- for (Index = 0; Index < HOLE_MAX_NUMBER; Index++) {
- if (Private->HoleData[Index].Size > 0) {
- if (HoleMemBase > Private->HoleData[Index].Base) {
- Private->HoleData[Index].OffsetPositive = TRUE;
- Private->HoleData[Index].Offset = (UINTN)(HoleMemBase - Private->HoleData[Index].Base);
- } else {
- Private->HoleData[Index].OffsetPositive = FALSE;
- Private->HoleData[Index].Offset = (UINTN)(Private->HoleData[Index].Base - HoleMemBase);
- }
-
- CopyMem ((VOID *)(UINTN)HoleMemBase, (VOID *)(UINTN)Private->HoleData[Index].Base, Private->HoleData[Index].Size);
- HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;
- }
- }
- }
-
- //
- // Switch new stack
- //
- SwitchStack (
- (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,
- (VOID *)SecCoreData,
- (VOID *)Private,
- (VOID *)(UINTN)TopOfNewStack
- );
- }
-
- //
- // Code should not come here
- //
- ASSERT (FALSE);
- }
-}
-
-/**
- Migrate a PEIM from temporary RAM to permanent memory.
-
- @param PeimFileHandle Pointer to the FFS file header of the image.
- @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
-
- @retval EFI_SUCCESS Successfully migrated the PEIM to permanent memory.
-
-**/
-EFI_STATUS
-EFIAPI
-MigratePeim (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN EFI_PEI_FILE_HANDLE MigratedFileHandle
- )
-{
- EFI_STATUS Status;
- EFI_FFS_FILE_HEADER *FileHeader;
- VOID *Pe32Data;
- VOID *ImageAddress;
- CHAR8 *AsciiString;
- UINTN Index;
-
- Status = EFI_SUCCESS;
-
- FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
- ASSERT (!IS_FFS_FILE2 (FileHeader));
-
- ImageAddress = NULL;
- PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
- if (ImageAddress != NULL) {
- DEBUG_CODE_BEGIN ();
- AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
- for (Index = 0; AsciiString[Index] != 0; Index++) {
- if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) {
- AsciiString = AsciiString + Index + 1;
- Index = 0;
- } else if (AsciiString[Index] == '.') {
- AsciiString[Index] = 0;
- }
- }
-
- DEBUG ((DEBUG_VERBOSE, "%a", AsciiString));
- DEBUG_CODE_END ();
-
- Pe32Data = (VOID *)((UINTN)ImageAddress - (UINTN)MigratedFileHandle + (UINTN)FileHandle);
- Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
- ASSERT_EFI_ERROR (Status);
- }
-
- return Status;
-}
-
-/**
- Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.
-
- @param OrgFvHandle Address of FV handle in temporary memory.
- @param FvHandle Address of FV handle in permanent memory.
- @param FvSize Size of the FV.
-
-**/
-VOID
-ConvertStatusCodeCallbacks (
- IN UINTN OrgFvHandle,
- IN UINTN FvHandle,
- IN UINTN FvSize
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- UINTN *NumberOfEntries;
- UINTN *CallbackEntry;
- UINTN Index;
-
- Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);
- while (Hob.Raw != NULL) {
- NumberOfEntries = GET_GUID_HOB_DATA (Hob);
- CallbackEntry = NumberOfEntries + 1;
- for (Index = 0; Index < *NumberOfEntries; Index++) {
- if (((VOID *)CallbackEntry[Index]) != NULL) {
- if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {
- DEBUG ((
- DEBUG_INFO,
- "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",
- (UINT64)Index,
- (sizeof CallbackEntry[Index]) * 2,
- (UINT64)CallbackEntry[Index]
- ));
- if (OrgFvHandle > FvHandle) {
- CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);
- } else {
- CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);
- }
-
- DEBUG ((
- DEBUG_INFO,
- "0x%0*Lx\n",
- (sizeof CallbackEntry[Index]) * 2,
- (UINT64)CallbackEntry[Index]
- ));
- }
- }
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
- }
-}
-
-/**
- Migrates PEIMs in the given firmware volume.
-
- @param Private Pointer to the PeiCore's private data structure.
- @param FvIndex The firmware volume index to migrate.
- @param OrgFvHandle The handle to the firmware volume in temporary memory.
- @param FvHandle The handle to the firmware volume in permanent memory.
-
- @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully
- @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-MigratePeimsInFv (
- IN PEI_CORE_INSTANCE *Private,
- IN UINTN FvIndex,
- IN UINTN OrgFvHandle,
- IN UINTN FvHandle
- )
-{
- EFI_STATUS Status;
- volatile UINTN FileIndex;
- EFI_PEI_FILE_HANDLE MigratedFileHandle;
- EFI_PEI_FILE_HANDLE FileHandle;
-
- if ((Private == NULL) || (FvIndex >= Private->FvCount)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Private->Fv[FvIndex].ScanFv) {
- for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {
- if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {
- FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];
-
- MigratedFileHandle = (EFI_PEI_FILE_HANDLE)((UINTN)FileHandle - OrgFvHandle + FvHandle);
-
- DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));
- Status = MigratePeim (FileHandle, MigratedFileHandle);
- DEBUG ((DEBUG_VERBOSE, "\n"));
- ASSERT_EFI_ERROR (Status);
-
- if (!EFI_ERROR (Status)) {
- Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;
- if (FvIndex == Private->CurrentPeimFvCount) {
- Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;
- }
- }
- }
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Migrate FVs out of temporary RAM before the cache is flushed.
-
- @param Private PeiCore's private data structure
- @param SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
-
- @retval EFI_SUCCESS Successfully migrated installed FVs from temporary RAM to permanent memory.
- @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
-
-**/
-EFI_STATUS
-EFIAPI
-EvacuateTempRam (
- IN PEI_CORE_INSTANCE *Private,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
- )
-{
- EFI_STATUS Status;
- volatile UINTN FvIndex;
- volatile UINTN FvChildIndex;
- UINTN ChildFvOffset;
- EFI_PHYSICAL_ADDRESS FvHeaderAddress;
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;
- EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;
- EFI_FIRMWARE_VOLUME_HEADER *RawDataFvHeader;
- EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;
-
- PEI_CORE_FV_HANDLE PeiCoreFvHandle;
- EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
- EFI_PEI_HOB_POINTERS Hob;
- EDKII_MIGRATION_INFO *MigrationInfo;
- TO_MIGRATE_FV_INFO *ToMigrateFvInfo;
- UINT32 FvMigrationFlags;
- EDKII_MIGRATED_FV_INFO MigratedFvInfo;
- UINTN Index;
-
- ASSERT (Private->PeiMemoryInstalled);
-
- DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));
-
- //
- // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
- //
- Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **)&Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **)&PeiCoreFvLocationPpi);
- if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
- PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)PeiCoreFvLocationPpi->PeiCoreFvLocation;
- } else {
- PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)SecCoreData->BootFirmwareVolumeBase;
- }
-
- for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
- if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
- CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));
- break;
- }
- }
-
- Status = EFI_SUCCESS;
-
- ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);
-
- Hob.Raw = GetFirstGuidHob (&gEdkiiMigrationInfoGuid);
- if (Hob.Raw != NULL) {
- MigrationInfo = GET_GUID_HOB_DATA (Hob);
- } else {
- MigrationInfo = NULL;
- }
-
- for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
- FvHeader = Private->Fv[FvIndex].FvHeader;
- ASSERT (FvHeader != NULL);
- ASSERT (FvIndex < Private->FvCount);
-
- DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN)FvHeader));
- if (
- !(
- ((EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader >= Private->PhysicalMemoryBegin) &&
- (((EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)
- )
- )
- {
- if ((MigrationInfo == NULL) || (MigrationInfo->MigrateAll == TRUE)) {
- //
- // Migrate all FVs and copy raw data
- //
- FvMigrationFlags = FLAGS_FV_RAW_DATA_COPY;
- } else {
- for (Index = 0; Index < MigrationInfo->ToMigrateFvCount; Index++) {
- ToMigrateFvInfo = ((TO_MIGRATE_FV_INFO *)(MigrationInfo + 1)) + Index;
- if (ToMigrateFvInfo->FvOrgBaseOnTempRam == (UINT32)(UINTN)FvHeader) {
- //
- // This FV is to migrate
- //
- FvMigrationFlags = ToMigrateFvInfo->FvMigrationFlags;
- break;
- }
- }
-
- if (Index == MigrationInfo->ToMigrateFvCount) {
- //
- // This FV is not expected to migrate
- //
- continue;
- }
- }
-
- //
- // Allocate pages to save the rebased PEIMs, the PEIMs will get dispatched later.
- //
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- EFI_SIZE_TO_PAGES ((UINTN)FvHeader->FvLength),
- &FvHeaderAddress
- );
- ASSERT_EFI_ERROR (Status);
- MigratedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHeaderAddress;
- CopyMem (MigratedFvHeader, FvHeader, (UINTN)FvHeader->FvLength);
-
- DEBUG ((
- DEBUG_VERBOSE,
- " Migrating FV[%d] from 0x%08X to 0x%08X\n",
- FvIndex,
- (UINTN)FvHeader,
- (UINTN)MigratedFvHeader
- ));
-
- //
- // Create hob to save MigratedFvInfo, this hob will only be produced when
- // Migration feature PCD PcdMigrateTemporaryRamFirmwareVolumes is set to TRUE.
- //
- MigratedFvInfo.FvOrgBase = (UINT32)(UINTN)FvHeader;
- MigratedFvInfo.FvNewBase = (UINT32)(UINTN)MigratedFvHeader;
- MigratedFvInfo.FvDataBase = 0;
- MigratedFvInfo.FvLength = (UINT32)(UINTN)FvHeader->FvLength;
-
- //
- // When FLAGS_FV_RAW_DATA_COPY bit is set, copy the context to the raw pages and
- // reset raw data base address in MigratedFvInfo hob.
- //
- if ((FvMigrationFlags & FLAGS_FV_RAW_DATA_COPY) == FLAGS_FV_RAW_DATA_COPY) {
- //
- // Allocate pages to save the raw PEIMs
- //
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- EFI_SIZE_TO_PAGES ((UINTN)FvHeader->FvLength),
- &FvHeaderAddress
- );
- ASSERT_EFI_ERROR (Status);
- RawDataFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHeaderAddress;
- CopyMem (RawDataFvHeader, FvHeader, (UINTN)FvHeader->FvLength);
- MigratedFvInfo.FvDataBase = (UINT32)(UINTN)RawDataFvHeader;
- }
-
- BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo));
-
- //
- // Migrate any children for this FV now
- //
- for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {
- ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;
- if (
- ((UINTN)ChildFvHeader > (UINTN)FvHeader) &&
- (((UINTN)ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN)FvHeader) + FvHeader->FvLength)
- )
- {
- DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));
- ChildFvOffset = (UINTN)ChildFvHeader - (UINTN)FvHeader;
- DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));
- MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)MigratedFvHeader + ChildFvOffset);
- Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;
- Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE)MigratedChildFvHeader;
- DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN)MigratedChildFvHeader));
-
- Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN)ChildFvHeader, (UINTN)MigratedChildFvHeader);
- ASSERT_EFI_ERROR (Status);
-
- ConvertPpiPointersFv (
- Private,
- (UINTN)ChildFvHeader,
- (UINTN)MigratedChildFvHeader,
- (UINTN)ChildFvHeader->FvLength - 1
- );
-
- ConvertStatusCodeCallbacks (
- (UINTN)ChildFvHeader,
- (UINTN)MigratedChildFvHeader,
- (UINTN)ChildFvHeader->FvLength - 1
- );
-
- ConvertFvHob (Private, (UINTN)ChildFvHeader, (UINTN)MigratedChildFvHeader);
- }
- }
-
- Private->Fv[FvIndex].FvHeader = MigratedFvHeader;
- Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE)MigratedFvHeader;
-
- Status = MigratePeimsInFv (Private, FvIndex, (UINTN)FvHeader, (UINTN)MigratedFvHeader);
- ASSERT_EFI_ERROR (Status);
-
- ConvertPpiPointersFv (
- Private,
- (UINTN)FvHeader,
- (UINTN)MigratedFvHeader,
- (UINTN)FvHeader->FvLength - 1
- );
-
- ConvertStatusCodeCallbacks (
- (UINTN)FvHeader,
- (UINTN)MigratedFvHeader,
- (UINTN)FvHeader->FvLength - 1
- );
-
- ConvertFvHob (Private, (UINTN)FvHeader, (UINTN)MigratedFvHeader);
- }
- }
-
- return Status;
-}
-
-/**
- Conduct PEIM dispatch.
-
- @param SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
- @param Private Pointer to the private data passed in from caller
-
-**/
-VOID
-PeiDispatcher (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *Private
- )
-{
- EFI_STATUS Status;
- UINT32 Index1;
- UINT32 Index2;
- CONST EFI_PEI_SERVICES **PeiServices;
- EFI_PEI_FILE_HANDLE PeimFileHandle;
- UINTN FvCount;
- UINTN PeimCount;
- UINT32 AuthenticationState;
- EFI_PHYSICAL_ADDRESS EntryPoint;
- EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
- UINTN SaveCurrentPeimCount;
- UINTN SaveCurrentFvCount;
- EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
- EFI_FV_FILE_INFO FvFileInfo;
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps;
- PeimEntryPoint = NULL;
- PeimFileHandle = NULL;
- EntryPoint = 0;
-
- if ((Private->PeiMemoryInstalled) &&
- (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
- PcdGetBool (PcdShadowPeimOnS3Boot))
- )
- {
- //
- // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
- // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.
- //
- SaveCurrentPeimCount = Private->CurrentPeimCount;
- SaveCurrentFvCount = Private->CurrentPeimFvCount;
- SaveCurrentFileHandle = Private->CurrentFileHandle;
-
- for (Index1 = 0; Index1 < Private->FvCount; Index1++) {
- for (Index2 = 0; Index2 < Private->Fv[Index1].PeimCount; Index2++) {
- if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISTER_FOR_SHADOW) {
- PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
- Private->CurrentFileHandle = PeimFileHandle;
- Private->CurrentPeimFvCount = Index1;
- Private->CurrentPeimCount = Index2;
- Status = PeiLoadImage (
- (CONST EFI_PEI_SERVICES **)&Private->Ps,
- PeimFileHandle,
- PEIM_STATE_REGISTER_FOR_SHADOW,
- &EntryPoint,
- &AuthenticationState
- );
- if (Status == EFI_SUCCESS) {
- //
- // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
- //
- Private->Fv[Index1].PeimState[Index2]++;
- //
- // Call the PEIM entry point
- //
- PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
-
- PERF_START_IMAGE_BEGIN (PeimFileHandle);
- PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)&Private->Ps);
- PERF_START_IMAGE_END (PeimFileHandle);
- }
-
- //
- // Process the Notify list and dispatch any notifies for
- // newly installed PPIs.
- //
- ProcessDispatchNotifyList (Private);
- }
- }
- }
-
- Private->CurrentFileHandle = SaveCurrentFileHandle;
- Private->CurrentPeimFvCount = SaveCurrentFvCount;
- Private->CurrentPeimCount = SaveCurrentPeimCount;
- }
-
- //
- // This is the main dispatch loop. It will search known FVs for PEIMs and
- // attempt to dispatch them. If any PEIM gets dispatched through a single
- // pass of the dispatcher, it will start over from the BFV again to see
- // if any new PEIMs dependencies got satisfied. With a well ordered
- // FV where PEIMs are found in the order their dependencies are also
- // satisfied, this dispatcher should run only once.
- //
- do {
- //
- // In case that reenter PeiCore happens, the last pass record is still available.
- //
- if (!Private->PeimDispatcherReenter) {
- Private->PeimNeedingDispatch = FALSE;
- Private->PeimDispatchOnThisPass = FALSE;
- } else {
- Private->PeimDispatcherReenter = FALSE;
- }
-
- for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
- CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
- ASSERT (CoreFvHandle != NULL);
-
- //
- // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
- //
- if (CoreFvHandle->FvPpi == NULL) {
- continue;
- }
-
- Private->CurrentPeimFvCount = FvCount;
-
- if (Private->CurrentPeimCount == 0) {
- //
- // When going through each FV, at first, search Apriori file to
- // reorder all PEIMs to ensure the PEIMs in Apriori file to get
- // dispatch at first.
- //
- DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
- }
-
- //
- // Start to dispatch all modules within the current FV.
- //
- for (PeimCount = Private->CurrentPeimCount;
- PeimCount < Private->Fv[FvCount].PeimCount;
- PeimCount++)
- {
- Private->CurrentPeimCount = PeimCount;
- PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
-
- if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
- if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
- Private->PeimNeedingDispatch = TRUE;
- } else {
- Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
- ASSERT_EFI_ERROR (Status);
- if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
- //
- // For FV type file, Produce new FvInfo PPI and FV HOB
- //
- Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);
- if (Status == EFI_SUCCESS) {
- //
- // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
- //
- Private->Fv[FvCount].PeimState[PeimCount]++;
- Private->PeimDispatchOnThisPass = TRUE;
- } else {
- //
- // The related GuidedSectionExtraction/Decompress PPI for the
- // encapsulated FV image section may be installed in the rest
- // of this do-while loop, so need to make another pass.
- //
- Private->PeimNeedingDispatch = TRUE;
- }
- } else {
- //
- // For PEIM driver, Load its entry point
- //
- Status = PeiLoadImage (
- PeiServices,
- PeimFileHandle,
- PEIM_STATE_NOT_DISPATCHED,
- &EntryPoint,
- &AuthenticationState
- );
- if (Status == EFI_SUCCESS) {
- //
- // The PEIM has its dependencies satisfied, and its entry point
- // has been found, so invoke it.
- //
- PERF_START_IMAGE_BEGIN (PeimFileHandle);
-
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
- EFI_PROGRESS_CODE,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
- (VOID *)(&PeimFileHandle),
- sizeof (PeimFileHandle)
- );
-
- Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);
- if (Status != EFI_SECURITY_VIOLATION) {
- //
- // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
- //
- Private->Fv[FvCount].PeimState[PeimCount]++;
- //
- // Call the PEIM entry point for PEIM driver
- //
- PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
- PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)PeiServices);
- Private->PeimDispatchOnThisPass = TRUE;
- } else {
- //
- // The related GuidedSectionExtraction PPI for the
- // signed PEIM image section may be installed in the rest
- // of this do-while loop, so need to make another pass.
- //
- Private->PeimNeedingDispatch = TRUE;
- }
-
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
- EFI_PROGRESS_CODE,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),
- (VOID *)(&PeimFileHandle),
- sizeof (PeimFileHandle)
- );
- PERF_START_IMAGE_END (PeimFileHandle);
- }
- }
-
- PeiCheckAndSwitchStack (SecCoreData, Private);
-
- //
- // Process the Notify list and dispatch any notifies for
- // newly installed PPIs.
- //
- ProcessDispatchNotifyList (Private);
-
- //
- // Recheck SwitchStackSignal after ProcessDispatchNotifyList()
- // in case PeiInstallPeiMemory() is done in a callback with
- // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.
- //
- PeiCheckAndSwitchStack (SecCoreData, Private);
-
- if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \
- (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
- PcdGetBool (PcdShadowPeimOnS3Boot))
- )
- {
- //
- // If memory is available we shadow images by default for performance reasons.
- // We call the entry point a 2nd time so the module knows it's shadowed.
- //
- // PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
- if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&
- !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes))
- {
- //
- // Load PEIM into Memory for Register for shadow PEIM.
- //
- Status = PeiLoadImage (
- PeiServices,
- PeimFileHandle,
- PEIM_STATE_REGISTER_FOR_SHADOW,
- &EntryPoint,
- &AuthenticationState
- );
- if (Status == EFI_SUCCESS) {
- PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
- }
- }
-
- ASSERT (PeimEntryPoint != NULL);
- PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)PeiServices);
- // PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
-
- //
- // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
- //
- Private->Fv[FvCount].PeimState[PeimCount]++;
-
- //
- // Process the Notify list and dispatch any notifies for
- // newly installed PPIs.
- //
- ProcessDispatchNotifyList (Private);
- }
- }
- }
- }
-
- //
- // Before walking through the next FV, we should set them to NULL/0 to
- // start at the beginning of the next FV.
- //
- Private->CurrentFileHandle = NULL;
- Private->CurrentPeimCount = 0;
- Private->CurrentFvFileHandles = NULL;
- Private->AprioriCount = 0;
- }
-
- //
- // Before making another pass, we should set it to 0 to
- // go through all the FVs.
- //
- Private->CurrentPeimFvCount = 0;
-
- //
- // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get
- // dispatched. So we need to make another pass
- //
- // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this
- // pass. If we did not dispatch a PEIM/FV there is no point in trying again
- // as it will fail the next time too (nothing has changed).
- //
- } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
-}
-
-/**
- Initialize the Dispatcher's data members
-
- @param PrivateData PeiCore's private data structure
- @param OldCoreData Old data from SecCore
- NULL if being run in non-permanent memory mode.
- @param SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
-
- @return None.
-
-**/
-VOID
-InitializeDispatcherData (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_INSTANCE *OldCoreData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
- )
-{
- if (OldCoreData == NULL) {
- PrivateData->PeimDispatcherReenter = FALSE;
- PeiInitializeFv (PrivateData, SecCoreData);
- } else {
- PeiReinitializeFv (PrivateData);
- }
-
- return;
-}
-
-/**
- This routine parses the Dependency Expression, if available, and
- decides if the module can be executed.
-
-
- @param Private PeiCore's private data structure
- @param FileHandle PEIM's file handle
- @param PeimCount Peim count in all dispatched PEIMs.
-
- @retval TRUE Can be dispatched
- @retval FALSE Cannot be dispatched
-
-**/
-BOOLEAN
-DepexSatisfied (
- IN PEI_CORE_INSTANCE *Private,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINTN PeimCount
- )
-{
- EFI_STATUS Status;
- VOID *DepexData;
- EFI_FV_FILE_INFO FileInfo;
-
- Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));
- } else {
- DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));
- }
-
- if (PeimCount < Private->AprioriCount) {
- //
- // If it's in the Apriori file then we set DEPEX to TRUE
- //
- DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));
- return TRUE;
- }
-
- //
- // Depex section not in the encapsulated section.
- //
- Status = PeiServicesFfsFindSectionData (
- EFI_SECTION_PEI_DEPEX,
- FileHandle,
- (VOID **)&DepexData
- );
-
- if (EFI_ERROR (Status)) {
- //
- // If there is no DEPEX, assume the module can be executed
- //
- DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));
- return TRUE;
- }
-
- //
- // Evaluate a given DEPEX
- //
- return PeimDispatchReadiness (&Private->Ps, DepexData);
-}
-
-/**
- This routine enables a PEIM to register itself for shadow when the PEI Foundation
- discovers permanent memory.
-
- @param FileHandle File handle of a PEIM.
-
- @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
- @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
- @retval EFI_SUCCESS Successfully to register itself.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiRegisterForShadow (
- IN EFI_PEI_FILE_HANDLE FileHandle
- )
-{
- PEI_CORE_INSTANCE *Private;
-
- Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
-
- if (Private->CurrentFileHandle != FileHandle) {
- //
- // The FileHandle must be for the current PEIM
- //
- return EFI_NOT_FOUND;
- }
-
- if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISTER_FOR_SHADOW) {
- //
- // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
- //
- return EFI_ALREADY_STARTED;
- }
-
- Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISTER_FOR_SHADOW;
-
- return EFI_SUCCESS;
-}
+/** @file + EFI PEI Core dispatch services + +Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR> +(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + Discover all PEIMs and optional Apriori file in one FV. There is at most one + Apriori file in one FV. + + + @param Private Pointer to the private data passed in from caller + @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE. + +**/ +VOID +DiscoverPeimsAndOrderWithApriori ( + IN PEI_CORE_INSTANCE *Private, + IN PEI_CORE_FV_HANDLE *CoreFileHandle + ) +{ + EFI_STATUS Status; + EFI_PEI_FILE_HANDLE FileHandle; + EFI_PEI_FILE_HANDLE AprioriFileHandle; + EFI_GUID *Apriori; + UINTN Index; + UINTN Index2; + UINTN PeimIndex; + UINTN PeimCount; + EFI_GUID *Guid; + EFI_PEI_FILE_HANDLE *TempFileHandles; + EFI_GUID *TempFileGuid; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + EFI_FV_FILE_INFO FileInfo; + + FvPpi = CoreFileHandle->FvPpi; + + // + // Walk the FV and find all the PEIMs and the Apriori file. + // + AprioriFileHandle = NULL; + Private->CurrentFvFileHandles = NULL; + Guid = NULL; + + // + // If the current FV has been scanned, directly get its cached records. + // + if (CoreFileHandle->ScanFv) { + Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles; + return; + } + + TempFileHandles = Private->TempFileHandles; + TempFileGuid = Private->TempFileGuid; + + // + // Go ahead to scan this FV, get PeimCount and cache FileHandles within it to TempFileHandles. + // + PeimCount = 0; + FileHandle = NULL; + do { + Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle); + if (!EFI_ERROR (Status)) { + if (PeimCount >= Private->TempPeimCount) { + // + // Run out of room, grow the buffer. + // + TempFileHandles = AllocatePool ( + sizeof (EFI_PEI_FILE_HANDLE) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP) + ); + ASSERT (TempFileHandles != NULL); + CopyMem ( + TempFileHandles, + Private->TempFileHandles, + sizeof (EFI_PEI_FILE_HANDLE) * Private->TempPeimCount + ); + Private->TempFileHandles = TempFileHandles; + TempFileGuid = AllocatePool ( + sizeof (EFI_GUID) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP) + ); + ASSERT (TempFileGuid != NULL); + CopyMem ( + TempFileGuid, + Private->TempFileGuid, + sizeof (EFI_GUID) * Private->TempPeimCount + ); + Private->TempFileGuid = TempFileGuid; + Private->TempPeimCount = Private->TempPeimCount + TEMP_FILE_GROWTH_STEP; + } + + TempFileHandles[PeimCount++] = FileHandle; + } + } while (!EFI_ERROR (Status)); + + DEBUG (( + DEBUG_INFO, + "%a(): Found 0x%x PEI FFS files in the %dth FV\n", + __func__, + PeimCount, + Private->CurrentPeimFvCount + )); + + if (PeimCount == 0) { + // + // No PEIM FFS file is found, set ScanFv flag and return. + // + CoreFileHandle->ScanFv = TRUE; + return; + } + + // + // Record PeimCount, allocate buffer for PeimState and FvFileHandles. + // + CoreFileHandle->PeimCount = PeimCount; + CoreFileHandle->PeimState = AllocateZeroPool (sizeof (UINT8) * PeimCount); + ASSERT (CoreFileHandle->PeimState != NULL); + CoreFileHandle->FvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PeimCount); + ASSERT (CoreFileHandle->FvFileHandles != NULL); + + // + // Get Apriori File handle + // + Private->AprioriCount = 0; + Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle); + if (!EFI_ERROR (Status) && (AprioriFileHandle != NULL)) { + // + // Read the Apriori file + // + Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **)&Apriori); + if (!EFI_ERROR (Status)) { + // + // Calculate the number of PEIMs in the Apriori file + // + Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo); + ASSERT_EFI_ERROR (Status); + Private->AprioriCount = FileInfo.BufferSize; + if (IS_SECTION2 (FileInfo.Buffer)) { + Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2); + } else { + Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER); + } + + Private->AprioriCount /= sizeof (EFI_GUID); + + for (Index = 0; Index < PeimCount; Index++) { + // + // Make an array of file name GUIDs that matches the FileHandle array so we can convert + // quickly from file name to file handle + // + Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo); + ASSERT_EFI_ERROR (Status); + CopyMem (&TempFileGuid[Index], &FileInfo.FileName, sizeof (EFI_GUID)); + } + + // + // Walk through TempFileGuid array to find out who is invalid PEIM GUID in Apriori file. + // Add available PEIMs in Apriori file into FvFileHandles array. + // + Index = 0; + for (Index2 = 0; Index2 < Private->AprioriCount; Index2++) { + Guid = ScanGuid (TempFileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2]); + if (Guid != NULL) { + PeimIndex = ((UINTN)Guid - (UINTN)&TempFileGuid[0])/sizeof (EFI_GUID); + CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[PeimIndex]; + + // + // Since we have copied the file handle we can remove it from this list. + // + TempFileHandles[PeimIndex] = NULL; + } + } + + // + // Update valid AprioriCount + // + Private->AprioriCount = Index; + + // + // Add in any PEIMs not in the Apriori file + // + for (Index2 = 0; Index2 < PeimCount; Index2++) { + if (TempFileHandles[Index2] != NULL) { + CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[Index2]; + TempFileHandles[Index2] = NULL; + } + } + + ASSERT (Index == PeimCount); + } + } else { + CopyMem (CoreFileHandle->FvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PeimCount); + } + + // + // The current FV File Handles have been cached. So that we don't have to scan the FV again. + // Instead, we can retrieve the file handles within this FV from cached records. + // + CoreFileHandle->ScanFv = TRUE; + Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles; +} + +// +// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled, +// This part of memory still need reserved on the very top of memory so that the DXE Core could +// use these memory for data initialization. This macro should be sync with the same marco +// defined in DXE Core. +// +#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000 + +/** + This function is to test if the memory range described in resource HOB is available or not. + + This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the + memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is + available or not. + + @param PrivateData Pointer to the private data passed in from caller + @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB +**/ +BOOLEAN +PeiLoadFixAddressIsMemoryRangeAvailable ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob + ) +{ + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; + BOOLEAN IsAvailable; + EFI_PEI_HOB_POINTERS Hob; + + IsAvailable = TRUE; + if ((PrivateData == NULL) || (ResourceHob == NULL)) { + return FALSE; + } + + // + // test if the memory range describe in the HOB is already allocated. + // + for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // See if this is a memory allocation HOB + // + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + MemoryHob = Hob.MemoryAllocation; + if ((MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart) && + (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) + { + IsAvailable = FALSE; + break; + } + } + } + + return IsAvailable; +} + +/** + Hook function for Loading Module at Fixed Address feature + + This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is + configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When + feature is configured as Load Modules at Fixed Offset, the function is to find the top address which is TOLM-TSEG in general. + And also the function will re-install PEI memory. + + @param PrivateData Pointer to the private data passed in from caller + +**/ +VOID +PeiLoadFixAddressHook ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + EFI_PHYSICAL_ADDRESS TopLoadingAddress; + UINT64 PeiMemorySize; + UINT64 TotalReservedMemorySize; + UINT64 MemoryRangeEnd; + EFI_PHYSICAL_ADDRESS HighAddress; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob; + EFI_PEI_HOB_POINTERS CurrentHob; + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS NextHob; + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; + + // + // Initialize Local Variables + // + CurrentResourceHob = NULL; + ResourceHob = NULL; + NextResourceHob = NULL; + HighAddress = 0; + TopLoadingAddress = 0; + MemoryRangeEnd = 0; + CurrentHob.Raw = PrivateData->HobList.Raw; + PeiMemorySize = PrivateData->PhysicalMemoryLength; + // + // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE + // then RuntimeCodePage range and Boot time code range. + // + TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber)); + TotalReservedMemorySize += EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber)); + // + // PEI memory range lies below the top reserved memory + // + TotalReservedMemorySize += PeiMemorySize; + + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber))); + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber))); + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressPeiCodePageNumber))); + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize)); + // + // Loop through the system memory typed HOB to merge the adjacent memory range + // + for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // See if this is a resource descriptor HOB + // + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + ResourceHob = Hob.ResourceDescriptor; + // + // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored. + // + if ((ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) || + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS)) + { + continue; + } + + for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) { + if (NextHob.Raw == Hob.Raw) { + continue; + } + + // + // See if this is a resource descriptor HOB + // + if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + NextResourceHob = NextHob.ResourceDescriptor; + // + // test if range described in this NextResourceHob is system memory and have the same attribute. + // Note: Here is a assumption that system memory should always be healthy even without test. + // + if ((NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && + (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)) + { + // + // See if the memory range described in ResourceHob and NextResourceHob is adjacent + // + if (((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart) && + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)) || + ((ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart) && + (ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength))) + { + MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ? + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) : (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength); + + ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ? + ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart; + + ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart); + + ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED); + // + // Delete the NextResourceHob by marking it as unused. + // + GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED; + } + } + } + } + } + } + + // + // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe + // the allocated memory range + // + for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // See if this is a memory allocation HOB + // + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + MemoryHob = Hob.MemoryAllocation; + for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) { + // + // See if this is a resource descriptor HOB + // + if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + NextResourceHob = NextHob.ResourceDescriptor; + // + // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored. + // + if ((NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) || (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS)) { + continue; + } + + // + // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB + // + if ((MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart) && + (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) + { + // + // Build separate resource HOB for this allocated range + // + if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + NextResourceHob->ResourceAttribute, + NextResourceHob->PhysicalStart, + (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart) + ); + } + + if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + NextResourceHob->ResourceAttribute, + MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength, + (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength)) + ); + } + + NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress; + NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength; + break; + } + } + } + } + } + + // + // Try to find and validate the TOP address. + // + if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0 ) { + // + // The LMFA feature is enabled as load module at fixed absolute address. + // + TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdLoadModuleAtFixAddressEnable); + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n")); + // + // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range + // + if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) { + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress)); + ASSERT (FALSE); + } + + // + // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies + // + for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // See if this is a resource descriptor HOB + // + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + ResourceHob = Hob.ResourceDescriptor; + // + // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS + // + if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS)) + { + // + // See if Top address specified by user is valid. + // + if ((ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress) && + ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) && + PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob)) + { + CurrentResourceHob = ResourceHob; + CurrentHob = Hob; + break; + } + } + } + } + + if (CurrentResourceHob != NULL) { + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress)); + TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE; + } else { + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress)); + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n")); + // + // Print the recommended Top address range. + // + for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // See if this is a resource descriptor HOB + // + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + ResourceHob = Hob.ResourceDescriptor; + // + // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS + // + if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS)) + { + // + // See if Top address specified by user is valid. + // + if ((ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob)) { + DEBUG (( + DEBUG_INFO, + "(0x%lx, 0x%lx)\n", + (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE), + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE) + )); + } + } + } + } + + // + // Assert here + // + ASSERT (FALSE); + return; + } + } else { + // + // The LMFA feature is enabled as load module at fixed offset relative to TOLM + // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG) + // + // + // Search for a tested memory region that is below MAX_ADDRESS + // + for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // See if this is a resource descriptor HOB + // + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + ResourceHob = Hob.ResourceDescriptor; + // + // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS + // + if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && + (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) && + (ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob)) + { + // + // See if this is the highest largest system memory region below MaxAddress + // + if (ResourceHob->PhysicalStart > HighAddress) { + CurrentResourceHob = ResourceHob; + CurrentHob = Hob; + HighAddress = CurrentResourceHob->PhysicalStart; + } + } + } + } + + if (CurrentResourceHob == NULL) { + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n")); + // + // Assert here + // + ASSERT (FALSE); + return; + } else { + TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength; + } + } + + if (CurrentResourceHob != NULL) { + // + // rebuild resource HOB for PEI memory and reserved memory + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + (TopLoadingAddress - TotalReservedMemorySize), + TotalReservedMemorySize + ); + // + // rebuild resource for the remain memory if necessary + // + if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + CurrentResourceHob->PhysicalStart, + (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart) + ); + } + + if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + TopLoadingAddress, + (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress) + ); + } + + // + // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt. + // + GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED; + } + + // + // Cache the top address for Loading Module at Fixed Address feature + // + PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE; + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress)); + // + // reinstall the PEI memory relative to TopLoadingAddress + // + PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize; + PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize; +} + +/** + This routine is invoked in switch stack as PeiCore Entry. + + @param SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + @param Private Pointer to old core data that is used to initialize the + core's data areas. +**/ +VOID +EFIAPI +PeiCoreEntry ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) +{ + // + // Entry PEI Phase 2 + // + PeiCore (SecCoreData, NULL, Private); +} + +/** + Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE. + + @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + @param[in] Private Pointer to the private data passed in from caller. + +**/ +VOID +PeiCheckAndSwitchStack ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) +{ + VOID *LoadFixPeiCodeBegin; + EFI_STATUS Status; + CONST EFI_PEI_SERVICES **PeiServices; + UINT64 NewStackSize; + EFI_PHYSICAL_ADDRESS TopOfOldStack; + EFI_PHYSICAL_ADDRESS TopOfNewStack; + UINTN StackOffset; + BOOLEAN StackOffsetPositive; + EFI_PHYSICAL_ADDRESS TemporaryRamBase; + UINTN TemporaryRamSize; + UINTN TemporaryStackSize; + VOID *TemporaryStackBase; + UINTN PeiTemporaryRamSize; + VOID *PeiTemporaryRamBase; + EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi; + EFI_PHYSICAL_ADDRESS BaseOfNewHeap; + EFI_PHYSICAL_ADDRESS HoleMemBase; + UINTN HoleMemSize; + UINTN HeapTemporaryRamSize; + EFI_PHYSICAL_ADDRESS TempBase1; + UINTN TempSize1; + EFI_PHYSICAL_ADDRESS TempBase2; + UINTN TempSize2; + UINTN Index; + + PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps; + + if (Private->SwitchStackSignal) { + // + // Before switch stack from temporary memory to permanent memory, calculate the heap and stack + // usage in temporary memory for debugging. + // + DEBUG_CODE_BEGIN (); + UINT32 *StackPointer; + EFI_PEI_HOB_POINTERS Hob; + + for ( StackPointer = (UINT32 *)SecCoreData->StackBase; + (StackPointer < (UINT32 *)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \ + && (*StackPointer == PcdGet32 (PcdInitValueInTempStack)); + StackPointer++) + { + } + + DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize)); + DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize)); + DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize)); + DEBUG (( + DEBUG_INFO, + " temporary memory stack ever used: %d bytes.\n", + (UINT32)(SecCoreData->StackSize - ((UINTN)StackPointer - (UINTN)SecCoreData->StackBase)) + )); + DEBUG (( + DEBUG_INFO, + " temporary memory heap used for HobList: %d bytes.\n", + (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw) + )); + DEBUG (( + DEBUG_INFO, + " temporary memory heap occupied by memory pages: %d bytes.\n", + (UINT32)(UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - Private->HobList.HandoffInformationTable->EfiFreeMemoryTop) + )); + for (Hob.Raw = Private->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + DEBUG (( + DEBUG_INFO, + "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \ + Hob.MemoryAllocation->AllocDescriptor.MemoryType, \ + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, \ + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1 + )); + } + } + + DEBUG_CODE_END (); + + if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // Loading Module at Fixed Address is enabled + // + PeiLoadFixAddressHook (Private); + + // + // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range. + // + LoadFixPeiCodeBegin = AllocatePages ((UINTN)PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)); + DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)(UINTN)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32 (PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE))); + } + + // + // Reserve the size of new stack at bottom of physical memory + // + // The size of new stack in permanent memory must be the same size + // or larger than the size of old stack in temporary memory. + // But if new stack is smaller than the size of old stack, we also reserve + // the size of old stack at bottom of permanent memory. + // + NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1); + NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE); + NewStackSize = MIN (PcdGet32 (PcdPeiCoreMaxPeiStackSize), NewStackSize); + DEBUG ((DEBUG_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize)); + ASSERT (NewStackSize >= SecCoreData->StackSize); + + // + // Calculate stack offset and heap offset between temporary memory and new permanent + // memory separately. + // + TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize; + TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize; + if (TopOfNewStack >= TopOfOldStack) { + StackOffsetPositive = TRUE; + StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack); + } else { + StackOffsetPositive = FALSE; + StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack); + } + + Private->StackOffsetPositive = StackOffsetPositive; + Private->StackOffset = StackOffset; + + // + // Build Stack HOB that describes the permanent memory stack + // + DEBUG ((DEBUG_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize)); + BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize); + + // + // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address + // + TemporaryRamBase = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase; + TemporaryRamSize = SecCoreData->TemporaryRamSize; + TemporaryStackSize = SecCoreData->StackSize; + TemporaryStackBase = SecCoreData->StackBase; + PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize; + PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase; + + // + // TemporaryRamSupportPpi is produced by platform's SEC + // + Status = PeiServicesLocatePpi ( + &gEfiTemporaryRamSupportPpiGuid, + 0, + NULL, + (VOID **)&TemporaryRamSupportPpi + ); + if (!EFI_ERROR (Status)) { + // + // Heap Offset + // + BaseOfNewHeap = TopOfNewStack; + if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) { + Private->HeapOffsetPositive = TRUE; + Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase); + } else { + Private->HeapOffsetPositive = FALSE; + Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap); + } + + DEBUG ((DEBUG_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64)Private->HeapOffset, (UINT64)Private->StackOffset)); + + // + // Calculate new HandOffTable and PrivateData address in permanent memory's stack + // + if (StackOffsetPositive) { + SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset); + Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset); + } else { + SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset); + Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset); + } + + // + // Temporary Ram Support PPI is provided by platform, it will copy + // temporary memory to permanent memory and do stack switching. + // After invoking Temporary Ram Support PPI, the following code's + // stack is in permanent memory. + // + TemporaryRamSupportPpi->TemporaryRamMigration ( + PeiServices, + TemporaryRamBase, + (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize), + TemporaryRamSize + ); + + // + // Migrate memory pages allocated in pre-memory phase. + // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration() + // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration(). + // + MigrateMemoryPages (Private, TRUE); + + // + // Entry PEI Phase 2 + // + PeiCore (SecCoreData, NULL, Private); + } else { + // + // Migrate memory pages allocated in pre-memory phase. + // + MigrateMemoryPages (Private, FALSE); + + // + // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM. + // + MigratePeiServicesTablePointer (); + + // + // Heap Offset + // + BaseOfNewHeap = TopOfNewStack; + HoleMemBase = TopOfNewStack; + HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize; + if (HoleMemSize != 0) { + // + // Make sure HOB List start address is 8 byte alignment. + // + BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8); + } + + if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) { + Private->HeapOffsetPositive = TRUE; + Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase); + } else { + Private->HeapOffsetPositive = FALSE; + Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap); + } + + DEBUG ((DEBUG_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64)Private->HeapOffset, (UINT64)Private->StackOffset)); + + // + // Migrate Heap + // + HeapTemporaryRamSize = (UINTN)(Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom); + ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop); + CopyMem ((UINT8 *)(UINTN)BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize); + + // + // Migrate Stack + // + CopyMem ((UINT8 *)(UINTN)(TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize); + + // + // Copy Hole Range Data + // + if (HoleMemSize != 0) { + // + // Prepare Hole + // + if (PeiTemporaryRamBase < TemporaryStackBase) { + TempBase1 = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiTemporaryRamBase; + TempSize1 = PeiTemporaryRamSize; + TempBase2 = (EFI_PHYSICAL_ADDRESS)(UINTN)TemporaryStackBase; + TempSize2 = TemporaryStackSize; + } else { + TempBase1 = (EFI_PHYSICAL_ADDRESS)(UINTN)TemporaryStackBase; + TempSize1 = TemporaryStackSize; + TempBase2 = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiTemporaryRamBase; + TempSize2 = PeiTemporaryRamSize; + } + + if (TemporaryRamBase < TempBase1) { + Private->HoleData[0].Base = TemporaryRamBase; + Private->HoleData[0].Size = (UINTN)(TempBase1 - TemporaryRamBase); + } + + if (TempBase1 + TempSize1 < TempBase2) { + Private->HoleData[1].Base = TempBase1 + TempSize1; + Private->HoleData[1].Size = (UINTN)(TempBase2 - TempBase1 - TempSize1); + } + + if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) { + Private->HoleData[2].Base = TempBase2 + TempSize2; + Private->HoleData[2].Size = (UINTN)(TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2); + } + + // + // Copy Hole Range data. + // + for (Index = 0; Index < HOLE_MAX_NUMBER; Index++) { + if (Private->HoleData[Index].Size > 0) { + if (HoleMemBase > Private->HoleData[Index].Base) { + Private->HoleData[Index].OffsetPositive = TRUE; + Private->HoleData[Index].Offset = (UINTN)(HoleMemBase - Private->HoleData[Index].Base); + } else { + Private->HoleData[Index].OffsetPositive = FALSE; + Private->HoleData[Index].Offset = (UINTN)(Private->HoleData[Index].Base - HoleMemBase); + } + + CopyMem ((VOID *)(UINTN)HoleMemBase, (VOID *)(UINTN)Private->HoleData[Index].Base, Private->HoleData[Index].Size); + HoleMemBase = HoleMemBase + Private->HoleData[Index].Size; + } + } + } + + // + // Switch new stack + // + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry, + (VOID *)SecCoreData, + (VOID *)Private, + (VOID *)(UINTN)TopOfNewStack + ); + } + + // + // Code should not come here + // + ASSERT (FALSE); + } +} + +/** + Migrate a PEIM from temporary RAM to permanent memory. + + @param PeimFileHandle Pointer to the FFS file header of the image. + @param MigratedFileHandle Pointer to the FFS file header of the migrated image. + + @retval EFI_SUCCESS Successfully migrated the PEIM to permanent memory. + +**/ +EFI_STATUS +EFIAPI +MigratePeim ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN EFI_PEI_FILE_HANDLE MigratedFileHandle + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FileHeader; + VOID *Pe32Data; + VOID *ImageAddress; + CHAR8 *AsciiString; + UINTN Index; + + Status = EFI_SUCCESS; + + FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + ASSERT (!IS_FFS_FILE2 (FileHeader)); + + ImageAddress = NULL; + PeiGetPe32Data (MigratedFileHandle, &ImageAddress); + if (ImageAddress != NULL) { + DEBUG_CODE_BEGIN (); + AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress); + for (Index = 0; AsciiString[Index] != 0; Index++) { + if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) { + AsciiString = AsciiString + Index + 1; + Index = 0; + } else if (AsciiString[Index] == '.') { + AsciiString[Index] = 0; + } + } + + DEBUG ((DEBUG_VERBOSE, "%a", AsciiString)); + DEBUG_CODE_END (); + + Pe32Data = (VOID *)((UINTN)ImageAddress - (UINTN)MigratedFileHandle + (UINTN)FileHandle); + Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} + +/** + Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory. + + @param OrgFvHandle Address of FV handle in temporary memory. + @param FvHandle Address of FV handle in permanent memory. + @param FvSize Size of the FV. + +**/ +VOID +ConvertStatusCodeCallbacks ( + IN UINTN OrgFvHandle, + IN UINTN FvHandle, + IN UINTN FvSize + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINTN *NumberOfEntries; + UINTN *CallbackEntry; + UINTN Index; + + Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid); + while (Hob.Raw != NULL) { + NumberOfEntries = GET_GUID_HOB_DATA (Hob); + CallbackEntry = NumberOfEntries + 1; + for (Index = 0; Index < *NumberOfEntries; Index++) { + if (((VOID *)CallbackEntry[Index]) != NULL) { + if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) { + DEBUG (( + DEBUG_INFO, + "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ", + (UINT64)Index, + (sizeof CallbackEntry[Index]) * 2, + (UINT64)CallbackEntry[Index] + )); + if (OrgFvHandle > FvHandle) { + CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle); + } else { + CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle); + } + + DEBUG (( + DEBUG_INFO, + "0x%0*Lx\n", + (sizeof CallbackEntry[Index]) * 2, + (UINT64)CallbackEntry[Index] + )); + } + } + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw); + } +} + +/** + Migrates PEIMs in the given firmware volume. + + @param Private Pointer to the PeiCore's private data structure. + @param FvIndex The firmware volume index to migrate. + @param OrgFvHandle The handle to the firmware volume in temporary memory. + @param FvHandle The handle to the firmware volume in permanent memory. + + @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully + @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid. + +**/ +EFI_STATUS +EFIAPI +MigratePeimsInFv ( + IN PEI_CORE_INSTANCE *Private, + IN UINTN FvIndex, + IN UINTN OrgFvHandle, + IN UINTN FvHandle + ) +{ + EFI_STATUS Status; + volatile UINTN FileIndex; + EFI_PEI_FILE_HANDLE MigratedFileHandle; + EFI_PEI_FILE_HANDLE FileHandle; + + if ((Private == NULL) || (FvIndex >= Private->FvCount)) { + return EFI_INVALID_PARAMETER; + } + + if (Private->Fv[FvIndex].ScanFv) { + for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) { + if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) { + FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex]; + + MigratedFileHandle = (EFI_PEI_FILE_HANDLE)((UINTN)FileHandle - OrgFvHandle + FvHandle); + + DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex)); + Status = MigratePeim (FileHandle, MigratedFileHandle); + DEBUG ((DEBUG_VERBOSE, "\n")); + ASSERT_EFI_ERROR (Status); + + if (!EFI_ERROR (Status)) { + Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle; + if (FvIndex == Private->CurrentPeimFvCount) { + Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle; + } + } + } + } + } + + return EFI_SUCCESS; +} + +/** + Migrate FVs out of temporary RAM before the cache is flushed. + + @param Private PeiCore's private data structure + @param SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + + @retval EFI_SUCCESS Successfully migrated installed FVs from temporary RAM to permanent memory. + @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages. + +**/ +EFI_STATUS +EFIAPI +EvacuateTempRam ( + IN PEI_CORE_INSTANCE *Private, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +{ + EFI_STATUS Status; + volatile UINTN FvIndex; + volatile UINTN FvChildIndex; + UINTN ChildFvOffset; + EFI_PHYSICAL_ADDRESS FvHeaderAddress; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader; + EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader; + EFI_FIRMWARE_VOLUME_HEADER *RawDataFvHeader; + EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader; + + PEI_CORE_FV_HANDLE PeiCoreFvHandle; + EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi; + EFI_PEI_HOB_POINTERS Hob; + EDKII_MIGRATION_INFO *MigrationInfo; + TO_MIGRATE_FV_INFO *ToMigrateFvInfo; + UINT32 FvMigrationFlags; + EDKII_MIGRATED_FV_INFO MigratedFvInfo; + UINTN Index; + + ASSERT (Private->PeiMemoryInstalled); + + DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n")); + + // + // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory. + // + Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **)&Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **)&PeiCoreFvLocationPpi); + if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) { + PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)PeiCoreFvLocationPpi->PeiCoreFvLocation; + } else { + PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)SecCoreData->BootFirmwareVolumeBase; + } + + for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) { + if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) { + CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE)); + break; + } + } + + Status = EFI_SUCCESS; + + ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle); + + Hob.Raw = GetFirstGuidHob (&gEdkiiMigrationInfoGuid); + if (Hob.Raw != NULL) { + MigrationInfo = GET_GUID_HOB_DATA (Hob); + } else { + MigrationInfo = NULL; + } + + for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) { + FvHeader = Private->Fv[FvIndex].FvHeader; + ASSERT (FvHeader != NULL); + ASSERT (FvIndex < Private->FvCount); + + DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN)FvHeader)); + if ( + !( + ((EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader >= Private->PhysicalMemoryBegin) && + (((EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop) + ) + ) + { + if ((MigrationInfo == NULL) || (MigrationInfo->MigrateAll == TRUE)) { + // + // Migrate all FVs and copy raw data + // + FvMigrationFlags = FLAGS_FV_RAW_DATA_COPY; + } else { + for (Index = 0; Index < MigrationInfo->ToMigrateFvCount; Index++) { + ToMigrateFvInfo = ((TO_MIGRATE_FV_INFO *)(MigrationInfo + 1)) + Index; + if (ToMigrateFvInfo->FvOrgBaseOnTempRam == (UINT32)(UINTN)FvHeader) { + // + // This FV is to migrate + // + FvMigrationFlags = ToMigrateFvInfo->FvMigrationFlags; + break; + } + } + + if (Index == MigrationInfo->ToMigrateFvCount) { + // + // This FV is not expected to migrate + // + continue; + } + } + + // + // Allocate pages to save the rebased PEIMs, the PEIMs will get dispatched later. + // + Status = PeiServicesAllocatePages ( + EfiBootServicesCode, + EFI_SIZE_TO_PAGES ((UINTN)FvHeader->FvLength), + &FvHeaderAddress + ); + ASSERT_EFI_ERROR (Status); + MigratedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHeaderAddress; + CopyMem (MigratedFvHeader, FvHeader, (UINTN)FvHeader->FvLength); + + DEBUG (( + DEBUG_VERBOSE, + " Migrating FV[%d] from 0x%08X to 0x%08X\n", + FvIndex, + (UINTN)FvHeader, + (UINTN)MigratedFvHeader + )); + + // + // Create hob to save MigratedFvInfo, this hob will only be produced when + // Migration feature PCD PcdMigrateTemporaryRamFirmwareVolumes is set to TRUE. + // + MigratedFvInfo.FvOrgBase = (UINT32)(UINTN)FvHeader; + MigratedFvInfo.FvNewBase = (UINT32)(UINTN)MigratedFvHeader; + MigratedFvInfo.FvDataBase = 0; + MigratedFvInfo.FvLength = (UINT32)(UINTN)FvHeader->FvLength; + + // + // When FLAGS_FV_RAW_DATA_COPY bit is set, copy the context to the raw pages and + // reset raw data base address in MigratedFvInfo hob. + // + if ((FvMigrationFlags & FLAGS_FV_RAW_DATA_COPY) == FLAGS_FV_RAW_DATA_COPY) { + // + // Allocate pages to save the raw PEIMs + // + Status = PeiServicesAllocatePages ( + EfiBootServicesCode, + EFI_SIZE_TO_PAGES ((UINTN)FvHeader->FvLength), + &FvHeaderAddress + ); + ASSERT_EFI_ERROR (Status); + RawDataFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHeaderAddress; + CopyMem (RawDataFvHeader, FvHeader, (UINTN)FvHeader->FvLength); + MigratedFvInfo.FvDataBase = (UINT32)(UINTN)RawDataFvHeader; + } + + BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo)); + + // + // Migrate any children for this FV now + // + for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) { + ChildFvHeader = Private->Fv[FvChildIndex].FvHeader; + if ( + ((UINTN)ChildFvHeader > (UINTN)FvHeader) && + (((UINTN)ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN)FvHeader) + FvHeader->FvLength) + ) + { + DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex)); + ChildFvOffset = (UINTN)ChildFvHeader - (UINTN)FvHeader; + DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset)); + MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)MigratedFvHeader + ChildFvOffset); + Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader; + Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE)MigratedChildFvHeader; + DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN)MigratedChildFvHeader)); + + Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN)ChildFvHeader, (UINTN)MigratedChildFvHeader); + ASSERT_EFI_ERROR (Status); + + ConvertPpiPointersFv ( + Private, + (UINTN)ChildFvHeader, + (UINTN)MigratedChildFvHeader, + (UINTN)ChildFvHeader->FvLength - 1 + ); + + ConvertStatusCodeCallbacks ( + (UINTN)ChildFvHeader, + (UINTN)MigratedChildFvHeader, + (UINTN)ChildFvHeader->FvLength - 1 + ); + + ConvertFvHob (Private, (UINTN)ChildFvHeader, (UINTN)MigratedChildFvHeader); + } + } + + Private->Fv[FvIndex].FvHeader = MigratedFvHeader; + Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE)MigratedFvHeader; + + Status = MigratePeimsInFv (Private, FvIndex, (UINTN)FvHeader, (UINTN)MigratedFvHeader); + ASSERT_EFI_ERROR (Status); + + ConvertPpiPointersFv ( + Private, + (UINTN)FvHeader, + (UINTN)MigratedFvHeader, + (UINTN)FvHeader->FvLength - 1 + ); + + ConvertStatusCodeCallbacks ( + (UINTN)FvHeader, + (UINTN)MigratedFvHeader, + (UINTN)FvHeader->FvLength - 1 + ); + + ConvertFvHob (Private, (UINTN)FvHeader, (UINTN)MigratedFvHeader); + } + } + + return Status; +} + +/** + Conduct PEIM dispatch. + + @param SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + @param Private Pointer to the private data passed in from caller + +**/ +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *Private + ) +{ + EFI_STATUS Status; + UINT32 Index1; + UINT32 Index2; + CONST EFI_PEI_SERVICES **PeiServices; + EFI_PEI_FILE_HANDLE PeimFileHandle; + UINTN FvCount; + UINTN PeimCount; + UINT32 AuthenticationState; + EFI_PHYSICAL_ADDRESS EntryPoint; + EFI_PEIM_ENTRY_POINT2 PeimEntryPoint; + UINTN SaveCurrentPeimCount; + UINTN SaveCurrentFvCount; + EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; + EFI_FV_FILE_INFO FvFileInfo; + PEI_CORE_FV_HANDLE *CoreFvHandle; + + PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps; + PeimEntryPoint = NULL; + PeimFileHandle = NULL; + EntryPoint = 0; + + if ((Private->PeiMemoryInstalled) && + (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) || + PcdGetBool (PcdShadowPeimOnS3Boot)) + ) + { + // + // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile + // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE. + // + SaveCurrentPeimCount = Private->CurrentPeimCount; + SaveCurrentFvCount = Private->CurrentPeimFvCount; + SaveCurrentFileHandle = Private->CurrentFileHandle; + + for (Index1 = 0; Index1 < Private->FvCount; Index1++) { + for (Index2 = 0; Index2 < Private->Fv[Index1].PeimCount; Index2++) { + if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISTER_FOR_SHADOW) { + PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2]; + Private->CurrentFileHandle = PeimFileHandle; + Private->CurrentPeimFvCount = Index1; + Private->CurrentPeimCount = Index2; + Status = PeiLoadImage ( + (CONST EFI_PEI_SERVICES **)&Private->Ps, + PeimFileHandle, + PEIM_STATE_REGISTER_FOR_SHADOW, + &EntryPoint, + &AuthenticationState + ); + if (Status == EFI_SUCCESS) { + // + // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[Index1].PeimState[Index2]++; + // + // Call the PEIM entry point + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint; + + PERF_START_IMAGE_BEGIN (PeimFileHandle); + PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)&Private->Ps); + PERF_START_IMAGE_END (PeimFileHandle); + } + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessDispatchNotifyList (Private); + } + } + } + + Private->CurrentFileHandle = SaveCurrentFileHandle; + Private->CurrentPeimFvCount = SaveCurrentFvCount; + Private->CurrentPeimCount = SaveCurrentPeimCount; + } + + // + // This is the main dispatch loop. It will search known FVs for PEIMs and + // attempt to dispatch them. If any PEIM gets dispatched through a single + // pass of the dispatcher, it will start over from the BFV again to see + // if any new PEIMs dependencies got satisfied. With a well ordered + // FV where PEIMs are found in the order their dependencies are also + // satisfied, this dispatcher should run only once. + // + do { + // + // In case that reenter PeiCore happens, the last pass record is still available. + // + if (!Private->PeimDispatcherReenter) { + Private->PeimNeedingDispatch = FALSE; + Private->PeimDispatchOnThisPass = FALSE; + } else { + Private->PeimDispatcherReenter = FALSE; + } + + for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) { + CoreFvHandle = FindNextCoreFvHandle (Private, FvCount); + ASSERT (CoreFvHandle != NULL); + + // + // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it. + // + if (CoreFvHandle->FvPpi == NULL) { + continue; + } + + Private->CurrentPeimFvCount = FvCount; + + if (Private->CurrentPeimCount == 0) { + // + // When going through each FV, at first, search Apriori file to + // reorder all PEIMs to ensure the PEIMs in Apriori file to get + // dispatch at first. + // + DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle); + } + + // + // Start to dispatch all modules within the current FV. + // + for (PeimCount = Private->CurrentPeimCount; + PeimCount < Private->Fv[FvCount].PeimCount; + PeimCount++) + { + Private->CurrentPeimCount = PeimCount; + PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount]; + + if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) { + if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) { + Private->PeimNeedingDispatch = TRUE; + } else { + Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo); + ASSERT_EFI_ERROR (Status); + if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // For FV type file, Produce new FvInfo PPI and FV HOB + // + Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle); + if (Status == EFI_SUCCESS) { + // + // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED + // + Private->Fv[FvCount].PeimState[PeimCount]++; + Private->PeimDispatchOnThisPass = TRUE; + } else { + // + // The related GuidedSectionExtraction/Decompress PPI for the + // encapsulated FV image section may be installed in the rest + // of this do-while loop, so need to make another pass. + // + Private->PeimNeedingDispatch = TRUE; + } + } else { + // + // For PEIM driver, Load its entry point + // + Status = PeiLoadImage ( + PeiServices, + PeimFileHandle, + PEIM_STATE_NOT_DISPATCHED, + &EntryPoint, + &AuthenticationState + ); + if (Status == EFI_SUCCESS) { + // + // The PEIM has its dependencies satisfied, and its entry point + // has been found, so invoke it. + // + PERF_START_IMAGE_BEGIN (PeimFileHandle); + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN), + (VOID *)(&PeimFileHandle), + sizeof (PeimFileHandle) + ); + + Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState); + if (Status != EFI_SECURITY_VIOLATION) { + // + // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED + // + Private->Fv[FvCount].PeimState[PeimCount]++; + // + // Call the PEIM entry point for PEIM driver + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint; + PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)PeiServices); + Private->PeimDispatchOnThisPass = TRUE; + } else { + // + // The related GuidedSectionExtraction PPI for the + // signed PEIM image section may be installed in the rest + // of this do-while loop, so need to make another pass. + // + Private->PeimNeedingDispatch = TRUE; + } + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END), + (VOID *)(&PeimFileHandle), + sizeof (PeimFileHandle) + ); + PERF_START_IMAGE_END (PeimFileHandle); + } + } + + PeiCheckAndSwitchStack (SecCoreData, Private); + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessDispatchNotifyList (Private); + + // + // Recheck SwitchStackSignal after ProcessDispatchNotifyList() + // in case PeiInstallPeiMemory() is done in a callback with + // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH. + // + PeiCheckAndSwitchStack (SecCoreData, Private); + + if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \ + (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) || + PcdGetBool (PcdShadowPeimOnS3Boot)) + ) + { + // + // If memory is available we shadow images by default for performance reasons. + // We call the entry point a 2nd time so the module knows it's shadowed. + // + // PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); + if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) && + !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) + { + // + // Load PEIM into Memory for Register for shadow PEIM. + // + Status = PeiLoadImage ( + PeiServices, + PeimFileHandle, + PEIM_STATE_REGISTER_FOR_SHADOW, + &EntryPoint, + &AuthenticationState + ); + if (Status == EFI_SUCCESS) { + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint; + } + } + + ASSERT (PeimEntryPoint != NULL); + PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)PeiServices); + // PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + + // + // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[FvCount].PeimState[PeimCount]++; + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessDispatchNotifyList (Private); + } + } + } + } + + // + // Before walking through the next FV, we should set them to NULL/0 to + // start at the beginning of the next FV. + // + Private->CurrentFileHandle = NULL; + Private->CurrentPeimCount = 0; + Private->CurrentFvFileHandles = NULL; + Private->AprioriCount = 0; + } + + // + // Before making another pass, we should set it to 0 to + // go through all the FVs. + // + Private->CurrentPeimFvCount = 0; + + // + // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get + // dispatched. So we need to make another pass + // + // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this + // pass. If we did not dispatch a PEIM/FV there is no point in trying again + // as it will fail the next time too (nothing has changed). + // + } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass); +} + +/** + Initialize the Dispatcher's data members + + @param PrivateData PeiCore's private data structure + @param OldCoreData Old data from SecCore + NULL if being run in non-permanent memory mode. + @param SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + + @return None. + +**/ +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +{ + if (OldCoreData == NULL) { + PrivateData->PeimDispatcherReenter = FALSE; + PeiInitializeFv (PrivateData, SecCoreData); + } else { + PeiReinitializeFv (PrivateData); + } + + return; +} + +/** + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + + + @param Private PeiCore's private data structure + @param FileHandle PEIM's file handle + @param PeimCount Peim count in all dispatched PEIMs. + + @retval TRUE Can be dispatched + @retval FALSE Cannot be dispatched + +**/ +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ) +{ + EFI_STATUS Status; + VOID *DepexData; + EFI_FV_FILE_INFO FileInfo; + + Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n")); + } else { + DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName)); + } + + if (PeimCount < Private->AprioriCount) { + // + // If it's in the Apriori file then we set DEPEX to TRUE + // + DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n")); + return TRUE; + } + + // + // Depex section not in the encapsulated section. + // + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_PEI_DEPEX, + FileHandle, + (VOID **)&DepexData + ); + + if (EFI_ERROR (Status)) { + // + // If there is no DEPEX, assume the module can be executed + // + DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n")); + return TRUE; + } + + // + // Evaluate a given DEPEX + // + return PeimDispatchReadiness (&Private->Ps, DepexData); +} + +/** + This routine enables a PEIM to register itself for shadow when the PEI Foundation + discovers permanent memory. + + @param FileHandle File handle of a PEIM. + + @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself. + @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself. + @retval EFI_SUCCESS Successfully to register itself. + +**/ +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +{ + PEI_CORE_INSTANCE *Private; + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + + if (Private->CurrentFileHandle != FileHandle) { + // + // The FileHandle must be for the current PEIM + // + return EFI_NOT_FOUND; + } + + if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISTER_FOR_SHADOW) { + // + // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started + // + return EFI_ALREADY_STARTED; + } + + Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISTER_FOR_SHADOW; + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c index f7cc94c6eb..ec127cfbf3 100644 --- a/MdeModulePkg/Core/Pei/FwVol/FwVol.c +++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c @@ -1,2465 +1,2465 @@ -/** @file
- Pei Core Firmware File System service routines.
-
-Copyright (c) 2015 HP Development Company, L.P.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "FwVol.h"
-
-EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList[] = {
- {
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
- &gEfiPeiFirmwareVolumeInfoPpiGuid,
- FirmwareVolumeInfoPpiNotifyCallback
- },
- {
- (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiPeiFirmwareVolumeInfo2PpiGuid,
- FirmwareVolumeInfoPpiNotifyCallback
- }
-};
-
-PEI_FW_VOL_INSTANCE mPeiFfs2FwVol = {
- PEI_FW_VOL_SIGNATURE,
- FALSE,
- {
- PeiFfsFvPpiProcessVolume,
- PeiFfsFvPpiFindFileByType,
- PeiFfsFvPpiFindFileByName,
- PeiFfsFvPpiGetFileInfo,
- PeiFfsFvPpiGetVolumeInfo,
- PeiFfsFvPpiFindSectionByType,
- PeiFfsFvPpiGetFileInfo2,
- PeiFfsFvPpiFindSectionByType2,
- EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE,
- EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION
- }
-};
-
-PEI_FW_VOL_INSTANCE mPeiFfs3FwVol = {
- PEI_FW_VOL_SIGNATURE,
- TRUE,
- {
- PeiFfsFvPpiProcessVolume,
- PeiFfsFvPpiFindFileByType,
- PeiFfsFvPpiFindFileByName,
- PeiFfsFvPpiGetFileInfo,
- PeiFfsFvPpiGetVolumeInfo,
- PeiFfsFvPpiFindSectionByType,
- PeiFfsFvPpiGetFileInfo2,
- PeiFfsFvPpiFindSectionByType2,
- EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE,
- EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION
- }
-};
-
-EFI_PEI_PPI_DESCRIPTOR mPeiFfs2FvPpiList = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiFirmwareFileSystem2Guid,
- &mPeiFfs2FwVol.Fv
-};
-
-EFI_PEI_PPI_DESCRIPTOR mPeiFfs3FvPpiList = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiFirmwareFileSystem3Guid,
- &mPeiFfs3FwVol.Fv
-};
-
-/**
-Required Alignment Alignment Value in FFS FFS_ATTRIB_DATA_ALIGNMENT2 Alignment Value in
-(bytes) Attributes Field in FFS Attributes Field Firmware Volume Interfaces
-1 0 0 0
-16 1 0 4
-128 2 0 7
-512 3 0 9
-1 KB 4 0 10
-4 KB 5 0 12
-32 KB 6 0 15
-64 KB 7 0 16
-128 KB 0 1 17
-256 KB 1 1 18
-512 KB 2 1 19
-1 MB 3 1 20
-2 MB 4 1 21
-4 MB 5 1 22
-8 MB 6 1 23
-16 MB 7 1 24
-**/
-UINT8 mFvAttributes[] = { 0, 4, 7, 9, 10, 12, 15, 16 };
-UINT8 mFvAttributes2[] = { 17, 18, 19, 20, 21, 22, 23, 24 };
-
-/**
- Convert the FFS File Attributes to FV File Attributes
-
- @param FfsAttributes The attributes of UINT8 type.
-
- @return The attributes of EFI_FV_FILE_ATTRIBUTES
-
-**/
-EFI_FV_FILE_ATTRIBUTES
-FfsAttributes2FvFileAttributes (
- IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
- )
-{
- UINT8 DataAlignment;
- EFI_FV_FILE_ATTRIBUTES FileAttribute;
-
- DataAlignment = (UINT8)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
- ASSERT (DataAlignment < 8);
-
- if ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT_2) != 0) {
- FileAttribute = (EFI_FV_FILE_ATTRIBUTES)mFvAttributes2[DataAlignment];
- } else {
- FileAttribute = (EFI_FV_FILE_ATTRIBUTES)mFvAttributes[DataAlignment];
- }
-
- if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) {
- FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED;
- }
-
- return FileAttribute;
-}
-
-/**
- Returns the file state set by the highest zero bit in the State field
-
- @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
- in the Attributes field.
- @param FfsHeader Pointer to FFS File Header.
-
- @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit
- in the header State field.
-**/
-EFI_FFS_FILE_STATE
-GetFileState (
- IN UINT8 ErasePolarity,
- IN EFI_FFS_FILE_HEADER *FfsHeader
- )
-{
- EFI_FFS_FILE_STATE FileState;
- EFI_FFS_FILE_STATE HighestBit;
-
- FileState = FfsHeader->State;
-
- if (ErasePolarity != 0) {
- FileState = (EFI_FFS_FILE_STATE) ~FileState;
- }
-
- //
- // Get file state set by its highest none zero bit.
- //
- HighestBit = 0x80;
- while (HighestBit != 0 && (HighestBit & FileState) == 0) {
- HighestBit >>= 1;
- }
-
- return HighestBit;
-}
-
-/**
- Calculates the checksum of the header of a file.
-
- @param FileHeader Pointer to FFS File Header.
-
- @return Checksum of the header.
- Zero means the header is good.
- Non-zero means the header is bad.
-**/
-UINT8
-CalculateHeaderChecksum (
- IN EFI_FFS_FILE_HEADER *FileHeader
- )
-{
- EFI_FFS_FILE_HEADER2 TestFileHeader;
-
- if (IS_FFS_FILE2 (FileHeader)) {
- CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER2));
- //
- // Ignore State and File field in FFS header.
- //
- TestFileHeader.State = 0;
- TestFileHeader.IntegrityCheck.Checksum.File = 0;
-
- return CalculateSum8 ((CONST UINT8 *)&TestFileHeader, sizeof (EFI_FFS_FILE_HEADER2));
- } else {
- CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER));
- //
- // Ignore State and File field in FFS header.
- //
- TestFileHeader.State = 0;
- TestFileHeader.IntegrityCheck.Checksum.File = 0;
-
- return CalculateSum8 ((CONST UINT8 *)&TestFileHeader, sizeof (EFI_FFS_FILE_HEADER));
- }
-}
-
-/**
- Find FV handler according to FileHandle in that FV.
-
- @param FileHandle Handle of file image
-
- @return Pointer to instance of PEI_CORE_FV_HANDLE.
-**/
-PEI_CORE_FV_HANDLE *
-FileHandleToVolume (
- IN EFI_PEI_FILE_HANDLE FileHandle
- )
-{
- UINTN Index;
- PEI_CORE_INSTANCE *PrivateData;
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
- UINTN BestIndex;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
- BestIndex = PrivateData->FvCount;
-
- //
- // Find the best matched FV image that includes this FileHandle.
- // FV may include the child FV, and they are in the same continuous space.
- // If FileHandle is from the child FV, the updated logic can find its matched FV.
- //
- for (Index = 0; Index < PrivateData->FvCount; Index++) {
- FwVolHeader = PrivateData->Fv[Index].FvHeader;
- if (((UINT64)(UINTN)FileHandle > (UINT64)(UINTN)FwVolHeader) && \
- ((UINT64)(UINTN)FileHandle <= ((UINT64)(UINTN)FwVolHeader + FwVolHeader->FvLength - 1)))
- {
- if (BestIndex == PrivateData->FvCount) {
- BestIndex = Index;
- } else {
- if ((UINT64)(UINTN)PrivateData->Fv[BestIndex].FvHeader < (UINT64)(UINTN)FwVolHeader) {
- BestIndex = Index;
- }
- }
- }
- }
-
- if (BestIndex < PrivateData->FvCount) {
- return &PrivateData->Fv[BestIndex];
- }
-
- return NULL;
-}
-
-/**
- Given the input file pointer, search for the first matching file in the
- FFS volume as defined by SearchType. The search starts from FileHeader inside
- the Firmware Volume defined by FwVolHeader.
- If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.
- If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
- the first PEIM, or COMBINED PEIM or FV file type FFS file will return.
-
- @param FvHandle Pointer to the FV header of the volume to search
- @param FileName File name
- @param SearchType Filter to find only files of this type.
- Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
- @param FileHandle This parameter must point to a valid FFS volume.
- @param AprioriFile Pointer to AprioriFile image in this FV if has
-
- @return EFI_NOT_FOUND No files matching the search criteria were found
- @retval EFI_SUCCESS Success to search given file
-
-**/
-EFI_STATUS
-FindFileEx (
- IN CONST EFI_PEI_FV_HANDLE FvHandle,
- IN CONST EFI_GUID *FileName OPTIONAL,
- IN EFI_FV_FILETYPE SearchType,
- IN OUT EFI_PEI_FILE_HANDLE *FileHandle,
- IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL
- )
-{
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
- EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;
- EFI_FFS_FILE_HEADER **FileHeader;
- EFI_FFS_FILE_HEADER *FfsFileHeader;
- UINT32 FileLength;
- UINT32 FileOccupiedSize;
- UINT32 FileOffset;
- UINT64 FvLength;
- UINT8 ErasePolarity;
- UINT8 FileState;
- UINT8 DataCheckSum;
- BOOLEAN IsFfs3Fv;
-
- //
- // Convert the handle of FV to FV header for memory-mapped firmware volume
- //
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;
- FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;
-
- IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
-
- FvLength = FwVolHeader->FvLength;
- if ((FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
- ErasePolarity = 1;
- } else {
- ErasePolarity = 0;
- }
-
- //
- // If FileHeader is not specified (NULL) or FileName is not NULL,
- // start with the first file in the firmware volume. Otherwise,
- // start from the FileHeader.
- //
- if ((*FileHeader == NULL) || (FileName != NULL)) {
- if (FwVolHeader->ExtHeaderOffset != 0) {
- //
- // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
- //
- FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->ExtHeaderOffset);
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);
- } else {
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
- }
-
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)ALIGN_POINTER (FfsFileHeader, 8);
- } else {
- if (IS_FFS_FILE2 (*FileHeader)) {
- if (!IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &(*FileHeader)->Name));
- }
-
- FileLength = FFS_FILE2_SIZE (*FileHeader);
- ASSERT (FileLength > 0x00FFFFFF);
- } else {
- FileLength = FFS_FILE_SIZE (*FileHeader);
- }
-
- //
- // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
- //
- FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
- }
-
- FileOffset = (UINT32)((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
- ASSERT (FileOffset <= 0xFFFFFFFF);
-
- while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
- //
- // Get FileState which is the highest bit of the State
- //
- FileState = GetFileState (ErasePolarity, FfsFileHeader);
- switch (FileState) {
- case EFI_FILE_HEADER_CONSTRUCTION:
- case EFI_FILE_HEADER_INVALID:
- if (IS_FFS_FILE2 (FfsFileHeader)) {
- if (!IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
- }
-
- FileOffset += sizeof (EFI_FFS_FILE_HEADER2);
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
- } else {
- FileOffset += sizeof (EFI_FFS_FILE_HEADER);
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
- }
-
- break;
-
- case EFI_FILE_DATA_VALID:
- case EFI_FILE_MARKED_FOR_UPDATE:
- if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
- ASSERT (FALSE);
- *FileHeader = NULL;
- return EFI_NOT_FOUND;
- }
-
- if (IS_FFS_FILE2 (FfsFileHeader)) {
- FileLength = FFS_FILE2_SIZE (FfsFileHeader);
- ASSERT (FileLength > 0x00FFFFFF);
- FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
- if (!IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
- FileOffset += FileOccupiedSize;
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
- break;
- }
- } else {
- FileLength = FFS_FILE_SIZE (FfsFileHeader);
- FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
- }
-
- DataCheckSum = FFS_FIXED_CHECKSUM;
- if ((FfsFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {
- if (IS_FFS_FILE2 (FfsFileHeader)) {
- DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FileLength - sizeof (EFI_FFS_FILE_HEADER2));
- } else {
- DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER), FileLength - sizeof (EFI_FFS_FILE_HEADER));
- }
- }
-
- if (FfsFileHeader->IntegrityCheck.Checksum.File != DataCheckSum) {
- ASSERT (FALSE);
- *FileHeader = NULL;
- return EFI_NOT_FOUND;
- }
-
- if (FileName != NULL) {
- if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID *)FileName)) {
- *FileHeader = FfsFileHeader;
- return EFI_SUCCESS;
- }
- } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {
- if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) ||
- (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||
- (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE))
- {
- *FileHeader = FfsFileHeader;
- return EFI_SUCCESS;
- } else if (AprioriFile != NULL) {
- if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {
- if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {
- *AprioriFile = (EFI_PEI_FILE_HANDLE)FfsFileHeader;
- }
- }
- }
- } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) &&
- (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD))
- {
- *FileHeader = FfsFileHeader;
- return EFI_SUCCESS;
- }
-
- FileOffset += FileOccupiedSize;
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
- break;
-
- case EFI_FILE_DELETED:
- if (IS_FFS_FILE2 (FfsFileHeader)) {
- if (!IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
- }
-
- FileLength = FFS_FILE2_SIZE (FfsFileHeader);
- ASSERT (FileLength > 0x00FFFFFF);
- } else {
- FileLength = FFS_FILE_SIZE (FfsFileHeader);
- }
-
- FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
- FileOffset += FileOccupiedSize;
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
- break;
-
- default:
- *FileHeader = NULL;
- return EFI_NOT_FOUND;
- }
- }
-
- *FileHeader = NULL;
- return EFI_NOT_FOUND;
-}
-
-/**
- Initialize PeiCore FV List.
-
- @param PrivateData - Pointer to PEI_CORE_INSTANCE.
- @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
-**/
-VOID
-PeiInitializeFv (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
- )
-{
- EFI_STATUS Status;
- EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
- EFI_PEI_FV_HANDLE FvHandle;
- EFI_FIRMWARE_VOLUME_HEADER *BfvHeader;
-
- //
- // Install FV_PPI for FFS2 file system.
- //
- PeiServicesInstallPpi (&mPeiFfs2FvPpiList);
-
- //
- // Install FV_PPI for FFS3 file system.
- //
- PeiServicesInstallPpi (&mPeiFfs3FvPpiList);
-
- BfvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
-
- //
- // The FV_PPI in BFV's format should be installed.
- //
- Status = PeiServicesLocatePpi (
- &BfvHeader->FileSystemGuid,
- 0,
- NULL,
- (VOID **)&FvPpi
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Get handle of BFV
- //
- Status = FvPpi->ProcessVolume (
- FvPpi,
- SecCoreData->BootFirmwareVolumeBase,
- (UINTN)BfvHeader->FvLength,
- &FvHandle
- );
- ASSERT_EFI_ERROR (Status);
-
- PrivateData->Fv = AllocateZeroPool (sizeof (PEI_CORE_FV_HANDLE) * FV_GROWTH_STEP);
- ASSERT (PrivateData->Fv != NULL);
- PrivateData->MaxFvCount = FV_GROWTH_STEP;
-
- //
- // Update internal PEI_CORE_FV array.
- //
- PrivateData->Fv[PrivateData->FvCount].FvHeader = BfvHeader;
- PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
- PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
- PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = 0;
- DEBUG ((
- DEBUG_INFO,
- "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
- (UINT32)PrivateData->FvCount,
- (VOID *)BfvHeader,
- (UINT32)BfvHeader->FvLength,
- FvHandle
- ));
- PrivateData->FvCount++;
-
- //
- // Post a call-back for the FvInfoPPI and FvInfo2PPI services to expose
- // additional FVs to PeiCore.
- //
- Status = PeiServicesNotifyPpi (mNotifyOnFvInfoList);
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- Process Firmware Volume Information once FvInfoPPI or FvInfo2PPI install.
- The FV Info will be registered into PeiCore private data structure.
- And search the inside FV image, if found, the new FV INFO(2) PPI will be installed.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.
- @return if not EFI_SUCCESS, fail to verify FV.
-
-**/
-EFI_STATUS
-EFIAPI
-FirmwareVolumeInfoPpiNotifyCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- )
-{
- EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI FvInfo2Ppi;
- EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
- PEI_CORE_INSTANCE *PrivateData;
- EFI_STATUS Status;
- EFI_PEI_FV_HANDLE FvHandle;
- UINTN FvIndex;
- EFI_PEI_FILE_HANDLE FileHandle;
- VOID *DepexData;
- BOOLEAN IsFvInfo2;
- UINTN CurFvCount;
- VOID *TempPtr;
-
- Status = EFI_SUCCESS;
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiFirmwareVolumeInfo2PpiGuid)) {
- //
- // It is FvInfo2PPI.
- //
- CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI));
- IsFvInfo2 = TRUE;
- } else {
- //
- // It is FvInfoPPI.
- //
- CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI));
- FvInfo2Ppi.AuthenticationStatus = 0;
- IsFvInfo2 = FALSE;
- }
-
- if (CompareGuid (&FvInfo2Ppi.FvFormat, &gEfiFirmwareFileSystem2Guid)) {
- //
- // gEfiFirmwareFileSystem2Guid is specified for FvFormat, then here to check the
- // FileSystemGuid pointed by FvInfo against gEfiFirmwareFileSystem2Guid to make sure
- // FvInfo has the firmware file system 2 format.
- //
- // If the ASSERT really appears, FvFormat needs to be specified correctly, for example,
- // gEfiFirmwareFileSystem3Guid can be used for firmware file system 3 format, or
- // ((EFI_FIRMWARE_VOLUME_HEADER *) FvInfo)->FileSystemGuid can be just used for both
- // firmware file system 2 and 3 format.
- //
- ASSERT (CompareGuid (&(((EFI_FIRMWARE_VOLUME_HEADER *)FvInfo2Ppi.FvInfo)->FileSystemGuid), &gEfiFirmwareFileSystem2Guid));
- }
-
- //
- // Locate the corresponding FV_PPI according to the format GUID of the FV found
- //
- Status = PeiServicesLocatePpi (
- &FvInfo2Ppi.FvFormat,
- 0,
- NULL,
- (VOID **)&FvPpi
- );
- if (!EFI_ERROR (Status)) {
- //
- // Process new found FV and get FV handle.
- //
- Status = FvPpi->ProcessVolume (FvPpi, FvInfo2Ppi.FvInfo, FvInfo2Ppi.FvInfoSize, &FvHandle);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));
- return Status;
- }
-
- //
- // Check whether the FV has already been processed.
- //
- for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex++) {
- if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
- if (IsFvInfo2 && (FvInfo2Ppi.AuthenticationStatus != PrivateData->Fv[FvIndex].AuthenticationStatus)) {
- PrivateData->Fv[FvIndex].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;
- DEBUG ((DEBUG_INFO, "Update AuthenticationStatus of the %dth FV to 0x%x!\n", FvIndex, FvInfo2Ppi.AuthenticationStatus));
- }
-
- DEBUG ((DEBUG_INFO, "The FV %p has already been processed!\n", FvInfo2Ppi.FvInfo));
- return EFI_SUCCESS;
- }
- }
-
- if (PrivateData->FvCount >= PrivateData->MaxFvCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempPtr = AllocateZeroPool (
- sizeof (PEI_CORE_FV_HANDLE) * (PrivateData->MaxFvCount + FV_GROWTH_STEP)
- );
- ASSERT (TempPtr != NULL);
- CopyMem (
- TempPtr,
- PrivateData->Fv,
- sizeof (PEI_CORE_FV_HANDLE) * PrivateData->MaxFvCount
- );
- PrivateData->Fv = TempPtr;
- PrivateData->MaxFvCount = PrivateData->MaxFvCount + FV_GROWTH_STEP;
- }
-
- //
- // Update internal PEI_CORE_FV array.
- //
- PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvInfo2Ppi.FvInfo;
- PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
- PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
- PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;
- CurFvCount = PrivateData->FvCount;
- DEBUG ((
- DEBUG_INFO,
- "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
- (UINT32)CurFvCount,
- (VOID *)FvInfo2Ppi.FvInfo,
- FvInfo2Ppi.FvInfoSize,
- FvHandle
- ));
- PrivateData->FvCount++;
-
- //
- // Scan and process the new discovered FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
- //
- FileHandle = NULL;
- do {
- Status = FvPpi->FindFileByType (
- FvPpi,
- EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
- FvHandle,
- &FileHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = FvPpi->FindSectionByType (
- FvPpi,
- EFI_SECTION_PEI_DEPEX,
- FileHandle,
- (VOID **)&DepexData
- );
- if (!EFI_ERROR (Status)) {
- if (!PeimDispatchReadiness (PeiServices, DepexData)) {
- //
- // Dependency is not satisfied.
- //
- continue;
- }
- }
-
- DEBUG ((DEBUG_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle));
- ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle);
- }
- } while (FileHandle != NULL);
- } else {
- DEBUG ((DEBUG_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfo2Ppi.FvInfo));
-
- AddUnknownFormatFvInfo (PrivateData, &FvInfo2Ppi);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Verify the Guided Section GUID by checking if there is the Guided Section GUID HOB recorded the GUID itself.
-
- @param GuidedSectionGuid The Guided Section GUID.
- @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Ppi
- for the Guided Section.
-
- @return TRUE The GuidedSectionGuid could be identified, and the pointer to
- the Guided Section Extraction Ppi will be returned to *GuidedSectionExtraction.
- @return FALSE The GuidedSectionGuid could not be identified, or
- the Guided Section Extraction Ppi has not been installed yet.
-
-**/
-BOOLEAN
-VerifyGuidedSectionGuid (
- IN EFI_GUID *GuidedSectionGuid,
- OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI **GuidedSectionExtraction
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_GUID *GuidRecorded;
- VOID *Interface;
- EFI_STATUS Status;
-
- //
- // Check if there is the Guided Section GUID HOB recorded the GUID itself.
- //
- Hob.Raw = GetFirstGuidHob (GuidedSectionGuid);
- if (Hob.Raw != NULL) {
- GuidRecorded = (EFI_GUID *)GET_GUID_HOB_DATA (Hob);
- if (CompareGuid (GuidRecorded, GuidedSectionGuid)) {
- //
- // Found the recorded GuidedSectionGuid.
- //
- Status = PeiServicesLocatePpi (GuidedSectionGuid, 0, NULL, (VOID **)&Interface);
- if (!EFI_ERROR (Status) && (Interface != NULL)) {
- //
- // Found the supported Guided Section Extraction Ppi for the Guided Section.
- //
- *GuidedSectionExtraction = (EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *)Interface;
- return TRUE;
- }
-
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Go through the file to search SectionType section.
- Search within encapsulation sections (compression and GUIDed) recursively,
- until the match section is found.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SectionType Filter to find only section of this type.
- @param SectionInstance Pointer to the filter to find the specific instance of section.
- @param Section From where to search.
- @param SectionSize The file size to search.
- @param OutputBuffer A pointer to the discovered section, if successful.
- NULL if section not found
- @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
- @param IsFfs3Fv Indicates the FV format.
-
- @return EFI_NOT_FOUND The match section is not found.
- @return EFI_SUCCESS The match section is found.
-
-**/
-EFI_STATUS
-ProcessSection (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_SECTION_TYPE SectionType,
- IN OUT UINTN *SectionInstance,
- IN EFI_COMMON_SECTION_HEADER *Section,
- IN UINTN SectionSize,
- OUT VOID **OutputBuffer,
- OUT UINT32 *AuthenticationStatus,
- IN BOOLEAN IsFfs3Fv
- )
-{
- EFI_STATUS Status;
- UINT32 SectionLength;
- UINT32 ParsedLength;
- EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;
- EFI_PEI_DECOMPRESS_PPI *DecompressPpi;
- VOID *PpiOutput;
- UINTN PpiOutputSize;
- UINTN Index;
- UINT32 Authentication;
- PEI_CORE_INSTANCE *PrivateData;
- EFI_GUID *SectionDefinitionGuid;
- BOOLEAN SectionCached;
- VOID *TempOutputBuffer;
- UINT32 TempAuthenticationStatus;
- UINT16 GuidedSectionAttributes;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
- *OutputBuffer = NULL;
- ParsedLength = 0;
- Index = 0;
- Status = EFI_NOT_FOUND;
- PpiOutput = NULL;
- PpiOutputSize = 0;
- while (ParsedLength < SectionSize) {
- if (IS_SECTION2 (Section)) {
- ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF);
- if (!IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
- SectionLength = SECTION2_SIZE (Section);
- //
- // SectionLength is adjusted it is 4 byte aligned.
- // Go to the next section
- //
- SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
- ASSERT (SectionLength != 0);
- ParsedLength += SectionLength;
- Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
- continue;
- }
- }
-
- if (Section->Type == SectionType) {
- //
- // The type matches, so check the instance count to see if it's the one we want.
- //
- (*SectionInstance)--;
- if (*SectionInstance == 0) {
- //
- // Got it!
- //
- if (IS_SECTION2 (Section)) {
- *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2));
- } else {
- *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER));
- }
-
- return EFI_SUCCESS;
- } else {
- if (IS_SECTION2 (Section)) {
- SectionLength = SECTION2_SIZE (Section);
- } else {
- SectionLength = SECTION_SIZE (Section);
- }
-
- //
- // SectionLength is adjusted it is 4 byte aligned.
- // Go to the next section
- //
- SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
- ASSERT (SectionLength != 0);
- ParsedLength += SectionLength;
- Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
- continue;
- }
- } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {
- //
- // Check the encapsulated section is extracted into the cache data.
- //
- SectionCached = FALSE;
- for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index++) {
- if (Section == PrivateData->CacheSection.Section[Index]) {
- SectionCached = TRUE;
- PpiOutput = PrivateData->CacheSection.SectionData[Index];
- PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];
- Authentication = PrivateData->CacheSection.AuthenticationStatus[Index];
- //
- // Search section directly from the cache data.
- //
- TempAuthenticationStatus = 0;
- Status = ProcessSection (
- PeiServices,
- SectionType,
- SectionInstance,
- PpiOutput,
- PpiOutputSize,
- &TempOutputBuffer,
- &TempAuthenticationStatus,
- IsFfs3Fv
- );
- if (!EFI_ERROR (Status)) {
- *OutputBuffer = TempOutputBuffer;
- *AuthenticationStatus = TempAuthenticationStatus | Authentication;
- return EFI_SUCCESS;
- }
- }
- }
-
- //
- // If SectionCached is TRUE, the section data has been cached and scanned.
- //
- if (!SectionCached) {
- Status = EFI_NOT_FOUND;
- Authentication = 0;
- if (Section->Type == EFI_SECTION_GUID_DEFINED) {
- if (IS_SECTION2 (Section)) {
- SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION2 *)Section)->SectionDefinitionGuid;
- GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *)Section)->Attributes;
- } else {
- SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid;
- GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION *)Section)->Attributes;
- }
-
- if (VerifyGuidedSectionGuid (SectionDefinitionGuid, &GuidSectionPpi)) {
- Status = GuidSectionPpi->ExtractSection (
- GuidSectionPpi,
- Section,
- &PpiOutput,
- &PpiOutputSize,
- &Authentication
- );
- } else if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
- //
- // Figure out the proper authentication status for GUIDED section without processing required
- //
- Status = EFI_SUCCESS;
- if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
- Authentication |= EFI_AUTH_STATUS_IMAGE_SIGNED | EFI_AUTH_STATUS_NOT_TESTED;
- }
-
- if (IS_SECTION2 (Section)) {
- PpiOutputSize = SECTION2_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION2 *)Section)->DataOffset;
- PpiOutput = (UINT8 *)Section + ((EFI_GUID_DEFINED_SECTION2 *)Section)->DataOffset;
- } else {
- PpiOutputSize = SECTION_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION *)Section)->DataOffset;
- PpiOutput = (UINT8 *)Section + ((EFI_GUID_DEFINED_SECTION *)Section)->DataOffset;
- }
- }
- } else if (Section->Type == EFI_SECTION_COMPRESSION) {
- Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **)&DecompressPpi);
- if (!EFI_ERROR (Status)) {
- Status = DecompressPpi->Decompress (
- DecompressPpi,
- (CONST EFI_COMPRESSION_SECTION *)Section,
- &PpiOutput,
- &PpiOutputSize
- );
- }
- }
-
- if (!EFI_ERROR (Status)) {
- if ((Authentication & EFI_AUTH_STATUS_NOT_TESTED) == 0) {
- //
- // Update cache section data.
- //
- if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {
- PrivateData->CacheSection.AllSectionCount++;
- }
-
- PrivateData->CacheSection.Section[PrivateData->CacheSection.SectionIndex] = Section;
- PrivateData->CacheSection.SectionData[PrivateData->CacheSection.SectionIndex] = PpiOutput;
- PrivateData->CacheSection.SectionSize[PrivateData->CacheSection.SectionIndex] = PpiOutputSize;
- PrivateData->CacheSection.AuthenticationStatus[PrivateData->CacheSection.SectionIndex] = Authentication;
- PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;
- }
-
- TempAuthenticationStatus = 0;
- Status = ProcessSection (
- PeiServices,
- SectionType,
- SectionInstance,
- PpiOutput,
- PpiOutputSize,
- &TempOutputBuffer,
- &TempAuthenticationStatus,
- IsFfs3Fv
- );
- if (!EFI_ERROR (Status)) {
- *OutputBuffer = TempOutputBuffer;
- *AuthenticationStatus = TempAuthenticationStatus | Authentication;
- return EFI_SUCCESS;
- }
- }
- }
- }
-
- if (IS_SECTION2 (Section)) {
- SectionLength = SECTION2_SIZE (Section);
- } else {
- SectionLength = SECTION_SIZE (Section);
- }
-
- //
- // SectionLength is adjusted it is 4 byte aligned.
- // Go to the next section
- //
- SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
- ASSERT (SectionLength != 0);
- ParsedLength += SectionLength;
- Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Searches for the next matching section within the specified file.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param SectionType Filter to find only sections of this type.
- @param FileHandle Pointer to the current file to search.
- @param SectionData A pointer to the discovered section, if successful.
- NULL if section not found
-
- @retval EFI_NOT_FOUND The section was not found.
- @retval EFI_SUCCESS The section was found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindSectionData (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_SECTION_TYPE SectionType,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData
- )
-{
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
- return EFI_NOT_FOUND;
- }
-
- return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData);
-}
-
-/**
- Searches for the next matching section within the specified file.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SectionType The value of the section type to find.
- @param SectionInstance Section instance to find.
- @param FileHandle Handle of the firmware file to search.
- @param SectionData A pointer to the discovered section, if successful.
- @param AuthenticationStatus A pointer to the authentication status for this section.
-
- @retval EFI_SUCCESS The section was found.
- @retval EFI_NOT_FOUND The section was not found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindSectionData3 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_SECTION_TYPE SectionType,
- IN UINTN SectionInstance,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData,
- OUT UINT32 *AuthenticationStatus
- )
-{
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
- return EFI_NOT_FOUND;
- }
-
- if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
- (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION))
- {
- return CoreFvHandle->FvPpi->FindSectionByType2 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus);
- }
-
- //
- // The old FvPpi doesn't support to find section by section instance
- // and return authentication status, so return EFI_UNSUPPORTED.
- //
- return EFI_UNSUPPORTED;
-}
-
-/**
- Searches for the next matching file in the firmware volume.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SearchType Filter to find only files of this type.
- Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
- @param FvHandle Handle of firmware volume in which to search.
- @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start
- at the beginning of the firmware volume. On exit, points the file handle of the next file
- in the volume or NULL if there are no more files.
-
- @retval EFI_NOT_FOUND The file was not found.
- @retval EFI_NOT_FOUND The header checksum was not zero.
- @retval EFI_SUCCESS The file was found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindNextFile (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINT8 SearchType,
- IN EFI_PEI_FV_HANDLE FvHandle,
- IN OUT EFI_PEI_FILE_HANDLE *FileHandle
- )
-{
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- CoreFvHandle = FvHandleToCoreHandle (FvHandle);
-
- if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
- return EFI_NOT_FOUND;
- }
-
- return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle);
-}
-
-/**
- Search the firmware volumes by index
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware
- Volume (BFV).
- @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.
-
- @retval EFI_INVALID_PARAMETER VolumeHandle is NULL
- @retval EFI_NOT_FOUND The volume was not found.
- @retval EFI_SUCCESS The volume was found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindNextVolume (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINTN Instance,
- IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
- )
-{
- PEI_CORE_INSTANCE *Private;
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- if (VolumeHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- CoreFvHandle = FindNextCoreFvHandle (Private, Instance);
- if (CoreFvHandle == NULL) {
- *VolumeHandle = NULL;
- return EFI_NOT_FOUND;
- }
-
- *VolumeHandle = CoreFvHandle->FvHandle;
-
- return EFI_SUCCESS;
-}
-
-/**
- Find a file within a volume by its name.
-
- @param FileName A pointer to the name of the file to find within the firmware volume.
- @param VolumeHandle The firmware volume to search
- @param FileHandle Upon exit, points to the found file's handle
- or NULL if it could not be found.
-
- @retval EFI_SUCCESS File was found.
- @retval EFI_NOT_FOUND File was not found.
- @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindFileByName (
- IN CONST EFI_GUID *FileName,
- IN EFI_PEI_FV_HANDLE VolumeHandle,
- OUT EFI_PEI_FILE_HANDLE *FileHandle
- )
-{
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CoreFvHandle = FvHandleToCoreHandle (VolumeHandle);
- if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
- return EFI_NOT_FOUND;
- }
-
- return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle);
-}
-
-/**
- Returns information about a specific file.
-
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's information.
-
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
- @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
- @retval EFI_SUCCESS File information returned.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsGetFileInfo (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO *FileInfo
- )
-{
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- if ((FileHandle == NULL) || (FileInfo == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Retrieve the FirmwareVolume which the file resides in.
- //
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo);
-}
-
-/**
- Returns information about a specific file.
-
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's information.
-
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
- @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
- @retval EFI_SUCCESS File information returned.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsGetFileInfo2 (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO2 *FileInfo
- )
-{
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- if ((FileHandle == NULL) || (FileInfo == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Retrieve the FirmwareVolume which the file resides in.
- //
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
- (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION))
- {
- return CoreFvHandle->FvPpi->GetFileInfo2 (CoreFvHandle->FvPpi, FileHandle, FileInfo);
- }
-
- //
- // The old FvPpi doesn't support to return file info with authentication status,
- // so return EFI_UNSUPPORTED.
- //
- return EFI_UNSUPPORTED;
-}
-
-/**
- Returns information about the specified volume.
-
- This function returns information about a specific firmware
- volume, including its name, type, attributes, starting address
- and size.
-
- @param VolumeHandle Handle of the volume.
- @param VolumeInfo Upon exit, points to the volume's information.
-
- @retval EFI_SUCCESS Volume information returned.
- @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.
- @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.
- @retval EFI_SUCCESS Information successfully returned.
- @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsGetVolumeInfo (
- IN EFI_PEI_FV_HANDLE VolumeHandle,
- OUT EFI_FV_INFO *VolumeInfo
- )
-{
- PEI_CORE_FV_HANDLE *CoreHandle;
-
- if ((VolumeInfo == NULL) || (VolumeHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CoreHandle = FvHandleToCoreHandle (VolumeHandle);
-
- if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);
-}
-
-/**
- Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size.
-
- @param[in] FvHeader Pointer to FV header.
- @param[out] FvUsedSize Pointer to FV used size returned,
- only valid if USED_SIZE FV_EXT_TYPE entry is found.
- @param[out] EraseByte Pointer to erase byte returned,
- only valid if USED_SIZE FV_EXT_TYPE entry is found.
-
- @retval TRUE USED_SIZE FV_EXT_TYPE entry is found,
- FV used size and erase byte are returned.
- @retval FALSE No USED_SIZE FV_EXT_TYPE entry found.
-
-**/
-BOOLEAN
-GetFvUsedSize (
- IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
- OUT UINT32 *FvUsedSize,
- OUT UINT8 *EraseByte
- )
-{
- UINT16 ExtHeaderOffset;
- EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader;
- EFI_FIRMWARE_VOLUME_EXT_ENTRY *ExtEntryList;
- EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *ExtEntryUsedSize;
-
- ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset);
- if (ExtHeaderOffset != 0) {
- ExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + ExtHeaderOffset);
- ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)(ExtHeader + 1);
- while ((UINTN)ExtEntryList < ((UINTN)ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) {
- if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {
- //
- // USED_SIZE FV_EXT_TYPE entry is found.
- //
- ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)ExtEntryList;
- *FvUsedSize = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize);
- if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) {
- *EraseByte = 0xFF;
- } else {
- *EraseByte = 0;
- }
-
- DEBUG ((
- DEBUG_INFO,
- "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n",
- FvHeader,
- *FvUsedSize,
- *EraseByte
- ));
- return TRUE;
- }
-
- ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)
- ((UINT8 *)ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize));
- }
- }
-
- //
- // No USED_SIZE FV_EXT_TYPE entry found.
- //
- return FALSE;
-}
-
-/**
- Get FV image(s) from the FV type file, then install FV INFO(2) PPI, Build FV(2, 3) HOB.
-
- @param PrivateData PeiCore's private data structure
- @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent FV image that contain this FV image.
- @param ParentFvFileHandle File handle of a FV type file that contain this FV image.
-
- @retval EFI_NOT_FOUND FV image can't be found.
- @retval EFI_SUCCESS Successfully to process it.
- @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
- @retval EFI_SECURITY_VIOLATION Image is illegal
- @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
-
-**/
-EFI_STATUS
-ProcessFvFile (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle,
- IN EFI_PEI_FILE_HANDLE ParentFvFileHandle
- )
-{
- EFI_STATUS Status;
- EFI_FV_INFO ParentFvImageInfo;
- UINT32 FvAlignment;
- VOID *NewFvBuffer;
- EFI_PEI_HOB_POINTERS HobPtr;
- EFI_PEI_FIRMWARE_VOLUME_PPI *ParentFvPpi;
- EFI_PEI_FV_HANDLE ParentFvHandle;
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- EFI_FV_FILE_INFO FileInfo;
- UINT64 FvLength;
- UINT32 AuthenticationStatus;
- UINT32 FvUsedSize;
- UINT8 EraseByte;
- UINTN Index;
-
- //
- // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
- // been extracted.
- //
- HobPtr.Raw = GetHobList ();
- while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {
- if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {
- //
- // this FILE has been dispatched, it will not be dispatched again.
- //
- DEBUG ((DEBUG_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle));
- return EFI_SUCCESS;
- }
-
- HobPtr.Raw = GET_NEXT_HOB (HobPtr);
- }
-
- ParentFvHandle = ParentFvCoreHandle->FvHandle;
- ParentFvPpi = ParentFvCoreHandle->FvPpi;
-
- Status = EFI_SUCCESS;
-
- //
- // Find FvImage(s) in FvFile
- //
- Index = 0;
- do {
- AuthenticationStatus = 0;
- if ((ParentFvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
- (ParentFvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION))
- {
- Status = ParentFvPpi->FindSectionByType2 (
- ParentFvPpi,
- EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
- Index,
- ParentFvFileHandle,
- (VOID **)&FvHeader,
- &AuthenticationStatus
- );
- } else {
- //
- // Old FvPpi has no parameter to input SearchInstance,
- // only one instance is supported.
- //
- if (Index > 0) {
- break;
- }
-
- Status = ParentFvPpi->FindSectionByType (
- ParentFvPpi,
- EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
- ParentFvFileHandle,
- (VOID **)&FvHeader
- );
- }
-
- if (EFI_ERROR (Status)) {
- break;
- }
-
- Status = VerifyPeim (PrivateData, ParentFvHandle, ParentFvFileHandle, AuthenticationStatus);
- if (Status == EFI_SECURITY_VIOLATION) {
- break;
- }
-
- //
- // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
- // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
- // its initial linked location and maintain its alignment.
- //
- if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
- //
- // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
- //
- FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);
- if (FvAlignment < 8) {
- FvAlignment = 8;
- }
-
- DEBUG ((
- DEBUG_INFO,
- "%a() FV at 0x%x, FvAlignment required is 0x%x\n",
- __func__,
- FvHeader,
- FvAlignment
- ));
-
- //
- // Check FvImage alignment.
- //
- if ((UINTN)FvHeader % FvAlignment != 0) {
- FvLength = ReadUnaligned64 (&FvHeader->FvLength);
- NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32)FvLength), FvAlignment);
- if (NewFvBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- break;
- }
-
- if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {
- //
- // Copy the used bytes and fill the rest with the erase value.
- //
- CopyMem (NewFvBuffer, FvHeader, (UINTN)FvUsedSize);
- SetMem (
- (UINT8 *)NewFvBuffer + FvUsedSize,
- (UINTN)(FvLength - FvUsedSize),
- EraseByte
- );
- } else {
- CopyMem (NewFvBuffer, FvHeader, (UINTN)FvLength);
- }
-
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NewFvBuffer;
- }
- }
-
- Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo);
- ASSERT_EFI_ERROR (Status);
-
- Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Install FvInfo(2) Ppi
- // NOTE: FvInfo2 must be installed before FvInfo so that recursive processing of encapsulated
- // FVs inherit the proper AuthenticationStatus.
- //
- PeiServicesInstallFvInfo2Ppi (
- &FvHeader->FileSystemGuid,
- (VOID **)FvHeader,
- (UINT32)FvHeader->FvLength,
- &ParentFvImageInfo.FvName,
- &FileInfo.FileName,
- AuthenticationStatus
- );
-
- PeiServicesInstallFvInfoPpi (
- &FvHeader->FileSystemGuid,
- (VOID **)FvHeader,
- (UINT32)FvHeader->FvLength,
- &ParentFvImageInfo.FvName,
- &FileInfo.FileName
- );
-
- //
- // Expose the extracted FvImage to the FV HOB consumer phase, i.e. DXE phase
- //
- BuildFvHob (
- (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
- FvHeader->FvLength
- );
-
- //
- // Makes the encapsulated volume show up in DXE phase to skip processing of
- // encapsulated file again.
- //
- BuildFv2Hob (
- (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
- FvHeader->FvLength,
- &ParentFvImageInfo.FvName,
- &FileInfo.FileName
- );
-
- //
- // Build FV3 HOB with authentication status to be propagated to DXE.
- //
- BuildFv3Hob (
- (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
- FvHeader->FvLength,
- AuthenticationStatus,
- TRUE,
- &ParentFvImageInfo.FvName,
- &FileInfo.FileName
- );
-
- Index++;
- } while (TRUE);
-
- if (Index > 0) {
- //
- // At least one FvImage has been processed successfully.
- //
- return EFI_SUCCESS;
- } else {
- return Status;
- }
-}
-
-/**
- Process a firmware volume and create a volume handle.
-
- Create a volume handle from the information in the buffer. For
- memory-mapped firmware volumes, Buffer and BufferSize refer to
- the start of the firmware volume and the firmware volume size.
- For non memory-mapped firmware volumes, this points to a
- buffer which contains the necessary information for creating
- the firmware volume handle. Normally, these values are derived
- from the EFI_FIRMWARE_VOLUME_INFO_PPI.
-
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param Buffer Points to the start of the buffer.
- @param BufferSize Size of the buffer.
- @param FvHandle Points to the returned firmware volume
- handle. The firmware volume handle must
- be unique within the system.
-
- @retval EFI_SUCCESS Firmware volume handle created.
- @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiProcessVolume (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN VOID *Buffer,
- IN UINTN BufferSize,
- OUT EFI_PEI_FV_HANDLE *FvHandle
- )
-{
- EFI_STATUS Status;
-
- ASSERT (FvHandle != NULL);
-
- if (Buffer == NULL) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- //
- // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped
- // FV image and the handle is pointed to FV image's buffer.
- //
- *FvHandle = (EFI_PEI_FV_HANDLE)Buffer;
-
- //
- // Do verify for given FV buffer.
- //
- Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER *)Buffer);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));
- return EFI_VOLUME_CORRUPTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Finds the next file of the specified type.
-
- This service enables PEI modules to discover additional firmware files.
- The FileHandle must be unique within the system.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param SearchType A filter to find only files of this type. Type
- EFI_FV_FILETYPE_ALL causes no filtering to be
- done.
- @param FvHandle Handle of firmware volume in which to
- search.
- @param FileHandle Points to the current handle from which to
- begin searching or NULL to start at the
- beginning of the firmware volume. Updated
- upon return to reflect the file found.
-
- @retval EFI_SUCCESS The file was found.
- @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindFileByType (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_FV_FILETYPE SearchType,
- IN EFI_PEI_FV_HANDLE FvHandle,
- IN OUT EFI_PEI_FILE_HANDLE *FileHandle
- )
-{
- return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
-}
-
-/**
- Find a file within a volume by its name.
-
- This service searches for files with a specific name, within
- either the specified firmware volume or all firmware volumes.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FileName A pointer to the name of the file to find
- within the firmware volume.
- @param FvHandle Upon entry, the pointer to the firmware
- volume to search or NULL if all firmware
- volumes should be searched. Upon exit, the
- actual firmware volume in which the file was
- found.
- @param FileHandle Upon exit, points to the found file's
- handle or NULL if it could not be found.
-
- @retval EFI_SUCCESS File was found.
- @retval EFI_NOT_FOUND File was not found.
- @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
- FileName was NULL.
-
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindFileByName (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN CONST EFI_GUID *FileName,
- IN EFI_PEI_FV_HANDLE *FvHandle,
- OUT EFI_PEI_FILE_HANDLE *FileHandle
- )
-{
- EFI_STATUS Status;
- PEI_CORE_INSTANCE *PrivateData;
- UINTN Index;
-
- if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (*FvHandle != NULL) {
- Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);
- if (Status == EFI_NOT_FOUND) {
- *FileHandle = NULL;
- }
- } else {
- //
- // If *FvHandle = NULL, so search all FV for given filename
- //
- Status = EFI_NOT_FOUND;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
- for (Index = 0; Index < PrivateData->FvCount; Index++) {
- //
- // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
- //
- if (PrivateData->Fv[Index].FvPpi != NULL) {
- Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);
- if (!EFI_ERROR (Status)) {
- *FvHandle = PrivateData->Fv[Index].FvHandle;
- break;
- }
- }
- }
- }
-
- return Status;
-}
-
-/**
- Returns information about a specific file.
-
- This function returns information about a specific
- file, including its file name, type, attributes, starting
- address and size.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's
- information.
-
- @retval EFI_SUCCESS File information returned.
- @retval EFI_INVALID_PARAMETER If FileHandle does not
- represent a valid file.
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiGetFileInfo (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO *FileInfo
- )
-{
- UINT8 FileState;
- UINT8 ErasePolarity;
- EFI_FFS_FILE_HEADER *FileHeader;
- PEI_CORE_FV_HANDLE *CoreFvHandle;
- PEI_FW_VOL_INSTANCE *FwVolInstance;
-
- if ((FileHandle == NULL) || (FileInfo == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Retrieve the FirmwareVolume which the file resides in.
- //
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if (CoreFvHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
-
- if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
- ErasePolarity = 1;
- } else {
- ErasePolarity = 0;
- }
-
- //
- // Get FileState which is the highest bit of the State
- //
- FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER *)FileHandle);
-
- switch (FileState) {
- case EFI_FILE_DATA_VALID:
- case EFI_FILE_MARKED_FOR_UPDATE:
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
-
- FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
- if (IS_FFS_FILE2 (FileHeader)) {
- ASSERT (FFS_FILE2_SIZE (FileHeader) > 0x00FFFFFF);
- if (!FwVolInstance->IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader->Name));
- return EFI_INVALID_PARAMETER;
- }
-
- FileInfo->BufferSize = FFS_FILE2_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
- FileInfo->Buffer = (UINT8 *)FileHeader + sizeof (EFI_FFS_FILE_HEADER2);
- } else {
- FileInfo->BufferSize = FFS_FILE_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER);
- FileInfo->Buffer = (UINT8 *)FileHeader + sizeof (EFI_FFS_FILE_HEADER);
- }
-
- CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof (EFI_GUID));
- FileInfo->FileType = FileHeader->Type;
- FileInfo->FileAttributes = FfsAttributes2FvFileAttributes (FileHeader->Attributes);
- if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
- FileInfo->FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Returns information about a specific file.
-
- This function returns information about a specific
- file, including its file name, type, attributes, starting
- address, size and authentication status.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's
- information.
-
- @retval EFI_SUCCESS File information returned.
- @retval EFI_INVALID_PARAMETER If FileHandle does not
- represent a valid file.
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiGetFileInfo2 (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO2 *FileInfo
- )
-{
- EFI_STATUS Status;
- PEI_CORE_FV_HANDLE *CoreFvHandle;
-
- if ((FileHandle == NULL) || (FileInfo == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Retrieve the FirmwareVolume which the file resides in.
- //
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if (CoreFvHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = PeiFfsFvPpiGetFileInfo (This, FileHandle, (EFI_FV_FILE_INFO *)FileInfo);
- if (!EFI_ERROR (Status)) {
- FileInfo->AuthenticationStatus = CoreFvHandle->AuthenticationStatus;
- }
-
- return Status;
-}
-
-/**
- This function returns information about the firmware volume.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FvHandle Handle to the firmware handle.
- @param VolumeInfo Points to the returned firmware volume
- information.
-
- @retval EFI_SUCCESS Information returned successfully.
- @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
- firmware volume or VolumeInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiGetVolumeInfo (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_PEI_FV_HANDLE FvHandle,
- OUT EFI_FV_INFO *VolumeInfo
- )
-{
- EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;
- EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
-
- if ((VolumeInfo == NULL) || (FvHandle == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // VolumeHandle may not align at 8 byte,
- // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
- // So, Copy FvHeader into the local FvHeader structure.
- //
- CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
-
- //
- // Check FV Image Signature
- //
- if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));
- VolumeInfo->FvAttributes = FwVolHeader.Attributes;
- VolumeInfo->FvStart = (VOID *)FvHandle;
- VolumeInfo->FvSize = FwVolHeader.FvLength;
- CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof (EFI_GUID));
-
- if (FwVolHeader.ExtHeaderOffset != 0) {
- FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);
- CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof (EFI_GUID));
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Find the next matching section in the firmware file.
-
- This service enables PEI modules to discover sections
- of a given type within a valid file.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param SearchType A filter to find only sections of this
- type.
- @param FileHandle Handle of firmware file in which to
- search.
- @param SectionData Updated upon return to point to the
- section found.
-
- @retval EFI_SUCCESS Section was found.
- @retval EFI_NOT_FOUND Section of the specified type was not
- found. SectionData contains NULL.
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindSectionByType (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_SECTION_TYPE SearchType,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData
- )
-{
- UINT32 AuthenticationStatus;
-
- return PeiFfsFvPpiFindSectionByType2 (This, SearchType, 0, FileHandle, SectionData, &AuthenticationStatus);
-}
-
-/**
- Find the next matching section in the firmware file.
-
- This service enables PEI modules to discover sections
- of a given instance and type within a valid file.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param SearchType A filter to find only sections of this
- type.
- @param SearchInstance A filter to find the specific instance
- of sections.
- @param FileHandle Handle of firmware file in which to
- search.
- @param SectionData Updated upon return to point to the
- section found.
- @param AuthenticationStatus Updated upon return to point to the
- authentication status for this section.
-
- @retval EFI_SUCCESS Section was found.
- @retval EFI_NOT_FOUND Section of the specified type was not
- found. SectionData contains NULL.
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindSectionByType2 (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_SECTION_TYPE SearchType,
- IN UINTN SearchInstance,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData,
- OUT UINT32 *AuthenticationStatus
- )
-{
- EFI_STATUS Status;
- EFI_FFS_FILE_HEADER *FfsFileHeader;
- UINT32 FileSize;
- EFI_COMMON_SECTION_HEADER *Section;
- PEI_FW_VOL_INSTANCE *FwVolInstance;
- PEI_CORE_FV_HANDLE *CoreFvHandle;
- UINTN Instance;
- UINT32 ExtractedAuthenticationStatus;
-
- if (SectionData == NULL) {
- return EFI_NOT_FOUND;
- }
-
- FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
-
- //
- // Retrieve the FirmwareVolume which the file resides in.
- //
- CoreFvHandle = FileHandleToVolume (FileHandle);
- if (CoreFvHandle == NULL) {
- return EFI_NOT_FOUND;
- }
-
- FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
-
- if (IS_FFS_FILE2 (FfsFileHeader)) {
- ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
- if (!FwVolInstance->IsFfs3Fv) {
- DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
- return EFI_NOT_FOUND;
- }
-
- Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
- FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
- } else {
- Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
- FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
- }
-
- Instance = SearchInstance + 1;
- ExtractedAuthenticationStatus = 0;
- Status = ProcessSection (
- GetPeiServicesTablePointer (),
- SearchType,
- &Instance,
- Section,
- FileSize,
- SectionData,
- &ExtractedAuthenticationStatus,
- FwVolInstance->IsFfs3Fv
- );
- if (!EFI_ERROR (Status)) {
- //
- // Inherit the authentication status.
- //
- *AuthenticationStatus = ExtractedAuthenticationStatus | CoreFvHandle->AuthenticationStatus;
- }
-
- return Status;
-}
-
-/**
- Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
-
- @param FvHandle The handle of a FV.
-
- @retval NULL if can not find.
- @return Pointer of corresponding PEI_CORE_FV_HANDLE.
-**/
-PEI_CORE_FV_HANDLE *
-FvHandleToCoreHandle (
- IN EFI_PEI_FV_HANDLE FvHandle
- )
-{
- UINTN Index;
- PEI_CORE_INSTANCE *PrivateData;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
- for (Index = 0; Index < PrivateData->FvCount; Index++) {
- if (FvHandle == PrivateData->Fv[Index].FvHandle) {
- return &PrivateData->Fv[Index];
- }
- }
-
- return NULL;
-}
-
-/**
- Gets a PEI_CORE_FV_HANDLE instance for the next volume according to the given index.
-
- This routine also will install an instance of the FvInfo PPI for the FV HOB
- as defined in the PI specification.
-
- @param Private Pointer of PEI_CORE_INSTANCE
- @param Instance Index of the FV to search
-
- @return Instance of PEI_CORE_FV_HANDLE.
-**/
-PEI_CORE_FV_HANDLE *
-FindNextCoreFvHandle (
- IN PEI_CORE_INSTANCE *Private,
- IN UINTN Instance
- )
-{
- if (Instance >= Private->FvCount) {
- return NULL;
- }
-
- return &Private->Fv[Instance];
-}
-
-/**
- After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
- be re-installed with the instance in permanent memory and all cached FvPpi pointers in
- PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent
- memory.
-
- @param PrivateData Pointer to PEI_CORE_INSTANCE.
-**/
-VOID
-PeiReinitializeFv (
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- VOID *OldFfsFvPpi;
- EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;
- UINTN Index;
- EFI_STATUS Status;
-
- //
- // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
- // in flash.
- //
- Status = PeiServicesLocatePpi (
- &gEfiFirmwareFileSystem2Guid,
- 0,
- &OldDescriptor,
- &OldFfsFvPpi
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
- // which is shadowed from flash to permanent memory within PeiCore image.
- //
- Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
- //
- for (Index = 0; Index < PrivateData->FvCount; Index++) {
- if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
- PrivateData->Fv[Index].FvPpi = &mPeiFfs2FwVol.Fv;
- }
- }
-
- //
- // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which
- // in flash.
- //
- Status = PeiServicesLocatePpi (
- &gEfiFirmwareFileSystem3Guid,
- 0,
- &OldDescriptor,
- &OldFfsFvPpi
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3
- // which is shadowed from flash to permanent memory within PeiCore image.
- //
- Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs3FvPpiList);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
- //
- for (Index = 0; Index < PrivateData->FvCount; Index++) {
- if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
- PrivateData->Fv[Index].FvPpi = &mPeiFfs3FwVol.Fv;
- }
- }
-}
-
-/**
- Report the information for a newly discovered FV in an unknown format.
-
- If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for a third-party FV format, but
- the FV has been discovered, then the information of this FV will be cached into PEI_CORE_INSTANCE's
- UnknownFvInfo array.
-
- Also a notification would be installed for unknown FV format GUID, if EFI_PEI_FIRMWARE_VOLUME_PPI
- is installed later by platform's PEIM, the original unknown FV will be processed by
- using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
-
- @param PrivateData Point to instance of PEI_CORE_INSTANCE
- @param FvInfo2Ppi Point to FvInfo2 PPI.
-
- @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
- @retval EFI_SUCCESS Success to add the information for unknown FV.
-**/
-EFI_STATUS
-AddUnknownFormatFvInfo (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi
- )
-{
- PEI_CORE_UNKNOW_FORMAT_FV_INFO *NewUnknownFv;
- VOID *TempPtr;
-
- if (PrivateData->UnknownFvInfoCount >= PrivateData->MaxUnknownFvInfoCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempPtr = AllocateZeroPool (
- sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO) * (PrivateData->MaxUnknownFvInfoCount + FV_GROWTH_STEP)
- );
- ASSERT (TempPtr != NULL);
- CopyMem (
- TempPtr,
- PrivateData->UnknownFvInfo,
- sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO) * PrivateData->MaxUnknownFvInfoCount
- );
- PrivateData->UnknownFvInfo = TempPtr;
- PrivateData->MaxUnknownFvInfoCount = PrivateData->MaxUnknownFvInfoCount + FV_GROWTH_STEP;
- }
-
- NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];
- PrivateData->UnknownFvInfoCount++;
-
- CopyGuid (&NewUnknownFv->FvFormat, &FvInfo2Ppi->FvFormat);
- NewUnknownFv->FvInfo = FvInfo2Ppi->FvInfo;
- NewUnknownFv->FvInfoSize = FvInfo2Ppi->FvInfoSize;
- NewUnknownFv->AuthenticationStatus = FvInfo2Ppi->AuthenticationStatus;
- NewUnknownFv->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
- NewUnknownFv->NotifyDescriptor.Guid = &NewUnknownFv->FvFormat;
- NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;
-
- PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);
- return EFI_SUCCESS;
-}
-
-/**
- Find the FV information according to third-party FV format GUID.
-
- This routine also will remove the FV information found by given FV format GUID from
- PrivateData->UnknownFvInfo[].
-
- @param PrivateData Point to instance of PEI_CORE_INSTANCE
- @param Format Point to given FV format GUID
- @param FvInfo On return, the pointer of FV information buffer
- @param FvInfoSize On return, the size of FV information buffer.
- @param AuthenticationStatus On return, the authentication status of FV information buffer.
-
- @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
- @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
-**/
-EFI_STATUS
-FindUnknownFormatFvInfo (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_GUID *Format,
- OUT VOID **FvInfo,
- OUT UINT32 *FvInfoSize,
- OUT UINT32 *AuthenticationStatus
- )
-{
- UINTN Index;
- UINTN Index2;
-
- Index = 0;
- for ( ; Index < PrivateData->UnknownFvInfoCount; Index++) {
- if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {
- break;
- }
- }
-
- if (Index == PrivateData->UnknownFvInfoCount) {
- return EFI_NOT_FOUND;
- }
-
- *FvInfo = PrivateData->UnknownFvInfo[Index].FvInfo;
- *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;
- *AuthenticationStatus = PrivateData->UnknownFvInfo[Index].AuthenticationStatus;
-
- //
- // Remove an entry from UnknownFvInfo array.
- //
- Index2 = Index + 1;
- for ( ; Index2 < PrivateData->UnknownFvInfoCount; Index2++, Index++) {
- CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));
- }
-
- PrivateData->UnknownFvInfoCount--;
- return EFI_SUCCESS;
-}
-
-/**
- Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
-
- When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
- routine is called to process all discovered FVs in this format.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS The notification callback is processed correctly.
-**/
-EFI_STATUS
-EFIAPI
-ThirdPartyFvPpiNotifyCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
- VOID *FvInfo;
- UINT32 FvInfoSize;
- UINT32 AuthenticationStatus;
- EFI_STATUS Status;
- EFI_PEI_FV_HANDLE FvHandle;
- BOOLEAN IsProcessed;
- UINTN FvIndex;
- EFI_PEI_FILE_HANDLE FileHandle;
- VOID *DepexData;
- UINTN CurFvCount;
- VOID *TempPtr;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
- FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI *)Ppi;
-
- do {
- Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize, &AuthenticationStatus);
- if (EFI_ERROR (Status)) {
- return EFI_SUCCESS;
- }
-
- //
- // Process new found FV and get FV handle.
- //
- Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));
- continue;
- }
-
- //
- // Check whether the FV has already been processed.
- //
- IsProcessed = FALSE;
- for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex++) {
- if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
- DEBUG ((DEBUG_INFO, "The FV %p has already been processed!\n", FvInfo));
- IsProcessed = TRUE;
- break;
- }
- }
-
- if (IsProcessed) {
- continue;
- }
-
- if (PrivateData->FvCount >= PrivateData->MaxFvCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempPtr = AllocateZeroPool (
- sizeof (PEI_CORE_FV_HANDLE) * (PrivateData->MaxFvCount + FV_GROWTH_STEP)
- );
- ASSERT (TempPtr != NULL);
- CopyMem (
- TempPtr,
- PrivateData->Fv,
- sizeof (PEI_CORE_FV_HANDLE) * PrivateData->MaxFvCount
- );
- PrivateData->Fv = TempPtr;
- PrivateData->MaxFvCount = PrivateData->MaxFvCount + FV_GROWTH_STEP;
- }
-
- //
- // Update internal PEI_CORE_FV array.
- //
- PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvInfo;
- PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
- PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
- PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = AuthenticationStatus;
- CurFvCount = PrivateData->FvCount;
- DEBUG ((
- DEBUG_INFO,
- "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
- (UINT32)CurFvCount,
- (VOID *)FvInfo,
- FvInfoSize,
- FvHandle
- ));
- PrivateData->FvCount++;
-
- //
- // Scan and process the new discovered FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
- //
- FileHandle = NULL;
- do {
- Status = FvPpi->FindFileByType (
- FvPpi,
- EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
- FvHandle,
- &FileHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = FvPpi->FindSectionByType (
- FvPpi,
- EFI_SECTION_PEI_DEPEX,
- FileHandle,
- (VOID **)&DepexData
- );
- if (!EFI_ERROR (Status)) {
- if (!PeimDispatchReadiness (PeiServices, DepexData)) {
- //
- // Dependency is not satisfied.
- //
- continue;
- }
- }
-
- DEBUG ((DEBUG_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle));
- ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle);
- }
- } while (FileHandle != NULL);
- } while (TRUE);
-}
+/** @file + Pei Core Firmware File System service routines. + +Copyright (c) 2015 HP Development Company, L.P. +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "FwVol.h" + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList[] = { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + &gEfiPeiFirmwareVolumeInfoPpiGuid, + FirmwareVolumeInfoPpiNotifyCallback + }, + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiFirmwareVolumeInfo2PpiGuid, + FirmwareVolumeInfoPpiNotifyCallback + } +}; + +PEI_FW_VOL_INSTANCE mPeiFfs2FwVol = { + PEI_FW_VOL_SIGNATURE, + FALSE, + { + PeiFfsFvPpiProcessVolume, + PeiFfsFvPpiFindFileByType, + PeiFfsFvPpiFindFileByName, + PeiFfsFvPpiGetFileInfo, + PeiFfsFvPpiGetVolumeInfo, + PeiFfsFvPpiFindSectionByType, + PeiFfsFvPpiGetFileInfo2, + PeiFfsFvPpiFindSectionByType2, + EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE, + EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION + } +}; + +PEI_FW_VOL_INSTANCE mPeiFfs3FwVol = { + PEI_FW_VOL_SIGNATURE, + TRUE, + { + PeiFfsFvPpiProcessVolume, + PeiFfsFvPpiFindFileByType, + PeiFfsFvPpiFindFileByName, + PeiFfsFvPpiGetFileInfo, + PeiFfsFvPpiGetVolumeInfo, + PeiFfsFvPpiFindSectionByType, + PeiFfsFvPpiGetFileInfo2, + PeiFfsFvPpiFindSectionByType2, + EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE, + EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION + } +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiFfs2FvPpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiFirmwareFileSystem2Guid, + &mPeiFfs2FwVol.Fv +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiFfs3FvPpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiFirmwareFileSystem3Guid, + &mPeiFfs3FwVol.Fv +}; + +/** +Required Alignment Alignment Value in FFS FFS_ATTRIB_DATA_ALIGNMENT2 Alignment Value in +(bytes) Attributes Field in FFS Attributes Field Firmware Volume Interfaces +1 0 0 0 +16 1 0 4 +128 2 0 7 +512 3 0 9 +1 KB 4 0 10 +4 KB 5 0 12 +32 KB 6 0 15 +64 KB 7 0 16 +128 KB 0 1 17 +256 KB 1 1 18 +512 KB 2 1 19 +1 MB 3 1 20 +2 MB 4 1 21 +4 MB 5 1 22 +8 MB 6 1 23 +16 MB 7 1 24 +**/ +UINT8 mFvAttributes[] = { 0, 4, 7, 9, 10, 12, 15, 16 }; +UINT8 mFvAttributes2[] = { 17, 18, 19, 20, 21, 22, 23, 24 }; + +/** + Convert the FFS File Attributes to FV File Attributes + + @param FfsAttributes The attributes of UINT8 type. + + @return The attributes of EFI_FV_FILE_ATTRIBUTES + +**/ +EFI_FV_FILE_ATTRIBUTES +FfsAttributes2FvFileAttributes ( + IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes + ) +{ + UINT8 DataAlignment; + EFI_FV_FILE_ATTRIBUTES FileAttribute; + + DataAlignment = (UINT8)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3); + ASSERT (DataAlignment < 8); + + if ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT_2) != 0) { + FileAttribute = (EFI_FV_FILE_ATTRIBUTES)mFvAttributes2[DataAlignment]; + } else { + FileAttribute = (EFI_FV_FILE_ATTRIBUTES)mFvAttributes[DataAlignment]; + } + + if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) { + FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED; + } + + return FileAttribute; +} + +/** + Returns the file state set by the highest zero bit in the State field + + @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY + in the Attributes field. + @param FfsHeader Pointer to FFS File Header. + + @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit + in the header State field. +**/ +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE) ~FileState; + } + + // + // Get file state set by its highest none zero bit. + // + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +/** + Calculates the checksum of the header of a file. + + @param FileHeader Pointer to FFS File Header. + + @return Checksum of the header. + Zero means the header is good. + Non-zero means the header is bad. +**/ +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +{ + EFI_FFS_FILE_HEADER2 TestFileHeader; + + if (IS_FFS_FILE2 (FileHeader)) { + CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER2)); + // + // Ignore State and File field in FFS header. + // + TestFileHeader.State = 0; + TestFileHeader.IntegrityCheck.Checksum.File = 0; + + return CalculateSum8 ((CONST UINT8 *)&TestFileHeader, sizeof (EFI_FFS_FILE_HEADER2)); + } else { + CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER)); + // + // Ignore State and File field in FFS header. + // + TestFileHeader.State = 0; + TestFileHeader.IntegrityCheck.Checksum.File = 0; + + return CalculateSum8 ((CONST UINT8 *)&TestFileHeader, sizeof (EFI_FFS_FILE_HEADER)); + } +} + +/** + Find FV handler according to FileHandle in that FV. + + @param FileHandle Handle of file image + + @return Pointer to instance of PEI_CORE_FV_HANDLE. +**/ +PEI_CORE_FV_HANDLE * +FileHandleToVolume ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +{ + UINTN Index; + PEI_CORE_INSTANCE *PrivateData; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINTN BestIndex; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + BestIndex = PrivateData->FvCount; + + // + // Find the best matched FV image that includes this FileHandle. + // FV may include the child FV, and they are in the same continuous space. + // If FileHandle is from the child FV, the updated logic can find its matched FV. + // + for (Index = 0; Index < PrivateData->FvCount; Index++) { + FwVolHeader = PrivateData->Fv[Index].FvHeader; + if (((UINT64)(UINTN)FileHandle > (UINT64)(UINTN)FwVolHeader) && \ + ((UINT64)(UINTN)FileHandle <= ((UINT64)(UINTN)FwVolHeader + FwVolHeader->FvLength - 1))) + { + if (BestIndex == PrivateData->FvCount) { + BestIndex = Index; + } else { + if ((UINT64)(UINTN)PrivateData->Fv[BestIndex].FvHeader < (UINT64)(UINTN)FwVolHeader) { + BestIndex = Index; + } + } + } + } + + if (BestIndex < PrivateData->FvCount) { + return &PrivateData->Fv[BestIndex]; + } + + return NULL; +} + +/** + Given the input file pointer, search for the first matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type. + If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, + the first PEIM, or COMBINED PEIM or FV file type FFS file will return. + + @param FvHandle Pointer to the FV header of the volume to search + @param FileName File name + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FileHandle This parameter must point to a valid FFS volume. + @param AprioriFile Pointer to AprioriFile image in this FV if has + + @return EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS Success to search given file + +**/ +EFI_STATUS +FindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName OPTIONAL, + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader; + EFI_FFS_FILE_HEADER **FileHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + UINT8 DataCheckSum; + BOOLEAN IsFfs3Fv; + + // + // Convert the handle of FV to FV header for memory-mapped firmware volume + // + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle; + FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle; + + IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); + + FvLength = FwVolHeader->FvLength; + if ((FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) or FileName is not NULL, + // start with the first file in the firmware volume. Otherwise, + // start from the FileHeader. + // + if ((*FileHeader == NULL) || (FileName != NULL)) { + if (FwVolHeader->ExtHeaderOffset != 0) { + // + // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. + // + FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->ExtHeaderOffset); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolExtHeader + FwVolExtHeader->ExtHeaderSize); + } else { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + } + + FfsFileHeader = (EFI_FFS_FILE_HEADER *)ALIGN_POINTER (FfsFileHeader, 8); + } else { + if (IS_FFS_FILE2 (*FileHeader)) { + if (!IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &(*FileHeader)->Name)); + } + + FileLength = FFS_FILE2_SIZE (*FileHeader); + ASSERT (FileLength > 0x00FFFFFF); + } else { + FileLength = FFS_FILE_SIZE (*FileHeader); + } + + // + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32)((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + ASSERT (FileOffset <= 0xFFFFFFFF); + + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + switch (FileState) { + case EFI_FILE_HEADER_CONSTRUCTION: + case EFI_FILE_HEADER_INVALID: + if (IS_FFS_FILE2 (FfsFileHeader)) { + if (!IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name)); + } + + FileOffset += sizeof (EFI_FFS_FILE_HEADER2); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); + } else { + FileOffset += sizeof (EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER)); + } + + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) != 0) { + ASSERT (FALSE); + *FileHeader = NULL; + return EFI_NOT_FOUND; + } + + if (IS_FFS_FILE2 (FfsFileHeader)) { + FileLength = FFS_FILE2_SIZE (FfsFileHeader); + ASSERT (FileLength > 0x00FFFFFF); + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + if (!IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name)); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + } + } else { + FileLength = FFS_FILE_SIZE (FfsFileHeader); + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + } + + DataCheckSum = FFS_FIXED_CHECKSUM; + if ((FfsFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { + if (IS_FFS_FILE2 (FfsFileHeader)) { + DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FileLength - sizeof (EFI_FFS_FILE_HEADER2)); + } else { + DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER), FileLength - sizeof (EFI_FFS_FILE_HEADER)); + } + } + + if (FfsFileHeader->IntegrityCheck.Checksum.File != DataCheckSum) { + ASSERT (FALSE); + *FileHeader = NULL; + return EFI_NOT_FOUND; + } + + if (FileName != NULL) { + if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID *)FileName)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) + { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } else if (AprioriFile != NULL) { + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) { + if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) { + *AprioriFile = (EFI_PEI_FILE_HANDLE)FfsFileHeader; + } + } + } + } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && + (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) + { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + case EFI_FILE_DELETED: + if (IS_FFS_FILE2 (FfsFileHeader)) { + if (!IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name)); + } + + FileLength = FFS_FILE2_SIZE (FfsFileHeader); + ASSERT (FileLength > 0x00FFFFFF); + } else { + FileLength = FFS_FILE_SIZE (FfsFileHeader); + } + + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + *FileHeader = NULL; + return EFI_NOT_FOUND; + } + } + + *FileHeader = NULL; + return EFI_NOT_FOUND; +} + +/** + Initialize PeiCore FV List. + + @param PrivateData - Pointer to PEI_CORE_INSTANCE. + @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. +**/ +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +{ + EFI_STATUS Status; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + EFI_PEI_FV_HANDLE FvHandle; + EFI_FIRMWARE_VOLUME_HEADER *BfvHeader; + + // + // Install FV_PPI for FFS2 file system. + // + PeiServicesInstallPpi (&mPeiFfs2FvPpiList); + + // + // Install FV_PPI for FFS3 file system. + // + PeiServicesInstallPpi (&mPeiFfs3FvPpiList); + + BfvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; + + // + // The FV_PPI in BFV's format should be installed. + // + Status = PeiServicesLocatePpi ( + &BfvHeader->FileSystemGuid, + 0, + NULL, + (VOID **)&FvPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Get handle of BFV + // + Status = FvPpi->ProcessVolume ( + FvPpi, + SecCoreData->BootFirmwareVolumeBase, + (UINTN)BfvHeader->FvLength, + &FvHandle + ); + ASSERT_EFI_ERROR (Status); + + PrivateData->Fv = AllocateZeroPool (sizeof (PEI_CORE_FV_HANDLE) * FV_GROWTH_STEP); + ASSERT (PrivateData->Fv != NULL); + PrivateData->MaxFvCount = FV_GROWTH_STEP; + + // + // Update internal PEI_CORE_FV array. + // + PrivateData->Fv[PrivateData->FvCount].FvHeader = BfvHeader; + PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi; + PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle; + PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = 0; + DEBUG (( + DEBUG_INFO, + "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", + (UINT32)PrivateData->FvCount, + (VOID *)BfvHeader, + (UINT32)BfvHeader->FvLength, + FvHandle + )); + PrivateData->FvCount++; + + // + // Post a call-back for the FvInfoPPI and FvInfo2PPI services to expose + // additional FVs to PeiCore. + // + Status = PeiServicesNotifyPpi (mNotifyOnFvInfoList); + ASSERT_EFI_ERROR (Status); +} + +/** + Process Firmware Volume Information once FvInfoPPI or FvInfo2PPI install. + The FV Info will be registered into PeiCore private data structure. + And search the inside FV image, if found, the new FV INFO(2) PPI will be installed. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure. + @return if not EFI_SUCCESS, fail to verify FV. + +**/ +EFI_STATUS +EFIAPI +FirmwareVolumeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI FvInfo2Ppi; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FvHandle; + UINTN FvIndex; + EFI_PEI_FILE_HANDLE FileHandle; + VOID *DepexData; + BOOLEAN IsFvInfo2; + UINTN CurFvCount; + VOID *TempPtr; + + Status = EFI_SUCCESS; + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiFirmwareVolumeInfo2PpiGuid)) { + // + // It is FvInfo2PPI. + // + CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI)); + IsFvInfo2 = TRUE; + } else { + // + // It is FvInfoPPI. + // + CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI)); + FvInfo2Ppi.AuthenticationStatus = 0; + IsFvInfo2 = FALSE; + } + + if (CompareGuid (&FvInfo2Ppi.FvFormat, &gEfiFirmwareFileSystem2Guid)) { + // + // gEfiFirmwareFileSystem2Guid is specified for FvFormat, then here to check the + // FileSystemGuid pointed by FvInfo against gEfiFirmwareFileSystem2Guid to make sure + // FvInfo has the firmware file system 2 format. + // + // If the ASSERT really appears, FvFormat needs to be specified correctly, for example, + // gEfiFirmwareFileSystem3Guid can be used for firmware file system 3 format, or + // ((EFI_FIRMWARE_VOLUME_HEADER *) FvInfo)->FileSystemGuid can be just used for both + // firmware file system 2 and 3 format. + // + ASSERT (CompareGuid (&(((EFI_FIRMWARE_VOLUME_HEADER *)FvInfo2Ppi.FvInfo)->FileSystemGuid), &gEfiFirmwareFileSystem2Guid)); + } + + // + // Locate the corresponding FV_PPI according to the format GUID of the FV found + // + Status = PeiServicesLocatePpi ( + &FvInfo2Ppi.FvFormat, + 0, + NULL, + (VOID **)&FvPpi + ); + if (!EFI_ERROR (Status)) { + // + // Process new found FV and get FV handle. + // + Status = FvPpi->ProcessVolume (FvPpi, FvInfo2Ppi.FvInfo, FvInfo2Ppi.FvInfoSize, &FvHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to process new found FV, FV may be corrupted!\n")); + return Status; + } + + // + // Check whether the FV has already been processed. + // + for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex++) { + if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) { + if (IsFvInfo2 && (FvInfo2Ppi.AuthenticationStatus != PrivateData->Fv[FvIndex].AuthenticationStatus)) { + PrivateData->Fv[FvIndex].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus; + DEBUG ((DEBUG_INFO, "Update AuthenticationStatus of the %dth FV to 0x%x!\n", FvIndex, FvInfo2Ppi.AuthenticationStatus)); + } + + DEBUG ((DEBUG_INFO, "The FV %p has already been processed!\n", FvInfo2Ppi.FvInfo)); + return EFI_SUCCESS; + } + } + + if (PrivateData->FvCount >= PrivateData->MaxFvCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_CORE_FV_HANDLE) * (PrivateData->MaxFvCount + FV_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + PrivateData->Fv, + sizeof (PEI_CORE_FV_HANDLE) * PrivateData->MaxFvCount + ); + PrivateData->Fv = TempPtr; + PrivateData->MaxFvCount = PrivateData->MaxFvCount + FV_GROWTH_STEP; + } + + // + // Update internal PEI_CORE_FV array. + // + PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvInfo2Ppi.FvInfo; + PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi; + PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle; + PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus; + CurFvCount = PrivateData->FvCount; + DEBUG (( + DEBUG_INFO, + "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", + (UINT32)CurFvCount, + (VOID *)FvInfo2Ppi.FvInfo, + FvInfo2Ppi.FvInfoSize, + FvHandle + )); + PrivateData->FvCount++; + + // + // Scan and process the new discovered FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE + // + FileHandle = NULL; + do { + Status = FvPpi->FindFileByType ( + FvPpi, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + FvHandle, + &FileHandle + ); + if (!EFI_ERROR (Status)) { + Status = FvPpi->FindSectionByType ( + FvPpi, + EFI_SECTION_PEI_DEPEX, + FileHandle, + (VOID **)&DepexData + ); + if (!EFI_ERROR (Status)) { + if (!PeimDispatchReadiness (PeiServices, DepexData)) { + // + // Dependency is not satisfied. + // + continue; + } + } + + DEBUG ((DEBUG_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle)); + ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle); + } + } while (FileHandle != NULL); + } else { + DEBUG ((DEBUG_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfo2Ppi.FvInfo)); + + AddUnknownFormatFvInfo (PrivateData, &FvInfo2Ppi); + } + + return EFI_SUCCESS; +} + +/** + Verify the Guided Section GUID by checking if there is the Guided Section GUID HOB recorded the GUID itself. + + @param GuidedSectionGuid The Guided Section GUID. + @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Ppi + for the Guided Section. + + @return TRUE The GuidedSectionGuid could be identified, and the pointer to + the Guided Section Extraction Ppi will be returned to *GuidedSectionExtraction. + @return FALSE The GuidedSectionGuid could not be identified, or + the Guided Section Extraction Ppi has not been installed yet. + +**/ +BOOLEAN +VerifyGuidedSectionGuid ( + IN EFI_GUID *GuidedSectionGuid, + OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI **GuidedSectionExtraction + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_GUID *GuidRecorded; + VOID *Interface; + EFI_STATUS Status; + + // + // Check if there is the Guided Section GUID HOB recorded the GUID itself. + // + Hob.Raw = GetFirstGuidHob (GuidedSectionGuid); + if (Hob.Raw != NULL) { + GuidRecorded = (EFI_GUID *)GET_GUID_HOB_DATA (Hob); + if (CompareGuid (GuidRecorded, GuidedSectionGuid)) { + // + // Found the recorded GuidedSectionGuid. + // + Status = PeiServicesLocatePpi (GuidedSectionGuid, 0, NULL, (VOID **)&Interface); + if (!EFI_ERROR (Status) && (Interface != NULL)) { + // + // Found the supported Guided Section Extraction Ppi for the Guided Section. + // + *GuidedSectionExtraction = (EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *)Interface; + return TRUE; + } + + return FALSE; + } + } + + return FALSE; +} + +/** + Go through the file to search SectionType section. + Search within encapsulation sections (compression and GUIDed) recursively, + until the match section is found. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType Filter to find only section of this type. + @param SectionInstance Pointer to the filter to find the specific instance of section. + @param Section From where to search. + @param SectionSize The file size to search. + @param OutputBuffer A pointer to the discovered section, if successful. + NULL if section not found + @param AuthenticationStatus Updated upon return to point to the authentication status for this section. + @param IsFfs3Fv Indicates the FV format. + + @return EFI_NOT_FOUND The match section is not found. + @return EFI_SUCCESS The match section is found. + +**/ +EFI_STATUS +ProcessSection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN OUT UINTN *SectionInstance, + IN EFI_COMMON_SECTION_HEADER *Section, + IN UINTN SectionSize, + OUT VOID **OutputBuffer, + OUT UINT32 *AuthenticationStatus, + IN BOOLEAN IsFfs3Fv + ) +{ + EFI_STATUS Status; + UINT32 SectionLength; + UINT32 ParsedLength; + EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi; + EFI_PEI_DECOMPRESS_PPI *DecompressPpi; + VOID *PpiOutput; + UINTN PpiOutputSize; + UINTN Index; + UINT32 Authentication; + PEI_CORE_INSTANCE *PrivateData; + EFI_GUID *SectionDefinitionGuid; + BOOLEAN SectionCached; + VOID *TempOutputBuffer; + UINT32 TempAuthenticationStatus; + UINT16 GuidedSectionAttributes; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + *OutputBuffer = NULL; + ParsedLength = 0; + Index = 0; + Status = EFI_NOT_FOUND; + PpiOutput = NULL; + PpiOutputSize = 0; + while (ParsedLength < SectionSize) { + if (IS_SECTION2 (Section)) { + ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF); + if (!IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n")); + SectionLength = SECTION2_SIZE (Section); + // + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + ASSERT (SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + continue; + } + } + + if (Section->Type == SectionType) { + // + // The type matches, so check the instance count to see if it's the one we want. + // + (*SectionInstance)--; + if (*SectionInstance == 0) { + // + // Got it! + // + if (IS_SECTION2 (Section)) { + *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + *OutputBuffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + + return EFI_SUCCESS; + } else { + if (IS_SECTION2 (Section)) { + SectionLength = SECTION2_SIZE (Section); + } else { + SectionLength = SECTION_SIZE (Section); + } + + // + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + ASSERT (SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + continue; + } + } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) { + // + // Check the encapsulated section is extracted into the cache data. + // + SectionCached = FALSE; + for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index++) { + if (Section == PrivateData->CacheSection.Section[Index]) { + SectionCached = TRUE; + PpiOutput = PrivateData->CacheSection.SectionData[Index]; + PpiOutputSize = PrivateData->CacheSection.SectionSize[Index]; + Authentication = PrivateData->CacheSection.AuthenticationStatus[Index]; + // + // Search section directly from the cache data. + // + TempAuthenticationStatus = 0; + Status = ProcessSection ( + PeiServices, + SectionType, + SectionInstance, + PpiOutput, + PpiOutputSize, + &TempOutputBuffer, + &TempAuthenticationStatus, + IsFfs3Fv + ); + if (!EFI_ERROR (Status)) { + *OutputBuffer = TempOutputBuffer; + *AuthenticationStatus = TempAuthenticationStatus | Authentication; + return EFI_SUCCESS; + } + } + } + + // + // If SectionCached is TRUE, the section data has been cached and scanned. + // + if (!SectionCached) { + Status = EFI_NOT_FOUND; + Authentication = 0; + if (Section->Type == EFI_SECTION_GUID_DEFINED) { + if (IS_SECTION2 (Section)) { + SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION2 *)Section)->SectionDefinitionGuid; + GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *)Section)->Attributes; + } else { + SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid; + GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION *)Section)->Attributes; + } + + if (VerifyGuidedSectionGuid (SectionDefinitionGuid, &GuidSectionPpi)) { + Status = GuidSectionPpi->ExtractSection ( + GuidSectionPpi, + Section, + &PpiOutput, + &PpiOutputSize, + &Authentication + ); + } else if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { + // + // Figure out the proper authentication status for GUIDED section without processing required + // + Status = EFI_SUCCESS; + if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { + Authentication |= EFI_AUTH_STATUS_IMAGE_SIGNED | EFI_AUTH_STATUS_NOT_TESTED; + } + + if (IS_SECTION2 (Section)) { + PpiOutputSize = SECTION2_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION2 *)Section)->DataOffset; + PpiOutput = (UINT8 *)Section + ((EFI_GUID_DEFINED_SECTION2 *)Section)->DataOffset; + } else { + PpiOutputSize = SECTION_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION *)Section)->DataOffset; + PpiOutput = (UINT8 *)Section + ((EFI_GUID_DEFINED_SECTION *)Section)->DataOffset; + } + } + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **)&DecompressPpi); + if (!EFI_ERROR (Status)) { + Status = DecompressPpi->Decompress ( + DecompressPpi, + (CONST EFI_COMPRESSION_SECTION *)Section, + &PpiOutput, + &PpiOutputSize + ); + } + } + + if (!EFI_ERROR (Status)) { + if ((Authentication & EFI_AUTH_STATUS_NOT_TESTED) == 0) { + // + // Update cache section data. + // + if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) { + PrivateData->CacheSection.AllSectionCount++; + } + + PrivateData->CacheSection.Section[PrivateData->CacheSection.SectionIndex] = Section; + PrivateData->CacheSection.SectionData[PrivateData->CacheSection.SectionIndex] = PpiOutput; + PrivateData->CacheSection.SectionSize[PrivateData->CacheSection.SectionIndex] = PpiOutputSize; + PrivateData->CacheSection.AuthenticationStatus[PrivateData->CacheSection.SectionIndex] = Authentication; + PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER; + } + + TempAuthenticationStatus = 0; + Status = ProcessSection ( + PeiServices, + SectionType, + SectionInstance, + PpiOutput, + PpiOutputSize, + &TempOutputBuffer, + &TempAuthenticationStatus, + IsFfs3Fv + ); + if (!EFI_ERROR (Status)) { + *OutputBuffer = TempOutputBuffer; + *AuthenticationStatus = TempAuthenticationStatus | Authentication; + return EFI_SUCCESS; + } + } + } + } + + if (IS_SECTION2 (Section)) { + SectionLength = SECTION2_SIZE (Section); + } else { + SectionLength = SECTION_SIZE (Section); + } + + // + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + ASSERT (SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; +} + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param SectionType Filter to find only sections of this type. + @param FileHandle Pointer to the current file to search. + @param SectionData A pointer to the discovered section, if successful. + NULL if section not found + + @retval EFI_NOT_FOUND The section was not found. + @retval EFI_SUCCESS The section was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +{ + PEI_CORE_FV_HANDLE *CoreFvHandle; + + CoreFvHandle = FileHandleToVolume (FileHandle); + if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) { + return EFI_NOT_FOUND; + } + + return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData); +} + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType The value of the section type to find. + @param SectionInstance Section instance to find. + @param FileHandle Handle of the firmware file to search. + @param SectionData A pointer to the discovered section, if successful. + @param AuthenticationStatus A pointer to the authentication status for this section. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindSectionData3 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ) +{ + PEI_CORE_FV_HANDLE *CoreFvHandle; + + CoreFvHandle = FileHandleToVolume (FileHandle); + if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) { + return EFI_NOT_FOUND; + } + + if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) && + (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) + { + return CoreFvHandle->FvPpi->FindSectionByType2 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus); + } + + // + // The old FvPpi doesn't support to find section by section instance + // and return authentication status, so return EFI_UNSUPPORTED. + // + return EFI_UNSUPPORTED; +} + +/** + Searches for the next matching file in the firmware volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FvHandle Handle of firmware volume in which to search. + @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start + at the beginning of the firmware volume. On exit, points the file handle of the next file + in the volume or NULL if there are no more files. + + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + @retval EFI_SUCCESS The file was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + PEI_CORE_FV_HANDLE *CoreFvHandle; + + CoreFvHandle = FvHandleToCoreHandle (FvHandle); + + if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) { + return EFI_NOT_FOUND; + } + + return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle); +} + +/** + Search the firmware volumes by index + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware + Volume (BFV). + @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist. + + @retval EFI_INVALID_PARAMETER VolumeHandle is NULL + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_SUCCESS The volume was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + PEI_CORE_INSTANCE *Private; + PEI_CORE_FV_HANDLE *CoreFvHandle; + + if (VolumeHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + CoreFvHandle = FindNextCoreFvHandle (Private, Instance); + if (CoreFvHandle == NULL) { + *VolumeHandle = NULL; + return EFI_NOT_FOUND; + } + + *VolumeHandle = CoreFvHandle->FvHandle; + + return EFI_SUCCESS; +} + +/** + Find a file within a volume by its name. + + @param FileName A pointer to the name of the file to find within the firmware volume. + @param VolumeHandle The firmware volume to search + @param FileHandle Upon exit, points to the found file's handle + or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + @retval EFI_NOT_FOUND File was not found. + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + PEI_CORE_FV_HANDLE *CoreFvHandle; + + if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CoreFvHandle = FvHandleToCoreHandle (VolumeHandle); + if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) { + return EFI_NOT_FOUND; + } + + return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle); +} + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + PEI_CORE_FV_HANDLE *CoreFvHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + CoreFvHandle = FileHandleToVolume (FileHandle); + if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo); +} + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo2 ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ) +{ + PEI_CORE_FV_HANDLE *CoreFvHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + CoreFvHandle = FileHandleToVolume (FileHandle); + if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) && + (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) + { + return CoreFvHandle->FvPpi->GetFileInfo2 (CoreFvHandle->FvPpi, FileHandle, FileInfo); + } + + // + // The old FvPpi doesn't support to return file info with authentication status, + // so return EFI_UNSUPPORTED. + // + return EFI_UNSUPPORTED; +} + +/** + Returns information about the specified volume. + + This function returns information about a specific firmware + volume, including its name, type, attributes, starting address + and size. + + @param VolumeHandle Handle of the volume. + @param VolumeInfo Upon exit, points to the volume's information. + + @retval EFI_SUCCESS Volume information returned. + @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume. + @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL. + @retval EFI_SUCCESS Information successfully returned. + @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + PEI_CORE_FV_HANDLE *CoreHandle; + + if ((VolumeInfo == NULL) || (VolumeHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CoreHandle = FvHandleToCoreHandle (VolumeHandle); + + if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo); +} + +/** + Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size. + + @param[in] FvHeader Pointer to FV header. + @param[out] FvUsedSize Pointer to FV used size returned, + only valid if USED_SIZE FV_EXT_TYPE entry is found. + @param[out] EraseByte Pointer to erase byte returned, + only valid if USED_SIZE FV_EXT_TYPE entry is found. + + @retval TRUE USED_SIZE FV_EXT_TYPE entry is found, + FV used size and erase byte are returned. + @retval FALSE No USED_SIZE FV_EXT_TYPE entry found. + +**/ +BOOLEAN +GetFvUsedSize ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader, + OUT UINT32 *FvUsedSize, + OUT UINT8 *EraseByte + ) +{ + UINT16 ExtHeaderOffset; + EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader; + EFI_FIRMWARE_VOLUME_EXT_ENTRY *ExtEntryList; + EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *ExtEntryUsedSize; + + ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset); + if (ExtHeaderOffset != 0) { + ExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FvHeader + ExtHeaderOffset); + ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)(ExtHeader + 1); + while ((UINTN)ExtEntryList < ((UINTN)ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) { + if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) { + // + // USED_SIZE FV_EXT_TYPE entry is found. + // + ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)ExtEntryList; + *FvUsedSize = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize); + if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) { + *EraseByte = 0xFF; + } else { + *EraseByte = 0; + } + + DEBUG (( + DEBUG_INFO, + "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n", + FvHeader, + *FvUsedSize, + *EraseByte + )); + return TRUE; + } + + ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *) + ((UINT8 *)ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize)); + } + } + + // + // No USED_SIZE FV_EXT_TYPE entry found. + // + return FALSE; +} + +/** + Get FV image(s) from the FV type file, then install FV INFO(2) PPI, Build FV(2, 3) HOB. + + @param PrivateData PeiCore's private data structure + @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent FV image that contain this FV image. + @param ParentFvFileHandle File handle of a FV type file that contain this FV image. + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image + @retval EFI_SECURITY_VIOLATION Image is illegal + @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section + +**/ +EFI_STATUS +ProcessFvFile ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle, + IN EFI_PEI_FILE_HANDLE ParentFvFileHandle + ) +{ + EFI_STATUS Status; + EFI_FV_INFO ParentFvImageInfo; + UINT32 FvAlignment; + VOID *NewFvBuffer; + EFI_PEI_HOB_POINTERS HobPtr; + EFI_PEI_FIRMWARE_VOLUME_PPI *ParentFvPpi; + EFI_PEI_FV_HANDLE ParentFvHandle; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FV_FILE_INFO FileInfo; + UINT64 FvLength; + UINT32 AuthenticationStatus; + UINT32 FvUsedSize; + UINT8 EraseByte; + UINTN Index; + + // + // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already + // been extracted. + // + HobPtr.Raw = GetHobList (); + while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) { + if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) { + // + // this FILE has been dispatched, it will not be dispatched again. + // + DEBUG ((DEBUG_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle)); + return EFI_SUCCESS; + } + + HobPtr.Raw = GET_NEXT_HOB (HobPtr); + } + + ParentFvHandle = ParentFvCoreHandle->FvHandle; + ParentFvPpi = ParentFvCoreHandle->FvPpi; + + Status = EFI_SUCCESS; + + // + // Find FvImage(s) in FvFile + // + Index = 0; + do { + AuthenticationStatus = 0; + if ((ParentFvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) && + (ParentFvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) + { + Status = ParentFvPpi->FindSectionByType2 ( + ParentFvPpi, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + Index, + ParentFvFileHandle, + (VOID **)&FvHeader, + &AuthenticationStatus + ); + } else { + // + // Old FvPpi has no parameter to input SearchInstance, + // only one instance is supported. + // + if (Index > 0) { + break; + } + + Status = ParentFvPpi->FindSectionByType ( + ParentFvPpi, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + ParentFvFileHandle, + (VOID **)&FvHeader + ); + } + + if (EFI_ERROR (Status)) { + break; + } + + Status = VerifyPeim (PrivateData, ParentFvHandle, ParentFvFileHandle, AuthenticationStatus); + if (Status == EFI_SECURITY_VIOLATION) { + break; + } + + // + // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume + // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from + // its initial linked location and maintain its alignment. + // + if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) { + // + // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. + // + FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16); + if (FvAlignment < 8) { + FvAlignment = 8; + } + + DEBUG (( + DEBUG_INFO, + "%a() FV at 0x%x, FvAlignment required is 0x%x\n", + __func__, + FvHeader, + FvAlignment + )); + + // + // Check FvImage alignment. + // + if ((UINTN)FvHeader % FvAlignment != 0) { + FvLength = ReadUnaligned64 (&FvHeader->FvLength); + NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32)FvLength), FvAlignment); + if (NewFvBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) { + // + // Copy the used bytes and fill the rest with the erase value. + // + CopyMem (NewFvBuffer, FvHeader, (UINTN)FvUsedSize); + SetMem ( + (UINT8 *)NewFvBuffer + FvUsedSize, + (UINTN)(FvLength - FvUsedSize), + EraseByte + ); + } else { + CopyMem (NewFvBuffer, FvHeader, (UINTN)FvLength); + } + + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NewFvBuffer; + } + } + + Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo); + ASSERT_EFI_ERROR (Status); + + Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo); + ASSERT_EFI_ERROR (Status); + + // + // Install FvInfo(2) Ppi + // NOTE: FvInfo2 must be installed before FvInfo so that recursive processing of encapsulated + // FVs inherit the proper AuthenticationStatus. + // + PeiServicesInstallFvInfo2Ppi ( + &FvHeader->FileSystemGuid, + (VOID **)FvHeader, + (UINT32)FvHeader->FvLength, + &ParentFvImageInfo.FvName, + &FileInfo.FileName, + AuthenticationStatus + ); + + PeiServicesInstallFvInfoPpi ( + &FvHeader->FileSystemGuid, + (VOID **)FvHeader, + (UINT32)FvHeader->FvLength, + &ParentFvImageInfo.FvName, + &FileInfo.FileName + ); + + // + // Expose the extracted FvImage to the FV HOB consumer phase, i.e. DXE phase + // + BuildFvHob ( + (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader, + FvHeader->FvLength + ); + + // + // Makes the encapsulated volume show up in DXE phase to skip processing of + // encapsulated file again. + // + BuildFv2Hob ( + (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader, + FvHeader->FvLength, + &ParentFvImageInfo.FvName, + &FileInfo.FileName + ); + + // + // Build FV3 HOB with authentication status to be propagated to DXE. + // + BuildFv3Hob ( + (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader, + FvHeader->FvLength, + AuthenticationStatus, + TRUE, + &ParentFvImageInfo.FvName, + &FileInfo.FileName + ); + + Index++; + } while (TRUE); + + if (Index > 0) { + // + // At least one FvImage has been processed successfully. + // + return EFI_SUCCESS; + } else { + return Status; + } +} + +/** + Process a firmware volume and create a volume handle. + + Create a volume handle from the information in the buffer. For + memory-mapped firmware volumes, Buffer and BufferSize refer to + the start of the firmware volume and the firmware volume size. + For non memory-mapped firmware volumes, this points to a + buffer which contains the necessary information for creating + the firmware volume handle. Normally, these values are derived + from the EFI_FIRMWARE_VOLUME_INFO_PPI. + + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param Buffer Points to the start of the buffer. + @param BufferSize Size of the buffer. + @param FvHandle Points to the returned firmware volume + handle. The firmware volume handle must + be unique within the system. + + @retval EFI_SUCCESS Firmware volume handle created. + @retval EFI_VOLUME_CORRUPTED Volume was corrupt. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiProcessVolume ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN VOID *Buffer, + IN UINTN BufferSize, + OUT EFI_PEI_FV_HANDLE *FvHandle + ) +{ + EFI_STATUS Status; + + ASSERT (FvHandle != NULL); + + if (Buffer == NULL) { + return EFI_VOLUME_CORRUPTED; + } + + // + // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped + // FV image and the handle is pointed to FV image's buffer. + // + *FvHandle = (EFI_PEI_FV_HANDLE)Buffer; + + // + // Do verify for given FV buffer. + // + Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER *)Buffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to verify FV which address is 0x%11p", Buffer)); + return EFI_VOLUME_CORRUPTED; + } + + return EFI_SUCCESS; +} + +/** + Finds the next file of the specified type. + + This service enables PEI modules to discover additional firmware files. + The FileHandle must be unique within the system. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only files of this type. Type + EFI_FV_FILETYPE_ALL causes no filtering to be + done. + @param FvHandle Handle of firmware volume in which to + search. + @param FileHandle Points to the current handle from which to + begin searching or NULL to start at the + beginning of the firmware volume. Updated + upon return to reflect the file found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindFileByType ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL); +} + +/** + Find a file within a volume by its name. + + This service searches for files with a specific name, within + either the specified firmware volume or all firmware volumes. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileName A pointer to the name of the file to find + within the firmware volume. + @param FvHandle Upon entry, the pointer to the firmware + volume to search or NULL if all firmware + volumes should be searched. Upon exit, the + actual firmware volume in which the file was + found. + @param FileHandle Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + @retval EFI_NOT_FOUND File was not found. + @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or + FileName was NULL. + + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindFileByName ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE *FvHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + EFI_STATUS Status; + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + + if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*FvHandle != NULL) { + Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL); + if (Status == EFI_NOT_FOUND) { + *FileHandle = NULL; + } + } else { + // + // If *FvHandle = NULL, so search all FV for given filename + // + Status = EFI_NOT_FOUND; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + for (Index = 0; Index < PrivateData->FvCount; Index++) { + // + // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance. + // + if (PrivateData->Fv[Index].FvPpi != NULL) { + Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL); + if (!EFI_ERROR (Status)) { + *FvHandle = PrivateData->Fv[Index].FvHandle; + break; + } + } + } + } + + return Status; +} + +/** + Returns information about a specific file. + + This function returns information about a specific + file, including its file name, type, attributes, starting + address and size. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiGetFileInfo ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + UINT8 FileState; + UINT8 ErasePolarity; + EFI_FFS_FILE_HEADER *FileHeader; + PEI_CORE_FV_HANDLE *CoreFvHandle; + PEI_FW_VOL_INSTANCE *FwVolInstance; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + CoreFvHandle = FileHandleToVolume (FileHandle); + if (CoreFvHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This); + + if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER *)FileHandle); + + switch (FileState) { + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + break; + default: + return EFI_INVALID_PARAMETER; + } + + FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + if (IS_FFS_FILE2 (FileHeader)) { + ASSERT (FFS_FILE2_SIZE (FileHeader) > 0x00FFFFFF); + if (!FwVolInstance->IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader->Name)); + return EFI_INVALID_PARAMETER; + } + + FileInfo->BufferSize = FFS_FILE2_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER2); + FileInfo->Buffer = (UINT8 *)FileHeader + sizeof (EFI_FFS_FILE_HEADER2); + } else { + FileInfo->BufferSize = FFS_FILE_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER); + FileInfo->Buffer = (UINT8 *)FileHeader + sizeof (EFI_FFS_FILE_HEADER); + } + + CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof (EFI_GUID)); + FileInfo->FileType = FileHeader->Type; + FileInfo->FileAttributes = FfsAttributes2FvFileAttributes (FileHeader->Attributes); + if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) { + FileInfo->FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED; + } + + return EFI_SUCCESS; +} + +/** + Returns information about a specific file. + + This function returns information about a specific + file, including its file name, type, attributes, starting + address, size and authentication status. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiGetFileInfo2 ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ) +{ + EFI_STATUS Status; + PEI_CORE_FV_HANDLE *CoreFvHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + CoreFvHandle = FileHandleToVolume (FileHandle); + if (CoreFvHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = PeiFfsFvPpiGetFileInfo (This, FileHandle, (EFI_FV_FILE_INFO *)FileInfo); + if (!EFI_ERROR (Status)) { + FileInfo->AuthenticationStatus = CoreFvHandle->AuthenticationStatus; + } + + return Status; +} + +/** + This function returns information about the firmware volume. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FvHandle Handle to the firmware handle. + @param VolumeInfo Points to the returned firmware volume + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid + firmware volume or VolumeInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiGetVolumeInfo ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FV_HANDLE FvHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + EFI_FIRMWARE_VOLUME_HEADER FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + + if ((VolumeInfo == NULL) || (FvHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // VolumeHandle may not align at 8 byte, + // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. + // So, Copy FvHeader into the local FvHeader structure. + // + CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + + // + // Check FV Image Signature + // + if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO)); + VolumeInfo->FvAttributes = FwVolHeader.Attributes; + VolumeInfo->FvStart = (VOID *)FvHandle; + VolumeInfo->FvSize = FwVolHeader.FvLength; + CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof (EFI_GUID)); + + if (FwVolHeader.ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset); + CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof (EFI_GUID)); + } + + return EFI_SUCCESS; +} + +/** + Find the next matching section in the firmware file. + + This service enables PEI modules to discover sections + of a given type within a valid file. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only sections of this + type. + @param FileHandle Handle of firmware file in which to + search. + @param SectionData Updated upon return to point to the + section found. + + @retval EFI_SUCCESS Section was found. + @retval EFI_NOT_FOUND Section of the specified type was not + found. SectionData contains NULL. +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindSectionByType ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_SECTION_TYPE SearchType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +{ + UINT32 AuthenticationStatus; + + return PeiFfsFvPpiFindSectionByType2 (This, SearchType, 0, FileHandle, SectionData, &AuthenticationStatus); +} + +/** + Find the next matching section in the firmware file. + + This service enables PEI modules to discover sections + of a given instance and type within a valid file. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only sections of this + type. + @param SearchInstance A filter to find the specific instance + of sections. + @param FileHandle Handle of firmware file in which to + search. + @param SectionData Updated upon return to point to the + section found. + @param AuthenticationStatus Updated upon return to point to the + authentication status for this section. + + @retval EFI_SUCCESS Section was found. + @retval EFI_NOT_FOUND Section of the specified type was not + found. SectionData contains NULL. +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindSectionByType2 ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_SECTION_TYPE SearchType, + IN UINTN SearchInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + PEI_FW_VOL_INSTANCE *FwVolInstance; + PEI_CORE_FV_HANDLE *CoreFvHandle; + UINTN Instance; + UINT32 ExtractedAuthenticationStatus; + + if (SectionData == NULL) { + return EFI_NOT_FOUND; + } + + FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This); + + // + // Retrieve the FirmwareVolume which the file resides in. + // + CoreFvHandle = FileHandleToVolume (FileHandle); + if (CoreFvHandle == NULL) { + return EFI_NOT_FOUND; + } + + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle); + + if (IS_FFS_FILE2 (FfsFileHeader)) { + ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF); + if (!FwVolInstance->IsFfs3Fv) { + DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name)); + return EFI_NOT_FOUND; + } + + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); + FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2); + } else { + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER)); + FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER); + } + + Instance = SearchInstance + 1; + ExtractedAuthenticationStatus = 0; + Status = ProcessSection ( + GetPeiServicesTablePointer (), + SearchType, + &Instance, + Section, + FileSize, + SectionData, + &ExtractedAuthenticationStatus, + FwVolInstance->IsFfs3Fv + ); + if (!EFI_ERROR (Status)) { + // + // Inherit the authentication status. + // + *AuthenticationStatus = ExtractedAuthenticationStatus | CoreFvHandle->AuthenticationStatus; + } + + return Status; +} + +/** + Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE. + + @param FvHandle The handle of a FV. + + @retval NULL if can not find. + @return Pointer of corresponding PEI_CORE_FV_HANDLE. +**/ +PEI_CORE_FV_HANDLE * +FvHandleToCoreHandle ( + IN EFI_PEI_FV_HANDLE FvHandle + ) +{ + UINTN Index; + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + for (Index = 0; Index < PrivateData->FvCount; Index++) { + if (FvHandle == PrivateData->Fv[Index].FvHandle) { + return &PrivateData->Fv[Index]; + } + } + + return NULL; +} + +/** + Gets a PEI_CORE_FV_HANDLE instance for the next volume according to the given index. + + This routine also will install an instance of the FvInfo PPI for the FV HOB + as defined in the PI specification. + + @param Private Pointer of PEI_CORE_INSTANCE + @param Instance Index of the FV to search + + @return Instance of PEI_CORE_FV_HANDLE. +**/ +PEI_CORE_FV_HANDLE * +FindNextCoreFvHandle ( + IN PEI_CORE_INSTANCE *Private, + IN UINTN Instance + ) +{ + if (Instance >= Private->FvCount) { + return NULL; + } + + return &Private->Fv[Instance]; +} + +/** + After PeiCore image is shadowed into permanent memory, all build-in FvPpi should + be re-installed with the instance in permanent memory and all cached FvPpi pointers in + PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent + memory. + + @param PrivateData Pointer to PEI_CORE_INSTANCE. +**/ +VOID +PeiReinitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + VOID *OldFfsFvPpi; + EFI_PEI_PPI_DESCRIPTOR *OldDescriptor; + UINTN Index; + EFI_STATUS Status; + + // + // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which + // in flash. + // + Status = PeiServicesLocatePpi ( + &gEfiFirmwareFileSystem2Guid, + 0, + &OldDescriptor, + &OldFfsFvPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2 + // which is shadowed from flash to permanent memory within PeiCore image. + // + Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList); + ASSERT_EFI_ERROR (Status); + + // + // Fixup all FvPpi pointers for the implementation in flash to permanent memory. + // + for (Index = 0; Index < PrivateData->FvCount; Index++) { + if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) { + PrivateData->Fv[Index].FvPpi = &mPeiFfs2FwVol.Fv; + } + } + + // + // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which + // in flash. + // + Status = PeiServicesLocatePpi ( + &gEfiFirmwareFileSystem3Guid, + 0, + &OldDescriptor, + &OldFfsFvPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3 + // which is shadowed from flash to permanent memory within PeiCore image. + // + Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs3FvPpiList); + ASSERT_EFI_ERROR (Status); + + // + // Fixup all FvPpi pointers for the implementation in flash to permanent memory. + // + for (Index = 0; Index < PrivateData->FvCount; Index++) { + if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) { + PrivateData->Fv[Index].FvPpi = &mPeiFfs3FwVol.Fv; + } + } +} + +/** + Report the information for a newly discovered FV in an unknown format. + + If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for a third-party FV format, but + the FV has been discovered, then the information of this FV will be cached into PEI_CORE_INSTANCE's + UnknownFvInfo array. + + Also a notification would be installed for unknown FV format GUID, if EFI_PEI_FIRMWARE_VOLUME_PPI + is installed later by platform's PEIM, the original unknown FV will be processed by + using new installed EFI_PEI_FIRMWARE_VOLUME_PPI. + + @param PrivateData Point to instance of PEI_CORE_INSTANCE + @param FvInfo2Ppi Point to FvInfo2 PPI. + + @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces. + @retval EFI_SUCCESS Success to add the information for unknown FV. +**/ +EFI_STATUS +AddUnknownFormatFvInfo ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi + ) +{ + PEI_CORE_UNKNOW_FORMAT_FV_INFO *NewUnknownFv; + VOID *TempPtr; + + if (PrivateData->UnknownFvInfoCount >= PrivateData->MaxUnknownFvInfoCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO) * (PrivateData->MaxUnknownFvInfoCount + FV_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + PrivateData->UnknownFvInfo, + sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO) * PrivateData->MaxUnknownFvInfoCount + ); + PrivateData->UnknownFvInfo = TempPtr; + PrivateData->MaxUnknownFvInfoCount = PrivateData->MaxUnknownFvInfoCount + FV_GROWTH_STEP; + } + + NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount]; + PrivateData->UnknownFvInfoCount++; + + CopyGuid (&NewUnknownFv->FvFormat, &FvInfo2Ppi->FvFormat); + NewUnknownFv->FvInfo = FvInfo2Ppi->FvInfo; + NewUnknownFv->FvInfoSize = FvInfo2Ppi->FvInfoSize; + NewUnknownFv->AuthenticationStatus = FvInfo2Ppi->AuthenticationStatus; + NewUnknownFv->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + NewUnknownFv->NotifyDescriptor.Guid = &NewUnknownFv->FvFormat; + NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback; + + PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor); + return EFI_SUCCESS; +} + +/** + Find the FV information according to third-party FV format GUID. + + This routine also will remove the FV information found by given FV format GUID from + PrivateData->UnknownFvInfo[]. + + @param PrivateData Point to instance of PEI_CORE_INSTANCE + @param Format Point to given FV format GUID + @param FvInfo On return, the pointer of FV information buffer + @param FvInfoSize On return, the size of FV information buffer. + @param AuthenticationStatus On return, the authentication status of FV information buffer. + + @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI + @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI. +**/ +EFI_STATUS +FindUnknownFormatFvInfo ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_GUID *Format, + OUT VOID **FvInfo, + OUT UINT32 *FvInfoSize, + OUT UINT32 *AuthenticationStatus + ) +{ + UINTN Index; + UINTN Index2; + + Index = 0; + for ( ; Index < PrivateData->UnknownFvInfoCount; Index++) { + if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) { + break; + } + } + + if (Index == PrivateData->UnknownFvInfoCount) { + return EFI_NOT_FOUND; + } + + *FvInfo = PrivateData->UnknownFvInfo[Index].FvInfo; + *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize; + *AuthenticationStatus = PrivateData->UnknownFvInfo[Index].AuthenticationStatus; + + // + // Remove an entry from UnknownFvInfo array. + // + Index2 = Index + 1; + for ( ; Index2 < PrivateData->UnknownFvInfoCount; Index2++, Index++) { + CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO)); + } + + PrivateData->UnknownFvInfoCount--; + return EFI_SUCCESS; +} + +/** + Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI. + + When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this + routine is called to process all discovered FVs in this format. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The notification callback is processed correctly. +**/ +EFI_STATUS +EFIAPI +ThirdPartyFvPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + VOID *FvInfo; + UINT32 FvInfoSize; + UINT32 AuthenticationStatus; + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FvHandle; + BOOLEAN IsProcessed; + UINTN FvIndex; + EFI_PEI_FILE_HANDLE FileHandle; + VOID *DepexData; + UINTN CurFvCount; + VOID *TempPtr; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI *)Ppi; + + do { + Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize, &AuthenticationStatus); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Process new found FV and get FV handle. + // + Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo)); + continue; + } + + // + // Check whether the FV has already been processed. + // + IsProcessed = FALSE; + for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex++) { + if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) { + DEBUG ((DEBUG_INFO, "The FV %p has already been processed!\n", FvInfo)); + IsProcessed = TRUE; + break; + } + } + + if (IsProcessed) { + continue; + } + + if (PrivateData->FvCount >= PrivateData->MaxFvCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_CORE_FV_HANDLE) * (PrivateData->MaxFvCount + FV_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + PrivateData->Fv, + sizeof (PEI_CORE_FV_HANDLE) * PrivateData->MaxFvCount + ); + PrivateData->Fv = TempPtr; + PrivateData->MaxFvCount = PrivateData->MaxFvCount + FV_GROWTH_STEP; + } + + // + // Update internal PEI_CORE_FV array. + // + PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvInfo; + PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi; + PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle; + PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = AuthenticationStatus; + CurFvCount = PrivateData->FvCount; + DEBUG (( + DEBUG_INFO, + "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", + (UINT32)CurFvCount, + (VOID *)FvInfo, + FvInfoSize, + FvHandle + )); + PrivateData->FvCount++; + + // + // Scan and process the new discovered FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE + // + FileHandle = NULL; + do { + Status = FvPpi->FindFileByType ( + FvPpi, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + FvHandle, + &FileHandle + ); + if (!EFI_ERROR (Status)) { + Status = FvPpi->FindSectionByType ( + FvPpi, + EFI_SECTION_PEI_DEPEX, + FileHandle, + (VOID **)&DepexData + ); + if (!EFI_ERROR (Status)) { + if (!PeimDispatchReadiness (PeiServices, DepexData)) { + // + // Dependency is not satisfied. + // + continue; + } + } + + DEBUG ((DEBUG_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle)); + ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle); + } + } while (FileHandle != NULL); + } while (TRUE); +} diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.h b/MdeModulePkg/Core/Pei/FwVol/FwVol.h index 7d1dc9cba1..475ed90a7c 100644 --- a/MdeModulePkg/Core/Pei/FwVol/FwVol.h +++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.h @@ -1,370 +1,370 @@ -/** @file
- The internal header file for firmware volume related definitions.
-
-Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _FWVOL_H_
-#define _FWVOL_H_
-
-#include "PeiMain.h"
-
-#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
- ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
-
-#define PEI_FW_VOL_SIGNATURE SIGNATURE_32('P','F','W','V')
-
-typedef struct {
- UINTN Signature;
- BOOLEAN IsFfs3Fv;
- EFI_PEI_FIRMWARE_VOLUME_PPI Fv;
-} PEI_FW_VOL_INSTANCE;
-
-#define PEI_FW_VOL_INSTANCE_FROM_FV_THIS(a) \
- CR(a, PEI_FW_VOL_INSTANCE, Fv, PEI_FW_VOL_SIGNATURE)
-
-/**
- Process a firmware volume and create a volume handle.
-
- Create a volume handle from the information in the buffer. For
- memory-mapped firmware volumes, Buffer and BufferSize refer to
- the start of the firmware volume and the firmware volume size.
- For non memory-mapped firmware volumes, this points to a
- buffer which contains the necessary information for creating
- the firmware volume handle. Normally, these values are derived
- from the EFI_FIRMWARE_VOLUME_INFO_PPI.
-
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param Buffer Points to the start of the buffer.
- @param BufferSize Size of the buffer.
- @param FvHandle Points to the returned firmware volume
- handle. The firmware volume handle must
- be unique within the system.
-
- @retval EFI_SUCCESS Firmware volume handle created.
- @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiProcessVolume (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN VOID *Buffer,
- IN UINTN BufferSize,
- OUT EFI_PEI_FV_HANDLE *FvHandle
- );
-
-/**
- Finds the next file of the specified type.
-
- This service enables PEI modules to discover additional firmware files.
- The FileHandle must be unique within the system.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param SearchType A filter to find only files of this type. Type
- EFI_FV_FILETYPE_ALL causes no filtering to be
- done.
- @param FvHandle Handle of firmware volume in which to
- search.
- @param FileHandle Points to the current handle from which to
- begin searching or NULL to start at the
- beginning of the firmware volume. Updated
- upon return to reflect the file found.
-
- @retval EFI_SUCCESS The file was found.
- @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindFileByType (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_FV_FILETYPE SearchType,
- IN EFI_PEI_FV_HANDLE FvHandle,
- IN OUT EFI_PEI_FILE_HANDLE *FileHandle
- );
-
-/**
- Find a file within a volume by its name.
-
- This service searches for files with a specific name, within
- either the specified firmware volume or all firmware volumes.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FileName A pointer to the name of the file to find
- within the firmware volume.
- @param FvHandle Upon entry, the pointer to the firmware
- volume to search or NULL if all firmware
- volumes should be searched. Upon exit, the
- actual firmware volume in which the file was
- found.
- @param FileHandle Upon exit, points to the found file's
- handle or NULL if it could not be found.
-
- @retval EFI_SUCCESS File was found.
- @retval EFI_NOT_FOUND File was not found.
- @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
- FileName was NULL.
-
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindFileByName (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN CONST EFI_GUID *FileName,
- IN EFI_PEI_FV_HANDLE *FvHandle,
- OUT EFI_PEI_FILE_HANDLE *FileHandle
- );
-
-/**
- Find the next matching section in the firmware file.
-
- This service enables PEI modules to discover sections
- of a given type within a valid file.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param SearchType A filter to find only sections of this
- type.
- @param FileHandle Handle of firmware file in which to
- search.
- @param SectionData Updated upon return to point to the
- section found.
-
- @retval EFI_SUCCESS Section was found.
- @retval EFI_NOT_FOUND Section of the specified type was not
- found. SectionData contains NULL.
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindSectionByType (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_SECTION_TYPE SearchType,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData
- );
-
-/**
- Find the next matching section in the firmware file.
-
- This service enables PEI modules to discover sections
- of a given instance and type within a valid file.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param SearchType A filter to find only sections of this
- type.
- @param SearchInstance A filter to find the specific instance
- of sections.
- @param FileHandle Handle of firmware file in which to
- search.
- @param SectionData Updated upon return to point to the
- section found.
- @param AuthenticationStatus Updated upon return to point to the
- authentication status for this section.
-
- @retval EFI_SUCCESS Section was found.
- @retval EFI_NOT_FOUND Section of the specified type was not
- found. SectionData contains NULL.
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiFindSectionByType2 (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_SECTION_TYPE SearchType,
- IN UINTN SearchInstance,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData,
- OUT UINT32 *AuthenticationStatus
- );
-
-/**
- Returns information about a specific file.
-
- This function returns information about a specific
- file, including its file name, type, attributes, starting
- address and size.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's
- information.
-
- @retval EFI_SUCCESS File information returned.
- @retval EFI_INVALID_PARAMETER If FileHandle does not
- represent a valid file.
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiGetFileInfo (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO *FileInfo
- );
-
-/**
- Returns information about a specific file.
-
- This function returns information about a specific
- file, including its file name, type, attributes, starting
- address, size and authentication status.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's
- information.
-
- @retval EFI_SUCCESS File information returned.
- @retval EFI_INVALID_PARAMETER If FileHandle does not
- represent a valid file.
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiGetFileInfo2 (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO2 *FileInfo
- );
-
-/**
- This function returns information about the firmware volume.
-
- @param This Points to this instance of the
- EFI_PEI_FIRMWARE_VOLUME_PPI.
- @param FvHandle Handle to the firmware handle.
- @param VolumeInfo Points to the returned firmware volume
- information.
-
- @retval EFI_SUCCESS Information returned successfully.
- @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
- firmware volume or VolumeInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFvPpiGetVolumeInfo (
- IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
- IN EFI_PEI_FV_HANDLE FvHandle,
- OUT EFI_FV_INFO *VolumeInfo
- );
-
-/**
- Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
-
- @param FvHandle The handle of a FV.
-
- @retval NULL if can not find.
- @return Pointer of corresponding PEI_CORE_FV_HANDLE.
-**/
-PEI_CORE_FV_HANDLE *
-FvHandleToCoreHandle (
- IN EFI_PEI_FV_HANDLE FvHandle
- );
-
-/**
- Given the input file pointer, search for the next matching file in the
- FFS volume as defined by SearchType. The search starts from FileHeader inside
- the Firmware Volume defined by FwVolHeader.
-
-
- @param FvHandle Pointer to the FV header of the volume to search
- @param FileName File name
- @param SearchType Filter to find only files of this type.
- Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
- @param FileHandle This parameter must point to a valid FFS volume.
- @param AprioriFile Pointer to AprioriFile image in this FV if has
-
- @return EFI_NOT_FOUND No files matching the search criteria were found
- @retval EFI_SUCCESS Success to search given file
-
-**/
-EFI_STATUS
-FindFileEx (
- IN CONST EFI_PEI_FV_HANDLE FvHandle,
- IN CONST EFI_GUID *FileName OPTIONAL,
- IN EFI_FV_FILETYPE SearchType,
- IN OUT EFI_PEI_FILE_HANDLE *FileHandle,
- IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL
- );
-
-/**
- Report the information for a newly discovered FV in an unknown format.
-
- If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for a third-party FV format, but
- the FV has been discovered, then the information of this FV will be cached into PEI_CORE_INSTANCE's
- UnknownFvInfo array.
-
- Also a notification would be installed for unknown FV format GUID, if EFI_PEI_FIRMWARE_VOLUME_PPI
- is installed later by platform's PEIM, the original unknown FV will be processed by
- using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
-
- @param PrivateData Point to instance of PEI_CORE_INSTANCE
- @param FvInfo2Ppi Point to FvInfo2 PPI.
-
- @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
- @retval EFI_SUCCESS Success to add the information for unknown FV.
-**/
-EFI_STATUS
-AddUnknownFormatFvInfo (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi
- );
-
-/**
- Find the FV information according to FV format GUID.
-
- This routine also will remove the FV information found by given FV format GUID from
- PrivateData->UnknownFvInfo[].
-
- @param PrivateData Point to instance of PEI_CORE_INSTANCE
- @param Format Point to given FV format GUID
- @param FvInfo On return, the pointer of FV information buffer in given FV format GUID
- @param FvInfoSize On return, the size of FV information buffer.
- @param AuthenticationStatus On return, the authentication status of FV information buffer.
-
- @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
- @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
-**/
-EFI_STATUS
-FindUnknownFormatFvInfo (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_GUID *Format,
- OUT VOID **FvInfo,
- OUT UINT32 *FvInfoSize,
- OUT UINT32 *AuthenticationStatus
- );
-
-/**
- Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
-
- When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
- routine is called to process all discovered FVs in this format.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS The notification callback is processed correctly.
-**/
-EFI_STATUS
-EFIAPI
-ThirdPartyFvPpiNotifyCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- );
-
-#endif
+/** @file + The internal header file for firmware volume related definitions. + +Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _FWVOL_H_ +#define _FWVOL_H_ + +#include "PeiMain.h" + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))) + +#define PEI_FW_VOL_SIGNATURE SIGNATURE_32('P','F','W','V') + +typedef struct { + UINTN Signature; + BOOLEAN IsFfs3Fv; + EFI_PEI_FIRMWARE_VOLUME_PPI Fv; +} PEI_FW_VOL_INSTANCE; + +#define PEI_FW_VOL_INSTANCE_FROM_FV_THIS(a) \ + CR(a, PEI_FW_VOL_INSTANCE, Fv, PEI_FW_VOL_SIGNATURE) + +/** + Process a firmware volume and create a volume handle. + + Create a volume handle from the information in the buffer. For + memory-mapped firmware volumes, Buffer and BufferSize refer to + the start of the firmware volume and the firmware volume size. + For non memory-mapped firmware volumes, this points to a + buffer which contains the necessary information for creating + the firmware volume handle. Normally, these values are derived + from the EFI_FIRMWARE_VOLUME_INFO_PPI. + + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param Buffer Points to the start of the buffer. + @param BufferSize Size of the buffer. + @param FvHandle Points to the returned firmware volume + handle. The firmware volume handle must + be unique within the system. + + @retval EFI_SUCCESS Firmware volume handle created. + @retval EFI_VOLUME_CORRUPTED Volume was corrupt. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiProcessVolume ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN VOID *Buffer, + IN UINTN BufferSize, + OUT EFI_PEI_FV_HANDLE *FvHandle + ); + +/** + Finds the next file of the specified type. + + This service enables PEI modules to discover additional firmware files. + The FileHandle must be unique within the system. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only files of this type. Type + EFI_FV_FILETYPE_ALL causes no filtering to be + done. + @param FvHandle Handle of firmware volume in which to + search. + @param FileHandle Points to the current handle from which to + begin searching or NULL to start at the + beginning of the firmware volume. Updated + upon return to reflect the file found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindFileByType ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Find a file within a volume by its name. + + This service searches for files with a specific name, within + either the specified firmware volume or all firmware volumes. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileName A pointer to the name of the file to find + within the firmware volume. + @param FvHandle Upon entry, the pointer to the firmware + volume to search or NULL if all firmware + volumes should be searched. Upon exit, the + actual firmware volume in which the file was + found. + @param FileHandle Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + @retval EFI_NOT_FOUND File was not found. + @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or + FileName was NULL. + + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindFileByName ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE *FvHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Find the next matching section in the firmware file. + + This service enables PEI modules to discover sections + of a given type within a valid file. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only sections of this + type. + @param FileHandle Handle of firmware file in which to + search. + @param SectionData Updated upon return to point to the + section found. + + @retval EFI_SUCCESS Section was found. + @retval EFI_NOT_FOUND Section of the specified type was not + found. SectionData contains NULL. +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindSectionByType ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_SECTION_TYPE SearchType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + +/** + Find the next matching section in the firmware file. + + This service enables PEI modules to discover sections + of a given instance and type within a valid file. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only sections of this + type. + @param SearchInstance A filter to find the specific instance + of sections. + @param FileHandle Handle of firmware file in which to + search. + @param SectionData Updated upon return to point to the + section found. + @param AuthenticationStatus Updated upon return to point to the + authentication status for this section. + + @retval EFI_SUCCESS Section was found. + @retval EFI_NOT_FOUND Section of the specified type was not + found. SectionData contains NULL. +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiFindSectionByType2 ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_SECTION_TYPE SearchType, + IN UINTN SearchInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ); + +/** + Returns information about a specific file. + + This function returns information about a specific + file, including its file name, type, attributes, starting + address and size. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiGetFileInfo ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + +/** + Returns information about a specific file. + + This function returns information about a specific + file, including its file name, type, attributes, starting + address, size and authentication status. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiGetFileInfo2 ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ); + +/** + This function returns information about the firmware volume. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FvHandle Handle to the firmware handle. + @param VolumeInfo Points to the returned firmware volume + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid + firmware volume or VolumeInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFvPpiGetVolumeInfo ( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FV_HANDLE FvHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + +/** + Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE. + + @param FvHandle The handle of a FV. + + @retval NULL if can not find. + @return Pointer of corresponding PEI_CORE_FV_HANDLE. +**/ +PEI_CORE_FV_HANDLE * +FvHandleToCoreHandle ( + IN EFI_PEI_FV_HANDLE FvHandle + ); + +/** + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + + + @param FvHandle Pointer to the FV header of the volume to search + @param FileName File name + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FileHandle This parameter must point to a valid FFS volume. + @param AprioriFile Pointer to AprioriFile image in this FV if has + + @return EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS Success to search given file + +**/ +EFI_STATUS +FindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName OPTIONAL, + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL + ); + +/** + Report the information for a newly discovered FV in an unknown format. + + If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for a third-party FV format, but + the FV has been discovered, then the information of this FV will be cached into PEI_CORE_INSTANCE's + UnknownFvInfo array. + + Also a notification would be installed for unknown FV format GUID, if EFI_PEI_FIRMWARE_VOLUME_PPI + is installed later by platform's PEIM, the original unknown FV will be processed by + using new installed EFI_PEI_FIRMWARE_VOLUME_PPI. + + @param PrivateData Point to instance of PEI_CORE_INSTANCE + @param FvInfo2Ppi Point to FvInfo2 PPI. + + @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces. + @retval EFI_SUCCESS Success to add the information for unknown FV. +**/ +EFI_STATUS +AddUnknownFormatFvInfo ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi + ); + +/** + Find the FV information according to FV format GUID. + + This routine also will remove the FV information found by given FV format GUID from + PrivateData->UnknownFvInfo[]. + + @param PrivateData Point to instance of PEI_CORE_INSTANCE + @param Format Point to given FV format GUID + @param FvInfo On return, the pointer of FV information buffer in given FV format GUID + @param FvInfoSize On return, the size of FV information buffer. + @param AuthenticationStatus On return, the authentication status of FV information buffer. + + @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI + @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI. +**/ +EFI_STATUS +FindUnknownFormatFvInfo ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_GUID *Format, + OUT VOID **FvInfo, + OUT UINT32 *FvInfoSize, + OUT UINT32 *AuthenticationStatus + ); + +/** + Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI. + + When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this + routine is called to process all discovered FVs in this format. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS The notification callback is processed correctly. +**/ +EFI_STATUS +EFIAPI +ThirdPartyFvPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +#endif diff --git a/MdeModulePkg/Core/Pei/Hob/Hob.c b/MdeModulePkg/Core/Pei/Hob/Hob.c index c4882a23cd..8aada50076 100644 --- a/MdeModulePkg/Core/Pei/Hob/Hob.c +++ b/MdeModulePkg/Core/Pei/Hob/Hob.c @@ -1,237 +1,237 @@ -/** @file
- This module provide Hand-Off Block manipulation.
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
-
- Gets the pointer to the HOB List.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param HobList Pointer to the HOB List.
-
- @retval EFI_SUCCESS Get the pointer of HOB List
- @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published
- @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode)
-
-**/
-EFI_STATUS
-EFIAPI
-PeiGetHobList (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN OUT VOID **HobList
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
-
- //
- // Only check this parameter in debug mode
- //
-
- DEBUG_CODE_BEGIN ();
- if (HobList == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- DEBUG_CODE_END ();
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- *HobList = PrivateData->HobList.Raw;
-
- return EFI_SUCCESS;
-}
-
-/**
- Add a new HOB to the HOB List.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param Type Type of the new HOB.
- @param Length Length of the new HOB to allocate.
- @param Hob Pointer to the new HOB.
-
- @return EFI_SUCCESS Success to create HOB.
- @retval EFI_INVALID_PARAMETER if Hob is NULL
- @retval EFI_NOT_AVAILABLE_YET if HobList is still not available.
- @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiCreateHob (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINT16 Type,
- IN UINT16 Length,
- IN OUT VOID **Hob
- )
-{
- EFI_STATUS Status;
- EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
- EFI_HOB_GENERIC_HEADER *HobEnd;
- EFI_PHYSICAL_ADDRESS FreeMemory;
-
- Status = PeiGetHobList (PeiServices, Hob);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- HandOffHob = *Hob;
-
- //
- // Check Length to avoid data overflow.
- //
- if (0x10000 - Length <= 0x7) {
- return EFI_INVALID_PARAMETER;
- }
-
- Length = (UINT16)((Length + 0x7) & (~0x7));
-
- FreeMemory = HandOffHob->EfiFreeMemoryTop -
- HandOffHob->EfiFreeMemoryBottom;
-
- if (FreeMemory < Length) {
- DEBUG ((DEBUG_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length));
- DEBUG ((DEBUG_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
- DEBUG ((DEBUG_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
- return EFI_OUT_OF_RESOURCES;
- }
-
- *Hob = (VOID *)(UINTN)HandOffHob->EfiEndOfHobList;
- ((EFI_HOB_GENERIC_HEADER *)*Hob)->HobType = Type;
- ((EFI_HOB_GENERIC_HEADER *)*Hob)->HobLength = Length;
- ((EFI_HOB_GENERIC_HEADER *)*Hob)->Reserved = 0;
-
- HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)*Hob + Length);
- HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
-
- HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
- HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER);
- HobEnd->Reserved = 0;
- HobEnd++;
- HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
-
- return EFI_SUCCESS;
-}
-
-/**
- Install SEC HOB data to the HOB List.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SecHobList Pointer to SEC HOB List.
-
- @return EFI_SUCCESS Success to install SEC HOB data.
- @retval EFI_OUT_OF_RESOURCES If there is no more memory to grow the Hoblist.
-
-**/
-EFI_STATUS
-PeiInstallSecHobData (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_HOB_GENERIC_HEADER *SecHobList
- )
-{
- EFI_STATUS Status;
- EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
- EFI_PEI_HOB_POINTERS HobStart;
- EFI_PEI_HOB_POINTERS Hob;
- UINTN SecHobListLength;
- EFI_PHYSICAL_ADDRESS FreeMemory;
- EFI_HOB_GENERIC_HEADER *HobEnd;
-
- HandOffHob = NULL;
- Status = PeiGetHobList (PeiServices, (VOID **)&HandOffHob);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ASSERT (HandOffHob != NULL);
-
- HobStart.Raw = (UINT8 *)SecHobList;
- //
- // The HobList must not contain a EFI_HOB_HANDOFF_INFO_TABLE HOB (PHIT) HOB.
- //
- ASSERT (HobStart.Header->HobType != EFI_HOB_TYPE_HANDOFF);
- //
- // Calculate the SEC HOB List length,
- // not including the terminated HOB(EFI_HOB_TYPE_END_OF_HOB_LIST).
- //
- for (Hob.Raw = HobStart.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- }
-
- SecHobListLength = (UINTN)Hob.Raw - (UINTN)HobStart.Raw;
- //
- // The length must be 8-bytes aligned.
- //
- ASSERT ((SecHobListLength & 0x7) == 0);
-
- FreeMemory = HandOffHob->EfiFreeMemoryTop -
- HandOffHob->EfiFreeMemoryBottom;
-
- if (FreeMemory < SecHobListLength) {
- DEBUG ((DEBUG_ERROR, "PeiInstallSecHobData fail: SecHobListLength - 0x%08x\n", SecHobListLength));
- DEBUG ((DEBUG_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop));
- DEBUG ((DEBUG_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom));
- return EFI_OUT_OF_RESOURCES;
- }
-
- Hob.Raw = (UINT8 *)(UINTN)HandOffHob->EfiEndOfHobList;
- CopyMem (Hob.Raw, HobStart.Raw, SecHobListLength);
-
- HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)Hob.Raw + SecHobListLength);
- HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
-
- HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
- HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER);
- HobEnd->Reserved = 0;
- HobEnd++;
- HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
-
- return EFI_SUCCESS;
-}
-
-/**
-
- Builds a Handoff Information Table HOB
-
- @param BootMode - Current Bootmode
- @param MemoryBegin - Start Memory Address.
- @param MemoryLength - Length of Memory.
-
- @return EFI_SUCCESS Always success to initialize HOB.
-
-**/
-EFI_STATUS
-PeiCoreBuildHobHandoffInfoTable (
- IN EFI_BOOT_MODE BootMode,
- IN EFI_PHYSICAL_ADDRESS MemoryBegin,
- IN UINT64 MemoryLength
- )
-{
- EFI_HOB_HANDOFF_INFO_TABLE *Hob;
- EFI_HOB_GENERIC_HEADER *HobEnd;
-
- Hob = (VOID *)(UINTN)MemoryBegin;
- HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1);
- Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
- Hob->Header.HobLength = (UINT16)sizeof (EFI_HOB_HANDOFF_INFO_TABLE);
- Hob->Header.Reserved = 0;
-
- HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
- HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER);
- HobEnd->Reserved = 0;
-
- Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
- Hob->BootMode = BootMode;
-
- Hob->EfiMemoryTop = MemoryBegin + MemoryLength;
- Hob->EfiMemoryBottom = MemoryBegin;
- Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;
- Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd + 1);
- Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
-
- return EFI_SUCCESS;
-}
+/** @file + This module provide Hand-Off Block manipulation. + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + Gets the pointer to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param HobList Pointer to the HOB List. + + @retval EFI_SUCCESS Get the pointer of HOB List + @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published + @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode) + +**/ +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Only check this parameter in debug mode + // + + DEBUG_CODE_BEGIN (); + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + + DEBUG_CODE_END (); + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + *HobList = PrivateData->HobList.Raw; + + return EFI_SUCCESS; +} + +/** + Add a new HOB to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + @param Hob Pointer to the new HOB. + + @return EFI_SUCCESS Success to create HOB. + @retval EFI_INVALID_PARAMETER if Hob is NULL + @retval EFI_NOT_AVAILABLE_YET if HobList is still not available. + @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + Status = PeiGetHobList (PeiServices, Hob); + if (EFI_ERROR (Status)) { + return Status; + } + + HandOffHob = *Hob; + + // + // Check Length to avoid data overflow. + // + if (0x10000 - Length <= 0x7) { + return EFI_INVALID_PARAMETER; + } + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + DEBUG ((DEBUG_ERROR, "PeiCreateHob fail: Length - 0x%08x\n", (UINTN)Length)); + DEBUG ((DEBUG_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + DEBUG ((DEBUG_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID *)(UINTN)HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER *)*Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER *)*Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER *)*Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)*Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + return EFI_SUCCESS; +} + +/** + Install SEC HOB data to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SecHobList Pointer to SEC HOB List. + + @return EFI_SUCCESS Success to install SEC HOB data. + @retval EFI_OUT_OF_RESOURCES If there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +PeiInstallSecHobData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_GENERIC_HEADER *SecHobList + ) +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_PEI_HOB_POINTERS HobStart; + EFI_PEI_HOB_POINTERS Hob; + UINTN SecHobListLength; + EFI_PHYSICAL_ADDRESS FreeMemory; + EFI_HOB_GENERIC_HEADER *HobEnd; + + HandOffHob = NULL; + Status = PeiGetHobList (PeiServices, (VOID **)&HandOffHob); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (HandOffHob != NULL); + + HobStart.Raw = (UINT8 *)SecHobList; + // + // The HobList must not contain a EFI_HOB_HANDOFF_INFO_TABLE HOB (PHIT) HOB. + // + ASSERT (HobStart.Header->HobType != EFI_HOB_TYPE_HANDOFF); + // + // Calculate the SEC HOB List length, + // not including the terminated HOB(EFI_HOB_TYPE_END_OF_HOB_LIST). + // + for (Hob.Raw = HobStart.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + } + + SecHobListLength = (UINTN)Hob.Raw - (UINTN)HobStart.Raw; + // + // The length must be 8-bytes aligned. + // + ASSERT ((SecHobListLength & 0x7) == 0); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < SecHobListLength) { + DEBUG ((DEBUG_ERROR, "PeiInstallSecHobData fail: SecHobListLength - 0x%08x\n", SecHobListLength)); + DEBUG ((DEBUG_ERROR, " FreeMemoryTop - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryTop)); + DEBUG ((DEBUG_ERROR, " FreeMemoryBottom - 0x%08x\n", (UINTN)HandOffHob->EfiFreeMemoryBottom)); + return EFI_OUT_OF_RESOURCES; + } + + Hob.Raw = (UINT8 *)(UINTN)HandOffHob->EfiEndOfHobList; + CopyMem (Hob.Raw, HobStart.Raw, SecHobListLength); + + HobEnd = (EFI_HOB_GENERIC_HEADER *)((UINTN)Hob.Raw + SecHobListLength); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + return EFI_SUCCESS; +} + +/** + + Builds a Handoff Information Table HOB + + @param BootMode - Current Bootmode + @param MemoryBegin - Start Memory Address. + @param MemoryLength - Length of Memory. + + @return EFI_SUCCESS Always success to initialize HOB. + +**/ +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = (UINT16)sizeof (EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16)sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd + 1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd; + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c index cee9f09c6e..46d7f60fc4 100644 --- a/MdeModulePkg/Core/Pei/Image/Image.c +++ b/MdeModulePkg/Core/Pei/Image/Image.c @@ -1,982 +1,982 @@ -/** @file
- Pei Core Load Image Support
-
-Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {
- PeiLoadImageLoadImageWrapper
-};
-
-EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiPeiLoadFilePpiGuid,
- &mPeiLoadImagePpi
-};
-
-/**
-
- Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file.
- The function is used for XIP code to have optimized memory copy.
-
- @param FileHandle - The handle to the PE/COFF file
- @param FileOffset - The offset, in bytes, into the file to read
- @param ReadSize - The number of bytes to read from the file starting at FileOffset
- @param Buffer - A pointer to the buffer to read the data into.
-
- @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
-
-**/
-EFI_STATUS
-EFIAPI
-PeiImageRead (
- IN VOID *FileHandle,
- IN UINTN FileOffset,
- IN UINTN *ReadSize,
- OUT VOID *Buffer
- )
-{
- CHAR8 *Destination8;
- CHAR8 *Source8;
-
- Destination8 = Buffer;
- Source8 = (CHAR8 *)((UINTN)FileHandle + FileOffset);
- if (Destination8 != Source8) {
- CopyMem (Destination8, Source8, *ReadSize);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If
- memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.
- The function is only invoked when load modules at fixed address feature is enabled.
-
- @param Private Pointer to the private data passed in from caller
- @param ImageBase The base address the image will be loaded at.
- @param ImageSize The size of the image
-
- @retval EFI_SUCCESS The memory range the image will be loaded in is available
- @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
-**/
-EFI_STATUS
-CheckAndMarkFixLoadingMemoryUsageBitMap (
- IN PEI_CORE_INSTANCE *Private,
- IN EFI_PHYSICAL_ADDRESS ImageBase,
- IN UINT32 ImageSize
- )
-{
- UINT32 DxeCodePageNumber;
- UINT64 ReservedCodeSize;
- EFI_PHYSICAL_ADDRESS PeiCodeBase;
- UINT32 BaseOffsetPageNumber;
- UINT32 TopOffsetPageNumber;
- UINT32 Index;
- UINT64 *MemoryUsageBitMap;
-
- //
- // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.
- //
- DxeCodePageNumber = PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber);
- DxeCodePageNumber += PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber);
- ReservedCodeSize = EFI_PAGES_TO_SIZE (DxeCodePageNumber + PcdGet32 (PcdLoadFixAddressPeiCodePageNumber));
- PeiCodeBase = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize;
-
- //
- // Test the memory range for loading the image in the PEI code range.
- //
- if (((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE (DxeCodePageNumber)) < (ImageBase + ImageSize)) ||
- (PeiCodeBase > ImageBase))
- {
- return EFI_NOT_FOUND;
- }
-
- //
- // Test if the memory is available or not.
- //
- MemoryUsageBitMap = Private->PeiCodeMemoryRangeUsageBitMap;
- BaseOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - PeiCodeBase));
- TopOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - PeiCodeBase));
- for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {
- if ((MemoryUsageBitMap[Index / 64] & LShiftU64 (1, (Index % 64))) != 0) {
- //
- // This page is already used.
- //
- return EFI_NOT_FOUND;
- }
- }
-
- //
- // Being here means the memory range is available. So mark the bits for the memory range
- //
- for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {
- MemoryUsageBitMap[Index / 64] |= LShiftU64 (1, (Index % 64));
- }
-
- return EFI_SUCCESS;
-}
-
-/**
-
- Get the fixed loading address from image header assigned by build tool. This function only be called
- when Loading module at Fixed address feature enabled.
-
- @param ImageContext Pointer to the image context structure that describes the PE/COFF
- image that needs to be examined by this function.
- @param Private Pointer to the private data passed in from caller
-
- @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
- @retval EFI_NOT_FOUND The image has no assigned fixed loading address.
-
-**/
-EFI_STATUS
-GetPeCoffImageFixLoadingAssignedAddress (
- IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
- IN PEI_CORE_INSTANCE *Private
- )
-{
- UINTN SectionHeaderOffset;
- EFI_STATUS Status;
- EFI_IMAGE_SECTION_HEADER SectionHeader;
- EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
- EFI_PHYSICAL_ADDRESS FixLoadingAddress;
- UINT16 Index;
- UINTN Size;
- UINT16 NumberOfSections;
- UINT64 ValueInSectionHeader;
-
- FixLoadingAddress = 0;
- Status = EFI_NOT_FOUND;
-
- //
- // Get PeHeader pointer
- //
- ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
- if (ImageContext->IsTeImage) {
- //
- // for TE image, the fix loading address is saved in first section header that doesn't point
- // to code section.
- //
- SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);
- NumberOfSections = ImgHdr->Te.NumberOfSections;
- } else {
- SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
- ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
- NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
- }
-
- //
- // Get base address from the first section header that doesn't point to code section.
- //
- for (Index = 0; Index < NumberOfSections; Index++) {
- //
- // Read section header from file
- //
- Size = sizeof (EFI_IMAGE_SECTION_HEADER);
- Status = ImageContext->ImageRead (
- ImageContext->Handle,
- SectionHeaderOffset,
- &Size,
- &SectionHeader
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = EFI_NOT_FOUND;
-
- if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
- //
- // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
- // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is
- // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because
- // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers
- // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a
- // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or
- // else, these 2 fields should be set to Zero
- //
- ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);
- if (ValueInSectionHeader != 0) {
- //
- // Found first section header that doesn't point to code section.
- //
- if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0) {
- //
- // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field
- // hold the absolute address of image base running in memory
- //
- FixLoadingAddress = ValueInSectionHeader;
- } else {
- //
- // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field
- // hold the offset relative to a platform-specific top address.
- //
- FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);
- }
-
- //
- // Check if the memory range is available.
- //
- Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoadingAddress, (UINT32)ImageContext->ImageSize);
- if (!EFI_ERROR (Status)) {
- //
- // The assigned address is valid. Return the specified loading address
- //
- ImageContext->ImageAddress = FixLoadingAddress;
- }
- }
-
- break;
- }
-
- SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
- }
-
- DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoadingAddress, Status));
- return Status;
-}
-
-/**
-
- Loads and relocates a PE/COFF image into memory.
- If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image.
-
- @param FileHandle - Pointer to the FFS file header of the image.
- @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
- @param ImageAddress - The base address of the relocated PE/COFF image
- @param ImageSize - The size of the relocated PE/COFF image
- @param EntryPoint - The entry point of the relocated PE/COFF image
-
- @retval EFI_SUCCESS The file was loaded and relocated
- @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
- @retval EFI_WARN_BUFFER_TOO_SMALL
- There is not enough heap to allocate the requested size.
- This will not prevent the XIP image from being invoked.
-
-**/
-EFI_STATUS
-LoadAndRelocatePeCoffImage (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN VOID *Pe32Data,
- OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
- OUT UINT64 *ImageSize,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint
- )
-{
- EFI_STATUS Status;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
- PEI_CORE_INSTANCE *Private;
- UINT64 AlignImageSize;
- BOOLEAN IsXipImage;
- EFI_STATUS ReturnStatus;
- BOOLEAN IsS3Boot;
- BOOLEAN IsPeiModule;
- BOOLEAN IsRegisterForShadow;
- EFI_FV_FILE_INFO FileInfo;
-
- Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
-
- ReturnStatus = EFI_SUCCESS;
- IsXipImage = FALSE;
- ZeroMem (&ImageContext, sizeof (ImageContext));
- ImageContext.Handle = Pe32Data;
- ImageContext.ImageRead = PeiImageRead;
-
- Status = PeCoffLoaderGetImageInfo (&ImageContext);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Initialize local IsS3Boot and IsRegisterForShadow variable
- //
- IsS3Boot = FALSE;
- if (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) {
- IsS3Boot = TRUE;
- }
-
- IsRegisterForShadow = FALSE;
- if ( (Private->CurrentFileHandle == FileHandle)
- && (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW))
- {
- IsRegisterForShadow = TRUE;
- }
-
- //
- // XIP image that ImageAddress is same to Image handle.
- //
- if (ImageContext.ImageAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {
- IsXipImage = TRUE;
- }
-
- //
- // Get file type first
- //
- Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Check whether the file type is PEI module.
- //
- IsPeiModule = FALSE;
- if ((FileInfo.FileType == EFI_FV_FILETYPE_PEI_CORE) ||
- (FileInfo.FileType == EFI_FV_FILETYPE_PEIM) ||
- (FileInfo.FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER))
- {
- IsPeiModule = TRUE;
- }
-
- //
- // When Image has no reloc section, it can't be relocated into memory.
- //
- if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) &&
- ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
- (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
- )
- {
- DEBUG ((DEBUG_INFO|DEBUG_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN)Pe32Data));
- }
-
- //
- // Set default base address to current image address.
- //
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;
-
- //
- // Allocate Memory for the image when memory is ready, and image is relocatable.
- // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.
- // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.
- //
- if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) &&
- ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
- (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
- )
- {
- //
- // Allocate more buffer to avoid buffer overflow.
- //
- if (ImageContext.IsTeImage) {
- AlignImageSize = ImageContext.ImageSize + ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
- } else {
- AlignImageSize = ImageContext.ImageSize;
- }
-
- if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
- AlignImageSize += ImageContext.SectionAlignment;
- }
-
- if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
- Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext, Private);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
- //
- // The PEIM is not assigned valid address, try to allocate page to load it.
- //
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize),
- &ImageContext.ImageAddress
- );
- }
- } else {
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize),
- &ImageContext.ImageAddress
- );
- }
-
- if (!EFI_ERROR (Status)) {
- //
- // Adjust the Image Address to make sure it is section alignment.
- //
- if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
- ImageContext.ImageAddress =
- (ImageContext.ImageAddress + ImageContext.SectionAlignment - 1) &
- ~((UINTN)ImageContext.SectionAlignment - 1);
- }
-
- //
- // Fix alignment requirement when Load IPF TeImage into memory.
- // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
- //
- if (ImageContext.IsTeImage) {
- ImageContext.ImageAddress = ImageContext.ImageAddress +
- ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize -
- sizeof (EFI_TE_IMAGE_HEADER);
- }
- } else {
- //
- // No enough memory resource.
- //
- if (IsXipImage) {
- //
- // XIP image can still be invoked.
- //
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;
- ReturnStatus = EFI_WARN_BUFFER_TOO_SMALL;
- } else {
- //
- // Non XIP image can't be loaded because no enough memory is allocated.
- //
- ASSERT (FALSE);
- return EFI_OUT_OF_RESOURCES;
- }
- }
- }
-
- //
- // Load the image to our new buffer
- //
- Status = PeCoffLoaderLoadImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- if (ImageContext.ImageError == IMAGE_ERROR_INVALID_SECTION_ALIGNMENT) {
- DEBUG ((DEBUG_ERROR, "PEIM Image Address 0x%11p doesn't meet with section alignment 0x%x.\n", (VOID *)(UINTN)ImageContext.ImageAddress, ImageContext.SectionAlignment));
- }
-
- return Status;
- }
-
- //
- // Relocate the image in our new buffer
- //
- Status = PeCoffLoaderRelocateImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Flush the instruction cache so the image data is written before we execute it
- //
- if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {
- InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
- }
-
- *ImageAddress = ImageContext.ImageAddress;
- *ImageSize = ImageContext.ImageSize;
- *EntryPoint = ImageContext.EntryPoint;
-
- return ReturnStatus;
-}
-
-/**
- Loads and relocates a PE/COFF image in place.
-
- @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
- @param ImageAddress The base address of the relocated PE/COFF image
-
- @retval EFI_SUCCESS The file was loaded and relocated.
- @retval Others The file not be loaded and error occurred.
-
-**/
-EFI_STATUS
-LoadAndRelocatePeCoffImageInPlace (
- IN VOID *Pe32Data,
- IN VOID *ImageAddress
- )
-{
- EFI_STATUS Status;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
-
- ZeroMem (&ImageContext, sizeof (ImageContext));
- ImageContext.Handle = Pe32Data;
- ImageContext.ImageRead = PeiImageRead;
-
- Status = PeCoffLoaderGetImageInfo (&ImageContext);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
-
- ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)ImageAddress;
-
- //
- // Load the image in place
- //
- Status = PeCoffLoaderLoadImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
-
- //
- // Relocate the image in place
- //
- Status = PeCoffLoaderRelocateImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
-
- //
- // Flush the instruction cache so the image data is written before we execute it
- //
- if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {
- InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
- }
-
- return Status;
-}
-
-/**
- Find the PE32 Data for an FFS file.
-
- @param FileHandle Pointer to the FFS file header of the image.
- @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
-
- @retval EFI_SUCCESS Image is successfully loaded.
- @retval EFI_NOT_FOUND Fail to locate PE32 Data.
-
-**/
-EFI_STATUS
-PeiGetPe32Data (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **Pe32Data
- )
-{
- EFI_STATUS Status;
- EFI_SECTION_TYPE SearchType1;
- EFI_SECTION_TYPE SearchType2;
- UINT32 AuthenticationState;
-
- *Pe32Data = NULL;
-
- if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
- SearchType1 = EFI_SECTION_TE;
- SearchType2 = EFI_SECTION_PE32;
- } else {
- SearchType1 = EFI_SECTION_PE32;
- SearchType2 = EFI_SECTION_TE;
- }
-
- //
- // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
- // is true, TE will be searched first).
- //
- Status = PeiServicesFfsFindSectionData3 (
- SearchType1,
- 0,
- FileHandle,
- Pe32Data,
- &AuthenticationState
- );
- //
- // If we didn't find a first exe section, try to find the second exe section.
- //
- if (EFI_ERROR (Status)) {
- Status = PeiServicesFfsFindSectionData3 (
- SearchType2,
- 0,
- FileHandle,
- Pe32Data,
- &AuthenticationState
- );
- }
-
- return Status;
-}
-
-/**
- Loads a PEIM into memory for subsequent execution. If there are compressed
- images or images that need to be relocated into memory for performance reasons,
- this service performs that transformation.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param FileHandle Pointer to the FFS file header of the image.
- @param ImageAddressArg Pointer to PE/TE image.
- @param ImageSizeArg Size of PE/TE image.
- @param EntryPoint Pointer to entry point of specified image file for output.
- @param AuthenticationState - Pointer to attestation authentication state of image.
-
- @retval EFI_SUCCESS Image is successfully loaded.
- @retval EFI_NOT_FOUND Fail to locate necessary PPI.
- @retval EFI_UNSUPPORTED Image Machine Type is not supported.
- @retval EFI_WARN_BUFFER_TOO_SMALL
- There is not enough heap to allocate the requested size.
- This will not prevent the XIP image from being invoked.
-
-**/
-EFI_STATUS
-PeiLoadImageLoadImage (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
- OUT UINT64 *ImageSizeArg OPTIONAL,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
- OUT UINT32 *AuthenticationState
- )
-{
- EFI_STATUS Status;
- VOID *Pe32Data;
- EFI_PHYSICAL_ADDRESS ImageAddress;
- UINT64 ImageSize;
- EFI_PHYSICAL_ADDRESS ImageEntryPoint;
- UINT16 Machine;
- EFI_SECTION_TYPE SearchType1;
- EFI_SECTION_TYPE SearchType2;
-
- *EntryPoint = 0;
- ImageSize = 0;
- *AuthenticationState = 0;
-
- if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
- SearchType1 = EFI_SECTION_TE;
- SearchType2 = EFI_SECTION_PE32;
- } else {
- SearchType1 = EFI_SECTION_PE32;
- SearchType2 = EFI_SECTION_TE;
- }
-
- //
- // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
- // is true, TE will be searched first).
- //
- Status = PeiServicesFfsFindSectionData3 (
- SearchType1,
- 0,
- FileHandle,
- &Pe32Data,
- AuthenticationState
- );
- //
- // If we didn't find a first exe section, try to find the second exe section.
- //
- if (EFI_ERROR (Status)) {
- Status = PeiServicesFfsFindSectionData3 (
- SearchType2,
- 0,
- FileHandle,
- &Pe32Data,
- AuthenticationState
- );
- if (EFI_ERROR (Status)) {
- //
- // PEI core only carry the loader function for TE and PE32 executables
- // If this two section does not exist, just return.
- //
- return Status;
- }
- }
-
- DEBUG ((DEBUG_INFO, "Loading PEIM %g\n", FileHandle));
-
- //
- // If memory is installed, perform the shadow operations
- //
- Status = LoadAndRelocatePeCoffImage (
- FileHandle,
- Pe32Data,
- &ImageAddress,
- &ImageSize,
- &ImageEntryPoint
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Got the entry point from the loaded Pe32Data
- //
- Pe32Data = (VOID *)((UINTN)ImageAddress);
- *EntryPoint = ImageEntryPoint;
-
- Machine = PeCoffLoaderGetMachineType (Pe32Data);
-
- if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
- if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {
- return EFI_UNSUPPORTED;
- }
- }
-
- if (ImageAddressArg != NULL) {
- *ImageAddressArg = ImageAddress;
- }
-
- if (ImageSizeArg != NULL) {
- *ImageSizeArg = ImageSize;
- }
-
- DEBUG_CODE_BEGIN ();
- CHAR8 *AsciiString;
- CHAR8 EfiFileName[512];
- INT32 Index;
- INT32 StartIndex;
-
- //
- // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi
- //
- if (Machine != EFI_IMAGE_MACHINE_IA64) {
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));
- } else {
- //
- // For IPF Image, the real entry point should be print.
- //
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
- }
-
- //
- // Print Module Name by PeImage PDB file name.
- //
- AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);
-
- if (AsciiString != NULL) {
- StartIndex = 0;
- for (Index = 0; AsciiString[Index] != 0; Index++) {
- if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) {
- StartIndex = Index + 1;
- }
- }
-
- //
- // Copy the PDB file name to our temporary string, and replace .pdb with .efi
- // The PDB file name is limited in the range of 0~511.
- // If the length is bigger than 511, trim the redundant characters to avoid overflow in array boundary.
- //
- for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
- EfiFileName[Index] = AsciiString[Index + StartIndex];
- if (EfiFileName[Index] == 0) {
- EfiFileName[Index] = '.';
- }
-
- if (EfiFileName[Index] == '.') {
- EfiFileName[Index + 1] = 'e';
- EfiFileName[Index + 2] = 'f';
- EfiFileName[Index + 3] = 'i';
- EfiFileName[Index + 4] = 0;
- break;
- }
- }
-
- if (Index == sizeof (EfiFileName) - 4) {
- EfiFileName[Index] = 0;
- }
-
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));
- }
-
- DEBUG_CODE_END ();
-
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));
-
- return EFI_SUCCESS;
-}
-
-/**
- The wrapper function of PeiLoadImageLoadImage().
-
- @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.
- @param FileHandle - Pointer to the FFS file header of the image.
- @param ImageAddressArg - Pointer to PE/TE image.
- @param ImageSizeArg - Size of PE/TE image.
- @param EntryPoint - Pointer to entry point of specified image file for output.
- @param AuthenticationState - Pointer to attestation authentication state of image.
-
- @return Status of PeiLoadImageLoadImage().
-
-**/
-EFI_STATUS
-EFIAPI
-PeiLoadImageLoadImageWrapper (
- IN CONST EFI_PEI_LOAD_FILE_PPI *This,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
- OUT UINT64 *ImageSizeArg OPTIONAL,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
- OUT UINT32 *AuthenticationState
- )
-{
- return PeiLoadImageLoadImage (
- GetPeiServicesTablePointer (),
- FileHandle,
- ImageAddressArg,
- ImageSizeArg,
- EntryPoint,
- AuthenticationState
- );
-}
-
-/**
- Check whether the input image has the relocation.
-
- @param Pe32Data Pointer to the PE/COFF or TE image.
-
- @retval TRUE Relocation is stripped.
- @retval FALSE Relocation is not stripped.
-
-**/
-BOOLEAN
-RelocationIsStrip (
- IN VOID *Pe32Data
- )
-{
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
- EFI_IMAGE_DOS_HEADER *DosHdr;
-
- ASSERT (Pe32Data != NULL);
-
- DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
- if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
- //
- // DOS image header is present, so read the PE header after the DOS image header.
- //
- Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
- } else {
- //
- // DOS image header is not present, so PE header is at the image base.
- //
- Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
- }
-
- //
- // Three cases with regards to relocations:
- // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
- // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
- // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
- // has no base relocs to apply
- // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
- //
- // Look at the file header to determine if relocations have been stripped, and
- // save this info in the image context for later use.
- //
- if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
- if ((Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {
- return TRUE;
- } else {
- return FALSE;
- }
- } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
- if ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Routine to load image file for subsequent execution by LoadFile Ppi.
- If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
- XIP image format is used.
-
- @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param FileHandle - Pointer to the FFS file header of the image.
- @param PeimState - The dispatch state of the input PEIM handle.
- @param EntryPoint - Pointer to entry point of specified image file for output.
- @param AuthenticationState - Pointer to attestation authentication state of image.
-
- @retval EFI_SUCCESS - Image is successfully loaded.
- @retval EFI_NOT_FOUND - Fail to locate necessary PPI
- @retval Others - Fail to load file.
-
-**/
-EFI_STATUS
-PeiLoadImage (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINT8 PeimState,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
- OUT UINT32 *AuthenticationState
- )
-{
- EFI_STATUS PpiStatus;
- EFI_STATUS Status;
- UINTN Index;
- EFI_PEI_LOAD_FILE_PPI *LoadFile;
- EFI_PHYSICAL_ADDRESS ImageAddress;
- UINT64 ImageSize;
- BOOLEAN IsStrip;
-
- IsStrip = FALSE;
- //
- // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.
- // one at a time, until one reports EFI_SUCCESS.
- //
- Index = 0;
- do {
- PpiStatus = PeiServicesLocatePpi (
- &gEfiPeiLoadFilePpiGuid,
- Index,
- NULL,
- (VOID **)&LoadFile
- );
- if (!EFI_ERROR (PpiStatus)) {
- Status = LoadFile->LoadFile (
- LoadFile,
- FileHandle,
- &ImageAddress,
- &ImageSize,
- EntryPoint,
- AuthenticationState
- );
- if (!EFI_ERROR (Status) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) {
- //
- // The shadowed PEIM must be relocatable.
- //
- if (PeimState == PEIM_STATE_REGISTER_FOR_SHADOW) {
- IsStrip = RelocationIsStrip ((VOID *)(UINTN)ImageAddress);
- ASSERT (!IsStrip);
- if (IsStrip) {
- return EFI_UNSUPPORTED;
- }
- }
-
- //
- // The image to be started must have the machine type supported by PeiCore.
- //
- ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress)));
- if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress))) {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
- }
- }
-
- Index++;
- } while (!EFI_ERROR (PpiStatus));
-
- return PpiStatus;
-}
-
-/**
-
- Install Pei Load File PPI.
-
-
- @param PrivateData - Pointer to PEI_CORE_INSTANCE.
- @param OldCoreData - Pointer to PEI_CORE_INSTANCE.
-
-**/
-VOID
-InitializeImageServices (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_INSTANCE *OldCoreData
- )
-{
- if (OldCoreData == NULL) {
- //
- // The first time we are XIP (running from FLASH). We need to remember the
- // FLASH address so we can reinstall the memory version that runs faster
- //
- PrivateData->XipLoadFile = &gPpiLoadFilePpiList;
- PeiServicesInstallPpi (PrivateData->XipLoadFile);
- } else {
- //
- // 2nd time we are running from memory so replace the XIP version with the
- // new memory version.
- //
- PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);
- }
-}
+/** @file + Pei Core Load Image Support + +Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = { + PeiLoadImageLoadImageWrapper +}; + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiLoadFilePpiGuid, + &mPeiLoadImagePpi +}; + +/** + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file. + The function is used for XIP code to have optimized memory copy. + + @param FileHandle - The handle to the PE/COFF file + @param FileOffset - The offset, in bytes, into the file to read + @param ReadSize - The number of bytes to read from the file starting at FileOffset + @param Buffer - A pointer to the buffer to read the data into. + + @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +**/ +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN UINTN *ReadSize, + OUT VOID *Buffer + ) +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + Destination8 = Buffer; + Source8 = (CHAR8 *)((UINTN)FileHandle + FileOffset); + if (Destination8 != Source8) { + CopyMem (Destination8, Source8, *ReadSize); + } + + return EFI_SUCCESS; +} + +/** + To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If + memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used. + The function is only invoked when load modules at fixed address feature is enabled. + + @param Private Pointer to the private data passed in from caller + @param ImageBase The base address the image will be loaded at. + @param ImageSize The size of the image + + @retval EFI_SUCCESS The memory range the image will be loaded in is available + @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available +**/ +EFI_STATUS +CheckAndMarkFixLoadingMemoryUsageBitMap ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT32 ImageSize + ) +{ + UINT32 DxeCodePageNumber; + UINT64 ReservedCodeSize; + EFI_PHYSICAL_ADDRESS PeiCodeBase; + UINT32 BaseOffsetPageNumber; + UINT32 TopOffsetPageNumber; + UINT32 Index; + UINT64 *MemoryUsageBitMap; + + // + // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range. + // + DxeCodePageNumber = PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber); + DxeCodePageNumber += PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber); + ReservedCodeSize = EFI_PAGES_TO_SIZE (DxeCodePageNumber + PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)); + PeiCodeBase = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize; + + // + // Test the memory range for loading the image in the PEI code range. + // + if (((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE (DxeCodePageNumber)) < (ImageBase + ImageSize)) || + (PeiCodeBase > ImageBase)) + { + return EFI_NOT_FOUND; + } + + // + // Test if the memory is available or not. + // + MemoryUsageBitMap = Private->PeiCodeMemoryRangeUsageBitMap; + BaseOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - PeiCodeBase)); + TopOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - PeiCodeBase)); + for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) { + if ((MemoryUsageBitMap[Index / 64] & LShiftU64 (1, (Index % 64))) != 0) { + // + // This page is already used. + // + return EFI_NOT_FOUND; + } + } + + // + // Being here means the memory range is available. So mark the bits for the memory range + // + for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) { + MemoryUsageBitMap[Index / 64] |= LShiftU64 (1, (Index % 64)); + } + + return EFI_SUCCESS; +} + +/** + + Get the fixed loading address from image header assigned by build tool. This function only be called + when Loading module at Fixed address feature enabled. + + @param ImageContext Pointer to the image context structure that describes the PE/COFF + image that needs to be examined by this function. + @param Private Pointer to the private data passed in from caller + + @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools . + @retval EFI_NOT_FOUND The image has no assigned fixed loading address. + +**/ +EFI_STATUS +GetPeCoffImageFixLoadingAssignedAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN PEI_CORE_INSTANCE *Private + ) +{ + UINTN SectionHeaderOffset; + EFI_STATUS Status; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_PHYSICAL_ADDRESS FixLoadingAddress; + UINT16 Index; + UINTN Size; + UINT16 NumberOfSections; + UINT64 ValueInSectionHeader; + + FixLoadingAddress = 0; + Status = EFI_NOT_FOUND; + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset); + if (ImageContext->IsTeImage) { + // + // for TE image, the fix loading address is saved in first section header that doesn't point + // to code section. + // + SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER); + NumberOfSections = ImgHdr->Te.NumberOfSections; + } else { + SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader; + NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; + } + + // + // Get base address from the first section header that doesn't point to code section. + // + for (Index = 0; Index < NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EFI_NOT_FOUND; + + if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { + // + // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header + // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is + // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because + // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers + // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a + // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or + // else, these 2 fields should be set to Zero + // + ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations); + if (ValueInSectionHeader != 0) { + // + // Found first section header that doesn't point to code section. + // + if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0) { + // + // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field + // hold the absolute address of image base running in memory + // + FixLoadingAddress = ValueInSectionHeader; + } else { + // + // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field + // hold the offset relative to a platform-specific top address. + // + FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader); + } + + // + // Check if the memory range is available. + // + Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoadingAddress, (UINT32)ImageContext->ImageSize); + if (!EFI_ERROR (Status)) { + // + // The assigned address is valid. Return the specified loading address + // + ImageContext->ImageAddress = FixLoadingAddress; + } + } + + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoadingAddress, Status)); + return Status; +} + +/** + + Loads and relocates a PE/COFF image into memory. + If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image. + + @param FileHandle - Pointer to the FFS file header of the image. + @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + @param ImageAddress - The base address of the relocated PE/COFF image + @param ImageSize - The size of the relocated PE/COFF image + @param EntryPoint - The entry point of the relocated PE/COFF image + + @retval EFI_SUCCESS The file was loaded and relocated + @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file + @retval EFI_WARN_BUFFER_TOO_SMALL + There is not enough heap to allocate the requested size. + This will not prevent the XIP image from being invoked. + +**/ +EFI_STATUS +LoadAndRelocatePeCoffImage ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + PEI_CORE_INSTANCE *Private; + UINT64 AlignImageSize; + BOOLEAN IsXipImage; + EFI_STATUS ReturnStatus; + BOOLEAN IsS3Boot; + BOOLEAN IsPeiModule; + BOOLEAN IsRegisterForShadow; + EFI_FV_FILE_INFO FileInfo; + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + + ReturnStatus = EFI_SUCCESS; + IsXipImage = FALSE; + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + ImageContext.ImageRead = PeiImageRead; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Initialize local IsS3Boot and IsRegisterForShadow variable + // + IsS3Boot = FALSE; + if (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) { + IsS3Boot = TRUE; + } + + IsRegisterForShadow = FALSE; + if ( (Private->CurrentFileHandle == FileHandle) + && (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW)) + { + IsRegisterForShadow = TRUE; + } + + // + // XIP image that ImageAddress is same to Image handle. + // + if (ImageContext.ImageAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) { + IsXipImage = TRUE; + } + + // + // Get file type first + // + Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo); + ASSERT_EFI_ERROR (Status); + + // + // Check whether the file type is PEI module. + // + IsPeiModule = FALSE; + if ((FileInfo.FileType == EFI_FV_FILETYPE_PEI_CORE) || + (FileInfo.FileType == EFI_FV_FILETYPE_PEIM) || + (FileInfo.FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) + { + IsPeiModule = TRUE; + } + + // + // When Image has no reloc section, it can't be relocated into memory. + // + if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && + ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || + (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || + (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot))) + ) + { + DEBUG ((DEBUG_INFO|DEBUG_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN)Pe32Data)); + } + + // + // Set default base address to current image address. + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data; + + // + // Allocate Memory for the image when memory is ready, and image is relocatable. + // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory. + // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory. + // + if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && + ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || + (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || + (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot))) + ) + { + // + // Allocate more buffer to avoid buffer overflow. + // + if (ImageContext.IsTeImage) { + AlignImageSize = ImageContext.ImageSize + ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + } else { + AlignImageSize = ImageContext.ImageSize; + } + + if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) { + AlignImageSize += ImageContext.SectionAlignment; + } + + if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext, Private); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n")); + // + // The PEIM is not assigned valid address, try to allocate page to load it. + // + Status = PeiServicesAllocatePages ( + EfiBootServicesCode, + EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize), + &ImageContext.ImageAddress + ); + } + } else { + Status = PeiServicesAllocatePages ( + EfiBootServicesCode, + EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize), + &ImageContext.ImageAddress + ); + } + + if (!EFI_ERROR (Status)) { + // + // Adjust the Image Address to make sure it is section alignment. + // + if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) { + ImageContext.ImageAddress = + (ImageContext.ImageAddress + ImageContext.SectionAlignment - 1) & + ~((UINTN)ImageContext.SectionAlignment - 1); + } + + // + // Fix alignment requirement when Load IPF TeImage into memory. + // Skip the reserved space for the stripped PeHeader when load TeImage into memory. + // + if (ImageContext.IsTeImage) { + ImageContext.ImageAddress = ImageContext.ImageAddress + + ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize - + sizeof (EFI_TE_IMAGE_HEADER); + } + } else { + // + // No enough memory resource. + // + if (IsXipImage) { + // + // XIP image can still be invoked. + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data; + ReturnStatus = EFI_WARN_BUFFER_TOO_SMALL; + } else { + // + // Non XIP image can't be loaded because no enough memory is allocated. + // + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + } + } + + // + // Load the image to our new buffer + // + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + if (ImageContext.ImageError == IMAGE_ERROR_INVALID_SECTION_ALIGNMENT) { + DEBUG ((DEBUG_ERROR, "PEIM Image Address 0x%11p doesn't meet with section alignment 0x%x.\n", (VOID *)(UINTN)ImageContext.ImageAddress, ImageContext.SectionAlignment)); + } + + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) { + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + } + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return ReturnStatus; +} + +/** + Loads and relocates a PE/COFF image in place. + + @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated + @param ImageAddress The base address of the relocated PE/COFF image + + @retval EFI_SUCCESS The file was loaded and relocated. + @retval Others The file not be loaded and error occurred. + +**/ +EFI_STATUS +LoadAndRelocatePeCoffImageInPlace ( + IN VOID *Pe32Data, + IN VOID *ImageAddress + ) +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + ImageContext.ImageRead = PeiImageRead; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)ImageAddress; + + // + // Load the image in place + // + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Relocate the image in place + // + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) { + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + } + + return Status; +} + +/** + Find the PE32 Data for an FFS file. + + @param FileHandle Pointer to the FFS file header of the image. + @param Pe32Data Pointer to a (VOID *) PE32 Data pointer. + + @retval EFI_SUCCESS Image is successfully loaded. + @retval EFI_NOT_FOUND Fail to locate PE32 Data. + +**/ +EFI_STATUS +PeiGetPe32Data ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **Pe32Data + ) +{ + EFI_STATUS Status; + EFI_SECTION_TYPE SearchType1; + EFI_SECTION_TYPE SearchType2; + UINT32 AuthenticationState; + + *Pe32Data = NULL; + + if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) { + SearchType1 = EFI_SECTION_TE; + SearchType2 = EFI_SECTION_PE32; + } else { + SearchType1 = EFI_SECTION_PE32; + SearchType2 = EFI_SECTION_TE; + } + + // + // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst + // is true, TE will be searched first). + // + Status = PeiServicesFfsFindSectionData3 ( + SearchType1, + 0, + FileHandle, + Pe32Data, + &AuthenticationState + ); + // + // If we didn't find a first exe section, try to find the second exe section. + // + if (EFI_ERROR (Status)) { + Status = PeiServicesFfsFindSectionData3 ( + SearchType2, + 0, + FileHandle, + Pe32Data, + &AuthenticationState + ); + } + + return Status; +} + +/** + Loads a PEIM into memory for subsequent execution. If there are compressed + images or images that need to be relocated into memory for performance reasons, + this service performs that transformation. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param FileHandle Pointer to the FFS file header of the image. + @param ImageAddressArg Pointer to PE/TE image. + @param ImageSizeArg Size of PE/TE image. + @param EntryPoint Pointer to entry point of specified image file for output. + @param AuthenticationState - Pointer to attestation authentication state of image. + + @retval EFI_SUCCESS Image is successfully loaded. + @retval EFI_NOT_FOUND Fail to locate necessary PPI. + @retval EFI_UNSUPPORTED Image Machine Type is not supported. + @retval EFI_WARN_BUFFER_TOO_SMALL + There is not enough heap to allocate the requested size. + This will not prevent the XIP image from being invoked. + +**/ +EFI_STATUS +PeiLoadImageLoadImage ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +{ + EFI_STATUS Status; + VOID *Pe32Data; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + UINT16 Machine; + EFI_SECTION_TYPE SearchType1; + EFI_SECTION_TYPE SearchType2; + + *EntryPoint = 0; + ImageSize = 0; + *AuthenticationState = 0; + + if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) { + SearchType1 = EFI_SECTION_TE; + SearchType2 = EFI_SECTION_PE32; + } else { + SearchType1 = EFI_SECTION_PE32; + SearchType2 = EFI_SECTION_TE; + } + + // + // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst + // is true, TE will be searched first). + // + Status = PeiServicesFfsFindSectionData3 ( + SearchType1, + 0, + FileHandle, + &Pe32Data, + AuthenticationState + ); + // + // If we didn't find a first exe section, try to find the second exe section. + // + if (EFI_ERROR (Status)) { + Status = PeiServicesFfsFindSectionData3 ( + SearchType2, + 0, + FileHandle, + &Pe32Data, + AuthenticationState + ); + if (EFI_ERROR (Status)) { + // + // PEI core only carry the loader function for TE and PE32 executables + // If this two section does not exist, just return. + // + return Status; + } + } + + DEBUG ((DEBUG_INFO, "Loading PEIM %g\n", FileHandle)); + + // + // If memory is installed, perform the shadow operations + // + Status = LoadAndRelocatePeCoffImage ( + FileHandle, + Pe32Data, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Got the entry point from the loaded Pe32Data + // + Pe32Data = (VOID *)((UINTN)ImageAddress); + *EntryPoint = ImageEntryPoint; + + Machine = PeCoffLoaderGetMachineType (Pe32Data); + + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) { + if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) { + return EFI_UNSUPPORTED; + } + } + + if (ImageAddressArg != NULL) { + *ImageAddressArg = ImageAddress; + } + + if (ImageSizeArg != NULL) { + *ImageSizeArg = ImageSize; + } + + DEBUG_CODE_BEGIN (); + CHAR8 *AsciiString; + CHAR8 EfiFileName[512]; + INT32 Index; + INT32 StartIndex; + + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + if (Machine != EFI_IMAGE_MACHINE_IA64) { + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint)); + } else { + // + // For IPF Image, the real entry point should be print. + // + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint))); + } + + // + // Print Module Name by PeImage PDB file name. + // + AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data); + + if (AsciiString != NULL) { + StartIndex = 0; + for (Index = 0; AsciiString[Index] != 0; Index++) { + if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) { + StartIndex = Index + 1; + } + } + + // + // Copy the PDB file name to our temporary string, and replace .pdb with .efi + // The PDB file name is limited in the range of 0~511. + // If the length is bigger than 511, trim the redundant characters to avoid overflow in array boundary. + // + for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) { + EfiFileName[Index] = AsciiString[Index + StartIndex]; + if (EfiFileName[Index] == 0) { + EfiFileName[Index] = '.'; + } + + if (EfiFileName[Index] == '.') { + EfiFileName[Index + 1] = 'e'; + EfiFileName[Index + 2] = 'f'; + EfiFileName[Index + 3] = 'i'; + EfiFileName[Index + 4] = 0; + break; + } + } + + if (Index == sizeof (EfiFileName) - 4) { + EfiFileName[Index] = 0; + } + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); + } + + DEBUG_CODE_END (); + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n")); + + return EFI_SUCCESS; +} + +/** + The wrapper function of PeiLoadImageLoadImage(). + + @param This - Pointer to EFI_PEI_LOAD_FILE_PPI. + @param FileHandle - Pointer to the FFS file header of the image. + @param ImageAddressArg - Pointer to PE/TE image. + @param ImageSizeArg - Size of PE/TE image. + @param EntryPoint - Pointer to entry point of specified image file for output. + @param AuthenticationState - Pointer to attestation authentication state of image. + + @return Status of PeiLoadImageLoadImage(). + +**/ +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +{ + return PeiLoadImageLoadImage ( + GetPeiServicesTablePointer (), + FileHandle, + ImageAddressArg, + ImageSizeArg, + EntryPoint, + AuthenticationState + ); +} + +/** + Check whether the input image has the relocation. + + @param Pe32Data Pointer to the PE/COFF or TE image. + + @retval TRUE Relocation is stripped. + @retval FALSE Relocation is not stripped. + +**/ +BOOLEAN +RelocationIsStrip ( + IN VOID *Pe32Data + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DOS_HEADER *DosHdr; + + ASSERT (Pe32Data != NULL); + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + if ((Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) { + return TRUE; + } else { + return FALSE; + } + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + if ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) { + return TRUE; + } else { + return FALSE; + } + } + + return FALSE; +} + +/** + Routine to load image file for subsequent execution by LoadFile Ppi. + If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE + XIP image format is used. + + @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param FileHandle - Pointer to the FFS file header of the image. + @param PeimState - The dispatch state of the input PEIM handle. + @param EntryPoint - Pointer to entry point of specified image file for output. + @param AuthenticationState - Pointer to attestation authentication state of image. + + @retval EFI_SUCCESS - Image is successfully loaded. + @retval EFI_NOT_FOUND - Fail to locate necessary PPI + @retval Others - Fail to load file. + +**/ +EFI_STATUS +PeiLoadImage ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINT8 PeimState, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +{ + EFI_STATUS PpiStatus; + EFI_STATUS Status; + UINTN Index; + EFI_PEI_LOAD_FILE_PPI *LoadFile; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + BOOLEAN IsStrip; + + IsStrip = FALSE; + // + // If any instances of PEI_LOAD_FILE_PPI are installed, they are called. + // one at a time, until one reports EFI_SUCCESS. + // + Index = 0; + do { + PpiStatus = PeiServicesLocatePpi ( + &gEfiPeiLoadFilePpiGuid, + Index, + NULL, + (VOID **)&LoadFile + ); + if (!EFI_ERROR (PpiStatus)) { + Status = LoadFile->LoadFile ( + LoadFile, + FileHandle, + &ImageAddress, + &ImageSize, + EntryPoint, + AuthenticationState + ); + if (!EFI_ERROR (Status) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) { + // + // The shadowed PEIM must be relocatable. + // + if (PeimState == PEIM_STATE_REGISTER_FOR_SHADOW) { + IsStrip = RelocationIsStrip ((VOID *)(UINTN)ImageAddress); + ASSERT (!IsStrip); + if (IsStrip) { + return EFI_UNSUPPORTED; + } + } + + // + // The image to be started must have the machine type supported by PeiCore. + // + ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress))); + if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress))) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; + } + } + + Index++; + } while (!EFI_ERROR (PpiStatus)); + + return PpiStatus; +} + +/** + + Install Pei Load File PPI. + + + @param PrivateData - Pointer to PEI_CORE_INSTANCE. + @param OldCoreData - Pointer to PEI_CORE_INSTANCE. + +**/ +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +{ + if (OldCoreData == NULL) { + // + // The first time we are XIP (running from FLASH). We need to remember the + // FLASH address so we can reinstall the memory version that runs faster + // + PrivateData->XipLoadFile = &gPpiLoadFilePpiList; + PeiServicesInstallPpi (PrivateData->XipLoadFile); + } else { + // + // 2nd time we are running from memory so replace the XIP version with the + // new memory version. + // + PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); + } +} diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c index 52f37c960e..792368c735 100644 --- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c +++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c @@ -1,874 +1,874 @@ -/** @file
- EFI PEI Core memory services
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
-
- Initialize the memory services.
-
- @param PrivateData Points to PeiCore's private instance data.
- @param SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
- @param OldCoreData Pointer to the PEI Core data.
- NULL if being run in non-permanent memory mode.
-
-**/
-VOID
-InitializeMemoryServices (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *OldCoreData
- )
-{
- PrivateData->SwitchStackSignal = FALSE;
-
- //
- // First entering PeiCore, following code will initialized some field
- // in PeiCore's private data according to hand off data from SEC core.
- //
- if (OldCoreData == NULL) {
- PrivateData->PeiMemoryInstalled = FALSE;
- PrivateData->HobList.Raw = SecCoreData->PeiTemporaryRamBase;
-
- PeiCoreBuildHobHandoffInfoTable (
- BOOT_WITH_FULL_CONFIGURATION,
- (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->PeiTemporaryRamBase,
- (UINTN)SecCoreData->PeiTemporaryRamSize
- );
-
- //
- // Set Ps to point to ServiceTableShadow in Cache
- //
- PrivateData->Ps = &(PrivateData->ServiceTableShadow);
- }
-
- return;
-}
-
-/**
-
- This function registers the found memory configuration with the PEI Foundation.
-
- The usage model is that the PEIM that discovers the permanent memory shall invoke this service.
- This routine will hold discoveried memory information into PeiCore's private data,
- and set SwitchStackSignal flag. After PEIM who discovery memory is dispatched,
- PeiDispatcher will migrate temporary memory to permanent memory.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param MemoryBegin Start of memory address.
- @param MemoryLength Length of memory.
-
- @return EFI_SUCCESS Always success.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiInstallPeiMemory (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS MemoryBegin,
- IN UINT64 MemoryLength
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
-
- DEBUG ((DEBUG_INFO, "PeiInstallPeiMemory MemoryBegin 0x%LX, MemoryLength 0x%LX\n", MemoryBegin, MemoryLength));
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- //
- // PEI_SERVICE.InstallPeiMemory should only be called one time during whole PEI phase.
- // If it is invoked more than one time, ASSERT information is given for developer debugging in debug tip and
- // simply return EFI_SUCCESS in release tip to ignore it.
- //
- if (PrivateData->PeiMemoryInstalled) {
- DEBUG ((DEBUG_ERROR, "ERROR: PeiInstallPeiMemory is called more than once!\n"));
- ASSERT (FALSE);
- return EFI_SUCCESS;
- }
-
- PrivateData->PhysicalMemoryBegin = MemoryBegin;
- PrivateData->PhysicalMemoryLength = MemoryLength;
- PrivateData->FreePhysicalMemoryTop = MemoryBegin + MemoryLength;
-
- PrivateData->SwitchStackSignal = TRUE;
-
- return EFI_SUCCESS;
-}
-
-/**
- Migrate memory pages allocated in pre-memory phase.
- Copy memory pages at temporary heap top to permanent heap top.
-
- @param[in] Private Pointer to the private data passed in from caller.
- @param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory.
-
-**/
-VOID
-MigrateMemoryPages (
- IN PEI_CORE_INSTANCE *Private,
- IN BOOLEAN TemporaryRamMigrated
- )
-{
- EFI_PHYSICAL_ADDRESS NewMemPagesBase;
- EFI_PHYSICAL_ADDRESS MemPagesBase;
-
- Private->MemoryPages.Size = (UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop -
- Private->HobList.HandoffInformationTable->EfiFreeMemoryTop);
- if (Private->MemoryPages.Size == 0) {
- //
- // No any memory page allocated in pre-memory phase.
- //
- return;
- }
-
- Private->MemoryPages.Base = Private->HobList.HandoffInformationTable->EfiFreeMemoryTop;
-
- ASSERT (Private->MemoryPages.Size <= Private->FreePhysicalMemoryTop);
- NewMemPagesBase = Private->FreePhysicalMemoryTop - Private->MemoryPages.Size;
- NewMemPagesBase &= ~(UINT64)EFI_PAGE_MASK;
- ASSERT (NewMemPagesBase >= Private->PhysicalMemoryBegin);
- //
- // Copy memory pages at temporary heap top to permanent heap top.
- //
- if (TemporaryRamMigrated) {
- //
- // Memory pages at temporary heap top has been migrated to permanent heap,
- // Here still needs to copy them from permanent heap to permanent heap top.
- //
- MemPagesBase = Private->MemoryPages.Base;
- if (Private->HeapOffsetPositive) {
- MemPagesBase += Private->HeapOffset;
- } else {
- MemPagesBase -= Private->HeapOffset;
- }
-
- CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)MemPagesBase, Private->MemoryPages.Size);
- } else {
- CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)Private->MemoryPages.Base, Private->MemoryPages.Size);
- }
-
- if (NewMemPagesBase >= Private->MemoryPages.Base) {
- Private->MemoryPages.OffsetPositive = TRUE;
- Private->MemoryPages.Offset = (UINTN)(NewMemPagesBase - Private->MemoryPages.Base);
- } else {
- Private->MemoryPages.OffsetPositive = FALSE;
- Private->MemoryPages.Offset = (UINTN)(Private->MemoryPages.Base - NewMemPagesBase);
- }
-
- DEBUG ((DEBUG_INFO, "Pages Offset = 0x%lX\n", (UINT64)Private->MemoryPages.Offset));
-
- Private->FreePhysicalMemoryTop = NewMemPagesBase;
-}
-
-/**
- Migrate the base address in firmware volume allocation HOBs
- from temporary memory to PEI installed memory.
-
- @param[in] PrivateData Pointer to PeiCore's private data structure.
- @param[in] OrgFvHandle Address of FV Handle in temporary memory.
- @param[in] FvHandle Address of FV Handle in permanent memory.
-
-**/
-VOID
-ConvertFvHob (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN UINTN OrgFvHandle,
- IN UINTN FvHandle
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
- EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2Hob;
- EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3Hob;
-
- DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n"));
-
- for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
- FirmwareVolumeHob = Hob.FirmwareVolume;
- if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) {
- FirmwareVolumeHob->BaseAddress = FvHandle;
- }
- } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
- FirmwareVolume2Hob = Hob.FirmwareVolume2;
- if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) {
- FirmwareVolume2Hob->BaseAddress = FvHandle;
- }
- } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
- FirmwareVolume3Hob = Hob.FirmwareVolume3;
- if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) {
- FirmwareVolume3Hob->BaseAddress = FvHandle;
- }
- }
- }
-}
-
-/**
- Migrate MemoryBaseAddress in memory allocation HOBs
- from the temporary memory to PEI installed memory.
-
- @param[in] PrivateData Pointer to PeiCore's private data structure.
-
-**/
-VOID
-ConvertMemoryAllocationHobs (
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
- EFI_PHYSICAL_ADDRESS OldMemPagesBase;
- UINTN OldMemPagesSize;
-
- if (PrivateData->MemoryPages.Size == 0) {
- //
- // No any memory page allocated in pre-memory phase.
- //
- return;
- }
-
- OldMemPagesBase = PrivateData->MemoryPages.Base;
- OldMemPagesSize = PrivateData->MemoryPages.Size;
-
- MemoryAllocationHob = NULL;
- Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
- while (Hob.Raw != NULL) {
- MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
- if ((MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress >= OldMemPagesBase) &&
- (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress < (OldMemPagesBase + OldMemPagesSize))
- )
- {
- if (PrivateData->MemoryPages.OffsetPositive) {
- MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress += PrivateData->MemoryPages.Offset;
- } else {
- MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress -= PrivateData->MemoryPages.Offset;
- }
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
- }
-}
-
-/**
- Internal function to build a HOB for the memory allocation.
- It will search and reuse the unused(freed) memory allocation HOB,
- or build memory allocation HOB normally if no unused(freed) memory allocation HOB found.
-
- @param[in] BaseAddress The 64 bit physical address of the memory.
- @param[in] Length The length of the memory allocation in bytes.
- @param[in] MemoryType The type of memory allocated by this HOB.
-
-**/
-VOID
-InternalBuildMemoryAllocationHob (
- IN EFI_PHYSICAL_ADDRESS BaseAddress,
- IN UINT64 Length,
- IN EFI_MEMORY_TYPE MemoryType
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
-
- //
- // Search unused(freed) memory allocation HOB.
- //
- MemoryAllocationHob = NULL;
- Hob.Raw = GetFirstHob (EFI_HOB_TYPE_UNUSED);
- while (Hob.Raw != NULL) {
- if (Hob.Header->HobLength == sizeof (EFI_HOB_MEMORY_ALLOCATION)) {
- MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
- break;
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextHob (EFI_HOB_TYPE_UNUSED, Hob.Raw);
- }
-
- if (MemoryAllocationHob != NULL) {
- //
- // Reuse the unused(freed) memory allocation HOB.
- //
- MemoryAllocationHob->Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION;
- ZeroMem (&(MemoryAllocationHob->AllocDescriptor.Name), sizeof (EFI_GUID));
- MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
- MemoryAllocationHob->AllocDescriptor.MemoryLength = Length;
- MemoryAllocationHob->AllocDescriptor.MemoryType = MemoryType;
- //
- // Zero the reserved space to match HOB spec
- //
- ZeroMem (MemoryAllocationHob->AllocDescriptor.Reserved, sizeof (MemoryAllocationHob->AllocDescriptor.Reserved));
- } else {
- //
- // No unused(freed) memory allocation HOB found.
- // Build memory allocation HOB normally.
- //
- BuildMemoryAllocationHob (
- BaseAddress,
- Length,
- MemoryType
- );
- }
-}
-
-/**
- Update or split memory allocation HOB for memory pages allocate and free.
-
- @param[in, out] MemoryAllocationHob Pointer to the memory allocation HOB
- that needs to be updated or split.
- On output, it will be filled with
- the input Memory, Bytes and MemoryType.
- @param[in] Memory Memory to allocate or free.
- @param[in] Bytes Bytes to allocate or free.
- @param[in] MemoryType EfiConventionalMemory for pages free,
- others for pages allocate.
-
-**/
-VOID
-UpdateOrSplitMemoryAllocationHob (
- IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob,
- IN EFI_PHYSICAL_ADDRESS Memory,
- IN UINT64 Bytes,
- IN EFI_MEMORY_TYPE MemoryType
- )
-{
- if ((Memory + Bytes) <
- (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllocationHob->AllocDescriptor.MemoryLength))
- {
- //
- // Last pages need to be split out.
- //
- InternalBuildMemoryAllocationHob (
- Memory + Bytes,
- (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllocationHob->AllocDescriptor.MemoryLength) - (Memory + Bytes),
- MemoryAllocationHob->AllocDescriptor.MemoryType
- );
- }
-
- if (Memory > MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) {
- //
- // First pages need to be split out.
- //
- InternalBuildMemoryAllocationHob (
- MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress,
- Memory - MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress,
- MemoryAllocationHob->AllocDescriptor.MemoryType
- );
- }
-
- //
- // Update the memory allocation HOB.
- //
- MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress = Memory;
- MemoryAllocationHob->AllocDescriptor.MemoryLength = Bytes;
- MemoryAllocationHob->AllocDescriptor.MemoryType = MemoryType;
-}
-
-/**
- Merge adjacent free memory ranges in memory allocation HOBs.
-
- @retval TRUE There are free memory ranges merged.
- @retval FALSE No free memory ranges merged.
-
-**/
-BOOLEAN
-MergeFreeMemoryInMemoryAllocationHob (
- VOID
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_PEI_HOB_POINTERS Hob2;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryHob2;
- UINT64 Start;
- UINT64 End;
- BOOLEAN Merged;
-
- Merged = FALSE;
-
- Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
- while (Hob.Raw != NULL) {
- if (Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) {
- MemoryHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
- Start = MemoryHob->AllocDescriptor.MemoryBaseAddress;
- End = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;
-
- Hob2.Raw = GET_NEXT_HOB (Hob);
- Hob2.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
- while (Hob2.Raw != NULL) {
- if (Hob2.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) {
- MemoryHob2 = (EFI_HOB_MEMORY_ALLOCATION *)Hob2.Raw;
- if (Start == (MemoryHob2->AllocDescriptor.MemoryBaseAddress + MemoryHob2->AllocDescriptor.MemoryLength)) {
- //
- // Merge adjacent two free memory ranges.
- //
- MemoryHob2->AllocDescriptor.MemoryLength += MemoryHob->AllocDescriptor.MemoryLength;
- Merged = TRUE;
- //
- // Mark MemoryHob to be unused(freed).
- //
- MemoryHob->Header.HobType = EFI_HOB_TYPE_UNUSED;
- break;
- } else if (End == MemoryHob2->AllocDescriptor.MemoryBaseAddress) {
- //
- // Merge adjacent two free memory ranges.
- //
- MemoryHob2->AllocDescriptor.MemoryBaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
- MemoryHob2->AllocDescriptor.MemoryLength += MemoryHob->AllocDescriptor.MemoryLength;
- Merged = TRUE;
- //
- // Mark MemoryHob to be unused(freed).
- //
- MemoryHob->Header.HobType = EFI_HOB_TYPE_UNUSED;
- break;
- }
- }
-
- Hob2.Raw = GET_NEXT_HOB (Hob2);
- Hob2.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob2.Raw);
- }
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
- }
-
- return Merged;
-}
-
-/**
- Find free memory by searching memory allocation HOBs.
-
- @param[in] MemoryType The type of memory to allocate.
- @param[in] Pages The number of contiguous 4 KB pages to allocate.
- @param[in] Granularity Page allocation granularity.
- @param[out] Memory Pointer to a physical address. On output, the address is set to the base
- of the page range that was allocated.
-
- @retval EFI_SUCCESS The memory range was successfully allocated.
- @retval EFI_NOT_FOUND No memory allocation HOB with big enough free memory found.
-
-**/
-EFI_STATUS
-FindFreeMemoryFromMemoryAllocationHob (
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- IN UINTN Granularity,
- OUT EFI_PHYSICAL_ADDRESS *Memory
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
- UINT64 Bytes;
- EFI_PHYSICAL_ADDRESS BaseAddress;
-
- Bytes = LShiftU64 (Pages, EFI_PAGE_SHIFT);
-
- BaseAddress = 0;
- MemoryAllocationHob = NULL;
- Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
- while (Hob.Raw != NULL) {
- if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) &&
- (Hob.MemoryAllocation->AllocDescriptor.MemoryLength >= Bytes))
- {
- //
- // Found one memory allocation HOB with big enough free memory.
- //
- MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
- BaseAddress = MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress +
- MemoryAllocationHob->AllocDescriptor.MemoryLength - Bytes;
- //
- // Make sure the granularity could be satisfied.
- //
- BaseAddress &= ~((EFI_PHYSICAL_ADDRESS)Granularity - 1);
- if (BaseAddress >= MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) {
- break;
- }
-
- BaseAddress = 0;
- MemoryAllocationHob = NULL;
- }
-
- //
- // Continue to find.
- //
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
- }
-
- if (MemoryAllocationHob != NULL) {
- UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, BaseAddress, Bytes, MemoryType);
- *Memory = BaseAddress;
- return EFI_SUCCESS;
- } else {
- if (MergeFreeMemoryInMemoryAllocationHob ()) {
- //
- // Retry if there are free memory ranges merged.
- //
- return FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
- }
-
- return EFI_NOT_FOUND;
- }
-}
-
-/**
- The purpose of the service is to publish an interface that allows
- PEIMs to allocate memory ranges that are managed by the PEI Foundation.
-
- Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap.
- After InstallPeiMemory() is called, PEI will allocate pages within the region
- of memory provided by InstallPeiMemory() service in a best-effort fashion.
- Location-specific allocations are not managed by the PEI foundation code.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param MemoryType The type of memory to allocate.
- @param Pages The number of contiguous 4 KB pages to allocate.
- @param Memory Pointer to a physical address. On output, the address is set to the base
- of the page range that was allocated.
-
- @retval EFI_SUCCESS The memory range was successfully allocated.
- @retval EFI_OUT_OF_RESOURCES The pages could not be allocated.
- @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode,
- EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData,
- EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiAllocatePages (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT EFI_PHYSICAL_ADDRESS *Memory
- )
-{
- EFI_STATUS Status;
- PEI_CORE_INSTANCE *PrivateData;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
- EFI_PHYSICAL_ADDRESS *FreeMemoryBottom;
- UINTN RemainingPages;
- UINTN Granularity;
- UINTN Padding;
-
- if ((MemoryType != EfiLoaderCode) &&
- (MemoryType != EfiLoaderData) &&
- (MemoryType != EfiRuntimeServicesCode) &&
- (MemoryType != EfiRuntimeServicesData) &&
- (MemoryType != EfiBootServicesCode) &&
- (MemoryType != EfiBootServicesData) &&
- (MemoryType != EfiACPIReclaimMemory) &&
- (MemoryType != EfiReservedMemoryType) &&
- (MemoryType != EfiACPIMemoryNVS))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
- Hob.Raw = PrivateData->HobList.Raw;
-
- if (Hob.Raw == NULL) {
- //
- // HOB is not initialized yet.
- //
- return EFI_NOT_AVAILABLE_YET;
- }
-
- if ((RUNTIME_PAGE_ALLOCATION_GRANULARITY > DEFAULT_PAGE_ALLOCATION_GRANULARITY) &&
- ((MemoryType == EfiReservedMemoryType) ||
- (MemoryType == EfiACPIMemoryNVS) ||
- (MemoryType == EfiRuntimeServicesCode) ||
- (MemoryType == EfiRuntimeServicesData)))
- {
- Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
-
- DEBUG ((
- DEBUG_INFO,
- "AllocatePages: aligning allocation to %d KB\n",
- Granularity / SIZE_1KB
- ));
- }
-
- if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) {
- //
- // When PeiInstallMemory is called but temporary memory has *not* been moved to permanent memory,
- // the AllocatePage will depend on the field of PEI_CORE_INSTANCE structure.
- //
- FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
- FreeMemoryBottom = &(PrivateData->PhysicalMemoryBegin);
- } else {
- FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop);
- FreeMemoryBottom = &(Hob.HandoffInformationTable->EfiFreeMemoryBottom);
- }
-
- //
- // Check to see if on correct boundary for the memory type.
- // If not aligned, make the allocation aligned.
- //
- Padding = *(FreeMemoryTop) & (Granularity - 1);
- if ((UINTN)(*FreeMemoryTop - *FreeMemoryBottom) < Padding) {
- DEBUG ((DEBUG_ERROR, "AllocatePages failed: Out of space after padding.\n"));
- return EFI_OUT_OF_RESOURCES;
- }
-
- *(FreeMemoryTop) -= Padding;
- if (Padding >= EFI_PAGE_SIZE) {
- //
- // Create a memory allocation HOB to cover
- // the pages that we will lose to rounding
- //
- InternalBuildMemoryAllocationHob (
- *(FreeMemoryTop),
- Padding & ~(UINTN)EFI_PAGE_MASK,
- EfiConventionalMemory
- );
- }
-
- //
- // Verify that there is sufficient memory to satisfy the allocation.
- //
- RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PAGE_SHIFT;
- //
- // The number of remaining pages needs to be greater than or equal to that of the request pages.
- //
- Pages = ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity));
- if (RemainingPages < Pages) {
- //
- // Try to find free memory by searching memory allocation HOBs.
- //
- Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
- if (!EFI_ERROR (Status)) {
- return Status;
- }
-
- DEBUG ((DEBUG_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64)Pages));
- DEBUG ((DEBUG_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64)RemainingPages));
- return EFI_OUT_OF_RESOURCES;
- } else {
- //
- // Update the PHIT to reflect the memory usage
- //
- *(FreeMemoryTop) -= Pages * EFI_PAGE_SIZE;
-
- //
- // Update the value for the caller
- //
- *Memory = *(FreeMemoryTop);
-
- //
- // Create a memory allocation HOB.
- //
- InternalBuildMemoryAllocationHob (
- *(FreeMemoryTop),
- Pages * EFI_PAGE_SIZE,
- MemoryType
- );
-
- return EFI_SUCCESS;
- }
-}
-
-/**
- Mark the memory allocation HOB to be unused(freed) and update *FreeMemoryTop
- if MemoryBaseAddress == *FreeMemoryTop.
-
- @param[in] PrivateData Pointer to PeiCore's private data structure.
- @param[in, out] MemoryAllocationHobToFree Pointer to memory allocation HOB to be freed.
-
-**/
-VOID
-FreeMemoryAllocationHob (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHobToFree
- )
-{
- EFI_PEI_HOB_POINTERS Hob;
- EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
- EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
-
- Hob.Raw = PrivateData->HobList.Raw;
-
- if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) {
- //
- // When PeiInstallMemory is called but temporary memory has *not* been moved to permanent memory,
- // use the FreePhysicalMemoryTop field of PEI_CORE_INSTANCE structure.
- //
- FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
- } else {
- FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop);
- }
-
- if (MemoryAllocationHobToFree->AllocDescriptor.MemoryBaseAddress == *FreeMemoryTop) {
- //
- // Update *FreeMemoryTop.
- //
- *FreeMemoryTop += MemoryAllocationHobToFree->AllocDescriptor.MemoryLength;
- //
- // Mark the memory allocation HOB to be unused(freed).
- //
- MemoryAllocationHobToFree->Header.HobType = EFI_HOB_TYPE_UNUSED;
-
- MemoryAllocationHob = NULL;
- Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
- while (Hob.Raw != NULL) {
- if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) &&
- (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == *FreeMemoryTop))
- {
- //
- // Found memory allocation HOB that has EfiConventionalMemory MemoryType and
- // MemoryBaseAddress == new *FreeMemoryTop.
- //
- MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
- break;
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
- }
-
- //
- // Free memory allocation HOB iteratively.
- //
- if (MemoryAllocationHob != NULL) {
- FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob);
- }
- }
-}
-
-/**
- Frees memory pages.
-
- @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param[in] Memory The base physical address of the pages to be freed.
- @param[in] Pages The number of contiguous 4 KB pages to free.
-
- @retval EFI_SUCCESS The requested pages were freed.
- @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid.
- @retval EFI_NOT_FOUND The requested memory pages were not allocated with
- AllocatePages().
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFreePages (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS Memory,
- IN UINTN Pages
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- UINT64 Bytes;
- UINT64 Start;
- UINT64 End;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
-
- Bytes = LShiftU64 (Pages, EFI_PAGE_SHIFT);
- Start = Memory;
- End = Start + Bytes - 1;
-
- if ((Pages == 0) || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
- Hob.Raw = PrivateData->HobList.Raw;
-
- if (Hob.Raw == NULL) {
- //
- // HOB is not initialized yet.
- //
- return EFI_NOT_AVAILABLE_YET;
- }
-
- MemoryAllocationHob = NULL;
- Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
- while (Hob.Raw != NULL) {
- if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType != EfiConventionalMemory) &&
- (Memory >= Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress) &&
- ((Memory + Bytes) <= (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength)))
- {
- //
- // Found the memory allocation HOB that includes the memory pages to be freed.
- //
- MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
- break;
- }
-
- Hob.Raw = GET_NEXT_HOB (Hob);
- Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
- }
-
- if (MemoryAllocationHob != NULL) {
- UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, Memory, Bytes, EfiConventionalMemory);
- FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob);
- return EFI_SUCCESS;
- } else {
- return EFI_NOT_FOUND;
- }
-}
-
-/**
-
- Pool allocation service. Before permanent memory is discovered, the pool will
- be allocated in the heap in temporary memory. Generally, the size of the heap in temporary
- memory does not exceed 64K, so the biggest pool size could be allocated is
- 64K.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param Size Amount of memory required
- @param Buffer Address of pointer to the buffer
-
- @retval EFI_SUCCESS The allocation was successful
- @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
- to allocate the requested size.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiAllocatePool (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINTN Size,
- OUT VOID **Buffer
- )
-{
- EFI_STATUS Status;
- EFI_HOB_MEMORY_POOL *Hob;
-
- //
- // If some "post-memory" PEIM wishes to allocate larger pool,
- // it should use AllocatePages service instead.
- //
-
- //
- // Generally, the size of heap in temporary memory does not exceed 64K,
- // HobLength is multiples of 8 bytes, so the maximum size of pool is 0xFFF8 - sizeof (EFI_HOB_MEMORY_POOL)
- //
- if (Size > (0xFFF8 - sizeof (EFI_HOB_MEMORY_POOL))) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = PeiServicesCreateHob (
- EFI_HOB_TYPE_MEMORY_POOL,
- (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
- (VOID **)&Hob
- );
- ASSERT_EFI_ERROR (Status);
-
- if (EFI_ERROR (Status)) {
- *Buffer = NULL;
- } else {
- *Buffer = Hob + 1;
- }
-
- return Status;
-}
+/** @file + EFI PEI Core memory services + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + Initialize the memory services. + + @param PrivateData Points to PeiCore's private instance data. + @param SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + @param OldCoreData Pointer to the PEI Core data. + NULL if being run in non-permanent memory mode. + +**/ +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +{ + PrivateData->SwitchStackSignal = FALSE; + + // + // First entering PeiCore, following code will initialized some field + // in PeiCore's private data according to hand off data from SEC core. + // + if (OldCoreData == NULL) { + PrivateData->PeiMemoryInstalled = FALSE; + PrivateData->HobList.Raw = SecCoreData->PeiTemporaryRamBase; + + PeiCoreBuildHobHandoffInfoTable ( + BOOT_WITH_FULL_CONFIGURATION, + (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->PeiTemporaryRamBase, + (UINTN)SecCoreData->PeiTemporaryRamSize + ); + + // + // Set Ps to point to ServiceTableShadow in Cache + // + PrivateData->Ps = &(PrivateData->ServiceTableShadow); + } + + return; +} + +/** + + This function registers the found memory configuration with the PEI Foundation. + + The usage model is that the PEIM that discovers the permanent memory shall invoke this service. + This routine will hold discoveried memory information into PeiCore's private data, + and set SwitchStackSignal flag. After PEIM who discovery memory is dispatched, + PeiDispatcher will migrate temporary memory to permanent memory. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryBegin Start of memory address. + @param MemoryLength Length of memory. + + @return EFI_SUCCESS Always success. + +**/ +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + PEI_CORE_INSTANCE *PrivateData; + + DEBUG ((DEBUG_INFO, "PeiInstallPeiMemory MemoryBegin 0x%LX, MemoryLength 0x%LX\n", MemoryBegin, MemoryLength)); + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // PEI_SERVICE.InstallPeiMemory should only be called one time during whole PEI phase. + // If it is invoked more than one time, ASSERT information is given for developer debugging in debug tip and + // simply return EFI_SUCCESS in release tip to ignore it. + // + if (PrivateData->PeiMemoryInstalled) { + DEBUG ((DEBUG_ERROR, "ERROR: PeiInstallPeiMemory is called more than once!\n")); + ASSERT (FALSE); + return EFI_SUCCESS; + } + + PrivateData->PhysicalMemoryBegin = MemoryBegin; + PrivateData->PhysicalMemoryLength = MemoryLength; + PrivateData->FreePhysicalMemoryTop = MemoryBegin + MemoryLength; + + PrivateData->SwitchStackSignal = TRUE; + + return EFI_SUCCESS; +} + +/** + Migrate memory pages allocated in pre-memory phase. + Copy memory pages at temporary heap top to permanent heap top. + + @param[in] Private Pointer to the private data passed in from caller. + @param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory. + +**/ +VOID +MigrateMemoryPages ( + IN PEI_CORE_INSTANCE *Private, + IN BOOLEAN TemporaryRamMigrated + ) +{ + EFI_PHYSICAL_ADDRESS NewMemPagesBase; + EFI_PHYSICAL_ADDRESS MemPagesBase; + + Private->MemoryPages.Size = (UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - + Private->HobList.HandoffInformationTable->EfiFreeMemoryTop); + if (Private->MemoryPages.Size == 0) { + // + // No any memory page allocated in pre-memory phase. + // + return; + } + + Private->MemoryPages.Base = Private->HobList.HandoffInformationTable->EfiFreeMemoryTop; + + ASSERT (Private->MemoryPages.Size <= Private->FreePhysicalMemoryTop); + NewMemPagesBase = Private->FreePhysicalMemoryTop - Private->MemoryPages.Size; + NewMemPagesBase &= ~(UINT64)EFI_PAGE_MASK; + ASSERT (NewMemPagesBase >= Private->PhysicalMemoryBegin); + // + // Copy memory pages at temporary heap top to permanent heap top. + // + if (TemporaryRamMigrated) { + // + // Memory pages at temporary heap top has been migrated to permanent heap, + // Here still needs to copy them from permanent heap to permanent heap top. + // + MemPagesBase = Private->MemoryPages.Base; + if (Private->HeapOffsetPositive) { + MemPagesBase += Private->HeapOffset; + } else { + MemPagesBase -= Private->HeapOffset; + } + + CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)MemPagesBase, Private->MemoryPages.Size); + } else { + CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)Private->MemoryPages.Base, Private->MemoryPages.Size); + } + + if (NewMemPagesBase >= Private->MemoryPages.Base) { + Private->MemoryPages.OffsetPositive = TRUE; + Private->MemoryPages.Offset = (UINTN)(NewMemPagesBase - Private->MemoryPages.Base); + } else { + Private->MemoryPages.OffsetPositive = FALSE; + Private->MemoryPages.Offset = (UINTN)(Private->MemoryPages.Base - NewMemPagesBase); + } + + DEBUG ((DEBUG_INFO, "Pages Offset = 0x%lX\n", (UINT64)Private->MemoryPages.Offset)); + + Private->FreePhysicalMemoryTop = NewMemPagesBase; +} + +/** + Migrate the base address in firmware volume allocation HOBs + from temporary memory to PEI installed memory. + + @param[in] PrivateData Pointer to PeiCore's private data structure. + @param[in] OrgFvHandle Address of FV Handle in temporary memory. + @param[in] FvHandle Address of FV Handle in permanent memory. + +**/ +VOID +ConvertFvHob ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN OrgFvHandle, + IN UINTN FvHandle + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob; + EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2Hob; + EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3Hob; + + DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n")); + + for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) { + FirmwareVolumeHob = Hob.FirmwareVolume; + if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) { + FirmwareVolumeHob->BaseAddress = FvHandle; + } + } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) { + FirmwareVolume2Hob = Hob.FirmwareVolume2; + if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) { + FirmwareVolume2Hob->BaseAddress = FvHandle; + } + } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) { + FirmwareVolume3Hob = Hob.FirmwareVolume3; + if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) { + FirmwareVolume3Hob->BaseAddress = FvHandle; + } + } + } +} + +/** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. + + @param[in] PrivateData Pointer to PeiCore's private data structure. + +**/ +VOID +ConvertMemoryAllocationHobs ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + EFI_PHYSICAL_ADDRESS OldMemPagesBase; + UINTN OldMemPagesSize; + + if (PrivateData->MemoryPages.Size == 0) { + // + // No any memory page allocated in pre-memory phase. + // + return; + } + + OldMemPagesBase = PrivateData->MemoryPages.Base; + OldMemPagesSize = PrivateData->MemoryPages.Size; + + MemoryAllocationHob = NULL; + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw != NULL) { + MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw; + if ((MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress >= OldMemPagesBase) && + (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress < (OldMemPagesBase + OldMemPagesSize)) + ) + { + if (PrivateData->MemoryPages.OffsetPositive) { + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress += PrivateData->MemoryPages.Offset; + } else { + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress -= PrivateData->MemoryPages.Offset; + } + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } +} + +/** + Internal function to build a HOB for the memory allocation. + It will search and reuse the unused(freed) memory allocation HOB, + or build memory allocation HOB normally if no unused(freed) memory allocation HOB found. + + @param[in] BaseAddress The 64 bit physical address of the memory. + @param[in] Length The length of the memory allocation in bytes. + @param[in] MemoryType The type of memory allocated by this HOB. + +**/ +VOID +InternalBuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + + // + // Search unused(freed) memory allocation HOB. + // + MemoryAllocationHob = NULL; + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_UNUSED); + while (Hob.Raw != NULL) { + if (Hob.Header->HobLength == sizeof (EFI_HOB_MEMORY_ALLOCATION)) { + MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw; + break; + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_UNUSED, Hob.Raw); + } + + if (MemoryAllocationHob != NULL) { + // + // Reuse the unused(freed) memory allocation HOB. + // + MemoryAllocationHob->Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION; + ZeroMem (&(MemoryAllocationHob->AllocDescriptor.Name), sizeof (EFI_GUID)); + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + MemoryAllocationHob->AllocDescriptor.MemoryLength = Length; + MemoryAllocationHob->AllocDescriptor.MemoryType = MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (MemoryAllocationHob->AllocDescriptor.Reserved, sizeof (MemoryAllocationHob->AllocDescriptor.Reserved)); + } else { + // + // No unused(freed) memory allocation HOB found. + // Build memory allocation HOB normally. + // + BuildMemoryAllocationHob ( + BaseAddress, + Length, + MemoryType + ); + } +} + +/** + Update or split memory allocation HOB for memory pages allocate and free. + + @param[in, out] MemoryAllocationHob Pointer to the memory allocation HOB + that needs to be updated or split. + On output, it will be filled with + the input Memory, Bytes and MemoryType. + @param[in] Memory Memory to allocate or free. + @param[in] Bytes Bytes to allocate or free. + @param[in] MemoryType EfiConventionalMemory for pages free, + others for pages allocate. + +**/ +VOID +UpdateOrSplitMemoryAllocationHob ( + IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINT64 Bytes, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + if ((Memory + Bytes) < + (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllocationHob->AllocDescriptor.MemoryLength)) + { + // + // Last pages need to be split out. + // + InternalBuildMemoryAllocationHob ( + Memory + Bytes, + (MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllocationHob->AllocDescriptor.MemoryLength) - (Memory + Bytes), + MemoryAllocationHob->AllocDescriptor.MemoryType + ); + } + + if (Memory > MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) { + // + // First pages need to be split out. + // + InternalBuildMemoryAllocationHob ( + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress, + Memory - MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress, + MemoryAllocationHob->AllocDescriptor.MemoryType + ); + } + + // + // Update the memory allocation HOB. + // + MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress = Memory; + MemoryAllocationHob->AllocDescriptor.MemoryLength = Bytes; + MemoryAllocationHob->AllocDescriptor.MemoryType = MemoryType; +} + +/** + Merge adjacent free memory ranges in memory allocation HOBs. + + @retval TRUE There are free memory ranges merged. + @retval FALSE No free memory ranges merged. + +**/ +BOOLEAN +MergeFreeMemoryInMemoryAllocationHob ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PEI_HOB_POINTERS Hob2; + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; + EFI_HOB_MEMORY_ALLOCATION *MemoryHob2; + UINT64 Start; + UINT64 End; + BOOLEAN Merged; + + Merged = FALSE; + + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw != NULL) { + if (Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) { + MemoryHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw; + Start = MemoryHob->AllocDescriptor.MemoryBaseAddress; + End = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength; + + Hob2.Raw = GET_NEXT_HOB (Hob); + Hob2.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + while (Hob2.Raw != NULL) { + if (Hob2.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) { + MemoryHob2 = (EFI_HOB_MEMORY_ALLOCATION *)Hob2.Raw; + if (Start == (MemoryHob2->AllocDescriptor.MemoryBaseAddress + MemoryHob2->AllocDescriptor.MemoryLength)) { + // + // Merge adjacent two free memory ranges. + // + MemoryHob2->AllocDescriptor.MemoryLength += MemoryHob->AllocDescriptor.MemoryLength; + Merged = TRUE; + // + // Mark MemoryHob to be unused(freed). + // + MemoryHob->Header.HobType = EFI_HOB_TYPE_UNUSED; + break; + } else if (End == MemoryHob2->AllocDescriptor.MemoryBaseAddress) { + // + // Merge adjacent two free memory ranges. + // + MemoryHob2->AllocDescriptor.MemoryBaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress; + MemoryHob2->AllocDescriptor.MemoryLength += MemoryHob->AllocDescriptor.MemoryLength; + Merged = TRUE; + // + // Mark MemoryHob to be unused(freed). + // + MemoryHob->Header.HobType = EFI_HOB_TYPE_UNUSED; + break; + } + } + + Hob2.Raw = GET_NEXT_HOB (Hob2); + Hob2.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob2.Raw); + } + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + return Merged; +} + +/** + Find free memory by searching memory allocation HOBs. + + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of contiguous 4 KB pages to allocate. + @param[in] Granularity Page allocation granularity. + @param[out] Memory Pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_NOT_FOUND No memory allocation HOB with big enough free memory found. + +**/ +EFI_STATUS +FindFreeMemoryFromMemoryAllocationHob ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Granularity, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + UINT64 Bytes; + EFI_PHYSICAL_ADDRESS BaseAddress; + + Bytes = LShiftU64 (Pages, EFI_PAGE_SHIFT); + + BaseAddress = 0; + MemoryAllocationHob = NULL; + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw != NULL) { + if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) && + (Hob.MemoryAllocation->AllocDescriptor.MemoryLength >= Bytes)) + { + // + // Found one memory allocation HOB with big enough free memory. + // + MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw; + BaseAddress = MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + + MemoryAllocationHob->AllocDescriptor.MemoryLength - Bytes; + // + // Make sure the granularity could be satisfied. + // + BaseAddress &= ~((EFI_PHYSICAL_ADDRESS)Granularity - 1); + if (BaseAddress >= MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) { + break; + } + + BaseAddress = 0; + MemoryAllocationHob = NULL; + } + + // + // Continue to find. + // + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + if (MemoryAllocationHob != NULL) { + UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, BaseAddress, Bytes, MemoryType); + *Memory = BaseAddress; + return EFI_SUCCESS; + } else { + if (MergeFreeMemoryInMemoryAllocationHob ()) { + // + // Retry if there are free memory ranges merged. + // + return FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory); + } + + return EFI_NOT_FOUND; + } +} + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap. + After InstallPeiMemory() is called, PEI will allocate pages within the region + of memory provided by InstallPeiMemory() service in a best-effort fashion. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + +**/ +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + EFI_STATUS Status; + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS *FreeMemoryTop; + EFI_PHYSICAL_ADDRESS *FreeMemoryBottom; + UINTN RemainingPages; + UINTN Granularity; + UINTN Padding; + + if ((MemoryType != EfiLoaderCode) && + (MemoryType != EfiLoaderData) && + (MemoryType != EfiRuntimeServicesCode) && + (MemoryType != EfiRuntimeServicesData) && + (MemoryType != EfiBootServicesCode) && + (MemoryType != EfiBootServicesData) && + (MemoryType != EfiACPIReclaimMemory) && + (MemoryType != EfiReservedMemoryType) && + (MemoryType != EfiACPIMemoryNVS)) + { + return EFI_INVALID_PARAMETER; + } + + Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + Hob.Raw = PrivateData->HobList.Raw; + + if (Hob.Raw == NULL) { + // + // HOB is not initialized yet. + // + return EFI_NOT_AVAILABLE_YET; + } + + if ((RUNTIME_PAGE_ALLOCATION_GRANULARITY > DEFAULT_PAGE_ALLOCATION_GRANULARITY) && + ((MemoryType == EfiReservedMemoryType) || + (MemoryType == EfiACPIMemoryNVS) || + (MemoryType == EfiRuntimeServicesCode) || + (MemoryType == EfiRuntimeServicesData))) + { + Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY; + + DEBUG (( + DEBUG_INFO, + "AllocatePages: aligning allocation to %d KB\n", + Granularity / SIZE_1KB + )); + } + + if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) { + // + // When PeiInstallMemory is called but temporary memory has *not* been moved to permanent memory, + // the AllocatePage will depend on the field of PEI_CORE_INSTANCE structure. + // + FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop); + FreeMemoryBottom = &(PrivateData->PhysicalMemoryBegin); + } else { + FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop); + FreeMemoryBottom = &(Hob.HandoffInformationTable->EfiFreeMemoryBottom); + } + + // + // Check to see if on correct boundary for the memory type. + // If not aligned, make the allocation aligned. + // + Padding = *(FreeMemoryTop) & (Granularity - 1); + if ((UINTN)(*FreeMemoryTop - *FreeMemoryBottom) < Padding) { + DEBUG ((DEBUG_ERROR, "AllocatePages failed: Out of space after padding.\n")); + return EFI_OUT_OF_RESOURCES; + } + + *(FreeMemoryTop) -= Padding; + if (Padding >= EFI_PAGE_SIZE) { + // + // Create a memory allocation HOB to cover + // the pages that we will lose to rounding + // + InternalBuildMemoryAllocationHob ( + *(FreeMemoryTop), + Padding & ~(UINTN)EFI_PAGE_MASK, + EfiConventionalMemory + ); + } + + // + // Verify that there is sufficient memory to satisfy the allocation. + // + RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PAGE_SHIFT; + // + // The number of remaining pages needs to be greater than or equal to that of the request pages. + // + Pages = ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity)); + if (RemainingPages < Pages) { + // + // Try to find free memory by searching memory allocation HOBs. + // + Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory); + if (!EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64)Pages)); + DEBUG ((DEBUG_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64)RemainingPages)); + return EFI_OUT_OF_RESOURCES; + } else { + // + // Update the PHIT to reflect the memory usage + // + *(FreeMemoryTop) -= Pages * EFI_PAGE_SIZE; + + // + // Update the value for the caller + // + *Memory = *(FreeMemoryTop); + + // + // Create a memory allocation HOB. + // + InternalBuildMemoryAllocationHob ( + *(FreeMemoryTop), + Pages * EFI_PAGE_SIZE, + MemoryType + ); + + return EFI_SUCCESS; + } +} + +/** + Mark the memory allocation HOB to be unused(freed) and update *FreeMemoryTop + if MemoryBaseAddress == *FreeMemoryTop. + + @param[in] PrivateData Pointer to PeiCore's private data structure. + @param[in, out] MemoryAllocationHobToFree Pointer to memory allocation HOB to be freed. + +**/ +VOID +FreeMemoryAllocationHob ( + IN PEI_CORE_INSTANCE *PrivateData, + IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHobToFree + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS *FreeMemoryTop; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + + Hob.Raw = PrivateData->HobList.Raw; + + if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) { + // + // When PeiInstallMemory is called but temporary memory has *not* been moved to permanent memory, + // use the FreePhysicalMemoryTop field of PEI_CORE_INSTANCE structure. + // + FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop); + } else { + FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop); + } + + if (MemoryAllocationHobToFree->AllocDescriptor.MemoryBaseAddress == *FreeMemoryTop) { + // + // Update *FreeMemoryTop. + // + *FreeMemoryTop += MemoryAllocationHobToFree->AllocDescriptor.MemoryLength; + // + // Mark the memory allocation HOB to be unused(freed). + // + MemoryAllocationHobToFree->Header.HobType = EFI_HOB_TYPE_UNUSED; + + MemoryAllocationHob = NULL; + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw != NULL) { + if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) && + (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == *FreeMemoryTop)) + { + // + // Found memory allocation HOB that has EfiConventionalMemory MemoryType and + // MemoryBaseAddress == new *FreeMemoryTop. + // + MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw; + break; + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + // + // Free memory allocation HOB iteratively. + // + if (MemoryAllocationHob != NULL) { + FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob); + } + } +} + +/** + Frees memory pages. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] Memory The base physical address of the pages to be freed. + @param[in] Pages The number of contiguous 4 KB pages to free. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +PeiFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINT64 Bytes; + UINT64 Start; + UINT64 End; + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob; + + Bytes = LShiftU64 (Pages, EFI_PAGE_SHIFT); + Start = Memory; + End = Start + Bytes - 1; + + if ((Pages == 0) || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + Hob.Raw = PrivateData->HobList.Raw; + + if (Hob.Raw == NULL) { + // + // HOB is not initialized yet. + // + return EFI_NOT_AVAILABLE_YET; + } + + MemoryAllocationHob = NULL; + Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); + while (Hob.Raw != NULL) { + if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType != EfiConventionalMemory) && + (Memory >= Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress) && + ((Memory + Bytes) <= (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength))) + { + // + // Found the memory allocation HOB that includes the memory pages to be freed. + // + MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw; + break; + } + + Hob.Raw = GET_NEXT_HOB (Hob); + Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw); + } + + if (MemoryAllocationHob != NULL) { + UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, Memory, Bytes, EfiConventionalMemory); + FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob); + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + +/** + + Pool allocation service. Before permanent memory is discovered, the pool will + be allocated in the heap in temporary memory. Generally, the size of the heap in temporary + memory does not exceed 64K, so the biggest pool size could be allocated is + 64K. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Size Amount of memory required + @param Buffer Address of pointer to the buffer + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_POOL *Hob; + + // + // If some "post-memory" PEIM wishes to allocate larger pool, + // it should use AllocatePages service instead. + // + + // + // Generally, the size of heap in temporary memory does not exceed 64K, + // HobLength is multiples of 8 bytes, so the maximum size of pool is 0xFFF8 - sizeof (EFI_HOB_MEMORY_POOL) + // + if (Size > (0xFFF8 - sizeof (EFI_HOB_MEMORY_POOL))) { + return EFI_OUT_OF_RESOURCES; + } + + Status = PeiServicesCreateHob ( + EFI_HOB_TYPE_MEMORY_POOL, + (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size), + (VOID **)&Hob + ); + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + *Buffer = NULL; + } else { + *Buffer = Hob + 1; + } + + return Status; +} diff --git a/MdeModulePkg/Core/Pei/PciCfg2/PciCfg2.c b/MdeModulePkg/Core/Pei/PciCfg2/PciCfg2.c index cd15d016d7..4728a29774 100644 --- a/MdeModulePkg/Core/Pei/PciCfg2/PciCfg2.c +++ b/MdeModulePkg/Core/Pei/PciCfg2/PciCfg2.c @@ -1,122 +1,122 @@ -/** @file
- The default version of EFI_PEI_PCI_CFG2_PPI support published by PeiServices in
- PeiCore initialization phase.
-
- EFI_PEI_PCI_CFG2_PPI is installed by the PEIM which supports a PCI root bridge.
- When PeiCore is started, the default version of EFI_PEI_PCI_CFG2_PPI will be assigned
- to PeiServices table.
-
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-///
-/// This default instance of EFI_PEI_PCI_CFG2_PPI install assigned to EFI_PEI_SERVICE.PciCfg
-/// when PeiCore's initialization.
-///
-EFI_PEI_PCI_CFG2_PPI gPeiDefaultPciCfg2Ppi = {
- PeiDefaultPciCfg2Read,
- PeiDefaultPciCfg2Write,
- PeiDefaultPciCfg2Modify
-};
-
-/**
- Reads from a given location in the PCI configuration space.
-
- If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- See EFI_PEI_PCI_CFG_PPI_WIDTH above.
- @param Address The physical address of the access. The format of
- the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER The invalid access width.
- @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultPciCfg2Read (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PCI_CFG2_PPI *This,
- IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
- IN UINT64 Address,
- IN OUT VOID *Buffer
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- Write to a given location in the PCI configuration space.
-
- If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- See EFI_PEI_PCI_CFG_PPI_WIDTH above.
- @param Address The physical address of the access. The format of
- the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER The invalid access width.
- @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultPciCfg2Write (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PCI_CFG2_PPI *This,
- IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
- IN UINT64 Address,
- IN OUT VOID *Buffer
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- This function performs a read-modify-write operation on the contents from a given
- location in the PCI configuration space.
- If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes. Type
- EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
- @param Address The physical address of the access.
- @param SetBits Points to value to bitwise-OR with the read configuration value.
- The size of the value is determined by Width.
- @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.
- The size of the value is determined by Width.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER The invalid access width.
- @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultPciCfg2Modify (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PCI_CFG2_PPI *This,
- IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
- IN UINT64 Address,
- IN VOID *SetBits,
- IN VOID *ClearBits
- )
-{
- return EFI_NOT_AVAILABLE_YET;
-}
+/** @file + The default version of EFI_PEI_PCI_CFG2_PPI support published by PeiServices in + PeiCore initialization phase. + + EFI_PEI_PCI_CFG2_PPI is installed by the PEIM which supports a PCI root bridge. + When PeiCore is started, the default version of EFI_PEI_PCI_CFG2_PPI will be assigned + to PeiServices table. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/// +/// This default instance of EFI_PEI_PCI_CFG2_PPI install assigned to EFI_PEI_SERVICE.PciCfg +/// when PeiCore's initialization. +/// +EFI_PEI_PCI_CFG2_PPI gPeiDefaultPciCfg2Ppi = { + PeiDefaultPciCfg2Read, + PeiDefaultPciCfg2Write, + PeiDefaultPciCfg2Modify +}; + +/** + Reads from a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. + +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Read ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Write to a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Write ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + This function performs a read-modify-write operation on the contents from a given + location in the PCI configuration space. + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + @param Address The physical address of the access. + @param SetBits Points to value to bitwise-OR with the read configuration value. + The size of the value is determined by Width. + @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Modify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN VOID *SetBits, + IN VOID *ClearBits + ) +{ + return EFI_NOT_AVAILABLE_YET; +} diff --git a/MdeModulePkg/Core/Pei/PeiCore.uni b/MdeModulePkg/Core/Pei/PeiCore.uni index 1ddf2b9a83..dc5552e515 100644 --- a/MdeModulePkg/Core/Pei/PeiCore.uni +++ b/MdeModulePkg/Core/Pei/PeiCore.uni @@ -1,22 +1,22 @@ -// /** @file
-// PeiMain module is core module in PEI phase.
-//
-// It takes responsibilities of:
-// 1) Initialize memory, PPI, image services etc, to establish PEIM runtime environment.
-// 2) Dispatch PEIM from discovered FV.
-// 3) Handoff control to DxeIpl to load DXE core and enter DXE phase.
-//
-// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "Core module in PEI phase"
-
-#string STR_MODULE_DESCRIPTION #language en-US "It takes responsibilities of:<BR>\n"
- "1) Initializing memory, PPI, image services etc., to establish the PEIM runtime environment.<BR>\n"
- "2) Dispatches PEIM from discovered FV.<BR>\n"
- "3) Handsoff control to DxeIpl to load DXE core and enters DXE phase.<BR>"
-
+// /** @file +// PeiMain module is core module in PEI phase. +// +// It takes responsibilities of: +// 1) Initialize memory, PPI, image services etc, to establish PEIM runtime environment. +// 2) Dispatch PEIM from discovered FV. +// 3) Handoff control to DxeIpl to load DXE core and enter DXE phase. +// +// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Core module in PEI phase" + +#string STR_MODULE_DESCRIPTION #language en-US "It takes responsibilities of:<BR>\n" + "1) Initializing memory, PPI, image services etc., to establish the PEIM runtime environment.<BR>\n" + "2) Dispatches PEIM from discovered FV.<BR>\n" + "3) Handsoff control to DxeIpl to load DXE core and enters DXE phase.<BR>" + diff --git a/MdeModulePkg/Core/Pei/PeiCoreExtra.uni b/MdeModulePkg/Core/Pei/PeiCoreExtra.uni index b9e4f97902..f0ed283533 100644 --- a/MdeModulePkg/Core/Pei/PeiCoreExtra.uni +++ b/MdeModulePkg/Core/Pei/PeiCoreExtra.uni @@ -1,14 +1,14 @@ -// /** @file
-// PeiCore Localized Strings and Content
-//
-// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-#string STR_PROPERTIES_MODULE_NAME
-#language en-US
-"Core PEI Services Module"
-
-
+// /** @file +// PeiCore Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Core PEI Services Module" + + diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h index 46b6c23014..8c8b829ac1 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.h +++ b/MdeModulePkg/Core/Pei/PeiMain.h @@ -1,2030 +1,2030 @@ -/** @file
- Definition of Pei Core Structures and Services
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _PEI_MAIN_H_
-#define _PEI_MAIN_H_
-
-#include <PiPei.h>
-#include <Ppi/DxeIpl.h>
-#include <Ppi/MemoryDiscovered.h>
-#include <Ppi/StatusCode.h>
-#include <Ppi/Reset.h>
-#include <Ppi/Reset2.h>
-#include <Ppi/FirmwareVolume.h>
-#include <Ppi/FirmwareVolumeInfo.h>
-#include <Ppi/FirmwareVolumeInfo2.h>
-#include <Ppi/Decompress.h>
-#include <Ppi/GuidedSectionExtraction.h>
-#include <Ppi/LoadFile.h>
-#include <Ppi/Security2.h>
-#include <Ppi/TemporaryRamSupport.h>
-#include <Ppi/TemporaryRamDone.h>
-#include <Ppi/SecHobData.h>
-#include <Ppi/PeiCoreFvLocation.h>
-#include <Library/DebugLib.h>
-#include <Library/PeiCoreEntryPoint.h>
-#include <Library/BaseLib.h>
-#include <Library/HobLib.h>
-#include <Library/PerformanceLib.h>
-#include <Library/PeiServicesLib.h>
-#include <Library/ReportStatusCodeLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/CacheMaintenanceLib.h>
-#include <Library/PcdLib.h>
-#include <IndustryStandard/PeImage.h>
-#include <Library/PeiServicesTablePointerLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Guid/FirmwareFileSystem2.h>
-#include <Guid/FirmwareFileSystem3.h>
-#include <Guid/AprioriFileName.h>
-#include <Guid/MigratedFvInfo.h>
-
-///
-/// It is an FFS type extension used for PeiFindFileEx. It indicates current
-/// FFS searching is for all PEIMs can be dispatched by PeiCore.
-///
-#define PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE 0xff
-
-///
-/// Pei Core private data structures
-///
-typedef union {
- EFI_PEI_PPI_DESCRIPTOR *Ppi;
- EFI_PEI_NOTIFY_DESCRIPTOR *Notify;
- VOID *Raw;
-} PEI_PPI_LIST_POINTERS;
-
-///
-/// Number of PEI_PPI_LIST_POINTERS to grow by each time we run out of room
-///
-#define PPI_GROWTH_STEP 64
-#define CALLBACK_NOTIFY_GROWTH_STEP 32
-#define DISPATCH_NOTIFY_GROWTH_STEP 8
-
-typedef struct {
- UINTN CurrentCount;
- UINTN MaxCount;
- UINTN LastDispatchedCount;
- ///
- /// MaxCount number of entries.
- ///
- PEI_PPI_LIST_POINTERS *PpiPtrs;
-} PEI_PPI_LIST;
-
-typedef struct {
- UINTN CurrentCount;
- UINTN MaxCount;
- ///
- /// MaxCount number of entries.
- ///
- PEI_PPI_LIST_POINTERS *NotifyPtrs;
-} PEI_CALLBACK_NOTIFY_LIST;
-
-typedef struct {
- UINTN CurrentCount;
- UINTN MaxCount;
- UINTN LastDispatchedCount;
- ///
- /// MaxCount number of entries.
- ///
- PEI_PPI_LIST_POINTERS *NotifyPtrs;
-} PEI_DISPATCH_NOTIFY_LIST;
-
-///
-/// PPI database structure which contains three links:
-/// PpiList, CallbackNotifyList and DispatchNotifyList.
-///
-typedef struct {
- ///
- /// PPI List.
- ///
- PEI_PPI_LIST PpiList;
- ///
- /// Notify List at dispatch level.
- ///
- PEI_CALLBACK_NOTIFY_LIST CallbackNotifyList;
- ///
- /// Notify List at callback level.
- ///
- PEI_DISPATCH_NOTIFY_LIST DispatchNotifyList;
-} PEI_PPI_DATABASE;
-
-//
-// PEI_CORE_FV_HANDLE.PeimState
-// Do not change these values as there is code doing math to change states.
-// Look for Private->Fv[FvCount].PeimState[PeimCount]++;
-//
-#define PEIM_STATE_NOT_DISPATCHED 0x00
-#define PEIM_STATE_DISPATCHED 0x01
-#define PEIM_STATE_REGISTER_FOR_SHADOW 0x02
-#define PEIM_STATE_DONE 0x03
-
-//
-// Number of FV instances to grow by each time we run out of room
-//
-#define FV_GROWTH_STEP 8
-
-typedef struct {
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
- EFI_PEI_FV_HANDLE FvHandle;
- UINTN PeimCount;
- //
- // Pointer to the buffer with the PeimCount number of Entries.
- //
- UINT8 *PeimState;
- //
- // Pointer to the buffer with the PeimCount number of Entries.
- //
- EFI_PEI_FILE_HANDLE *FvFileHandles;
- BOOLEAN ScanFv;
- UINT32 AuthenticationStatus;
-} PEI_CORE_FV_HANDLE;
-
-typedef struct {
- EFI_GUID FvFormat;
- VOID *FvInfo;
- UINT32 FvInfoSize;
- UINT32 AuthenticationStatus;
- EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor;
-} PEI_CORE_UNKNOW_FORMAT_FV_INFO;
-
-#define CACHE_SETION_MAX_NUMBER 0x10
-typedef struct {
- EFI_COMMON_SECTION_HEADER *Section[CACHE_SETION_MAX_NUMBER];
- VOID *SectionData[CACHE_SETION_MAX_NUMBER];
- UINTN SectionSize[CACHE_SETION_MAX_NUMBER];
- UINT32 AuthenticationStatus[CACHE_SETION_MAX_NUMBER];
- UINTN AllSectionCount;
- UINTN SectionIndex;
-} CACHE_SECTION_DATA;
-
-#define HOLE_MAX_NUMBER 0x3
-typedef struct {
- EFI_PHYSICAL_ADDRESS Base;
- UINTN Size;
- UINTN Offset;
- BOOLEAN OffsetPositive;
-} HOLE_MEMORY_DATA;
-
-///
-/// Forward declaration for PEI_CORE_INSTANCE
-///
-typedef struct _PEI_CORE_INSTANCE PEI_CORE_INSTANCE;
-
-/**
- Function Pointer type for PeiCore function.
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
- An empty PPI list consists of a single descriptor with the end-tag
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
- phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
- that both the PEI Foundation and any modules can leverage the associated service
- calls and/or code in these early PPIs
- @param OldCoreData Pointer to old core data that is used to initialize the
- core's data areas.
-**/
-typedef
-EFI_STATUS
-(EFIAPI *PEICORE_FUNCTION_POINTER)(
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
- IN PEI_CORE_INSTANCE *OldCoreData
- );
-
-//
-// Number of files to grow by each time we run out of room
-//
-#define TEMP_FILE_GROWTH_STEP 32
-
-#define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C')
-
-///
-/// Pei Core private data structure instance
-///
-struct _PEI_CORE_INSTANCE {
- UINTN Signature;
-
- ///
- /// Point to ServiceTableShadow
- ///
- EFI_PEI_SERVICES *Ps;
- PEI_PPI_DATABASE PpiData;
-
- ///
- /// The count of FVs which contains FFS and could be dispatched by PeiCore.
- ///
- UINTN FvCount;
-
- ///
- /// The max count of FVs which contains FFS and could be dispatched by PeiCore.
- ///
- UINTN MaxFvCount;
-
- ///
- /// Pointer to the buffer with the MaxFvCount number of entries.
- /// Each entry is for one FV which contains FFS and could be dispatched by PeiCore.
- ///
- PEI_CORE_FV_HANDLE *Fv;
-
- ///
- /// Pointer to the buffer with the MaxUnknownFvInfoCount number of entries.
- /// Each entry is for one FV which could not be dispatched by PeiCore.
- ///
- PEI_CORE_UNKNOW_FORMAT_FV_INFO *UnknownFvInfo;
- UINTN MaxUnknownFvInfoCount;
- UINTN UnknownFvInfoCount;
-
- ///
- /// Pointer to the buffer FvFileHandlers in PEI_CORE_FV_HANDLE specified by CurrentPeimFvCount.
- ///
- EFI_PEI_FILE_HANDLE *CurrentFvFileHandles;
- UINTN AprioriCount;
- UINTN CurrentPeimFvCount;
- UINTN CurrentPeimCount;
- EFI_PEI_FILE_HANDLE CurrentFileHandle;
- BOOLEAN PeimNeedingDispatch;
- BOOLEAN PeimDispatchOnThisPass;
- BOOLEAN PeimDispatcherReenter;
- EFI_PEI_HOB_POINTERS HobList;
- BOOLEAN SwitchStackSignal;
- BOOLEAN PeiMemoryInstalled;
- VOID *CpuIo;
- EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi;
- EFI_PEI_SERVICES ServiceTableShadow;
- EFI_PEI_PPI_DESCRIPTOR *XipLoadFile;
- EFI_PHYSICAL_ADDRESS PhysicalMemoryBegin;
- UINT64 PhysicalMemoryLength;
- EFI_PHYSICAL_ADDRESS FreePhysicalMemoryTop;
- UINTN HeapOffset;
- BOOLEAN HeapOffsetPositive;
- UINTN StackOffset;
- BOOLEAN StackOffsetPositive;
- //
- // Information for migrating memory pages allocated in pre-memory phase.
- //
- HOLE_MEMORY_DATA MemoryPages;
- PEICORE_FUNCTION_POINTER ShadowedPeiCore;
- CACHE_SECTION_DATA CacheSection;
- //
- // For Loading modules at fixed address feature to cache the top address below which the
- // Runtime code, boot time code and PEI memory will be placed. Please note that the offset between this field
- // and Ps should not be changed since maybe user could get this top address by using the offset to Ps.
- //
- EFI_PHYSICAL_ADDRESS LoadModuleAtFixAddressTopAddress;
- //
- // The field is define for Loading modules at fixed address feature to tracker the PEI code
- // memory range usage. It is a bit mapped array in which every bit indicates the corresponding memory page
- // available or not.
- //
- UINT64 *PeiCodeMemoryRangeUsageBitMap;
- //
- // This field points to the shadowed image read function
- //
- PE_COFF_LOADER_READ_FILE ShadowedImageRead;
-
- UINTN TempPeimCount;
-
- //
- // Pointer to the temp buffer with the TempPeimCount number of entries.
- //
- EFI_PEI_FILE_HANDLE *TempFileHandles;
- //
- // Pointer to the temp buffer with the TempPeimCount number of entries.
- //
- EFI_GUID *TempFileGuid;
-
- //
- // Temp Memory Range is not covered by PeiTempMem and Stack.
- // Those Memory Range will be migrated into physical memory.
- //
- HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER];
-};
-
-///
-/// Pei Core Instance Data Macros
-///
-#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \
- CR(a, PEI_CORE_INSTANCE, Ps, PEI_CORE_HANDLE_SIGNATURE)
-
-///
-/// Union of temporarily used function pointers (to save stack space)
-///
-typedef union {
- PEICORE_FUNCTION_POINTER PeiCore;
- EFI_PEIM_ENTRY_POINT2 PeimEntry;
- EFI_PEIM_NOTIFY_ENTRY_POINT PeimNotifyEntry;
- EFI_DXE_IPL_PPI *DxeIpl;
- EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;
- EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
- VOID *Raw;
-} PEI_CORE_TEMP_POINTERS;
-
-typedef struct {
- CONST EFI_SEC_PEI_HAND_OFF *SecCoreData;
- EFI_PEI_PPI_DESCRIPTOR *PpiList;
- VOID *Data;
-} PEI_CORE_PARAMETERS;
-
-//
-// PeiCore function
-//
-
-/**
-
- The entry routine to Pei Core, invoked by PeiMain during transition
- from SEC to PEI. After switching stack in the PEI core, it will restart
- with the old core data.
-
-
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
- An empty PPI list consists of a single descriptor with the end-tag
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
- phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
- that both the PEI Foundation and any modules can leverage the associated service
- calls and/or code in these early PPIs
- @param Data Pointer to old core data that is used to initialize the
- core's data areas.
-
-**/
-VOID
-EFIAPI
-PeiCore (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
- IN VOID *Data
- );
-
-//
-// Dispatcher support functions
-//
-
-/**
-
- This is the POSTFIX version of the dependency evaluator. When a
- PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on
- the evaluation stack. When that entry is popped from the evaluation
- stack, the PPI is checked if it is installed. This method allows
- some time savings as not all PPIs must be checked for certain
- operation types (AND, OR).
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to
- the BNF described above and is stored in postfix notation.
-
- @retval TRUE if it is a well-formed Grammar
- @retval FALSE if the dependency expression overflows the evaluation stack
- if the dependency expression underflows the evaluation stack
- if the dependency expression is not a well-formed Grammar.
-
-**/
-BOOLEAN
-PeimDispatchReadiness (
- IN EFI_PEI_SERVICES **PeiServices,
- IN VOID *DependencyExpression
- );
-
-/**
- Migrate a PEIM from temporary RAM to permanent memory.
-
- @param PeimFileHandle Pointer to the FFS file header of the image.
- @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
-
- @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.
-
-**/
-EFI_STATUS
-EFIAPI
-MigratePeim (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN EFI_PEI_FILE_HANDLE MigratedFileHandle
- );
-
-/**
- Migrate FVs out of temporary RAM before the cache is flushed.
-
- @param Private PeiCore's private data structure
- @param SecCoreData Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
-
- @retval EFI_SUCCESS Successfully migrated installed FVs from temporary RAM to permanent memory.
- @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
-
-**/
-EFI_STATUS
-EFIAPI
-EvacuateTempRam (
- IN PEI_CORE_INSTANCE *Private,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
- );
-
-/**
- Conduct PEIM dispatch.
-
- @param SecCoreData Pointer to the data structure containing SEC to PEI handoff data
- @param PrivateData Pointer to the private data passed in from caller
-
-**/
-VOID
-PeiDispatcher (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *PrivateData
- );
-
-/**
- Initialize the Dispatcher's data members
-
- @param PrivateData PeiCore's private data structure
- @param OldCoreData Old data from SecCore
- NULL if being run in non-permanent memory mode.
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
-
-**/
-VOID
-InitializeDispatcherData (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_INSTANCE *OldCoreData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
- );
-
-/**
- This routine parses the Dependency Expression, if available, and
- decides if the module can be executed.
-
-
- @param Private PeiCore's private data structure
- @param FileHandle PEIM's file handle
- @param PeimCount The index of last dispatched PEIM.
-
- @retval TRUE Can be dispatched
- @retval FALSE Cannot be dispatched
-
-**/
-BOOLEAN
-DepexSatisfied (
- IN PEI_CORE_INSTANCE *Private,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINTN PeimCount
- );
-
-//
-// PPI support functions
-//
-
-/**
-
- Initialize PPI services.
-
- @param PrivateData Pointer to the PEI Core data.
- @param OldCoreData Pointer to old PEI Core data.
- NULL if being run in non-permanent memory mode.
-
-**/
-VOID
-InitializePpiServices (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_INSTANCE *OldCoreData
- );
-
-/**
-
- Migrate the Hob list from the temporary memory to PEI installed memory.
-
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param PrivateData Pointer to PeiCore's private data structure.
-
-**/
-VOID
-ConvertPpiPointers (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *PrivateData
- );
-
-/**
-
- Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
-
- @param PrivateData Pointer to PeiCore's private data structure.
- @param OrgFvHandle Address of FV Handle in temporary memory.
- @param FvHandle Address of FV Handle in permanent memory.
- @param FvSize Size of the FV.
-
-**/
-VOID
-ConvertPpiPointersFv (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN UINTN OrgFvHandle,
- IN UINTN FvHandle,
- IN UINTN FvSize
- );
-
-/**
-
- Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
-
- @param PrivateData Pointer to PeiCore's private data structure.
- @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
-
-**/
-VOID
-ConvertPeiCorePpiPointers (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_FV_HANDLE *CoreFvHandle
- );
-
-/**
-
- Dumps the PPI lists to debug output.
-
- @param PrivateData Points to PeiCore's private instance data.
-
-**/
-VOID
-DumpPpiList (
- IN PEI_CORE_INSTANCE *PrivateData
- );
-
-/**
-
- Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param PpiList Pointer to PPI array that want to be installed.
-
- @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
- @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
- if any PPI in PpiList is not valid
- @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
-
-**/
-EFI_STATUS
-EFIAPI
-PeiInstallPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
- );
-
-/**
-
- Re-Install PPI services.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param OldPpi Pointer to the old PEI PPI Descriptors.
- @param NewPpi Pointer to the new PEI PPI Descriptors.
-
- @retval EFI_SUCCESS if the operation was successful
- @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL
- if NewPpi is not valid
- @retval EFI_NOT_FOUND if the PPI was not in the database
-
-**/
-EFI_STATUS
-EFIAPI
-PeiReInstallPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi
- );
-
-/**
-
- Locate a given named PPI.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param Guid Pointer to GUID of the PPI.
- @param Instance Instance Number to discover.
- @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,
- returns a pointer to the descriptor (includes flags, etc)
- @param Ppi Pointer to reference the found PPI
-
- @retval EFI_SUCCESS if the PPI is in the database
- @retval EFI_NOT_FOUND if the PPI is not in the database
-
-**/
-EFI_STATUS
-EFIAPI
-PeiLocatePpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_GUID *Guid,
- IN UINTN Instance,
- IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
- IN OUT VOID **Ppi
- );
-
-/**
-
- Install a notification for a given PPI.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param NotifyList Pointer to list of Descriptors to notify upon.
-
- @retval EFI_SUCCESS if successful
- @retval EFI_OUT_OF_RESOURCES if no space in the database
- @retval EFI_INVALID_PARAMETER if not a good descriptor
-
-**/
-EFI_STATUS
-EFIAPI
-PeiNotifyPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
- );
-
-/**
-
- Process the Notify List at dispatch level.
-
- @param PrivateData PeiCore's private data structure.
-
-**/
-VOID
-ProcessDispatchNotifyList (
- IN PEI_CORE_INSTANCE *PrivateData
- );
-
-/**
-
- Process notifications.
-
- @param PrivateData PeiCore's private data structure
- @param NotifyType Type of notify to fire.
- @param InstallStartIndex Install Beginning index.
- @param InstallStopIndex Install Ending index.
- @param NotifyStartIndex Notify Beginning index.
- @param NotifyStopIndex Notify Ending index.
-
-**/
-VOID
-ProcessNotify (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN UINTN NotifyType,
- IN INTN InstallStartIndex,
- IN INTN InstallStopIndex,
- IN INTN NotifyStartIndex,
- IN INTN NotifyStopIndex
- );
-
-/**
- Process PpiList from SEC phase.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
- These PPI's will be installed and/or immediately signaled if they are notification type.
-
-**/
-VOID
-ProcessPpiListFromSec (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
- );
-
-//
-// Boot mode support functions
-//
-
-/**
- This service enables PEIMs to ascertain the present value of the boot mode.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param BootMode A pointer to contain the value of the boot mode.
-
- @retval EFI_SUCCESS The boot mode was returned successfully.
- @retval EFI_INVALID_PARAMETER BootMode is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiGetBootMode (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN OUT EFI_BOOT_MODE *BootMode
- );
-
-/**
- This service enables PEIMs to update the boot mode variable.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param BootMode The value of the boot mode to set.
-
- @return EFI_SUCCESS The value was successfully updated
-
-**/
-EFI_STATUS
-EFIAPI
-PeiSetBootMode (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_BOOT_MODE BootMode
- );
-
-//
-// Security support functions
-//
-
-/**
-
- Initialize the security services.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param OldCoreData Pointer to the old core data.
- NULL if being run in non-permanent memory mode.
-
-**/
-VOID
-InitializeSecurityServices (
- IN EFI_PEI_SERVICES **PeiServices,
- IN PEI_CORE_INSTANCE *OldCoreData
- );
-
-/**
- Verify a Firmware volume.
-
- @param CurrentFvAddress Pointer to the current Firmware Volume under consideration
-
- @retval EFI_SUCCESS Firmware Volume is legal
- @retval EFI_SECURITY_VIOLATION Firmware Volume fails integrity test
-
-**/
-EFI_STATUS
-VerifyFv (
- IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
- );
-
-/**
- Provide a callout to the security verification service.
-
- @param PrivateData PeiCore's private data structure
- @param VolumeHandle Handle of FV
- @param FileHandle Handle of PEIM's FFS
- @param AuthenticationStatus Authentication status
-
- @retval EFI_SUCCESS Image is OK
- @retval EFI_SECURITY_VIOLATION Image is illegal
- @retval EFI_NOT_FOUND If security PPI is not installed.
-**/
-EFI_STATUS
-VerifyPeim (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_PEI_FV_HANDLE VolumeHandle,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINT32 AuthenticationStatus
- );
-
-/**
-
- Gets the pointer to the HOB List.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param HobList Pointer to the HOB List.
-
- @retval EFI_SUCCESS Get the pointer of HOB List
- @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published
- @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode)
-
-**/
-EFI_STATUS
-EFIAPI
-PeiGetHobList (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN OUT VOID **HobList
- );
-
-/**
- Add a new HOB to the HOB List.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param Type Type of the new HOB.
- @param Length Length of the new HOB to allocate.
- @param Hob Pointer to the new HOB.
-
- @return EFI_SUCCESS Success to create HOB.
- @retval EFI_INVALID_PARAMETER if Hob is NULL
- @retval EFI_NOT_AVAILABLE_YET if HobList is still not available.
- @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiCreateHob (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINT16 Type,
- IN UINT16 Length,
- IN OUT VOID **Hob
- );
-
-/**
-
- Builds a Handoff Information Table HOB
-
- @param BootMode - Current Bootmode
- @param MemoryBegin - Start Memory Address.
- @param MemoryLength - Length of Memory.
-
- @return EFI_SUCCESS Always success to initialize HOB.
-
-**/
-EFI_STATUS
-PeiCoreBuildHobHandoffInfoTable (
- IN EFI_BOOT_MODE BootMode,
- IN EFI_PHYSICAL_ADDRESS MemoryBegin,
- IN UINT64 MemoryLength
- );
-
-/**
- Install SEC HOB data to the HOB List.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SecHobList Pointer to SEC HOB List.
-
- @return EFI_SUCCESS Success to install SEC HOB data.
- @retval EFI_OUT_OF_RESOURCES If there is no more memory to grow the Hoblist.
-
-**/
-EFI_STATUS
-PeiInstallSecHobData (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_HOB_GENERIC_HEADER *SecHobList
- );
-
-//
-// FFS Fw Volume support functions
-//
-
-/**
- Searches for the next matching file in the firmware volume.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SearchType Filter to find only files of this type.
- Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
- @param FvHandle Handle of firmware volume in which to search.
- @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start
- at the beginning of the firmware volume. On exit, points the file handle of the next file
- in the volume or NULL if there are no more files.
-
- @retval EFI_NOT_FOUND The file was not found.
- @retval EFI_NOT_FOUND The header checksum was not zero.
- @retval EFI_SUCCESS The file was found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindNextFile (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINT8 SearchType,
- IN EFI_PEI_FV_HANDLE FvHandle,
- IN OUT EFI_PEI_FILE_HANDLE *FileHandle
- );
-
-/**
- Go through the file to search SectionType section.
- Search within encapsulation sections (compression and GUIDed) recursively,
- until the match section is found.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SectionType Filter to find only section of this type.
- @param SectionInstance Pointer to the filter to find the specific instance of section.
- @param Section From where to search.
- @param SectionSize The file size to search.
- @param OutputBuffer A pointer to the discovered section, if successful.
- NULL if section not found.
- @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
- @param IsFfs3Fv Indicates the FV format.
-
- @return EFI_NOT_FOUND The match section is not found.
- @return EFI_SUCCESS The match section is found.
-
-**/
-EFI_STATUS
-ProcessSection (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_SECTION_TYPE SectionType,
- IN OUT UINTN *SectionInstance,
- IN EFI_COMMON_SECTION_HEADER *Section,
- IN UINTN SectionSize,
- OUT VOID **OutputBuffer,
- OUT UINT32 *AuthenticationStatus,
- IN BOOLEAN IsFfs3Fv
- );
-
-/**
- Searches for the next matching section within the specified file.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param SectionType Filter to find only sections of this type.
- @param FileHandle Pointer to the current file to search.
- @param SectionData A pointer to the discovered section, if successful.
- NULL if section not found
-
- @retval EFI_NOT_FOUND The section was not found.
- @retval EFI_SUCCESS The section was found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindSectionData (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_SECTION_TYPE SectionType,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData
- );
-
-/**
- Searches for the next matching section within the specified file.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param SectionType The value of the section type to find.
- @param SectionInstance Section instance to find.
- @param FileHandle Handle of the firmware file to search.
- @param SectionData A pointer to the discovered section, if successful.
- @param AuthenticationStatus A pointer to the authentication status for this section.
-
- @retval EFI_SUCCESS The section was found.
- @retval EFI_NOT_FOUND The section was not found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindSectionData3 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_SECTION_TYPE SectionType,
- IN UINTN SectionInstance,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **SectionData,
- OUT UINT32 *AuthenticationStatus
- );
-
-/**
- Search the firmware volumes by index
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
- @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware
- Volume (BFV).
- @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.
-
- @retval EFI_INVALID_PARAMETER VolumeHandle is NULL
- @retval EFI_NOT_FOUND The volume was not found.
- @retval EFI_SUCCESS The volume was found.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindNextVolume (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINTN Instance,
- IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
- );
-
-//
-// Memory support functions
-//
-
-/**
-
- Initialize the memory services.
-
- @param PrivateData PeiCore's private data structure
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param OldCoreData Pointer to the PEI Core data.
- NULL if being run in non-permanent memory mode.
-
-**/
-VOID
-InitializeMemoryServices (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *OldCoreData
- );
-
-/**
-
- Install the permanent memory is now available.
- Creates HOB (PHIT and Stack).
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param MemoryBegin Start of memory address.
- @param MemoryLength Length of memory.
-
- @return EFI_SUCCESS Always success.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiInstallPeiMemory (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS MemoryBegin,
- IN UINT64 MemoryLength
- );
-
-/**
- Migrate memory pages allocated in pre-memory phase.
- Copy memory pages at temporary heap top to permanent heap top.
-
- @param[in] Private Pointer to the private data passed in from caller.
- @param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory.
-
-**/
-VOID
-MigrateMemoryPages (
- IN PEI_CORE_INSTANCE *Private,
- IN BOOLEAN TemporaryRamMigrated
- );
-
-/**
- Migrate the base address in firmware volume allocation HOBs
- from temporary memory to PEI installed memory.
-
- @param[in] PrivateData Pointer to PeiCore's private data structure.
- @param[in] OrgFvHandle Address of FV Handle in temporary memory.
- @param[in] FvHandle Address of FV Handle in permanent memory.
-
-**/
-VOID
-ConvertFvHob (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN UINTN OrgFvHandle,
- IN UINTN FvHandle
- );
-
-/**
- Migrate MemoryBaseAddress in memory allocation HOBs
- from the temporary memory to PEI installed memory.
-
- @param[in] PrivateData Pointer to PeiCore's private data structure.
-
-**/
-VOID
-ConvertMemoryAllocationHobs (
- IN PEI_CORE_INSTANCE *PrivateData
- );
-
-/**
- The purpose of the service is to publish an interface that allows
- PEIMs to allocate memory ranges that are managed by the PEI Foundation.
-
- Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap.
- After InstallPeiMemory() is called, PEI will allocate pages within the region
- of memory provided by InstallPeiMemory() service in a best-effort fashion.
- Location-specific allocations are not managed by the PEI foundation code.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param MemoryType The type of memory to allocate.
- @param Pages The number of contiguous 4 KB pages to allocate.
- @param Memory Pointer to a physical address. On output, the address is set to the base
- of the page range that was allocated.
-
- @retval EFI_SUCCESS The memory range was successfully allocated.
- @retval EFI_OUT_OF_RESOURCES The pages could not be allocated.
- @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode,
- EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData,
- EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiAllocatePages (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_MEMORY_TYPE MemoryType,
- IN UINTN Pages,
- OUT EFI_PHYSICAL_ADDRESS *Memory
- );
-
-/**
- Frees memory pages.
-
- @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param[in] Memory The base physical address of the pages to be freed.
- @param[in] Pages The number of contiguous 4 KB pages to free.
-
- @retval EFI_SUCCESS The requested pages were freed.
- @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid.
- @retval EFI_NOT_FOUND The requested memory pages were not allocated with
- AllocatePages().
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFreePages (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS Memory,
- IN UINTN Pages
- );
-
-/**
-
- Memory allocation service on the temporary memory.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param Size Amount of memory required
- @param Buffer Address of pointer to the buffer
-
- @retval EFI_SUCCESS The allocation was successful
- @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement
- to allocate the requested size.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiAllocatePool (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN UINTN Size,
- OUT VOID **Buffer
- );
-
-/**
-
- Routine for load image file.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param FileHandle Pointer to the FFS file header of the image.
- @param PeimState The dispatch state of the input PEIM handle.
- @param EntryPoint Pointer to entry point of specified image file for output.
- @param AuthenticationState Pointer to attestation authentication state of image.
-
- @retval EFI_SUCCESS Image is successfully loaded.
- @retval EFI_NOT_FOUND Fail to locate necessary PPI
- @retval Others Fail to load file.
-
-**/
-EFI_STATUS
-PeiLoadImage (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINT8 PeimState,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
- OUT UINT32 *AuthenticationState
- );
-
-/**
-
- Core version of the Status Code reporter
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param CodeType Type of Status Code.
- @param Value Value to output for Status Code.
- @param Instance Instance Number of this status code.
- @param CallerId ID of the caller of this status code.
- @param Data Optional data associated with this status code.
-
- @retval EFI_SUCCESS if status code is successfully reported
- @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed
-
-**/
-EFI_STATUS
-EFIAPI
-PeiReportStatusCode (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_STATUS_CODE_TYPE CodeType,
- IN EFI_STATUS_CODE_VALUE Value,
- IN UINT32 Instance,
- IN CONST EFI_GUID *CallerId,
- IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
- );
-
-/**
-
- Core version of the Reset System
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
-
- @retval EFI_NOT_AVAILABLE_YET PPI not available yet.
- @retval EFI_DEVICE_ERROR Did not reset system.
- Otherwise, resets the system.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiResetSystem (
- IN CONST EFI_PEI_SERVICES **PeiServices
- );
-
-/**
- Resets the entire platform.
-
- @param[in] ResetType The type of reset to perform.
- @param[in] ResetStatus The status code for the reset.
- @param[in] DataSize The size, in bytes, of ResetData.
- @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown
- the data buffer starts with a Null-terminated string, optionally
- followed by additional binary data. The string is a description
- that the caller may use to further indicate the reason for the
- system reset.
-
-**/
-VOID
-EFIAPI
-PeiResetSystem2 (
- IN EFI_RESET_TYPE ResetType,
- IN EFI_STATUS ResetStatus,
- IN UINTN DataSize,
- IN VOID *ResetData OPTIONAL
- );
-
-/**
-
- Initialize PeiCore FV List.
-
-
- @param PrivateData - Pointer to PEI_CORE_INSTANCE.
- @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
-
-**/
-VOID
-PeiInitializeFv (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
- );
-
-/**
- Process Firmware Volume Information once FvInfoPPI install.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
-
- @retval EFI_SUCCESS if the interface could be successfully installed
-
-**/
-EFI_STATUS
-EFIAPI
-FirmwareVolumeInfoPpiNotifyCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- );
-
-/**
-
- Given the input VolumeHandle, search for the next matching name file.
-
- @param FileName File name to search.
- @param VolumeHandle The current FV to search.
- @param FileHandle Pointer to the file matching name in VolumeHandle.
- NULL if file not found
-
- @retval EFI_NOT_FOUND No files matching the search criteria were found
- @retval EFI_SUCCESS Success to search given file
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsFindFileByName (
- IN CONST EFI_GUID *FileName,
- IN EFI_PEI_FV_HANDLE VolumeHandle,
- OUT EFI_PEI_FILE_HANDLE *FileHandle
- );
-
-/**
- Returns information about a specific file.
-
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's information.
-
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
- @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
- @retval EFI_SUCCESS File information returned.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsGetFileInfo (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO *FileInfo
- );
-
-/**
- Returns information about a specific file.
-
- @param FileHandle Handle of the file.
- @param FileInfo Upon exit, points to the file's information.
-
- @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
- @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
- @retval EFI_SUCCESS File information returned.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsGetFileInfo2 (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_FV_FILE_INFO2 *FileInfo
- );
-
-/**
- Returns information about the specified volume.
-
- @param VolumeHandle Handle of the volume.
- @param VolumeInfo Upon exit, points to the volume's information.
-
- @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.
- @retval EFI_INVALID_PARAMETER If VolumeInfo is NULL.
- @retval EFI_SUCCESS Volume information returned.
-**/
-EFI_STATUS
-EFIAPI
-PeiFfsGetVolumeInfo (
- IN EFI_PEI_FV_HANDLE VolumeHandle,
- OUT EFI_FV_INFO *VolumeInfo
- );
-
-/**
- This routine enables a PEIM to register itself for shadow when the PEI Foundation
- discovers permanent memory.
-
- @param FileHandle File handle of a PEIM.
-
- @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.
- @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.
- @retval EFI_SUCCESS Successfully to register itself.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiRegisterForShadow (
- IN EFI_PEI_FILE_HANDLE FileHandle
- );
-
-/**
- Initialize image service that install PeiLoadFilePpi.
-
- @param PrivateData Pointer to PeiCore's private data structure PEI_CORE_INSTANCE.
- @param OldCoreData Pointer to Old PeiCore's private data.
- If NULL, PeiCore is entered at first time, stack/heap in temporary memory.
- If not NULL, PeiCore is entered at second time, stack/heap has been moved
- to permanent memory.
-
-**/
-VOID
-InitializeImageServices (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_INSTANCE *OldCoreData
- );
-
-/**
- Loads and relocates a PE/COFF image in place.
-
- @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
- @param ImageAddress The base address of the relocated PE/COFF image
-
- @retval EFI_SUCCESS The file was loaded and relocated
- @retval Others The file not be loaded and error occurred.
-
-**/
-EFI_STATUS
-LoadAndRelocatePeCoffImageInPlace (
- IN VOID *Pe32Data,
- IN VOID *ImageAddress
- );
-
-/**
- Find the PE32 Data for an FFS file.
-
- @param FileHandle Pointer to the FFS file header of the image.
- @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
-
- @retval EFI_SUCCESS Image is successfully loaded.
- @retval EFI_NOT_FOUND Fail to locate PE32 Data.
-
-**/
-EFI_STATUS
-PeiGetPe32Data (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT VOID **Pe32Data
- );
-
-/**
- The wrapper function of PeiLoadImageLoadImage().
-
- @param This Pointer to EFI_PEI_LOAD_FILE_PPI.
- @param FileHandle Pointer to the FFS file header of the image.
- @param ImageAddressArg Pointer to PE/TE image.
- @param ImageSizeArg Size of PE/TE image.
- @param EntryPoint Pointer to entry point of specified image file for output.
- @param AuthenticationState Pointer to attestation authentication state of image.
-
- @return Status of PeiLoadImageLoadImage().
-
-**/
-EFI_STATUS
-EFIAPI
-PeiLoadImageLoadImageWrapper (
- IN CONST EFI_PEI_LOAD_FILE_PPI *This,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,
- OUT UINT64 *ImageSizeArg OPTIONAL,
- OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
- OUT UINT32 *AuthenticationState
- );
-
-/**
-
- Provide a callback for when the security PPI is installed.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param NotifyDescriptor The descriptor for the notification event.
- @param Ppi Pointer to the PPI in question.
-
- @return Always success
-
-**/
-EFI_STATUS
-EFIAPI
-SecurityPpiNotifyCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- );
-
-/**
- Get FV image(s) from the FV type file, then install FV INFO(2) PPI, Build FV(2, 3) HOB.
-
- @param PrivateData PeiCore's private data structure
- @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent FV image that contain this FV image.
- @param ParentFvFileHandle File handle of a FV type file that contain this FV image.
-
- @retval EFI_NOT_FOUND FV image can't be found.
- @retval EFI_SUCCESS Successfully to process it.
- @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
- @retval EFI_SECURITY_VIOLATION Image is illegal
- @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
-
-**/
-EFI_STATUS
-ProcessFvFile (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle,
- IN EFI_PEI_FILE_HANDLE ParentFvFileHandle
- );
-
-/**
- Gets a PEI_CORE_FV_HANDLE instance for the next volume according to the given index.
-
- This routine also will install an instance of the FvInfo PPI for the FV HOB
- as defined in the PI specification.
-
- @param Private Pointer of PEI_CORE_INSTANCE
- @param Instance Index of the FV to search
-
- @return Instance of PEI_CORE_FV_HANDLE.
-**/
-PEI_CORE_FV_HANDLE *
-FindNextCoreFvHandle (
- IN PEI_CORE_INSTANCE *Private,
- IN UINTN Instance
- );
-
-//
-// Default EFI_PEI_CPU_IO_PPI support for EFI_PEI_SERVICES table when PeiCore initialization.
-//
-
-/**
- Memory-based read services.
-
- This function is to perform the Memory Access Read service based on installed
- instance of the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultMemRead (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-/**
- Memory-based write services.
-
- This function is to perform the Memory Access Write service based on installed
- instance of the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultMemWrite (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-/**
- IO-based read services.
-
- This function is to perform the IO-base read service for the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultIoRead (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-/**
- IO-based write services.
-
- This function is to perform the IO-base write service for the EFI_PEI_CPU_IO_PPI.
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- @param Address The physical address of the access.
- @param Count The number of accesses to perform.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_NOT_YET_AVAILABLE The service has not been installed.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultIoWrite (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN OUT VOID *Buffer
- );
-
-/**
- 8-bit I/O read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 8-bit value returned from the I/O space.
-**/
-UINT8
-EFIAPI
-PeiDefaultIoRead8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- Reads an 16-bit I/O port.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return A 16-bit value returned from the I/O space.
-**/
-UINT16
-EFIAPI
-PeiDefaultIoRead16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- Reads an 32-bit I/O port.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return A 32-bit value returned from the I/O space.
-**/
-UINT32
-EFIAPI
-PeiDefaultIoRead32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- Reads an 64-bit I/O port.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return A 64-bit value returned from the I/O space.
-**/
-UINT64
-EFIAPI
-PeiDefaultIoRead64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- 8-bit I/O write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT8 Data
- );
-
-/**
- 16-bit I/O write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT16 Data
- );
-
-/**
- 32-bit I/O write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT32 Data
- );
-
-/**
- 64-bit I/O write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-**/
-VOID
-EFIAPI
-PeiDefaultIoWrite64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT64 Data
- );
-
-/**
- 8-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 8-bit value returned from the memory space.
-
-**/
-UINT8
-EFIAPI
-PeiDefaultMemRead8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- 16-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 16-bit value returned from the memory space.
-
-**/
-UINT16
-EFIAPI
-PeiDefaultMemRead16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- 32-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 32-bit value returned from the memory space.
-
-**/
-UINT32
-EFIAPI
-PeiDefaultMemRead32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- 64-bit memory read operations.
-
- If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then
- return 0.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
-
- @return An 64-bit value returned from the memory space.
-
-**/
-UINT64
-EFIAPI
-PeiDefaultMemRead64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address
- );
-
-/**
- 8-bit memory write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite8 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT8 Data
- );
-
-/**
- 16-bit memory write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite16 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT16 Data
- );
-
-/**
- 32-bit memory write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite32 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT32 Data
- );
-
-/**
- 64-bit memory write operations.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Address The physical address of the access.
- @param Data The data to write.
-
-**/
-VOID
-EFIAPI
-PeiDefaultMemWrite64 (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_CPU_IO_PPI *This,
- IN UINT64 Address,
- IN UINT64 Data
- );
-
-extern EFI_PEI_CPU_IO_PPI gPeiDefaultCpuIoPpi;
-
-//
-// Default EFI_PEI_PCI_CFG2_PPI support for EFI_PEI_SERVICES table when PeiCore initialization.
-//
-
-/**
- Reads from a given location in the PCI configuration space.
-
- If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- See EFI_PEI_PCI_CFG_PPI_WIDTH above.
- @param Address The physical address of the access. The format of
- the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER The invalid access width.
- @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultPciCfg2Read (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PCI_CFG2_PPI *This,
- IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
- IN UINT64 Address,
- IN OUT VOID *Buffer
- );
-
-/**
- Write to a given location in the PCI configuration space.
-
- If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then
- return EFI_NOT_YET_AVAILABLE.
-
- @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes.
- See EFI_PEI_PCI_CFG_PPI_WIDTH above.
- @param Address The physical address of the access. The format of
- the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
- @param Buffer A pointer to the buffer of data.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER The invalid access width.
- @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultPciCfg2Write (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PCI_CFG2_PPI *This,
- IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
- IN UINT64 Address,
- IN OUT VOID *Buffer
- );
-
-/**
- This function performs a read-modify-write operation on the contents from a given
- location in the PCI configuration space.
-
- @param PeiServices An indirect pointer to the PEI Services Table
- published by the PEI Foundation.
- @param This Pointer to local data for the interface.
- @param Width The width of the access. Enumerated in bytes. Type
- EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
- @param Address The physical address of the access.
- @param SetBits Points to value to bitwise-OR with the read configuration value.
- The size of the value is determined by Width.
- @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.
- The size of the value is determined by Width.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER The invalid access width.
- @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM.
-**/
-EFI_STATUS
-EFIAPI
-PeiDefaultPciCfg2Modify (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PCI_CFG2_PPI *This,
- IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,
- IN UINT64 Address,
- IN VOID *SetBits,
- IN VOID *ClearBits
- );
-
-extern EFI_PEI_PCI_CFG2_PPI gPeiDefaultPciCfg2Ppi;
-
-/**
- After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
- be re-installed with the instance in permanent memory and all cached FvPpi pointers in
- PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent
- memory.
-
- @param PrivateData Pointer to PEI_CORE_INSTANCE.
-**/
-VOID
-PeiReinitializeFv (
- IN PEI_CORE_INSTANCE *PrivateData
- );
-
-#endif
+/** @file + Definition of Pei Core Structures and Services + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PEI_MAIN_H_ +#define _PEI_MAIN_H_ + +#include <PiPei.h> +#include <Ppi/DxeIpl.h> +#include <Ppi/MemoryDiscovered.h> +#include <Ppi/StatusCode.h> +#include <Ppi/Reset.h> +#include <Ppi/Reset2.h> +#include <Ppi/FirmwareVolume.h> +#include <Ppi/FirmwareVolumeInfo.h> +#include <Ppi/FirmwareVolumeInfo2.h> +#include <Ppi/Decompress.h> +#include <Ppi/GuidedSectionExtraction.h> +#include <Ppi/LoadFile.h> +#include <Ppi/Security2.h> +#include <Ppi/TemporaryRamSupport.h> +#include <Ppi/TemporaryRamDone.h> +#include <Ppi/SecHobData.h> +#include <Ppi/PeiCoreFvLocation.h> +#include <Library/DebugLib.h> +#include <Library/PeiCoreEntryPoint.h> +#include <Library/BaseLib.h> +#include <Library/HobLib.h> +#include <Library/PerformanceLib.h> +#include <Library/PeiServicesLib.h> +#include <Library/ReportStatusCodeLib.h> +#include <Library/PeCoffLib.h> +#include <Library/PeCoffGetEntryPointLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/PcdLib.h> +#include <IndustryStandard/PeImage.h> +#include <Library/PeiServicesTablePointerLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Guid/FirmwareFileSystem2.h> +#include <Guid/FirmwareFileSystem3.h> +#include <Guid/AprioriFileName.h> +#include <Guid/MigratedFvInfo.h> + +/// +/// It is an FFS type extension used for PeiFindFileEx. It indicates current +/// FFS searching is for all PEIMs can be dispatched by PeiCore. +/// +#define PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE 0xff + +/// +/// Pei Core private data structures +/// +typedef union { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + +/// +/// Number of PEI_PPI_LIST_POINTERS to grow by each time we run out of room +/// +#define PPI_GROWTH_STEP 64 +#define CALLBACK_NOTIFY_GROWTH_STEP 32 +#define DISPATCH_NOTIFY_GROWTH_STEP 8 + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + UINTN LastDispatchedCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS *PpiPtrs; +} PEI_PPI_LIST; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS *NotifyPtrs; +} PEI_CALLBACK_NOTIFY_LIST; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + UINTN LastDispatchedCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS *NotifyPtrs; +} PEI_DISPATCH_NOTIFY_LIST; + +/// +/// PPI database structure which contains three links: +/// PpiList, CallbackNotifyList and DispatchNotifyList. +/// +typedef struct { + /// + /// PPI List. + /// + PEI_PPI_LIST PpiList; + /// + /// Notify List at dispatch level. + /// + PEI_CALLBACK_NOTIFY_LIST CallbackNotifyList; + /// + /// Notify List at callback level. + /// + PEI_DISPATCH_NOTIFY_LIST DispatchNotifyList; +} PEI_PPI_DATABASE; + +// +// PEI_CORE_FV_HANDLE.PeimState +// Do not change these values as there is code doing math to change states. +// Look for Private->Fv[FvCount].PeimState[PeimCount]++; +// +#define PEIM_STATE_NOT_DISPATCHED 0x00 +#define PEIM_STATE_DISPATCHED 0x01 +#define PEIM_STATE_REGISTER_FOR_SHADOW 0x02 +#define PEIM_STATE_DONE 0x03 + +// +// Number of FV instances to grow by each time we run out of room +// +#define FV_GROWTH_STEP 8 + +typedef struct { + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + EFI_PEI_FV_HANDLE FvHandle; + UINTN PeimCount; + // + // Pointer to the buffer with the PeimCount number of Entries. + // + UINT8 *PeimState; + // + // Pointer to the buffer with the PeimCount number of Entries. + // + EFI_PEI_FILE_HANDLE *FvFileHandles; + BOOLEAN ScanFv; + UINT32 AuthenticationStatus; +} PEI_CORE_FV_HANDLE; + +typedef struct { + EFI_GUID FvFormat; + VOID *FvInfo; + UINT32 FvInfoSize; + UINT32 AuthenticationStatus; + EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor; +} PEI_CORE_UNKNOW_FORMAT_FV_INFO; + +#define CACHE_SETION_MAX_NUMBER 0x10 +typedef struct { + EFI_COMMON_SECTION_HEADER *Section[CACHE_SETION_MAX_NUMBER]; + VOID *SectionData[CACHE_SETION_MAX_NUMBER]; + UINTN SectionSize[CACHE_SETION_MAX_NUMBER]; + UINT32 AuthenticationStatus[CACHE_SETION_MAX_NUMBER]; + UINTN AllSectionCount; + UINTN SectionIndex; +} CACHE_SECTION_DATA; + +#define HOLE_MAX_NUMBER 0x3 +typedef struct { + EFI_PHYSICAL_ADDRESS Base; + UINTN Size; + UINTN Offset; + BOOLEAN OffsetPositive; +} HOLE_MEMORY_DATA; + +/// +/// Forward declaration for PEI_CORE_INSTANCE +/// +typedef struct _PEI_CORE_INSTANCE PEI_CORE_INSTANCE; + +/** + Function Pointer type for PeiCore function. + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + An empty PPI list consists of a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization + phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such + that both the PEI Foundation and any modules can leverage the associated service + calls and/or code in these early PPIs + @param OldCoreData Pointer to old core data that is used to initialize the + core's data areas. +**/ +typedef +EFI_STATUS +(EFIAPI *PEICORE_FUNCTION_POINTER)( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Number of files to grow by each time we run out of room +// +#define TEMP_FILE_GROWTH_STEP 32 + +#define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C') + +/// +/// Pei Core private data structure instance +/// +struct _PEI_CORE_INSTANCE { + UINTN Signature; + + /// + /// Point to ServiceTableShadow + /// + EFI_PEI_SERVICES *Ps; + PEI_PPI_DATABASE PpiData; + + /// + /// The count of FVs which contains FFS and could be dispatched by PeiCore. + /// + UINTN FvCount; + + /// + /// The max count of FVs which contains FFS and could be dispatched by PeiCore. + /// + UINTN MaxFvCount; + + /// + /// Pointer to the buffer with the MaxFvCount number of entries. + /// Each entry is for one FV which contains FFS and could be dispatched by PeiCore. + /// + PEI_CORE_FV_HANDLE *Fv; + + /// + /// Pointer to the buffer with the MaxUnknownFvInfoCount number of entries. + /// Each entry is for one FV which could not be dispatched by PeiCore. + /// + PEI_CORE_UNKNOW_FORMAT_FV_INFO *UnknownFvInfo; + UINTN MaxUnknownFvInfoCount; + UINTN UnknownFvInfoCount; + + /// + /// Pointer to the buffer FvFileHandlers in PEI_CORE_FV_HANDLE specified by CurrentPeimFvCount. + /// + EFI_PEI_FILE_HANDLE *CurrentFvFileHandles; + UINTN AprioriCount; + UINTN CurrentPeimFvCount; + UINTN CurrentPeimCount; + EFI_PEI_FILE_HANDLE CurrentFileHandle; + BOOLEAN PeimNeedingDispatch; + BOOLEAN PeimDispatchOnThisPass; + BOOLEAN PeimDispatcherReenter; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + VOID *CpuIo; + EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; + EFI_PEI_PPI_DESCRIPTOR *XipLoadFile; + EFI_PHYSICAL_ADDRESS PhysicalMemoryBegin; + UINT64 PhysicalMemoryLength; + EFI_PHYSICAL_ADDRESS FreePhysicalMemoryTop; + UINTN HeapOffset; + BOOLEAN HeapOffsetPositive; + UINTN StackOffset; + BOOLEAN StackOffsetPositive; + // + // Information for migrating memory pages allocated in pre-memory phase. + // + HOLE_MEMORY_DATA MemoryPages; + PEICORE_FUNCTION_POINTER ShadowedPeiCore; + CACHE_SECTION_DATA CacheSection; + // + // For Loading modules at fixed address feature to cache the top address below which the + // Runtime code, boot time code and PEI memory will be placed. Please note that the offset between this field + // and Ps should not be changed since maybe user could get this top address by using the offset to Ps. + // + EFI_PHYSICAL_ADDRESS LoadModuleAtFixAddressTopAddress; + // + // The field is define for Loading modules at fixed address feature to tracker the PEI code + // memory range usage. It is a bit mapped array in which every bit indicates the corresponding memory page + // available or not. + // + UINT64 *PeiCodeMemoryRangeUsageBitMap; + // + // This field points to the shadowed image read function + // + PE_COFF_LOADER_READ_FILE ShadowedImageRead; + + UINTN TempPeimCount; + + // + // Pointer to the temp buffer with the TempPeimCount number of entries. + // + EFI_PEI_FILE_HANDLE *TempFileHandles; + // + // Pointer to the temp buffer with the TempPeimCount number of entries. + // + EFI_GUID *TempFileGuid; + + // + // Temp Memory Range is not covered by PeiTempMem and Stack. + // Those Memory Range will be migrated into physical memory. + // + HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER]; +}; + +/// +/// Pei Core Instance Data Macros +/// +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + CR(a, PEI_CORE_INSTANCE, Ps, PEI_CORE_HANDLE_SIGNATURE) + +/// +/// Union of temporarily used function pointers (to save stack space) +/// +typedef union { + PEICORE_FUNCTION_POINTER PeiCore; + EFI_PEIM_ENTRY_POINT2 PeimEntry; + EFI_PEIM_NOTIFY_ENTRY_POINT PeimNotifyEntry; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + VOID *Raw; +} PEI_CORE_TEMP_POINTERS; + +typedef struct { + CONST EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_PEI_PPI_DESCRIPTOR *PpiList; + VOID *Data; +} PEI_CORE_PARAMETERS; + +// +// PeiCore function +// + +/** + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + An empty PPI list consists of a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization + phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such + that both the PEI Foundation and any modules can leverage the associated service + calls and/or code in these early PPIs + @param Data Pointer to old core data that is used to initialize the + core's data areas. + +**/ +VOID +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Data + ); + +// +// Dispatcher support functions +// + +/** + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is popped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + + @retval TRUE if it is a well-formed Grammar + @retval FALSE if the dependency expression overflows the evaluation stack + if the dependency expression underflows the evaluation stack + if the dependency expression is not a well-formed Grammar. + +**/ +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ); + +/** + Migrate a PEIM from temporary RAM to permanent memory. + + @param PeimFileHandle Pointer to the FFS file header of the image. + @param MigratedFileHandle Pointer to the FFS file header of the migrated image. + + @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory. + +**/ +EFI_STATUS +EFIAPI +MigratePeim ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN EFI_PEI_FILE_HANDLE MigratedFileHandle + ); + +/** + Migrate FVs out of temporary RAM before the cache is flushed. + + @param Private PeiCore's private data structure + @param SecCoreData Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + + @retval EFI_SUCCESS Successfully migrated installed FVs from temporary RAM to permanent memory. + @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages. + +**/ +EFI_STATUS +EFIAPI +EvacuateTempRam ( + IN PEI_CORE_INSTANCE *Private, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ); + +/** + Conduct PEIM dispatch. + + @param SecCoreData Pointer to the data structure containing SEC to PEI handoff data + @param PrivateData Pointer to the private data passed in from caller + +**/ +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + Initialize the Dispatcher's data members + + @param PrivateData PeiCore's private data structure + @param OldCoreData Old data from SecCore + NULL if being run in non-permanent memory mode. + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + +**/ +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ); + +/** + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + + + @param Private PeiCore's private data structure + @param FileHandle PEIM's file handle + @param PeimCount The index of last dispatched PEIM. + + @retval TRUE Can be dispatched + @retval FALSE Cannot be dispatched + +**/ +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ); + +// +// PPI support functions +// + +/** + + Initialize PPI services. + + @param PrivateData Pointer to the PEI Core data. + @param OldCoreData Pointer to old PEI Core data. + NULL if being run in non-permanent memory mode. + +**/ +VOID +InitializePpiServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + + Migrate the Hob list from the temporary memory to PEI installed memory. + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PrivateData Pointer to PeiCore's private data structure. + +**/ +VOID +ConvertPpiPointers ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + + Migrate Notify Pointers inside an FV from temporary memory to permanent memory. + + @param PrivateData Pointer to PeiCore's private data structure. + @param OrgFvHandle Address of FV Handle in temporary memory. + @param FvHandle Address of FV Handle in permanent memory. + @param FvSize Size of the FV. + +**/ +VOID +ConvertPpiPointersFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN OrgFvHandle, + IN UINTN FvHandle, + IN UINTN FvSize + ); + +/** + + Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory. + + @param PrivateData Pointer to PeiCore's private data structure. + @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory. + +**/ +VOID +ConvertPeiCorePpiPointers ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_FV_HANDLE *CoreFvHandle + ); + +/** + + Dumps the PPI lists to debug output. + + @param PrivateData Points to PeiCore's private instance data. + +**/ +VOID +DumpPpiList ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + + Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to PPI array that want to be installed. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +/** + + Re-Install PPI services. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS if the operation was successful + @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL + if NewPpi is not valid + @retval EFI_NOT_FOUND if the PPI was not in the database + +**/ +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ); + +/** + + Locate a given named PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Guid Pointer to GUID of the PPI. + @param Instance Instance Number to discover. + @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + @param Ppi Pointer to reference the found PPI + + @retval EFI_SUCCESS if the PPI is in the database + @retval EFI_NOT_FOUND if the PPI is not in the database + +**/ +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ); + +/** + + Install a notification for a given PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ); + +/** + + Process the Notify List at dispatch level. + + @param PrivateData PeiCore's private data structure. + +**/ +VOID +ProcessDispatchNotifyList ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + + Process notifications. + + @param PrivateData PeiCore's private data structure + @param NotifyType Type of notify to fire. + @param InstallStartIndex Install Beginning index. + @param InstallStopIndex Install Ending index. + @param NotifyStartIndex Notify Beginning index. + @param NotifyStopIndex Notify Ending index. + +**/ +VOID +ProcessNotify ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ); + +/** + Process PpiList from SEC phase. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + These PPI's will be installed and/or immediately signaled if they are notification type. + +**/ +VOID +ProcessPpiListFromSec ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +// +// Boot mode support functions +// + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ); + +/** + This service enables PEIMs to update the boot mode variable. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode The value of the boot mode to set. + + @return EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +// +// Security support functions +// + +/** + + Initialize the security services. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldCoreData Pointer to the old core data. + NULL if being run in non-permanent memory mode. + +**/ +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + Verify a Firmware volume. + + @param CurrentFvAddress Pointer to the current Firmware Volume under consideration + + @retval EFI_SUCCESS Firmware Volume is legal + @retval EFI_SECURITY_VIOLATION Firmware Volume fails integrity test + +**/ +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ); + +/** + Provide a callout to the security verification service. + + @param PrivateData PeiCore's private data structure + @param VolumeHandle Handle of FV + @param FileHandle Handle of PEIM's FFS + @param AuthenticationStatus Authentication status + + @retval EFI_SUCCESS Image is OK + @retval EFI_SECURITY_VIOLATION Image is illegal + @retval EFI_NOT_FOUND If security PPI is not installed. +**/ +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINT32 AuthenticationStatus + ); + +/** + + Gets the pointer to the HOB List. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param HobList Pointer to the HOB List. + + @retval EFI_SUCCESS Get the pointer of HOB List + @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published + @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode) + +**/ +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ); + +/** + Add a new HOB to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + @param Hob Pointer to the new HOB. + + @return EFI_SUCCESS Success to create HOB. + @retval EFI_INVALID_PARAMETER if Hob is NULL + @retval EFI_NOT_AVAILABLE_YET if HobList is still not available. + @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ); + +/** + + Builds a Handoff Information Table HOB + + @param BootMode - Current Bootmode + @param MemoryBegin - Start Memory Address. + @param MemoryLength - Length of Memory. + + @return EFI_SUCCESS Always success to initialize HOB. + +**/ +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + Install SEC HOB data to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SecHobList Pointer to SEC HOB List. + + @return EFI_SUCCESS Success to install SEC HOB data. + @retval EFI_OUT_OF_RESOURCES If there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +PeiInstallSecHobData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_GENERIC_HEADER *SecHobList + ); + +// +// FFS Fw Volume support functions +// + +/** + Searches for the next matching file in the firmware volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FvHandle Handle of firmware volume in which to search. + @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start + at the beginning of the firmware volume. On exit, points the file handle of the next file + in the volume or NULL if there are no more files. + + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + @retval EFI_SUCCESS The file was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Go through the file to search SectionType section. + Search within encapsulation sections (compression and GUIDed) recursively, + until the match section is found. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType Filter to find only section of this type. + @param SectionInstance Pointer to the filter to find the specific instance of section. + @param Section From where to search. + @param SectionSize The file size to search. + @param OutputBuffer A pointer to the discovered section, if successful. + NULL if section not found. + @param AuthenticationStatus Updated upon return to point to the authentication status for this section. + @param IsFfs3Fv Indicates the FV format. + + @return EFI_NOT_FOUND The match section is not found. + @return EFI_SUCCESS The match section is found. + +**/ +EFI_STATUS +ProcessSection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN OUT UINTN *SectionInstance, + IN EFI_COMMON_SECTION_HEADER *Section, + IN UINTN SectionSize, + OUT VOID **OutputBuffer, + OUT UINT32 *AuthenticationStatus, + IN BOOLEAN IsFfs3Fv + ); + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param SectionType Filter to find only sections of this type. + @param FileHandle Pointer to the current file to search. + @param SectionData A pointer to the discovered section, if successful. + NULL if section not found + + @retval EFI_NOT_FOUND The section was not found. + @retval EFI_SUCCESS The section was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType The value of the section type to find. + @param SectionInstance Section instance to find. + @param FileHandle Handle of the firmware file to search. + @param SectionData A pointer to the discovered section, if successful. + @param AuthenticationStatus A pointer to the authentication status for this section. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindSectionData3 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ); + +/** + Search the firmware volumes by index + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware + Volume (BFV). + @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist. + + @retval EFI_INVALID_PARAMETER VolumeHandle is NULL + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_SUCCESS The volume was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ); + +// +// Memory support functions +// + +/** + + Initialize the memory services. + + @param PrivateData PeiCore's private data structure + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param OldCoreData Pointer to the PEI Core data. + NULL if being run in non-permanent memory mode. + +**/ +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryBegin Start of memory address. + @param MemoryLength Length of memory. + + @return EFI_SUCCESS Always success. + +**/ +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + Migrate memory pages allocated in pre-memory phase. + Copy memory pages at temporary heap top to permanent heap top. + + @param[in] Private Pointer to the private data passed in from caller. + @param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory. + +**/ +VOID +MigrateMemoryPages ( + IN PEI_CORE_INSTANCE *Private, + IN BOOLEAN TemporaryRamMigrated + ); + +/** + Migrate the base address in firmware volume allocation HOBs + from temporary memory to PEI installed memory. + + @param[in] PrivateData Pointer to PeiCore's private data structure. + @param[in] OrgFvHandle Address of FV Handle in temporary memory. + @param[in] FvHandle Address of FV Handle in permanent memory. + +**/ +VOID +ConvertFvHob ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN OrgFvHandle, + IN UINTN FvHandle + ); + +/** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. + + @param[in] PrivateData Pointer to PeiCore's private data structure. + +**/ +VOID +ConvertMemoryAllocationHobs ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap. + After InstallPeiMemory() is called, PEI will allocate pages within the region + of memory provided by InstallPeiMemory() service in a best-effort fashion. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + +**/ +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] Memory The base physical address of the pages to be freed. + @param[in] Pages The number of contiguous 4 KB pages to free. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +PeiFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +/** + + Memory allocation service on the temporary memory. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Size Amount of memory required + @param Buffer Address of pointer to the buffer + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + + Routine for load image file. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param FileHandle Pointer to the FFS file header of the image. + @param PeimState The dispatch state of the input PEIM handle. + @param EntryPoint Pointer to entry point of specified image file for output. + @param AuthenticationState Pointer to attestation authentication state of image. + + @retval EFI_SUCCESS Image is successfully loaded. + @retval EFI_NOT_FOUND Fail to locate necessary PPI + @retval Others Fail to load file. + +**/ +EFI_STATUS +PeiLoadImage ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINT8 PeimState, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ); + +/** + + Core version of the Status Code reporter + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Type of Status Code. + @param Value Value to output for Status Code. + @param Instance Instance Number of this status code. + @param CallerId ID of the caller of this status code. + @param Data Optional data associated with this status code. + + @retval EFI_SUCCESS if status code is successfully reported + @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +**/ +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + + Core version of the Reset System + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @retval EFI_NOT_AVAILABLE_YET PPI not available yet. + @retval EFI_DEVICE_ERROR Did not reset system. + Otherwise, resets the system. + +**/ +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + Resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. + +**/ +VOID +EFIAPI +PeiResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + + Initialize PeiCore FV List. + + + @param PrivateData - Pointer to PEI_CORE_INSTANCE. + @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +**/ +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ); + +/** + Process Firmware Volume Information once FvInfoPPI install. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS if the interface could be successfully installed + +**/ +EFI_STATUS +EFIAPI +FirmwareVolumeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + + Given the input VolumeHandle, search for the next matching name file. + + @param FileName File name to search. + @param VolumeHandle The current FV to search. + @param FileHandle Pointer to the file matching name in VolumeHandle. + NULL if file not found + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS Success to search given file + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo2 ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ); + +/** + Returns information about the specified volume. + + @param VolumeHandle Handle of the volume. + @param VolumeInfo Upon exit, points to the volume's information. + + @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume. + @retval EFI_INVALID_PARAMETER If VolumeInfo is NULL. + @retval EFI_SUCCESS Volume information returned. +**/ +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + +/** + This routine enables a PEIM to register itself for shadow when the PEI Foundation + discovers permanent memory. + + @param FileHandle File handle of a PEIM. + + @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself. + @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself. + @retval EFI_SUCCESS Successfully to register itself. + +**/ +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ); + +/** + Initialize image service that install PeiLoadFilePpi. + + @param PrivateData Pointer to PeiCore's private data structure PEI_CORE_INSTANCE. + @param OldCoreData Pointer to Old PeiCore's private data. + If NULL, PeiCore is entered at first time, stack/heap in temporary memory. + If not NULL, PeiCore is entered at second time, stack/heap has been moved + to permanent memory. + +**/ +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + Loads and relocates a PE/COFF image in place. + + @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated + @param ImageAddress The base address of the relocated PE/COFF image + + @retval EFI_SUCCESS The file was loaded and relocated + @retval Others The file not be loaded and error occurred. + +**/ +EFI_STATUS +LoadAndRelocatePeCoffImageInPlace ( + IN VOID *Pe32Data, + IN VOID *ImageAddress + ); + +/** + Find the PE32 Data for an FFS file. + + @param FileHandle Pointer to the FFS file header of the image. + @param Pe32Data Pointer to a (VOID *) PE32 Data pointer. + + @retval EFI_SUCCESS Image is successfully loaded. + @retval EFI_NOT_FOUND Fail to locate PE32 Data. + +**/ +EFI_STATUS +PeiGetPe32Data ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **Pe32Data + ); + +/** + The wrapper function of PeiLoadImageLoadImage(). + + @param This Pointer to EFI_PEI_LOAD_FILE_PPI. + @param FileHandle Pointer to the FFS file header of the image. + @param ImageAddressArg Pointer to PE/TE image. + @param ImageSizeArg Size of PE/TE image. + @param EntryPoint Pointer to entry point of specified image file for output. + @param AuthenticationState Pointer to attestation authentication state of image. + + @return Status of PeiLoadImageLoadImage(). + +**/ +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ); + +/** + + Provide a callback for when the security PPI is installed. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyDescriptor The descriptor for the notification event. + @param Ppi Pointer to the PPI in question. + + @return Always success + +**/ +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + Get FV image(s) from the FV type file, then install FV INFO(2) PPI, Build FV(2, 3) HOB. + + @param PrivateData PeiCore's private data structure + @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent FV image that contain this FV image. + @param ParentFvFileHandle File handle of a FV type file that contain this FV image. + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image + @retval EFI_SECURITY_VIOLATION Image is illegal + @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section + +**/ +EFI_STATUS +ProcessFvFile ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle, + IN EFI_PEI_FILE_HANDLE ParentFvFileHandle + ); + +/** + Gets a PEI_CORE_FV_HANDLE instance for the next volume according to the given index. + + This routine also will install an instance of the FvInfo PPI for the FV HOB + as defined in the PI specification. + + @param Private Pointer of PEI_CORE_INSTANCE + @param Instance Index of the FV to search + + @return Instance of PEI_CORE_FV_HANDLE. +**/ +PEI_CORE_FV_HANDLE * +FindNextCoreFvHandle ( + IN PEI_CORE_INSTANCE *Private, + IN UINTN Instance + ); + +// +// Default EFI_PEI_CPU_IO_PPI support for EFI_PEI_SERVICES table when PeiCore initialization. +// + +/** + Memory-based read services. + + This function is to perform the Memory Access Read service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + Memory-based write services. + + This function is to perform the Memory Access Write service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + IO-based read services. + + This function is to perform the IO-base read service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + IO-based write services. + + This function is to perform the IO-base write service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + 8-bit I/O read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the I/O space. +**/ +UINT8 +EFIAPI +PeiDefaultIoRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + Reads an 16-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 16-bit value returned from the I/O space. +**/ +UINT16 +EFIAPI +PeiDefaultIoRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + Reads an 32-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 32-bit value returned from the I/O space. +**/ +UINT32 +EFIAPI +PeiDefaultIoRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + Reads an 64-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 64-bit value returned from the I/O space. +**/ +UINT64 +EFIAPI +PeiDefaultIoRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +/** + 8-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the memory space. + +**/ +UINT8 +EFIAPI +PeiDefaultMemRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 16-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 16-bit value returned from the memory space. + +**/ +UINT16 +EFIAPI +PeiDefaultMemRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 32-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 32-bit value returned from the memory space. + +**/ +UINT32 +EFIAPI +PeiDefaultMemRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 64-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 64-bit value returned from the memory space. + +**/ +UINT64 +EFIAPI +PeiDefaultMemRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +extern EFI_PEI_CPU_IO_PPI gPeiDefaultCpuIoPpi; + +// +// Default EFI_PEI_PCI_CFG2_PPI support for EFI_PEI_SERVICES table when PeiCore initialization. +// + +/** + Reads from a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. + +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Read ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ); + +/** + Write to a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Write ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ); + +/** + This function performs a read-modify-write operation on the contents from a given + location in the PCI configuration space. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + @param Address The physical address of the access. + @param SetBits Points to value to bitwise-OR with the read configuration value. + The size of the value is determined by Width. + @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Modify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN VOID *SetBits, + IN VOID *ClearBits + ); + +extern EFI_PEI_PCI_CFG2_PPI gPeiDefaultPciCfg2Ppi; + +/** + After PeiCore image is shadowed into permanent memory, all build-in FvPpi should + be re-installed with the instance in permanent memory and all cached FvPpi pointers in + PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent + memory. + + @param PrivateData Pointer to PEI_CORE_INSTANCE. +**/ +VOID +PeiReinitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +#endif diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf index 893bdc0527..7d809570ad 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.inf +++ b/MdeModulePkg/Core/Pei/PeiMain.inf @@ -1,132 +1,132 @@ -## @file
-# PeiMain module is core module in PEI phase.
-#
-# It takes responsibilities of:
-# 1) Initialize memory, PPI, image services etc, to establish PEIM runtime environment.
-# 2) Dispatch PEIM from discovered FV.
-# 3) Handoff control to DxeIpl to load DXE core and enter DXE phase.
-#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = PeiCore
- MODULE_UNI_FILE = PeiCore.uni
- FILE_GUID = 52C05B14-0B98-496c-BC3B-04B50211D680
- MODULE_TYPE = PEI_CORE
- VERSION_STRING = 1.0
- ENTRY_POINT = PeiCore
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only)
-#
-
-[Sources]
- StatusCode/StatusCode.c
- Security/Security.c
- Reset/Reset.c
- Ppi/Ppi.c
- PeiMain/PeiMain.c
- Memory/MemoryServices.c
- Image/Image.c
- Hob/Hob.c
- FwVol/FwVol.c
- FwVol/FwVol.h
- Dispatcher/Dispatcher.c
- Dependency/Dependency.c
- Dependency/Dependency.h
- BootMode/BootMode.c
- CpuIo/CpuIo.c
- PciCfg2/PciCfg2.c
- PeiMain.h
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- BaseMemoryLib
- PeCoffGetEntryPointLib
- ReportStatusCodeLib
- PeiServicesLib
- PerformanceLib
- HobLib
- BaseLib
- PeiCoreEntryPoint
- DebugLib
- MemoryAllocationLib
- CacheMaintenanceLib
- PeCoffLib
- PeiServicesTablePointerLib
- PcdLib
-
-[Guids]
- gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File
- ## PRODUCES ## UNDEFINED # Install PPI
- ## CONSUMES ## UNDEFINED # Locate PPI
- gEfiFirmwareFileSystem2Guid
- ## PRODUCES ## UNDEFINED # Install PPI
- ## CONSUMES ## UNDEFINED # Locate PPI
- ## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format
- gEfiFirmwareFileSystem3Guid
- gStatusCodeCallbackGuid
- gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB
- gEdkiiMigrationInfoGuid ## SOMETIMES_CONSUMES ## HOB
-
-[Ppis]
- gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
- gEfiPeiResetPpiGuid ## SOMETIMES_CONSUMES # PeiResetService is not ready if this PPI doesn't exist
- gEfiDxeIplPpiGuid ## CONSUMES
- gEfiPeiMemoryDiscoveredPpiGuid ## PRODUCES
- gEfiPeiDecompressPpiGuid ## SOMETIMES_CONSUMES
- ## NOTIFY
- ## SOMETIMES_PRODUCES # Produce FvInfoPpi if the encapsulated FvImage is found
- gEfiPeiFirmwareVolumeInfoPpiGuid
- ## NOTIFY
- ## SOMETIMES_PRODUCES # Produce FvInfoPpi2 if the encapsulated FvImage is found
- gEfiPeiFirmwareVolumeInfo2PpiGuid
- ## PRODUCES
- ## CONSUMES
- gEfiPeiLoadFilePpiGuid
- gEfiPeiSecurity2PpiGuid ## NOTIFY
- gEfiTemporaryRamSupportPpiGuid ## SOMETIMES_CONSUMES
- gEfiTemporaryRamDonePpiGuid ## SOMETIMES_CONSUMES
- gEfiPeiReset2PpiGuid ## SOMETIMES_CONSUMES
- gEfiSecHobDataPpiGuid ## SOMETIMES_CONSUMES
- gEfiPeiCoreFvLocationPpiGuid ## SOMETIMES_CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressPeiCodePageNumber ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
-
-# [BootMode]
-# S3_RESUME ## SOMETIMES_CONSUMES
-
-# [Hob]
-# PHIT ## PRODUCES
-# RESOURCE_DESCRIPTOR ## SOMETIMES_PRODUCES
-# RESOURCE_DESCRIPTOR ## SOMETIMES_CONSUMES
-# MEMORY_ALLOCATION ## SOMETIMES_CONSUMES
-# FIRMWARE_VOLUME ## SOMETIMES_PRODUCES
-# FIRMWARE_VOLUME ## SOMETIMES_CONSUMES
-# MEMORY_ALLOCATION ## SOMETIMES_PRODUCES
-# MEMORY_ALLOCATION ## PRODUCES # MEMORY_ALLOCATION_STACK
-# UNDEFINED ## PRODUCES # MEMORY_POOL
-
-[UserExtensions.TianoCore."ExtraFiles"]
- PeiCoreExtra.uni
+## @file +# PeiMain module is core module in PEI phase. +# +# It takes responsibilities of: +# 1) Initialize memory, PPI, image services etc, to establish PEIM runtime environment. +# 2) Dispatch PEIM from discovered FV. +# 3) Handoff control to DxeIpl to load DXE core and enter DXE phase. +# +# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiCore + MODULE_UNI_FILE = PeiCore.uni + FILE_GUID = 52C05B14-0B98-496c-BC3B-04B50211D680 + MODULE_TYPE = PEI_CORE + VERSION_STRING = 1.0 + ENTRY_POINT = PeiCore + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + StatusCode/StatusCode.c + Security/Security.c + Reset/Reset.c + Ppi/Ppi.c + PeiMain/PeiMain.c + Memory/MemoryServices.c + Image/Image.c + Hob/Hob.c + FwVol/FwVol.c + FwVol/FwVol.h + Dispatcher/Dispatcher.c + Dependency/Dependency.c + Dependency/Dependency.h + BootMode/BootMode.c + CpuIo/CpuIo.c + PciCfg2/PciCfg2.c + PeiMain.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseMemoryLib + PeCoffGetEntryPointLib + ReportStatusCodeLib + PeiServicesLib + PerformanceLib + HobLib + BaseLib + PeiCoreEntryPoint + DebugLib + MemoryAllocationLib + CacheMaintenanceLib + PeCoffLib + PeiServicesTablePointerLib + PcdLib + +[Guids] + gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File + ## PRODUCES ## UNDEFINED # Install PPI + ## CONSUMES ## UNDEFINED # Locate PPI + gEfiFirmwareFileSystem2Guid + ## PRODUCES ## UNDEFINED # Install PPI + ## CONSUMES ## UNDEFINED # Locate PPI + ## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format + gEfiFirmwareFileSystem3Guid + gStatusCodeCallbackGuid + gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB + gEdkiiMigrationInfoGuid ## SOMETIMES_CONSUMES ## HOB + +[Ppis] + gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist + gEfiPeiResetPpiGuid ## SOMETIMES_CONSUMES # PeiResetService is not ready if this PPI doesn't exist + gEfiDxeIplPpiGuid ## CONSUMES + gEfiPeiMemoryDiscoveredPpiGuid ## PRODUCES + gEfiPeiDecompressPpiGuid ## SOMETIMES_CONSUMES + ## NOTIFY + ## SOMETIMES_PRODUCES # Produce FvInfoPpi if the encapsulated FvImage is found + gEfiPeiFirmwareVolumeInfoPpiGuid + ## NOTIFY + ## SOMETIMES_PRODUCES # Produce FvInfoPpi2 if the encapsulated FvImage is found + gEfiPeiFirmwareVolumeInfo2PpiGuid + ## PRODUCES + ## CONSUMES + gEfiPeiLoadFilePpiGuid + gEfiPeiSecurity2PpiGuid ## NOTIFY + gEfiTemporaryRamSupportPpiGuid ## SOMETIMES_CONSUMES + gEfiTemporaryRamDonePpiGuid ## SOMETIMES_CONSUMES + gEfiPeiReset2PpiGuid ## SOMETIMES_CONSUMES + gEfiSecHobDataPpiGuid ## SOMETIMES_CONSUMES + gEfiPeiCoreFvLocationPpiGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressPeiCodePageNumber ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES + +# [BootMode] +# S3_RESUME ## SOMETIMES_CONSUMES + +# [Hob] +# PHIT ## PRODUCES +# RESOURCE_DESCRIPTOR ## SOMETIMES_PRODUCES +# RESOURCE_DESCRIPTOR ## SOMETIMES_CONSUMES +# MEMORY_ALLOCATION ## SOMETIMES_CONSUMES +# FIRMWARE_VOLUME ## SOMETIMES_PRODUCES +# FIRMWARE_VOLUME ## SOMETIMES_CONSUMES +# MEMORY_ALLOCATION ## SOMETIMES_PRODUCES +# MEMORY_ALLOCATION ## PRODUCES # MEMORY_ALLOCATION_STACK +# UNDEFINED ## PRODUCES # MEMORY_POOL + +[UserExtensions.TianoCore."ExtraFiles"] + PeiCoreExtra.uni diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c index bf1719d794..6a0bb4abd7 100644 --- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c +++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c @@ -1,541 +1,541 @@ -/** @file
- Pei Core Main Entry Point
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiPeiMemoryDiscoveredPpiGuid,
- NULL
-};
-
-///
-/// Pei service instance
-///
-EFI_PEI_SERVICES gPs = {
- {
- PEI_SERVICES_SIGNATURE,
- PEI_SERVICES_REVISION,
- sizeof (EFI_PEI_SERVICES),
- 0,
- 0
- },
- PeiInstallPpi,
- PeiReInstallPpi,
- PeiLocatePpi,
- PeiNotifyPpi,
-
- PeiGetBootMode,
- PeiSetBootMode,
-
- PeiGetHobList,
- PeiCreateHob,
-
- PeiFfsFindNextVolume,
- PeiFfsFindNextFile,
- PeiFfsFindSectionData,
-
- PeiInstallPeiMemory,
- PeiAllocatePages,
- PeiAllocatePool,
- (EFI_PEI_COPY_MEM)CopyMem,
- (EFI_PEI_SET_MEM)SetMem,
-
- PeiReportStatusCode,
- PeiResetSystem,
-
- &gPeiDefaultCpuIoPpi,
- &gPeiDefaultPciCfg2Ppi,
-
- PeiFfsFindFileByName,
- PeiFfsGetFileInfo,
- PeiFfsGetVolumeInfo,
- PeiRegisterForShadow,
- PeiFfsFindSectionData3,
- PeiFfsGetFileInfo2,
- PeiResetSystem2,
- PeiFreePages,
-};
-
-/**
- Shadow PeiCore module from flash to installed memory.
-
- @param PrivateData PeiCore's private data structure
-
- @return PeiCore function address after shadowing.
-**/
-PEICORE_FUNCTION_POINTER
-ShadowPeiCore (
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
- EFI_PHYSICAL_ADDRESS EntryPoint;
- EFI_STATUS Status;
- UINT32 AuthenticationState;
- UINTN Index;
- EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
- UINTN PeiCoreFvIndex;
-
- PeiCoreFileHandle = NULL;
- //
- // Default PeiCore is in BFV
- //
- PeiCoreFvIndex = 0;
- //
- // Find the PEI Core either from EFI_PEI_CORE_FV_LOCATION_PPI indicated FV or BFV
- //
- Status = PeiServicesLocatePpi (
- &gEfiPeiCoreFvLocationPpiGuid,
- 0,
- NULL,
- (VOID **)&PeiCoreFvLocationPpi
- );
- if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
- //
- // If PeiCoreFvLocation present, the PEI Core should be found from indicated FV
- //
- for (Index = 0; Index < PrivateData->FvCount; Index++) {
- if (PrivateData->Fv[Index].FvHandle == PeiCoreFvLocationPpi->PeiCoreFvLocation) {
- PeiCoreFvIndex = Index;
- break;
- }
- }
-
- ASSERT (Index < PrivateData->FvCount);
- }
-
- //
- // Find PEI Core from the given FV index
- //
- Status = PrivateData->Fv[PeiCoreFvIndex].FvPpi->FindFileByType (
- PrivateData->Fv[PeiCoreFvIndex].FvPpi,
- EFI_FV_FILETYPE_PEI_CORE,
- PrivateData->Fv[PeiCoreFvIndex].FvHandle,
- &PeiCoreFileHandle
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Shadow PEI Core into memory so it will run faster
- //
- Status = PeiLoadImage (
- GetPeiServicesTablePointer (),
- *((EFI_PEI_FILE_HANDLE *)&PeiCoreFileHandle),
- PEIM_STATE_REGISTER_FOR_SHADOW,
- &EntryPoint,
- &AuthenticationState
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Compute the PeiCore's function address after shadowed PeiCore.
- // _ModuleEntryPoint is PeiCore main function entry
- //
- return (PEICORE_FUNCTION_POINTER)((UINTN)EntryPoint + (UINTN)PeiCore - (UINTN)_ModuleEntryPoint);
-}
-
-/**
- This routine is invoked by main entry of PeiMain module during transition
- from SEC to PEI. After switching stack in the PEI core, it will restart
- with the old core data.
-
- @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating
- environment, such as the size and location of temporary RAM, the stack location and
- the BFV location.
- @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
- An empty PPI list consists of a single descriptor with the end-tag
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
- phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
- that both the PEI Foundation and any modules can leverage the associated service
- calls and/or code in these early PPIs
- @param Data Pointer to old core data that is used to initialize the
- core's data areas.
- If NULL, it is first PeiCore entering.
-
-**/
-VOID
-EFIAPI
-PeiCore (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
- IN VOID *Data
- )
-{
- PEI_CORE_INSTANCE PrivateData;
- EFI_SEC_PEI_HAND_OFF *SecCoreData;
- EFI_SEC_PEI_HAND_OFF NewSecCoreData;
- EFI_STATUS Status;
- PEI_CORE_TEMP_POINTERS TempPtr;
- PEI_CORE_INSTANCE *OldCoreData;
- EFI_PEI_CPU_IO_PPI *CpuIo;
- EFI_PEI_PCI_CFG2_PPI *PciCfg;
- EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable;
- EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi;
- UINTN Index;
-
- //
- // Retrieve context passed into PEI Core
- //
- OldCoreData = (PEI_CORE_INSTANCE *)Data;
- SecCoreData = (EFI_SEC_PEI_HAND_OFF *)SecCoreDataPtr;
-
- //
- // Perform PEI Core phase specific actions.
- //
- if (OldCoreData == NULL) {
- //
- // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
- //
- ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
- PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
- CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
- } else {
- //
- // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet.
- //
- if (OldCoreData->ShadowedPeiCore == NULL) {
- //
- // Fixup the PeiCore's private data
- //
- OldCoreData->Ps = &OldCoreData->ServiceTableShadow;
- OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo;
- if (OldCoreData->HeapOffsetPositive) {
- OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset);
- if (OldCoreData->UnknownFvInfo != NULL) {
- OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *)((UINT8 *)OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->CurrentFvFileHandles != NULL) {
- OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
- OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs + OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
- OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
- OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
- }
-
- OldCoreData->Fv = (PEI_CORE_FV_HANDLE *)((UINT8 *)OldCoreData->Fv + OldCoreData->HeapOffset);
- for (Index = 0; Index < OldCoreData->FvCount; Index++) {
- if (OldCoreData->Fv[Index].PeimState != NULL) {
- OldCoreData->Fv[Index].PeimState = (UINT8 *)OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset;
- }
-
- if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
- OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
- }
- }
-
- OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid + OldCoreData->HeapOffset);
- OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles + OldCoreData->HeapOffset);
- } else {
- OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset);
- if (OldCoreData->UnknownFvInfo != NULL) {
- OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *)((UINT8 *)OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->CurrentFvFileHandles != NULL) {
- OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
- OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs - OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
- OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs - OldCoreData->HeapOffset);
- }
-
- if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
- OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs - OldCoreData->HeapOffset);
- }
-
- OldCoreData->Fv = (PEI_CORE_FV_HANDLE *)((UINT8 *)OldCoreData->Fv - OldCoreData->HeapOffset);
- for (Index = 0; Index < OldCoreData->FvCount; Index++) {
- if (OldCoreData->Fv[Index].PeimState != NULL) {
- OldCoreData->Fv[Index].PeimState = (UINT8 *)OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset;
- }
-
- if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
- OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset);
- }
- }
-
- OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid - OldCoreData->HeapOffset);
- OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset);
- }
-
- //
- // Fixup for PeiService's address
- //
- SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
-
- //
- // Initialize libraries that the PEI Core is linked against
- //
- ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
-
- //
- // Update HandOffHob for new installed permanent memory
- //
- HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
- if (OldCoreData->HeapOffsetPositive) {
- HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
- } else {
- HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
- }
-
- HandoffInformationTable->EfiMemoryTop = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength;
- HandoffInformationTable->EfiMemoryBottom = OldCoreData->PhysicalMemoryBegin;
- HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop;
- HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);
-
- //
- // We need convert MemoryBaseAddress in memory allocation HOBs
- //
- ConvertMemoryAllocationHobs (OldCoreData);
-
- //
- // We need convert the PPI descriptor's pointer
- //
- ConvertPpiPointers (SecCoreData, OldCoreData);
-
- //
- // After the whole temporary memory is migrated, then we can allocate page in
- // permanent memory.
- //
- OldCoreData->PeiMemoryInstalled = TRUE;
-
- //
- // Indicate that PeiCore reenter
- //
- OldCoreData->PeimDispatcherReenter = TRUE;
-
- if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
- //
- // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
- // Every bit in the array indicate the status of the corresponding memory page available or not
- //
- OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof (UINT64));
- }
-
- //
- // Shadow PEI Core. When permanent memory is available, shadow
- // PEI Core and PEIMs to get high performance.
- //
- OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER)(UINTN)PeiCore;
- if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
- ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnS3Boot)) ||
- ((HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnBoot)))
- {
- OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
- }
-
- //
- // PEI Core has now been shadowed to memory. Restart PEI Core in memory.
- //
- OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
-
- //
- // Should never reach here.
- //
- ASSERT (FALSE);
- CpuDeadLoop ();
-
- UNREACHABLE ();
- }
-
- //
- // Memory is available to the PEI Core and the PEI Core has been shadowed to memory.
- //
- CopyMem (&NewSecCoreData, SecCoreDataPtr, sizeof (NewSecCoreData));
- SecCoreData = &NewSecCoreData;
-
- CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData));
-
- CpuIo = (VOID *)PrivateData.ServiceTableShadow.CpuIo;
- PciCfg = (VOID *)PrivateData.ServiceTableShadow.PciCfg;
-
- CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
-
- PrivateData.ServiceTableShadow.CpuIo = CpuIo;
- PrivateData.ServiceTableShadow.PciCfg = PciCfg;
- }
-
- //
- // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory
- //
- PrivateData.Ps = &PrivateData.ServiceTableShadow;
-
- //
- // Save PeiServicePointer so that it can be retrieved anywhere.
- //
- SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
-
- //
- // Initialize libraries that the PEI Core is linked against
- //
- ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps);
-
- //
- // Initialize PEI Core Services
- //
- InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData);
-
- //
- // Update performance measurements
- //
- if (OldCoreData == NULL) {
- PERF_EVENT ("SEC"); // Means the end of SEC phase.
-
- //
- // If first pass, start performance measurement.
- //
- PERF_CROSSMODULE_BEGIN ("PEI");
- PERF_INMODULE_BEGIN ("PreMem");
- } else {
- PERF_INMODULE_END ("PreMem");
- PERF_INMODULE_BEGIN ("PostMem");
- }
-
- //
- // Complete PEI Core Service initialization
- //
- InitializeSecurityServices (&PrivateData.Ps, OldCoreData);
- InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData);
- InitializeImageServices (&PrivateData, OldCoreData);
-
- //
- // Perform PEI Core Phase specific actions
- //
- if (OldCoreData == NULL) {
- //
- // Report Status Code EFI_SW_PC_INIT
- //
- REPORT_STATUS_CODE (
- EFI_PROGRESS_CODE,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT)
- );
-
- //
- // If SEC provided the PpiList, process it.
- //
- if (PpiList != NULL) {
- ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps, PpiList);
- }
- } else {
- if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
- //
- // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all
- // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot
- //
- DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n"));
- DumpPpiList (&PrivateData);
-
- //
- // Migrate installed content from Temporary RAM to Permanent RAM
- //
- EvacuateTempRam (&PrivateData, SecCoreData);
-
- DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n"));
- DumpPpiList (&PrivateData);
- }
-
- //
- // Try to locate Temporary RAM Done Ppi.
- //
- Status = PeiServicesLocatePpi (
- &gEfiTemporaryRamDonePpiGuid,
- 0,
- NULL,
- (VOID **)&TemporaryRamDonePpi
- );
- if (!EFI_ERROR (Status)) {
- //
- // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete.
- //
- TemporaryRamDonePpi->TemporaryRamDone ();
- }
-
- //
- // Alert any listeners that there is permanent memory available
- //
- PERF_INMODULE_BEGIN ("DisMem");
- Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi);
-
- //
- // Process the Notify list and dispatch any notifies for the Memory Discovered PPI
- //
- ProcessDispatchNotifyList (&PrivateData);
-
- PERF_INMODULE_END ("DisMem");
- }
-
- //
- // Call PEIM dispatcher
- //
- PeiDispatcher (SecCoreData, &PrivateData);
-
- if (PrivateData.HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) {
- //
- // Check if InstallPeiMemory service was called on non-S3 resume boot path.
- //
- ASSERT (PrivateData.PeiMemoryInstalled == TRUE);
- }
-
- //
- // Measure PEI Core execution time.
- //
- PERF_INMODULE_END ("PostMem");
-
- //
- // Lookup DXE IPL PPI
- //
- Status = PeiServicesLocatePpi (
- &gEfiDxeIplPpiGuid,
- 0,
- NULL,
- (VOID **)&TempPtr.DxeIpl
- );
- ASSERT_EFI_ERROR (Status);
-
- if (EFI_ERROR (Status)) {
- //
- // Report status code to indicate DXE IPL PPI could not be found.
- //
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MAJOR,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND)
- );
- CpuDeadLoop ();
- }
-
- //
- // Enter DxeIpl to load Dxe core.
- //
- DEBUG ((DEBUG_INFO, "DXE IPL Entry\n"));
- Status = TempPtr.DxeIpl->Entry (
- TempPtr.DxeIpl,
- &PrivateData.Ps,
- PrivateData.HobList
- );
- //
- // Should never reach here.
- //
- ASSERT_EFI_ERROR (Status);
- CpuDeadLoop ();
-
- UNREACHABLE ();
-}
+/** @file + Pei Core Main Entry Point + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMemoryDiscoveredPpiGuid, + NULL +}; + +/// +/// Pei service instance +/// +EFI_PEI_SERVICES gPs = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFfsFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + (EFI_PEI_COPY_MEM)CopyMem, + (EFI_PEI_SET_MEM)SetMem, + + PeiReportStatusCode, + PeiResetSystem, + + &gPeiDefaultCpuIoPpi, + &gPeiDefaultPciCfg2Ppi, + + PeiFfsFindFileByName, + PeiFfsGetFileInfo, + PeiFfsGetVolumeInfo, + PeiRegisterForShadow, + PeiFfsFindSectionData3, + PeiFfsGetFileInfo2, + PeiResetSystem2, + PeiFreePages, +}; + +/** + Shadow PeiCore module from flash to installed memory. + + @param PrivateData PeiCore's private data structure + + @return PeiCore function address after shadowing. +**/ +PEICORE_FUNCTION_POINTER +ShadowPeiCore ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + EFI_PHYSICAL_ADDRESS EntryPoint; + EFI_STATUS Status; + UINT32 AuthenticationState; + UINTN Index; + EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi; + UINTN PeiCoreFvIndex; + + PeiCoreFileHandle = NULL; + // + // Default PeiCore is in BFV + // + PeiCoreFvIndex = 0; + // + // Find the PEI Core either from EFI_PEI_CORE_FV_LOCATION_PPI indicated FV or BFV + // + Status = PeiServicesLocatePpi ( + &gEfiPeiCoreFvLocationPpiGuid, + 0, + NULL, + (VOID **)&PeiCoreFvLocationPpi + ); + if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) { + // + // If PeiCoreFvLocation present, the PEI Core should be found from indicated FV + // + for (Index = 0; Index < PrivateData->FvCount; Index++) { + if (PrivateData->Fv[Index].FvHandle == PeiCoreFvLocationPpi->PeiCoreFvLocation) { + PeiCoreFvIndex = Index; + break; + } + } + + ASSERT (Index < PrivateData->FvCount); + } + + // + // Find PEI Core from the given FV index + // + Status = PrivateData->Fv[PeiCoreFvIndex].FvPpi->FindFileByType ( + PrivateData->Fv[PeiCoreFvIndex].FvPpi, + EFI_FV_FILETYPE_PEI_CORE, + PrivateData->Fv[PeiCoreFvIndex].FvHandle, + &PeiCoreFileHandle + ); + ASSERT_EFI_ERROR (Status); + + // + // Shadow PEI Core into memory so it will run faster + // + Status = PeiLoadImage ( + GetPeiServicesTablePointer (), + *((EFI_PEI_FILE_HANDLE *)&PeiCoreFileHandle), + PEIM_STATE_REGISTER_FOR_SHADOW, + &EntryPoint, + &AuthenticationState + ); + ASSERT_EFI_ERROR (Status); + + // + // Compute the PeiCore's function address after shadowed PeiCore. + // _ModuleEntryPoint is PeiCore main function entry + // + return (PEICORE_FUNCTION_POINTER)((UINTN)EntryPoint + (UINTN)PeiCore - (UINTN)_ModuleEntryPoint); +} + +/** + This routine is invoked by main entry of PeiMain module during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + + @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating + environment, such as the size and location of temporary RAM, the stack location and + the BFV location. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + An empty PPI list consists of a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization + phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such + that both the PEI Foundation and any modules can leverage the associated service + calls and/or code in these early PPIs + @param Data Pointer to old core data that is used to initialize the + core's data areas. + If NULL, it is first PeiCore entering. + +**/ +VOID +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Data + ) +{ + PEI_CORE_INSTANCE PrivateData; + EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_SEC_PEI_HAND_OFF NewSecCoreData; + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + PEI_CORE_INSTANCE *OldCoreData; + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_PEI_PCI_CFG2_PPI *PciCfg; + EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable; + EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi; + UINTN Index; + + // + // Retrieve context passed into PEI Core + // + OldCoreData = (PEI_CORE_INSTANCE *)Data; + SecCoreData = (EFI_SEC_PEI_HAND_OFF *)SecCoreDataPtr; + + // + // Perform PEI Core phase specific actions. + // + if (OldCoreData == NULL) { + // + // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available. + // + ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE)); + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs)); + } else { + // + // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet. + // + if (OldCoreData->ShadowedPeiCore == NULL) { + // + // Fixup the PeiCore's private data + // + OldCoreData->Ps = &OldCoreData->ServiceTableShadow; + OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo; + if (OldCoreData->HeapOffsetPositive) { + OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset); + if (OldCoreData->UnknownFvInfo != NULL) { + OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *)((UINT8 *)OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset); + } + + if (OldCoreData->CurrentFvFileHandles != NULL) { + OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset); + } + + if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) { + OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs + OldCoreData->HeapOffset); + } + + if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) { + OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs + OldCoreData->HeapOffset); + } + + if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) { + OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs + OldCoreData->HeapOffset); + } + + OldCoreData->Fv = (PEI_CORE_FV_HANDLE *)((UINT8 *)OldCoreData->Fv + OldCoreData->HeapOffset); + for (Index = 0; Index < OldCoreData->FvCount; Index++) { + if (OldCoreData->Fv[Index].PeimState != NULL) { + OldCoreData->Fv[Index].PeimState = (UINT8 *)OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset; + } + + if (OldCoreData->Fv[Index].FvFileHandles != NULL) { + OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset); + } + } + + OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid + OldCoreData->HeapOffset); + OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles + OldCoreData->HeapOffset); + } else { + OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset); + if (OldCoreData->UnknownFvInfo != NULL) { + OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *)((UINT8 *)OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset); + } + + if (OldCoreData->CurrentFvFileHandles != NULL) { + OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset); + } + + if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) { + OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs - OldCoreData->HeapOffset); + } + + if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) { + OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs - OldCoreData->HeapOffset); + } + + if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) { + OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs - OldCoreData->HeapOffset); + } + + OldCoreData->Fv = (PEI_CORE_FV_HANDLE *)((UINT8 *)OldCoreData->Fv - OldCoreData->HeapOffset); + for (Index = 0; Index < OldCoreData->FvCount; Index++) { + if (OldCoreData->Fv[Index].PeimState != NULL) { + OldCoreData->Fv[Index].PeimState = (UINT8 *)OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset; + } + + if (OldCoreData->Fv[Index].FvFileHandles != NULL) { + OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset); + } + } + + OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid - OldCoreData->HeapOffset); + OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset); + } + + // + // Fixup for PeiService's address + // + SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps); + + // + // Initialize libraries that the PEI Core is linked against + // + ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps); + + // + // Update HandOffHob for new installed permanent memory + // + HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable; + if (OldCoreData->HeapOffsetPositive) { + HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset; + } else { + HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset; + } + + HandoffInformationTable->EfiMemoryTop = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength; + HandoffInformationTable->EfiMemoryBottom = OldCoreData->PhysicalMemoryBegin; + HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop; + HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER); + + // + // We need convert MemoryBaseAddress in memory allocation HOBs + // + ConvertMemoryAllocationHobs (OldCoreData); + + // + // We need convert the PPI descriptor's pointer + // + ConvertPpiPointers (SecCoreData, OldCoreData); + + // + // After the whole temporary memory is migrated, then we can allocate page in + // permanent memory. + // + OldCoreData->PeiMemoryInstalled = TRUE; + + // + // Indicate that PeiCore reenter + // + OldCoreData->PeimDispatcherReenter = TRUE; + + if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array. + // Every bit in the array indicate the status of the corresponding memory page available or not + // + OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof (UINT64)); + } + + // + // Shadow PEI Core. When permanent memory is available, shadow + // PEI Core and PEIMs to get high performance. + // + OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER)(UINTN)PeiCore; + if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || + ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnS3Boot)) || + ((HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnBoot))) + { + OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData); + } + + // + // PEI Core has now been shadowed to memory. Restart PEI Core in memory. + // + OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData); + + // + // Should never reach here. + // + ASSERT (FALSE); + CpuDeadLoop (); + + UNREACHABLE (); + } + + // + // Memory is available to the PEI Core and the PEI Core has been shadowed to memory. + // + CopyMem (&NewSecCoreData, SecCoreDataPtr, sizeof (NewSecCoreData)); + SecCoreData = &NewSecCoreData; + + CopyMem (&PrivateData, OldCoreData, sizeof (PrivateData)); + + CpuIo = (VOID *)PrivateData.ServiceTableShadow.CpuIo; + PciCfg = (VOID *)PrivateData.ServiceTableShadow.PciCfg; + + CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs)); + + PrivateData.ServiceTableShadow.CpuIo = CpuIo; + PrivateData.ServiceTableShadow.PciCfg = PciCfg; + } + + // + // Cache a pointer to the PEI Services Table that is either in temporary memory or permanent memory + // + PrivateData.Ps = &PrivateData.ServiceTableShadow; + + // + // Save PeiServicePointer so that it can be retrieved anywhere. + // + SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps); + + // + // Initialize libraries that the PEI Core is linked against + // + ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&PrivateData.Ps); + + // + // Initialize PEI Core Services + // + InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData); + + // + // Update performance measurements + // + if (OldCoreData == NULL) { + PERF_EVENT ("SEC"); // Means the end of SEC phase. + + // + // If first pass, start performance measurement. + // + PERF_CROSSMODULE_BEGIN ("PEI"); + PERF_INMODULE_BEGIN ("PreMem"); + } else { + PERF_INMODULE_END ("PreMem"); + PERF_INMODULE_BEGIN ("PostMem"); + } + + // + // Complete PEI Core Service initialization + // + InitializeSecurityServices (&PrivateData.Ps, OldCoreData); + InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData); + InitializeImageServices (&PrivateData, OldCoreData); + + // + // Perform PEI Core Phase specific actions + // + if (OldCoreData == NULL) { + // + // Report Status Code EFI_SW_PC_INIT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT) + ); + + // + // If SEC provided the PpiList, process it. + // + if (PpiList != NULL) { + ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **)&PrivateData.Ps, PpiList); + } + } else { + if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { + // + // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all + // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot + // + DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n")); + DumpPpiList (&PrivateData); + + // + // Migrate installed content from Temporary RAM to Permanent RAM + // + EvacuateTempRam (&PrivateData, SecCoreData); + + DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n")); + DumpPpiList (&PrivateData); + } + + // + // Try to locate Temporary RAM Done Ppi. + // + Status = PeiServicesLocatePpi ( + &gEfiTemporaryRamDonePpiGuid, + 0, + NULL, + (VOID **)&TemporaryRamDonePpi + ); + if (!EFI_ERROR (Status)) { + // + // Disable the use of Temporary RAM after the transition from Temporary RAM to Permanent RAM is complete. + // + TemporaryRamDonePpi->TemporaryRamDone (); + } + + // + // Alert any listeners that there is permanent memory available + // + PERF_INMODULE_BEGIN ("DisMem"); + Status = PeiServicesInstallPpi (&mMemoryDiscoveredPpi); + + // + // Process the Notify list and dispatch any notifies for the Memory Discovered PPI + // + ProcessDispatchNotifyList (&PrivateData); + + PERF_INMODULE_END ("DisMem"); + } + + // + // Call PEIM dispatcher + // + PeiDispatcher (SecCoreData, &PrivateData); + + if (PrivateData.HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) { + // + // Check if InstallPeiMemory service was called on non-S3 resume boot path. + // + ASSERT (PrivateData.PeiMemoryInstalled == TRUE); + } + + // + // Measure PEI Core execution time. + // + PERF_INMODULE_END ("PostMem"); + + // + // Lookup DXE IPL PPI + // + Status = PeiServicesLocatePpi ( + &gEfiDxeIplPpiGuid, + 0, + NULL, + (VOID **)&TempPtr.DxeIpl + ); + ASSERT_EFI_ERROR (Status); + + if (EFI_ERROR (Status)) { + // + // Report status code to indicate DXE IPL PPI could not be found. + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MAJOR, + (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND) + ); + CpuDeadLoop (); + } + + // + // Enter DxeIpl to load Dxe core. + // + DEBUG ((DEBUG_INFO, "DXE IPL Entry\n")); + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.Ps, + PrivateData.HobList + ); + // + // Should never reach here. + // + ASSERT_EFI_ERROR (Status); + CpuDeadLoop (); + + UNREACHABLE (); +} diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c index 0e85264ddb..214a831da5 100644 --- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c +++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c @@ -1,1134 +1,1134 @@ -/** @file
- EFI PEI Core PPI services
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
-
- Migrate Pointer from the temporary memory to PEI installed memory.
-
- @param Pointer Pointer to the Pointer needs to be converted.
- @param TempBottom Base of old temporary memory
- @param TempTop Top of old temporary memory
- @param Offset Offset of new memory to old temporary memory.
- @param OffsetPositive Positive flag of Offset value.
-
-**/
-VOID
-ConvertPointer (
- IN OUT VOID **Pointer,
- IN UINTN TempBottom,
- IN UINTN TempTop,
- IN UINTN Offset,
- IN BOOLEAN OffsetPositive
- )
-{
- if (((UINTN)*Pointer < TempTop) &&
- ((UINTN)*Pointer >= TempBottom))
- {
- if (OffsetPositive) {
- *Pointer = (VOID *)((UINTN)*Pointer + Offset);
- } else {
- *Pointer = (VOID *)((UINTN)*Pointer - Offset);
- }
- }
-}
-
-/**
-
- Migrate Pointer in ranges of the temporary memory to PEI installed memory.
-
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param PrivateData Pointer to PeiCore's private data structure.
- @param Pointer Pointer to the Pointer needs to be converted.
-
-**/
-VOID
-ConvertPointerInRanges (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *PrivateData,
- IN OUT VOID **Pointer
- )
-{
- UINT8 IndexHole;
-
- if (PrivateData->MemoryPages.Size != 0) {
- //
- // Convert PPI pointer in old memory pages
- // It needs to be done before Convert PPI pointer in old Heap
- //
- ConvertPointer (
- Pointer,
- (UINTN)PrivateData->MemoryPages.Base,
- (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,
- PrivateData->MemoryPages.Offset,
- PrivateData->MemoryPages.OffsetPositive
- );
- }
-
- //
- // Convert PPI pointer in old Heap
- //
- ConvertPointer (
- Pointer,
- (UINTN)SecCoreData->PeiTemporaryRamBase,
- (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize,
- PrivateData->HeapOffset,
- PrivateData->HeapOffsetPositive
- );
-
- //
- // Convert PPI pointer in old Stack
- //
- ConvertPointer (
- Pointer,
- (UINTN)SecCoreData->StackBase,
- (UINTN)SecCoreData->StackBase + SecCoreData->StackSize,
- PrivateData->StackOffset,
- PrivateData->StackOffsetPositive
- );
-
- //
- // Convert PPI pointer in old TempRam Hole
- //
- for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole++) {
- if (PrivateData->HoleData[IndexHole].Size == 0) {
- continue;
- }
-
- ConvertPointer (
- Pointer,
- (UINTN)PrivateData->HoleData[IndexHole].Base,
- (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size,
- PrivateData->HoleData[IndexHole].Offset,
- PrivateData->HoleData[IndexHole].OffsetPositive
- );
- }
-}
-
-/**
-
- Migrate Single PPI Pointer from the temporary memory to PEI installed memory.
-
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param PrivateData Pointer to PeiCore's private data structure.
- @param PpiPointer Pointer to Ppi
-
-**/
-VOID
-ConvertSinglePpiPointer (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_PPI_LIST_POINTERS *PpiPointer
- )
-{
- //
- // 1. Convert the pointer to the PPI descriptor from the old TempRam
- // to the relocated physical memory.
- // It (for the pointer to the PPI descriptor) needs to be done before 2 (for
- // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure).
- //
- ConvertPointerInRanges (SecCoreData, PrivateData, &PpiPointer->Raw);
- //
- // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor
- // from the old TempRam to the relocated physical memory.
- //
- ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **)&PpiPointer->Ppi->Guid);
- //
- // 3. Convert the pointer to the PPI interface structure in the PPI descriptor
- // from the old TempRam to the relocated physical memory.
- //
- ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **)&PpiPointer->Ppi->Ppi);
-}
-
-/**
-
- Migrate PPI Pointers from the temporary memory to PEI installed memory.
-
- @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
- and location of temporary RAM, the stack location and the BFV location.
- @param PrivateData Pointer to PeiCore's private data structure.
-
-**/
-VOID
-ConvertPpiPointers (
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- UINT8 Index;
-
- //
- // Convert normal PPIs.
- //
- for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
- ConvertSinglePpiPointer (
- SecCoreData,
- PrivateData,
- &PrivateData->PpiData.PpiList.PpiPtrs[Index]
- );
- }
-
- //
- // Convert Callback Notification PPIs.
- //
- for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
- ConvertSinglePpiPointer (
- SecCoreData,
- PrivateData,
- &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index]
- );
- }
-
- //
- // Convert Dispatch Notification PPIs.
- //
- for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
- ConvertSinglePpiPointer (
- SecCoreData,
- PrivateData,
- &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index]
- );
- }
-}
-
-/**
-
- Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
-
- @param PrivateData Pointer to PeiCore's private data structure.
- @param OrgFvHandle Address of FV Handle in temporary memory.
- @param FvHandle Address of FV Handle in permanent memory.
- @param FvSize Size of the FV.
-
-**/
-VOID
-ConvertPpiPointersFv (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN UINTN OrgFvHandle,
- IN UINTN FvHandle,
- IN UINTN FvSize
- )
-{
- UINT8 Index;
- UINTN Offset;
- BOOLEAN OffsetPositive;
- EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;
- UINT8 GuidIndex;
- EFI_GUID *Guid;
- EFI_GUID *GuidCheckList[2];
-
- GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;
- GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;
-
- if (FvHandle > OrgFvHandle) {
- OffsetPositive = TRUE;
- Offset = FvHandle - OrgFvHandle;
- } else {
- OffsetPositive = FALSE;
- Offset = OrgFvHandle - FvHandle;
- }
-
- DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));
- DEBUG ((
- DEBUG_VERBOSE,
- " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
- (UINTN)OrgFvHandle,
- (UINTN)FvHandle,
- FvSize
- ));
- DEBUG ((
- DEBUG_VERBOSE,
- " OrgFvHandle range: 0x%08x - 0x%08x\n",
- OrgFvHandle,
- OrgFvHandle + FvSize
- ));
-
- for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- }
-
- for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- }
-
- for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- ConvertPointer (
- (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
-
- Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;
- for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {
- //
- // Don't use CompareGuid function here for performance reasons.
- // Instead we compare the GUID as INT32 at a time and branch
- // on the first failed comparison.
- //
- if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&
- (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&
- (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&
- (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3]))
- {
- FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;
- DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));
- if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {
- ConvertPointer (
- (VOID **)&FvInfoPpi->FvInfo,
- OrgFvHandle,
- OrgFvHandle + FvSize,
- Offset,
- OffsetPositive
- );
- DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));
- }
-
- DEBUG ((DEBUG_VERBOSE, "\n"));
- break;
- }
- }
- }
-}
-
-/**
-
- Dumps the PPI lists to debug output.
-
- @param PrivateData Points to PeiCore's private instance data.
-
-**/
-VOID
-DumpPpiList (
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- DEBUG_CODE_BEGIN ();
- UINTN Index;
-
- if (PrivateData == NULL) {
- return;
- }
-
- for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
- DEBUG ((
- DEBUG_VERBOSE,
- "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
- Index,
- PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
- (UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
- (
- !(
- ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
- (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
- )
- ? "CAR" : "Post-Memory"
- )
- ));
- }
-
- for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
- DEBUG ((
- DEBUG_VERBOSE,
- "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
- Index,
- PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
- (UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
- (
- !(
- ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
- (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
- )
- ? "CAR" : "Post-Memory"
- )
- ));
- }
-
- for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
- DEBUG ((
- DEBUG_VERBOSE,
- "PPI[%2d] {%g} at 0x%x (%a)\n",
- Index,
- PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
- (UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
- (
- !(
- ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
- (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
- )
- ? "CAR" : "Post-Memory"
- )
- ));
- }
-
- DEBUG_CODE_END ();
-}
-
-/**
-
- This function installs an interface in the PEI PPI database by GUID.
- The purpose of the service is to publish an interface that other parties
- can use to call additional PEIMs.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param PpiList Pointer to a list of PEI PPI Descriptors.
- @param Single TRUE if only single entry in the PpiList.
- FALSE if the PpiList is ended with an entry which has the
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
-
- @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
- @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
- if any PPI in PpiList is not valid
- @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
-
-**/
-EFI_STATUS
-InternalPeiInstallPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList,
- IN BOOLEAN Single
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- PEI_PPI_LIST *PpiListPointer;
- UINTN Index;
- UINTN LastCount;
- VOID *TempPtr;
-
- if (PpiList == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- PpiListPointer = &PrivateData->PpiData.PpiList;
- Index = PpiListPointer->CurrentCount;
- LastCount = Index;
-
- //
- // This is loop installs all PPI descriptors in the PpiList. It is terminated
- // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
- // EFI_PEI_PPI_DESCRIPTOR in the list.
- //
-
- for ( ; ;) {
- //
- // Check if it is a valid PPI.
- // If not, rollback list to exclude all in this list.
- // Try to indicate which item failed.
- //
- if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
- PpiListPointer->CurrentCount = LastCount;
- DEBUG ((DEBUG_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi));
- return EFI_INVALID_PARAMETER;
- }
-
- if (Index >= PpiListPointer->MaxCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempPtr = AllocateZeroPool (
- sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP)
- );
- ASSERT (TempPtr != NULL);
- CopyMem (
- TempPtr,
- PpiListPointer->PpiPtrs,
- sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount
- );
- PpiListPointer->PpiPtrs = TempPtr;
- PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP;
- }
-
- DEBUG ((DEBUG_INFO, "Install PPI: %g\n", PpiList->Guid));
- PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)PpiList;
- Index++;
- PpiListPointer->CurrentCount++;
-
- if (Single) {
- //
- // Only single entry in the PpiList.
- //
- break;
- } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)
- {
- //
- // Continue until the end of the PPI List.
- //
- break;
- }
-
- //
- // Go to the next descriptor.
- //
- PpiList++;
- }
-
- //
- // Process any callback level notifies for newly installed PPIs.
- //
- ProcessNotify (
- PrivateData,
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
- LastCount,
- PpiListPointer->CurrentCount,
- 0,
- PrivateData->PpiData.CallbackNotifyList.CurrentCount
- );
-
- return EFI_SUCCESS;
-}
-
-/**
-
- This function installs an interface in the PEI PPI database by GUID.
- The purpose of the service is to publish an interface that other parties
- can use to call additional PEIMs.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param PpiList Pointer to a list of PEI PPI Descriptors.
-
- @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed.
- @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer
- if any PPI in PpiList is not valid
- @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI
-
-**/
-EFI_STATUS
-EFIAPI
-PeiInstallPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
- )
-{
- return InternalPeiInstallPpi (PeiServices, PpiList, FALSE);
-}
-
-/**
-
- This function reinstalls an interface in the PEI PPI database by GUID.
- The purpose of the service is to publish an interface that other parties can
- use to replace an interface of the same name in the protocol database with a
- different interface.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param OldPpi Pointer to the old PEI PPI Descriptors.
- @param NewPpi Pointer to the new PEI PPI Descriptors.
-
- @retval EFI_SUCCESS if the operation was successful
- @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL
- @retval EFI_INVALID_PARAMETER if NewPpi is not valid
- @retval EFI_NOT_FOUND if the PPI was not in the database
-
-**/
-EFI_STATUS
-EFIAPI
-PeiReInstallPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- UINTN Index;
-
- if ((OldPpi == NULL) || (NewPpi == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- //
- // Find the old PPI instance in the database. If we can not find it,
- // return the EFI_NOT_FOUND error.
- //
- for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
- if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) {
- break;
- }
- }
-
- if (Index == PrivateData->PpiData.PpiList.CurrentCount) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Replace the old PPI with the new one.
- //
- DEBUG ((DEBUG_INFO, "Reinstall PPI: %g\n", NewPpi->Guid));
- PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)NewPpi;
-
- //
- // Process any callback level notifies for the newly installed PPI.
- //
- ProcessNotify (
- PrivateData,
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
- Index,
- Index+1,
- 0,
- PrivateData->PpiData.CallbackNotifyList.CurrentCount
- );
-
- return EFI_SUCCESS;
-}
-
-/**
-
- Locate a given named PPI.
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param Guid Pointer to GUID of the PPI.
- @param Instance Instance Number to discover.
- @param PpiDescriptor Pointer to reference the found descriptor. If not NULL,
- returns a pointer to the descriptor (includes flags, etc)
- @param Ppi Pointer to reference the found PPI
-
- @retval EFI_SUCCESS if the PPI is in the database
- @retval EFI_NOT_FOUND if the PPI is not in the database
-
-**/
-EFI_STATUS
-EFIAPI
-PeiLocatePpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_GUID *Guid,
- IN UINTN Instance,
- IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor,
- IN OUT VOID **Ppi
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- UINTN Index;
- EFI_GUID *CheckGuid;
- EFI_PEI_PPI_DESCRIPTOR *TempPtr;
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- //
- // Search the data base for the matching instance of the GUIDed PPI.
- //
- for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
- TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi;
- CheckGuid = TempPtr->Guid;
-
- //
- // Don't use CompareGuid function here for performance reasons.
- // Instead we compare the GUID as INT32 at a time and branch
- // on the first failed comparison.
- //
- if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) &&
- (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) &&
- (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) &&
- (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3]))
- {
- if (Instance == 0) {
- if (PpiDescriptor != NULL) {
- *PpiDescriptor = TempPtr;
- }
-
- if (Ppi != NULL) {
- *Ppi = TempPtr->Ppi;
- }
-
- return EFI_SUCCESS;
- }
-
- Instance--;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
-
- This function installs a notification service to be called back when a given
- interface is installed or reinstalled. The purpose of the service is to publish
- an interface that other parties can use to call additional PPIs that may materialize later.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param NotifyList Pointer to list of Descriptors to notify upon.
- @param Single TRUE if only single entry in the NotifyList.
- FALSE if the NotifyList is ended with an entry which has the
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field.
-
- @retval EFI_SUCCESS if successful
- @retval EFI_OUT_OF_RESOURCES if no space in the database
- @retval EFI_INVALID_PARAMETER if not a good descriptor
-
-**/
-EFI_STATUS
-InternalPeiNotifyPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList,
- IN BOOLEAN Single
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
- PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer;
- UINTN CallbackNotifyIndex;
- UINTN LastCallbackNotifyCount;
- PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer;
- UINTN DispatchNotifyIndex;
- UINTN LastDispatchNotifyCount;
- VOID *TempPtr;
-
- if (NotifyList == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList;
- CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount;
- LastCallbackNotifyCount = CallbackNotifyIndex;
-
- DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList;
- DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount;
- LastDispatchNotifyCount = DispatchNotifyIndex;
-
- //
- // This is loop installs all Notify descriptors in the NotifyList. It is
- // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last
- // EFI_PEI_NOTIFY_DESCRIPTOR in the list.
- //
-
- for ( ; ;) {
- //
- // If some of the PPI data is invalid restore original Notify PPI database value
- //
- if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) {
- CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount;
- DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount;
- DEBUG ((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify));
- return EFI_INVALID_PARAMETER;
- }
-
- if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) {
- if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempPtr = AllocateZeroPool (
- sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP)
- );
- ASSERT (TempPtr != NULL);
- CopyMem (
- TempPtr,
- CallbackNotifyListPointer->NotifyPtrs,
- sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount
- );
- CallbackNotifyListPointer->NotifyPtrs = TempPtr;
- CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP;
- }
-
- CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList;
- CallbackNotifyIndex++;
- CallbackNotifyListPointer->CurrentCount++;
- } else {
- if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) {
- //
- // Run out of room, grow the buffer.
- //
- TempPtr = AllocateZeroPool (
- sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP)
- );
- ASSERT (TempPtr != NULL);
- CopyMem (
- TempPtr,
- DispatchNotifyListPointer->NotifyPtrs,
- sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount
- );
- DispatchNotifyListPointer->NotifyPtrs = TempPtr;
- DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP;
- }
-
- DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList;
- DispatchNotifyIndex++;
- DispatchNotifyListPointer->CurrentCount++;
- }
-
- DEBUG ((DEBUG_INFO, "Register PPI Notify: %g\n", NotifyList->Guid));
-
- if (Single) {
- //
- // Only single entry in the NotifyList.
- //
- break;
- } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) ==
- EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)
- {
- //
- // Continue until the end of the Notify List.
- //
- break;
- }
-
- //
- // Go to the next descriptor.
- //
- NotifyList++;
- }
-
- //
- // Process any callback level notifies for all previously installed PPIs.
- //
- ProcessNotify (
- PrivateData,
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
- 0,
- PrivateData->PpiData.PpiList.CurrentCount,
- LastCallbackNotifyCount,
- CallbackNotifyListPointer->CurrentCount
- );
-
- return EFI_SUCCESS;
-}
-
-/**
-
- This function installs a notification service to be called back when a given
- interface is installed or reinstalled. The purpose of the service is to publish
- an interface that other parties can use to call additional PPIs that may materialize later.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param NotifyList Pointer to list of Descriptors to notify upon.
-
- @retval EFI_SUCCESS if successful
- @retval EFI_OUT_OF_RESOURCES if no space in the database
- @retval EFI_INVALID_PARAMETER if not a good descriptor
-
-**/
-EFI_STATUS
-EFIAPI
-PeiNotifyPpi (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList
- )
-{
- return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE);
-}
-
-/**
-
- Process the Notify List at dispatch level.
-
- @param PrivateData PeiCore's private data structure.
-
-**/
-VOID
-ProcessDispatchNotifyList (
- IN PEI_CORE_INSTANCE *PrivateData
- )
-{
- UINTN TempValue;
-
- while (TRUE) {
- //
- // Check if the PEIM that was just dispatched resulted in any
- // Notifies getting installed. If so, go process any dispatch
- // level Notifies that match the previously installed PPIs.
- // Use "while" instead of "if" since ProcessNotify can modify
- // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have
- // to iterate until the same.
- //
- while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) {
- TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount;
- ProcessNotify (
- PrivateData,
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
- 0,
- PrivateData->PpiData.PpiList.LastDispatchedCount,
- PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount,
- PrivateData->PpiData.DispatchNotifyList.CurrentCount
- );
- PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue;
- }
-
- //
- // Check if the PEIM that was just dispatched resulted in any
- // PPIs getting installed. If so, go process any dispatch
- // level Notifies that match the installed PPIs.
- // Use "while" instead of "if" since ProcessNotify can modify
- // PpiList.CurrentCount (with InstallPpi) so we have to iterate
- // until the same.
- //
- while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) {
- TempValue = PrivateData->PpiData.PpiList.CurrentCount;
- ProcessNotify (
- PrivateData,
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH,
- PrivateData->PpiData.PpiList.LastDispatchedCount,
- PrivateData->PpiData.PpiList.CurrentCount,
- 0,
- PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount
- );
- PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue;
- }
-
- if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) {
- break;
- }
- }
-
- return;
-}
-
-/**
-
- Process notifications.
-
- @param PrivateData PeiCore's private data structure
- @param NotifyType Type of notify to fire.
- @param InstallStartIndex Install Beginning index.
- @param InstallStopIndex Install Ending index.
- @param NotifyStartIndex Notify Beginning index.
- @param NotifyStopIndex Notify Ending index.
-
-**/
-VOID
-ProcessNotify (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN UINTN NotifyType,
- IN INTN InstallStartIndex,
- IN INTN InstallStopIndex,
- IN INTN NotifyStartIndex,
- IN INTN NotifyStopIndex
- )
-{
- INTN Index1;
- INTN Index2;
- EFI_GUID *SearchGuid;
- EFI_GUID *CheckGuid;
- EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor;
-
- for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) {
- if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) {
- NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify;
- } else {
- NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify;
- }
-
- CheckGuid = NotifyDescriptor->Guid;
-
- for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) {
- SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid;
- //
- // Don't use CompareGuid function here for performance reasons.
- // Instead we compare the GUID as INT32 at a time and branch
- // on the first failed comparison.
- //
- if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) &&
- (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) &&
- (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) &&
- (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3]))
- {
- DEBUG ((
- DEBUG_INFO,
- "Notify: PPI Guid: %g, Peim notify entry point: %p\n",
- SearchGuid,
- NotifyDescriptor->Notify
- ));
- NotifyDescriptor->Notify (
- (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
- NotifyDescriptor,
- (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi
- );
- }
- }
- }
-}
-
-/**
- Process PpiList from SEC phase.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
- These PPI's will be installed and/or immediately signaled if they are notification type.
-
-**/
-VOID
-ProcessPpiListFromSec (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList
- )
-{
- EFI_STATUS Status;
- EFI_SEC_HOB_DATA_PPI *SecHobDataPpi;
- EFI_HOB_GENERIC_HEADER *SecHobList;
-
- for ( ; ;) {
- if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) {
- //
- // It is a notification PPI.
- //
- Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *)PpiList, TRUE);
- ASSERT_EFI_ERROR (Status);
- } else {
- //
- // It is a normal PPI.
- //
- Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE);
- ASSERT_EFI_ERROR (Status);
- }
-
- if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
- //
- // Continue until the end of the PPI List.
- //
- break;
- }
-
- PpiList++;
- }
-
- //
- // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point,
- // the PEI Foundation will call the GetHobs() member function and install all HOBs
- // returned into the HOB list. It does this after installing all PPIs passed from SEC
- // into the PPI database and before dispatching any PEIMs.
- //
- Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **)&SecHobDataPpi);
- if (!EFI_ERROR (Status)) {
- Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList);
- if (!EFI_ERROR (Status)) {
- Status = PeiInstallSecHobData (PeiServices, SecHobList);
- ASSERT_EFI_ERROR (Status);
- }
- }
-}
-
-/**
-
- Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
-
- @param PrivateData Pointer to PeiCore's private data structure.
- @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
-
-**/
-VOID
-ConvertPeiCorePpiPointers (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_FV_HANDLE *CoreFvHandle
- )
-{
- EFI_FV_FILE_INFO FileInfo;
- EFI_PHYSICAL_ADDRESS OrgImageBase;
- EFI_PHYSICAL_ADDRESS MigratedImageBase;
- UINTN PeiCoreModuleSize;
- EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
- VOID *PeiCoreImageBase;
- VOID *PeiCoreEntryPoint;
- EFI_STATUS Status;
-
- PeiCoreFileHandle = NULL;
-
- //
- // Find the PEI Core in the BFV in temporary memory.
- //
- Status = CoreFvHandle->FvPpi->FindFileByType (
- CoreFvHandle->FvPpi,
- EFI_FV_FILETYPE_PEI_CORE,
- CoreFvHandle->FvHandle,
- &PeiCoreFileHandle
- );
- ASSERT_EFI_ERROR (Status);
-
- if (!EFI_ERROR (Status)) {
- Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeiCoreFileHandle, &FileInfo);
- ASSERT_EFI_ERROR (Status);
-
- Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Find PEI Core EntryPoint in the BFV in temporary memory.
- //
- Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, &PeiCoreEntryPoint);
- ASSERT_EFI_ERROR (Status);
-
- OrgImageBase = (UINTN)PeiCoreImageBase;
- MigratedImageBase = (UINTN)_ModuleEntryPoint - ((UINTN)PeiCoreEntryPoint - (UINTN)PeiCoreImageBase);
-
- //
- // Size of loaded PEI_CORE in permanent memory.
- //
- PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN)OrgImageBase - (UINTN)FileInfo.Buffer);
-
- //
- // Migrate PEI_CORE PPI pointers from temporary memory to newly
- // installed PEI_CORE in permanent memory.
- //
- ConvertPpiPointersFv (PrivateData, (UINTN)OrgImageBase, (UINTN)MigratedImageBase, PeiCoreModuleSize);
- }
-}
+/** @file + EFI PEI Core PPI services + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + Migrate Pointer from the temporary memory to PEI installed memory. + + @param Pointer Pointer to the Pointer needs to be converted. + @param TempBottom Base of old temporary memory + @param TempTop Top of old temporary memory + @param Offset Offset of new memory to old temporary memory. + @param OffsetPositive Positive flag of Offset value. + +**/ +VOID +ConvertPointer ( + IN OUT VOID **Pointer, + IN UINTN TempBottom, + IN UINTN TempTop, + IN UINTN Offset, + IN BOOLEAN OffsetPositive + ) +{ + if (((UINTN)*Pointer < TempTop) && + ((UINTN)*Pointer >= TempBottom)) + { + if (OffsetPositive) { + *Pointer = (VOID *)((UINTN)*Pointer + Offset); + } else { + *Pointer = (VOID *)((UINTN)*Pointer - Offset); + } + } +} + +/** + + Migrate Pointer in ranges of the temporary memory to PEI installed memory. + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PrivateData Pointer to PeiCore's private data structure. + @param Pointer Pointer to the Pointer needs to be converted. + +**/ +VOID +ConvertPointerInRanges ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData, + IN OUT VOID **Pointer + ) +{ + UINT8 IndexHole; + + if (PrivateData->MemoryPages.Size != 0) { + // + // Convert PPI pointer in old memory pages + // It needs to be done before Convert PPI pointer in old Heap + // + ConvertPointer ( + Pointer, + (UINTN)PrivateData->MemoryPages.Base, + (UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size, + PrivateData->MemoryPages.Offset, + PrivateData->MemoryPages.OffsetPositive + ); + } + + // + // Convert PPI pointer in old Heap + // + ConvertPointer ( + Pointer, + (UINTN)SecCoreData->PeiTemporaryRamBase, + (UINTN)SecCoreData->PeiTemporaryRamBase + SecCoreData->PeiTemporaryRamSize, + PrivateData->HeapOffset, + PrivateData->HeapOffsetPositive + ); + + // + // Convert PPI pointer in old Stack + // + ConvertPointer ( + Pointer, + (UINTN)SecCoreData->StackBase, + (UINTN)SecCoreData->StackBase + SecCoreData->StackSize, + PrivateData->StackOffset, + PrivateData->StackOffsetPositive + ); + + // + // Convert PPI pointer in old TempRam Hole + // + for (IndexHole = 0; IndexHole < HOLE_MAX_NUMBER; IndexHole++) { + if (PrivateData->HoleData[IndexHole].Size == 0) { + continue; + } + + ConvertPointer ( + Pointer, + (UINTN)PrivateData->HoleData[IndexHole].Base, + (UINTN)PrivateData->HoleData[IndexHole].Base + PrivateData->HoleData[IndexHole].Size, + PrivateData->HoleData[IndexHole].Offset, + PrivateData->HoleData[IndexHole].OffsetPositive + ); + } +} + +/** + + Migrate Single PPI Pointer from the temporary memory to PEI installed memory. + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PrivateData Pointer to PeiCore's private data structure. + @param PpiPointer Pointer to Ppi + +**/ +VOID +ConvertSinglePpiPointer ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_PPI_LIST_POINTERS *PpiPointer + ) +{ + // + // 1. Convert the pointer to the PPI descriptor from the old TempRam + // to the relocated physical memory. + // It (for the pointer to the PPI descriptor) needs to be done before 2 (for + // the pointer to the GUID) and 3 (for the pointer to the PPI interface structure). + // + ConvertPointerInRanges (SecCoreData, PrivateData, &PpiPointer->Raw); + // + // 2. Convert the pointer to the GUID in the PPI or NOTIFY descriptor + // from the old TempRam to the relocated physical memory. + // + ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **)&PpiPointer->Ppi->Guid); + // + // 3. Convert the pointer to the PPI interface structure in the PPI descriptor + // from the old TempRam to the relocated physical memory. + // + ConvertPointerInRanges (SecCoreData, PrivateData, (VOID **)&PpiPointer->Ppi->Ppi); +} + +/** + + Migrate PPI Pointers from the temporary memory to PEI installed memory. + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PrivateData Pointer to PeiCore's private data structure. + +**/ +VOID +ConvertPpiPointers ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + UINT8 Index; + + // + // Convert normal PPIs. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + ConvertSinglePpiPointer ( + SecCoreData, + PrivateData, + &PrivateData->PpiData.PpiList.PpiPtrs[Index] + ); + } + + // + // Convert Callback Notification PPIs. + // + for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) { + ConvertSinglePpiPointer ( + SecCoreData, + PrivateData, + &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index] + ); + } + + // + // Convert Dispatch Notification PPIs. + // + for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) { + ConvertSinglePpiPointer ( + SecCoreData, + PrivateData, + &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index] + ); + } +} + +/** + + Migrate Notify Pointers inside an FV from temporary memory to permanent memory. + + @param PrivateData Pointer to PeiCore's private data structure. + @param OrgFvHandle Address of FV Handle in temporary memory. + @param FvHandle Address of FV Handle in permanent memory. + @param FvSize Size of the FV. + +**/ +VOID +ConvertPpiPointersFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN OrgFvHandle, + IN UINTN FvHandle, + IN UINTN FvSize + ) +{ + UINT8 Index; + UINTN Offset; + BOOLEAN OffsetPositive; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi; + UINT8 GuidIndex; + EFI_GUID *Guid; + EFI_GUID *GuidCheckList[2]; + + GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid; + GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid; + + if (FvHandle > OrgFvHandle) { + OffsetPositive = TRUE; + Offset = FvHandle - OrgFvHandle; + } else { + OffsetPositive = FALSE; + Offset = OrgFvHandle - FvHandle; + } + + DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n")); + DEBUG (( + DEBUG_VERBOSE, + " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n", + (UINTN)OrgFvHandle, + (UINTN)FvHandle, + FvSize + )); + DEBUG (( + DEBUG_VERBOSE, + " OrgFvHandle range: 0x%08x - 0x%08x\n", + OrgFvHandle, + OrgFvHandle + FvSize + )); + + for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) { + ConvertPointer ( + (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + ConvertPointer ( + (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + ConvertPointer ( + (VOID **)&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + } + + for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) { + ConvertPointer ( + (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + ConvertPointer ( + (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + ConvertPointer ( + (VOID **)&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + } + + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + ConvertPointer ( + (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + ConvertPointer ( + (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + ConvertPointer ( + (VOID **)&PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + + Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid; + for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) { + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) + { + FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi; + DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo)); + if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) { + ConvertPointer ( + (VOID **)&FvInfoPpi->FvInfo, + OrgFvHandle, + OrgFvHandle + FvSize, + Offset, + OffsetPositive + ); + DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo)); + } + + DEBUG ((DEBUG_VERBOSE, "\n")); + break; + } + } + } +} + +/** + + Dumps the PPI lists to debug output. + + @param PrivateData Points to PeiCore's private instance data. + +**/ +VOID +DumpPpiList ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + DEBUG_CODE_BEGIN (); + UINTN Index; + + if (PrivateData == NULL) { + return; + } + + for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) { + DEBUG (( + DEBUG_VERBOSE, + "CallbackNotify[%2d] {%g} at 0x%x (%a)\n", + Index, + PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid, + (UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw, + ( + !( + ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) && + (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop) + ) + ? "CAR" : "Post-Memory" + ) + )); + } + + for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) { + DEBUG (( + DEBUG_VERBOSE, + "DispatchNotify[%2d] {%g} at 0x%x (%a)\n", + Index, + PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid, + (UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw, + ( + !( + ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) && + (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop) + ) + ? "CAR" : "Post-Memory" + ) + )); + } + + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + DEBUG (( + DEBUG_VERBOSE, + "PPI[%2d] {%g} at 0x%x (%a)\n", + Index, + PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid, + (UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw, + ( + !( + ((EFI_PHYSICAL_ADDRESS)(UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) && + (((EFI_PHYSICAL_ADDRESS)((UINTN)PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop) + ) + ? "CAR" : "Post-Memory" + ) + )); + } + + DEBUG_CODE_END (); +} + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + @param Single TRUE if only single entry in the PpiList. + FALSE if the PpiList is ended with an entry which has the + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +InternalPeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN BOOLEAN Single + ) +{ + PEI_CORE_INSTANCE *PrivateData; + PEI_PPI_LIST *PpiListPointer; + UINTN Index; + UINTN LastCount; + VOID *TempPtr; + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + PpiListPointer = &PrivateData->PpiData.PpiList; + Index = PpiListPointer->CurrentCount; + LastCount = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for ( ; ;) { + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PpiListPointer->CurrentCount = LastCount; + DEBUG ((DEBUG_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + + if (Index >= PpiListPointer->MaxCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + PpiListPointer->PpiPtrs, + sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount + ); + PpiListPointer->PpiPtrs = TempPtr; + PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP; + } + + DEBUG ((DEBUG_INFO, "Install PPI: %g\n", PpiList->Guid)); + PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)PpiList; + Index++; + PpiListPointer->CurrentCount++; + + if (Single) { + // + // Only single entry in the PpiList. + // + break; + } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) + { + // + // Continue until the end of the PPI List. + // + break; + } + + // + // Go to the next descriptor. + // + PpiList++; + } + + // + // Process any callback level notifies for newly installed PPIs. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCount, + PpiListPointer->CurrentCount, + 0, + PrivateData->PpiData.CallbackNotifyList.CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + return InternalPeiInstallPpi (PeiServices, PpiList, FALSE); +} + +/** + + This function reinstalls an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties can + use to replace an interface of the same name in the protocol database with a + different interface. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS if the operation was successful + @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL + @retval EFI_INVALID_PARAMETER if NewPpi is not valid + @retval EFI_NOT_FOUND if the PPI was not in the database + +**/ +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) { + break; + } + } + + if (Index == PrivateData->PpiData.PpiList.CurrentCount) { + return EFI_NOT_FOUND; + } + + // + // Replace the old PPI with the new one. + // + DEBUG ((DEBUG_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); + PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *)NewPpi; + + // + // Process any callback level notifies for the newly installed PPI. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + 0, + PrivateData->PpiData.CallbackNotifyList.CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + Locate a given named PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Guid Pointer to GUID of the PPI. + @param Instance Instance Number to discover. + @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + @param Ppi Pointer to reference the found PPI + + @retval EFI_SUCCESS if the PPI is in the database + @retval EFI_NOT_FOUND if the PPI is not in the database + +**/ +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) + { + if (Instance == 0) { + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + return EFI_SUCCESS; + } + + Instance--; + } + } + + return EFI_NOT_FOUND; +} + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + @param Single TRUE if only single entry in the NotifyList. + FALSE if the NotifyList is ended with an entry which has the + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +InternalPeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList, + IN BOOLEAN Single + ) +{ + PEI_CORE_INSTANCE *PrivateData; + PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer; + UINTN CallbackNotifyIndex; + UINTN LastCallbackNotifyCount; + PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer; + UINTN DispatchNotifyIndex; + UINTN LastDispatchNotifyCount; + VOID *TempPtr; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList; + CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount; + LastCallbackNotifyCount = CallbackNotifyIndex; + + DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList; + DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount; + LastDispatchNotifyCount = DispatchNotifyIndex; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for ( ; ;) { + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount; + DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount; + DEBUG ((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) { + if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + CallbackNotifyListPointer->NotifyPtrs, + sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount + ); + CallbackNotifyListPointer->NotifyPtrs = TempPtr; + CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP; + } + + CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList; + CallbackNotifyIndex++; + CallbackNotifyListPointer->CurrentCount++; + } else { + if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + DispatchNotifyListPointer->NotifyPtrs, + sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount + ); + DispatchNotifyListPointer->NotifyPtrs = TempPtr; + DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP; + } + + DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *)NotifyList; + DispatchNotifyIndex++; + DispatchNotifyListPointer->CurrentCount++; + } + + DEBUG ((DEBUG_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + + if (Single) { + // + // Only single entry in the NotifyList. + // + break; + } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) + { + // + // Continue until the end of the Notify List. + // + break; + } + + // + // Go to the next descriptor. + // + NotifyList++; + } + + // + // Process any callback level notifies for all previously installed PPIs. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiList.CurrentCount, + LastCallbackNotifyCount, + CallbackNotifyListPointer->CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +{ + return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE); +} + +/** + + Process the Notify List at dispatch level. + + @param PrivateData PeiCore's private data structure. + +**/ +VOID +ProcessDispatchNotifyList ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + UINTN TempValue; + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previously installed PPIs. + // Use "while" instead of "if" since ProcessNotify can modify + // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have + // to iterate until the same. + // + while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) { + TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount; + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.PpiList.LastDispatchedCount, + PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount, + PrivateData->PpiData.DispatchNotifyList.CurrentCount + ); + PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue; + } + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since ProcessNotify can modify + // PpiList.CurrentCount (with InstallPpi) so we have to iterate + // until the same. + // + while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) { + TempValue = PrivateData->PpiData.PpiList.CurrentCount; + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.PpiList.LastDispatchedCount, + PrivateData->PpiData.PpiList.CurrentCount, + 0, + PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount + ); + PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue; + } + + if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) { + break; + } + } + + return; +} + +/** + + Process notifications. + + @param PrivateData PeiCore's private data structure + @param NotifyType Type of notify to fire. + @param InstallStartIndex Install Beginning index. + @param InstallStopIndex Install Ending index. + @param NotifyStartIndex Notify Beginning index. + @param NotifyStopIndex Notify Ending index. + +**/ +VOID +ProcessNotify ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +{ + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) { + if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) { + NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify; + } else { + NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify; + } + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) + { + DEBUG (( + DEBUG_INFO, + "Notify: PPI Guid: %g, Peim notify entry point: %p\n", + SearchGuid, + NotifyDescriptor->Notify + )); + NotifyDescriptor->Notify ( + (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), + NotifyDescriptor, + (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi + ); + } + } + } +} + +/** + Process PpiList from SEC phase. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + These PPI's will be installed and/or immediately signaled if they are notification type. + +**/ +VOID +ProcessPpiListFromSec ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + EFI_STATUS Status; + EFI_SEC_HOB_DATA_PPI *SecHobDataPpi; + EFI_HOB_GENERIC_HEADER *SecHobList; + + for ( ; ;) { + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) != 0) { + // + // It is a notification PPI. + // + Status = InternalPeiNotifyPpi (PeiServices, (CONST EFI_PEI_NOTIFY_DESCRIPTOR *)PpiList, TRUE); + ASSERT_EFI_ERROR (Status); + } else { + // + // It is a normal PPI. + // + Status = InternalPeiInstallPpi (PeiServices, PpiList, TRUE); + ASSERT_EFI_ERROR (Status); + } + + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + // + // Continue until the end of the PPI List. + // + break; + } + + PpiList++; + } + + // + // If the EFI_SEC_HOB_DATA_PPI is in the list of PPIs passed to the PEI entry point, + // the PEI Foundation will call the GetHobs() member function and install all HOBs + // returned into the HOB list. It does this after installing all PPIs passed from SEC + // into the PPI database and before dispatching any PEIMs. + // + Status = PeiLocatePpi (PeiServices, &gEfiSecHobDataPpiGuid, 0, NULL, (VOID **)&SecHobDataPpi); + if (!EFI_ERROR (Status)) { + Status = SecHobDataPpi->GetHobs (SecHobDataPpi, &SecHobList); + if (!EFI_ERROR (Status)) { + Status = PeiInstallSecHobData (PeiServices, SecHobList); + ASSERT_EFI_ERROR (Status); + } + } +} + +/** + + Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory. + + @param PrivateData Pointer to PeiCore's private data structure. + @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory. + +**/ +VOID +ConvertPeiCorePpiPointers ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_FV_HANDLE *CoreFvHandle + ) +{ + EFI_FV_FILE_INFO FileInfo; + EFI_PHYSICAL_ADDRESS OrgImageBase; + EFI_PHYSICAL_ADDRESS MigratedImageBase; + UINTN PeiCoreModuleSize; + EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + VOID *PeiCoreImageBase; + VOID *PeiCoreEntryPoint; + EFI_STATUS Status; + + PeiCoreFileHandle = NULL; + + // + // Find the PEI Core in the BFV in temporary memory. + // + Status = CoreFvHandle->FvPpi->FindFileByType ( + CoreFvHandle->FvPpi, + EFI_FV_FILETYPE_PEI_CORE, + CoreFvHandle->FvHandle, + &PeiCoreFileHandle + ); + ASSERT_EFI_ERROR (Status); + + if (!EFI_ERROR (Status)) { + Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeiCoreFileHandle, &FileInfo); + ASSERT_EFI_ERROR (Status); + + Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase); + ASSERT_EFI_ERROR (Status); + + // + // Find PEI Core EntryPoint in the BFV in temporary memory. + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, &PeiCoreEntryPoint); + ASSERT_EFI_ERROR (Status); + + OrgImageBase = (UINTN)PeiCoreImageBase; + MigratedImageBase = (UINTN)_ModuleEntryPoint - ((UINTN)PeiCoreEntryPoint - (UINTN)PeiCoreImageBase); + + // + // Size of loaded PEI_CORE in permanent memory. + // + PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN)OrgImageBase - (UINTN)FileInfo.Buffer); + + // + // Migrate PEI_CORE PPI pointers from temporary memory to newly + // installed PEI_CORE in permanent memory. + // + ConvertPpiPointersFv (PrivateData, (UINTN)OrgImageBase, (UINTN)MigratedImageBase, PeiCoreModuleSize); + } +} diff --git a/MdeModulePkg/Core/Pei/Reset/Reset.c b/MdeModulePkg/Core/Pei/Reset/Reset.c index a679cfecd0..6c98a72b7e 100644 --- a/MdeModulePkg/Core/Pei/Reset/Reset.c +++ b/MdeModulePkg/Core/Pei/Reset/Reset.c @@ -1,111 +1,111 @@ -/** @file
- Pei Core Reset System Support
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
-
- Core version of the Reset System
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
-
- @retval EFI_NOT_AVAILABLE_YET PPI not available yet.
- @retval EFI_DEVICE_ERROR Did not reset system.
- Otherwise, resets the system.
-
-**/
-EFI_STATUS
-EFIAPI
-PeiResetSystem (
- IN CONST EFI_PEI_SERVICES **PeiServices
- )
-{
- EFI_STATUS Status;
- EFI_PEI_RESET_PPI *ResetPpi;
-
- //
- // Attempt to use newer ResetSystem2(). If this returns, then ResetSystem2()
- // is not available.
- //
- PeiResetSystem2 (EfiResetCold, EFI_SUCCESS, 0, NULL);
-
- //
- // Look for PEI Reset System PPI
- //
- Status = PeiServicesLocatePpi (
- &gEfiPeiResetPpiGuid,
- 0,
- NULL,
- (VOID **)&ResetPpi
- );
- if (!EFI_ERROR (Status)) {
- return ResetPpi->ResetSystem (PeiServices);
- }
-
- //
- // Report Status Code that Reset PPI is not available.
- //
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MINOR,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PS_EC_RESET_NOT_AVAILABLE)
- );
-
- //
- // No reset PPIs are available yet.
- //
- return EFI_NOT_AVAILABLE_YET;
-}
-
-/**
- Resets the entire platform.
-
- @param[in] ResetType The type of reset to perform.
- @param[in] ResetStatus The status code for the reset.
- @param[in] DataSize The size, in bytes, of ResetData.
- @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown
- the data buffer starts with a Null-terminated string, optionally
- followed by additional binary data. The string is a description
- that the caller may use to further indicate the reason for the
- system reset.
-
-**/
-VOID
-EFIAPI
-PeiResetSystem2 (
- IN EFI_RESET_TYPE ResetType,
- IN EFI_STATUS ResetStatus,
- IN UINTN DataSize,
- IN VOID *ResetData OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_PEI_RESET2_PPI *Reset2Ppi;
-
- //
- // Look for PEI Reset System 2 PPI
- //
- Status = PeiServicesLocatePpi (
- &gEfiPeiReset2PpiGuid,
- 0,
- NULL,
- (VOID **)&Reset2Ppi
- );
- if (!EFI_ERROR (Status)) {
- Reset2Ppi->ResetSystem (ResetType, ResetStatus, DataSize, ResetData);
- return;
- }
-
- //
- // Report Status Code that Reset2 PPI is not available.
- //
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MINOR,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PS_EC_RESET_NOT_AVAILABLE)
- );
-}
+/** @file + Pei Core Reset System Support + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + Core version of the Reset System + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @retval EFI_NOT_AVAILABLE_YET PPI not available yet. + @retval EFI_DEVICE_ERROR Did not reset system. + Otherwise, resets the system. + +**/ +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PEI_RESET_PPI *ResetPpi; + + // + // Attempt to use newer ResetSystem2(). If this returns, then ResetSystem2() + // is not available. + // + PeiResetSystem2 (EfiResetCold, EFI_SUCCESS, 0, NULL); + + // + // Look for PEI Reset System PPI + // + Status = PeiServicesLocatePpi ( + &gEfiPeiResetPpiGuid, + 0, + NULL, + (VOID **)&ResetPpi + ); + if (!EFI_ERROR (Status)) { + return ResetPpi->ResetSystem (PeiServices); + } + + // + // Report Status Code that Reset PPI is not available. + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_PEI_CORE | EFI_SW_PS_EC_RESET_NOT_AVAILABLE) + ); + + // + // No reset PPIs are available yet. + // + return EFI_NOT_AVAILABLE_YET; +} + +/** + Resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. + +**/ +VOID +EFIAPI +PeiResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PEI_RESET2_PPI *Reset2Ppi; + + // + // Look for PEI Reset System 2 PPI + // + Status = PeiServicesLocatePpi ( + &gEfiPeiReset2PpiGuid, + 0, + NULL, + (VOID **)&Reset2Ppi + ); + if (!EFI_ERROR (Status)) { + Reset2Ppi->ResetSystem (ResetType, ResetStatus, DataSize, ResetData); + return; + } + + // + // Report Status Code that Reset2 PPI is not available. + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_PEI_CORE | EFI_SW_PS_EC_RESET_NOT_AVAILABLE) + ); +} diff --git a/MdeModulePkg/Core/Pei/Security/Security.c b/MdeModulePkg/Core/Pei/Security/Security.c index a771007b6a..fbe04eba93 100644 --- a/MdeModulePkg/Core/Pei/Security/Security.c +++ b/MdeModulePkg/Core/Pei/Security/Security.c @@ -1,146 +1,146 @@ -/** @file
- EFI PEI Core Security services
-
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
- &gEfiPeiSecurity2PpiGuid,
- SecurityPpiNotifyCallback
-};
-
-/**
- Initialize the security services.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param OldCoreData Pointer to the old core data.
- NULL if being run in non-permanent memory mode.
-
-**/
-VOID
-InitializeSecurityServices (
- IN EFI_PEI_SERVICES **PeiServices,
- IN PEI_CORE_INSTANCE *OldCoreData
- )
-{
- if (OldCoreData == NULL) {
- PeiServicesNotifyPpi (&mNotifyList);
- }
-
- return;
-}
-
-/**
-
- Provide a callback for when the security PPI is installed.
- This routine will cache installed security PPI into PeiCore's private data.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param NotifyDescriptor The descriptor for the notification event.
- @param Ppi Pointer to the PPI in question.
-
- @return Always success
-
-**/
-EFI_STATUS
-EFIAPI
-SecurityPpiNotifyCallback (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- )
-{
- PEI_CORE_INSTANCE *PrivateData;
-
- //
- // Get PEI Core private data
- //
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
-
- //
- // If there isn't a security PPI installed, use the one from notification
- //
- if (PrivateData->PrivateSecurityPpi == NULL) {
- PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY2_PPI *)Ppi;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Provide a callout to the security verification service.
-
- @param PrivateData PeiCore's private data structure
- @param VolumeHandle Handle of FV
- @param FileHandle Handle of PEIM's FFS
- @param AuthenticationStatus Authentication status
-
- @retval EFI_SUCCESS Image is OK
- @retval EFI_SECURITY_VIOLATION Image is illegal
- @retval EFI_NOT_FOUND If security PPI is not installed.
-**/
-EFI_STATUS
-VerifyPeim (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN EFI_PEI_FV_HANDLE VolumeHandle,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINT32 AuthenticationStatus
- )
-{
- EFI_STATUS Status;
- BOOLEAN DeferExecution;
-
- Status = EFI_NOT_FOUND;
- if (PrivateData->PrivateSecurityPpi == NULL) {
- //
- // Check AuthenticationStatus first.
- //
- if ((AuthenticationStatus & EFI_AUTH_STATUS_IMAGE_SIGNED) != 0) {
- if ((AuthenticationStatus & (EFI_AUTH_STATUS_TEST_FAILED | EFI_AUTH_STATUS_NOT_TESTED)) != 0) {
- Status = EFI_SECURITY_VIOLATION;
- }
- }
- } else {
- //
- // Check to see if the image is OK
- //
- Status = PrivateData->PrivateSecurityPpi->AuthenticationState (
- (CONST EFI_PEI_SERVICES **)&PrivateData->Ps,
- PrivateData->PrivateSecurityPpi,
- AuthenticationStatus,
- VolumeHandle,
- FileHandle,
- &DeferExecution
- );
- if (DeferExecution) {
- Status = EFI_SECURITY_VIOLATION;
- }
- }
-
- return Status;
-}
-
-/**
- Verify a Firmware volume.
-
- @param CurrentFvAddress Pointer to the current Firmware Volume under consideration
-
- @retval EFI_SUCCESS Firmware Volume is legal
-
-**/
-EFI_STATUS
-VerifyFv (
- IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress
- )
-{
- //
- // Right now just pass the test. Future can authenticate and/or check the
- // FV-header or other metric for goodness of binary.
- //
- return EFI_SUCCESS;
-}
+/** @file + EFI PEI Core Security services + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiSecurity2PpiGuid, + SecurityPpiNotifyCallback +}; + +/** + Initialize the security services. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldCoreData Pointer to the old core data. + NULL if being run in non-permanent memory mode. + +**/ +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +{ + if (OldCoreData == NULL) { + PeiServicesNotifyPpi (&mNotifyList); + } + + return; +} + +/** + + Provide a callback for when the security PPI is installed. + This routine will cache installed security PPI into PeiCore's private data. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyDescriptor The descriptor for the notification event. + @param Ppi Pointer to the PPI in question. + + @return Always success + +**/ +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Get PEI Core private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // If there isn't a security PPI installed, use the one from notification + // + if (PrivateData->PrivateSecurityPpi == NULL) { + PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY2_PPI *)Ppi; + } + + return EFI_SUCCESS; +} + +/** + Provide a callout to the security verification service. + + @param PrivateData PeiCore's private data structure + @param VolumeHandle Handle of FV + @param FileHandle Handle of PEIM's FFS + @param AuthenticationStatus Authentication status + + @retval EFI_SUCCESS Image is OK + @retval EFI_SECURITY_VIOLATION Image is illegal + @retval EFI_NOT_FOUND If security PPI is not installed. +**/ +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINT32 AuthenticationStatus + ) +{ + EFI_STATUS Status; + BOOLEAN DeferExecution; + + Status = EFI_NOT_FOUND; + if (PrivateData->PrivateSecurityPpi == NULL) { + // + // Check AuthenticationStatus first. + // + if ((AuthenticationStatus & EFI_AUTH_STATUS_IMAGE_SIGNED) != 0) { + if ((AuthenticationStatus & (EFI_AUTH_STATUS_TEST_FAILED | EFI_AUTH_STATUS_NOT_TESTED)) != 0) { + Status = EFI_SECURITY_VIOLATION; + } + } + } else { + // + // Check to see if the image is OK + // + Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( + (CONST EFI_PEI_SERVICES **)&PrivateData->Ps, + PrivateData->PrivateSecurityPpi, + AuthenticationStatus, + VolumeHandle, + FileHandle, + &DeferExecution + ); + if (DeferExecution) { + Status = EFI_SECURITY_VIOLATION; + } + } + + return Status; +} + +/** + Verify a Firmware volume. + + @param CurrentFvAddress Pointer to the current Firmware Volume under consideration + + @retval EFI_SUCCESS Firmware Volume is legal + +**/ +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +{ + // + // Right now just pass the test. Future can authenticate and/or check the + // FV-header or other metric for goodness of binary. + // + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c b/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c index 94e6e114ef..fd506814cf 100644 --- a/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c +++ b/MdeModulePkg/Core/Pei/StatusCode/StatusCode.c @@ -1,65 +1,65 @@ -/** @file
- Pei Core Status Code Support
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PeiMain.h"
-
-/**
-
- Core version of the Status Code reporter
-
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param CodeType Type of Status Code.
- @param Value Value to output for Status Code.
- @param Instance Instance Number of this status code.
- @param CallerId ID of the caller of this status code.
- @param Data Optional data associated with this status code.
-
- @retval EFI_SUCCESS if status code is successfully reported
- @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed
-
-**/
-EFI_STATUS
-EFIAPI
-PeiReportStatusCode (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_STATUS_CODE_TYPE CodeType,
- IN EFI_STATUS_CODE_VALUE Value,
- IN UINT32 Instance,
- IN CONST EFI_GUID *CallerId,
- IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_PEI_PROGRESS_CODE_PPI *StatusCodePpi;
-
- //
- // Locate StatusCode Ppi.
- //
- Status = PeiServicesLocatePpi (
- &gEfiPeiStatusCodePpiGuid,
- 0,
- NULL,
- (VOID **)&StatusCodePpi
- );
-
- if (!EFI_ERROR (Status)) {
- Status = StatusCodePpi->ReportStatusCode (
- PeiServices,
- CodeType,
- Value,
- Instance,
- CallerId,
- Data
- );
-
- return Status;
- }
-
- return EFI_NOT_AVAILABLE_YET;
-}
+/** @file + Pei Core Status Code Support + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + Core version of the Status Code reporter + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Type of Status Code. + @param Value Value to output for Status Code. + @param Instance Instance Number of this status code. + @param CallerId ID of the caller of this status code. + @param Data Optional data associated with this status code. + + @retval EFI_SUCCESS if status code is successfully reported + @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +**/ +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PEI_PROGRESS_CODE_PPI *StatusCodePpi; + + // + // Locate StatusCode Ppi. + // + Status = PeiServicesLocatePpi ( + &gEfiPeiStatusCodePpiGuid, + 0, + NULL, + (VOID **)&StatusCodePpi + ); + + if (!EFI_ERROR (Status)) { + Status = StatusCodePpi->ReportStatusCode ( + PeiServices, + CodeType, + Value, + Instance, + CallerId, + Data + ); + + return Status; + } + + return EFI_NOT_AVAILABLE_YET; +} |
