/** @file Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include /** Allocate Memory for Debug Test Cases. Check if the DebugDataPtr is allocated memory by a debug test case already. If yes, do nothing. Else allocate memory for DebugDataPtr of size DEBUG_DATA. **/ VOID CheckAndAllocateDebugDataMemory ( VOID ) { LOADER_GLOBAL_DATA *LdrGlobal; LdrGlobal = (LOADER_GLOBAL_DATA *)GetLoaderGlobalDataPointer(); if (LdrGlobal->DebugDataPtr == NULL) { LdrGlobal->DebugDataPtr = AllocatePool (sizeof (DEBUG_DATA)); if (LdrGlobal->BootMode != BOOT_ON_S3_RESUME) { ZeroMem (LdrGlobal->DebugDataPtr, sizeof (DEBUG_DATA)); } } // else, DebugData Memory is already // allocated by another test case. } /** Restore the CRC32 values saved and compare. Stage1B will calculate and save the CRC32 for the 1MiB memory ranges within Unreserved Memory Regions. Re-calculate the CRC32 for the same memory ranges and report the un-matched CRC regions. This routine is called right before jumping to S3 WakeUp trampoline. **/ BOOLEAN EFIAPI S3DebugRestoreAndCompareCRC32 ( VOID ) { LOADER_GLOBAL_DATA *LdrGlobal; S3_CRC_DATA *SavedS3CrcTable; UINT32 CrcRegionIdx; UINT32 NewCrcValue; BOOLEAN CrcMatching; CrcMatching = TRUE; LdrGlobal = (LOADER_GLOBAL_DATA *)GetLoaderGlobalDataPointer(); SavedS3CrcTable = ((DEBUG_DATA *)LdrGlobal->DebugDataPtr)->S3CrcTable; DEBUG ((DEBUG_INFO, "Checking for unmatched-CRC Regions ...\n")); for (CrcRegionIdx = 0; SavedS3CrcTable[CrcRegionIdx].RegionSize != 0x00; CrcRegionIdx++) { CalculateCrc32WithType ((UINT8 *)(UINTN) SavedS3CrcTable[CrcRegionIdx].RegionBase, (UINTN) (SavedS3CrcTable[CrcRegionIdx].RegionSize), Crc32TypeCastagnoli, &NewCrcValue); if (NewCrcValue != SavedS3CrcTable[CrcRegionIdx].RegionCrc32Value) { DEBUG ((DEBUG_INFO, "RegBase=0x%08X RegLimit=0x%08X RegSize=0x%08X SavedS3CrcValue=0x%08X NewCrcValue=0x%08X\n", SavedS3CrcTable[CrcRegionIdx].RegionBase, SavedS3CrcTable[CrcRegionIdx].RegionLimit, SavedS3CrcTable[CrcRegionIdx].RegionSize, SavedS3CrcTable[CrcRegionIdx].RegionCrc32Value, NewCrcValue)); CrcMatching = FALSE; } } if (!CrcMatching) { return FALSE; } else { DEBUG ((DEBUG_INFO, "None\n")); return TRUE; } } /** Calculate CRC32 values for 1MiB memory ranges Calculate CRC32 values for 1MiB memory ranges within the UnReserved Memory Regions from MmeoryMap. This gets control only in S3Rseume path. @param S3CrcTable Pointer to the CRC table to be stored for later comparison. @param S3CrcTableSize CRC table size @param MemoryMapEntry Pointer to an UnReserved Memory Region entry from MemoryMap. @param S3CrcRegionIdx Address of the variable used for indexing S3CrcTable. **/ VOID S3DebugCalculateCRC32 ( IN OUT S3_CRC_DATA *S3CrcTable, IN UINT32 S3CrcTableSize, IN MEMORY_MAP_ENTRY *MemoryMapEntry, IN OUT UINT32 *S3CrcRegionIdx ) { UINT32 SubRegionBase; UINT32 SubRegionSize; UINT32 SubRegionCount; UINT32 SubRegionIndex; UINT32 CrcRegionIdx; CrcRegionIdx = *S3CrcRegionIdx; if ( CrcRegionIdx >= DivU64x32 (S3CrcTableSize, sizeof (S3_CRC_DATA)) ) { DEBUG ((DEBUG_INFO, "S3CrcTable to over-flow! Returning\n")); return; } SubRegionBase = (UINT32)MemoryMapEntry->Base; SubRegionSize = S3_DEBUG_CRC32_REGION_SIZE; SubRegionCount = (UINT32) DivU64x32 (MemoryMapEntry->Size + S3_DEBUG_CRC32_REGION_SIZE - 1, S3_DEBUG_CRC32_REGION_SIZE); for (SubRegionIndex = 0; SubRegionIndex < SubRegionCount; SubRegionIndex++) { S3CrcTable[CrcRegionIdx].RegionBase = SubRegionBase; S3CrcTable[CrcRegionIdx].RegionSize = SubRegionSize; if (S3CrcTable[CrcRegionIdx].RegionBase == 0x00000000) { S3CrcTable[CrcRegionIdx].RegionBase = 0x00000001; S3CrcTable[CrcRegionIdx].RegionSize -= 1; } if ( (S3CrcTable[CrcRegionIdx].RegionBase + S3CrcTable[CrcRegionIdx].RegionSize) >= ((UINT32)MemoryMapEntry->Base + (UINT32)MemoryMapEntry->Size) ) { S3CrcTable[CrcRegionIdx].RegionSize = (UINT32)MemoryMapEntry->Base + (UINT32)MemoryMapEntry->Size - S3CrcTable[CrcRegionIdx].RegionBase - 1; } S3CrcTable[CrcRegionIdx].RegionLimit = S3CrcTable[CrcRegionIdx].RegionBase + S3CrcTable[CrcRegionIdx].RegionSize - 1; CalculateCrc32WithType ((UINT8 *)(UINTN)S3CrcTable[CrcRegionIdx].RegionBase, (UINTN) (S3CrcTable[CrcRegionIdx].RegionSize), Crc32TypeCastagnoli, & (S3CrcTable[CrcRegionIdx].RegionCrc32Value)); DEBUG ((DEBUG_INFO, "RegBase=0x%08X RegLimit=0x%08X RegSize=0x%08X CrcValue=0x%08X\n", S3CrcTable[CrcRegionIdx].RegionBase, S3CrcTable[CrcRegionIdx].RegionLimit, S3CrcTable[CrcRegionIdx].RegionSize, S3CrcTable[CrcRegionIdx].RegionCrc32Value )); CrcRegionIdx++; SubRegionBase += SubRegionSize; } *S3CrcRegionIdx = CrcRegionIdx; } /** Calculate and Save the CRC32 values. Stage1B will calculate and save the CRC32 for the 1MiB memory ranges for Unreserved Memory Regions. This gets control only in S3Rseume path. @param[in] LdrHobList Pointer to saved/restored LdrHobList from NormalBoot path. **/ VOID EFIAPI S3DebugSaveCRC32 ( IN VOID *LdrHobList ) { UINT32 S3CrcRegionIdx; VOID *GuidHob; MEMORY_MAP_INFO *MemoryMapInfo; UINT8 MemoryMapIdx; LOADER_GLOBAL_DATA *LdrGlobal; S3_CRC_DATA *S3CrcTable; UINT32 S3CrcTableSize; S3CrcRegionIdx = 0; CheckAndAllocateDebugDataMemory (); LdrGlobal = (LOADER_GLOBAL_DATA *)GetLoaderGlobalDataPointer(); // Allocating predefined amount of memory here due to lack of // Memory Map availablity in Stage1B in Normal Boot. S3CrcTableSize = sizeof (S3_CRC_DATA) * (S3_DEBUG_CRC32_LIMIT / S3_DEBUG_CRC32_REGION_SIZE); S3CrcTable = (S3_CRC_DATA *) AllocatePool (S3CrcTableSize); if (S3CrcTable != NULL) { if (LdrGlobal->BootMode != BOOT_ON_S3_RESUME) { ZeroMem (S3CrcTable, S3CrcTableSize); } else { GuidHob = GetNextGuidHob (&gLoaderMemoryMapInfoGuid, LdrHobList); ASSERT (GuidHob != NULL); MemoryMapInfo = (MEMORY_MAP_INFO *)GET_GUID_HOB_DATA (GuidHob); for (MemoryMapIdx = 0; MemoryMapIdx < MemoryMapInfo->Count; MemoryMapIdx++) { if (MemoryMapInfo->Entry[MemoryMapIdx].Base >= S3_DEBUG_CRC32_LIMIT) { break; } // Calculate CRC32 for this memory region if it is unreserved if (MemoryMapInfo->Entry[MemoryMapIdx].Type == 1) { S3DebugCalculateCRC32 (S3CrcTable, S3CrcTableSize, & (MemoryMapInfo->Entry[MemoryMapIdx]), &S3CrcRegionIdx); } } } ((DEBUG_DATA *)LdrGlobal->DebugDataPtr)->S3CrcTable = S3CrcTable; } } /** For serial debugger, it will show the buffer message line by line to serial console. @param[in] Message the address point of buffer message @param[in] Length message length **/ VOID ShowBuffer ( IN UINT8 *Message, IN UINT32 Length ) { DEBUG_CODE_BEGIN (); UINT32 Index; UINT32 Offset; CHAR16 Buffer[LINE_BUFFER]; Index = 0; Offset = 0; ZeroMem (Buffer, sizeof (Buffer)); while (Length-- > 0) { // // Get the corresponding offset value from the index of buffer message. // Offset = ((Index & 0x0F) > 7) ? (((Index & 0x0F) * 3) + 2) : ((Index & 0x0F) * 3); // // Print "- " at the half of a line increases the readability of debug message. // if ((Index & 0x0F) == 0x08) { UnicodeSPrint (&Buffer [24], 3 * sizeof (CHAR16), L"- "); } // // Collect the data of buffer message. // UnicodeSPrint (&Buffer[Offset], 4 * sizeof (CHAR16), L"%02x ", Message [Index]); // // A line contains 16 bytes of buffer message. If a line is complete, it will be shown through DEBUG macro. // if (Offset == END_OF_LINE_OFFSET) { DEBUG ((DEBUG_INFO, "%02x: %s\n", (Index & 0xF0), Buffer)); } Index++; } // // If a line isn't complete, show the remaining data. // if (Offset != END_OF_LINE_OFFSET) { DEBUG ((DEBUG_INFO, "%02x: %s\n", (Index & 0xF0), Buffer)); } DEBUG_CODE_END (); return; }