mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Improve microcode header detection, parse DevExp1 region as ME region
This commit is contained in:
parent
90ff19692d
commit
95c838181f
@ -630,6 +630,8 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
||||
result = parsePdrRegion(region.data, region.offset, index, regionIndex);
|
||||
break;
|
||||
case Subtypes::DevExp1Region:
|
||||
result = parseDevExp1Region(region.data, region.offset, index, regionIndex);
|
||||
break;
|
||||
case Subtypes::Bios2Region:
|
||||
case Subtypes::MicrocodeRegion:
|
||||
case Subtypes::EcRegion:
|
||||
@ -779,6 +781,33 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseDevExp1Region(const UByteArray & devExp1, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
// Check sanity
|
||||
if (devExp1.isEmpty())
|
||||
return U_EMPTY_REGION;
|
||||
|
||||
// Get info
|
||||
UString name("DevExp1 region");
|
||||
UString info = usprintf("Full size: %Xh (%u)", devExp1.size(), devExp1.size());
|
||||
|
||||
bool emptyRegion = false;
|
||||
// Check for empty region
|
||||
if (devExp1.size() == devExp1.count('\xFF') || devExp1.size() == devExp1.count('\x00')) {
|
||||
// Further parsing not needed
|
||||
emptyRegion = true;
|
||||
info += ("\nState: empty");
|
||||
}
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(localOffset, Types::Region, Subtypes::DevExp1Region, name, UString(), info, UByteArray(), devExp1, UByteArray(), Fixed, parent);
|
||||
|
||||
if (!emptyRegion) {
|
||||
meParser->parseMeRegionBody(index);
|
||||
}
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
// Check sanity
|
||||
@ -1189,6 +1218,75 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN FfsParser::microcodeHeaderValid(const INTEL_MICROCODE_HEADER* ucodeHeader)
|
||||
{
|
||||
// Check main reserved bytes to be zero
|
||||
bool reservedBytesValid = true;
|
||||
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++) {
|
||||
if (ucodeHeader->Reserved[i] != 0x00) {
|
||||
reservedBytesValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!reservedBytesValid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check CpuFlags reserved bytes to be zero
|
||||
for (UINT32 i = 0; i < sizeof(ucodeHeader->CpuFlagsReserved); i++) {
|
||||
if (ucodeHeader->CpuFlagsReserved[i] != 0x00) {
|
||||
reservedBytesValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!reservedBytesValid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check data size to be multiple of 4
|
||||
if (ucodeHeader->DataSize % 4 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check TotalSize to be greater then DataSize and multiple of 1024
|
||||
if (ucodeHeader->TotalSize <= ucodeHeader->DataSize || ucodeHeader->TotalSize % 1024 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check date to be sane
|
||||
// Check day to be in 0x01-0x09, 0x10-0x19, 0x20-0x29, 0x30-0x31
|
||||
if (ucodeHeader->DateDay < 0x01 ||
|
||||
(ucodeHeader->DateDay > 0x09 && ucodeHeader->DateDay < 0x10) ||
|
||||
(ucodeHeader->DateDay > 0x19 && ucodeHeader->DateDay < 0x20) ||
|
||||
(ucodeHeader->DateDay > 0x29 && ucodeHeader->DateDay < 0x30) ||
|
||||
ucodeHeader->DateDay > 0x31) {
|
||||
return FALSE;
|
||||
}
|
||||
// Check month to be in 0x01-0x09, 0x10-0x12
|
||||
if (ucodeHeader->DateMonth < 0x01 ||
|
||||
(ucodeHeader->DateMonth > 0x09 && ucodeHeader->DateMonth < 0x10) ||
|
||||
ucodeHeader->DateMonth > 0x12) {
|
||||
return FALSE;
|
||||
}
|
||||
// Check year to be in 0x1990-0x1999, 0x2000-0x2009, 0x2010-0x2019, 0x2020-0x2029, 0x2030-0x2030, 0x2040-0x2049
|
||||
if (ucodeHeader->DateYear < 0x1990 ||
|
||||
(ucodeHeader->DateYear > 0x1999 && ucodeHeader->DateYear < 0x2000) ||
|
||||
(ucodeHeader->DateYear > 0x2009 && ucodeHeader->DateYear < 0x2010) ||
|
||||
(ucodeHeader->DateYear > 0x2019 && ucodeHeader->DateYear < 0x2020) ||
|
||||
(ucodeHeader->DateYear > 0x2029 && ucodeHeader->DateYear < 0x2030) ||
|
||||
(ucodeHeader->DateYear > 0x2039 && ucodeHeader->DateYear < 0x2040) ||
|
||||
ucodeHeader->DateYear > 0x2049) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check loader revision to be sane
|
||||
if (ucodeHeader->LoaderRevision > INTEL_MICROCODE_MAX_LOADER_REVISION) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 localOffset, UINT8 & nextItemType, UINT32 & nextItemOffset, UINT32 & nextItemSize, UINT32 & nextItemAlternativeSize)
|
||||
{
|
||||
UByteArray data = model->body(index);
|
||||
@ -1203,29 +1301,14 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
|
||||
const UINT32 restSize = dataSize - offset;
|
||||
if (readUnaligned(currentPos) == INTEL_MICROCODE_HEADER_VERSION_1) {// Intel microcode
|
||||
// Check data size
|
||||
if (restSize < sizeof(INTEL_MICROCODE_HEADER))
|
||||
continue;
|
||||
|
||||
// Check microcode size
|
||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
||||
|
||||
// Check reserved bytes
|
||||
bool reservedBytesValid = true;
|
||||
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
|
||||
if (ucodeHeader->Reserved[i] != 0x00) {
|
||||
reservedBytesValid = false;
|
||||
break;
|
||||
}
|
||||
if (!reservedBytesValid)
|
||||
continue;
|
||||
|
||||
// Data size is multiple of 4
|
||||
if (ucodeHeader->DataSize % 4 != 0) {
|
||||
if (restSize < sizeof(INTEL_MICROCODE_HEADER)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TotalSize is greater then DataSize and is multiple of 1024
|
||||
if (ucodeHeader->TotalSize <= ucodeHeader->DataSize || ucodeHeader->TotalSize % 1024 != 0) {
|
||||
// Check microcode header candidate
|
||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
||||
|
||||
if (FALSE == microcodeHeaderValid(ucodeHeader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3742,47 +3825,27 @@ void FfsParser::findFitRecursive(const UModelIndex & index, UModelIndex & found,
|
||||
USTATUS FfsParser::parseFitEntryMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
|
||||
{
|
||||
U_UNUSED_PARAMETER(parent);
|
||||
if ((UINT32)microcode.size() < localOffset + sizeof(INTEL_MICROCODE_HEADER)) {
|
||||
if ((UINT32)microcode.size() - localOffset < sizeof(INTEL_MICROCODE_HEADER)) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
const INTEL_MICROCODE_HEADER* header = (const INTEL_MICROCODE_HEADER*)(microcode.constData() + localOffset);
|
||||
if (header->Version != INTEL_MICROCODE_HEADER_VERSION_1) {
|
||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)(microcode.constData() + localOffset);
|
||||
if (!microcodeHeaderValid(ucodeHeader)) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
bool reservedBytesValid = true;
|
||||
for (UINT8 i = 0; i < sizeof(header->Reserved); i++)
|
||||
if (header->Reserved[i] != 0x00) {
|
||||
reservedBytesValid = false;
|
||||
break;
|
||||
}
|
||||
if (!reservedBytesValid) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
if (header->DataSize % 4 != 0) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
if (header->TotalSize <= header->DataSize || header->TotalSize % 1024 != 0) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
UINT32 mcSize = header->TotalSize;
|
||||
if ((UINT32)microcode.size() < localOffset + mcSize) {
|
||||
if ((UINT32)microcode.size() - localOffset < ucodeHeader->TotalSize) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
// Valid microcode found
|
||||
info = usprintf("CpuSignature: %08Xh, Revision: %08Xh, Date: %02X.%02X.%04X",
|
||||
header->CpuSignature,
|
||||
header->Revision,
|
||||
header->DateDay,
|
||||
header->DateMonth,
|
||||
header->DateYear
|
||||
);
|
||||
realSize = mcSize;
|
||||
ucodeHeader->CpuSignature,
|
||||
ucodeHeader->Revision,
|
||||
ucodeHeader->DateDay,
|
||||
ucodeHeader->DateMonth,
|
||||
ucodeHeader->DateYear);
|
||||
realSize = ucodeHeader->TotalSize;
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
@ -4214,30 +4277,7 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const
|
||||
|
||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)microcode.constData();
|
||||
|
||||
// Header version is 1
|
||||
if (ucodeHeader->Version != INTEL_MICROCODE_HEADER_VERSION_1) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
// Reserved bytes are all zeroes
|
||||
bool reservedBytesValid = true;
|
||||
for (UINT8 i = 0; i < sizeof(ucodeHeader->Reserved); i++) {
|
||||
if (ucodeHeader->Reserved[i] != 0x00) {
|
||||
reservedBytesValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!reservedBytesValid) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
// Data size is multiple of 4
|
||||
if (ucodeHeader->DataSize % 4 != 0) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
// TotalSize is greater then DataSize and is multiple of 1024
|
||||
if (ucodeHeader->TotalSize <= ucodeHeader->DataSize || ucodeHeader->TotalSize % 1024 != 0) {
|
||||
if (!microcodeHeaderValid(ucodeHeader)) {
|
||||
return U_INVALID_MICROCODE;
|
||||
}
|
||||
|
||||
@ -4301,8 +4341,7 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const
|
||||
tempUcodeHeader->CpuSignature = entry->CpuSignature;
|
||||
UINT32 entryCalculated = calculateChecksum32((const UINT32*)tempMicrocode.constData(), sizeof(INTEL_MICROCODE_HEADER) + dataSize);
|
||||
|
||||
|
||||
extendedHeaderInfo += usprintf("\nCPU signature #%u: %08Xh\nCPU flags #%u: %08Xh\nChecksum #%u: %08Xh, ",
|
||||
extendedHeaderInfo += usprintf("\nCPU signature #%u: %08Xh\nCPU flags #%u: %02Xh\nChecksum #%u: %08Xh, ",
|
||||
i + 1, entry->CpuSignature,
|
||||
i + 1, entry->CpuFlags,
|
||||
i + 1, entry->Checksum)
|
||||
@ -4314,7 +4353,7 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const
|
||||
// Add info
|
||||
UString name("Intel microcode");
|
||||
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nTail size: %Xh (%u)\n"
|
||||
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh\nChecksum: %08Xh, ",
|
||||
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nLoader revision: %08Xh\nCPU flags: %02Xh\nChecksum: %08Xh, ",
|
||||
dataSize, dataSize,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
|
@ -115,6 +115,7 @@ private:
|
||||
USTATUS parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseDevExp1Region(const UByteArray & devExp1, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
USTATUS parsePadFileBody(const UModelIndex & index);
|
||||
@ -142,6 +143,9 @@ private:
|
||||
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
|
||||
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
|
||||
|
||||
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
BOOLEAN microcodeHeaderValid(const INTEL_MICROCODE_HEADER* ucodeHeader);
|
||||
|
||||
// Second pass
|
||||
USTATUS performSecondPass(const UModelIndex & index);
|
||||
USTATUS addInfoRecursive(const UModelIndex & index);
|
||||
@ -152,7 +156,7 @@ private:
|
||||
USTATUS parseResetVectorData();
|
||||
USTATUS parseFit(const UModelIndex & index);
|
||||
USTATUS parseVendorHashFile(const UByteArray & fileGuid, const UModelIndex & index);
|
||||
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
|
||||
#ifdef U_ENABLE_FIT_PARSING_SUPPORT
|
||||
void findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset);
|
||||
|
@ -71,7 +71,8 @@ typedef struct INTEL_MICROCODE_HEADER_ {
|
||||
// that comprise the microcode update result in 00000000H.
|
||||
|
||||
UINT32 LoaderRevision;
|
||||
UINT32 CpuFlags;
|
||||
UINT8 CpuFlags;
|
||||
UINT8 CpuFlagsReserved[3];
|
||||
UINT32 DataSize; // Specifies the size of the encrypted data in bytes, and must be a multiple of DWORDs.
|
||||
// If this value is 00000000H, then the microcode update encrypted data is 2000 bytes (or 500 DWORDs).
|
||||
|
||||
@ -102,7 +103,8 @@ typedef struct INTEL_MICROCODE_EXTENDED_HEADER_ENTRY_ {
|
||||
// Checksum is correct when the summation of all DWORDs that comprise the created Extended Processor Patch results in 00000000H.
|
||||
} INTEL_MICROCODE_EXTENDED_HEADER_ENTRY;
|
||||
|
||||
#define INTEL_MICROCODE_HEADER_VERSION_1 0x00000001
|
||||
#define INTEL_MICROCODE_HEADER_VERSION_1 0x00000001
|
||||
#define INTEL_MICROCODE_MAX_LOADER_REVISION 0x00000010
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
@ -533,6 +533,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
||||
if (dataSize < sizeof(UINT32))
|
||||
return U_STORES_NOT_FOUND;
|
||||
|
||||
// TODO: add checks for restSize
|
||||
UINT32 offset = storeOffset;
|
||||
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
||||
const UINT32* currentPos = (const UINT32*)(volume.constData() + offset);
|
||||
@ -646,24 +647,10 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
||||
break;
|
||||
}
|
||||
else if (*currentPos == INTEL_MICROCODE_HEADER_VERSION_1) {// Intel microcode
|
||||
// Check reserved bytes
|
||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
||||
bool reservedBytesValid = true;
|
||||
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
|
||||
if (ucodeHeader->Reserved[i] != 0x00) {
|
||||
reservedBytesValid = false;
|
||||
break;
|
||||
}
|
||||
if (!reservedBytesValid)
|
||||
continue;
|
||||
|
||||
// Data size is multiple of 4
|
||||
if (ucodeHeader->DataSize % 4 != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TotalSize is greater then DataSize and is multiple of 1024
|
||||
if (ucodeHeader->TotalSize <= ucodeHeader->DataSize || ucodeHeader->TotalSize % 1024 != 0) {
|
||||
if (FALSE == ffsParser->microcodeHeaderValid(ucodeHeader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user