Date   

Re: [PATCH] SecurityPkg: Debug code to audit BIOS TPM extend operations.

Yao, Jiewen
 

Some feedback:

1) I think it is OK to add Tpm2PcrReadForActiveBank() API.
But I feel we will add too many noise to dump Tpm2PcrReadForActiveBank() in the code everytime.
I am not sure why it is needed.
What is the problem statement?

2) Below definition does not follow EDKII coding style. Please use 2 "space" as indent.
EFI_STATUS
EFIAPI
Tpm2PcrReadForActiveBank (
IN TPMI_DH_PCR PcrHandle,
OUT TPML_DIGEST *HashList
)

-----Original Message-----
From: Gonzalez Del Cueto, Rodrigo <rodrigo.gonzalez.del.cueto@intel.com>
Sent: Friday, July 30, 2021 6:43 AM
To: devel@edk2.groups.io
Cc: Gonzalez Del Cueto, Rodrigo <rodrigo.gonzalez.del.cueto@intel.com>; Yao,
Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
Subject: [PATCH] SecurityPkg: Debug code to audit BIOS TPM extend operations.

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

Add debug functionality to examine TPM extend operations
performed by BIOS and inspect the PCR 00 value prior to
any BIOS measurements.

Replaced usage of EFI_D_* for DEBUG_* definitions in debug
messages.

Signed-off-by: Rodrigo Gonzalez del Cueto
<rodrigo.gonzalez.del.cueto@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
---
SecurityPkg/Include/Library/Tpm2CommandLib.h | 28
++++++++++++++++++++++------
SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c | 226
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++-----------------------
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 34 ++++++++++++++++++++------
--------
3 files changed, 245 insertions(+), 43 deletions(-)

diff --git a/SecurityPkg/Include/Library/Tpm2CommandLib.h
b/SecurityPkg/Include/Library/Tpm2CommandLib.h
index ee8eb62295..5e5c340893 100644
--- a/SecurityPkg/Include/Library/Tpm2CommandLib.h
+++ b/SecurityPkg/Include/Library/Tpm2CommandLib.h
@@ -1,7 +1,7 @@
/** @file
This library is used by other modules to send TPM2 command.

-Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/
@@ -505,7 +505,7 @@ EFIAPI
Tpm2PcrEvent (
IN TPMI_DH_PCR PcrHandle,
IN TPM2B_EVENT *EventData,
- OUT TPML_DIGEST_VALUES *Digests
+ OUT TPML_DIGEST_VALUES *Digests
);

/**
@@ -522,10 +522,10 @@ Tpm2PcrEvent (
EFI_STATUS
EFIAPI
Tpm2PcrRead (
- IN TPML_PCR_SELECTION *PcrSelectionIn,
- OUT UINT32 *PcrUpdateCounter,
- OUT TPML_PCR_SELECTION *PcrSelectionOut,
- OUT TPML_DIGEST *PcrValues
+ IN TPML_PCR_SELECTION *PcrSelectionIn,
+ OUT UINT32 *PcrUpdateCounter,
+ OUT TPML_PCR_SELECTION *PcrSelectionOut,
+ OUT TPML_DIGEST *PcrValues
);

/**
@@ -1113,4 +1113,20 @@ GetDigestFromDigestList(
OUT VOID *Digest
);

+ /**
+ This function will query the TPM to determine which hashing algorithms and
+ get the digests of all active and supported PCR banks of a specific PCR
register.
+
+ @param[in] PcrHandle The index of the PCR register to be read.
+ @param[out] HashList List of digests from PCR register being read.
+
+ @retval EFI_SUCCESS The Pcr was read successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrReadForActiveBank (
+ IN TPMI_DH_PCR PcrHandle,
+ OUT TPML_DIGEST *HashList
+ );
#endif
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
index ddb15178fb..3b49192b93 100644
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
@@ -1,7 +1,7 @@
/** @file
Implement TPM2 Integrity related command.

-Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/
@@ -109,7 +109,6 @@ Tpm2PcrExtend (
Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend);
Cmd.PcrHandle = SwapBytes32(PcrHandle);

-
//
// Add in Auth session
//
@@ -130,14 +129,26 @@ Tpm2PcrExtend (
Buffer += sizeof(UINT16);
DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
if (DigestSize == 0) {
- DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests-
digests[Index].hashAlg));
+ DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests-
digests[Index].hashAlg));
return EFI_DEVICE_ERROR;
}
+
CopyMem(
Buffer,
&Digests->digests[Index].digest,
DigestSize
);
+
+ DEBUG_CODE_BEGIN ();
+ UINTN Index2;
+ DEBUG ((DEBUG_VERBOSE, "Tpm2PcrExtend - Hash = 0x%04x, Pcr[%02d],
digest = ", Digests->digests[Index].hashAlg, (UINT8) PcrHandle));
+
+ for (Index2 = 0; Index2 < DigestSize; Index2++) {
+ DEBUG ((DEBUG_VERBOSE, "%02x ", Buffer[Index2]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG_CODE_END ();
+
Buffer += DigestSize;
}

@@ -151,7 +162,7 @@ Tpm2PcrExtend (
}

if (ResultBufSize > sizeof(Res)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer
Too Small\r\n"));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer
Too Small\r\n"));
return EFI_BUFFER_TOO_SMALL;
}

@@ -160,7 +171,7 @@ Tpm2PcrExtend (
//
RespSize = SwapBytes32(Res.Header.paramSize);
if (RespSize > sizeof(Res)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n",
RespSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n",
RespSize));
return EFI_BUFFER_TOO_SMALL;
}

@@ -168,10 +179,15 @@ Tpm2PcrExtend (
// Fail if command failed
//
if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n",
SwapBytes32(Res.Header.responseCode)));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response Code error!
0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
return EFI_DEVICE_ERROR;
}

+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_VERBOSE, "Tpm2PcrExtend: PCR read after extend...\n"));
+ Tpm2PcrReadForActiveBank (PcrHandle, NULL);
+ DEBUG_CODE_END ();
+
//
// Unmarshal the response
//
@@ -246,7 +262,7 @@ Tpm2PcrEvent (
}

if (ResultBufSize > sizeof(Res)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer
Too Small\r\n"));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer
Too Small\r\n"));
return EFI_BUFFER_TOO_SMALL;
}

@@ -255,7 +271,7 @@ Tpm2PcrEvent (
//
RespSize = SwapBytes32(Res.Header.paramSize);
if (RespSize > sizeof(Res)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n",
RespSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n",
RespSize));
return EFI_BUFFER_TOO_SMALL;
}

@@ -263,7 +279,7 @@ Tpm2PcrEvent (
// Fail if command failed
//
if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n",
SwapBytes32(Res.Header.responseCode)));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response Code error!
0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
return EFI_DEVICE_ERROR;
}

@@ -284,7 +300,7 @@ Tpm2PcrEvent (
Buffer += sizeof(UINT16);
DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
if (DigestSize == 0) {
- DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests-
digests[Index].hashAlg));
+ DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests-
digests[Index].hashAlg));
return EFI_DEVICE_ERROR;
}
CopyMem(
@@ -298,6 +314,7 @@ Tpm2PcrEvent (
return EFI_SUCCESS;
}

+
/**
This command returns the values of all PCR specified in pcrSelect.

@@ -353,11 +370,11 @@ Tpm2PcrRead (
}

if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
return EFI_DEVICE_ERROR;
}
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n",
SwapBytes32(RecvBuffer.Header.responseCode)));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - responseCode - %x\n",
SwapBytes32(RecvBuffer.Header.responseCode)));
return EFI_NOT_FOUND;
}

@@ -369,7 +386,7 @@ Tpm2PcrRead (
// PcrUpdateCounter
//
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) +
sizeof(RecvBuffer.PcrUpdateCounter)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
return EFI_DEVICE_ERROR;
}
*PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter);
@@ -378,7 +395,7 @@ Tpm2PcrRead (
// PcrSelectionOut
//
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) +
sizeof(RecvBuffer.PcrUpdateCounter) +
sizeof(RecvBuffer.PcrSelectionOut.count)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
return EFI_DEVICE_ERROR;
}
PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count);
@@ -388,7 +405,7 @@ Tpm2PcrRead (
}

if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) +
sizeof(RecvBuffer.PcrUpdateCounter) +
sizeof(RecvBuffer.PcrSelectionOut.count) +
sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n",
RecvBufferSize));
return EFI_DEVICE_ERROR;
}
for (Index = 0; Index < PcrSelectionOut->count; Index++) {
@@ -513,7 +530,7 @@ Tpm2PcrAllocate (
}

if (ResultBufSize > sizeof(Res)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer
Too Small\r\n"));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand:
Buffer Too Small\r\n"));
Status = EFI_BUFFER_TOO_SMALL;
goto Done;
}
@@ -523,7 +540,7 @@ Tpm2PcrAllocate (
//
RespSize = SwapBytes32(Res.Header.paramSize);
if (RespSize > sizeof(Res)) {
- DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n",
RespSize));
+ DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response size too
large! %d\r\n", RespSize));
Status = EFI_BUFFER_TOO_SMALL;
goto Done;
}
@@ -532,7 +549,7 @@ Tpm2PcrAllocate (
// Fail if command failed
//
if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {
- DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n",
SwapBytes32(Res.Header.responseCode)));
+ DEBUG((DEBUG_ERROR,"Tpm2PcrAllocate: Response Code error!
0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));
Status = EFI_DEVICE_ERROR;
goto Done;
}
@@ -673,17 +690,180 @@ Tpm2PcrAllocateBanks (
&SizeNeeded,
&SizeAvailable
);
- DEBUG ((EFI_D_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n",
Status));
+ DEBUG ((DEBUG_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n",
Status));
if (EFI_ERROR (Status)) {
goto Done;
}

- DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
- DEBUG ((EFI_D_INFO, "MaxPCR - %08x\n", MaxPCR));
- DEBUG ((EFI_D_INFO, "SizeNeeded - %08x\n", SizeNeeded));
- DEBUG ((EFI_D_INFO, "SizeAvailable - %08x\n", SizeAvailable));
+ DEBUG ((DEBUG_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
+ DEBUG ((DEBUG_INFO, "MaxPCR - %08x\n", MaxPCR));
+ DEBUG ((DEBUG_INFO, "SizeNeeded - %08x\n", SizeNeeded));
+ DEBUG ((DEBUG_INFO, "SizeAvailable - %08x\n", SizeAvailable));

Done:
ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
return Status;
}
+
+/**
+ This function will query the TPM to determine which hashing algorithms and
+ get the digests of all active and supported PCR banks of a specific PCR
register.
+
+ @param[in] PcrHandle The index of the PCR register to be read.
+ @param[out] HashList List of digests from PCR register being read.
+
+ @retval EFI_SUCCESS The Pcr was read successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2PcrReadForActiveBank (
+ IN TPMI_DH_PCR PcrHandle,
+ OUT TPML_DIGEST *HashList
+)
+{
+ EFI_STATUS Status;
+ TPML_PCR_SELECTION Pcrs;
+ TPML_PCR_SELECTION PcrSelectionIn;
+ TPML_PCR_SELECTION PcrSelectionOut;
+ TPML_DIGEST PcrValues;
+ UINT32 PcrUpdateCounter;
+ UINT8 PcrIndex;
+ UINT32 TpmHashAlgorithmBitmap;
+ TPMI_ALG_HASH CurrentPcrBankHash;
+ UINT32 ActivePcrBanks;
+ UINT32 TcgRegistryHashAlg;
+ UINTN Index;
+ UINTN Index2;
+
+ PcrIndex = (UINT8) PcrHandle;
+
+ if ((PcrIndex < 0) ||
+ (PcrIndex >= IMPLEMENTATION_PCR)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&PcrSelectionIn, sizeof (PcrSelectionIn));
+ ZeroMem (&PcrUpdateCounter, sizeof (UINT32));
+ ZeroMem (&PcrSelectionOut, sizeof (PcrSelectionOut));
+ ZeroMem (&PcrValues, sizeof (PcrValues));
+ ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));
+
+ DEBUG ((DEBUG_INFO, "ReadPcr - %02d\n", PcrIndex));
+
+ //
+ // Read TPM capabilities
+ //
+ Status = Tpm2GetCapabilityPcrs (&Pcrs);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get Active Pcrs
+ //
+ Status = Tpm2GetCapabilitySupportedAndActivePcrs (
+ &TpmHashAlgorithmBitmap,
+ &ActivePcrBanks
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities and
active PCRs\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select from Active PCRs
+ //
+ for (Index = 0; Index < Pcrs.count; Index++) {
+ CurrentPcrBankHash = Pcrs.pcrSelections[Index].hash;
+
+ switch (CurrentPcrBankHash) {
+ case TPM_ALG_SHA1:
+ DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA1 Present\n"));
+ TcgRegistryHashAlg = HASH_ALG_SHA1;
+ break;
+ case TPM_ALG_SHA256:
+ DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA256 Present\n"));
+ TcgRegistryHashAlg = HASH_ALG_SHA256;
+ break;
+ case TPM_ALG_SHA384:
+ DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA384 Present\n"));
+ TcgRegistryHashAlg = HASH_ALG_SHA384;
+ break;
+ case TPM_ALG_SHA512:
+ DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA512 Present\n"));
+ TcgRegistryHashAlg = HASH_ALG_SHA512;
+ break;
+ case TPM_ALG_SM3_256:
+ DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SM3 Present\n"));
+ TcgRegistryHashAlg = HASH_ALG_SM3_256;
+ break;
+ default:
+ //
+ // Unsupported algorithm
+ //
+ DEBUG ((DEBUG_VERBOSE, "Unknown algorithm present\n"));
+ TcgRegistryHashAlg = 0;
+ break;
+ }
+ //
+ // Skip unsupported and inactive PCR banks
+ //
+ if ((TcgRegistryHashAlg & ActivePcrBanks) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "Skipping unsupported or inactive bank:
0x%04x\n", CurrentPcrBankHash));
+ continue;
+ }
+
+ //
+ // Select PCR from current active bank
+ //
+ PcrSelectionIn.pcrSelections[PcrSelectionIn.count].hash =
Pcrs.pcrSelections[Index].hash;
+ PcrSelectionIn.pcrSelections[PcrSelectionIn.count].sizeofSelect =
PCR_SELECT_MAX;
+ PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[0] = (PcrIndex <
8) ? 1 << PcrIndex : 0;
+ PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[1] = (PcrIndex >
7) && (PcrIndex < 16) ? 1 << (PcrIndex - 8) : 0;
+ PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[2] = (PcrIndex >
15) ? 1 << (PcrIndex - 16) : 0;
+ PcrSelectionIn.count++;
+ }
+
+ //
+ // Read PCRs
+ //
+ Status = Tpm2PcrRead (
+ &PcrSelectionIn,
+ &PcrUpdateCounter,
+ &PcrSelectionOut,
+ &PcrValues
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "Tpm2PcrRead failed Status = %r \n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+
+ for (Index = 0; Index < PcrValues.count; Index++) {
+ DEBUG ((
+ DEBUG_INFO,
+ "ReadPcr - HashAlg = 0x%04x, Pcr[%02d], digest = ",
+ PcrSelectionOut.pcrSelections[Index].hash,
+ PcrIndex
+ ));
+
+ for(Index2 = 0; Index2 < PcrValues.digests[Index].size; Index2++) {
+ DEBUG ((DEBUG_INFO, "%02x ", PcrValues.digests[Index].buffer[Index2]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+
+ if (HashList != NULL) {
+ CopyMem (
+ HashList,
+ &PcrValues,
+ sizeof (TPML_DIGEST)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
index 93a8803ff6..ea79fa0af6 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
@@ -1,7 +1,7 @@
/** @file
Initialize TPM2 device and measure FVs before handing off control to DXE.

-Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -191,7 +191,6 @@ EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
}
};

-
/**
Record all measured Firmware Volume Information into a Guid Hob
Guid Hob payload layout is
@@ -267,7 +266,7 @@ SyncPcrAllocationsAndPcrMask (
UINT32 Tpm2PcrMask;
UINT32 NewTpm2PcrMask;

- DEBUG ((EFI_D_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));
+ DEBUG ((DEBUG_ERROR, "SyncPcrAllocationsAndPcrMask!\n"));

//
// Determine the current TPM support and the Platform PCR mask.
@@ -278,7 +277,7 @@ SyncPcrAllocationsAndPcrMask (
Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
if (Tpm2PcrMask == 0) {
//
- // if PcdTPm2HashMask is zero, use ActivePcr setting
+ // if PcdTpm2HashMask is zero, use ActivePcr setting
//
PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
Tpm2PcrMask = TpmActivePcrBanks;
@@ -297,9 +296,9 @@ SyncPcrAllocationsAndPcrMask (
if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {
NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;

- DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n",
__FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
+ DEBUG ((DEBUG_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n",
__FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
if (NewTpmActivePcrBanks == 0) {
- DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less
restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
+ DEBUG ((DEBUG_ERROR, "%a - No viable PCRs active! Please set a less
restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
ASSERT (FALSE);
} else {
Status = Tpm2PcrAllocateBanks (NULL, (UINT32)TpmHashAlgorithmBitmap,
NewTpmActivePcrBanks);
@@ -307,7 +306,7 @@ SyncPcrAllocationsAndPcrMask (
//
// We can't do much here, but we hope that this doesn't happen.
//
- DEBUG ((EFI_D_ERROR, "%a - Failed to reallocate PCRs!\n",
__FUNCTION__));
+ DEBUG ((DEBUG_ERROR, "%a - Failed to reallocate PCRs!\n",
__FUNCTION__));
ASSERT_EFI_ERROR (Status);
}
//
@@ -324,9 +323,9 @@ SyncPcrAllocationsAndPcrMask (
if ((Tpm2PcrMask & TpmHashAlgorithmBitmap) != Tpm2PcrMask) {
NewTpm2PcrMask = Tpm2PcrMask & TpmHashAlgorithmBitmap;

- DEBUG ((EFI_D_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to
0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
+ DEBUG ((DEBUG_INFO, "%a - Updating PcdTpm2HashMask from 0x%X to
0x%X.\n", __FUNCTION__, Tpm2PcrMask, NewTpm2PcrMask));
if (NewTpm2PcrMask == 0) {
- DEBUG ((EFI_D_ERROR, "%a - No viable PCRs supported! Please set a less
restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
+ DEBUG ((DEBUG_ERROR, "%a - No viable PCRs supported! Please set a less
restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
ASSERT (FALSE);
}

@@ -365,7 +364,7 @@ LogHashEvent (
RetStatus = EFI_SUCCESS;
for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]);
Index++) {
if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
- DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n",
mTcg2EventInfo[Index].LogFormat));
+ DEBUG ((DEBUG_INFO, " LogFormat - 0x%08x\n",
mTcg2EventInfo[Index].LogFormat));
switch (mTcg2EventInfo[Index].LogFormat) {
case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList,
&NewEventHdr->Digest);
@@ -476,7 +475,7 @@ HashLogExtendEvent (
}

if (Status == EFI_DEVICE_ERROR) {
- DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));
+ DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n",
Status));
BuildGuidHob (&gTpmErrorHobGuid,0);
REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
@@ -1011,7 +1010,7 @@ PeimEntryMA (
}

if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
- DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
+ DEBUG ((DEBUG_ERROR, "TPM2 error!\n"));
return EFI_DEVICE_ERROR;
}

@@ -1075,7 +1074,7 @@ PeimEntryMA (
for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
Status = MeasureSeparatorEventWithError (PcrIndex);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Separator Event with Error not Measured.
Error!\n"));
+ DEBUG ((DEBUG_ERROR, "Separator Event with Error not Measured.
Error!\n"));
}
}
}
@@ -1092,6 +1091,13 @@ PeimEntryMA (
}
}

+ DEBUG_CODE_BEGIN ();
+ //
+ // Peek into TPM PCR 00 before any BIOS measurement.
+ //
+ Tpm2PcrReadForActiveBank (00, NULL);
+ DEBUG_CODE_END ();
+
//
// Only install TpmInitializedPpi on success
//
@@ -1106,7 +1112,7 @@ PeimEntryMA (

Done:
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "TPM2 error! Build Hob\n"));
+ DEBUG ((DEBUG_ERROR, "TPM2 error! Build Hob\n"));
BuildGuidHob (&gTpmErrorHobGuid,0);
REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MINOR,
--
2.31.1.windows.1


Re: [PATCH] Reallocate TPM Active PCRs based on platform support.

Yao, Jiewen
 

Hi Rodrigo
I don't understand the problem statement.

This code has been there for long time. What is changed recently ?

Thank you
Yao Jiewen

-----Original Message-----
From: Gonzalez Del Cueto, Rodrigo <rodrigo.gonzalez.del.cueto@intel.com>
Sent: Thursday, August 5, 2021 7:28 AM
To: devel@edk2.groups.io
Cc: Gonzalez Del Cueto, Rodrigo <rodrigo.gonzalez.del.cueto@intel.com>;
Wang, Jian J <jian.j.wang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: [PATCH] Reallocate TPM Active PCRs based on platform support.

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

In V2: Add case to RegisterHashInterfaceLib logic

RegisterHashInterfaceLib needs to correctly handle registering the HashLib
instance supported algorithm bitmap when PcdTpm2HashMask is set to zero.

The current implementation of SyncPcrAllocationsAndPcrMask() triggers
PCR bank reallocation only based on the intersection between
TpmActivePcrBanks and PcdTpm2HashMask.

When the software HashLibBaseCryptoRouter solution is used, no PCR bank
reallocation is occurring based on the supported hashing algorithms
registered by the HashLib instances.

Need to have an additional check for the intersection between the
TpmActivePcrBanks and the PcdTcg2HashAlgorithmBitmap populated by the
HashLib instances present on the platform's BIOS.

Signed-off-by: Rodrigo Gonzalez del Cueto
<rodrigo.gonzalez.del.cueto@intel.com>

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
---
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
| 6 +++++-
SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c |
6 +++++-
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 18
+++++++++++++++++-
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf | 1 +
4 files changed, 28 insertions(+), 3 deletions(-)

diff --git
a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.
c
b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.
c
index 7a0f61efbb..0821159120 100644
---
a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.
c
+++
b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.
c
@@ -230,13 +230,17 @@ RegisterHashInterfaceLib (
{
UINTN Index;
UINT32 HashMask;
+ UINT32 Tpm2HashMask;
EFI_STATUS Status;

//
// Check allow
//
HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);
- if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {
+ Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
+
+ if ((Tpm2HashMask != 0) &&
+ ((HashMask & Tpm2HashMask) == 0)) {
return EFI_UNSUPPORTED;
}

diff --git
a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
index 42cb562f67..6ae51dbce4 100644
---
a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
+++
b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.c
@@ -327,13 +327,17 @@ RegisterHashInterfaceLib (
UINTN Index;
HASH_INTERFACE_HOB *HashInterfaceHob;
UINT32 HashMask;
+ UINT32 Tpm2HashMask;
EFI_STATUS Status;

//
// Check allow
//
HashMask = Tpm2GetHashMaskFromAlgo (&HashInterface->HashGuid);
- if ((HashMask & PcdGet32 (PcdTpm2HashMask)) == 0) {
+ Tpm2HashMask = PcdGet32 (PcdTpm2HashMask);
+
+ if ((Tpm2HashMask != 0) &&
+ ((HashMask & Tpm2HashMask) == 0)) {
return EFI_UNSUPPORTED;
}

diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
index 93a8803ff6..5ad6a45cf3 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
@@ -262,6 +262,7 @@ SyncPcrAllocationsAndPcrMask (
{
EFI_STATUS Status;
EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;
+ EFI_TCG2_EVENT_ALGORITHM_BITMAP BiosHashAlgorithmBitmap;
UINT32 TpmActivePcrBanks;
UINT32 NewTpmActivePcrBanks;
UINT32 Tpm2PcrMask;
@@ -273,16 +274,27 @@ SyncPcrAllocationsAndPcrMask (
// Determine the current TPM support and the Platform PCR mask.
//
Status = Tpm2GetCapabilitySupportedAndActivePcrs
(&TpmHashAlgorithmBitmap, &TpmActivePcrBanks);
+
ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "Tpm2GetCapabilitySupportedAndActivePcrs -
TpmHashAlgorithmBitmap: 0x%08x\n", TpmHashAlgorithmBitmap));
+ DEBUG ((EFI_D_INFO, "Tpm2GetCapabilitySupportedAndActivePcrs -
TpmActivePcrBanks 0x%08x\n", TpmActivePcrBanks));

Tpm2PcrMask = PcdGet32 (PcdTpm2HashMask);
if (Tpm2PcrMask == 0) {
//
// if PcdTPm2HashMask is zero, use ActivePcr setting
//
+ DEBUG ((EFI_D_VERBOSE, "Initializing PcdTpm2HashMask to
TpmActivePcrBanks 0x%08x\n", TpmActivePcrBanks));
PcdSet32S (PcdTpm2HashMask, TpmActivePcrBanks);
+ DEBUG ((EFI_D_VERBOSE, "Initializing Tpm2PcrMask to TpmActivePcrBanks
0x%08x\n", Tpm2PcrMask));
Tpm2PcrMask = TpmActivePcrBanks;
}
+
+ BiosHashAlgorithmBitmap = PcdGet32 (PcdTcg2HashAlgorithmBitmap);
+ DEBUG ((EFI_D_INFO, "PcdTcg2HashAlgorithmBitmap 0x%08x\n",
BiosHashAlgorithmBitmap));
+ DEBUG ((EFI_D_INFO, "Tpm2PcrMask 0x%08x\n", Tpm2PcrMask)); // Active
PCR banks from TPM input
+ DEBUG ((EFI_D_INFO, "TpmActivePcrBanks & BiosHashAlgorithmBitmap =
0x%08x\n", NewTpmActivePcrBanks));

//
// Find the intersection of Pcd support and TPM support.
@@ -294,9 +306,12 @@ SyncPcrAllocationsAndPcrMask (
// If there are active PCR banks that are not supported by the Platform mask,
// update the TPM allocations and reboot the machine.
//
- if ((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) {
+ if (((TpmActivePcrBanks & Tpm2PcrMask) != TpmActivePcrBanks) ||
+ ((TpmActivePcrBanks & BiosHashAlgorithmBitmap) != TpmActivePcrBanks)) {
NewTpmActivePcrBanks = TpmActivePcrBanks & Tpm2PcrMask;
+ NewTpmActivePcrBanks &= BiosHashAlgorithmBitmap;

+ DEBUG ((EFI_D_INFO, "NewTpmActivePcrBanks 0x%08x\n",
NewTpmActivePcrBanks));
DEBUG ((EFI_D_INFO, "%a - Reallocating PCR banks from 0x%X to 0x%X.\n",
__FUNCTION__, TpmActivePcrBanks, NewTpmActivePcrBanks));
if (NewTpmActivePcrBanks == 0) {
DEBUG ((EFI_D_ERROR, "%a - No viable PCRs active! Please set a less
restrictive value for PcdTpm2HashMask!\n", __FUNCTION__));
@@ -331,6 +346,7 @@ SyncPcrAllocationsAndPcrMask (
}

Status = PcdSet32S (PcdTpm2HashMask, NewTpm2PcrMask);
+ DEBUG ((EFI_D_INFO, "Setting PcdTpm2Hash Mask to 0x%08x\n",
NewTpm2PcrMask));
ASSERT_EFI_ERROR (Status);
}
}
diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
index 06c26a2904..17ad116126 100644
--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -86,6 +86,7 @@
## SOMETIMES_CONSUMES
## SOMETIMES_PRODUCES
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap ##
CONSUMES

[Depex]
gEfiPeiMasterBootModePpiGuid AND
--
2.31.1.windows.1


Re: [PATCH] SecurityPkg/DxeImageVerificationLib: Always lookup SHA-256 hash in dbx

Min Xu
 

On August 9, 2021 3:40 AM, Marvin Häuser wrote:
Subject: [PATCH] SecurityPkg/DxeImageVerificationLib: Always lookup SHA-256
hash in dbx

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

The UEFI specification prohibits loading any UEFI image of which a matching
SHA-256 hash is contained in "dbx" (UEFI 2.9, 32.5.3.3 "Authorization Process",
3.A). Currently, this is only explicitly checked when the image is unsigned and
otherwise the hash algorithms of the certificates are used.

Align with the UEFI specification by specifically looking up the
SHA-256 hash of the image in "dbx".

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
It seems there are 3 patches sent from Marvin Häuser and I suppose they're in one patch-set, right? Please follow the link below to send out patch-set for review.
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers
For example, if there are 3 commits in one patch-set, then the subject of the commits looks like:
[PATCH 0/4] This is the cover letter
[PATCH 1/4] This is patch 1

Otherwise the reviewers are confused by the patches.

Thanks!
Xu, Min


[PATCH 2/3] efi_gdb.py: - Add gdb EFI commands and pretty Print

Andrew Fish
 

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

Use efi_debugging.py Python Classes to implement EFI gdb commands:
(gdb) help efi
Commands for debugging EFI. efi <cmd>

List of efi subcommands:

efi devicepath -- Display an EFI device path.
efi guid -- Display info about EFI GUID's.
efi hob -- Dump EFI HOBs. Type 'hob -h' for more info.
efi symbols -- Load Symbols for EFI. Type 'efi_symbols -h' for more info.
efi table -- Dump EFI System Tables. Type 'table -h' for more info.

This module is coded against a generic gdb remote serial stub. It should
work with QEMU, JTAG debugger, or a generic EFI gdb remote serial stub.
No modifications of EFI is required to load symbols.

Example usage:
OvmfPkg/build.sh qemu -gdb tcp::9000
gdb -ex "target remote localhost:9000" -ex "source efi_gdb.py"

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Signed-off-by: Andrew Fish <afish@apple.com>
---
efi_gdb.py | 918 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 918 insertions(+)
create mode 100755 efi_gdb.py

diff --git a/efi_gdb.py b/efi_gdb.py
new file mode 100755
index 000000000000..f3e7fd9d0c28
--- /dev/null
+++ b/efi_gdb.py
@@ -0,0 +1,918 @@
+#!/usr/bin/python3
+'''
+Copyright 2021 (c) Apple Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+EFI gdb commands based on efi_debugging classes.
+
+Example usage:
+OvmfPkg/build.sh qemu -gdb tcp::9000
+gdb -ex "target remote localhost:9000" -ex "source efi_gdb.py"
+
+(gdb) help efi
+Commands for debugging EFI. efi <cmd>
+
+List of efi subcommands:
+
+efi devicepath -- Display an EFI device path.
+efi guid -- Display info about EFI GUID's.
+efi hob -- Dump EFI HOBs. Type 'hob -h' for more info.
+efi symbols -- Load Symbols for EFI. Type 'efi_symbols -h' for more info.
+efi table -- Dump EFI System Tables. Type 'table -h' for more info.
+
+This module is coded against a generic gdb remote serial stub. It should work
+with QEMU, JTAG debugger, or a generic EFI gdb remote serial stub.
+
+If you are debugging with QEMU or a JTAG hardware debugger you can insert
+a CpuDeadLoop(); in your code, attach with gdb, and then `p Index=1` to
+step past. If you have a debug stub in EFI you can use CpuBreakpoint();.
+'''
+
+from gdb.printing import RegexpCollectionPrettyPrinter
+from gdb.printing import register_pretty_printer
+import gdb
+import os
+import sys
+import uuid
+import optparse
+import shlex
+
+# gdb will not import from the same path as this script.
+# so lets fix that for gdb...
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+
+from efi_debugging import PeTeImage, patch_ctypes # noqa: E402
+from efi_debugging import EfiHob, GuidNames, EfiStatusClass # noqa: E402
+from efi_debugging import EfiBootMode, EfiDevicePath # noqa: E402
+from efi_debugging import EfiConfigurationTable, EfiTpl # noqa: E402
+
+
+class GdbFileObject(object):
+ '''Provide a file like object required by efi_debugging'''
+
+ def __init__(self):
+ self.inferior = gdb.selected_inferior()
+ self.offset = 0
+
+ def tell(self):
+ return self.offset
+
+ def read(self, size=-1):
+ if size == -1:
+ # arbitrary default size
+ size = 0x1000000
+
+ try:
+ data = self.inferior.read_memory(self.offset, size)
+ except MemoryError:
+ data = bytearray(size)
+ assert False
+ if len(data) != size:
+ raise MemoryError(
+ f'gdb could not read memory 0x{size:x}'
+ + f' bytes from 0x{self.offset:08x}')
+ else:
+ # convert memoryview object to a bytestring.
+ return data.tobytes()
+
+ def readable(self):
+ return True
+
+ def seek(self, offset, whence=0):
+ if whence == 0:
+ self.offset = offset
+ elif whence == 1:
+ self.offset += offset
+ else:
+ # whence == 2 is seek from end
+ raise NotImplementedError
+
+ def seekable(self):
+ return True
+
+ def write(self, data):
+ self.inferior.write_memory(self.offset, data)
+ return len(data)
+
+ def writable(self):
+ return True
+
+ def truncate(self, size=None):
+ raise NotImplementedError
+
+ def flush(self):
+ raise NotImplementedError
+
+ def fileno(self):
+ raise NotImplementedError
+
+
+class EfiSymbols:
+ """Class to manage EFI Symbols"""
+
+ loaded = {}
+ stride = None
+ range = None
+ verbose = False
+
+ def __init__(self, file=None):
+ EfiSymbols.file = file if file else GdbFileObject()
+
+ @ classmethod
+ def __str__(cls):
+ return ''.join(f'{value}\n' for value in cls.loaded.values())
+
+ @ classmethod
+ def configure_search(cls, stride, range=None, verbose=False):
+ cls.stride = stride
+ cls.range = range
+ cls.verbose = verbose
+
+ @ classmethod
+ def clear(cls):
+ cls.loaded = {}
+
+ @ classmethod
+ def add_symbols_for_pecoff(cls, pecoff):
+ '''Tell lldb the location of the .text and .data sections.'''
+
+ if pecoff.TextAddress in cls.loaded:
+ return 'Already Loaded: '
+ try:
+ res = 'Loading Symbols Failed:'
+ res = gdb.execute('add-symbol-file ' + pecoff.CodeViewPdb +
+ ' ' + hex(pecoff.TextAddress) +
+ ' -s .data ' + hex(pecoff.DataAddress),
+ False, True)
+
+ cls.loaded[pecoff.TextAddress] = pecoff
+ if cls.verbose:
+ print(f'\n{res:s}\n')
+ return ''
+ except gdb.error:
+ return res
+
+ @ classmethod
+ def address_to_symbols(cls, address, reprobe=False):
+ '''
+ Given an address search backwards for a PE/COFF (or TE) header
+ and load symbols. Return a status string.
+ '''
+ if not isinstance(address, int):
+ address = int(address)
+
+ pecoff = cls.address_in_loaded_pecoff(address)
+ if not reprobe and pecoff is not None:
+ # skip the probe of the remote
+ return f'{pecoff} is already loaded'
+
+ pecoff = PeTeImage(cls.file, None)
+ if pecoff.pcToPeCoff(address, cls.stride, cls.range):
+ res = cls.add_symbols_for_pecoff(pecoff)
+ return f'{res}{pecoff}'
+ else:
+ return f'0x{address:08x} not in a PE/COFF (or TE) image'
+
+ @ classmethod
+ def address_in_loaded_pecoff(cls, address):
+ if not isinstance(address, int):
+ address = int(address)
+
+ for value in cls.loaded.values():
+ if (address >= value.LoadAddress and
+ address <= value.EndLoadAddress):
+ return value
+
+ return None
+
+ @ classmethod
+ def unload_symbols(cls, address):
+ if not isinstance(address, int):
+ address = int(address)
+
+ pecoff = cls.address_in_loaded_pecoff(address)
+ try:
+ res = 'Unloading Symbols Failed:'
+ res = gdb.execute(
+ f'remove-symbol-file -a {hex(pecoff.TextAddress):s}',
+ False, True)
+ del cls.loaded[pecoff.LoadAddress]
+ return res
+ except gdb.error:
+ return res
+
+
+class CHAR16_PrettyPrinter(object):
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ if int(self.val) < 0x20:
+ return f"L'\\x{int(self.val):02x}'"
+ else:
+ return f"L'{chr(self.val):s}'"
+
+
+class EFI_TPL_PrettyPrinter(object):
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return str(EfiTpl(int(self.val)))
+
+
+class EFI_STATUS_PrettyPrinter(object):
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ status = int(self.val)
+ return f'{str(EfiStatusClass(status)):s} (0x{status:08x})'
+
+
+class EFI_BOOT_MODE_PrettyPrinter(object):
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return str(EfiBootMode(int(self.val)))
+
+
+class EFI_GUID_PrettyPrinter(object):
+ """Print 'EFI_GUID' as 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"""
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ # if we could get a byte like object of *(unsigned char (*)[16])
+ # then we could just use uuid.UUID() to convert
+ Data1 = int(self.val['Data1'])
+ Data2 = int(self.val['Data2'])
+ Data3 = int(self.val['Data3'])
+ Data4 = self.val['Data4']
+ guid = f'{Data1:08X}-{Data2:04X}-'
+ guid += f'{Data3:04X}-'
+ guid += f'{int(Data4[0]):02X}{int(Data4[1]):02X}-'
+ guid += f'{int(Data4[2]):02X}{int(Data4[3]):02X}'
+ guid += f'{int(Data4[4]):02X}{int(Data4[5]):02X}'
+ guid += f'{int(Data4[6]):02X}{int(Data4[7]):02X}'
+ return str(GuidNames(guid))
+
+
+def build_pretty_printer():
+ # Turn off via: disable pretty-printer global EFI
+ pp = RegexpCollectionPrettyPrinter("EFI")
+ # you can also tell gdb `x/sh <address>` to print CHAR16 string
+ pp.add_printer('CHAR16', '^CHAR16$', CHAR16_PrettyPrinter)
+ pp.add_printer('EFI_BOOT_MODE', '^EFI_BOOT_MODE$',
+ EFI_BOOT_MODE_PrettyPrinter)
+ pp.add_printer('EFI_GUID', '^EFI_GUID$', EFI_GUID_PrettyPrinter)
+ pp.add_printer('EFI_STATUS', '^EFI_STATUS$', EFI_STATUS_PrettyPrinter)
+ pp.add_printer('EFI_TPL', '^EFI_TPL$', EFI_TPL_PrettyPrinter)
+ return pp
+
+
+class EfiDevicePathCmd (gdb.Command):
+ """Display an EFI device path. Type 'efi devicepath -h' for more info"""
+
+ def __init__(self):
+ super(EfiDevicePathCmd, self).__init__(
+ "efi devicepath", gdb.COMMAND_NONE)
+
+ self.file = GdbFileObject()
+
+ def create_options(self, arg, from_tty):
+ usage = "usage: %prog [options] [arg]"
+ description = (
+ "Command that can load EFI PE/COFF and TE image symbols. ")
+
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='efi devicepath',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='hex dump extra data',
+ default=False)
+
+ self.parser.add_option(
+ '-n',
+ '--node',
+ action='store_true',
+ dest='node',
+ help='dump a single device path node',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ return self.parser.parse_args(shlex.split(arg))
+
+ def invoke(self, arg, from_tty):
+ '''gdb command to dump EFI device paths'''
+
+ try:
+ (options, _) = self.create_options(arg, from_tty)
+ if options.help:
+ self.parser.print_help()
+ return
+
+ dev_addr = int(gdb.parse_and_eval(arg))
+ except ValueError:
+ print("Invalid argument!")
+ return
+
+ if options.node:
+ print(EfiDevicePath(
+ self.file).device_path_node_str(dev_addr,
+ options.verbose))
+ else:
+ device_path = EfiDevicePath(self.file, dev_addr, options.verbose)
+ if device_path.valid():
+ print(device_path)
+
+
+class EfiGuidCmd (gdb.Command):
+ """Display info about EFI GUID's. Type 'efi guid -h' for more info"""
+
+ def __init__(self):
+ super(EfiGuidCmd, self).__init__("efi guid",
+ gdb.COMMAND_NONE,
+ gdb.COMPLETE_EXPRESSION)
+ self.file = GdbFileObject()
+
+ def create_options(self, arg, from_tty):
+ usage = "usage: %prog [options] [arg]"
+ description = (
+ "Show EFI_GUID values and the C name of the EFI_GUID variables"
+ "in the C code. If symbols are loaded the Guid.xref file"
+ "can be processed and the complete GUID database can be shown."
+ "This command also suports generating new GUID's, and showing"
+ "the value used to initialize the C variable.")
+
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='efi guid',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-n',
+ '--new',
+ action='store_true',
+ dest='new',
+ help='Generate a new GUID',
+ default=False)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='Also display GUID C structure values',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ return self.parser.parse_args(shlex.split(arg))
+
+ def invoke(self, arg, from_tty):
+ '''gdb command to dump EFI System Tables'''
+
+ try:
+ (options, args) = self.create_options(arg, from_tty)
+ if options.help:
+ self.parser.print_help()
+ return
+ if len(args) >= 1:
+ # guid { 0x414e6bdd, 0xe47b, 0x47cc,
+ # { 0xb2, 0x44, 0xbb, 0x61, 0x02, 0x0c,0xf5, 0x16 }}
+ # this generates multiple args
+ guid = ' '.join(args)
+ except ValueError:
+ print('bad arguments!')
+ return
+
+ if options.new:
+ guid = uuid.uuid4()
+ print(str(guid).upper())
+ print(GuidNames.to_c_guid(guid))
+ return
+
+ if len(args) > 0:
+ if GuidNames.is_guid_str(arg):
+ # guid 05AD34BA-6F02-4214-952E-4DA0398E2BB9
+ key = guid.upper()
+ name = GuidNames.to_name(key)
+ elif GuidNames.is_c_guid(arg):
+ # guid { 0x414e6bdd, 0xe47b, 0x47cc,
+ # { 0xb2, 0x44, 0xbb, 0x61, 0x02, 0x0c,0xf5, 0x16 }}
+ key = GuidNames.from_c_guid(arg)
+ name = GuidNames.to_name(key)
+ else:
+ # guid gEfiDxeServicesTableGuid
+ name = guid
+ try:
+ key = GuidNames.to_guid(name)
+ name = GuidNames.to_name(key)
+ except ValueError:
+ return
+
+ extra = f'{GuidNames.to_c_guid(key)}: ' if options.verbose else ''
+ print(f'{key}: {extra}{name}')
+
+ else:
+ for key, value in GuidNames._dict_.items():
+ if options.verbose:
+ extra = f'{GuidNames.to_c_guid(key)}: '
+ else:
+ extra = ''
+ print(f'{key}: {extra}{value}')
+
+
+class EfiHobCmd (gdb.Command):
+ """Dump EFI HOBs. Type 'hob -h' for more info."""
+
+ def __init__(self):
+ super(EfiHobCmd, self).__init__("efi hob", gdb.COMMAND_NONE)
+ self.file = GdbFileObject()
+
+ def create_options(self, arg, from_tty):
+ usage = "usage: %prog [options] [arg]"
+ description = (
+ "Command that can load EFI PE/COFF and TE image symbols. ")
+
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='efi hob',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-a',
+ '--address',
+ type="int",
+ dest='address',
+ help='Parse HOBs from address',
+ default=None)
+
+ self.parser.add_option(
+ '-t',
+ '--type',
+ type="int",
+ dest='type',
+ help='Only dump HOBS of his type',
+ default=None)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='hex dump extra data',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ return self.parser.parse_args(shlex.split(arg))
+
+ def invoke(self, arg, from_tty):
+ '''gdb command to dump EFI System Tables'''
+
+ try:
+ (options, _) = self.create_options(arg, from_tty)
+ if options.help:
+ self.parser.print_help()
+ return
+ except ValueError:
+ print('bad arguments!')
+ return
+
+ if options.address:
+ try:
+ value = gdb.parse_and_eval(options.address)
+ address = int(value)
+ except ValueError:
+ address = None
+ else:
+ address = None
+
+ hob = EfiHob(self.file,
+ address,
+ options.verbose).get_hob_by_type(options.type)
+ print(hob)
+
+
+class EfiTablesCmd (gdb.Command):
+ """Dump EFI System Tables. Type 'table -h' for more info."""
+
+ def __init__(self):
+ super(EfiTablesCmd, self).__init__("efi table", gdb.COMMAND_NONE)
+
+ self.file = GdbFileObject()
+
+ def create_options(self, arg, from_tty):
+ usage = "usage: %prog [options] [arg]"
+ description = "Dump EFI System Tables. Requires symbols to be loaded"
+
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='efi table',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ return self.parser.parse_args(shlex.split(arg))
+
+ def invoke(self, arg, from_tty):
+ '''gdb command to dump EFI System Tables'''
+
+ try:
+ (options, _) = self.create_options(arg, from_tty)
+ if options.help:
+ self.parser.print_help()
+ return
+ except ValueError:
+ print('bad arguments!')
+ return
+
+ gST = gdb.lookup_global_symbol('gST')
+ if gST is None:
+ print('Error: This command requires symbols for gST to be loaded')
+ return
+
+ table = EfiConfigurationTable(
+ self.file, int(gST.value(gdb.selected_frame())))
+ if table:
+ print(table, '\n')
+
+
+class EfiSymbolsCmd (gdb.Command):
+ """Load Symbols for EFI. Type 'efi symbols -h' for more info."""
+
+ def __init__(self):
+ super(EfiSymbolsCmd, self).__init__("efi symbols",
+ gdb.COMMAND_NONE,
+ gdb.COMPLETE_EXPRESSION)
+ self.file = GdbFileObject()
+ self.gST = None
+ self.efi_symbols = EfiSymbols(self.file)
+
+ def create_options(self, arg, from_tty):
+ usage = "usage: %prog [options]"
+ description = (
+ "Command that can load EFI PE/COFF and TE image symbols. "
+ "If you are having trouble in PEI try adding --pei. "
+ "Given any address search backward for the PE/COFF (or TE header) "
+ "and then parse the PE/COFF image to get debug info. "
+ "The address can come from the current pc, pc values in the "
+ "frame, or an address provided to the command"
+ "")
+
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='efi symbols',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-a',
+ '--address',
+ type="str",
+ dest='address',
+ help='Load symbols for image that contains address',
+ default=None)
+
+ self.parser.add_option(
+ '-c',
+ '--clear',
+ action='store_true',
+ dest='clear',
+ help='Clear the cache of loaded images',
+ default=False)
+
+ self.parser.add_option(
+ '-f',
+ '--frame',
+ action='store_true',
+ dest='frame',
+ help='Load symbols for current stack frame',
+ default=False)
+
+ self.parser.add_option(
+ '-p',
+ '--pc',
+ action='store_true',
+ dest='pc',
+ help='Load symbols for pc',
+ default=False)
+
+ self.parser.add_option(
+ '--pei',
+ action='store_true',
+ dest='pei',
+ help='Load symbols for PEI (searches every 4 bytes)',
+ default=False)
+
+ self.parser.add_option(
+ '-e',
+ '--extended',
+ action='store_true',
+ dest='extended',
+ help='Try to load all symbols based on config tables',
+ default=False)
+
+ self.parser.add_option(
+ '-r',
+ '--range',
+ type="long",
+ dest='range',
+ help='How far to search backward for start of PE/COFF Image',
+ default=None)
+
+ self.parser.add_option(
+ '-s',
+ '--stride',
+ type="long",
+ dest='stride',
+ help='Boundary to search for PE/COFF header',
+ default=None)
+
+ self.parser.add_option(
+ '-t',
+ '--thread',
+ action='store_true',
+ dest='thread',
+ help='Load symbols for the frames of all threads',
+ default=False)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='Show more info on symbols loading in gdb',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ return self.parser.parse_args(shlex.split(arg))
+
+ def save_user_state(self):
+ self.pagination = gdb.parameter("pagination")
+ if self.pagination:
+ gdb.execute("set pagination off")
+
+ self.user_selected_thread = gdb.selected_thread()
+ self.user_selected_frame = gdb.selected_frame()
+
+ def restore_user_state(self):
+ self.user_selected_thread.switch()
+ self.user_selected_frame.select()
+
+ if self.pagination:
+ gdb.execute("set pagination on")
+
+ def canonical_address(self, address):
+ '''
+ Scrub out 48-bit non canonical addresses
+ Raw frames in gdb can have some funky values
+ '''
+
+ # Skip lowest 256 bytes to avoid interrupt frames
+ if address > 0xFF and address < 0x00007FFFFFFFFFFF:
+ return True
+ if address >= 0xFFFF800000000000:
+ return True
+
+ return False
+
+ def pc_set_for_frames(self):
+ '''Return a set for the PC's in the current frame'''
+ pc_list = []
+ frame = gdb.newest_frame()
+ while frame:
+ pc = int(frame.read_register('pc'))
+ if self.canonical_address(pc):
+ pc_list.append(pc)
+ frame = frame.older()
+
+ return set(pc_list)
+
+ def invoke(self, arg, from_tty):
+ '''gdb command to symbolicate all the frames from all the threads'''
+
+ try:
+ (options, _) = self.create_options(arg, from_tty)
+ if options.help:
+ self.parser.print_help()
+ return
+ except ValueError:
+ print('bad arguments!')
+ return
+
+ self.dont_repeat()
+
+ self.save_user_state()
+
+ if options.clear:
+ self.efi_symbols.clear()
+ return
+
+ if options.pei:
+ # XIP code can be 4 byte aligned in the FV
+ options.stride = 4
+ options.range = 0x100000
+ self.efi_symbols.configure_search(options.stride,
+ options.range,
+ options.verbose)
+
+ if options.thread:
+ thread_list = gdb.selected_inferior().threads()
+ else:
+ thread_list = (gdb.selected_thread(),)
+
+ address = None
+ if options.address:
+ value = gdb.parse_and_eval(options.address)
+ address = int(value)
+ elif options.pc:
+ address = gdb.selected_frame().pc()
+
+ if address:
+ res = self.efi_symbols.address_to_symbols(address)
+ print(res)
+ else:
+
+ for thread in thread_list:
+ thread.switch()
+
+ # You can not iterate over frames as you load symbols. Loading
+ # symbols changes the frames gdb can see due to inlining and
+ # boom. So we loop adding symbols for the current frame, and
+ # we test to see if new frames have shown up. If new frames
+ # show up we process those new frames. Thus 1st pass is the
+ # raw frame, and other passes are only new PC values.
+ NewPcSet = self.pc_set_for_frames()
+ while NewPcSet:
+ PcSet = self.pc_set_for_frames()
+ for pc in NewPcSet:
+ res = self.efi_symbols.address_to_symbols(pc)
+ print(res)
+
+ NewPcSet = PcSet.symmetric_difference(
+ self.pc_set_for_frames())
+
+ # find the EFI System tables the 1st time
+ if self.gST is None:
+ gST = gdb.lookup_global_symbol('gST')
+ if gST is not None:
+ self.gST = int(gST.value(gdb.selected_frame()))
+ table = EfiConfigurationTable(self.file, self.gST)
+ else:
+ table = None
+ else:
+ table = EfiConfigurationTable(self.file, self.gST)
+
+ if options.extended and table:
+ # load symbols from EFI System Table entry
+ for address, _ in table.DebugImageInfo():
+ res = self.efi_symbols.address_to_symbols(address)
+ print(res)
+
+ # sync up the GUID database from the build output
+ for m in gdb.objfiles():
+ if GuidNames.add_build_guid_file(str(m.filename)):
+ break
+
+ self.restore_user_state()
+
+
+class EfiCmd (gdb.Command):
+ """Commands for debugging EFI. efi <cmd>"""
+
+ def __init__(self):
+ super(EfiCmd, self).__init__("efi",
+ gdb.COMMAND_NONE,
+ gdb.COMPLETE_NONE,
+ True)
+
+ def invoke(self, arg, from_tty):
+ '''default to loading symbols'''
+ if '-h' in arg or '--help' in arg:
+ gdb.execute('help efi')
+ else:
+ # default to loading all symbols
+ gdb.execute('efi symbols --extended')
+
+
+class LoadEmulatorEfiSymbols(gdb.Breakpoint):
+ '''
+ breakpoint for EmulatorPkg to load symbols
+ Note: make sure SecGdbScriptBreak is not optimized away!
+ Also turn off the dlopen() flow like on macOS.
+ '''
+ def stop(self):
+ symbols = EfiSymbols()
+ # Emulator adds SizeOfHeaders so we need file alignment to search
+ symbols.configure_search(0x20)
+
+ frame = gdb.newest_frame()
+
+ try:
+ # gdb was looking at spill address, pre spill :(
+ LoadAddress = frame.read_register('rdx')
+ AddSymbolFlag = frame.read_register('rcx')
+ except gdb.error:
+ LoadAddress = frame.read_var('LoadAddress')
+ AddSymbolFlag = frame.read_var('AddSymbolFlag')
+
+ if AddSymbolFlag == 1:
+ res = symbols.address_to_symbols(LoadAddress)
+ else:
+ res = symbols.unload_symbols(LoadAddress)
+ print(res)
+
+ # keep running
+ return False
+
+
+# Get python backtraces to debug errors in this script
+gdb.execute("set python print-stack full")
+
+# tell efi_debugging how to walk data structures with pointers
+try:
+ pointer_width = gdb.lookup_type('int').pointer().sizeof
+except ValueError:
+ pointer_width = 8
+patch_ctypes(pointer_width)
+
+register_pretty_printer(None, build_pretty_printer(), replace=True)
+
+# gdb commands that we are adding
+# add `efi` prefix gdb command
+EfiCmd()
+
+# subcommands for `efi`
+EfiSymbolsCmd()
+EfiTablesCmd()
+EfiHobCmd()
+EfiDevicePathCmd()
+EfiGuidCmd()
+
+#
+bp = LoadEmulatorEfiSymbols('SecGdbScriptBreak', internal=True)
+if bp.pending:
+ try:
+ gdb.selected_frame()
+ # Not the emulator so do this when you attach
+ gdb.execute('efi symbols --frame --extended', True)
+ gdb.execute('bt')
+ # If you want to skip the above commands comment them out
+ pass
+ except gdb.error:
+ # If you load the script and there is no target ignore the error.
+ pass
+else:
+ # start the emulator
+ gdb.execute('run')
--
2.30.1 (Apple Git-130)


[PATCH 3/3] efi_lldb.py: - Add lldb EFI commands and pretty Print

Andrew Fish
 

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

Use efi_debugging.py Python Classes to implement EFI gdb commands:
efi_symbols, guid, table, hob, and devicepath

You can attach to any standard gdb or kdp remote server and get EFI
symbols. No modifications of EFI are required.

Example usage:
OvmfPkg/build.sh qemu -gdb tcp::9000
lldb -o "gdb-remote localhost:9000" -o "command script import efi_lldb.py"
Note you may also have to teach lldb about QEMU:
-o "settings set plugin.process.gdb-remote.target-definition-file
x86_64_target_definition.py"

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Signed-off-by: Andrew Fish <afish@apple.com>
---
efi_lldb.py | 1044 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1044 insertions(+)
create mode 100755 efi_lldb.py

diff --git a/efi_lldb.py b/efi_lldb.py
new file mode 100755
index 000000000000..6487e41bf50c
--- /dev/null
+++ b/efi_lldb.py
@@ -0,0 +1,1044 @@
+#!/usr/bin/python3
+'''
+Copyright (c) Apple Inc. 2021
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Example usage:
+OvmfPkg/build.sh qemu -gdb tcp::9000
+lldb -o "gdb-remote localhost:9000" -o "command script import efi_lldb.py"
+'''
+
+import optparse
+import shlex
+import subprocess
+import uuid
+import sys
+import os
+from pathlib import Path
+from efi_debugging import EfiDevicePath, EfiConfigurationTable, EfiTpl
+from efi_debugging import EfiHob, GuidNames, EfiStatusClass, EfiBootMode
+from efi_debugging import PeTeImage, patch_ctypes
+
+try:
+ # Just try for LLDB in case PYTHONPATH is already correctly setup
+ import lldb
+except ImportError:
+ try:
+ env = os.environ.copy()
+ env['LLDB_DEFAULT_PYTHON_VERSION'] = str(sys.version_info.major)
+ lldb_python_path = subprocess.check_output(
+ ["xcrun", "lldb", "-P"], env=env).decode("utf-8").strip()
+ sys.path.append(lldb_python_path)
+ import lldb
+ except ValueError:
+ print("Couldn't find LLDB.framework from lldb -P")
+ print("PYTHONPATH should match the currently selected lldb")
+ sys.exit(-1)
+
+
+class LldbFileObject(object):
+ '''
+ Class that fakes out file object to abstract lldb from the generic code.
+ For lldb this is memory so we don't have a concept of the end of the file.
+ '''
+
+ def __init__(self, process):
+ # _exe_ctx is lldb.SBExecutionContext
+ self._process = process
+ self._offset = 0
+ self._SBError = lldb.SBError()
+
+ def tell(self):
+ return self._offset
+
+ def read(self, size=-1):
+ if size == -1:
+ # arbitrary default size
+ size = 0x1000000
+
+ data = self._process.ReadMemory(self._offset, size, self._SBError)
+ if self._SBError.fail:
+ raise MemoryError(
+ f'lldb could not read memory 0x{size:x} '
+ f' bytes from 0x{self._offset:08x}')
+ else:
+ return data
+
+ def readable(self):
+ return True
+
+ def seek(self, offset, whence=0):
+ if whence == 0:
+ self._offset = offset
+ elif whence == 1:
+ self._offset += offset
+ else:
+ # whence == 2 is seek from end
+ raise NotImplementedError
+
+ def seekable(self):
+ return True
+
+ def write(self, data):
+ result = self._process.WriteMemory(self._offset, data, self._SBError)
+ if self._SBError.fail:
+ raise MemoryError(
+ f'lldb could not write memory to 0x{self._offset:08x}')
+ return result
+
+ def writable(self):
+ return True
+
+ def truncate(self, size=None):
+ raise NotImplementedError
+
+ def flush(self):
+ raise NotImplementedError
+
+ def fileno(self):
+ raise NotImplementedError
+
+
+class EfiSymbols:
+ """
+ Class to manage EFI Symbols
+ You need to pass file, and exe_ctx to load symbols.
+ You can print(EfiSymbols()) to see the currently loaded symbols
+ """
+
+ loaded = {}
+ stride = None
+ range = None
+ verbose = False
+
+ def __init__(self, target=None):
+ if target:
+ EfiSymbols.target = target
+ EfiSymbols._file = LldbFileObject(target.process)
+
+ @ classmethod
+ def __str__(cls):
+ return ''.join(f'{pecoff}\n' for (pecoff, _) in cls.loaded.values())
+
+ @ classmethod
+ def configure_search(cls, stride, range, verbose=False):
+ cls.stride = stride
+ cls.range = range
+ cls.verbose = verbose
+
+ @ classmethod
+ def clear(cls):
+ cls.loaded = {}
+
+ @ classmethod
+ def add_symbols_for_pecoff(cls, pecoff):
+ '''Tell lldb the location of the .text and .data sections.'''
+
+ if pecoff.LoadAddress in cls.loaded:
+ return 'Already Loaded: '
+
+ module = cls.target.AddModule(None, None, str(pecoff.CodeViewUuid))
+ if not module:
+ module = cls.target.AddModule(pecoff.CodeViewPdb,
+ None,
+ str(pecoff.CodeViewUuid))
+ if module.IsValid():
+ SBError = cls.target.SetModuleLoadAddress(
+ module, pecoff.LoadAddress + pecoff.TeAdjust)
+ if SBError.success:
+ cls.loaded[pecoff.LoadAddress] = (pecoff, module)
+ return ''
+
+ return 'Symbols NOT FOUND: '
+
+ @ classmethod
+ def address_to_symbols(cls, address, reprobe=False):
+ '''
+ Given an address search backwards for a PE/COFF (or TE) header
+ and load symbols. Return a status string.
+ '''
+ if not isinstance(address, int):
+ address = int(address)
+
+ pecoff, _ = cls.address_in_loaded_pecoff(address)
+ if not reprobe and pecoff is not None:
+ # skip the probe of the remote
+ return f'{pecoff} is already loaded'
+
+ pecoff = PeTeImage(cls._file, None)
+ if pecoff.pcToPeCoff(address, cls.stride, cls.range):
+ res = cls.add_symbols_for_pecoff(pecoff)
+ return f'{res}{pecoff}'
+ else:
+ return f'0x{address:08x} not in a PE/COFF (or TE) image'
+
+ @ classmethod
+ def address_in_loaded_pecoff(cls, address):
+ if not isinstance(address, int):
+ address = int(address)
+
+ for (pecoff, module) in cls.loaded.values():
+ if (address >= pecoff.LoadAddress and
+ address <= pecoff.EndLoadAddress):
+
+ return pecoff, module
+
+ return None, None
+
+ @ classmethod
+ def unload_symbols(cls, address):
+ pecoff, module = cls.address_in_loaded_pecoff(address)
+ if module:
+ name = str(module)
+ cls.target.ClearModuleLoadAddress(module)
+ cls.target.RemoveModule(module)
+ del cls.loaded[pecoff.LoadAddress]
+ return f'{name:s} was unloaded'
+ return f'0x{address:x} was not in a loaded image'
+
+
+def arg_to_address(frame, arg):
+ ''' convert an lldb command arg into a memory address (addr_t)'''
+
+ if arg is None:
+ return None
+
+ arg_str = arg if isinstance(arg, str) else str(arg)
+ SBValue = frame.EvaluateExpression(arg_str)
+ if SBValue.error.fail:
+ return arg
+
+ if (SBValue.TypeIsPointerType() or
+ SBValue.value_type == lldb.eValueTypeRegister or
+ SBValue.value_type == lldb.eValueTypeRegisterSet or
+ SBValue.value_type == lldb.eValueTypeConstResult):
+ try:
+ addr = SBValue.GetValueAsAddress()
+ except ValueError:
+ addr = SBValue.unsigned
+ else:
+ try:
+ addr = SBValue.address_of.GetValueAsAddress()
+ except ValueError:
+ addr = SBValue.address_of.unsigned
+
+ return addr
+
+
+def arg_to_data(frame, arg):
+ ''' convert an lldb command arg into a data vale (uint32_t/uint64_t)'''
+ if not isinstance(arg, str):
+ arg_str = str(str)
+
+ SBValue = frame.EvaluateExpression(arg_str)
+ return SBValue.unsigned
+
+
+class EfiDevicePathCommand:
+
+ def create_options(self):
+ ''' standard lldb command help/options parser'''
+ usage = "usage: %prog [options]"
+ description = '''Command that can EFI Config Tables
+'''
+
+ # Pass add_help_option = False, since this keeps the command in line
+ # with lldb commands, and we wire up "help command" to work by
+ # providing the long & short help methods below.
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='devicepath',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='hex dump extra data',
+ default=False)
+
+ self.parser.add_option(
+ '-n',
+ '--node',
+ action='store_true',
+ dest='node',
+ help='dump a single device path node',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ def get_short_help(self):
+ '''standard lldb function method'''
+ return "Display EFI Tables"
+
+ def get_long_help(self):
+ '''standard lldb function method'''
+ return self.help_string
+
+ def __init__(self, debugger, internal_dict):
+ '''standard lldb function method'''
+ self.create_options()
+ self.help_string = self.parser.format_help()
+
+ def __call__(self, debugger, command, exe_ctx, result):
+ '''standard lldb function method'''
+ # Use the Shell Lexer to properly parse up command options just like a
+ # shell would
+ command_args = shlex.split(command)
+
+ try:
+ (options, args) = self.parser.parse_args(command_args)
+ dev_list = []
+ for arg in args:
+ dev_list.append(arg_to_address(exe_ctx.frame, arg))
+ except ValueError:
+ # if you don't handle exceptions, passing an incorrect argument
+ # to the OptionParser will cause LLDB to exit (courtesy of
+ # OptParse dealing with argument errors by throwing SystemExit)
+ result.SetError("option parsing failed")
+ return
+
+ if options.help:
+ self.parser.print_help()
+ return
+
+ file = LldbFileObject(exe_ctx.process)
+
+ for dev_addr in dev_list:
+ if options.node:
+ print(EfiDevicePath(file).device_path_node_str(
+ dev_addr, options.verbose))
+ else:
+ device_path = EfiDevicePath(file, dev_addr, options.verbose)
+ if device_path.valid():
+ print(device_path)
+
+
+class EfiHobCommand:
+ def create_options(self):
+ ''' standard lldb command help/options parser'''
+ usage = "usage: %prog [options]"
+ description = '''Command that can EFI dump EFI HOBs'''
+
+ # Pass add_help_option = False, since this keeps the command in line
+ # with lldb commands, and we wire up "help command" to work by
+ # providing the long & short help methods below.
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='table',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-a',
+ '--address',
+ type="int",
+ dest='address',
+ help='Parse HOBs from address',
+ default=None)
+
+ self.parser.add_option(
+ '-t',
+ '--type',
+ type="int",
+ dest='type',
+ help='Only dump HOBS of his type',
+ default=None)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='hex dump extra data',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ def get_short_help(self):
+ '''standard lldb function method'''
+ return "Display EFI Hobs"
+
+ def get_long_help(self):
+ '''standard lldb function method'''
+ return self.help_string
+
+ def __init__(self, debugger, internal_dict):
+ '''standard lldb function method'''
+ self.create_options()
+ self.help_string = self.parser.format_help()
+
+ def __call__(self, debugger, command, exe_ctx, result):
+ '''standard lldb function method'''
+ # Use the Shell Lexer to properly parse up command options just like a
+ # shell would
+ command_args = shlex.split(command)
+
+ try:
+ (options, _) = self.parser.parse_args(command_args)
+ except ValueError:
+ # if you don't handle exceptions, passing an incorrect argument
+ # to the OptionParser will cause LLDB to exit (courtesy of
+ # OptParse dealing with argument errors by throwing SystemExit)
+ result.SetError("option parsing failed")
+ return
+
+ if options.help:
+ self.parser.print_help()
+ return
+
+ address = arg_to_address(exe_ctx.frame, options.address)
+
+ file = LldbFileObject(exe_ctx.process)
+ hob = EfiHob(file, address, options.verbose).get_hob_by_type(
+ options.type)
+ print(hob)
+
+
+class EfiTableCommand:
+
+ def create_options(self):
+ ''' standard lldb command help/options parser'''
+ usage = "usage: %prog [options]"
+ description = '''Command that can display EFI Config Tables
+'''
+
+ # Pass add_help_option = False, since this keeps the command in line
+ # with lldb commands, and we wire up "help command" to work by
+ # providing the long & short help methods below.
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='table',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ def get_short_help(self):
+ '''standard lldb function method'''
+ return "Display EFI Tables"
+
+ def get_long_help(self):
+ '''standard lldb function method'''
+ return self.help_string
+
+ def __init__(self, debugger, internal_dict):
+ '''standard lldb function method'''
+ self.create_options()
+ self.help_string = self.parser.format_help()
+
+ def __call__(self, debugger, command, exe_ctx, result):
+ '''standard lldb function method'''
+ # Use the Shell Lexer to properly parse up command options just like a
+ # shell would
+ command_args = shlex.split(command)
+
+ try:
+ (options, _) = self.parser.parse_args(command_args)
+ except ValueError:
+ # if you don't handle exceptions, passing an incorrect argument
+ # to the OptionParser will cause LLDB to exit (courtesy of
+ # OptParse dealing with argument errors by throwing SystemExit)
+ result.SetError("option parsing failed")
+ return
+
+ if options.help:
+ self.parser.print_help()
+ return
+
+ gST = exe_ctx.target.FindFirstGlobalVariable('gST')
+ if gST.error.fail:
+ print('Error: This command requires symbols for gST to be loaded')
+ return
+
+ file = LldbFileObject(exe_ctx.process)
+ table = EfiConfigurationTable(file, gST.unsigned)
+ if table:
+ print(table, '\n')
+
+
+class EfiGuidCommand:
+
+ def create_options(self):
+ ''' standard lldb command help/options parser'''
+ usage = "usage: %prog [options]"
+ description = '''
+ Command that can display all EFI GUID's or give info on a
+ specific GUID's
+ '''
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='guid',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-n',
+ '--new',
+ action='store_true',
+ dest='new',
+ help='Generate a new GUID',
+ default=False)
+
+ self.parser.add_option(
+ '-v',
+ '--verbose',
+ action='store_true',
+ dest='verbose',
+ help='Also display GUID C structure values',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ def get_short_help(self):
+ '''standard lldb function method'''
+ return "Display EFI GUID's"
+
+ def get_long_help(self):
+ '''standard lldb function method'''
+ return self.help_string
+
+ def __init__(self, debugger, internal_dict):
+ '''standard lldb function method'''
+ self.create_options()
+ self.help_string = self.parser.format_help()
+
+ def __call__(self, debugger, command, exe_ctx, result):
+ '''standard lldb function method'''
+ # Use the Shell Lexer to properly parse up command options just like a
+ # shell would
+ command_args = shlex.split(command)
+
+ try:
+ (options, args) = self.parser.parse_args(command_args)
+ if len(args) >= 1:
+ # guid { 0x414e6bdd, 0xe47b, 0x47cc,
+ # { 0xb2, 0x44, 0xbb, 0x61, 0x02, 0x0c,0xf5, 0x16 }}
+ # this generates multiple args
+ arg = ' '.join(args)
+ except ValueError:
+ # if you don't handle exceptions, passing an incorrect argument
+ # to the OptionParser will cause LLDB to exit (courtesy of
+ # OptParse dealing with argument errors by throwing SystemExit)
+ result.SetError("option parsing failed")
+ return
+
+ if options.help:
+ self.parser.print_help()
+ return
+
+ if options.new:
+ guid = uuid.uuid4()
+ print(str(guid).upper())
+ print(GuidNames.to_c_guid(guid))
+ return
+
+ if len(args) > 0:
+ if GuidNames.is_guid_str(arg):
+ # guid 05AD34BA-6F02-4214-952E-4DA0398E2BB9
+ key = arg.lower()
+ name = GuidNames.to_name(key)
+ elif GuidNames.is_c_guid(arg):
+ # guid { 0x414e6bdd, 0xe47b, 0x47cc,
+ # { 0xb2, 0x44, 0xbb, 0x61, 0x02, 0x0c,0xf5, 0x16 }}
+ key = GuidNames.from_c_guid(arg)
+ name = GuidNames.to_name(key)
+ else:
+ # guid gEfiDxeServicesTableGuid
+ name = arg
+ try:
+ key = GuidNames.to_guid(name)
+ name = GuidNames.to_name(key)
+ except ValueError:
+ return
+
+ extra = f'{GuidNames.to_c_guid(key)}: ' if options.verbose else ''
+ print(f'{key}: {extra}{name}')
+
+ else:
+ for key, value in GuidNames._dict_.items():
+ if options.verbose:
+ extra = f'{GuidNames.to_c_guid(key)}: '
+ else:
+ extra = ''
+ print(f'{key}: {extra}{value}')
+
+
+class EfiSymbolicateCommand(object):
+ '''Class to abstract an lldb command'''
+
+ def create_options(self):
+ ''' standard lldb command help/options parser'''
+ usage = "usage: %prog [options]"
+ description = '''Command that can load EFI PE/COFF and TE image
+ symbols. If you are having trouble in PEI try adding --pei.
+ '''
+
+ # Pass add_help_option = False, since this keeps the command in line
+ # with lldb commands, and we wire up "help command" to work by
+ # providing the long & short help methods below.
+ self.parser = optparse.OptionParser(
+ description=description,
+ prog='efi_symbols',
+ usage=usage,
+ add_help_option=False)
+
+ self.parser.add_option(
+ '-a',
+ '--address',
+ type="int",
+ dest='address',
+ help='Load symbols for image at address',
+ default=None)
+
+ self.parser.add_option(
+ '-f',
+ '--frame',
+ action='store_true',
+ dest='frame',
+ help='Load symbols for current stack frame',
+ default=False)
+
+ self.parser.add_option(
+ '-p',
+ '--pc',
+ action='store_true',
+ dest='pc',
+ help='Load symbols for pc',
+ default=False)
+
+ self.parser.add_option(
+ '--pei',
+ action='store_true',
+ dest='pei',
+ help='Load symbols for PEI (searches every 4 bytes)',
+ default=False)
+
+ self.parser.add_option(
+ '-e',
+ '--extended',
+ action='store_true',
+ dest='extended',
+ help='Try to load all symbols based on config tables.',
+ default=False)
+
+ self.parser.add_option(
+ '-r',
+ '--range',
+ type="long",
+ dest='range',
+ help='How far to search backward for start of PE/COFF Image',
+ default=None)
+
+ self.parser.add_option(
+ '-s',
+ '--stride',
+ type="long",
+ dest='stride',
+ help='Boundary to search for PE/COFF header',
+ default=None)
+
+ self.parser.add_option(
+ '-t',
+ '--thread',
+ action='store_true',
+ dest='thread',
+ help='Load symbols for the frames of all threads',
+ default=False)
+
+ self.parser.add_option(
+ '-h',
+ '--help',
+ action='store_true',
+ dest='help',
+ help='Show help for the command',
+ default=False)
+
+ def get_short_help(self):
+ '''standard lldb function method'''
+ return (
+ "Load symbols based on an address that is part of"
+ " a PE/COFF EFI image.")
+
+ def get_long_help(self):
+ '''standard lldb function method'''
+ return self.help_string
+
+ def __init__(self, debugger, unused):
+ '''standard lldb function method'''
+ self.create_options()
+ self.help_string = self.parser.format_help()
+
+ def lldb_print(self, lldb_str):
+ # capture command out like an lldb command
+ self.result.PutCString(lldb_str)
+ # flush the output right away
+ self.result.SetImmediateOutputFile(
+ self.exe_ctx.target.debugger.GetOutputFile())
+
+ def __call__(self, debugger, command, exe_ctx, result):
+ '''standard lldb function method'''
+ # Use the Shell Lexer to properly parse up command options just like a
+ # shell would
+ command_args = shlex.split(command)
+
+ try:
+ (options, _) = self.parser.parse_args(command_args)
+ except ValueError:
+ # if you don't handle exceptions, passing an incorrect argument
+ # to the OptionParser will cause LLDB to exit (courtesy of
+ # OptParse dealing with argument errors by throwing SystemExit)
+ result.SetError("option parsing failed")
+ return
+
+ if options.help:
+ self.parser.print_help()
+ return
+
+ file = LldbFileObject(exe_ctx.process)
+ efi_symbols = EfiSymbols(exe_ctx.target)
+ self.result = result
+ self.exe_ctx = exe_ctx
+
+ if options.pei:
+ # XIP code ends up on a 4 byte boundary.
+ options.stride = 4
+ options.range = 0x100000
+ efi_symbols.configure_search(options.stride, options.range)
+
+ if not options.pc and options.address is None:
+ # default to
+ options.frame = True
+
+ if options.frame:
+ if not exe_ctx.frame.IsValid():
+ result.SetError("invalid frame")
+ return
+
+ threads = exe_ctx.process.threads if options.thread else [
+ exe_ctx.thread]
+
+ for thread in threads:
+ for frame in thread:
+ res = efi_symbols.address_to_symbols(frame.pc)
+ self.lldb_print(res)
+
+ else:
+ if options.address is not None:
+ address = options.address
+ elif options.pc:
+ try:
+ address = exe_ctx.thread.GetSelectedFrame().pc
+ except ValueError:
+ result.SetError("invalid pc")
+ return
+ else:
+ address = 0
+
+ res = efi_symbols.address_to_symbols(address.pc)
+ print(res)
+
+ if options.extended:
+
+ gST = exe_ctx.target.FindFirstGlobalVariable('gST')
+ if gST.error.fail:
+ print('Error: This command requires symbols to be loaded')
+ else:
+ table = EfiConfigurationTable(file, gST.unsigned)
+ for address, _ in table.DebugImageInfo():
+ res = efi_symbols.address_to_symbols(address)
+ self.lldb_print(res)
+
+ # keep trying module file names until we find a GUID xref file
+ for m in exe_ctx.target.modules:
+ if GuidNames.add_build_guid_file(str(m.file)):
+ break
+
+
+def CHAR16_TypeSummary(valobj, internal_dict):
+ '''
+ Display CHAR16 as a String in the debugger.
+ Note: utf-8 is returned as that is the value for the debugger.
+ '''
+ SBError = lldb.SBError()
+ Str = ''
+ if valobj.TypeIsPointerType():
+ if valobj.GetValueAsUnsigned() == 0:
+ return "NULL"
+
+ # CHAR16 * max string size 1024
+ for i in range(1024):
+ Char = valobj.GetPointeeData(i, 1).GetUnsignedInt16(SBError, 0)
+ if SBError.fail or Char == 0:
+ break
+ Str += chr(Char)
+ return 'L"' + Str + '"'
+
+ if valobj.num_children == 0:
+ # CHAR16
+ return "L'" + chr(valobj.unsigned) + "'"
+
+ else:
+ # CHAR16 []
+ for i in range(valobj.num_children):
+ Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt16(SBError, 0)
+ if Char == 0:
+ break
+ Str += chr(Char)
+ return 'L"' + Str + '"'
+
+ return Str
+
+
+def CHAR8_TypeSummary(valobj, internal_dict):
+ '''
+ Display CHAR8 as a String in the debugger.
+ Note: utf-8 is returned as that is the value for the debugger.
+ '''
+ SBError = lldb.SBError()
+ Str = ''
+ if valobj.TypeIsPointerType():
+ if valobj.GetValueAsUnsigned() == 0:
+ return "NULL"
+
+ # CHAR8 * max string size 1024
+ for i in range(1024):
+ Char = valobj.GetPointeeData(i, 1).GetUnsignedInt8(SBError, 0)
+ if SBError.fail or Char == 0:
+ break
+ Str += chr(Char)
+ Str = '"' + Str + '"'
+ return Str
+
+ if valobj.num_children == 0:
+ # CHAR8
+ return "'" + chr(valobj.unsigned) + "'"
+ else:
+ # CHAR8 []
+ for i in range(valobj.num_children):
+ Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0)
+ if SBError.fail or Char == 0:
+ break
+ Str += chr(Char)
+ return '"' + Str + '"'
+
+ return Str
+
+
+def EFI_STATUS_TypeSummary(valobj, internal_dict):
+ if valobj.TypeIsPointerType():
+ return ''
+ return str(EfiStatusClass(valobj.unsigned))
+
+
+def EFI_TPL_TypeSummary(valobj, internal_dict):
+ if valobj.TypeIsPointerType():
+ return ''
+ return str(EfiTpl(valobj.unsigned))
+
+
+def EFI_GUID_TypeSummary(valobj, internal_dict):
+ if valobj.TypeIsPointerType():
+ return ''
+ return str(GuidNames(bytes(valobj.data.uint8)))
+
+
+def EFI_BOOT_MODE_TypeSummary(valobj, internal_dict):
+ if valobj.TypeIsPointerType():
+ return ''
+ '''Return #define name for EFI_BOOT_MODE'''
+ return str(EfiBootMode(valobj.unsigned))
+
+
+def lldb_type_formaters(debugger, mod_name):
+ '''Teach lldb about EFI types'''
+
+ category = debugger.GetDefaultCategory()
+ FormatBool = lldb.SBTypeFormat(lldb.eFormatBoolean)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("BOOLEAN"), FormatBool)
+
+ FormatHex = lldb.SBTypeFormat(lldb.eFormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT64"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT64"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT32"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT32"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT16"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT16"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT8"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT8"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINTN"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("INTN"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR8"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR16"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier(
+ "EFI_PHYSICAL_ADDRESS"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier(
+ "PHYSICAL_ADDRESS"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_LBA"), FormatHex)
+ category.AddTypeFormat(
+ lldb.SBTypeNameSpecifier("EFI_BOOT_MODE"), FormatHex)
+ category.AddTypeFormat(lldb.SBTypeNameSpecifier(
+ "EFI_FV_FILETYPE"), FormatHex)
+
+ #
+ # Smart type printing for EFI
+ #
+
+ debugger.HandleCommand(
+ f'type summary add GUID - -python-function '
+ f'{mod_name}.EFI_GUID_TypeSummary')
+ debugger.HandleCommand(
+ f'type summary add EFI_GUID --python-function '
+ f'{mod_name}.EFI_GUID_TypeSummary')
+ debugger.HandleCommand(
+ f'type summary add EFI_STATUS --python-function '
+ f'{mod_name}.EFI_STATUS_TypeSummary')
+ debugger.HandleCommand(
+ f'type summary add EFI_TPL - -python-function '
+ f'{mod_name}.EFI_TPL_TypeSummary')
+ debugger.HandleCommand(
+ f'type summary add EFI_BOOT_MODE --python-function '
+ f'{mod_name}.EFI_BOOT_MODE_TypeSummary')
+
+ debugger.HandleCommand(
+ f'type summary add CHAR16 --python-function '
+ f'{mod_name}.CHAR16_TypeSummary')
+
+ # W605 this is the correct escape sequence for the lldb command
+ debugger.HandleCommand(
+ f'type summary add --regex "CHAR16 \[[0-9]+\]" ' # noqa: W605
+ f'--python-function {mod_name}.CHAR16_TypeSummary')
+
+ debugger.HandleCommand(
+ f'type summary add CHAR8 --python-function '
+ f'{mod_name}.CHAR8_TypeSummary')
+
+ # W605 this is the correct escape sequence for the lldb command
+ debugger.HandleCommand(
+ f'type summary add --regex "CHAR8 \[[0-9]+\]" ' # noqa: W605
+ f'--python-function {mod_name}.CHAR8_TypeSummary')
+
+
+class LldbWorkaround:
+ needed = True
+
+ @classmethod
+ def activate(cls):
+ if cls.needed:
+ lldb.debugger.HandleCommand("process handle SIGALRM -n false")
+ cls.needed = False
+
+
+def LoadEmulatorEfiSymbols(frame, bp_loc, internal_dict):
+ #
+ # This is an lldb breakpoint script, and assumes the breakpoint is on a
+ # function with the same prototype as SecGdbScriptBreak(). The
+ # argument names are important as lldb looks them up.
+ #
+ # VOID
+ # SecGdbScriptBreak (
+ # char *FileName,
+ # int FileNameLength,
+ # long unsigned int LoadAddress,
+ # int AddSymbolFlag
+ # )
+ # {
+ # return;
+ # }
+ #
+ # When the emulator loads a PE/COFF image, it calls the stub function with
+ # the filename of the symbol file, the length of the FileName, the
+ # load address and a flag to indicate if this is a load or unload operation
+ #
+ LldbWorkaround().activate()
+
+ symbols = EfiSymbols(frame.thread.process.target)
+ LoadAddress = frame.FindVariable("LoadAddress").unsigned
+ if frame.FindVariable("AddSymbolFlag").unsigned == 1:
+ res = symbols.address_to_symbols(LoadAddress)
+ else:
+ res = symbols.unload_symbols(LoadAddress)
+ print(res)
+
+ # make breakpoint command continue
+ return False
+
+
+def __lldb_init_module(debugger, internal_dict):
+ '''
+ This initializer is being run from LLDB in the embedded command interpreter
+ '''
+
+ mod_name = Path(__file__).stem
+ lldb_type_formaters(debugger, mod_name)
+
+ # Add any commands contained in this module to LLDB
+ debugger.HandleCommand(
+ f'command script add -c {mod_name}.EfiSymbolicateCommand efi_symbols')
+ debugger.HandleCommand(
+ f'command script add -c {mod_name}.EfiGuidCommand guid')
+ debugger.HandleCommand(
+ f'command script add -c {mod_name}.EfiTableCommand table')
+ debugger.HandleCommand(
+ f'command script add -c {mod_name}.EfiHobCommand hob')
+ debugger.HandleCommand(
+ f'command script add -c {mod_name}.EfiDevicePathCommand devicepath')
+
+ print('EFI specific commands have been installed.')
+
+ # patch the ctypes c_void_p values if the debuggers OS and EFI have
+ # different ideas on the size of the debug.
+ try:
+ patch_ctypes(debugger.GetSelectedTarget().addr_size)
+ except ValueError:
+ # incase the script is imported and the debugger has not target
+ # defaults to sizeof(UINTN) == sizeof(UINT64)
+ patch_ctypes()
+
+ try:
+ target = debugger.GetSelectedTarget()
+ if target.FindFunctions('SecGdbScriptBreak').symbols:
+ breakpoint = target.BreakpointCreateByName('SecGdbScriptBreak')
+ # Set the emulator breakpoints, if we are in the emulator
+ cmd = 'breakpoint command add -s python -F '
+ cmd += f'efi_lldb.LoadEmulatorEfiSymbols {breakpoint.GetID()}'
+ debugger.HandleCommand(cmd)
+ print('Type r to run emulator.')
+ else:
+ raise ValueError("No Emulator Symbols")
+
+ except ValueError:
+ # default action when the script is imported
+ debugger.HandleCommand("efi_symbols --frame --extended")
+ debugger.HandleCommand("register read")
+ debugger.HandleCommand("bt all")
+
+
+if __name__ == '__main__':
+ pass
--
2.30.1 (Apple Git-130)


[PATCH 0/3] Add support for gdb and lldb

Andrew Fish
 

This patch set adds debugging support for gdb and lldb.
It also adds generic debugging classes that use a file like object to
make it easy to import into any debugger that supports Python.

Since these debugging scripts don't depend on any EFI code I was thinking
we could place them in the root of the repo to be easy to discover.

I've tested gdb on Ubuntu and lldb on macOS for IA32 and X64.

Andrew Fish (3):
efi_debugging.py: - Add debugger agnostic debugging Python Classes
efi_gdb.py: - Add gdb EFI commands and pretty Print
efi_lldb.py: - Add lldb EFI commands and pretty Print

efi_debugging.py | 2187 ++++++++++++++++++++++++++++++++++++++++++++++
efi_gdb.py | 918 +++++++++++++++++++
efi_lldb.py | 1044 ++++++++++++++++++++++
3 files changed, 4149 insertions(+)
create mode 100755 efi_debugging.py
create mode 100755 efi_gdb.py
create mode 100755 efi_lldb.py

--
2.30.1 (Apple Git-130)


[PATCH 1/3] efi_debugging.py: - Add debugger agnostic debugging Python Classes

Andrew Fish
 


[PATCH] EmbeddedPkg/GdbStub: Mandatory LoadedImage for DebugImageInfoTable

Marvin Häuser
 

To make parsing DebugImageInfoTable easier and safer, require the
LoadedImage protocol instance to be valid for every NormalImage
entry.

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Daniel Schaefer <daniel.schaefer@hpe.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
EmbeddedPkg/GdbStub/GdbStub.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/EmbeddedPkg/GdbStub/GdbStub.c b/EmbeddedPkg/GdbStub/GdbStub.c
index 09167fdafb4d..29aa63237304 100644
--- a/EmbeddedPkg/GdbStub/GdbStub.c
+++ b/EmbeddedPkg/GdbStub/GdbStub.c
@@ -1044,8 +1044,9 @@ QxferLibrary (
if (gDebugTable != NULL) {
for (; gEfiDebugImageTableEntry < gDebugImageTableHeader->TableSize; gEfiDebugImageTableEntry++, gDebugTable++) {
if (gDebugTable->ImageInfoType != NULL) {
- if ((*gDebugTable->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
- (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
+ if (*gDebugTable->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) {
+ ASSERT (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL);
+
Pdb = PeCoffLoaderGetDebuggerInfo (
gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase,
&LoadAddress
--
2.31.1


[PATCH] ArmPkg/DefaultExceptionHandlerLib: Mandatory LoadedImage for DebugImageInfoTable

Marvin Häuser
 

To make parsing DebugImageInfoTable easier and safer, require the
LoadedImage protocol instance to be valid for every NormalImage
entry.

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
index 9befb6d4db9b..d442b5d358b2 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
@@ -52,8 +52,9 @@ GetImageName (
Address = (CHAR8 *)(UINTN)FaultAddress;
for (Entry = 0; Entry < DebugTableHeader->TableSize; Entry++, DebugTable++) {
if (DebugTable->ImageInfoType != NULL) {
- if ((*DebugTable->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
- (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
+ if (*DebugTable->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) {
+ ASSERT (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL);
+
if ((Address >= (CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase) &&
(Address <= ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance->ImageSize))) {
*ImageBase = (UINTN)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;
--
2.31.1


[PATCH] MdeModulePkg/CoreDxe: Mandatory LoadedImage for DebugImageInfoTable

Marvin Häuser
 

To make parsing DebugImageInfoTable easier and safer, require the
LoadedImage protocol instance to be valid for every NormalImage
entry.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
index cc22e23eb0b3..afc54965bc33 100644
--- a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
+++ b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
@@ -173,6 +173,8 @@ CoreNewDebugImageInfoEntry (
UINTN TableSize;
EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage;

+ ASSERT (LoadedImage != NULL);
+
//
// Set the flag indicating that we're in the process of updating the table.
//
--
2.31.1


[PATCH] ArmPkg/DefaultExceptionHandlerLib: Check DebugImageInfoTable type safely

Marvin Häuser
 

C does not allow casting to or dereferencing incompatible pointer
types. Use the ImageInfoType member of the union first to determine
the data type before dereferencing NormalImage.

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
index e9fea4038252..9befb6d4db9b 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c
@@ -51,8 +51,8 @@ GetImageName (

Address = (CHAR8 *)(UINTN)FaultAddress;
for (Entry = 0; Entry < DebugTableHeader->TableSize; Entry++, DebugTable++) {
- if (DebugTable->NormalImage != NULL) {
- if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
+ if (DebugTable->ImageInfoType != NULL) {
+ if ((*DebugTable->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
(DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
if ((Address >= (CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase) &&
(Address <= ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance->ImageSize))) {
--
2.31.1


[PATCH] EmbeddedPkg/GdbStub: Check DebugImageInfoTable type safely

Marvin Häuser
 

C does not allow casting to or dereferencing incompatible pointer
types. Use the ImageInfoType member of the union first to determine
the data type before dereferencing NormalImage.

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Daniel Schaefer <daniel.schaefer@hpe.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
EmbeddedPkg/GdbStub/GdbStub.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/EmbeddedPkg/GdbStub/GdbStub.c b/EmbeddedPkg/GdbStub/GdbStub.c
index 7f2a5ed20011..09167fdafb4d 100644
--- a/EmbeddedPkg/GdbStub/GdbStub.c
+++ b/EmbeddedPkg/GdbStub/GdbStub.c
@@ -1043,8 +1043,8 @@ QxferLibrary (

if (gDebugTable != NULL) {
for (; gEfiDebugImageTableEntry < gDebugImageTableHeader->TableSize; gEfiDebugImageTableEntry++, gDebugTable++) {
- if (gDebugTable->NormalImage != NULL) {
- if ((gDebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
+ if (gDebugTable->ImageInfoType != NULL) {
+ if ((*gDebugTable->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
(gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
Pdb = PeCoffLoaderGetDebuggerInfo (
gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase,
--
2.31.1


[PATCH] SecurityPkg/SecureBootConfigDxe: Fix certificate lookup algorithm

Marvin Häuser
 

The current certificate lookup code does not check the bounds of the
authentication data before accessing it. Abort if the header cannot
fit, and proceed to the next hashing algortihm if the OID of the
current one exceeds the authentication data bounds.

Additionally move the two-byte encoding check out of the loop as the
data is invariant.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c | 45 ++++++++++++--------
1 file changed, 28 insertions(+), 17 deletions(-)

diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
index 65a8188d6d03..fd7629f61862 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
@@ -1969,30 +1969,41 @@ HashPeImageByType (
{
UINT8 Index;
WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
+ UINT32 AuthDataSize;

PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);
+ if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof (PkcsCertData->Hdr);
+ if (AuthDataSize < 32) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check the Hash algorithm in PE/COFF Authenticode.
+ // According to PKCS#7 Definition:
+ // SignedData ::= SEQUENCE {
+ // version Version,
+ // digestAlgorithms DigestAlgorithmIdentifiers,
+ // contentInfo ContentInfo,
+ // .... }
+ // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
+ // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
+ // Fixed offset (+32) is calculated based on two bytes of length encoding.
+ //
+ if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
+ //
+ // Only support two bytes of Long Form of Length Encoding.
+ //
+ return EFI_UNSUPPORTED;
+ }

for (Index = 0; Index < HASHALG_MAX; Index++) {
- //
- // Check the Hash algorithm in PE/COFF Authenticode.
- // According to PKCS#7 Definition:
- // SignedData ::= SEQUENCE {
- // version Version,
- // digestAlgorithms DigestAlgorithmIdentifiers,
- // contentInfo ContentInfo,
- // .... }
- // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
- // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
- // Fixed offset (+32) is calculated based on two bytes of length encoding.
- //
- if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
- //
- // Only support two bytes of Long Form of Length Encoding.
- //
+ if (AuthDataSize - 32 < mHash[Index].OidLength) {
continue;
}

- //
if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
break;
}
--
2.31.1


[PATCH] UefiCpuPkg/BaseUefiCpuLib: Use toolchain-specific rodata section name

Marvin Häuser
 

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

Correctly define the read-only data sections with the
toolchain-specific section name. This hardens image permission
security and may save image space.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.nasm | 2 +-
UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.nasm | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.nasm b/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.nasm
index 5e27cc325012..cfb8bf4a5ae0 100644
--- a/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.nasm
+++ b/UefiCpuPkg/Library/BaseUefiCpuLib/Ia32/InitializeFpu.nasm
@@ -6,7 +6,7 @@
;*
;------------------------------------------------------------------------------

- SECTION .rodata
+ SECTION RODATA_SECTION_NAME

;
; Float control word initial value:
diff --git a/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.nasm b/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.nasm
index 8485b4713548..3c976a21e391 100644
--- a/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.nasm
+++ b/UefiCpuPkg/Library/BaseUefiCpuLib/X64/InitializeFpu.nasm
@@ -6,7 +6,7 @@
;*
;------------------------------------------------------------------------------

- SECTION .rodata
+ SECTION RODATA_SECTION_NAME
;
; Float control word initial value:
; all exceptions masked, double-extended-precision, round-to-nearest
--
2.31.1


[PATCH] MdeModulePkg/DxeCore: Fix DebugImageInfoTable size report

Marvin Häuser
 

Separate tracking the used entries from the table's self-reported
size. Removing an entry from the table does not necessarily reduce
the size of the table as defragmentation is not performed.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
index 7bd970115111..cc22e23eb0b3 100644
--- a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
+++ b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
@@ -18,6 +18,8 @@ EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = {

UINTN mMaxTableEntries = 0;

+UINTN mUsedTableEntries = 0;
+
EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL;

#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *))
@@ -178,7 +180,7 @@ CoreNewDebugImageInfoEntry (

Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;

- if (mDebugInfoTableHeader.TableSize < mMaxTableEntries) {
+ if (mUsedTableEntries < mMaxTableEntries) {
//
// We still have empty entires in the Table, find the first empty entry.
//
@@ -237,8 +239,17 @@ CoreNewDebugImageInfoEntry (
// increase the number of EFI_DEBUG_IMAGE_INFO elements.
//
mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
+ mUsedTableEntries++;
Table[Index].NormalImage = NormalImage;
- mDebugInfoTableHeader.TableSize++;
+ //
+ // Only increase the amount of elements in the table if the new entry did
+ // not take the place of a previously removed entry.
+ //
+ if (Index == mDebugInfoTableHeader.TableSize) {
+ mDebugInfoTableHeader.TableSize++;
+ }
+
+ ASSERT (Index < mDebugInfoTableHeader.TableSize);
}
mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS;
}
@@ -274,9 +285,10 @@ CoreRemoveDebugImageInfoEntry (
mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED;
Table[Index].NormalImage = NULL;
//
- // Decrease the number of EFI_DEBUG_IMAGE_INFO elements.
+ // Do not reduce the amount of elements reported to be in the table as
+ // this would only work for the last element without defragmentation.
//
- mDebugInfoTableHeader.TableSize--;
+ mUsedTableEntries--;
//
// Free up the record.
//
--
2.31.1


[PATCH] BaseTools/CommonLib: Fix unaligned API prototypes

Marvin Häuser
 

C prohibits not only dereferencing but also casting to unaligned
pointers. Thus, the current set of unaligned APIs cannot be called
safely. Update their prototypes to take VOID * pointers, which must
be able to represent any valid pointer.

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
BaseTools/Source/C/Common/CommonLib.c | 16 ++++++++--------
BaseTools/Source/C/Common/CommonLib.h | 8 ++++----
2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/BaseTools/Source/C/Common/CommonLib.c b/BaseTools/Source/C/Common/CommonLib.c
index 7fb4ab764fcd..f1223fb2ae0a 100644
--- a/BaseTools/Source/C/Common/CommonLib.c
+++ b/BaseTools/Source/C/Common/CommonLib.c
@@ -1154,23 +1154,23 @@ StrSize (

UINT64
ReadUnaligned64 (
- CONST UINT64 *Buffer
+ CONST VOID *Buffer
)
{
ASSERT (Buffer != NULL);

- return *Buffer;
+ return *(CONST UINT64 *) Buffer;
}

UINT64
WriteUnaligned64 (
- UINT64 *Buffer,
+ VOID *Buffer,
UINT64 Value
)
{
ASSERT (Buffer != NULL);

- return *Buffer = Value;
+ return *(UINT64 *) Buffer = Value;
}


@@ -2018,23 +2018,23 @@ AllocatePool (

UINT16
WriteUnaligned16 (
- UINT16 *Buffer,
+ VOID *Buffer,
UINT16 Value
)
{
ASSERT (Buffer != NULL);

- return *Buffer = Value;
+ return *(UINT16 *) Buffer = Value;
}

UINT16
ReadUnaligned16 (
- CONST UINT16 *Buffer
+ CONST VOID *Buffer
)
{
ASSERT (Buffer != NULL);

- return *Buffer;
+ return *(CONST UINT16 *) Buffer;
}
/**
Return whether the integer string is a hex string.
diff --git a/BaseTools/Source/C/Common/CommonLib.h b/BaseTools/Source/C/Common/CommonLib.h
index 0f05d88db206..67c42a91765d 100644
--- a/BaseTools/Source/C/Common/CommonLib.h
+++ b/BaseTools/Source/C/Common/CommonLib.h
@@ -238,13 +238,13 @@ CopyGuid (

UINT64
WriteUnaligned64 (
- UINT64 *Buffer,
+ VOID *Buffer,
UINT64 Value
);

UINT64
ReadUnaligned64 (
- CONST UINT64 *Buffer
+ CONST VOID *Buffer
);

UINTN
@@ -363,13 +363,13 @@ AllocatePool (

UINT16
WriteUnaligned16 (
- UINT16 *Buffer,
+ VOID *Buffer,
UINT16 Value
);

UINT16
ReadUnaligned16 (
- CONST UINT16 *Buffer
+ CONST VOID *Buffer
);

VOID *
--
2.31.1


[PATCH] UefiPayloadPkg/UefiPayloadEntry: Fix memory corruption

Marvin Häuser
 

UefiPayloadEntry's AllocatePool() applies the "sizeof" operator to
HOB index rather than the HOB header structure. This yields 4 Bytes
compared to the 8 Bytes the structure header requires. Fix the call
to allocate the required space instead.

Cc: Guo Dong <guo.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c b/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c
index 1204573b3e09..f3494969e5ac 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c
+++ b/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c
@@ -163,7 +163,7 @@ AllocatePool (
return NULL;
}

- Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_TYPE_MEMORY_POOL) + AllocationSize));
+ Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + AllocationSize));
return (VOID *)(Hob + 1);
}

--
2.31.1


[PATCH] StandaloneMmPkg: Support CLANGPDB X64 builds

Marvin Häuser
 

Currently, the flag "-fpie" is passed for all builds with a GCC
family toolchain, including CLANGPDB. CLANGPDB however does not
support this flag as it generates PE/COFF files directly.

As the flag is mostly required for AArch64-specific self-relocation,
drop it for X64 builds and document the limitation to enable X64
CLANGPDB builds of StandaloneMmCore.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
StandaloneMmPkg/Core/StandaloneMmCore.inf | 9 +++++++--
StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf | 7 ++++++-
2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.inf b/StandaloneMmPkg/Core/StandaloneMmCore.inf
index 87bf6e9440a7..e3349fff29cc 100644
--- a/StandaloneMmPkg/Core/StandaloneMmCore.inf
+++ b/StandaloneMmPkg/Core/StandaloneMmCore.inf
@@ -76,6 +76,11 @@ [Guids]
gEfiEventExitBootServicesGuid
gEfiEventReadyToBootGuid

+#
+# This configuration fails for CLANGPDB, which does not support PIE in the GCC
+# sense. Such however is required for AArch64 StandaloneMmCore self-relocation,
+# and thus the CLANGPDB toolchain is unsupported for AArch64 for this module.
+#
[BuildOptions]
- GCC:*_*_*_CC_FLAGS = -fpie
- GCC:*_*_*_DLINK_FLAGS = -Wl,-z,text,-Bsymbolic,-pie
+ GCC:*_*_AARCH64_CC_FLAGS = -fpie
+ GCC:*_*_AARCH64_DLINK_FLAGS = -Wl,-z,text,-Bsymbolic,-pie
diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
index 4fa426f58ef4..dcbb082d4ab8 100644
--- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
+++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
@@ -54,5 +54,10 @@ [Guids]
[FeaturePcd.AARCH64]
gArmTokenSpaceGuid.PcdFfaEnable

+#
+# This configuration fails for CLANGPDB, which does not support PIE in the GCC
+# sense. Such however is required for AArch64 StandaloneMmCore self-relocation,
+# and thus the CLANGPDB toolchain is unsupported for AArch64 for this module.
+#
[BuildOptions]
- GCC:*_*_*_CC_FLAGS = -fpie
+ GCC:*_*_AARCH64_CC_FLAGS = -fpie
--
2.31.1


[PATCH] StandaloneMmPkg/StandaloneMmCore: Drop unused fixed address feature

Marvin Häuser
 

StandaloneMmCore does not support fixed load addresses for modules.
Remove the unreferenced functions that are used in other dispatchers
to implement this feature.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
StandaloneMmPkg/Core/Dispatcher.c | 167 --------------------
1 file changed, 167 deletions(-)

diff --git a/StandaloneMmPkg/Core/Dispatcher.c b/StandaloneMmPkg/Core/Dispatcher.c
index 7e4bf5e94025..d5631f47be68 100644
--- a/StandaloneMmPkg/Core/Dispatcher.c
+++ b/StandaloneMmPkg/Core/Dispatcher.c
@@ -109,173 +109,6 @@ BOOLEAN gRequestDispatch = FALSE;
//
GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mMmCodeMemoryRangeUsageBitMap=NULL;

-/**
- To check memory usage bit map array to figure out if the memory range in which the image will be loaded
- is available or not. If memory range is avaliable, the function will mark the corresponding bits to 1
- which indicates the memory range is used. The function is only invoked when load modules at fixed address
- feature is enabled.
-
- @param ImageBase The base addres the image will be loaded at.
- @param ImageSize The size of the image
-
- @retval EFI_SUCCESS The memory range the image will be loaded in is available
- @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
-**/
-EFI_STATUS
-CheckAndMarkFixLoadingMemoryUsageBitMap (
- IN EFI_PHYSICAL_ADDRESS ImageBase,
- IN UINTN ImageSize
- )
-{
- UINT32 MmCodePageNumber;
- UINT64 MmCodeSize;
- EFI_PHYSICAL_ADDRESS MmCodeBase;
- UINTN BaseOffsetPageNumber;
- UINTN TopOffsetPageNumber;
- UINTN Index;
-
- //
- // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressMmCodePageNumber
- //
- MmCodePageNumber = 0;
- MmCodeSize = EFI_PAGES_TO_SIZE (MmCodePageNumber);
- MmCodeBase = gLoadModuleAtFixAddressMmramBase;
-
- //
- // If the memory usage bit map is not initialized, do it. Every bit in the array
- // indicate the status of the corresponding memory page, available or not
- //
- if (mMmCodeMemoryRangeUsageBitMap == NULL) {
- mMmCodeMemoryRangeUsageBitMap = AllocateZeroPool (((MmCodePageNumber / 64) + 1) * sizeof (UINT64));
- }
-
- //
- // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
- //
- if (mMmCodeMemoryRangeUsageBitMap == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // see if the memory range for loading the image is in the MM code range.
- //
- if (MmCodeBase + MmCodeSize < ImageBase + ImageSize || MmCodeBase > ImageBase) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Test if the memory is available or not.
- //
- BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - MmCodeBase));
- TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - MmCodeBase));
- for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
- if ((mMmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64 (1, (Index % 64))) != 0) {
- //
- // This page is already used.
- //
- return EFI_NOT_FOUND;
- }
- }
-
- //
- // Being here means the memory range is available. So mark the bits for the memory range
- //
- for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
- mMmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64 (1, (Index % 64));
- }
- return EFI_SUCCESS;
-}
-
-/**
- Get the fixed loading address from image header assigned by build tool. This function only be called
- when Loading module at Fixed address feature enabled.
-
- @param ImageContext Pointer to the image context structure that describes the PE/COFF
- image that needs to be examined by this function.
- @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
- @retval EFI_NOT_FOUND The image has no assigned fixed loadding address.
-
-**/
-EFI_STATUS
-GetPeCoffImageFixLoadingAssignedAddress(
- IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
- )
-{
- UINTN SectionHeaderOffset;
- EFI_STATUS Status;
- EFI_IMAGE_SECTION_HEADER SectionHeader;
- EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
- EFI_PHYSICAL_ADDRESS FixLoadingAddress;
- UINT16 Index;
- UINTN Size;
- UINT16 NumberOfSections;
- UINT64 ValueInSectionHeader;
-
- FixLoadingAddress = 0;
- Status = EFI_NOT_FOUND;
-
- //
- // Get PeHeader pointer
- //
- ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
- SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) +
- ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;
- NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
-
- //
- // Get base address from the first section header that doesn't point to code section.
- //
- for (Index = 0; Index < NumberOfSections; Index++) {
- //
- // Read section header from file
- //
- Size = sizeof (EFI_IMAGE_SECTION_HEADER);
- Status = ImageContext->ImageRead (
- ImageContext->Handle,
- SectionHeaderOffset,
- &Size,
- &SectionHeader
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = EFI_NOT_FOUND;
-
- if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
- //
- // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields
- // in the first section header that doesn't point to code section in image header. So there
- // is an assumption that when the feature is enabled, if a module with a loading address
- // assigned by tools, the PointerToRelocations & PointerToLineNumbers fields should not be
- // Zero, or else, these 2 fields should be set to Zero
- //
- ValueInSectionHeader = ReadUnaligned64 ((UINT64*)&SectionHeader.PointerToRelocations);
- if (ValueInSectionHeader != 0) {
- //
- // Found first section header that doesn't point to code section in which build tool saves the
- // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
- //
- FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressMmramBase + (INT64)ValueInSectionHeader);
- //
- // Check if the memory range is available.
- //
- Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
- if (!EFI_ERROR(Status)) {
- //
- // The assigned address is valid. Return the specified loading address
- //
- ImageContext->ImageAddress = FixLoadingAddress;
- }
- }
- break;
- }
- SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
- }
- DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n",
- FixLoadingAddress, Status));
- return Status;
-}
/**
Loads an EFI image into SMRAM.

--
2.31.1


[PATCH] StandaloneMmPkg/StandaloneMmCore: Drop code for traditional drivers

Marvin Häuser
 

StandaloneMmCore has code paths in place to support traditional MM
drivers based on the availability of mEfiSystemTable. This variable
is not populated anywhere however, rendering said paths unreachable.
Remove the unreachable support code.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
Cc: Vitaly Cheptsov <vit9696@protonmail.com>
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
---
StandaloneMmPkg/Core/Dependency.c | 6 ---
StandaloneMmPkg/Core/Dispatcher.c | 51 +-------------------
StandaloneMmPkg/Core/StandaloneMmCore.c | 1 -
StandaloneMmPkg/Core/StandaloneMmCore.h | 1 -
4 files changed, 2 insertions(+), 57 deletions(-)

diff --git a/StandaloneMmPkg/Core/Dependency.c b/StandaloneMmPkg/Core/Dependency.c
index eb4baa4086f0..3ae0201eb647 100644
--- a/StandaloneMmPkg/Core/Dependency.c
+++ b/StandaloneMmPkg/Core/Dependency.c
@@ -242,12 +242,6 @@ MmIsSchedulable (
CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID));

Status = MmLocateProtocol (&DriverGuid, NULL, &Interface);
- if (EFI_ERROR (Status) && (mEfiSystemTable != NULL)) {
- //
- // For MM Driver, it may depend on uefi protocols
- //
- Status = mEfiSystemTable->BootServices->LocateProtocol (&DriverGuid, NULL, &Interface);
- }

if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) = FALSE\n", &DriverGuid));
diff --git a/StandaloneMmPkg/Core/Dispatcher.c b/StandaloneMmPkg/Core/Dispatcher.c
index 7e4bf5e94025..76d33f81fef1 100644
--- a/StandaloneMmPkg/Core/Dispatcher.c
+++ b/StandaloneMmPkg/Core/Dispatcher.c
@@ -364,45 +364,6 @@ MmLoadImage (
DriverEntry->ImageBuffer = DstBuffer;
DriverEntry->NumberOfPage = PageCount;

- if (mEfiSystemTable != NULL) {
- Status = mEfiSystemTable->BootServices->AllocatePool (
- EfiBootServicesData,
- sizeof (EFI_LOADED_IMAGE_PROTOCOL),
- (VOID **)&DriverEntry->LoadedImage
- );
- if (EFI_ERROR (Status)) {
- MmFreePages (DstBuffer, PageCount);
- return Status;
- }
-
- ZeroMem (DriverEntry->LoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));
- //
- // Fill in the remaining fields of the Loaded Image Protocol instance.
- // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.
- //
- DriverEntry->LoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
- DriverEntry->LoadedImage->ParentHandle = NULL;
- DriverEntry->LoadedImage->SystemTable = mEfiSystemTable;
- DriverEntry->LoadedImage->DeviceHandle = NULL;
- DriverEntry->LoadedImage->FilePath = NULL;
-
- DriverEntry->LoadedImage->ImageBase = (VOID *)(UINTN)DriverEntry->ImageBuffer;
- DriverEntry->LoadedImage->ImageSize = ImageContext.ImageSize;
- DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode;
- DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData;
-
- //
- // Create a new image handle in the UEFI handle database for the MM Driver
- //
- DriverEntry->ImageHandle = NULL;
- Status = mEfiSystemTable->BootServices->InstallMultipleProtocolInterfaces (
- &DriverEntry->ImageHandle,
- &gEfiLoadedImageProtocolGuid,
- DriverEntry->LoadedImage,
- NULL
- );
- }
-
//
// Print the load address and the PDB file name if it is available
//
@@ -637,16 +598,8 @@ MmDispatcher (
//
// For each MM driver, pass NULL as ImageHandle
//
- if (mEfiSystemTable == NULL) {
- DEBUG ((DEBUG_INFO, "StartImage - 0x%x (Standalone Mode)\n", DriverEntry->ImageEntryPoint));
- Status = ((MM_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint) (DriverEntry->ImageHandle, &gMmCoreMmst);
- } else {
- DEBUG ((DEBUG_INFO, "StartImage - 0x%x (Tradition Mode)\n", DriverEntry->ImageEntryPoint));
- Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint) (
- DriverEntry->ImageHandle,
- mEfiSystemTable
- );
- }
+ DEBUG ((DEBUG_INFO, "StartImage - 0x%x (Standalone Mode)\n", DriverEntry->ImageEntryPoint));
+ Status = ((MM_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint) (DriverEntry->ImageHandle, &gMmCoreMmst);
if (EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "StartImage Status - %r\n", Status));
MmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.c b/StandaloneMmPkg/Core/StandaloneMmCore.c
index fbb0ec75e557..45976f203dd9 100644
--- a/StandaloneMmPkg/Core/StandaloneMmCore.c
+++ b/StandaloneMmPkg/Core/StandaloneMmCore.c
@@ -92,7 +92,6 @@ MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] = {
{ NULL, NULL, NULL, FALSE },
};

-EFI_SYSTEM_TABLE *mEfiSystemTable;
UINTN mMmramRangeCount;
EFI_MMRAM_DESCRIPTOR *mMmramRanges;

diff --git a/StandaloneMmPkg/Core/StandaloneMmCore.h b/StandaloneMmPkg/Core/StandaloneMmCore.h
index 2a89edd0fc46..f6b3cc861e39 100644
--- a/StandaloneMmPkg/Core/StandaloneMmCore.h
+++ b/StandaloneMmPkg/Core/StandaloneMmCore.h
@@ -848,6 +848,5 @@ DumpMmramInfo (

extern UINTN mMmramRangeCount;
extern EFI_MMRAM_DESCRIPTOR *mMmramRanges;
-extern EFI_SYSTEM_TABLE *mEfiSystemTable;

#endif
--
2.31.1

5241 - 5260 of 84076