[TGL] Invalidate bad DSO region

This patch invalidates the DSO region with a marker after
a DSO hang (caused by corrupted DSO) is detected (by WDT timeout).
With the marker, stage1b can know the DSO tuning should be skipped.

The bad DSO mark is defined as both Signature and Size in the
TCCT component header are zero.

With this patch, the previous defined WDT scratchpad bit,
WDT_FLAG_TCC_BAD_DSO, is removed.

TEST=Verified on TGL-U RVP

Signed-off-by: Stanley Chang <stanley.chang@intel.com>
This commit is contained in:
Stanley Chang 2021-12-16 12:58:26 +08:00 committed by Maurice Ma
parent c533416ef8
commit d66202f25d
4 changed files with 123 additions and 9 deletions

View File

@ -754,13 +754,17 @@ UpdateContainerComp (
//
ComponentBase = ContainerEntryPtr->Base + ContainerHdr->DataOffset + ComponentEntryPtr->Offset;
// Check Svn for container component
// Current implementation only supports compressed header.
// Exception: empty Signature and Size, which is a mark for previously detected bad region, e.g., TCCT
FlashCompLzHeader = (LOADER_COMPRESSED_HEADER *) (UINTN) ComponentBase;
CapCompLzHeader = (LOADER_COMPRESSED_HEADER *) ((UINTN)ImageHdr + sizeof(EFI_FW_MGMT_CAP_IMAGE_HEADER));
if ((IS_COMPRESSED (FlashCompLzHeader) == FALSE) || (IS_COMPRESSED (CapCompLzHeader) == FALSE)) {
if (((IS_COMPRESSED (FlashCompLzHeader) == FALSE) &&
((FlashCompLzHeader->Signature != 0) || (FlashCompLzHeader->Size != 0))) ||
(IS_COMPRESSED (CapCompLzHeader) == FALSE)) {
return EFI_UNSUPPORTED;
}
// Check Svn for container component
if (CapCompLzHeader->Svn < FlashCompLzHeader->Svn) {
DEBUG((DEBUG_INFO, "Container Component svn did not met!"));
return EFI_UNSUPPORTED;

View File

@ -58,6 +58,117 @@ GetBoardId (
OUT UINT8 *BoardId
);
/**
Check if the BAD DSO mark exists or not
BAD DSO mark is defined as
LOADER_COMPRESSED_HEADER of the component in flash
Its Signature' and 'Size' fields are 0 (zero).
Other fields are subject to change
@retval TRUE DSO was marked as BAD DSO
@retval FALSE No BAD DSO mark found
*/
BOOLEAN
EFIAPI
IsMarkedBadDso (
VOID
)
{
EFI_STATUS Status;
UINT32 Length;
LOADER_COMPRESSED_HEADER *Hdr;
LOADER_COMPRESSED_HEADER BadDsoMark = {0};
DEBUG ((DEBUG_INFO, "Check BAD DSO mark\n"));
Status = LocateComponent (SIGNATURE_32 ('I', 'P', 'F', 'W'),
SIGNATURE_32 ('T', 'C', 'C', 'T'),
(VOID *)&Hdr, &Length);
if (EFI_ERROR (Status) || (Length < sizeof(LOADER_COMPRESSED_HEADER))) {
return FALSE;
}
if ((Hdr->Signature == BadDsoMark.Signature) && (Hdr->Size == BadDsoMark.Size)) {
DEBUG ((DEBUG_INFO, "BAD DSO(TCCT) detected!\n"));
return TRUE;
} else {
return FALSE;
}
}
/**
Invalidate BAD DSO
@retval EFI_SUCCESS
@retval EFI_NOT_FOUND Unable to find IPFW/TCCT
@retval EFI_OUT_OF_RESOURCES Bios region is too small
@retval Others Errors during SPI operations
*/
EFI_STATUS
EFIAPI
InvalidateBadDso (
VOID
)
{
EFI_STATUS Status;
UINT32 Address;
UINT32 Length;
UINT32 BaseAddress;
UINT32 RegionSize;
CONTAINER_ENTRY *ContainerEntry;
COMPONENT_ENTRY *CompEntry;
CONTAINER_HDR *ContainerHdr;
// BAD DSO mark: The 'Signature' and 'Size' fields are zero(0)
// Other fields are subject to change
LOADER_COMPRESSED_HEADER BadDsoMark = {0};
DEBUG ((DEBUG_INFO, "Invalidate BAD DSO region\n"));
Status = LocateComponentEntry (SIGNATURE_32 ('I', 'P', 'F', 'W'),
SIGNATURE_32 ('T', 'C', 'C', 'T'),
&ContainerEntry, &CompEntry);
if (EFI_ERROR (Status) || (ContainerEntry == NULL) || (CompEntry == NULL)) {
return EFI_NOT_FOUND;
}
/* a region should have 4KB as min erase size */
Length = SIZE_4KB;
if (CompEntry->Size < Length) {
return EFI_OUT_OF_RESOURCES;
}
ContainerHdr = (CONTAINER_HDR *)(UINTN)ContainerEntry->HeaderCache;
Address = ContainerEntry->Base + ContainerHdr->DataOffset + CompEntry->Offset;
/* Svn is kept for anti-rollback control */
BadDsoMark.Svn = ((LOADER_COMPRESSED_HEADER *)(UINTN)Address)->Svn;
Status = SpiGetRegionAddress (FlashRegionBios, &BaseAddress, &RegionSize);
if (EFI_ERROR (Status)) {
return Status;
}
BaseAddress = ((UINT32)(~RegionSize) + 1);
Address -= BaseAddress;
if ((Address + Length) > RegionSize) {
return EFI_OUT_OF_RESOURCES;
}
Status = SpiFlashErase (FlashRegionBios, Address, Length);
if (!EFI_ERROR(Status)) {
Status = SpiFlashWrite (FlashRegionBios, Address, sizeof(BadDsoMark), (VOID *)&BadDsoMark);
if (!EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "Mark BAD DSO(TCCT) successfully\n"));
}
}
return Status;
}
/**
Update FSP-M UPD config data for TCC mode and tuning
@ -108,12 +219,14 @@ TccModePreMemConfig (
DEBUG ((DEBUG_INFO, "S0ix is turned off when TCC is enabled\n"));
}
if (IsWdtFlagsSet(WDT_FLAG_TCC_BAD_DSO) ||
(IsWdtFlagsSet(WDT_FLAG_TCC_DSO_IN_PROGRESS) && IsWdtTimeout())) {
if (IsMarkedBadDso ()) {
DEBUG ((DEBUG_ERROR, "Incorrect TCC tuning parameters. Platform rebooted with default values.\n"));
FspmUpd->FspmConfig.TccStreamCfgStatusPreMem = 1;
} else if (IsWdtFlagsSet(WDT_FLAG_TCC_DSO_IN_PROGRESS) && IsWdtTimeout()) {
DEBUG ((DEBUG_ERROR, "Incorrect TCC tuning parameters. Platform rebooted with default values.\n"));
WdtClearScratchpad (WDT_FLAG_TCC_DSO_IN_PROGRESS);
WdtSetScratchpad (WDT_FLAG_TCC_BAD_DSO);
FspmUpd->FspmConfig.TccStreamCfgStatusPreMem = 1;
InvalidateBadDso ();
} else if (TccCfgData->TccTuning != 0) {
// Setup Watch dog timer
WdtReloadAndStart (WDT_TIMEOUT_TCC_DSO, WDT_FLAG_TCC_DSO_IN_PROGRESS);

View File

@ -1024,9 +1024,6 @@ BoardInit (
case ReadyToBoot:
if ((GetBootMode() != BOOT_ON_FLASH_UPDATE) && (GetPayloadId() == 0)) {
ProgramSecuritySetting ();
} else if (GetBootMode() == BOOT_ON_FLASH_UPDATE) {
/* clear bad DSO mark (if have), so next boot is a fresh restart */
WdtClearScratchpad (WDT_FLAG_TCC_BAD_DSO);
}
break;
@ -3026,3 +3023,4 @@ PlatformUpdateAcpiGnvs (
PlatformNvs->Rtd3Support = mTccRtd3Support;
}
}

View File

@ -10,7 +10,6 @@
#define WDT_TIMEOUT_TCC_DSO 200 // 200 seconds
#define WDT_FLAG_TCC_DSO_IN_PROGRESS BIT17
#define WDT_FLAG_TCC_BAD_DSO BIT18
/**