Initial ME parser, improved ucode parser, reset vector info

This commit is contained in:
Nikolaj Schlej 2019-07-24 10:30:59 -07:00
parent f386eda430
commit 2e7aa8133a
21 changed files with 1867 additions and 166 deletions

View file

@ -711,10 +711,6 @@ Decode (
UINT32 DataIdx;
UINT16 CharC;
BytesRemain = (UINT16)(-1);
DataIdx = 0;
for (;;) {
//
// Get one code from mBitBuf

View file

@ -68,6 +68,19 @@ typedef size_t USTATUS;
#define U_INVALID_BG_BOOT_POLICY 46
#define U_INVALID_TXT_CONF 47
#define U_ELEMENTS_NOT_FOUND 48
#define U_PEI_CORE_ENTRY_POINT_NOT_FOUND 49
#define U_INVALID_STORE_SIZE 50
#define U_UNKNOWN_COMPRESSION_ALGORITHM 51
#define U_NOTHING_TO_PATCH 52
#define U_UNKNOWN_PATCH_TYPE 53
#define U_PATCH_OFFSET_OUT_OF_BOUNDS 54
#define U_INVALID_SYMBOL 55
#define U_INVALID_MANIFEST 251
#define U_UNKNOWN_MANIFEST_HEADER_VERSION 252
#define U_INVALID_ME_PARTITION_TABLE 253
#define U_INVALID_ME_PARTITION 254
#define U_NOT_IMPLEMENTED 0xFF
// EDK2 porting definitions

View file

@ -39,16 +39,16 @@ const UINT8 ffsAlignment2Table[] =
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
{
ffsSize[2] = (UINT8)((size) >> 16);
ffsSize[1] = (UINT8)((size) >> 8);
ffsSize[2] = (UINT8)((size) >> 16U);
ffsSize[1] = (UINT8)((size) >> 8U);
ffsSize[0] = (UINT8)((size));
}
UINT32 uint24ToUint32(const UINT8* ffsSize)
{
return (UINT32) ffsSize[0]
+ ((UINT32) ffsSize[1] << 8U)
+ ((UINT32) ffsSize[2] << 16U);
+ ((UINT32) ffsSize[1] << 8U)
+ ((UINT32) ffsSize[2] << 16U);
}
UString guidToUString(const EFI_GUID & guid, bool convertToString)
@ -84,17 +84,17 @@ bool ustringToGuid(const UString & str, EFI_GUID & guid)
if (err == 0)
return false;
guid.Data1 = p0;
guid.Data2 = p1;
guid.Data3 = p2;
guid.Data4[0] = p3;
guid.Data4[1] = p4;
guid.Data4[2] = p5;
guid.Data4[3] = p6;
guid.Data4[4] = p7;
guid.Data4[5] = p8;
guid.Data4[6] = p9;
guid.Data4[7] = p10;
guid.Data1 = (UINT32)p0;
guid.Data2 = (UINT16)p1;
guid.Data3 = (UINT16)p2;
guid.Data4[0] = (UINT8)p3;
guid.Data4[1] = (UINT8)p4;
guid.Data4[2] = (UINT8)p5;
guid.Data4[3] = (UINT8)p6;
guid.Data4[4] = (UINT8)p7;
guid.Data4[5] = (UINT8)p8;
guid.Data4[6] = (UINT8)p9;
guid.Data4[7] = (UINT8)p10;
return true;
}

View file

@ -571,6 +571,21 @@ typedef struct POSTCODE_SECTION_ {
///
#define EFI_DEP_SOR 0x09
//*****************************************************************************
// X86 Reset Vector Data
//*****************************************************************************
typedef struct X86_RESET_VECTOR_DATA_ {
UINT8 ApEntryVector[8]; // Base: 0xffffffd0
UINT8 Reserved0[8];
UINT32 PeiCoreEntryPoint; // Base: 0xffffffe0
UINT8 Reserved1[12];
UINT8 ResetVector[8]; // Base: 0xfffffff0
UINT32 ApStartupSegment; // Base: 0xfffffff8
UINT32 BootFvBaseAddress; // Base: 0xfffffffc
} X86_RESET_VECTOR_DATA;
#define X86_RESET_VECTOR_DATA_UNPOPULATED 0x12345678
// Restore previous packing rules
#pragma pack(pop)

View file

@ -120,7 +120,7 @@ USTATUS FfsParser::parse(const UByteArray & buffer)
USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & index)
{
// Sanity check
// Sanity check
if (buffer.isEmpty()) {
return EFI_INVALID_PARAMETER;
}
@ -756,7 +756,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
// Parse PDR region as BIOS space
USTATUS result = parseRawArea(index);
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME && result != U_STORES_NOT_FOUND)
return result;
return U_SUCCESS;
@ -910,8 +910,8 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
prevItemType = itemType;
result = findNextRawAreaItem(index, itemOffset + prevItemSize, itemType, itemOffset, itemSize, itemAltSize);
// Silence value not used after assignment warning
(void)prevItemType;
// Silence value not used after assignment warning
(void)prevItemType;
}
// Padding at the end of RAW area
@ -1058,7 +1058,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
UINT32 usedSpace = *(UINT32*)(volume.constData() + 12);
if (appleCrc32 != 0) {
// Calculate CRC32 of the volume body
UINT32 crc = crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
UINT32 crc = (UINT32)crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
if (crc == appleCrc32) {
hasAppleCrc32 = true;
}
@ -1161,26 +1161,34 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
for (; offset < dataSize - sizeof(UINT32); offset++) {
const UINT32* currentPos = (const UINT32*)(data.constData() + offset);
const UINT32 restSize = dataSize - offset;
if (readUnaligned(currentPos) == INTEL_MICROCODE_HEADER_VERSION) {// Intel microcode
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;
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(currentPos) || restSize < ucodeHeader->TotalSize) //TODO: needs a separate checking function
continue;
// Check reserved bytes
bool reservedBytesValid = true;
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
if (ucodeHeader->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
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) {
continue;
}
// All checks passed, microcode found
nextItemType = Types::Microcode;
nextItemSize = ucodeHeader->TotalSize;
@ -1442,7 +1450,6 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
if (file.isEmpty()) {
return U_INVALID_PARAMETER;
}
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER)) {
return U_INVALID_FILE;
}
@ -1480,14 +1487,16 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
}
UINT32 alignment = (UINT32)(1UL << alignmentPower);
if ((localOffset + header.size()) % alignment)
if ((localOffset + header.size()) % alignment) {
msgUnalignedFile = true;
}
// Check file alignment agains volume alignment
bool msgFileAlignmentIsGreaterThanVolumeAlignment = false;
if (!isWeakAligned && volumeAlignment < alignment)
if (!isWeakAligned && volumeAlignment < alignment) {
msgFileAlignmentIsGreaterThanVolumeAlignment = true;
}
// Get file body
UByteArray body = file.mid(header.size());
@ -1508,9 +1517,10 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
// Check header checksum
UINT8 calculatedHeader = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State);
bool msgInvalidHeaderChecksum = false;
if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader)
if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader) {
msgInvalidHeaderChecksum = true;
}
// Check data checksum
// Data checksum must be calculated
bool msgInvalidDataChecksum = false;
@ -1526,9 +1536,10 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
calculatedData = FFS_FIXED_CHECKSUM2;
}
if (fileHeader->IntegrityCheck.Checksum.File != calculatedData)
if (fileHeader->IntegrityCheck.Checksum.File != calculatedData) {
msgInvalidDataChecksum = true;
}
// Check file type
bool msgUnknownType = false;
if (fileHeader->Type > EFI_FV_FILETYPE_MM_CORE_STANDALONE && fileHeader->Type != EFI_FV_FILETYPE_PAD) {
@ -1663,19 +1674,16 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index)
model->setText(index, UString("NVAR store"));
return nvramParser->parseNvarStore(index);
}
if (fileGuid == NVRAM_NVAR_PEI_EXTERNAL_DEFAULTS_FILE_GUID) {
else if (fileGuid == NVRAM_NVAR_PEI_EXTERNAL_DEFAULTS_FILE_GUID) {
model->setText(index, UString("NVRAM external defaults"));
return nvramParser->parseNvarStore(index);
}
if (fileGuid == NVRAM_NVAR_BB_DEFAULTS_FILE_GUID) {
else if (fileGuid == NVRAM_NVAR_BB_DEFAULTS_FILE_GUID) {
model->setText(index, UString("NVAR bb defaults"));
return nvramParser->parseNvarStore(index);
}
// Parse vendor hash file
if (fileGuid == BG_VENDOR_HASH_FILE_GUID_PHOENIX) {
else if (fileGuid == BG_VENDOR_HASH_FILE_GUID_PHOENIX) {
return parseVendorHashFile(fileGuid, index);
}
@ -2081,7 +2089,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
UINT32 crc = *(UINT32*)(section.constData() + headerSize);
additionalInfo += UString("\nChecksum type: CRC32");
// Calculate CRC32 of section data
UINT32 calculated = crc32(0, (const UINT8*)section.constData() + dataOffset, section.size() - dataOffset);
UINT32 calculated = (UINT32)crc32(0, (const UINT8*)section.constData() + dataOffset, section.size() - dataOffset);
if (crc == calculated) {
additionalInfo += usprintf("\nChecksum: %08Xh, valid", crc);
}
@ -2995,6 +3003,9 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index)
const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size();
addressDiff = 0xFFFFFFFFULL - model->base(lastVtf) - vtfSize + 1;
// Parse reset vector data
parseResetVectorData();
// Find and parse FIT
parseFit(index);
@ -3007,6 +3018,37 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index)
return U_SUCCESS;
}
USTATUS FfsParser::parseResetVectorData()
{
// Sanity check
if (!lastVtf.isValid())
return U_SUCCESS;
// Check VTF to have enough space at the end to fit Reset Vector Data
UByteArray vtf = model->header(lastVtf) + model->body(lastVtf) + model->tail(lastVtf);
if ((UINT32)vtf.size() < sizeof(X86_RESET_VECTOR_DATA))
return U_SUCCESS;
const X86_RESET_VECTOR_DATA* resetVectorData = (const X86_RESET_VECTOR_DATA*)(vtf.constData() + vtf.size() - sizeof(X86_RESET_VECTOR_DATA));
// Add info
UString info = usprintf("\nAP entry vector: %02X %02X %02X %02X %02X %02X %02X %02X\n"
"Reset vector: %02X %02X %02X %02X %02X %02X %02X %02X\n"
"PEI core entry point: %08Xh\n"
"AP startup segment: %08X\n"
"BootFV base address: %08X\n",
resetVectorData->ApEntryVector[0], resetVectorData->ApEntryVector[1], resetVectorData->ApEntryVector[2], resetVectorData->ApEntryVector[3],
resetVectorData->ApEntryVector[4], resetVectorData->ApEntryVector[5], resetVectorData->ApEntryVector[6], resetVectorData->ApEntryVector[7],
resetVectorData->ResetVector[0], resetVectorData->ResetVector[1], resetVectorData->ResetVector[2], resetVectorData->ResetVector[3],
resetVectorData->ResetVector[4], resetVectorData->ResetVector[5], resetVectorData->ResetVector[6], resetVectorData->ResetVector[7],
resetVectorData->PeiCoreEntryPoint,
resetVectorData->ApStartupSegment,
resetVectorData->BootFvBaseAddress);
model->addInfo(lastVtf, info);
return U_SUCCESS;
}
USTATUS FfsParser::checkTeImageBase(const UModelIndex & index)
{
// Sanity check
@ -3618,13 +3660,13 @@ USTATUS FfsParser::parseFitEntryMicrocode(const UByteArray & microcode, const UI
}
const INTEL_MICROCODE_HEADER* header = (const INTEL_MICROCODE_HEADER*)(microcode.constData() + localOffset);
if (header->Version != INTEL_MICROCODE_HEADER_VERSION) {
if (header->Version != INTEL_MICROCODE_HEADER_VERSION_1) {
return U_INVALID_MICROCODE;
}
bool reservedBytesValid = true;
for (UINT8 i = 0; i < sizeof(header->Reserved); i++)
if (header->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
if (header->Reserved[i] != 0x00) {
reservedBytesValid = false;
break;
}
@ -3632,13 +3674,21 @@ USTATUS FfsParser::parseFitEntryMicrocode(const UByteArray & microcode, const UI
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) {
return U_INVALID_MICROCODE;
}
// Valid microcode found
info = usprintf("CPUID: %08Xh, Revision: %08Xh, Date: %02X.%02X.%04X",
info = usprintf("CpuSignature: %08Xh, Revision: %08Xh, Date: %02X.%02X.%04X",
header->CpuSignature,
header->Revision,
header->DateDay,
@ -3678,34 +3728,33 @@ USTATUS FfsParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOf
// Add ACM header info
UString acmInfo;
acmInfo += usprintf(
" found at base %Xh\n"
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n"
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n"
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh",
model->base(parent) + localOffset,
header->ModuleType,
header->ModuleSubtype,
header->ModuleSize * sizeof(UINT32),
header->HeaderVersion,
header->ChipsetId,
header->Flags,
header->ModuleVendor,
header->DateDay, header->DateMonth, header->DateYear,
header->ModuleSize * sizeof(UINT32),
header->EntryPoint,
header->AcmSvn,
header->Unknown1,
header->Unknown2,
header->GdtBase,
header->GdtMax,
header->SegmentSel,
header->KeySize * sizeof(UINT32),
header->Unknown4 * sizeof(UINT32)
);
acmInfo += usprintf(" found at base %Xh\n"
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n"
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n"
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh",
model->base(parent) + localOffset,
header->ModuleType,
header->ModuleSubtype,
header->ModuleSize * sizeof(UINT32),
header->HeaderVersion,
header->ChipsetId,
header->Flags,
header->ModuleVendor,
header->DateDay, header->DateMonth, header->DateYear,
header->ModuleSize * sizeof(UINT32),
header->EntryPoint,
header->AcmSvn,
header->Unknown1,
header->Unknown2,
header->GdtBase,
header->GdtMax,
header->SegmentSel,
header->KeySize * sizeof(UINT32),
header->Unknown4 * sizeof(UINT32)
);
// Add PubKey
acmInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", header->RsaPubExp);
for (UINT16 i = 0; i < sizeof(header->RsaPubKey); i++) {
@ -4071,66 +4120,134 @@ USTATUS FfsParser::parseMicrocodeVolumeBody(const UModelIndex & index)
USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
{
const UINT32 dataSize = (const UINT32)microcode.size();
if (dataSize < sizeof(INTEL_MICROCODE_HEADER)) {
//msg(usprintf("%s: input is too small even for Intel microcode header", __FUNCTION__), parent);
// We have enough data to fit the header
if ((UINT32)microcode.size() < sizeof(INTEL_MICROCODE_HEADER)) {
return U_INVALID_MICROCODE;
}
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)microcode.constData();
if (ucodeHeader->Version != INTEL_MICROCODE_HEADER_VERSION) {
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(ucodeHeader)) {
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
// 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] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
for (UINT8 i = 0; i < sizeof(ucodeHeader->Reserved); i++) {
if (ucodeHeader->Reserved[i] != 0x00) {
reservedBytesValid = false;
break;
}
}
if (!reservedBytesValid) {
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
if (dataSize < ucodeHeader->TotalSize) {
//msg(usprintf("%s: input is too small for the whole Intel microcode", __FUNCTION__), parent);
// 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) {
return U_INVALID_MICROCODE;
}
// We have enough data to fit the whole TotalSize
if ((UINT32)microcode.size() < ucodeHeader->TotalSize) {
return U_INVALID_MICROCODE;
}
// Valid microcode found
// Construct header and body
UINT32 dataSize = ucodeHeader->DataSize;
if (dataSize == 0)
dataSize = INTEL_MICROCODE_REAL_DATA_SIZE_ON_ZERO;
// Recalculate the whole microcode checksum
UByteArray tempMicrocode = microcode;
INTEL_MICROCODE_HEADER* tempUcodeHeader = (INTEL_MICROCODE_HEADER*)(tempMicrocode.data());
tempUcodeHeader->Checksum = 0;
UINT32 calculated = calculateChecksum32((const UINT32*)tempMicrocode.constData(), tempUcodeHeader->TotalSize);
bool msgInvalidChecksum = (ucodeHeader->Checksum != calculated);
// Construct header, body and tail
UByteArray header = microcode.left(sizeof(INTEL_MICROCODE_HEADER));
UByteArray body = microcode.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize);
//TODO: recalculate microcode checksum
UByteArray body = microcode.mid(sizeof(INTEL_MICROCODE_HEADER), dataSize);
UByteArray tail = microcode.mid(sizeof(INTEL_MICROCODE_HEADER) + dataSize);
// Check if we have extended header in the tail
UString extendedHeaderInfo;
if ((UINT32)tail.size() >= sizeof(INTEL_MICROCODE_EXTENDED_HEADER)) {
const INTEL_MICROCODE_EXTENDED_HEADER* extendedHeader = (const INTEL_MICROCODE_EXTENDED_HEADER*)tail.constData();
// Reserved bytes are all zeroes
bool extendedReservedBytesValid = true;
for (UINT8 i = 0; i < sizeof(extendedHeader->Reserved); i++) {
if (extendedHeader->Reserved[i] != 0x00) {
extendedReservedBytesValid = false;
break;
}
}
// We have more than 0 entries and they are all in the tail
if (extendedReservedBytesValid
&& extendedHeader->EntryCount > 0
&& (UINT32)tail.size() >= sizeof(INTEL_MICROCODE_EXTENDED_HEADER) + extendedHeader->EntryCount * sizeof(INTEL_MICROCODE_EXTENDED_HEADER_ENTRY)) {
// Recalculate extended header checksum
INTEL_MICROCODE_EXTENDED_HEADER* tempExtendedHeader = (INTEL_MICROCODE_EXTENDED_HEADER*)(tempMicrocode.data() + sizeof(INTEL_MICROCODE_HEADER) + dataSize);
tempExtendedHeader->Checksum = 0;
UINT32 extendedCalculated = calculateChecksum32((const UINT32*)tempExtendedHeader, sizeof(INTEL_MICROCODE_EXTENDED_HEADER) + extendedHeader->EntryCount * sizeof(INTEL_MICROCODE_EXTENDED_HEADER_ENTRY));
extendedHeaderInfo = usprintf("\nExtended header entries: %u\nExtended header checksum: %08Xh, ",
extendedHeader->EntryCount,
extendedHeader->Checksum)
+ (extendedHeader->Checksum == extendedCalculated ? UString("valid") : usprintf("invalid, should be %08Xh", extendedCalculated));
const INTEL_MICROCODE_EXTENDED_HEADER_ENTRY* firstEntry = (const INTEL_MICROCODE_EXTENDED_HEADER_ENTRY*)(extendedHeader + 1);
for (UINT8 i = 0; i < extendedHeader->EntryCount; i++) {
const INTEL_MICROCODE_EXTENDED_HEADER_ENTRY* entry = (const INTEL_MICROCODE_EXTENDED_HEADER_ENTRY*)(firstEntry + i);
// Recalculate checksum after patching
tempUcodeHeader->Checksum = 0;
tempUcodeHeader->CpuFlags = entry->CpuFlags;
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, ",
i + 1, entry->CpuSignature,
i + 1, entry->CpuFlags,
i + 1, entry->Checksum)
+ (entry->Checksum == entryCalculated ? UString("valid") : usprintf("invalid, should be %08Xh", entryCalculated));
}
}
}
// Add info
UString name("Intel microcode");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n"
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh",
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
header.size(), header.size(),
body.size(), body.size(),
ucodeHeader->DateDay,
ucodeHeader->DateMonth,
ucodeHeader->DateYear,
ucodeHeader->CpuSignature,
ucodeHeader->Revision,
ucodeHeader->Checksum,
ucodeHeader->LoaderRevision,
ucodeHeader->CpuFlags);
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, ",
dataSize, dataSize,
header.size(), header.size(),
body.size(), body.size(),
tail.size(), tail.size(),
ucodeHeader->DateDay,
ucodeHeader->DateMonth,
ucodeHeader->DateYear,
ucodeHeader->CpuSignature,
ucodeHeader->Revision,
ucodeHeader->LoaderRevision,
ucodeHeader->CpuFlags,
ucodeHeader->Checksum)
+ (ucodeHeader->Checksum == calculated ? UString("valid") : usprintf("invalid, should be %08Xh", calculated))
+ extendedHeaderInfo;
// Add tree item
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent);
// No need to parse body further for now
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, tail, Fixed, parent);
if (msgInvalidChecksum)
msg(usprintf("%s: invalid microcode checksum %08Xh, should be %08Xh", __FUNCTION__, ucodeHeader->Checksum, calculated), index);
// No need to parse the body further for now
return U_SUCCESS;
}

View file

@ -144,6 +144,7 @@ private:
USTATUS checkProtectedRanges(const UModelIndex & index);
USTATUS markProtectedRangeRecursive(const UModelIndex & index, const BG_PROTECTED_RANGE & range);
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);

View file

@ -49,7 +49,7 @@ USTATUS FfsReport::generateRecursive(std::vector<UString> & report, const UModel
// Calculate item CRC32
UByteArray data = model->header(index) + model->body(index) + model->tail(index);
UINT32 crc = crc32(0, (const UINT8*)data.constData(), data.size());
UINT32 crc = (UINT32)crc32(0, (const UINT8*)data.constData(), data.size());
// Information on current item
UString text = model->text(index);

63
common/fit.h Normal file → Executable file
View file

@ -50,21 +50,6 @@ typedef struct FIT_ENTRY_ {
UINT8 Checksum;
} FIT_ENTRY;
typedef struct INTEL_MICROCODE_HEADER_ {
UINT32 Version;
UINT32 Revision;
UINT16 DateYear;
UINT8 DateDay;
UINT8 DateMonth;
UINT32 CpuSignature;
UINT32 Checksum;
UINT32 LoaderRevision;
UINT32 CpuFlags;
UINT32 DataSize;
UINT32 TotalSize;
UINT8 Reserved[12];
} INTEL_MICROCODE_HEADER;
typedef struct {
UINT16 IndexRegisterAddress;
UINT16 DataRegisterAddress;
@ -73,9 +58,51 @@ typedef struct {
UINT16 Index;
} FIT_ENTRY_VERSION_0_CONFIG_POLICY;
#define INTEL_MICROCODE_HEADER_VERSION 0x00000001
#define INTEL_MICROCODE_HEADER_RESERVED_BYTE 0x00
#define INTEL_MICROCODE_HEADER_SIZES_VALID(ptr) (((INTEL_MICROCODE_HEADER*)ptr)->TotalSize - ((INTEL_MICROCODE_HEADER*)ptr)->DataSize == sizeof(INTEL_MICROCODE_HEADER))
// This scructure is described in Section 9.11.1 of the Intel Software Developer manual Volume 3A Part 1
typedef struct INTEL_MICROCODE_HEADER_ {
UINT32 Version;
UINT32 Revision;
UINT16 DateYear;
UINT8 DateDay;
UINT8 DateMonth;
UINT32 CpuSignature;
UINT32 Checksum; // Checksum of Update Data and Header. Used to verify the integrity of the update header and data.
// Checksum is correct when the summation of all the DWORDs (including the extended Processor Signature Table)
// that comprise the microcode update result in 00000000H.
UINT32 LoaderRevision;
UINT32 CpuFlags;
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).
UINT32 TotalSize;// Specifies the total size of the microcode update in bytes.
// It is the summation of the header size, the encrypted data size and the size of the optional extended signature table.
// This value is always a multiple of 1024.
UINT8 Reserved[12];
} INTEL_MICROCODE_HEADER;
#define INTEL_MICROCODE_REAL_DATA_SIZE_ON_ZERO 2000
typedef struct INTEL_MICROCODE_EXTENDED_HEADER_ {
UINT32 EntryCount;
UINT32 Checksum; // Checksum of extended processor signature table.
// Used to verify the integrity of the extended processor signature table.
// Checksum is correct when the summation of the DWORDs that comprise the extended processor signature table results in 00000000H.
UINT8 Reserved[12];
// INTEL_MICROCODE_EXTENDED_HEADER_ENTRY Entries[EntryCount];
} INTEL_MICROCODE_EXTENDED_HEADER;
typedef struct INTEL_MICROCODE_EXTENDED_HEADER_ENTRY_ {
UINT32 CpuSignature;
UINT32 CpuFlags;
UINT32 Checksum; // To calculate the Checksum, substitute the Primary Processor Signature entry and the Processor Flags entry with the corresponding Extended Patch entry.
// Delete the Extended Processor Signature Table entries.
// 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
#pragma pack(pop)

1169
common/meparser.cpp Executable file

File diff suppressed because it is too large Load diff

230
common/meparser.h Normal file → Executable file
View file

@ -21,10 +21,235 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ustring.h"
#include "ubytearray.h"
#include "treemodel.h"
#include "me.h"
#include "sha256.h"
// TODO: implement ME region parser
#ifdef U_ENABLE_ME_PARSING_SUPPORT
// FPT
#define ME_ROM_BYPASS_VECTOR_SIZE 0x10
const UByteArray ME_FPT_HEADER_SIGNATURE("\x24\x46\x50\x54", 4); //$FPT
typedef struct ME_FPT_HEADER_ {
UINT32 Signature;
UINT32 NumEntries;
UINT8 HeaderVersion;
UINT8 EntryVersion;
UINT8 HeaderLength;
UINT8 Checksum; // One bit for Redundant before IFWI
UINT16 TicksToAdd;
UINT16 TokensToAdd;
UINT32 UmaSize; // Flags in SPS
UINT32 FlashLayout; // Crc32 before IFWI
UINT16 FitcMajor;
UINT16 FitcMinor;
UINT16 FitcHotfix;
UINT16 FitcBuild;
} ME_FPT_HEADER;
typedef struct ME_FPT_ENTRY_{
CHAR8 PartitionName[4];
UINT8 Reserved1;
UINT32 Offset;
UINT32 Length;
UINT8 Reserved2[12];
UINT32 PartitionType : 7;
UINT32 CopyToDramCache : 1;
UINT32 Reserved3 : 7;
UINT32 BuiltWithLength1 : 1;
UINT32 BuiltWithLength2 : 1;
UINT32 Reserved4 : 7;
UINT32 EntryValid : 8;
} ME_FPT_ENTRY;
// IFWI
typedef struct ME_IFWI_LAYOUT_HEADER_ {
UINT8 RomBypassVector[16];
UINT32 DataPartitionOffset;
UINT32 DataPartitionSize;
UINT32 Boot1Offset;
UINT32 Boot1Size;
UINT32 Boot2Offset;
UINT32 Boot2Size;
UINT32 Boot3Offset;
UINT32 Boot3Size;
} ME_IFWI_LAYOUT_HEADER;
// BPDT
const UByteArray ME_BPDT_GREEN_SIGNATURE("\xAA\x55\x00\x00", 4); //0x000055AA
const UByteArray ME_BPDT_YELLOW_SIGNATURE("\xAA\x55\xAA\x00", 4); //0x00AA55AA
typedef struct ME_BPDT_HEADER_ {
UINT32 Signature;
UINT16 NumEntries;
UINT16 Version;
UINT32 Checksum;
UINT32 IfwiVersion;
UINT16 FitcMajor;
UINT16 FitcMinor;
UINT16 FitcHotfix;
UINT16 FitcBuild;
} ME_BPDT_HEADER ;
typedef struct ME_BPDT_ENTRY_ {
UINT32 Type : 16;
UINT32 SplitSubPartitionFirstPart : 1;
UINT32 SplitSubPartitionSecondPart : 1;
UINT32 CodeSubPartition : 1;
UINT32 UmaCachable : 1;
UINT32 Reserved: 12;
UINT32 Offset;
UINT32 Length;
} ME_BPDT_ENTRY;
// CPD
const UByteArray ME_CPD_SIGNATURE("\x24\x43\x50\x44", 4); //$CPD
typedef struct ME_CPD_HEADER_ {
UINT32 Signature;
UINT32 NumEntries;
UINT8 HeaderVersion;
UINT8 EntryVersion;
UINT8 HeaderLength;
UINT8 HeaderChecksum;
UINT8 ShortName[4];
} ME_CPD_HEADER;
typedef struct ME_BPDT_CPD_ENTRY_ {
UINT8 EntryName[12];
struct {
UINT32 Offset : 25;
UINT32 HuffmanCompressed : 1;
UINT32 Reserved : 6;
} Offset;
UINT32 Length;
UINT32 Reserved;
} ME_BPDT_CPD_ENTRY;
typedef struct ME_CPD_MANIFEST_HEADER_ {
UINT32 HeaderType;
UINT32 HeaderLength;
UINT32 HeaderVersion;
UINT32 Flags;
UINT32 Vendor;
UINT32 Date;
UINT32 Size;
UINT32 HeaderId;
UINT32 Reserved1;
UINT16 VersionMajor;
UINT16 VersionMinor;
UINT16 VersionBugfix;
UINT16 VersionBuild;
UINT32 SecurityVersion;
UINT8 Reserved2[8];
UINT8 Reserved3[64];
UINT32 ModulusSize;
UINT32 ExponentSize;
//manifest_rsa_key_t public_key;
//manifest_signature_t signature;
} ME_CPD_MANIFEST_HEADER;
typedef struct ME_CPD_EXTENTION_HEADER_ {
UINT32 Type;
UINT32 Length;
} ME_CPD_EXTENTION_HEADER;
typedef struct ME_CPD_EXT_SIGNED_PACKAGE_INFO_MODULES_ {
UINT8 Name[12];
UINT8 Type;
UINT8 HashAlgorithm;
UINT16 HashSize;
UINT32 MetadataSize;
UINT8 MetadataHash[32];
} ME_CPD_EXT_SIGNED_PACKAGE_INFO_MODULES;
typedef struct ME_CPD_EXT_SIGNED_PACKAGE_INFO_ {
UINT32 ExtensionType;
UINT32 ExtensionLength;
UINT8 PackageName[4];
UINT32 Vcn;
UINT8 UsageBitmap[16];
UINT32 Svn;
UINT8 Reserved[16];
// ME_EXT_SIGNED_PACKAGE_INFO_MODULES Modules[];
} ME_CPD_EXT_SIGNED_PACKAGE_INFO;
typedef struct ME_CPD_EXT_MODULE_ATTRIBUTES_ {
UINT32 ExtensionType;
UINT32 ExtensionLength;
UINT8 CompressionType;
UINT8 Reserved[3];
UINT32 UncompressedSize;
UINT32 CompressedSize;
UINT32 GlobalModuleId;
UINT8 ImageHash[32];
} ME_CPD_EXT_MODULE_ATTRIBUTES;
typedef struct ME_CPD_EXT_IFWI_PARTITION_MANIFEST_ {
UINT32 ExtensionType;
UINT32 ExtensionLength;
UINT8 PartitionName[4];
UINT32 CompletePartitionLength;
UINT16 PartitionVersionMinor;
UINT16 PartitionVersionMajor;
UINT32 DataFormatVersion;
UINT32 InstanceId;
UINT32 SupportMultipleInstances : 1;
UINT32 SupportApiVersionBasedUpdate : 1;
UINT32 ActionOnUpdate : 2;
UINT32 ObeyFullUpdateRules : 1;
UINT32 IfrEnableOnly : 1;
UINT32 AllowCrossPointUpdate : 1;
UINT32 AllowCrossHotfixUpdate : 1;
UINT32 PartialUpdateOnly : 1;
UINT32 ReservedFlags : 23;
UINT32 HashAlgorithm : 8;
UINT32 HashSize : 24;
UINT8 CompletePartitionHash[32];
UINT8 Reserved[20];
} ME_CPD_EXT_IFWI_PARTITION_MANIFEST;
#define ME_MODULE_COMPRESSION_TYPE_UNCOMPRESSED 0
#define ME_MODULE_COMPRESSION_TYPE_HUFFMAN 1
#define ME_MODULE_COMPRESSION_TYPE_LZMA 2
#define ME_MANIFEST_HEADER_ID 0x324E4D24 //$MN2
class MeParser
{
public:
// Default constructor and destructor
MeParser(TreeModel* treeModel) : model(treeModel) {}
~MeParser() {}
// Returns messages
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
// Clears messages
void clearMessages() { messagesVector.clear(); }
// ME parsing
USTATUS parseMeRegionBody(const UModelIndex & index);
private:
TreeModel *model;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const UString message, const UModelIndex index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
}
USTATUS parseFptRegion(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
USTATUS parseIfwiRegion(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
USTATUS parseBpdtRegion(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
USTATUS parseCodePartitionDirectory(const UByteArray & directory, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseExtensionsArea(const UModelIndex & index);
USTATUS parseSignedPackageInfoData(const UModelIndex & index);
};
#else
class MeParser
{
public:
@ -40,4 +265,5 @@ public:
// ME parsing
USTATUS parseMeRegionBody(const UModelIndex & index) { U_UNUSED_PARAMETER(index); return U_SUCCESS; }
};
#endif // U_ENABLE_ME_PARSING_SUPPORT
#endif // MEPARSER_H

1
common/nvram.h Normal file → Executable file
View file

@ -86,6 +86,7 @@ const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
#define NVRAM_APPLE_NSS_STORE_SIGNATURE 0x53534E24 // $NSS
#define NVRAM_APPLE_FSYS_STORE_SIGNATURE 0x73797346 // Fsys
#define NVRAM_APPLE_GAID_STORE_SIGNATURE 0x64696147 // Gaid
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA

52
common/nvramparser.cpp Normal file → Executable file
View file

@ -536,7 +536,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
UINT32 offset = storeOffset;
for (; offset < dataSize - sizeof(UINT32); offset++) {
const UINT32* currentPos = (const UINT32*)(volume.constData() + offset);
if (*currentPos == NVRAM_VSS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_SVS_STORE_SIGNATURE) { // $VSS or $SVS signatures found, perform checks
if (*currentPos == NVRAM_VSS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_SVS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_NSS_STORE_SIGNATURE) { // $VSS, $SVS or $NSS signatures found, perform checks
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)currentPos;
if (vssHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) {
msg(usprintf("%s: VSS store candidate at offset %Xh skipped, has invalid format %02Xh", __FUNCTION__, localOffset + offset, vssHeader->Format), index);
@ -645,20 +645,27 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
// All checks passed, store found
break;
}
else if (*currentPos == INTEL_MICROCODE_HEADER_VERSION) {// Intel microcode
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(currentPos)) // Check header sizes
continue;
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] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
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) {
continue;
}
// All checks passed, store found
break;
@ -710,7 +717,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize)
{
const UINT32* signature = (const UINT32*)(data.constData() + storeOffset);
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE || *signature == NVRAM_APPLE_NSS_STORE_SIGNATURE) {
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
storeSize = vssHeader->Size;
}
@ -755,7 +762,7 @@ USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOff
const OEM_ACTIVATION_MARKER* markerHeader = (const OEM_ACTIVATION_MARKER*)signature;
storeSize = markerHeader->Size;
}
else if (*signature == INTEL_MICROCODE_HEADER_VERSION) { // Intel microcode, must be checked after SLIC marker because of the same *signature values
else if (*signature == INTEL_MICROCODE_HEADER_VERSION_1) { // Intel microcode, must be checked after SLIC marker because of the same *signature values
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)signature;
storeSize = ucodeHeader->TotalSize;
} else {
@ -796,10 +803,19 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
UByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), storeSize - sizeof(VSS_VARIABLE_STORE_HEADER));
// Add info
bool isSvsStore = (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE);
UString name = isSvsStore ? UString("SVS store") : UString("VSS store");
UString info = usprintf("Signature: %s\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
isSvsStore ? "$SVS" : "$VSS",
UString name;
if (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
name = UString("SVS store");
}
else if (vssStoreHeader->Signature == NVRAM_APPLE_NSS_STORE_SIGNATURE) {
name = UString("NSS store");
}
else {
name = UString("VSS store");
}
UString info = usprintf("Signature: %Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
vssStoreHeader->Signature,
storeSize, storeSize,
header.size(), header.size(),
body.size(), body.size(),
@ -912,7 +928,7 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)header.data();
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
UINT32 calculatedCrc = crc32(0, (const UINT8*)crcFtwBlockHeader, headerSize);
UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, headerSize);
// Add info
UString name("FTW store");
@ -996,7 +1012,7 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32
// Check store checksum
UINT32 storedCrc = *(UINT32*)store.right(sizeof(UINT32)).constData();
UINT32 calculatedCrc = crc32(0, (const UINT8*)store.constData(), (const UINT32)store.size() - sizeof(UINT32));
UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)store.constData(), (const UINT32)store.size() - sizeof(UINT32));
// Add info
bool isGaidStore = (fsysStoreHeader->Signature == NVRAM_APPLE_GAID_STORE_SIGNATURE);
@ -1234,8 +1250,8 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
}
// Check signature and run parser function needed
// VSS/SVS store
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
// VSS/SVS/NSS store
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE || *signature == NVRAM_APPLE_NSS_STORE_SIGNATURE)
return parseVssStoreHeader(store, localOffset, false, parent, index);
// VSS2 store
if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1)
@ -1266,7 +1282,7 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
return parseSlicMarkerHeader(store, localOffset, parent, index);
// Intel microcode
// Must be checked after SLIC marker because of the same *signature values
else if (*signature == INTEL_MICROCODE_HEADER_VERSION)
else if (*signature == INTEL_MICROCODE_HEADER_VERSION_1)
return ffsParser->parseIntelMicrocodeHeader(store, localOffset, parent, index);
msg(usprintf("parseStoreHeader: don't know how to parse a header with signature %08Xh", *signature), parent);
@ -1393,7 +1409,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
// Calculate CRC32 of the variable data
storedCrc32 = appleVariableHeader->DataCrc32;
calculatedCrc32 = crc32(0, (const UINT8*)body.constData(), body.size());
calculatedCrc32 = (UINT32)crc32(0, (const UINT8*)body.constData(), body.size());
}
}

34
common/types.cpp Normal file → Executable file
View file

@ -66,6 +66,20 @@ UString itemTypeToUString(const UINT8 type)
case Types::FlashMapEntry: return UString("FlashMap entry");
case Types::Microcode: return UString("Microcode");
case Types::SlicData: return UString("SLIC data");
// ME-specific
case Types::FptStore: return UString("FPT store");
case Types::FptEntry: return UString("FPT entry");
case Types::IfwiHeader: return UString("IFWI header");
case Types::IfwiPartition: return UString("IFWI partition");
case Types::FptPartition: return UString("FPT partition");
case Types::BpdtStore: return UString("BPDT store");
case Types::BpdtEntry: return UString("BPDT entry");
case Types::BpdtPartition: return UString("BPDT partition");
case Types::CpdStore: return UString("CPD store");
case Types::CpdEntry: return UString("CPD entry");
case Types::CpdPartition: return UString("CPD partition");
case Types::CpdExtension: return UString("CPD extension");
case Types::CpdSpiEntry: return UString("CPD SPI entry");
}
return UString("Unknown");
@ -132,6 +146,26 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
if (subtype == Subtypes::IntelMicrocode) return UString("Intel");
if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
break;
// ME-specific
case Types::FptEntry:
if (subtype == Subtypes::ValidFptEntry) return UString("Valid");
if (subtype == Subtypes::InvalidFptEntry) return UString("Invalid");
break;
case Types::FptPartition:
if (subtype == Subtypes::CodeFptPartition) return UString("Code");
if (subtype == Subtypes::DataFptPartition) return UString("Data");
if (subtype == Subtypes::GlutFptPartition) return UString("GLUT");
break;
case Types::IfwiPartition:
if (subtype == Subtypes::BootIfwiPartition) return UString("Boot");
if (subtype == Subtypes::DataIfwiPartition) return UString("Data");
break;
case Types::CpdPartition:
if (subtype == Subtypes::ManifestCpdPartition) return UString("Manifest");
if (subtype == Subtypes::MetadataCpdPartition) return UString("Metadata");
if (subtype == Subtypes::KeyCpdPartition) return UString("Key");
if (subtype == Subtypes::CodeCpdPartition) return UString("Code");
break;
}
return UString();

38
common/types.h Normal file → Executable file
View file

@ -58,6 +58,20 @@ namespace Types {
FlashMapEntry,
Microcode,
SlicData,
// ME-specific
IfwiHeader,
IfwiPartition,
FptStore,
FptEntry,
FptPartition,
BpdtStore,
BpdtEntry,
BpdtPartition,
CpdStore,
CpdEntry,
CpdPartition,
CpdExtension,
CpdSpiEntry
};
}
@ -150,6 +164,30 @@ namespace Subtypes {
PubkeySlicData = 190,
MarkerSlicData
};
// ME-specific
enum IfwiPartitionSubtypes {
DataIfwiPartition = 200,
BootIfwiPartition
};
enum FptEntrySubtypes {
ValidFptEntry = 210,
InvalidFptEntry
};
enum FptPartitionSubtypes {
CodeFptPartition = 220,
DataFptPartition,
GlutFptPartition
};
enum CpdPartitionSubtypes {
ManifestCpdPartition = 230,
MetadataCpdPartition,
KeyCpdPartition,
CodeCpdPartition
};
}
// *ToUString conversion routines

25
common/utility.cpp Normal file → Executable file
View file

@ -141,6 +141,7 @@ UString errorCodeToUString(USTATUS errorCode)
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
case U_INVALID_CAPSULE: return UString("Invalid capsule");
case U_STORES_NOT_FOUND: return UString("Stores not found");
case U_INVALID_STORE_SIZE: return UString("Invalid store size");
default: return usprintf("Unknown error %02X", errorCode);
}
}
@ -149,12 +150,12 @@ UString errorCodeToUString(USTATUS errorCode)
USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionType, UINT8 & algorithm, UINT32 & dictionarySize, UByteArray & decompressedData, UByteArray & efiDecompressedData)
{
const UINT8* data;
UINT32 dataSize;
UINT32 dataSize;
UINT8* decompressed;
UINT8* efiDecompressed;
UINT32 decompressedSize = 0;
UINT32 decompressedSize = 0;
UINT8* scratch;
UINT32 scratchSize = 0;
UINT32 scratchSize = 0;
const EFI_TIANO_HEADER* header;
// For all but LZMA dictionary size is 0
@ -333,6 +334,24 @@ UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize)
return (UINT16)(0x10000 - counter);
}
// 32bit checksum calculation routine
UINT32 calculateChecksum32(const UINT32* buffer, UINT32 bufferSize)
{
if (!buffer)
return 0;
UINT32 counter = 0;
UINT32 index = 0;
bufferSize /= sizeof(UINT32);
for (; index < bufferSize; index++) {
counter = (UINT32)(counter + buffer[index]);
}
return (UINT32)(0x100000000ULL - counter);
}
// Get padding type for a given padding
UINT8 getPaddingType(const UByteArray & padding)
{

3
common/utility.h Normal file → Executable file
View file

@ -44,6 +44,9 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
// 16bit checksum calculation routine
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
// 32bit checksum calculation routine
UINT32 calculateChecksum32(const UINT32* buffer, UINT32 bufferSize);
// Return padding type from it's contents
UINT8 getPaddingType(const UByteArray & padding);

View file

@ -417,6 +417,9 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
z_size_t len;
gz_statep state;
if (nitems == 0 || size == 0)
return 0;
/* get internal structure */
if (file == NULL)
return 0;

View file

@ -280,6 +280,9 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
z_size_t len;
gz_statep state;
if (nitems == 0 || size == 0)
return 0;
/* get internal structure */
if (file == NULL)
return 0;