Date   

[PATCH v4 7/9] UefiCpuPkg/CpuMpPei: Enable paging and set NP flag to avoid TOCTOU (CVE-2019-11098)

Guomin Jiang
 

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

To avoid the TOCTOU, enable paging and set Not Present flag so when
access any code in the flash range, it will trigger #NP exception.

Cc: Eric Dong <eric.dong@...>
Cc: Ray Ni <ray.ni@...>
Cc: Laszlo Ersek <lersek@...>
Cc: Rahul Kumar <rahul1.kumar@...>
Signed-off-by: Guomin Jiang <guomin.jiang@...>
---
UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 3 +++
UefiCpuPkg/CpuMpPei/CpuPaging.c | 26 ++++++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
index f4d11b861f77..7e511325d8b8 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
@@ -46,6 +46,9 @@ [LibraryClasses]
BaseMemoryLib
CpuLib

+[Guids]
+ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB
+
[Ppis]
gEfiPeiMpServicesPpiGuid ## PRODUCES
gEfiSecPlatformInformationPpiGuid ## SOMETIMES_CONSUMES
diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c
index 3bf0574b34c6..04a16fb2b620 100644
--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c
+++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c
@@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/MemoryAllocationLib.h>
#include <Library/CpuLib.h>
#include <Library/BaseLib.h>
+#include <Guid/MigratedFvInfo.h>

#include "CpuMpPei.h"

@@ -605,6 +606,8 @@ MemoryDiscoveredPpiNotifyCallback (
EFI_STATUS Status;
BOOLEAN InitStackGuard;
BOOLEAN InterruptState;
+ EDKII_MIGRATED_FV_INFO *MigratedFvInfo;
+ EFI_PEI_HOB_POINTERS Hob;

if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
InterruptState = SaveAndDisableInterrupts ();
@@ -619,9 +622,14 @@ MemoryDiscoveredPpiNotifyCallback (
// the task switch (for the sake of stack switch).
//
InitStackGuard = FALSE;
- if (IsIa32PaeSupported () && PcdGetBool (PcdCpuStackGuard)) {
+ Hob.Raw = NULL;
+ if (IsIa32PaeSupported ()) {
+ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
+ InitStackGuard = PcdGetBool (PcdCpuStackGuard);
+ }
+
+ if (InitStackGuard || Hob.Raw != NULL) {
EnablePaging ();
- InitStackGuard = TRUE;
}

Status = InitializeCpuMpWorker ((CONST EFI_PEI_SERVICES **)PeiServices);
@@ -631,6 +639,20 @@ MemoryDiscoveredPpiNotifyCallback (
SetupStackGuardPage ();
}

+ while (Hob.Raw != NULL) {
+ MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
+
+ //
+ // Enable #NP exception, so if the code access after disable NEM, it will generate
+ // to avoid potential vulnerability.
+ //
+ ConvertMemoryPageAttributes (MigratedFvInfo->FvOrgBase, MigratedFvInfo->FvLength, 0);
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
+ }
+ CpuFlushTlb ();
+
return Status;
}

--
2.25.1.windows.1


[PATCH v4 6/9] SecurityPkg/Tcg2Pei: Use Migrated FV Info Hob for calculating hash (CVE-2019-11098)

Guomin Jiang
 

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

When we allocate pool to save rebased the PEIMs, the address will change
randomly, therefore the hash will change and result PCR0 change as well.
To avoid this, we save the raw PEIMs and use it to calculate hash.
The Tcg2Pei calculate the hash and it use the Migrated FV Info.

Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jian J Wang <jian.j.wang@...>
Cc: Chao Zhang <chao.b.zhang@...>
Cc: Qi Zhang <qi1.zhang@...>
Cc: Rahul Kumar <rahul1.kumar@...>
Signed-off-by: Guomin Jiang <guomin.jiang@...>
---
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf | 1 +
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 31 ++++++++++++++++++++++++++---
2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
index 3d361e8859e7..367df21eedaf 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -63,6 +63,7 @@ [Guids]
gTcgEvent2EntryHobGuid ## PRODUCES ## HOB
gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier
gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier
+ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB

[Ppis]
gEfiPeiFirmwareVolumeInfoPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
index 4852d8690617..651a60c1f0e2 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
@@ -21,6 +21,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Guid/TcgEventHob.h>
#include <Guid/MeasuredFvHob.h>
#include <Guid/TpmInstance.h>
+#include <Guid/MigratedFvInfo.h>

#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
@@ -536,6 +537,10 @@ MeasureFvImage (
EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI *PrehashedFvPpi;
HASH_INFO *PreHashInfo;
UINT32 HashAlgoMask;
+ EFI_PHYSICAL_ADDRESS FvOrgBase;
+ EFI_PHYSICAL_ADDRESS FvDataBase;
+ EFI_PEI_HOB_POINTERS Hob;
+ EDKII_MIGRATED_FV_INFO *MigratedFvInfo;

//
// Check Excluded FV list
@@ -621,6 +626,26 @@ MeasureFvImage (
Instance++;
} while (!EFI_ERROR(Status));

+ //
+ // Search the matched migration FV info
+ //
+ FvOrgBase = FvBase;
+ FvDataBase = FvBase;
+ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
+ while (Hob.Raw != NULL) {
+ MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
+ if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) {
+ //
+ // Found the migrated FV info
+ //
+ FvOrgBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase;
+ FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase;
+ break;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
+ }
+
//
// Init the log event for FV measurement
//
@@ -631,13 +656,13 @@ MeasureFvImage (
if (FvName != NULL) {
AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);
}
- FvBlob2.BlobBase = FvBase;
+ FvBlob2.BlobBase = FvOrgBase;
FvBlob2.BlobLength = FvLength;
TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
TcgEventHdr.EventSize = sizeof (FvBlob2);
EventData = &FvBlob2;
} else {
- FvBlob.BlobBase = FvBase;
+ FvBlob.BlobBase = FvOrgBase;
FvBlob.BlobLength = FvLength;
TcgEventHdr.PCRIndex = 0;
TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
@@ -672,7 +697,7 @@ MeasureFvImage (
//
Status = HashLogExtendEvent (
0,
- (UINT8*) (UINTN) FvBase, // HashData
+ (UINT8*) (UINTN) FvDataBase, // HashData
(UINTN) FvLength, // HashDataLen
&TcgEventHdr, // EventHdr
EventData // EventData
--
2.25.1.windows.1


[PATCH v4 5/9] MdeModulePkg/Core: Create Migrated FV Info Hob for calculating hash (CVE-2019-11098)

Guomin Jiang
 

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

When we allocate pool to save the rebased PEIMs, the address will change
randomly, therefore the hash will change and result PCR0 change as well.
To avoid this, we save the raw PEIMs and use it to calculate hash.

The MigratedFvInfo HOB will never produce when
PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control
the total feature.

Cc: Jian J Wang <jian.j.wang@...>
Cc: Hao A Wu <hao.a.wu@...>
Cc: Dandan Bi <dandan.bi@...>
Cc: Liming Gao <liming.gao@...>
Cc: Debkumar De <debkumar.de@...>
Cc: Harry Han <harry.han@...>
Cc: Catharine West <catharine.west@...>
Signed-off-by: Guomin Jiang <guomin.jiang@...>
---
MdeModulePkg/MdeModulePkg.dec | 3 ++
MdeModulePkg/Core/Pei/PeiMain.inf | 1 +
MdeModulePkg/Core/Pei/PeiMain.h | 1 +
MdeModulePkg/Include/Guid/MigratedFvInfo.h | 22 +++++++++++++++
MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 28 +++++++++++++++++++
5 files changed, 55 insertions(+)
create mode 100644 MdeModulePkg/Include/Guid/MigratedFvInfo.h

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 16db17d0a873..40197dba862c 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -389,6 +389,9 @@ [Guids]
## GUID indicates the capsule is to store Capsule On Disk file names.
gEdkiiCapsuleOnDiskNameGuid = { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93, 0x9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } }

+ ## Include/Guid/MigratedFvInfo.h
+ gEdkiiMigratedFvInfoGuid = { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf4, 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } }
+
[Ppis]
## Include/Ppi/AtaController.h
gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf
index 5b36d516b3fa..0cf357371a16 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -77,6 +77,7 @@ [Guids]
## 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

[Ppis]
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index b0101dba5e30..cbf74d5b9d9a 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -44,6 +44,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#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
diff --git a/MdeModulePkg/Include/Guid/MigratedFvInfo.h b/MdeModulePkg/Include/Guid/MigratedFvInfo.h
new file mode 100644
index 000000000000..061c17ed0e48
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/MigratedFvInfo.h
@@ -0,0 +1,22 @@
+/** @file
+ Migrated FV information
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EDKII_MIGRATED_FV_INFO_GUID_H__
+#define __EDKII_MIGRATED_FV_INFO_GUID_H__
+
+typedef struct {
+ UINT32 FvOrgBase; // original FV address
+ UINT32 FvNewBase; // new FV address
+ UINT32 FvDataBase; // original FV data
+ UINT32 FvLength; // Fv Length
+} EDKII_MIGRATED_FV_INFO;
+
+extern EFI_GUID gEdkiiMigratedFvInfoGuid;
+
+#endif // #ifndef __EDKII_MIGRATED_FV_INFO_GUID_H__
+
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index ef88b3423376..f654cea15c59 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -1223,10 +1223,12 @@ EvacuateTempRam (
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;
+ EDKII_MIGRATED_FV_INFO MigratedFvInfo;

ASSERT (Private->PeiMemoryInstalled);

@@ -1263,6 +1265,9 @@ EvacuateTempRam (
(((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)
)
) {
+ //
+ // Allocate page to save the rebased PEIMs, the PEIMs will get control later
+ //
Status = PeiServicesAllocatePages (
EfiBootServicesCode,
EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
@@ -1270,6 +1275,17 @@ EvacuateTempRam (
);
ASSERT_EFI_ERROR (Status);

+ //
+ // Allocate pool to save the raw PEIMs, it used to keep consistent context across
+ // multiple boot and PCR0 will keep same no matter if allocate random page address.
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
+ (EFI_PHYSICAL_ADDRESS *) &RawDataFvHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
DEBUG ((
DEBUG_VERBOSE,
" Migrating FV[%d] from 0x%08X to 0x%08X\n",
@@ -1278,7 +1294,19 @@ EvacuateTempRam (
(UINTN) MigratedFvHeader
));

+ //
+ // Copy the context to the rebased pages and raw pages, and create hob to save the
+ // information. the MigratedFvInfo HOB will never produce when
+ // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the
+ // feature.
+ //
CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);
+ CopyMem (RawDataFvHeader, MigratedFvHeader, (UINTN) FvHeader->FvLength);
+ MigratedFvInfo.FvOrgBase = (UINT32) (UINTN) FvHeader;
+ MigratedFvInfo.FvNewBase = (UINT32) (UINTN) MigratedFvHeader;
+ MigratedFvInfo.FvDataBase = (UINT32) (UINTN) RawDataFvHeader;
+ MigratedFvInfo.FvLength = (UINT32) (UINTN) FvHeader->FvLength;
+ BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo));

//
// Migrate any children for this FV now
--
2.25.1.windows.1


[PATCH v4 4/9] UefiCpuPkg/SecMigrationPei: Add initial PEIM (CVE-2019-11098)

Guomin Jiang
 

From: Michael Kubacki <michael.a.kubacki@...>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

Adds a PEIM that republishes structures produced in SEC. This
is done because SEC modules may not be shadowed in some platforms
due to space constraints or special alignment requirements. The
SecMigrationPei module locates interfaces that may be published in
SEC and reinstalls the interface with permanent memory addresses.

This is important if pre-memory address access is forbidden after
memory initialization and data such as a PPI descriptor, PPI GUID,
or PPI inteface reside in pre-memory.

Cc: Eric Dong <eric.dong@...>
Cc: Ray Ni <ray.ni@...>
Cc: Laszlo Ersek <lersek@...>
Cc: Rahul Kumar <rahul1.kumar@...>
Cc: Debkumar De <debkumar.de@...>
Cc: Harry Han <harry.han@...>
Cc: Catharine West <catharine.west@...>
Signed-off-by: Michael Kubacki <michael.a.kubacki@...>
---
UefiCpuPkg/UefiCpuPkg.dec | 4 +
UefiCpuPkg/UefiCpuPkg.dsc | 1 +
UefiCpuPkg/SecCore/SecCore.inf | 2 +
.../SecMigrationPei/SecMigrationPei.inf | 67 ++++
UefiCpuPkg/Include/Ppi/RepublishSecPpi.h | 54 +++
UefiCpuPkg/SecCore/SecMain.h | 1 +
UefiCpuPkg/SecMigrationPei/SecMigrationPei.h | 154 +++++++
UefiCpuPkg/SecCore/SecMain.c | 26 +-
UefiCpuPkg/SecMigrationPei/SecMigrationPei.c | 378 ++++++++++++++++++
.../SecMigrationPei/SecMigrationPei.uni | 13 +
10 files changed, 698 insertions(+), 2 deletions(-)
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
create mode 100644 UefiCpuPkg/Include/Ppi/RepublishSecPpi.h
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.h
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.c
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni

diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index 762badf5d239..0a005bd20311 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -66,6 +66,10 @@ [Guids]
## Include/Guid/MicrocodePatchHob.h
gEdkiiMicrocodePatchHobGuid = { 0xd178f11d, 0x8716, 0x418e, { 0xa1, 0x31, 0x96, 0x7d, 0x2a, 0xc4, 0x28, 0x43 }}

+[Ppis]
+ ## Include/Ppi/RepublishSecPpi.h
+ gRepublishSecPpiPpiGuid = { 0x27a71b1e, 0x73ee, 0x43d6, { 0xac, 0xe3, 0x52, 0x1a, 0x2d, 0xc5, 0xd0, 0x92 }}
+
[Protocols]
## Include/Protocol/SmmCpuService.h
gEfiSmmCpuServiceProtocolGuid = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index afa304128221..964720048dd7 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -146,6 +146,7 @@ [Components.IA32, Components.X64]
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
UefiCpuPkg/SecCore/SecCore.inf
+ UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf {
<Defines>
diff --git a/UefiCpuPkg/SecCore/SecCore.inf b/UefiCpuPkg/SecCore/SecCore.inf
index 0562820c95e0..545781d6b4b3 100644
--- a/UefiCpuPkg/SecCore/SecCore.inf
+++ b/UefiCpuPkg/SecCore/SecCore.inf
@@ -68,6 +68,8 @@ [Ppis]
## SOMETIMES_CONSUMES
gPeiSecPerformancePpiGuid
gEfiPeiCoreFvLocationPpiGuid
+ ## CONSUMES
+ gRepublishSecPpiPpiGuid

[Guids]
## SOMETIMES_PRODUCES ## HOB
diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
new file mode 100644
index 000000000000..f4c2f6b658fb
--- /dev/null
+++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
@@ -0,0 +1,67 @@
+## @file
+# Migrates SEC structures after permanent memory is installed.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecMigrationPei
+ MODULE_UNI_FILE = SecMigrationPei.uni
+ FILE_GUID = 58B35361-8922-41BC-B313-EF7ED9ADFDF7
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SecMigrationPeiInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ SecMigrationPei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ MemoryAllocationLib
+ PeimEntryPoint
+ PeiServicesLib
+ PeiServicesTablePointerLib
+
+[Ppis]
+ ## PRODUCES
+ gRepublishSecPpiPpiGuid
+
+ ## SOMETIMES_PRODUCES
+ gEfiTemporaryRamDonePpiGuid
+
+ ## SOMETIME_PRODUCES
+ gEfiTemporaryRamSupportPpiGuid
+
+ ## SOMETIMES_PRODUCES
+ gPeiSecPerformancePpiGuid
+
+ ## SOMETIMES_CONSUMES
+ ## PRODUCES
+ gEfiSecPlatformInformationPpiGuid
+
+ ## SOMETIMES_CONSUMES
+ ## SOMETIMES_PRODUCES
+ gEfiSecPlatformInformation2PpiGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
+
+[Depex]
+ TRUE
diff --git a/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h b/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h
new file mode 100644
index 000000000000..ea865acbb5c8
--- /dev/null
+++ b/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h
@@ -0,0 +1,54 @@
+/** @file
+ This file declares Sec Platform Information PPI.
+
+ This service is the primary handoff state into the PEI Foundation.
+ The Security (SEC) component creates the early, transitory memory
+ environment and also encapsulates knowledge of at least the
+ location of the Boot Firmware Volume (BFV).
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This PPI is introduced in PI Version 1.0.
+
+**/
+
+#ifndef __REPUBLISH_SEC_PPI_H__
+#define __REPUBLISH_SEC_PPI_H__
+
+#include <Pi/PiPeiCis.h>
+
+#define REPUBLISH_SEC_PPI_PPI_GUID \
+ { \
+ 0x27a71b1e, 0x73ee, 0x43d6, { 0xac, 0xe3, 0x52, 0x1a, 0x2d, 0xc5, 0xd0, 0x92 } \
+ }
+
+typedef struct _REPUBLISH_SEC_PPI_PPI REPUBLISH_SEC_PPI_PPI;
+
+/**
+ This interface re-installs PPIs installed in SecCore from a post-memory PEIM.
+
+ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory
+ copy from a PEIM that has been shadowed to permanent memory.
+
+ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully.
+ @retval Others An error occurred re-installing the SecCore PPIs.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *REPUBLISH_SEC_PPI_REPUBLISH_SEC_PPIS)(
+ VOID
+ );
+
+///
+/// Republish SEC PPIs
+///
+struct _REPUBLISH_SEC_PPI_PPI {
+ REPUBLISH_SEC_PPI_REPUBLISH_SEC_PPIS RepublishSecPpis;
+};
+
+extern EFI_GUID gRepublishSecPpiPpiGuid;
+
+#endif
diff --git a/UefiCpuPkg/SecCore/SecMain.h b/UefiCpuPkg/SecCore/SecMain.h
index e8c05d713668..e20bcf86532c 100644
--- a/UefiCpuPkg/SecCore/SecMain.h
+++ b/UefiCpuPkg/SecCore/SecMain.h
@@ -15,6 +15,7 @@
#include <Ppi/TemporaryRamDone.h>
#include <Ppi/SecPerformance.h>
#include <Ppi/PeiCoreFvLocation.h>
+#include <Ppi/RepublishSecPpi.h>

#include <Guid/FirmwarePerformance.h>

diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h
new file mode 100644
index 000000000000..414672a5afe6
--- /dev/null
+++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h
@@ -0,0 +1,154 @@
+/** @file
+ Migrates SEC structures after permanent memory is installed.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __SEC_MIGRATION_H__
+#define __SEC_MIGRATION_H__
+
+#include <Base.h>
+
+#include <Pi/PiPeiCis.h>
+#include <Ppi/RepublishSecPpi.h>
+#include <Ppi/SecPerformance.h>
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/SecPlatformInformation2.h>
+#include <Ppi/TemporaryRamDone.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer.
+ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformationPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+/**
+ Re-installs the SEC Platform Information PPIs to implementation in this module to support post-memory.
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The SEC Platform Information PPI could not be re-installed.
+ @return Others An error occurred during PPI re-install.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformationPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ This interface re-installs PPIs installed in SecCore from a post-memory PEIM.
+
+ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory
+ copy from a PEIM that has been shadowed to permanent memory.
+
+ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully.
+ @retval Others An error occurred re-installing the SecCore PPIs.
+
+**/
+EFI_STATUS
+EFIAPI
+RepublishSecPpis (
+ VOID
+ );
+
+/**
+ Disables the use of Temporary RAM.
+
+ If present, this service is invoked by the PEI Foundation after
+ the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
+
+ @retval EFI_SUCCESS Use of Temporary RAM was disabled.
+ @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamDonePostMemory (
+ VOID
+ );
+
+/**
+ This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupportPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The performance data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPerformancePostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ );
+
+typedef struct {
+ UINT64 StructureSize;
+ EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord;
+} SEC_PLATFORM_INFORMATION_CONTEXT;
+
+typedef struct {
+ EFI_HOB_GUID_TYPE Header;
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ FIRMWARE_SEC_PERFORMANCE FirmwareSecPerformance;
+ SEC_PLATFORM_INFORMATION_CONTEXT Context;
+} SEC_PLATFORM_INFORMATION_CONTEXT_HOB;
+
+#endif
diff --git a/UefiCpuPkg/SecCore/SecMain.c b/UefiCpuPkg/SecCore/SecMain.c
index 5d5e7f17dced..155be49a6011 100644
--- a/UefiCpuPkg/SecCore/SecMain.c
+++ b/UefiCpuPkg/SecCore/SecMain.c
@@ -370,13 +370,35 @@ SecTemporaryRamDone (
VOID
)
{
- BOOLEAN State;
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+ UINTN Index;
+ BOOLEAN State;
+ EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;
+ REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi;

//
// Republish Sec Platform Information(2) PPI
//
RepublishSecPlatformInformationPpi ();

+ //
+ // Re-install SEC PPIs using a PEIM produced service if published
+ //
+ for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) {
+ Status = PeiServicesLocatePpi (
+ &gRepublishSecPpiPpiGuid,
+ Index,
+ &PeiPpiDescriptor,
+ (VOID **) &RepublishSecPpiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index));
+ Status2 = RepublishSecPpiPpi->RepublishSecPpis ();
+ ASSERT_EFI_ERROR (Status2);
+ }
+ }
+
//
// Migrate DebugAgentContext.
//
@@ -385,7 +407,7 @@ SecTemporaryRamDone (
//
// Disable interrupts and save current interrupt state
//
- State = SaveAndDisableInterrupts();
+ State = SaveAndDisableInterrupts ();

//
// Disable Temporary RAM after Stack and Heap have been migrated at this point.
diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c
new file mode 100644
index 000000000000..d764fcacb504
--- /dev/null
+++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c
@@ -0,0 +1,378 @@
+/** @file
+ Migrates SEC structures after permanent memory is installed.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+#include "SecMigrationPei.h"
+
+STATIC REPUBLISH_SEC_PPI_PPI mEdkiiRepublishSecPpiPpi = {
+ RepublishSecPpis
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPostMemoryPpi = {
+ SecPlatformInformationPostMemory
+ };
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_TEMPORARY_RAM_DONE_PPI mSecTemporaryRamDonePostMemoryPpi = {
+ SecTemporaryRamDonePostMemory
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPostMemoryPpi = {
+ SecTemporaryRamSupportPostMemory
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED PEI_SEC_PERFORMANCE_PPI mSecPerformancePpi = {
+ GetPerformancePostMemory
+ };
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mEdkiiRepublishSecPpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gRepublishSecPpiPpiGuid,
+ &mEdkiiRepublishSecPpiPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecPlatformInformationPostMemoryDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiSecPlatformInformationPpiGuid,
+ &mSecPlatformInformationPostMemoryPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecTemporaryRamDonePostMemoryDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamDonePpiGuid,
+ &mSecTemporaryRamDonePostMemoryPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecTemporaryRamSupportPostMemoryDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamSupportPpiGuid,
+ &mSecTemporaryRamSupportPostMemoryPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecPerformancePpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiSecPerformancePpiGuid,
+ &mSecPerformancePpi
+ };
+
+/**
+ Disables the use of Temporary RAM.
+
+ If present, this service is invoked by the PEI Foundation after
+ the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
+
+ @retval EFI_SUCCESS Use of Temporary RAM was disabled.
+ @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamDonePostMemory (
+ VOID
+ )
+{
+ //
+ // Temporary RAM Done is already done in post-memory
+ // install a stub function that is located in permanent memory
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupportPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ //
+ // Temporary RAM Support is already done in post-memory
+ // install a stub function that is located in permanent memory
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The performance data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPerformancePostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ )
+{
+ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContexHob;
+
+ if (This == NULL || Performance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SecPlatformInformationContexHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ if (SecPlatformInformationContexHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Performance->ResetEnd = SecPlatformInformationContexHob->FirmwareSecPerformance.ResetEnd;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer.
+ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformationPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ )
+{
+ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContexHob;
+
+ if (StructureSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SecPlatformInformationContexHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ if (SecPlatformInformationContexHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*StructureSize < SecPlatformInformationContexHob->Context.StructureSize) {
+ *StructureSize = SecPlatformInformationContexHob->Context.StructureSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (PlatformInformationRecord == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *StructureSize = SecPlatformInformationContexHob->Context.StructureSize;
+ CopyMem (
+ (VOID *) PlatformInformationRecord,
+ (VOID *) SecPlatformInformationContexHob->Context.PlatformInformationRecord,
+ (UINTN) SecPlatformInformationContexHob->Context.StructureSize
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface re-installs PPIs installed in SecCore from a post-memory PEIM.
+
+ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory
+ copy from a PEIM that has been shadowed to permanent memory.
+
+ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully.
+ @retval Others An error occurred re-installing the SecCore PPIs.
+
+**/
+EFI_STATUS
+EFIAPI
+RepublishSecPpis (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;
+ VOID *PeiPpi;
+ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContextHob;
+ EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformationPtr;
+ UINT64 SecStructureSize;
+
+ SecPlatformInformationPtr = NULL;
+ SecStructureSize = 0;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiTemporaryRamDonePpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecTemporaryRamDonePostMemoryDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiTemporaryRamSupportPpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecTemporaryRamSupportPostMemoryDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = PeiServicesCreateHob (
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof (SEC_PLATFORM_INFORMATION_CONTEXT_HOB),
+ (VOID **) &SecPlatformInformationContextHob
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SecPlatformInformation Context HOB could not be created.\n"));
+ return Status;
+ }
+
+ SecPlatformInformationContextHob->Header.Name = gEfiCallerIdGuid;
+ SecPlatformInformationContextHob->Revision = 1;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSecPerformancePpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = ((PEI_SEC_PERFORMANCE_PPI *) PeiPpi)->GetPerformance (
+ GetPeiServicesTablePointer (),
+ (PEI_SEC_PERFORMANCE_PPI *) PeiPpi,
+ &SecPlatformInformationContextHob->FirmwareSecPerformance
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecPerformancePpiDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiSecPlatformInformationPpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = ((EFI_SEC_PLATFORM_INFORMATION_PPI *) PeiPpi)->PlatformInformation (
+ GetPeiServicesTablePointer (),
+ &SecStructureSize,
+ SecPlatformInformationPtr
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ZeroMem ((VOID *) &(SecPlatformInformationContextHob->Context), sizeof (SEC_PLATFORM_INFORMATION_CONTEXT));
+ SecPlatformInformationContextHob->Context.PlatformInformationRecord = AllocatePool ((UINTN) SecStructureSize);
+ ASSERT (SecPlatformInformationContextHob->Context.PlatformInformationRecord != NULL);
+ if (SecPlatformInformationContextHob->Context.PlatformInformationRecord == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SecPlatformInformationContextHob->Context.StructureSize = SecStructureSize;
+
+ Status = ((EFI_SEC_PLATFORM_INFORMATION_PPI *) PeiPpi)->PlatformInformation (
+ GetPeiServicesTablePointer (),
+ &(SecPlatformInformationContextHob->Context.StructureSize),
+ SecPlatformInformationContextHob->Context.PlatformInformationRecord
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecPlatformInformationPostMemoryDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the entry point which installs an instance of REPUBLISH_SEC_PPI_PPI.
+
+ It install the RepublishSecPpi depent on PcdMigrateTemporaryRamFirmwareVolumes, install
+ the PPI when the PcdMigrateTemporaryRamFirmwareVolumes enabled.
+
+ @param[in] FileHandle Pointer to image file handle.
+ @param[in] PeiServices Pointer to PEI Services Table
+
+ @retval EFI_SUCCESS An instance of REPUBLISH_SEC_PPI_PPI was installed successfully or
+ PcdMigrateTemporaryRamFirmwareVolumes is disabled.
+ @retval Others An error occurred installing and instance of REPUBLISH_SEC_PPI_PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+SecMigrationPeiInitialize (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ Status = PeiServicesInstallPpi (&mEdkiiRepublishSecPpiDescriptor);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni
new file mode 100644
index 000000000000..62c2064ba217
--- /dev/null
+++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Migrates SEC structures after permanent memory is installed.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Migrates SEC structures after permanent memory is installed"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Migrates SEC structures after permanent memory is installed."
+
--
2.25.1.windows.1


[PATCH v4 3/9] UefiCpuPkg/CpuMpPei: Add GDT and IDT migration support (CVE-2019-11098)

Guomin Jiang
 

From: Michael Kubacki <michael.a.kubacki@...>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

Moves the GDT and IDT to permanent memory in a memory discovered
callback. This is done to ensure the GDT and IDT authenticated in
pre-memory is not fetched from outside a verified location after
the permanent memory transition.

Cc: Eric Dong <eric.dong@...>
Cc: Ray Ni <ray.ni@...>
Cc: Laszlo Ersek <lersek@...>
Cc: Rahul Kumar <rahul1.kumar@...>
Signed-off-by: Michael Kubacki <michael.a.kubacki@...>
---
UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 1 +
UefiCpuPkg/CpuMpPei/CpuMpPei.h | 12 +++++++++++
UefiCpuPkg/CpuMpPei/CpuMpPei.c | 37 ++++++++++++++++++++++++++++++++
UefiCpuPkg/CpuMpPei/CpuPaging.c | 12 +++++++++--
4 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
index caead3ce34d4..f4d11b861f77 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
@@ -63,6 +63,7 @@ [Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES

[Depex]
TRUE
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h
index 7d5c527d6006..309478cbe14c 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h
@@ -397,6 +397,18 @@ SecPlatformInformation2 (
OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
);

+/**
+ Migrates the Global Descriptor Table (GDT) to permanent memory.
+
+ @retval EFI_SUCCESS The GDT was migrated successfully.
+ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.
+
+**/
+EFI_STATUS
+MigrateGdt (
+ VOID
+ );
+
/**
Initializes MP and exceptions handlers.

diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c
index 07ccbe7c6a91..d07540cf7471 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c
@@ -429,6 +429,43 @@ GetGdtr (
AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer);
}

+/**
+ Migrates the Global Descriptor Table (GDT) to permanent memory.
+
+ @retval EFI_SUCCESS The GDT was migrated successfully.
+ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.
+
+**/
+EFI_STATUS
+MigrateGdt (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN GdtBufferSize;
+ IA32_DESCRIPTOR Gdtr;
+ VOID *GdtBuffer;
+
+ AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr);
+ GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1;
+
+ Status = PeiServicesAllocatePool (
+ GdtBufferSize,
+ &GdtBuffer
+ );
+ ASSERT (GdtBuffer != NULL);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR));
+ CopyMem (GdtBuffer, (VOID *) Gdtr.Base, Gdtr.Limit + 1);
+ Gdtr.Base = (UINTN) GdtBuffer;
+ AsmWriteGdtr (&Gdtr);
+
+ return EFI_SUCCESS;
+}
+
/**
Initializes CPU exceptions handlers for the sake of stack switch requirement.

diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c
index a462e7ee1e38..3bf0574b34c6 100644
--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c
+++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c
@@ -602,8 +602,16 @@ MemoryDiscoveredPpiNotifyCallback (
IN VOID *Ppi
)
{
- EFI_STATUS Status;
- BOOLEAN InitStackGuard;
+ EFI_STATUS Status;
+ BOOLEAN InitStackGuard;
+ BOOLEAN InterruptState;
+
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ InterruptState = SaveAndDisableInterrupts ();
+ Status = MigrateGdt ();
+ ASSERT_EFI_ERROR (Status);
+ SetInterruptState (InterruptState);
+ }

//
// Paging must be setup first. Otherwise the exception TSS setup during MP
--
2.25.1.windows.1


[PATCH v4 2/9] MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore (CVE-2019-11098)

Guomin Jiang
 

From: Michael Kubacki <michael.a.kubacki@...>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

Introduces new changes to PeiCore to move the contents of temporary
RAM visible to the PeiCore to permanent memory. This expands on
pre-existing shadowing support in the PeiCore to perform the following
additional actions:

1. Migrate pointers in PPIs installed in PeiCore to the permanent
memory copy of PeiCore.

2. Copy all installed firmware volumes to permanent memory.

3. Relocate and fix up the PEIMs within the firmware volumes.

4. Convert all PPIs into the migrated firmware volume to the corresponding
PPI address in the permanent memory location.

This applies to PPIs and PEI notifications.

5. Convert all status code callbacks in the migrated firmware volume to
the corresponding address in the permanent memory location.

6. Update the FV HOB to the corresponding firmware volume in permanent
memory.

7. Add PcdMigrateTemporaryRamFirmwareVolumes to control if enable the
feature or not. when the PCD disable, the EvacuateTempRam() will
never be called.

The function control flow as below:
PeiCore()
DumpPpiList()
EvacuateTempRam()
ConvertPeiCorePpiPointers()
ConvertPpiPointersFv()
MigratePeimsInFv()
MigratePeim()
PeiGetPe32Data()
LoadAndRelocatePeCoffImageInPlace()
MigrateSecModulesInFv()
ConvertPpiPointersFv()
ConvertStatusCodeCallbacks()
ConvertFvHob()
RemoveFvHobsInTemporaryMemory()
DumpPpiList()

Cc: Jian J Wang <jian.j.wang@...>
Cc: Hao A Wu <hao.a.wu@...>
Cc: Dandan Bi <dandan.bi@...>
Cc: Liming Gao <liming.gao@...>
Cc: Debkumar De <debkumar.de@...>
Cc: Harry Han <harry.han@...>
Cc: Catharine West <catharine.west@...>
Signed-off-by: Michael Kubacki <michael.a.kubacki@...>
---
MdeModulePkg/Core/Pei/PeiMain.inf | 2 +
MdeModulePkg/Core/Pei/PeiMain.h | 168 ++++++++
MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 402 ++++++++++++++++++
MdeModulePkg/Core/Pei/Image/Image.c | 115 +++++
MdeModulePkg/Core/Pei/Memory/MemoryServices.c | 82 ++++
MdeModulePkg/Core/Pei/PeiMain/PeiMain.c | 22 +
MdeModulePkg/Core/Pei/Ppi/Ppi.c | 287 +++++++++++++
7 files changed, 1078 insertions(+)

diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf
index 6e25cc40232a..5b36d516b3fa 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -76,6 +76,7 @@ [Guids]
## 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

[Ppis]
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
@@ -109,6 +110,7 @@ [Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES

# [BootMode]
# S3_RESUME ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index 56b3bd85793d..b0101dba5e30 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -394,6 +394,41 @@ PeimDispatchReadiness (
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 Succesfully 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.

@@ -477,6 +512,50 @@ ConvertPpiPointers (
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,
+ 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.
@@ -808,6 +887,37 @@ PeiFfsFindNextFile (
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.

@@ -931,6 +1041,33 @@ MigrateMemoryPages (
IN BOOLEAN TemporaryRamMigrated
);

+/**
+ Removes any FV HOBs whose base address is not in PEI installed memory.
+
+ @param[in] Private Pointer to PeiCore's private data structure.
+
+**/
+VOID
+RemoveFvHobsInTemporaryMemory (
+ IN PEI_CORE_INSTANCE *Private
+ );
+
+/**
+ 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.
@@ -1249,6 +1386,37 @@ InitializeImageServices (
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
+
+**/
+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().

diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 4c2eac1384e8..ef88b3423376 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -952,6 +952,408 @@ PeiCheckAndSwitchStack (
}
}

+/**
+ 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
+ )
+{
+ 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) {
+ 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_INFO, "%a", AsciiString));
+
+ 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[%d] from 0x%08X to ", Index, CallbackEntry[Index]));
+ if (OrgFvHandle > FvHandle) {
+ CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);
+ } else {
+ CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);
+ }
+ DEBUG ((DEBUG_INFO, "0x%08X\n", CallbackEntry[Index]));
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
+ }
+}
+
+/**
+ Migrates SEC modules in the given firmware volume.
+
+ Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch.
+
+ This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has
+ been updated.
+
+ @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.
+
+ @retval EFI_SUCCESS SEC modules were migrated successfully
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+MigrateSecModulesInFv (
+ IN PEI_CORE_INSTANCE *Private,
+ IN UINTN FvIndex,
+ IN UINTN OrgFvHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS FindFileStatus;
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ UINT32 SectionAuthenticationStatus;
+ UINT32 FileSize;
+ VOID *OrgPe32SectionData;
+ VOID *Pe32SectionData;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ EFI_COMMON_SECTION_HEADER *Section;
+ BOOLEAN IsFfs3Fv;
+ UINTN SectionInstance;
+
+ if (Private == NULL || FvIndex >= Private->FvCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ do {
+ FindFileStatus = PeiFfsFindNextFile (
+ GetPeiServicesTablePointer (),
+ EFI_FV_FILETYPE_SECURITY_CORE,
+ Private->Fv[FvIndex].FvHandle,
+ &MigratedFileHandle
+ );
+ if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {
+ FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;
+
+ DEBUG ((DEBUG_VERBOSE, " Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle));
+ DEBUG ((DEBUG_VERBOSE, " FileHandle at 0x%x.\n", (UINTN) FileHandle));
+
+ IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
+ if (IS_FFS_FILE2 (FfsFileHeader)) {
+ ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
+ if (!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);
+ }
+
+ SectionInstance = 1;
+ SectionAuthenticationStatus = 0;
+ Status = ProcessSection (
+ GetPeiServicesTablePointer (),
+ EFI_SECTION_PE32,
+ &SectionInstance,
+ Section,
+ FileSize,
+ &Pe32SectionData,
+ &SectionAuthenticationStatus,
+ IsFfs3Fv
+ );
+
+ if (!EFI_ERROR (Status)) {
+ OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData));
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData));
+ Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData, Pe32SectionData);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ } while (!EFI_ERROR (FindFileStatus));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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_INFO, "\n"));
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ // if (Private->Fv[FvIndex].PeimState[FileIndex] == PEIM_STATE_REGISTER_FOR_SHADOW) {
+ // Private->Fv[FvIndex].PeimState[FileIndex]++;
+ // }
+ 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 Succesfully 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_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;
+
+ PEI_CORE_FV_HANDLE PeiCoreFvHandle;
+ EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
+
+ 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) {
+ PeiCoreFvHandle = Private->Fv[FvIndex];
+ break;
+ }
+ }
+ Status = EFI_SUCCESS;
+
+ ConvertPeiCorePpiPointers (Private, PeiCoreFvHandle);
+
+ 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)
+ )
+ ) {
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
+ (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Migrating FV[%d] from 0x%08X to 0x%08X\n",
+ FvIndex,
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader
+ ));
+
+ CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);
+
+ //
+ // 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));
+
+ // @todo: find issue with file and section alignment in SEC PE32 images for migration
+ // (alignment in P32 is given as 32-bit when actual alignment is 16-bit)
+ // SEC PPIs are currently re-installed with a dedicated PEIM
+ // Status = MigrateSecModulesInFv (Private, FvChildIndex, (UINTN) ChildFvHeader);
+ // ASSERT_EFI_ERROR (Status);
+ 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;
+
+ // @todo: find issue with file and section alignment in SEC PE32 images for migration
+ // (alignment in P32 is given as 32-bit when actual alignment is 16-bit)
+ // SEC PPIs are currently re-installed with a dedicated PEIM
+ // Status = MigrateSecModulesInFv (Private, FvIndex, (UINTN) FvHeader);
+ // ASSERT_EFI_ERROR (Status);
+ 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);
+ }
+ }
+
+ RemoveFvHobsInTemporaryMemory (Private);
+
+ return Status;
+}
+
/**
Conduct PEIM dispatch.

diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c
index e3ee3699337f..612797722a3e 100644
--- a/MdeModulePkg/Core/Pei/Image/Image.c
+++ b/MdeModulePkg/Core/Pei/Image/Image.c
@@ -444,6 +444,121 @@ LoadAndRelocatePeCoffImage (
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
+
+**/
+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,
diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
index 6b3a64a811cd..9d933f0393a8 100644
--- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
+++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -166,6 +166,88 @@ MigrateMemoryPages (
Private->FreePhysicalMemoryTop = NewMemPagesBase;
}

+/**
+ Removes any FV HOBs whose base address is not in PEI installed memory.
+
+ @param[in] Private Pointer to PeiCore's private data structure.
+
+**/
+VOID
+RemoveFvHobsInTemporaryMemory (
+ IN PEI_CORE_INSTANCE *Private
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+
+ DEBUG ((DEBUG_INFO, "Removing FVs in FV HOB not already migrated to permanent memory.\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 || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2 || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ DEBUG ((DEBUG_INFO, " Found FV HOB.\n"));
+ DEBUG ((
+ DEBUG_INFO,
+ " BA=%016lx L=%016lx\n",
+ FirmwareVolumeHob->BaseAddress,
+ FirmwareVolumeHob->Length
+ ));
+ if (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress >= Private->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress + (FirmwareVolumeHob->Length - 1)) < Private->FreePhysicalMemoryTop)
+ )
+ ) {
+ DEBUG ((DEBUG_INFO, " Removing FV HOB to an FV in T-RAM (was not migrated).\n"));
+ Hob.Header->HobType = EFI_HOB_TYPE_UNUSED;
+ }
+ }
+ }
+}
+
+/**
+ 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.
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index cca57c4c0686..7be6e9f3b06c 100644
--- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
+++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -176,6 +176,7 @@ PeiCore (
EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable;
EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi;
UINTN Index;
+ BOOLEAN Shadow;

//
// Retrieve context passed into PEI Core
@@ -418,6 +419,27 @@ PeiCore (
ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps, PpiList);
}
} else {
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ if (PrivateData.HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) {
+ Shadow = PcdGetBool (PcdShadowPeimOnS3Boot);
+ } else {
+ Shadow = PcdGetBool (PcdShadowPeimOnBoot);
+ }
+ }
+
+ if (Shadow) {
+ 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.
//
diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
index 1ffe718c4702..018b25f86470 100644
--- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c
+++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
@@ -198,6 +198,227 @@ ConvertPpiPointers (
}
}

+/**
+
+ 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.
@@ -830,3 +1051,69 @@ ProcessPpiListFromSec (
}
}

+/**
+
+ 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,
+ 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);
+ }
+}
+
--
2.25.1.windows.1


[PATCH v4 1/9] MdeModulePkg: Add new PCD to control the evacuate temporary memory feature (CVE-2019-11098)

Guomin Jiang
 

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

The security researcher found that we can get control after NEM disable.

The reason is that the flash content reside in NEM at startup and the
code will get the content from flash directly after disable NEM.

To avoid this vulnerability, the feature will copy the PEIMs from
temporary memory to permanent memory and only execute the code in
permanent memory.

The vulnerability is exist in physical platform and haven't report in
virtual platform, so the virtual can disable the feature currently.

Cc: Jian J Wang <jian.j.wang@...>
Cc: Hao A Wu <hao.a.wu@...>
Signed-off-by: Guomin Jiang <guomin.jiang@...>
---
MdeModulePkg/MdeModulePkg.dec | 7 +++++++
MdeModulePkg/MdeModulePkg.uni | 6 ++++++
2 files changed, 13 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 843e963ad34b..16db17d0a873 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -1220,6 +1220,13 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
# @Prompt Shadow Peim and PeiCore on boot
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot|TRUE|BOOLEAN|0x30001029

+ ## Enable the feature that evacuate temporary memory to permanent memory or not
+ # Set FALSE as default, if the developer need this feature to avoid this vulnerability, please
+ # enable it in dsc file.
+ # TRUE - Evacuate temporary memory, the actions include copy memory, convert PPI pointers and so on.
+ # FALSE - Do nothing, for example, no copy memory, no convert PPI pointers and so on.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes|FALSE|BOOLEAN|0x3000102A
+
## The mask is used to control memory profile behavior.<BR><BR>
# BIT0 - Enable UEFI memory profile.<BR>
# BIT1 - Enable SMRAM profile.<BR>
diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni
index 2007e0596c4f..5235dee561ad 100644
--- a/MdeModulePkg/MdeModulePkg.uni
+++ b/MdeModulePkg/MdeModulePkg.uni
@@ -214,6 +214,12 @@
"TRUE - Shadow PEIM on S3 boot path after memory is ready.<BR>\n"
"FALSE - Not shadow PEIM on S3 boot path after memory is ready.<BR>"

+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMigrateTemporaryRamFirmwareVolumes_HELP #language en-US "Enable the feature that evacuate temporary memory to permanent memory or not.<BR><BR>\n"
+ "It will allocate page to save the temporary PEIMs resided in NEM(or CAR) to the permanent memory and change all pointers pointed to the NEM(or CAR) to permanent memory.<BR><BR>\n"
+ "After then, there are no pointer pointed to NEM(or CAR) and TOCTOU volnerability can be avoid.<BR><BR>\n"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMigrateTemporaryRamFirmwareVolumes_PROMPT #language en-US "Enable the feature that evacuate temporary memory to permanent memory or not"
+
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiDefaultOemId_PROMPT #language en-US "Default OEM ID for ACPI table creation"

#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiDefaultOemId_HELP #language en-US "Default OEM ID for ACPI table creation, its length must be 0x6 bytes to follow ACPI specification."
--
2.25.1.windows.1


[PATCH v4 0/9] Add new feature that evacuate temporary to permanent memory (CVE-2019-11098)

Guomin Jiang
 

The TOCTOU vulnerability allow that the physical present person to replace the code with the normal BootGuard check and PCR0 value.
The issue occur when BootGuard measure IBB and access flash code after NEM disable.
the reason why we access the flash code is that we have some pointer to flash.
To avoid this vulnerability, we need to convert those pointers, the patch series do this work and make sure that no code will access flash address.

v2:
Create gEdkiiMigratedFvInfoGuid HOB and add PcdMigrateTemporaryRamFirmwareVolumes to control whole feature.

v3:
Remove changes which is not related with the feature and disable the feature in virtual platform.

v4:
Disable the feature as default, Copy the Tcg2Pei behavior to TcgPei

Cc: Jian J Wang <jian.j.wang@...>
Cc: Hao A Wu <hao.a.wu@...>
Cc: Dandan Bi <dandan.bi@...>
Cc: Liming Gao <liming.gao@...>
Cc: Debkumar De <debkumar.de@...>
Cc: Harry Han <harry.han@...>
Cc: Catharine West <catharine.west@...>
Cc: Eric Dong <eric.dong@...>
Cc: Ray Ni <ray.ni@...>
Cc: Jordan Justen <jordan.l.justen@...>
Cc: Andrew Fish <afish@...>
Cc: Laszlo Ersek <lersek@...>
Cc: Ard Biesheuvel <ard.biesheuvel@...>
Cc: Anthony Perard <anthony.perard@...>
Cc: Julien Grall <julien@...>
Cc: Leif Lindholm <leif@...>
Cc: Rahul Kumar <rahul1.kumar@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Chao Zhang <chao.b.zhang@...>
Cc: Qi Zhang <qi1.zhang@...>

Guomin Jiang (6):
MdeModulePkg: Add new PCD to control the evacuate temporary memory
feature (CVE-2019-11098)
MdeModulePkg/Core: Create Migrated FV Info Hob for calculating hash
(CVE-2019-11098)
SecurityPkg/Tcg2Pei: Use Migrated FV Info Hob for calculating hash
(CVE-2019-11098)
UefiCpuPkg/CpuMpPei: Enable paging and set NP flag to avoid TOCTOU
(CVE-2019-11098)
UefiCpuPkg: Correct some typos.
SecurityPkg/TcgPei: Use Migrated FV Info Hob for calculating hash
(CVE-2019-11098)

Michael Kubacki (3):
MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore
(CVE-2019-11098)
UefiCpuPkg/CpuMpPei: Add GDT and IDT migration support
(CVE-2019-11098)
UefiCpuPkg/SecMigrationPei: Add initial PEIM (CVE-2019-11098)

MdeModulePkg/MdeModulePkg.dec | 10 +
UefiCpuPkg/UefiCpuPkg.dec | 4 +
UefiCpuPkg/UefiCpuPkg.dsc | 1 +
MdeModulePkg/Core/Pei/PeiMain.inf | 3 +
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf | 1 +
SecurityPkg/Tcg/TcgPei/TcgPei.inf | 1 +
UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 4 +
UefiCpuPkg/SecCore/SecCore.inf | 2 +
.../SecMigrationPei/SecMigrationPei.inf | 67 +++
MdeModulePkg/Core/Pei/PeiMain.h | 169 +++++++
MdeModulePkg/Include/Guid/MigratedFvInfo.h | 22 +
UefiCpuPkg/CpuMpPei/CpuMpPei.h | 12 +
UefiCpuPkg/Include/Ppi/RepublishSecPpi.h | 54 +++
UefiCpuPkg/SecCore/SecMain.h | 1 +
UefiCpuPkg/SecMigrationPei/SecMigrationPei.h | 154 +++++++
MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 430 ++++++++++++++++++
MdeModulePkg/Core/Pei/Image/Image.c | 115 +++++
MdeModulePkg/Core/Pei/Memory/MemoryServices.c | 82 ++++
MdeModulePkg/Core/Pei/PeiMain/PeiMain.c | 22 +
MdeModulePkg/Core/Pei/Ppi/Ppi.c | 287 ++++++++++++
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 31 +-
SecurityPkg/Tcg/TcgPei/TcgPei.c | 29 +-
UefiCpuPkg/CpuMpPei/CpuMpPei.c | 37 ++
UefiCpuPkg/CpuMpPei/CpuPaging.c | 42 +-
.../Ia32/ArchExceptionHandler.c | 4 +-
.../SecPeiCpuException.c | 2 +-
UefiCpuPkg/SecCore/SecMain.c | 26 +-
UefiCpuPkg/SecMigrationPei/SecMigrationPei.c | 378 +++++++++++++++
MdeModulePkg/MdeModulePkg.uni | 6 +
.../SecMigrationPei/SecMigrationPei.uni | 13 +
30 files changed, 1993 insertions(+), 16 deletions(-)
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
create mode 100644 MdeModulePkg/Include/Guid/MigratedFvInfo.h
create mode 100644 UefiCpuPkg/Include/Ppi/RepublishSecPpi.h
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.h
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.c
create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni

--
2.25.1.windows.1


Re: [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver

Gary Lin
 

On Tue, Jul 07, 2020 at 02:49:48PM +0200, Laszlo Ersek wrote:
On 07/01/20 06:04, Gary Lin wrote:
Cc: Jordan Justen <jordan.l.justen@...>
Cc: Laszlo Ersek <lersek@...>
Cc: Ard Biesheuvel <ard.biesheuvel@...>
Signed-off-by: Gary Lin <glin@...>
---
Maintainers.txt | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/Maintainers.txt b/Maintainers.txt
index 32c9003a6209..666d3af4d76a 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -400,6 +400,10 @@ OvmfPkg: CSM modules
F: OvmfPkg/Csm/
R: David Woodhouse <dwmw2@...>

+OvmfPkg: LsiScsi Driver
+F: OvmfPkg/LsiScsiDxe/
+R: Gary Lin <glin@...>
+
OvmfPkg: MptScsi and PVSCSI driver
F: OvmfPkg/MptScsiDxe/
F: OvmfPkg/PvScsiDxe/
(1) Please use your name rather than "myself" in the subject -- consider
"git log --oneline".

(2) Please write "driver" rather than "Driver" in the new entry, for
consistency with the "MptScsi and PVSCSI" entry (and other entries in
the file too).
Will fix this commit in v2.

Thanks,

Gary Lin

With those updates:

Reviewed-by: Laszlo Ersek <lersek@...>

Thanks
Laszlo


Re: [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet

Gary Lin
 

On Tue, Jul 07, 2020 at 02:46:14PM +0200, Laszlo Ersek wrote:
On 07/01/20 06:04, Gary Lin wrote:
This is the second part of LsiScsiPassThru(). LsiScsiProcessRequest() is
added to translate the SCSI Request Packet into the LSI 53C895A
commands. This function utilizes the so-called Script buffer to transmit
a series of commands to the chip and then polls the DMA Status (DSTAT)
register until the Scripts Interrupt Instruction Received (SIR) bit
sets. Once the script is done, the SCSI Request Packet will be modified
to reflect the result of the script.

Cc: Jordan Justen <jordan.l.justen@...>
Cc: Laszlo Ersek <lersek@...>
Cc: Ard Biesheuvel <ard.biesheuvel@...>
Signed-off-by: Gary Lin <glin@...>
---
OvmfPkg/Include/IndustryStandard/LsiScsi.h | 39 +++
OvmfPkg/LsiScsiDxe/LsiScsi.c | 308 +++++++++++++++++++++
OvmfPkg/LsiScsiDxe/LsiScsi.h | 21 ++
OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf | 3 +
OvmfPkg/OvmfPkg.dec | 3 +
5 files changed, 374 insertions(+)

diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
index 60e527f1c6a7..cbf049c18310 100644
--- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
@@ -26,6 +26,18 @@
#define LSI_REG_SIST0 0x42
#define LSI_REG_SIST1 0x43

+//
+// The status bits for DMA Status (DSTAT)
+//
+#define LSI_DSTAT_IID 0x01
+#define LSI_DSTAT_R 0x02
+#define LSI_DSTAT_SIR 0x04
+#define LSI_DSTAT_SSI 0x08
+#define LSI_DSTAT_ABRT 0x10
+#define LSI_DSTAT_BF 0x20
+#define LSI_DSTAT_MDPE 0x40
+#define LSI_DSTAT_DFE 0x80
+
(1) Please use the BITx macros.
Will fix it.


//
// The status bits for Interrupt Status Zero (ISTAT0)
//
@@ -38,4 +50,31 @@
#define LSI_ISTAT0_SRST 0x40
#define LSI_ISTAT0_ABRT 0x80

+//
+// LSI 53C895A Script Instructions
+//
+#define LSI_INS_TYPE_BLK 0x00000000
+#define LSI_INS_TYPE_IO 0x40000000
+#define LSI_INS_TYPE_TC 0x80000000
+
+#define LSI_INS_BLK_SCSIP_DAT_OUT 0x00000000
+#define LSI_INS_BLK_SCSIP_DAT_IN 0x01000000
+#define LSI_INS_BLK_SCSIP_CMD 0x02000000
+#define LSI_INS_BLK_SCSIP_STAT 0x03000000
+#define LSI_INS_BLK_SCSIP_MSG_OUT 0x06000000
+#define LSI_INS_BLK_SCSIP_MSG_IN 0x07000000
+
+#define LSI_INS_IO_OPC_SEL 0x00000000
+#define LSI_INS_IO_OPC_WAIT_RESEL 0x10000000
+
+#define LSI_INS_TC_CP 0x00020000
+#define LSI_INS_TC_JMP 0x00080000
+#define LSI_INS_TC_RA 0x00800000
+
+#define LSI_INS_TC_OPC_JMP 0x00000000
+#define LSI_INS_TC_OPC_INT 0x18000000
+
+#define LSI_INS_TC_SCSIP_DAT_OUT 0x00000000
+#define LSI_INS_TC_SCSIP_MSG_IN 0x07000000
+
#endif // _LSI_SCSI_H_
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index 1bcebd92e455..090d7df15b34 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -43,6 +43,42 @@ Out8 (
);
}

+STATIC
+EFI_STATUS
+Out32 (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT32 Addr,
+ IN UINT32 Data
+ )
+{
+ return Dev->PciIo->Io.Write (
+ Dev->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Addr,
+ 1,
+ &Data
+ );
+}
+
+STATIC
+EFI_STATUS
+In8 (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT32 Addr,
+ OUT UINT8 *Data
+ )
+{
+ return Dev->PciIo->Io.Read (
+ Dev->PciIo,
+ EfiPciIoWidthUint8,
+ PCI_BAR_IDX0,
+ Addr,
+ 1,
+ Data
+ );
+}
+
STATIC
EFI_STATUS
LsiScsiReset (
@@ -141,6 +177,272 @@ LsiScsiCheckRequest (
return EFI_SUCCESS;
}

+/**
+
+ Interpret the request packet from the Extended SCSI Pass Thru Protocol and
+ compose the script to submit the command and data to the contorller.
(2) s/contorller/controller/
Oops. Will fix it.


+
+ @param[in] Dev The LSI 53C895A SCSI device the packet targets.
+
+ @param[in] Target The SCSI target controlled by the LSI 53C895A SCSI
+ device.
+
+ @param[in] Lun The Logical Unit Number under the SCSI target.
+
+ @param[in out] Packet The Extended SCSI Pass Thru Protocol packet.
+
+
+ @retval EFI_SUCCESS The Extended SCSI Pass Thru Protocol packet was valid.
+
+ @return Otherwise, invalid or unsupported parameters were
+ detected. Status codes are meant for direct forwarding
+ by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
+ implementation.
+
+ **/
+STATIC
+EFI_STATUS
+LsiScsiProcessRequest (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT8 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ EFI_STATUS Status;
+ UINT32 *Script;
+ UINT8 *Cdb;
+ UINT8 *MsgOut;
+ UINT8 *MsgIn;
+ UINT8 *ScsiStatus;
+ UINT8 *Data;
+ UINT8 DStat;
+ UINT8 SIst0;
+ UINT8 SIst1;
+
+ Script = Dev->Dma->Script;
+ Cdb = Dev->Dma->Cdb;
+ Data = Dev->Dma->Data;
+ MsgIn = Dev->Dma->MsgIn;
+ MsgOut = &Dev->Dma->MsgOut;
+ ScsiStatus = &Dev->Dma->Status;
+
+ *ScsiStatus = 0xFF;
+
+ SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
+ CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
+
+ //
+ // Clean up the DMA buffer for the script.
+ //
+ SetMem (Script, sizeof Dev->Dma->Script, 0x00);
+
+ //
+ // Compose the script to transfer data between the host and the device.
+ //
+ // Reference:
+ // LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
+ // - Chapter 5 SCSI SCRIPT Instruction Set
+ //
+ // All instructions used here consist of 2 32bit words. The first word
+ // contains the command to execute. The second word is loaded into the
+ // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
+ // for data transmission or the address/offset for the jump command.
+ // Some commands, such as the selection of the target, don't need to
+ // transfer data through DMA or jump to another instruction, then DSPS
+ // has to be zero.
+ //
+ // There are 3 major parts in this script. The first part (1~3) contains
+ // the instructions to select target and LUN and send the SCSI command
+ // from the request packet. The second part (4~7) is to handle the
+ // potential disconnection and prepare for the data transmission. The
+ // instructions in the third part (8~10) transmit the given data and
+ // collect the result. Instruction 11 raises the interrupt and marks the
+ // end of the script.
+ //
+
+ //
+ // 1. Select target.
+ //
+ *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
+ *Script++ = 0x00000000;
+
+ //
+ // 2. Select LUN.
+ //
+ *MsgOut = 0x80 | (UINT8) Lun; // 0x80: Identify bit
This implies that the maximum (inclusive) LUN can be 127.

(3) I suggest adding a STATIC_ASSERT() to LsiScsiControllerStart(),
where you fetch "PcdLsiScsiMaxLunLimit".

(If the device has a stricter limit on LUNs than 127, then please use
that limit.)
Ok, will add an assert for MaxLun.


+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT | \
+ sizeof Dev->Dma->MsgOut;
(4) Please cast the result of the "sizeof" operator to UINT32
explicitly.


(5) Please drop the backslash; it is not needed.

Note that (4) and (5) apply to multiple locations in this function;
please update each location in the composition of the script.
Will fix them in v2.


+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgOut);
This opcode seems to mean that the device is not capable of taking the
LUN selector message from outside of the 32-bit address space.

(6) If that's the case, then please remove DUAL_ADDRESS_CYCLE from
"[PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer".

Otherwise, AllocateBuffer() could theoretically allocate the buffer
structure (including the MsgOut member) such that
LSI_SCSI_DMA_ADDR_LOW() would truncate the address.


(7) Once you remove DUAL_ADDRESS_CYCLE (i.e. once we guarantee that the
allocation will be satisfied from the 32-bit address space), you can
drop the _LOW suffix as well, from the macro name.

Now, if the device is actually 64-bit capable, only it would take a more
complex script, and you don't want that, that's fine -- the above steps
remain the same. (IOW it doesn't matter whether the device is 64-bit
uncapable, or you don't want to write a 64-bit aware command script --
you should remove DUAL_ADDRESS_CYCLE just the same.)
Ok. Will remove DUAL_ADDRESS_CYCLE.


+
+ //
+ // 3. Send the SCSI Command.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD | \
+ sizeof Dev->Dma->Cdb;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Cdb);
+
+ //
+ // 4. Check whether the current SCSI phase is "Message In" or not
+ // and jump to 8 if it is.
+ //
+ *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP | \
+ LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA | \
+ LSI_INS_TC_CP;
+ *Script++ = 0x00000018;
(8) The constant 0x18 is obscure. Can you extend the comment? How is
"step 8" connected to value 0x18?

(Step 8 starts at command offset 7 in the script, meaning UINT32 offset
14, or byte offset 56. But 0x18 is 24, not matching any of those
constants.)
Urghhh, it should be "jump to 7". LSI_INS_TC_RA stands for "Relative
Addressing Mode", so it's 4 + 24/8 = 7. Will fix the comment.


+
+ //
+ // 5. Read "Message" from the initiator to trigger reselect.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
+ sizeof Dev->Dma->MsgIn;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
+
+ //
+ // 6. Wait reselect.
+ //
+ *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
+ *Script++ = 0x00000000;
+
+ //
+ // 7. Read "Message" from the initiator again
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
+ sizeof Dev->Dma->MsgIn;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
+
+ //
+ // 8. Set the DMA command for the read/write operations.
+ //
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ &&
+ Packet->InTransferLength > 0) {
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN | \
+ Packet->InTransferLength;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
+ } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE &&
+ Packet->OutTransferLength > 0) {
+ // LsiScsiCheckRequest() guarantees that OutTransferLength is no
+ // larger than sizeof Dev->Dma->Data, so we can safely copy the
+ // the data to Dev->Dma->Data.
+ CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT | \
+ Packet->OutTransferLength;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
+ }
The comment is not bad, but it could be improved.

First, the comment style is not 100% correct (empty "//" lines are
missing before and after.)

Second, instead of a long comment, I'd suggest a short comment, plus an
ASSERT.
Will amend the comment and add an assert.

Third, the transfer length in the packet ("in" and "out" alike) isn't
*only* relevant due to buffer overflow concerns, but also because the
command opcode has some bits set (in particular,
LSI_INS_BLK_SCSIP_DAT_IN) that effectively limit the transfer length to
a bitmask that's narrower than a UINT32.
Yeah, the controller only takes 24 bits for the transfer length.


Another observation is that control can flow through this snippet
without taking *either* branch.

(For example if the data direction is WRITE, but OutTransferLength is
zero. That's a condition that LsiScsiCheckRequest() does not catch. My
point is not that LsiScsiCheckRequest() should catch it -- I think it's
not an invalid request --, but that LsiScsiProcessRequest() should deal
with it.)
Hmmm, this is possible when ScsiIo requests sense data throught
Packet->SenseData, and it's a read request with 0 InTransferLength.
I encountered that during the development of this driver. It's gone after
I set SenseDataLength to 0 later to make ScsiIo request sense data through
Transfer buffer. Maybe I should filter this kind of requests in
LsiScsiCheckRequest().

If we take neither branch, then (minimally) the jump address under step
4. will be wrong -- there's not going to be a DAT_IN / DAT_OUT command
to jump to.


(9) So, for addressing all of the above, I suggest:

//
// 8. Set the DMA command for the read/write operations.
//
// LsiScsiCheckRequest() prevents both integer overflows in the command
// opcodes, and buffer overflows.
//
if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
ASSERT (Packet->InTransferLength <= sizeof Dev->Dma->Data);
*Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN |
Packet->InTransferLength;
} else {
ASSERT (Packet->OutTransferLength <= sizeof Dev->Dma->Data);
CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
*Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT |
Packet->OutTransferLength;
}
*Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
Thanks. Will modify the code here.


+
+ //
+ // 9. Get the SCSI status.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT | \
+ sizeof Dev->Dma->Status;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Status);
+
+ //
+ // 10. Get the SCSI message.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
+ sizeof Dev->Dma->MsgIn;
+ *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
+
+ //
+ // 11. Raise the interrupt to end the script.
+ //
+ *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT | \
+ LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
+ *Script++ = 0x00000000;
+
+ //
+ // Make sure the size of the script doesn't exceed the buffer.
+ //
+ ASSERT (Script < Dev->Dma->Script + sizeof Dev->Dma->Script);
(10) Please replace "<" with "<=".

(11) Please replace "sizeof" with ARRAY_SIZE().
Will fix it.


+
+ //
+ // The controller starts to execute the script once the DMA Script
+ // Pointer (DSP) register is set.
+ //
+ Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR_LOW(Dev, Script));
(12) Missing space after "LSI_SCSI_DMA_ADDR".
Ditto.


+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
This return statement doesn't seem right. We do not translate the error
code to one of the error codes specified for
EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(). We also do not set any
output field in Packet.

(13) I think we should jump to the "Error" label from here.
Right. It should jump to "Error".


+
+ //
+ // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
+ // bit sets.
+ //
+ for(;;) {
+ Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ if (SIst0 != 0 || SIst1 != 0) {
+ goto Error;
+ }
+
+ //
+ // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
+ //
+ if (DStat & LSI_DSTAT_SIR) {
+ break;
+ }
+
+ gBS->Stall (Dev->StallPerPollUsec);
+ }
+
+ //
+ // Check if everything is good.
+ // SCSI Message Code 0x00: COMMAND COMPLETE
+ // SCSI Status Code 0x00: Good
+ //
+ if (MsgIn[0] == 0 && *ScsiStatus == 0) {
(14) Please negate this condition, and unnest the success branch:

if (MsgIn[0] != 0 || *ScsiStatus != 0) {
goto Error;
}

/* ... */

return EFI_SUCCESS;

Ok. Will do that.

+ //
+ // Copy Data to InDataBuffer if necessary.
+ //
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+ CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
+ }
+
+ //
+ // The controller doesn't return sense data when replying "TEST UNIT READY",
+ // so we have to set SenseDataLength to 0 to notify ScsiIo to issue
+ // "REQUEST SENSE" for the sense data.
+ //
+ if (Cdb[0] == 0x00) {
+ Packet->SenseDataLength = 0;
+ }
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+
+ return EFI_SUCCESS;
+ }
The mapping on success does not deal with short transfers (in or out) --
we're supposed to update InTransferLength / OutTransferLength on output.

(15) Does the device report short transfers somehow?
I'm not sure. Have to check the spec of controller to see if there is
any instruction to fetch the real transfer length.


The spec says about SenseDataLength, "On input, the length in bytes of
the SenseData buffer. On output, the number of bytes written to the
SenseData buffer".

But we only set SenseDataLength conditionally. In case we do *not* set
it, the caller may attempt to parse garbage from the "SenseData" buffer.

(16) We should either get real sense data back to the caller, or always
zero out "SenseDataLength".

For simplicity, I would choose zeroing out "SenseDataLength" since
ScsiDiskDxe can handle it.

+
+Error:
+ DEBUG((DEBUG_VERBOSE, "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
+ __FUNCTION__, DStat, SIst0, SIst1));
(17) missing space after "DEBUG".

(18) The line starting with __FUNCTION__ is not correctly indented.
Will fix them.


+ //
+ // Update the request packet to reflect the status.
+ //
+ if (*ScsiStatus != 0xFF) {
+ Packet->TargetStatus = *ScsiStatus;
+ } else {
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
+ }
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+ Packet->InTransferLength = 0;
+ Packet->OutTransferLength = 0;
+ Packet->SenseDataLength = 0;
+
+ return EFI_DEVICE_ERROR;
+}
+
//
// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
@@ -168,6 +470,11 @@ LsiScsiPassThru (
return Status;
}

+ Status = LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
return EFI_SUCCESS;
}
(19) I think this can be simplified -- just return Status after calling
LsiScsiProcessRequest().
Agree.


@@ -469,6 +776,7 @@ LsiScsiControllerStart (

Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
+ Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);

Status = gBS->OpenProtocol (
ControllerHandle,
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index 9272eb7506c7..1a16ef9f7795 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -13,6 +13,11 @@
#define _LSI_SCSI_DXE_H_

typedef struct {
+ //
+ // Allocate 32 UINT32 entries for the script and it's sufficient for
+ // 16 instructions.
+ //
+ UINT32 Script[32];
//
// The max size of CDB is 32.
//
@@ -21,6 +26,18 @@ typedef struct {
// Allocate 64KB for read/write buffer.
//
UINT8 Data[0x10000];
+ //
+ // For SCSI Message In phase
+ //
+ UINT8 MsgIn[2];
+ //
+ // For SCSI Message Out phase
+ //
+ UINT8 MsgOut;
+ //
+ // For SCSI Status phase
+ //
+ UINT8 Status;
} LSI_SCSI_DMA_BUFFER;

typedef struct {
@@ -30,6 +47,7 @@ typedef struct {
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 MaxTarget;
UINT8 MaxLun;
+ UINT32 StallPerPollUsec;
LSI_SCSI_DMA_BUFFER *Dma;
EFI_PHYSICAL_ADDRESS DmaPhysical;
VOID *DmaMapping;
@@ -42,6 +60,9 @@ typedef struct {
#define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)

+#define LSI_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
+ ((UINT32)(Dev->DmaPhysical + OFFSET_OF (LSI_SCSI_DMA_BUFFER, MemberName)))
+

//
// Probe, start and stop functions of this driver, called by the DXE core for
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
index 68844c6772e3..cbd7294573ac 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -41,3 +41,6 @@ [Protocols]
[FixedPcd]
gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit ## CONSUMES
gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit ## CONSUMES
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index ae7d1d648d22..57e418d4b8a9 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -179,6 +179,9 @@ [PcdsFixedAtBuild]
gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c

+ ## Microseconds to stall between polling for LsiScsi request result
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec|5|UINT32|0x3d
+
(20) The token value should be 0x3c here, according to my request (5)
under "[PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs".
Ok, will do that if we won't change the toke value of PcdMptScsiStallPerPollUsec.

Thanks,

Gary Lin


gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
Thanks
Laszlo


[PATCH edk2-platforms 3/3] Silicon/NXP: Add Support for git commit info print

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

This patch adds the Support for printing the git commit information
in linux build environment.

Ideal place of retrieving this information should be python script in
BaseTools.

A Feature request for the same has been created:
https://bugzilla.tianocore.org/show_bug.cgi?id=2838

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
---
Silicon/NXP/NxpQoriqLs.dsc.inc | 3 ++
Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.inf | 5 +++
Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.inf | 5 +++
Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.c | 17 +++++++++
Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.c | 17 +++++++++
Silicon/NXP/set_firmware_ver.sh | 36 ++++++++++++++++++++
6 files changed, 83 insertions(+)

diff --git a/Silicon/NXP/NxpQoriqLs.dsc.inc b/Silicon/NXP/NxpQoriqLs.dsc.inc
index 06ee012c227a..a0762a6ef61d 100644
--- a/Silicon/NXP/NxpQoriqLs.dsc.inc
+++ b/Silicon/NXP/NxpQoriqLs.dsc.inc
@@ -224,6 +224,9 @@ [PcdsDynamicHii.common.DEFAULT]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10

[PcdsFixedAtBuild.common]
+ !ifdef $(FIRMWARE_VER)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L"$(FIRMWARE_VER)"
+ !endif
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
diff --git a/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.inf b/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.inf
index f5dbd1349dc5..69f884af9e34 100644
--- a/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.inf
+++ b/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.inf
@@ -16,6 +16,7 @@ [Defines]

[Packages]
ArmPkg/ArmPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
Silicon/NXP/Chassis2/Chassis2.dec
Silicon/NXP/NxpQoriqLs.dec
@@ -24,6 +25,7 @@ [LibraryClasses]
IoAccessLib
IoLib
PcdLib
+ PrintLib
SerialPortLib

[Sources.common]
@@ -31,3 +33,6 @@ [Sources.common]

[FeaturePcd]
gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
diff --git a/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.inf b/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.inf
index 75b68cc4ca2d..632acc52b20a 100644
--- a/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.inf
+++ b/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.inf
@@ -16,6 +16,7 @@ [Defines]

[Packages]
ArmPkg/ArmPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
Silicon/NXP/Chassis3V2/Chassis3V2.dec
Silicon/NXP/NxpQoriqLs.dec
@@ -24,6 +25,7 @@ [LibraryClasses]
IoAccessLib
IoLib
PcdLib
+ PrintLib
SerialPortLib

[Sources.common]
@@ -31,3 +33,6 @@ [Sources.common]

[FeaturePcd]
gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
diff --git a/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.c b/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.c
index 91b19f832f00..bc782e7e3873 100644
--- a/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.c
+++ b/Silicon/NXP/Chassis2/Library/ChassisLib/ChassisLib.c
@@ -12,6 +12,7 @@
#include <Library/IoAccessLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
#include <Library/SerialPortLib.h>

/**
@@ -89,10 +90,26 @@ ChassisInit (
VOID
)
{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+
//
// Early init serial Port to get board information.
//
SerialPortInitialize ();

+ CharCount = AsciiSPrint (
+ Buffer, sizeof (Buffer),
+ "UEFI firmware built at %a on %a. version:\n\r",
+ __TIME__, __DATE__
+ );
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+ CharCount = AsciiSPrint (
+ Buffer, sizeof (Buffer), "%s\n\r",
+ (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString)
+ );
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
SmmuInit ();
}
diff --git a/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.c b/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.c
index 30f8f945b233..6d546f4754f9 100644
--- a/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.c
+++ b/Silicon/NXP/Chassis3V2/Library/ChassisLib/ChassisLib.c
@@ -12,6 +12,7 @@
#include <Library/IoAccessLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
#include <Library/SerialPortLib.h>

/**
@@ -64,8 +65,24 @@ ChassisInit (
VOID
)
{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+
//
// Early init serial Port to get board information.
//
SerialPortInitialize ();
+
+ CharCount = AsciiSPrint (
+ Buffer, sizeof (Buffer),
+ "UEFI firmware built at %a on %a. version:\n\r",
+ __TIME__, __DATE__
+ );
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+ CharCount = AsciiSPrint (
+ Buffer, sizeof (Buffer), "%s\n\r",
+ (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString)
+ );
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
}
diff --git a/Silicon/NXP/set_firmware_ver.sh b/Silicon/NXP/set_firmware_ver.sh
new file mode 100755
index 000000000000..ba2336ad23dc
--- /dev/null
+++ b/Silicon/NXP/set_firmware_ver.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# parse PACKAGES_PATH and set FIRMWARE_VER based on that
+
+get_git_version()
+{
+ command -v git>/dev/null 2>&1
+ if [ $? -eq 0 ] && [ -n "$1" ]
+ then
+ head_or_tag=`git -C $1 describe --tag --dirty --broken --always 2>/dev/null`
+ printf $head_or_tag
+ fi
+}
+
+if [ -n "$FIRMWARE_VER" ]; then
+ echo "Warning FIRMWARE_VER=$FIRMWARE_VER is already set"
+ echo "Please retry after 'unset FIRMWARE_VER' command"
+fi
+
+directories=$(echo $PACKAGES_PATH | tr ":" "\n")
+for dir in $directories; do
+ if [ -n "$FIRMWARE_VER" ]; then
+ FIRMWARE_VER="$FIRMWARE_VER;$(basename $dir):$(get_git_version $dir)"
+ else
+ FIRMWARE_VER=$(basename $dir):$(get_git_version $dir)
+ fi
+done
+
+echo "FIRMWARE_VER=$FIRMWARE_VER"
+export FIRMWARE_VER=$FIRMWARE_VER
+
+echo "build edk2 firmware with -D FIRMWARE_VER=\$FIRMWARE_VER"
--
2.17.1


[PATCH edk2-platforms 2/3] Silicon/NXP: Add support for reserving a chunk from RAM

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

Some NXP SOCs have some specialized IP blocks (like MC), which
require DDR memory to operate. This DDR memory should not be managed
by OS or UEFI.

Moreover to ensure that these IP blocks always get memory, and maximum
contiguous RAM is available for UEFI and OS to use, add the support for
reserving a chunk from RAM before reporting available RAM to UEFI.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
---
Silicon/NXP/NxpQoriqLs.dec | 10 ++
Silicon/NXP/LX2160A/LX2160A.dsc.inc | 4 +
Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf | 3 +
Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.c | 142 +++++++++++++++++++-
4 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
index 188a9fe1f382..0e762066e547 100644
--- a/Silicon/NXP/NxpQoriqLs.dec
+++ b/Silicon/NXP/NxpQoriqLs.dec
@@ -41,3 +41,13 @@ [PcdsDynamic.common]
gNxpQoriqLsTokenSpaceGuid.PcdPciCfgShiftEnable|FALSE|BOOLEAN|0x00000600
gNxpQoriqLsTokenSpaceGuid.PcdPciLsGen4Ctrl|FALSE|BOOLEAN|0x00000601
gNxpQoriqLsTokenSpaceGuid.PcdPciHideRootPort|FALSE|BOOLEAN|0x00000602
+
+ # Reserved RAM Base address alignment. This number ought to be Power of two
+ # in case no alignment is needed, this number should be 1.
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemAlignment|0x1|UINT64|0x00000603
+ # Size of the RAM to be reserved. This RAM region is neither reported to UEFI
+ # nor to OS
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemSize|0x0|UINT64|0x00000604
+ # Reserved RAM Base address which is calculated based on PcdReservedMemSize
+ # and PcdReservedMemAlignment
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemBase|0x0|UINT64|0x00000605
diff --git a/Silicon/NXP/LX2160A/LX2160A.dsc.inc b/Silicon/NXP/LX2160A/LX2160A.dsc.inc
index 43e361464c8e..755ca169f213 100644
--- a/Silicon/NXP/LX2160A/LX2160A.dsc.inc
+++ b/Silicon/NXP/LX2160A/LX2160A.dsc.inc
@@ -29,6 +29,10 @@ [PcdsDynamicDefault.common]
gArmTokenSpaceGuid.PcdGicRedistributorsBase|0x6200000
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0xC0C0000

+[PcdsDynamicHii]
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemAlignment|L"ReservedMemAlignment"|gEfiGlobalVariableGuid|0x0|0x20000000|NV,BS
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemSize|L"ReservedMemSize"|gEfiGlobalVariableGuid|0x0|0x20000000|NV,BS
+
[PcdsFixedAtBuild.common]
gArmTokenSpaceGuid.PcdGenericWatchdogControlBase|0x23A0000
gArmTokenSpaceGuid.PcdGenericWatchdogRefreshBase|0x2390000
diff --git a/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf b/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf
index a33f8cd3f743..ed23a86b43d9 100644
--- a/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf
+++ b/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf
@@ -49,6 +49,9 @@ [FixedPcd]
[Pcd]
gArmTokenSpaceGuid.PcdSystemMemoryBase
gArmTokenSpaceGuid.PcdSystemMemorySize
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemAlignment
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemBase
+ gNxpQoriqLsTokenSpaceGuid.PcdReservedMemSize

[Depex]
TRUE
diff --git a/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.c b/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.c
index 11d1f1260b35..b416323a4ced 100644
--- a/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.c
+++ b/Silicon/NXP/Library/MemoryInitPeiLib/MemoryInitPeiLib.c
@@ -118,6 +118,127 @@ GetDramRegionsInfo (
return EFI_BUFFER_TOO_SMALL;
}

+/**
+ Calculate the base address of Reserved RAM.
+ Reserved RAM is not reported to either UEFI or OS.
+
+ @param[in, out] DramRegions Array of type DRAM_REGION_INFO. The size of this
+ array must be one more (+ 1) than the maximum
+ regions supported on platform. This is because,
+ if due to Reserved RAM alignment requirements a
+ hole is created in any DRAM region, then the RAM
+ after hole gets reported to UEFI and then
+ subsequently to OS. which is why, the last entry
+ of this array will not be parsed while
+ calculating Reserved RAM base address. Caller
+ must ensure that last entry of this array is zero
+ initialized.
+ @param[in] NumRegions Size of DramRegions array (including +1 for hole)
+ @param[in] ReservedMemSize Size of RAM to be reserved.
+
+ @return if successful Address of the Reserved RAM region, 0 otherwise.
+**/
+STATIC
+UINTN
+CalculateReservedMemBase (
+ IN DRAM_REGION_INFO *DramRegions,
+ IN UINT32 NumRegions,
+ IN UINTN ReservedMemSize
+)
+{
+ UINTN ReservedMemAlignment;
+ EFI_PHYSICAL_ADDRESS AlignmentMask;
+ UINTN RegionBaseAddress;
+ UINTN RegionSize;
+ UINTN ReservedBaseAddress;
+ INTN Index;
+ INTN Index2;
+
+ ReservedMemAlignment = PcdGet64 (PcdReservedMemAlignment);
+ //
+ // Compute alignment bit mask
+ //
+ if (ReservedMemAlignment) {
+ AlignmentMask = LShiftU64 (1, LowBitSet64(ReservedMemAlignment)) - 1;
+ } else {
+ AlignmentMask = 0;
+ }
+
+ // The DRAM region info is sorted based on the RAM address is SOC memory map.
+ // i.e. DramRegions[0] is at lower address, as compared to DramRegions[1].
+ // The goal to start from last region is to find the topmost RAM region that
+ // can contain Reserved RAM region i.e. PcdReservedMemSize.
+ // Since this RAM is not reported to either UEFI or OS, This ensures that
+ // maximum amount of lower RAM (32 bit addresses) are left
+ // for OS to allocate to devices that can only work with 32bit physical
+ // addresses. E.g. legacy devices that need to DMA to 32bit addresses.
+ for (Index = NumRegions - 2; Index >=0; Index--) {
+ RegionBaseAddress = DramRegions[Index].BaseAddress;
+ RegionSize = DramRegions[Index].Size;
+
+ if (ReservedMemSize > RegionSize) {
+ continue;
+ }
+
+ ReservedBaseAddress = (RegionBaseAddress + RegionSize - ReservedMemSize);
+ ReservedBaseAddress &= (~AlignmentMask);
+ if (ReservedBaseAddress < RegionBaseAddress) {
+ continue;
+ }
+
+ // found the region from which reserved mem is to be carved out
+ // Need to modify the region size and create/delete region if need be
+
+ RegionSize -= ReservedMemSize;
+ if (RegionSize == 0) {
+ // delete the region but maintain the sorted list of regions
+ for (Index2 = Index; Index2 < NumRegions; Index2++) {
+ CopyMem (
+ &DramRegions[Index2],
+ &DramRegions[Index2 + 1],
+ sizeof (DRAM_REGION_INFO)
+ );
+ }
+ break;
+ }
+
+ if (ReservedBaseAddress - RegionBaseAddress) {
+ DramRegions[Index].Size = ReservedBaseAddress - RegionBaseAddress;
+ RegionSize -= DramRegions[Index].Size;
+ } else {
+ DramRegions[Index].BaseAddress = ReservedBaseAddress + ReservedMemSize;
+ DramRegions[Index].Size = RegionSize;
+ RegionSize = 0;
+ }
+
+ if (RegionSize == 0) {
+ break;
+ }
+
+ // A hole has been created in DRAM regions due to Reserved RAM alignment
+ // requirements. create a new DRAM region for DRAM memory after hole.
+ // Maintain the sorted list of regions
+ for (Index2 = NumRegions; Index2 > (Index + 1); Index2--) {
+ CopyMem (
+ &DramRegions[Index2],
+ &DramRegions[Index2 - 1],
+ sizeof (DRAM_REGION_INFO)
+ );
+ }
+ DramRegions[Index2].BaseAddress = ReservedBaseAddress + ReservedMemSize;
+ DramRegions[Index2].Size = RegionSize;
+ RegionSize = 0;
+
+ break;
+ }
+
+ if (Index == -1) {
+ return 0;
+ } else {
+ return ReservedBaseAddress;
+ }
+}
+
/**
Get the installed RAM information.
Initialize Memory HOBs (Resource Descriptor HOBs)
@@ -135,7 +256,9 @@ MemoryInitPeiLibConstructor (
UINTN BaseAddress;
UINTN Size;
UINTN Top;
- DRAM_REGION_INFO DramRegions[MAX_DRAM_REGIONS];
+ // Extra region gets created if we want to reserve a memory region and that
+ // creates a memory hole because of alignment requirements
+ DRAM_REGION_INFO DramRegions[MAX_DRAM_REGIONS + 1];
EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
UINTN FdBase;
UINTN FdTop;
@@ -155,6 +278,21 @@ MemoryInitPeiLibConstructor (

(VOID)GetDramRegionsInfo (DramRegions, ARRAY_SIZE (DramRegions));

+ // Get the reserved memory size from non volatile storage
+ Size = PcdGet64 (PcdReservedMemSize);
+ if (Size) {
+ BaseAddress = CalculateReservedMemBase (
+ DramRegions,
+ ARRAY_SIZE (DramRegions),
+ Size
+ );
+ if (BaseAddress) {
+ DEBUG ((DEBUG_INFO, "ReservedMem: start 0x%lx, size 0x%lx\n",
+ BaseAddress, Size));
+ PcdSet64S (PcdReservedMemBase, BaseAddress);
+ }
+ }
+
FdBase = (UINTN)PcdGet64 (PcdFdBaseAddress);
FdTop = FdBase + (UINTN)PcdGet32 (PcdFdSize);

@@ -168,7 +306,7 @@ MemoryInitPeiLibConstructor (
// This ensures that maximum amount of lower RAM (32 bit addresses) are left
// for OS to allocate to devices that can only work with 32bit physical
// addresses. E.g. legacy devices that need to DMA to 32bit addresses.
- for (Index = MAX_DRAM_REGIONS - 1; Index >= 0; Index--) {
+ for (Index = MAX_DRAM_REGIONS; Index >= 0; Index--) {
if (DramRegions[Index].Size == 0) {
continue;
}
--
2.17.1


[PATCH edk2-platforms 1/3] Silicon/NXP: Use runtime safe version of DebugLib

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

For DXE_RUNTIME_DRIVER runtime safe version of DebugLib should be
used. Otherwise, any DEBUG print in code can result in abort in OS.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
---
Silicon/NXP/NxpQoriqLs.dsc.inc | 1 +
1 file changed, 1 insertion(+)

diff --git a/Silicon/NXP/NxpQoriqLs.dsc.inc b/Silicon/NXP/NxpQoriqLs.dsc.inc
index ee639d552483..06ee012c227a 100644
--- a/Silicon/NXP/NxpQoriqLs.dsc.inc
+++ b/Silicon/NXP/NxpQoriqLs.dsc.inc
@@ -163,6 +163,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+ DebugLib|MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf

[LibraryClasses.AARCH64]
#
--
2.17.1


[PATCH edk2-platforms 0/3] Add Features to NXP Platforms

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

This patch series adds some useful features to NXP platforms.
- runtime safe version of DebugLib
- Add support for reserving a chunk from RAM
- Add Support for git commit info print

Pankaj Bansal (3):
Silicon/NXP: Use runtime safe version of DebugLib
Silicon/NXP: Add support for reserving a chunk from RAM
Silicon/NXP: Add Support for git commit info print

Silicon/NXP/NxpQoriqLs.dec | 10 ++
Silicon/NXP/LX2160A/LX2160A.dsc.inc | 4 +
Silicon/NXP/NxpQoriqLs.dsc.inc | 4 +
.../Library/ChassisLib/ChassisLib.inf | 5 +
.../Library/ChassisLib/ChassisLib.inf | 5 +
.../MemoryInitPeiLib/MemoryInitPeiLib.inf | 3 +
.../Chassis2/Library/ChassisLib/ChassisLib.c | 17 +++
.../Library/ChassisLib/ChassisLib.c | 17 +++
.../MemoryInitPeiLib/MemoryInitPeiLib.c | 142 +++++++++++++++++-
Silicon/NXP/set_firmware_ver.sh | 36 +++++
10 files changed, 241 insertions(+), 2 deletions(-)
create mode 100755 Silicon/NXP/set_firmware_ver.sh

--
2.17.1


[PATCH edk2-platforms v3 5/5] Platform/NXP/LS1046aFrwyPkg: Add VarStore

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

Add VarStore Fd. This Fd is used to store non volatile variables in
flash.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>
---

Notes:
V3:
- Added Reviewed-by: Leif Lindholm <leif@...>

V2:
- No change

Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf | 1 +
Platform/NXP/LS1046aFrwyPkg/VarStore.fdf.inc | 91 ++++++++++++++++++++
2 files changed, 92 insertions(+)

diff --git a/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
index 8da5b57cb49e..24af547729c7 100644
--- a/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
+++ b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
@@ -48,6 +48,7 @@ [FD.LS1046AFRWY_EFI]
FV = FVMAIN_COMPACT

!include Platform/NXP/FVRules.fdf.inc
+!include VarStore.fdf.inc
################################################################################
#
# FV Section
diff --git a/Platform/NXP/LS1046aFrwyPkg/VarStore.fdf.inc b/Platform/NXP/LS1046aFrwyPkg/VarStore.fdf.inc
new file mode 100644
index 000000000000..727705feaea1
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/VarStore.fdf.inc
@@ -0,0 +1,91 @@
+## @file
+# FDF include file with FD definition that defines an empty variable store.
+#
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2016, Linaro, Ltd. All rights reserved.
+# Copyright (c) 2016, Freescale Semiconductor. All rights reserved.
+# Copyright 2017-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[FD.LS1046aFrwyNv_EFI]
+BaseAddress = 0x40500000 #The base address of the FLASH device
+Size = 0x000C0000 #The size in bytes of the FLASH device
+ErasePolarity = 1
+BlockSize = 0x1000
+NumBlocks = 0xC0
+
+#
+# Place NV Storage just above Platform Data Base
+#
+DEFINE NVRAM_AREA_VARIABLE_BASE = 0x00000000
+DEFINE NVRAM_AREA_VARIABLE_SIZE = 0x00040000
+DEFINE FTW_WORKING_BASE = $(NVRAM_AREA_VARIABLE_BASE) + $(NVRAM_AREA_VARIABLE_SIZE)
+DEFINE FTW_WORKING_SIZE = 0x00040000
+DEFINE FTW_SPARE_BASE = $(FTW_WORKING_BASE) + $(FTW_WORKING_SIZE)
+DEFINE FTW_SPARE_SIZE = 0x00040000
+
+#############################################################################
+# LS1046AFRWY NVRAM Area
+# LS1046AFRWY NVRAM Area contains: Variable + FTW Working + FTW Spare
+#############################################################################
+
+
+$(NVRAM_AREA_VARIABLE_BASE)|$(NVRAM_AREA_VARIABLE_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#NV_VARIABLE_STORE
+DATA = {
+ ## This is the EFI_FIRMWARE_VOLUME_HEADER
+ # ZeroVector []
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # FileSystemGuid: gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B,
+ # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+ # FvLength: Flash Size : 0x4000000
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ # Signature "_FVH" # Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0x36, 0x0E, 0x00, 0x00,
+ # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
+ 0x48, 0x00, 0x08, 0xA6, 0x00, 0x00, 0x00, 0x02,
+ # Blockmap[0]: 0x4000 Blocks * 0x1000 Bytes / Block = SIZE_64MB
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ # Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+ # It is compatible with SECURE_BOOT_ENABLE == FALSE as well.
+ # Signature: gEfiVariableGuid =
+ # { 0xddcf3616, 0x3275, 0x4164,
+ # { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
+ 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
+ 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
+ # Size: 0x40000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+ # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x3ffb8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0xFF, 0x03, 0x00,
+ # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(FTW_WORKING_BASE)|$(FTW_WORKING_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#NV_FTW_WORKING
+DATA = {
+ # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
+ # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+ 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+ 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95,
+ # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+ 0x5b, 0xe7, 0xc6, 0x86, 0xFE, 0xFF, 0xFF, 0xFF,
+ # WriteQueueSize: UINT64
+ 0xE0, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(FTW_SPARE_BASE)|$(FTW_SPARE_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+#NV_FTW_SPARE
--
2.17.1


[PATCH edk2-platforms v3 4/5] Platform/NXP: Add LS1046AFRWY Platform

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

LS1046A Freeway (FRWY) is a high-performance development
platform that supports the QorIQ LS1046A Layerscape Architecture SOCs.

Co-authored-by: Pramod Kumar <pramod.kumar_1@...>
Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
---

Notes:
V3:
- Squashed previous commit to this commit

V2:
- No change

Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dec | 23 +++
Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dsc | 46 ++++++
Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf | 168 ++++++++++++++++++++
Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.inf | 42 +++++
Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.c | 147 +++++++++++++++++
Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c | 75 +++++++++
Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S | 45 ++++++
7 files changed, 546 insertions(+)

diff --git a/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dec b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dec
new file mode 100644
index 000000000000..a693d8262444
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dec
@@ -0,0 +1,23 @@
+# LS1046aFrwyPkg.dec
+# LS1046a board package.
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+[Defines]
+ PACKAGE_NAME = LS1046aFrwyPkg
+ PACKAGE_GUID = 3547d88c-62c2-4fb2-a11b-80245f80928f
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+ Include # Root include for the package
diff --git a/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dsc b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dsc
new file mode 100644
index 000000000000..3f29dadd5d1d
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dsc
@@ -0,0 +1,46 @@
+# LS1046aFrwyPkg.dsc
+#
+# LS1046AFRWY Board package.
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ #
+ # Defines for default states. These can be changed on the command line.
+ # -D FLAG=VALUE
+ #
+ PLATFORM_NAME = LS1046aFrwyPkg
+ PLATFORM_GUID = 79adaa48-5f50-49f0-aa9a-544ac9260ef8
+ OUTPUT_DIRECTORY = Build/LS1046aFrwyPkg
+ FLASH_DEFINITION = Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
+
+!include Silicon/NXP/NxpQoriqLs.dsc.inc
+!include Silicon/NXP/LS1046A/LS1046A.dsc.inc
+
+[LibraryClasses.common]
+ ArmPlatformLib|Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
+ RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform
+#
+################################################################################
+[Components.common]
+ #
+ # Architectural Protocols
+ #
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+ <PcdsFixedAtBuild>
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
+ }
+
+##
diff --git a/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
new file mode 100644
index 000000000000..8da5b57cb49e
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
@@ -0,0 +1,168 @@
+# LS1046aFrwyPkg.fdf
+#
+# FLASH layout file for LS1046a board.
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+################################################################################
+#
+# FD Section
+# The [FD] Section is made up of the definition statements and a
+# description of what goes into the Flash Device Image. Each FD section
+# defines one flash "device" image. A flash device image may be one of
+# the following: Removable media bootable image (like a boot floppy
+# image,) an Option ROM image (that would be "flashed" into an add-in
+# card,) a System "Flash" image (that would be burned into a system's
+# flash) or an Update ("Capsule") image that will be used to update and
+# existing system flash.
+#
+################################################################################
+
+[FD.LS1046AFRWY_EFI]
+BaseAddress = 0x82000000|gArmTokenSpaceGuid.PcdFdBaseAddress #The base address of the FLASH Device.
+Size = 0x00140000|gArmTokenSpaceGuid.PcdFdSize #The size in bytes of the FLASH Device
+ErasePolarity = 1
+BlockSize = 0x1000
+NumBlocks = 0x140
+
+################################################################################
+#
+# Following are lists of FD Region layout which correspond to the locations of different
+# images within the flash device.
+#
+# Regions must be defined in ascending order and may not overlap.
+#
+# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by
+# the pipe "|" character, followed by the size of the region, also in hex with the leading
+# "0x" characters. Like:
+# Offset|Size
+# PcdOffsetCName|PcdSizeCName
+# RegionType <FV, DATA, or FILE>
+#
+################################################################################
+0x00000000|0x00140000
+gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
+FV = FVMAIN_COMPACT
+
+!include Platform/NXP/FVRules.fdf.inc
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+
+[FV.FvMain]
+FvNameGuid = 1037c42b-8452-4c41-aac7-41e6c31468da
+BlockSize = 0x1
+NumBlocks = 0 # This FV gets compressed so make it just big enough
+FvAlignment = 8 # FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+ INF MdeModulePkg/Core/Dxe/DxeMain.inf
+ INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+ #
+ # PI DXE Drivers producing Architectural Protocols (EFI Services)
+ #
+ INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+
+ INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+ INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+ INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+ INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+ INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+ INF MdeModulePkg/Universal/Metronome/Metronome.inf
+ INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+
+ #
+ # Multiple Console IO support
+ #
+ INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+ INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+ INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
+
+ INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+ INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+ INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+
+ #
+ # FAT filesystem + GPT/MBR partitioning
+ #
+ INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+ INF FatPkg/EnhancedFatDxe/Fat.inf
+ INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+
+ #
+ # UEFI application (Shell Embedded Boot Loader)
+ #
+ INF ShellPkg/Application/Shell/Shell.inf
+
+ #
+ # Bds
+ #
+ INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+ INF MdeModulePkg/Application/UiApp/UiApp.inf
+
+[FV.FVMAIN_COMPACT]
+FvAlignment = 8
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+ INF ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf
+ INF MdeModulePkg/Core/Pei/PeiMain.inf
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+ INF MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
+ INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+ INF ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
+ INF ArmPkg/Drivers/CpuPei/CpuPei.inf
+ INF ArmPlatformPkg/PlatformPei/PlatformPeim.inf
+ INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+ SECTION FV_IMAGE = FVMAIN
+ }
+ }
diff --git a/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.inf b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
new file mode 100644
index 000000000000..7802696bf39b
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
@@ -0,0 +1,42 @@
+# @file
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = PlatformLib
+ FILE_GUID = c61c8a13-36a0-46f4-a3bc-7bab5a55db81
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmPlatformLib
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/NXP/Chassis2/Chassis2.dec
+ Silicon/NXP/LS1046A/LS1046A.dec
+ Silicon/NXP/NxpQoriqLs.dec
+
+[LibraryClasses]
+ ArmLib
+ DebugLib
+ SocLib
+
+[Sources.common]
+ ArmPlatformLib.c
+ ArmPlatformLibMem.c
+
+[Sources.AArch64]
+ AArch64/ArmPlatformHelper.S
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmPrimaryCore
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
+
+[Ppis]
+ gArmMpCoreInfoPpiGuid
diff --git a/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.c b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.c
new file mode 100644
index 000000000000..e1f20da09337
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.c
@@ -0,0 +1,147 @@
+/** @file
+*
+* Copyright 2019-2020 NXP
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/ArmLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/SocLib.h>
+
+#include <Ppi/ArmMpCoreInfo.h>
+#include <Ppi/NxpPlatformGetClock.h>
+
+ARM_CORE_INFO mLS1046aMpCoreInfoTable[] = {
+ {
+ // Cluster 0, Core 0
+ 0x0, 0x0,
+
+ // MP Core MailBox Set/Get/Clear Addresses and Clear Value
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (EFI_PHYSICAL_ADDRESS)0,
+ (UINT64)0xFFFFFFFF
+ }
+};
+
+/**
+ Return the current Boot Mode
+
+ This function returns the boot reason on the platform
+
+**/
+EFI_BOOT_MODE
+ArmPlatformGetBootMode (
+ VOID
+ )
+{
+ return BOOT_WITH_FULL_CONFIGURATION;
+}
+
+/**
+ Get the clocks supplied by Platform(Board) to NXP Layerscape SOC IPs
+
+ @param[in] ClockType Variable of Type NXP_IP_CLOCK. Indicates which IP clock
+ is to be retrieved.
+ @param[in] ... Variable argument list which is parsed based on
+ ClockType. e.g. if the ClockType is NXP_I2C_CLOCK, then
+ the second argument will be interpreted as controller
+ number.
+ if ClockType is NXP_CORE_CLOCK, then second argument
+ is interpreted as cluster number and third argument is
+ interpreted as core number (within the cluster)
+
+ @return Actual Clock Frequency. Return value 0 should be
+ interpreted as clock not being provided to IP.
+**/
+UINT64
+EFIAPI
+NxpPlatformGetClock(
+ IN UINT32 ClockType,
+ ...
+ )
+{
+ UINT64 Clock;
+ VA_LIST Args;
+
+ Clock = 0;
+
+ VA_START (Args, ClockType);
+
+ switch (ClockType) {
+ case NXP_SYSTEM_CLOCK:
+ Clock = 100 * 1000 * 1000; // 100 MHz
+ break;
+ case NXP_I2C_CLOCK:
+ case NXP_UART_CLOCK:
+ Clock = NxpPlatformGetClock (NXP_SYSTEM_CLOCK);
+ Clock = SocGetClock (Clock, ClockType, Args);
+ break;
+ default:
+ break;
+ }
+
+ VA_END (Args);
+
+ return Clock;
+}
+
+/**
+ Initialize controllers that must setup in the normal world
+
+ This function is called by the ArmPlatformPkg/PrePi or ArmPlatformPkg/PlatformPei
+ in the PEI phase.
+
+**/
+EFI_STATUS
+ArmPlatformInitialize (
+ IN UINTN MpId
+ )
+{
+ SocInit ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PrePeiCoreGetMpCoreInfo (
+ OUT UINTN *CoreCount,
+ OUT ARM_CORE_INFO **ArmCoreTable
+ )
+{
+ if (ArmIsMpCore()) {
+ *CoreCount = sizeof(mLS1046aMpCoreInfoTable) / sizeof(ARM_CORE_INFO);
+ *ArmCoreTable = mLS1046aMpCoreInfoTable;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo };
+NXP_PLATFORM_GET_CLOCK_PPI gPlatformGetClockPpi = { NxpPlatformGetClock };
+
+EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gArmMpCoreInfoPpiGuid,
+ &mMpCoreInfoPpi
+ }
+};
+
+VOID
+ArmPlatformGetPlatformPpiList (
+ OUT UINTN *PpiListSize,
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList
+ )
+{
+ if (ArmIsMpCore()) {
+ *PpiListSize = sizeof(gPlatformPpiTable);
+ *PpiList = gPlatformPpiTable;
+ } else {
+ *PpiListSize = 0;
+ *PpiList = NULL;
+ }
+}
diff --git a/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c
new file mode 100644
index 000000000000..f712d5931821
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c
@@ -0,0 +1,75 @@
+/** @file
+*
+* Copyright 2019-2020 NXP
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Soc.h>
+
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 5
+
+/**
+ Return the Virtual Memory Map of your platform
+
+ This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform.
+
+ @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to-
+ Virtual Memory mapping. This array must be ended by a zero-filled
+ entry
+
+**/
+VOID
+ArmPlatformGetVirtualMemoryMap (
+ IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
+ )
+{
+ UINTN Index;
+ ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
+
+ Index = 0;
+
+ ASSERT (VirtualMemoryMap != NULL);
+
+ VirtualMemoryTable = AllocatePool (sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
+ MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
+
+ if (VirtualMemoryTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Error: Failed AllocatePool()\n", __FUNCTION__));
+ return;
+ }
+
+ VirtualMemoryTable[Index].PhysicalBase = LS1046A_DRAM0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1046A_DRAM0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1046A_DRAM0_SIZE;
+ VirtualMemoryTable[Index++].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
+
+ VirtualMemoryTable[Index].PhysicalBase = LS1046A_DRAM1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1046A_DRAM1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1046A_DRAM1_SIZE;
+ VirtualMemoryTable[Index++].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
+
+ // CCSR Space
+ VirtualMemoryTable[Index].PhysicalBase = LS1046A_CCSR_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1046A_CCSR_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1046A_CCSR_SIZE;
+ VirtualMemoryTable[Index++].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+ // QSPI
+ VirtualMemoryTable[Index].PhysicalBase = LS1046A_QSPI0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1046A_QSPI0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1046A_QSPI0_SIZE;
+ VirtualMemoryTable[Index++].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+
+ // End of Table
+ ZeroMem (&VirtualMemoryTable[Index], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+
+ ASSERT (Index < MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS);
+
+ *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S
new file mode 100644
index 000000000000..4f56a1c366ab
--- /dev/null
+++ b/Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2012-2013, ARM Limited. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+
+#include <AsmMacroIoLibV8.h>
+#include <Library/ArmLib.h>
+
+ASM_FUNC(ArmPlatformPeiBootAction)
+ ret
+
+//UINTN
+//ArmPlatformGetCorePosition (
+// IN UINTN MpId
+// );
+// With this function: CorePos = (ClusterId * 4) CoreId
+ASM_FUNC(ArmPlatformGetCorePosition)
+ and x1, x0, #ARM_CORE_MASK
+ and x0, x0, #ARM_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+
+//UINTN
+//ArmPlatformGetPrimaryCoreMpId (
+// VOID
+// );
+ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
+ MOV32 (w0, FixedPcdGet32 (PcdArmPrimaryCore))
+ ret
+
+//UINTN
+//ArmPlatformIsPrimaryCore (
+// IN UINTN MpId
+// );
+ASM_FUNC(ArmPlatformIsPrimaryCore)
+ MOV32 (w1, FixedPcdGet32 (PcdArmPrimaryCoreMask))
+ and x0, x0, x1
+ MOV32 (w1, FixedPcdGet32 (PcdArmPrimaryCore))
+ cmp w0, w1
+ mov x0, #1
+ mov x1, #0
+ csel x0, x0, x1, eq
+ ret
--
2.17.1


[PATCH edk2-platforms v3 3/5] Silicon/NXP: Add LS1046A Soc package

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

LS1046A is QorIq Layerscape multicore communications processor with
four Arm Cortex-A72 cores.
This SOC is based on Layerscape Chassis v2.

Co-authored-by: Vabhav Sharma <vabhav.sharma@...>
Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>
---

Notes:
V3:
- Removed Co-authored-by: Pankaj Bansal <pankaj.bansal@...>
- Added Reviewed-by: Leif Lindholm <leif@...>

V2:
- No change

Silicon/NXP/LS1046A/LS1046A.dec | 13 +++
Silicon/NXP/LS1046A/LS1046A.dsc.inc | 42 +++++++
Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf | 27 +++++
Silicon/NXP/LS1046A/Include/Soc.h | 63 +++++++++++
Silicon/NXP/LS1046A/Include/SocSerDes.h | 33 ++++++
Silicon/NXP/LS1046A/Library/SocLib/SerDes.c | 119 ++++++++++++++++++++
Silicon/NXP/LS1046A/Library/SocLib/SocLib.c | 78 +++++++++++++
7 files changed, 375 insertions(+)

diff --git a/Silicon/NXP/LS1046A/LS1046A.dec b/Silicon/NXP/LS1046A/LS1046A.dec
new file mode 100644
index 000000000000..bf4863c6d89e
--- /dev/null
+++ b/Silicon/NXP/LS1046A/LS1046A.dec
@@ -0,0 +1,13 @@
+# LS1046A.dec
+#
+# Copyright 2017, 2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+
+[Defines]
+ DEC_SPECIFICATION = 0x0001001A
+
+[Includes]
+ Include
diff --git a/Silicon/NXP/LS1046A/LS1046A.dsc.inc b/Silicon/NXP/LS1046A/LS1046A.dsc.inc
new file mode 100644
index 000000000000..dbe7f408fce9
--- /dev/null
+++ b/Silicon/NXP/LS1046A/LS1046A.dsc.inc
@@ -0,0 +1,42 @@
+# LS1046A.dsc
+# LS1046A Soc package.
+#
+# Copyright 2017-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+
+!include Silicon/NXP/Chassis2/Chassis2.dsc.inc
+
+[LibraryClasses.common]
+ SocLib|Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf
+ SerialPortLib|Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsDynamicDefault.common]
+
+ #
+ # ARM General Interrupt Controller
+ gArmTokenSpaceGuid.PcdGicDistributorBase|0x01410000
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x01420000
+
+[PcdsFixedAtBuild.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x021c0500
+
+[PcdsFeatureFlag]
+ gNxpQoriqLsTokenSpaceGuid.PcdDcfgBigEndian|TRUE
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform
+#
+################################################################################
+[Components.common]
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+
+##
diff --git a/Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf b/Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf
new file mode 100644
index 000000000000..01ed0f6592d2
--- /dev/null
+++ b/Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf
@@ -0,0 +1,27 @@
+# @file
+#
+# Copyright 2017-2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = SocLib
+ FILE_GUID = ddd5f950-8816-4d38-8f98-f42b07333f78
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SocLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Silicon/NXP/Chassis2/Chassis2.dec
+ Silicon/NXP/LS1046A/LS1046A.dec
+ Silicon/NXP/NxpQoriqLs.dec
+
+[LibraryClasses]
+ ChassisLib
+ DebugLib
+
+[Sources.common]
+ SocLib.c
diff --git a/Silicon/NXP/LS1046A/Include/Soc.h b/Silicon/NXP/LS1046A/Include/Soc.h
new file mode 100644
index 000000000000..84f433d5cb94
--- /dev/null
+++ b/Silicon/NXP/LS1046A/Include/Soc.h
@@ -0,0 +1,63 @@
+/** @file
+
+ Copyright 2020 NXP
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef SOC_H__
+#define SOC_H__
+
+#include <Chassis.h>
+
+/**
+ Soc Memory Map
+**/
+#define LS1046A_DRAM0_PHYS_ADDRESS (BASE_2GB)
+#define LS1046A_DRAM0_SIZE (SIZE_2GB)
+#define LS1046A_DRAM1_PHYS_ADDRESS (BASE_32GB + BASE_2GB)
+#define LS1046A_DRAM1_SIZE (SIZE_32GB - SIZE_2GB) // 30 GB
+
+#define LS1046A_CCSR_PHYS_ADDRESS (BASE_16MB)
+#define LS1046A_CCSR_SIZE (SIZE_256MB - SIZE_16MB) // 240MB
+
+#define LS1046A_QSPI0_PHYS_ADDRESS (BASE_1GB)
+#define LS1046A_QSPI0_SIZE (SIZE_512MB)
+
+#define LS1046A_DCFG_ADDRESS NXP_LAYERSCAPE_CHASSIS2_DCFG_ADDRESS
+
+/**
+ Reset Control Word (RCW) Bits
+
+ RCWSR contains the Reset Configuration Word (RCW) information written with
+ values read from flash memory by the device at power-on reset and read-only
+ upon exiting reset.
+
+ RCW bits in RCWSR registers are mirror of bit position in Little Endian (LE)
+
+RCW Bits |
+in RCWSR |
+(MSBit 0)| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+------------------------------------------------------------------------------------------------
+LE | 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+(LSBit 0)|
+
+ Moreover the RCW bits are to be interpreted in below fasion
+
+Bit(s) | Field Name | Description | Notes/comments
+----------------------------------------------------------------------
+ 2-6 | SYS_PLL_RAT | System PLL Multiplier/Ratio | This field selects the platform
+ | | | clock:SYSCLK ratio.
+ | | | 0_0011 3:1
+ | | | 0_0100 4:1
+ | | | 0_1101 13:1
+ | | | 0_1111 15:1
+ | | | 1_0000 16:1
+
+ which is why the RCW bits in RCWSR registers are parsed this way
+**/
+#define SYS_PLL_RAT(x) (((x) >> 25) & 0x1f) // Bits 2-6
+
+typedef NXP_LAYERSCAPE_CHASSIS2_DEVICE_CONFIG LS1046A_DEVICE_CONFIG;
+
+#endif // SOC_H__
diff --git a/Silicon/NXP/LS1046A/Include/SocSerDes.h b/Silicon/NXP/LS1046A/Include/SocSerDes.h
new file mode 100644
index 000000000000..2fc5651c004c
--- /dev/null
+++ b/Silicon/NXP/LS1046A/Include/SocSerDes.h
@@ -0,0 +1,33 @@
+/** SocSerDes.h
+ SoC Specific header file for SerDes
+
+ Copyright 2017-2020 NXP
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef SOC_SERDES_H
+#define SOC_SERDES_H
+
+typedef enum {
+ NONE = 0,
+ PCIE1,
+ PCIE2,
+ PCIE3,
+ SATA,
+ SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC5,
+ SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC9,
+ SGMII_FM1_DTSEC10,
+ QSGMII_FM1_A,
+ XFI_FM1_MAC9,
+ XFI_FM1_MAC10,
+ SGMII_2500_FM1_DTSEC2,
+ SGMII_2500_FM1_DTSEC5,
+ SGMII_2500_FM1_DTSEC9,
+ SGMII_2500_FM1_DTSEC10,
+ SERDES_PROTOCOL_COUNT
+} SERDES_PROTOCOL;
+#endif
diff --git a/Silicon/NXP/LS1046A/Library/SocLib/SerDes.c b/Silicon/NXP/LS1046A/Library/SocLib/SerDes.c
new file mode 100644
index 000000000000..a50e0b61e19a
--- /dev/null
+++ b/Silicon/NXP/LS1046A/Library/SocLib/SerDes.c
@@ -0,0 +1,119 @@
+/** SerDes.c
+ Provides SoC specific SerDes interface
+
+ Copyright 2017-2020 NXP
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/ChassisLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SerDesHelperLib.h>
+#include <SocSerDes.h>
+#include <Soc.h>
+#include <Uefi.h>
+
+// SerDes1 Protocol Mask in Reset Configuration Word (RCW) Status Register
+#define SERDES1_PROTOCOL_MASK 0xffff0000
+
+// SerDes1 Protocol Shift in Reset Configuration Word (RCW) Status Register
+#define SERDES1_PROTOCOL_SHIFT 16
+
+STATIC SERDES_CONFIG mSerDes1ConfigTable[] = {
+ {0x1555, {XFI_FM1_MAC9, PCIE1, PCIE2, PCIE3 } },
+ {0x2555, {SGMII_2500_FM1_DTSEC9, PCIE1, PCIE2, PCIE3 } },
+ {0x4555, {QSGMII_FM1_A, PCIE1, PCIE2, PCIE3 } },
+ {0x4558, {QSGMII_FM1_A, PCIE1, PCIE2, SATA } },
+ {0x1355, {XFI_FM1_MAC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3 } },
+ {0x2355, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3 } },
+ {0x3335, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5, PCIE3 } },
+ {0x3355, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3 } },
+ {0x3358, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, SATA } },
+ {0x3555, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, PCIE3 } },
+ {0x3558, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, SATA } },
+ {0x7000, {PCIE1, PCIE1, PCIE1, PCIE1 } },
+ {0x9998, {PCIE1, PCIE2, PCIE3, SATA } },
+ {0x6058, {PCIE1, PCIE1, PCIE2, SATA } },
+ {0x1455, {XFI_FM1_MAC9, QSGMII_FM1_A, PCIE2, PCIE3 } },
+ {0x2455, {SGMII_2500_FM1_DTSEC9, QSGMII_FM1_A, PCIE2, PCIE3 } },
+ {0x2255, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC2, PCIE2, PCIE3 } },
+ {0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6 } },
+ {0x1460, {XFI_FM1_MAC9, QSGMII_FM1_A, PCIE3, PCIE3 } },
+ {0x2460, {SGMII_2500_FM1_DTSEC9, QSGMII_FM1_A, PCIE3, PCIE3 } },
+ {0x3460, {SGMII_FM1_DTSEC9, QSGMII_FM1_A, PCIE3, PCIE3 } },
+ {0x3455, {SGMII_FM1_DTSEC9, QSGMII_FM1_A, PCIE2, PCIE3 } },
+ {0x9960, {PCIE1, PCIE2, PCIE3, PCIE3 } },
+ {0x2233, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6 } },
+ {0x2533, {SGMII_2500_FM1_DTSEC9, PCIE1, SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6 } },
+ {}
+};
+
+SERDES_CONFIG *gSerDesConfig[] = {
+ mSerDes1ConfigTable
+};
+
+/**
+ Probe all SerDes for lane protocol and execute provided callback function.
+
+ @param SerDesLaneProbeCallback Pointer Callback function to be called for Lane protocol
+ @param Arg Pointer to Arguments to be passed to callback function.
+
+**/
+VOID
+SerDesProbeLanes (
+ IN SERDES_PROBE_LANES_CALLBACK SerDesLaneProbeCallback,
+ IN VOID *Arg
+ )
+{
+ UINT32 SerDesProtocol;
+ LS1046A_DEVICE_CONFIG *DeviceConfig;
+
+ DeviceConfig = (LS1046A_DEVICE_CONFIG *)LS1046A_DCFG_ADDRESS;
+ SerDesProtocol = DcfgRead32 ((UINTN)&DeviceConfig->RcwSr[4]) & SERDES1_PROTOCOL_MASK;
+ SerDesProtocol >>= SERDES1_PROTOCOL_SHIFT;
+
+ SerDesInstanceProbeLanes (
+ SERDES_1,
+ SerDesProtocol,
+ FixedPcdGet8 (PcdSerDesLanes),
+ SERDES_PROTOCOL_COUNT,
+ gSerDesConfig[SERDES_1],
+ SerDesLaneProbeCallback,
+ Arg
+ );
+}
+
+/**
+ Function to return SerDes protocol map for all SerDes available on board.
+
+ @param SerDesProtocolMap Pointer to SerDes protocl map.
+
+**/
+VOID
+GetSerDesProtocolMap (
+ OUT UINT64 *SerDesProtocolMap
+ )
+{
+ UINT32 SerDesProtocol;
+ LS1046A_DEVICE_CONFIG *DeviceConfig;
+ EFI_STATUS Status;
+
+ *SerDesProtocolMap = 0;
+ DeviceConfig = (LS1046A_DEVICE_CONFIG *)LS1046A_DCFG_ADDRESS;
+ SerDesProtocol = DcfgRead32 ((UINTN)&DeviceConfig->RcwSr[4]) & SERDES1_PROTOCOL_MASK;
+ SerDesProtocol >>= SERDES1_PROTOCOL_SHIFT;
+
+ Status = GetSerDesMap (
+ SERDES_1,
+ SerDesProtocol,
+ FixedPcdGet8 (PcdSerDesLanes),
+ SERDES_PROTOCOL_COUNT,
+ gSerDesConfig[SERDES_1],
+ SerDesProtocolMap
+ );
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "%a: failed for SerDes1 \n",__FUNCTION__));
+ *SerDesProtocolMap = 0;
+ }
+}
diff --git a/Silicon/NXP/LS1046A/Library/SocLib/SocLib.c b/Silicon/NXP/LS1046A/Library/SocLib/SocLib.c
new file mode 100644
index 000000000000..3b15aee6ecae
--- /dev/null
+++ b/Silicon/NXP/LS1046A/Library/SocLib/SocLib.c
@@ -0,0 +1,78 @@
+/** @Soc.c
+ SoC specific Library containg functions to initialize various SoC components
+
+ Copyright 2017-2020 NXP
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/ChassisLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SocLib.h>
+#include <Soc.h>
+
+/**
+ Return the input clock frequency to an IP Module.
+ This function reads the RCW bits and calculates the PLL multiplier/divider
+ values to be applied to various IP modules.
+ If a module is disabled or doesn't exist on platform, then return zero.
+
+ @param[in] BaseClock Base clock to which PLL multiplier/divider values is
+ to be applied.
+ @param[in] ClockType Variable of Type NXP_IP_CLOCK. Indicates which IP clock
+ is to be retrieved.
+ @param[in] Args Variable argument list which is parsed based on
+ ClockType. e.g. if the ClockType is NXP_I2C_CLOCK, then
+ the second argument will be interpreted as controller
+ number. e.g. if there are four i2c controllers in SOC,
+ then this value can be 0, 1, 2, 3
+ e.g. if ClockType is NXP_CORE_CLOCK, then second
+ argument is interpreted as cluster number and third
+ argument is interpreted as core number (within the
+ cluster)
+
+ @return Actual Clock Frequency. Return value 0 should be
+ interpreted as clock not being provided to IP.
+**/
+UINT64
+SocGetClock (
+ IN UINT64 BaseClock,
+ IN NXP_IP_CLOCK ClockType,
+ IN VA_LIST Args
+ )
+{
+ LS1046A_DEVICE_CONFIG *Dcfg;
+ UINT32 RcwSr;
+ UINT64 ReturnValue;
+
+ ReturnValue = 0;
+ Dcfg = (LS1046A_DEVICE_CONFIG *)LS1046A_DCFG_ADDRESS;
+
+ switch (ClockType) {
+ case NXP_UART_CLOCK:
+ case NXP_I2C_CLOCK:
+ RcwSr = DcfgRead32 ((UINTN)&Dcfg->RcwSr[0]);
+ ReturnValue = BaseClock * SYS_PLL_RAT (RcwSr);
+ ReturnValue >>= 1; // 1/2 Platform Clock
+ break;
+ default:
+ break;
+ }
+
+ return ReturnValue;
+}
+
+/**
+ Function to initialize SoC specific constructs
+ **/
+VOID
+SocInit (
+ VOID
+ )
+{
+ ChassisInit ();
+
+ return;
+}
--
2.17.1


[PATCH edk2-platforms v3 2/5] Silicon/NXP/LS1043A: Fix the RCW bits' parsing

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

For LS1043A SOC the DCFG registers are read in big endian format.
After Reading the registers in code we have the registers in Little
Endian Bit format i.e. LSBit 0.

However, the RCW bits in RCWSR registers in LS1043A SOC are in MSBit 0
format.

Currently, we are parsing the RCW bits in LE bit format i.e. LSBit 0.
Therefore, Fix the RCW bits' parsing as per MSBit 0.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>
---

Notes:
V3:
- Added Reviewed-by: Leif Lindholm <leif@...>

V2:
- Changed commit header and description.
- Moved changes in comments to previous commit

Silicon/NXP/LS1043A/Include/Soc.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Silicon/NXP/LS1043A/Include/Soc.h b/Silicon/NXP/LS1043A/Include/Soc.h
index c694576ed18d..40619536c6fe 100644
--- a/Silicon/NXP/LS1043A/Include/Soc.h
+++ b/Silicon/NXP/LS1043A/Include/Soc.h
@@ -78,7 +78,7 @@ Bit(s) | Field Name | Description | Notes/comments

which is why the RCW bits in RCWSR registers are parsed this way
**/
-#define SYS_PLL_RAT(x) (((x) & 0x7c) >> 2) // Bits 2-6
+#define SYS_PLL_RAT(x) (((x) >> 25) & 0x1f) // Bits 2-6

typedef NXP_LAYERSCAPE_CHASSIS2_DEVICE_CONFIG LS1043A_DEVICE_CONFIG;

--
2.17.1


[PATCH edk2-platforms v3 1/5] Silicon/NXP: Add comments explaining RCW bits' parsing

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

RCW bits parsing and their interpretation varies between various SOCs.
Add the comments that explain this parsing scheme.

Based on this explanation, fix the comments for SYS_PLL_RAT parsing
in LX2160A.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>
---

Notes:
V3:
- Added Reviewed-by: Leif Lindholm <leif@...>

V2:
- new commit

Silicon/NXP/LS1043A/Include/Soc.h | 27 +++++++++++++++++++
Silicon/NXP/LX2160A/Include/Soc.h | 28 +++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/Silicon/NXP/LS1043A/Include/Soc.h b/Silicon/NXP/LS1043A/Include/Soc.h
index 21b0dafffe91..c694576ed18d 100644
--- a/Silicon/NXP/LS1043A/Include/Soc.h
+++ b/Silicon/NXP/LS1043A/Include/Soc.h
@@ -50,6 +50,33 @@

/**
Reset Control Word (RCW) Bits
+
+ RCWSR contains the Reset Configuration Word (RCW) information written with
+ values read from flash memory by the device at power-on reset and read-only
+ upon exiting reset.
+
+ RCW bits in RCWSR registers are mirror of bit position in Little Endian (LE)
+
+RCW Bits |
+in RCWSR |
+(MSBit 0)| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+------------------------------------------------------------------------------------------------
+LE | 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+(LSBit 0)|
+
+ Moreover the RCW bits are to be interpreted in below fasion
+
+Bit(s) | Field Name | Description | Notes/comments
+----------------------------------------------------------------------
+ 2-6 | SYS_PLL_RAT | System PLL Multiplier/Ratio | This field selects the platform
+ | | | clock:SYSCLK ratio.
+ | | | 0_0011 3:1
+ | | | 0_0100 4:1
+ | | | 0_1101 13:1
+ | | | 0_1111 15:1
+ | | | 1_0000 16:1
+
+ which is why the RCW bits in RCWSR registers are parsed this way
**/
#define SYS_PLL_RAT(x) (((x) & 0x7c) >> 2) // Bits 2-6

diff --git a/Silicon/NXP/LX2160A/Include/Soc.h b/Silicon/NXP/LX2160A/Include/Soc.h
index d62b8adcdbe7..e8198addc966 100644
--- a/Silicon/NXP/LX2160A/Include/Soc.h
+++ b/Silicon/NXP/LX2160A/Include/Soc.h
@@ -36,8 +36,34 @@

/**
Reset Control Word (RCW) Bits
+
+ RCWSR contains the Reset Configuration Word (RCW) information written with
+ values read from flash memory by the device at power-on reset and read-only
+ upon exiting reset.
+
+ RCW bits in RCWSR registers are same as bit position in Little Endian (LE)
+
+RCW Bits |
+in RCWSR |
+(LSBit 0)| 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+------------------------------------------------------------------------------------------------
+LE | 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+(LSBit 0)|
+
+ Moreover the RCW bits are to be interpreted in below fasion
+
+Bit(s) | Field Name | Description | Notes/comments
+----------------------------------------------------------------------
+ 6-2 | SYS_PLL_RAT | System PLL Multiplier/Ratio | This field selects the platform
+ | | | clock:SYSCLK ratio.
+ | | | 0_0100 4:1
+ | | | 0_0110 6:1
+ | | | 0_1000 8:1
+ | | | 0_1101 13:1
+ | | | 0_1111 15:1
+
**/
-#define SYS_PLL_RAT(x) (((x) & 0x7c) >> 2) // Bits 2-6
+#define SYS_PLL_RAT(x) (((x) & 0x7c) >> 2) // Bits 6-2

typedef NXP_LAYERSCAPE_CHASSIS3V2_DEVICE_CONFIG LX2160A_DEVICE_CONFIG;

--
2.17.1


[PATCH edk2-platforms v3 0/5] Add LS1046AFRWY Platform

Pankaj Bansal
 

From: Pankaj Bansal <pankaj.bansal@...>

The Layerscape LS1046A Freeway (FRWY-LS1046A) board is a high-performance
development platform that supports the QorIQ LS1046A architecture
processor.

The LS1046A SOC is based on Layerscape Chassis2.

The code structure is same as Chassis2 and LS1043A SOC and LS1043ARDB
platform.

V2 can be referred here:
https://edk2.groups.io/g/devel/message/62064

Changes in V2 w.r.t V1:
- No functional changes
- Removed Co-authored-by: Pankaj Bansal <pankaj.bansal@...>
from "PATCH 3/6 Silicon/NXP: Add LS1046A Soc package" and
"PATCH 5/6 Platform/NXP: Add LS1046AFRWY Platform"
- Squashed "PATCH 4/6 Platform/NXP/LS1046AFRWY: Add ArmPlatformLib"
in "PATCH 5/6 Platform/NXP: Add LS1046AFRWY Platform"

Pankaj Bansal (5):
Silicon/NXP: Add comments explaining RCW bits' parsing
Silicon/NXP/LS1043A: Fix the RCW bits' parsing
Silicon/NXP: Add LS1046A Soc package
Platform/NXP: Add LS1046AFRWY Platform
Platform/NXP/LS1046aFrwyPkg: Add VarStore

.../NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dec | 23 +++
Silicon/NXP/LS1046A/LS1046A.dec | 13 ++
Silicon/NXP/LS1046A/LS1046A.dsc.inc | 42 +++++
.../NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dsc | 46 +++++
.../NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf | 169 ++++++++++++++++++
.../Library/ArmPlatformLib/ArmPlatformLib.inf | 42 +++++
Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf | 27 +++
Silicon/NXP/LS1043A/Include/Soc.h | 29 ++-
Silicon/NXP/LS1046A/Include/Soc.h | 63 +++++++
Silicon/NXP/LS1046A/Include/SocSerDes.h | 33 ++++
Silicon/NXP/LX2160A/Include/Soc.h | 28 ++-
.../Library/ArmPlatformLib/ArmPlatformLib.c | 147 +++++++++++++++
.../ArmPlatformLib/ArmPlatformLibMem.c | 75 ++++++++
Silicon/NXP/LS1046A/Library/SocLib/SerDes.c | 119 ++++++++++++
Silicon/NXP/LS1046A/Library/SocLib/SocLib.c | 78 ++++++++
.../AArch64/ArmPlatformHelper.S | 45 +++++
Platform/NXP/LS1046aFrwyPkg/VarStore.fdf.inc | 91 ++++++++++
17 files changed, 1068 insertions(+), 2 deletions(-)
create mode 100644 Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dec
create mode 100644 Silicon/NXP/LS1046A/LS1046A.dec
create mode 100644 Silicon/NXP/LS1046A/LS1046A.dsc.inc
create mode 100644 Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.dsc
create mode 100644 Platform/NXP/LS1046aFrwyPkg/LS1046aFrwyPkg.fdf
create mode 100644 Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
create mode 100644 Silicon/NXP/LS1046A/Library/SocLib/SocLib.inf
create mode 100644 Silicon/NXP/LS1046A/Include/Soc.h
create mode 100644 Silicon/NXP/LS1046A/Include/SocSerDes.h
create mode 100644 Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLib.c
create mode 100644 Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c
create mode 100644 Silicon/NXP/LS1046A/Library/SocLib/SerDes.c
create mode 100644 Silicon/NXP/LS1046A/Library/SocLib/SocLib.c
create mode 100644 Platform/NXP/LS1046aFrwyPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S
create mode 100644 Platform/NXP/LS1046aFrwyPkg/VarStore.fdf.inc

--
2.17.1