mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Initial ME parser, improved ucode parser, reset vector info
This commit is contained in:
parent
f386eda430
commit
2e7aa8133a
@ -192,11 +192,24 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
ui->menuVolumeActions->setEnabled(type == Types::Volume);
|
ui->menuVolumeActions->setEnabled(type == Types::Volume);
|
||||||
ui->menuFileActions->setEnabled(type == Types::File);
|
ui->menuFileActions->setEnabled(type == Types::File);
|
||||||
ui->menuSectionActions->setEnabled(type == Types::Section);
|
ui->menuSectionActions->setEnabled(type == Types::Section);
|
||||||
ui->menuEntryActions->setEnabled(type == Types::NvarEntry
|
ui->menuEntryActions->setEnabled(type == Types::Microcode
|
||||||
|
|| type == Types::SlicData
|
||||||
|
|| type == Types::NvarEntry
|
||||||
|| type == Types::VssEntry
|
|| type == Types::VssEntry
|
||||||
|| type == Types::FsysEntry
|
|| type == Types::FsysEntry
|
||||||
|| type == Types::EvsaEntry
|
|| type == Types::EvsaEntry
|
||||||
|| type == Types::FlashMapEntry);
|
|| type == Types::FlashMapEntry
|
||||||
|
|| type == Types::IfwiHeader
|
||||||
|
|| type == Types::IfwiPartition
|
||||||
|
|| type == Types::FptPartition
|
||||||
|
|| type == Types::FptEntry
|
||||||
|
|| type == Types::BpdtPartition
|
||||||
|
|| type == Types::BpdtEntry
|
||||||
|
|| type == Types::CpdPartition
|
||||||
|
|| type == Types::CpdEntry
|
||||||
|
|| type == Types::CpdExtension
|
||||||
|
|| type == Types::CpdSpiEntry
|
||||||
|
);
|
||||||
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
||||||
|| type == Types::Vss2Store
|
|| type == Types::Vss2Store
|
||||||
|| type == Types::FdcStore
|
|| type == Types::FdcStore
|
||||||
@ -204,9 +217,11 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
|| type == Types::EvsaStore
|
|| type == Types::EvsaStore
|
||||||
|| type == Types::FtwStore
|
|| type == Types::FtwStore
|
||||||
|| type == Types::FlashMapStore
|
|| type == Types::FlashMapStore
|
||||||
|| type == Types::CmdbStore
|
|| type == Types::CmdbStore
|
||||||
|| type == Types::Microcode
|
|| type == Types::FptStore
|
||||||
|| type == Types::SlicData);
|
|| type == Types::BpdtStore
|
||||||
|
|| type == Types::CpdStore
|
||||||
|
);
|
||||||
|
|
||||||
// Enable actions
|
// Enable actions
|
||||||
ui->actionHexView->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
|
ui->actionHexView->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
|
||||||
@ -481,7 +496,7 @@ void UEFITool::extract(const UINT8 mode)
|
|||||||
if (subtype == Subtypes::PubkeySlicData) path = QFileDialog::getSaveFileName(this, tr("Save SLIC pubkey to file"), name + ".spk", tr("SLIC pubkey files (*.spk *.bin);;All files (*)"));
|
if (subtype == Subtypes::PubkeySlicData) path = QFileDialog::getSaveFileName(this, tr("Save SLIC pubkey to file"), name + ".spk", tr("SLIC pubkey files (*.spk *.bin);;All files (*)"));
|
||||||
else path = QFileDialog::getSaveFileName(this, tr("Save SLIC marker to file"), name + ".smk", tr("SLIC marker files (*.smk *.bin);;All files (*)"));
|
else path = QFileDialog::getSaveFileName(this, tr("Save SLIC marker to file"), name + ".smk", tr("SLIC marker files (*.smk *.bin);;All files (*)"));
|
||||||
break;
|
break;
|
||||||
default: path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", tr("Binary files (*.bin);;All files (*)"));
|
default: path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", tr("Binary files (*.bin);;All files (*)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == EXTRACT_MODE_BODY || mode == EXTRACT_MODE_BODY_UNCOMPRESSED) {
|
else if (mode == EXTRACT_MODE_BODY || mode == EXTRACT_MODE_BODY_UNCOMPRESSED) {
|
||||||
@ -553,7 +568,7 @@ void UEFITool::remove()
|
|||||||
void UEFITool::about()
|
void UEFITool::about()
|
||||||
{
|
{
|
||||||
QMessageBox::about(this, tr("About UEFITool"), tr(
|
QMessageBox::about(this, tr("About UEFITool"), tr(
|
||||||
"Copyright (c) 2018, LongSoft.<br>"
|
"Copyright (c) 2019, Nikolaj Schlej.<br>"
|
||||||
"Program icon made by <a href=https://www.behance.net/alzhidkov>Alexander Zhidkov</a>.<br>"
|
"Program icon made by <a href=https://www.behance.net/alzhidkov>Alexander Zhidkov</a>.<br>"
|
||||||
"The program uses QHexEdit2 library made by <a href=https://github.com/Simsys/>Simsys</a>.<br>"
|
"The program uses QHexEdit2 library made by <a href=https://github.com/Simsys/>Simsys</a>.<br>"
|
||||||
"Qt-less engine is using Bstrlib made by <a href=https://github.com/websnarf/>Paul Hsieh</a>.<br><br>"
|
"Qt-less engine is using Bstrlib made by <a href=https://github.com/websnarf/>Paul Hsieh</a>.<br><br>"
|
||||||
@ -858,8 +873,11 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
case Types::EvsaStore:
|
case Types::EvsaStore:
|
||||||
case Types::FtwStore:
|
case Types::FtwStore:
|
||||||
case Types::FlashMapStore:
|
case Types::FlashMapStore:
|
||||||
case Types::CmdbStore: ui->menuStoreActions->exec(event->globalPos()); break;
|
case Types::CmdbStore:
|
||||||
case Types::FreeSpace: break;
|
case Types::FptStore:
|
||||||
|
case Types::CpdStore:
|
||||||
|
case Types::BpdtStore: ui->menuStoreActions->exec(event->globalPos()); break;
|
||||||
|
case Types::FreeSpace: break; // No menu needed for FreeSpace item
|
||||||
default: ui->menuEntryActions->exec(event->globalPos()); break;
|
default: ui->menuEntryActions->exec(event->globalPos()); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ TARGET = UEFITool
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
DEFINES += "U_ENABLE_FIT_PARSING_SUPPORT"
|
DEFINES += "U_ENABLE_FIT_PARSING_SUPPORT"
|
||||||
DEFINES += "U_ENABLE_NVRAM_PARSING_SUPPORT"
|
DEFINES += "U_ENABLE_NVRAM_PARSING_SUPPORT"
|
||||||
|
DEFINES += "U_ENABLE_ME_PARSING_SUPPORT"
|
||||||
DEFINES += "U_ENABLE_GUID_DATABASE_SUPPORT"
|
DEFINES += "U_ENABLE_GUID_DATABASE_SUPPORT"
|
||||||
|
|
||||||
HEADERS += uefitool.h \
|
HEADERS += uefitool.h \
|
||||||
@ -70,6 +71,7 @@ SOURCES += uefitool_main.cpp \
|
|||||||
../common/guiddatabase.cpp \
|
../common/guiddatabase.cpp \
|
||||||
../common/nvram.cpp \
|
../common/nvram.cpp \
|
||||||
../common/nvramparser.cpp \
|
../common/nvramparser.cpp \
|
||||||
|
../common/meparser.cpp \
|
||||||
../common/ffsops.cpp \
|
../common/ffsops.cpp \
|
||||||
../common/types.cpp \
|
../common/types.cpp \
|
||||||
../common/descriptor.cpp \
|
../common/descriptor.cpp \
|
||||||
|
@ -711,10 +711,6 @@ Decode (
|
|||||||
UINT32 DataIdx;
|
UINT32 DataIdx;
|
||||||
UINT16 CharC;
|
UINT16 CharC;
|
||||||
|
|
||||||
BytesRemain = (UINT16)(-1);
|
|
||||||
|
|
||||||
DataIdx = 0;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
//
|
//
|
||||||
// Get one code from mBitBuf
|
// Get one code from mBitBuf
|
||||||
|
@ -68,6 +68,19 @@ typedef size_t USTATUS;
|
|||||||
#define U_INVALID_BG_BOOT_POLICY 46
|
#define U_INVALID_BG_BOOT_POLICY 46
|
||||||
#define U_INVALID_TXT_CONF 47
|
#define U_INVALID_TXT_CONF 47
|
||||||
#define U_ELEMENTS_NOT_FOUND 48
|
#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
|
#define U_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
// EDK2 porting definitions
|
// EDK2 porting definitions
|
||||||
|
@ -39,16 +39,16 @@ const UINT8 ffsAlignment2Table[] =
|
|||||||
|
|
||||||
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
||||||
{
|
{
|
||||||
ffsSize[2] = (UINT8)((size) >> 16);
|
ffsSize[2] = (UINT8)((size) >> 16U);
|
||||||
ffsSize[1] = (UINT8)((size) >> 8);
|
ffsSize[1] = (UINT8)((size) >> 8U);
|
||||||
ffsSize[0] = (UINT8)((size));
|
ffsSize[0] = (UINT8)((size));
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 uint24ToUint32(const UINT8* ffsSize)
|
UINT32 uint24ToUint32(const UINT8* ffsSize)
|
||||||
{
|
{
|
||||||
return (UINT32) ffsSize[0]
|
return (UINT32) ffsSize[0]
|
||||||
+ ((UINT32) ffsSize[1] << 8U)
|
+ ((UINT32) ffsSize[1] << 8U)
|
||||||
+ ((UINT32) ffsSize[2] << 16U);
|
+ ((UINT32) ffsSize[2] << 16U);
|
||||||
}
|
}
|
||||||
|
|
||||||
UString guidToUString(const EFI_GUID & guid, bool convertToString)
|
UString guidToUString(const EFI_GUID & guid, bool convertToString)
|
||||||
@ -84,17 +84,17 @@ bool ustringToGuid(const UString & str, EFI_GUID & guid)
|
|||||||
if (err == 0)
|
if (err == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
guid.Data1 = p0;
|
guid.Data1 = (UINT32)p0;
|
||||||
guid.Data2 = p1;
|
guid.Data2 = (UINT16)p1;
|
||||||
guid.Data3 = p2;
|
guid.Data3 = (UINT16)p2;
|
||||||
guid.Data4[0] = p3;
|
guid.Data4[0] = (UINT8)p3;
|
||||||
guid.Data4[1] = p4;
|
guid.Data4[1] = (UINT8)p4;
|
||||||
guid.Data4[2] = p5;
|
guid.Data4[2] = (UINT8)p5;
|
||||||
guid.Data4[3] = p6;
|
guid.Data4[3] = (UINT8)p6;
|
||||||
guid.Data4[4] = p7;
|
guid.Data4[4] = (UINT8)p7;
|
||||||
guid.Data4[5] = p8;
|
guid.Data4[5] = (UINT8)p8;
|
||||||
guid.Data4[6] = p9;
|
guid.Data4[6] = (UINT8)p9;
|
||||||
guid.Data4[7] = p10;
|
guid.Data4[7] = (UINT8)p10;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
15
common/ffs.h
15
common/ffs.h
@ -571,6 +571,21 @@ typedef struct POSTCODE_SECTION_ {
|
|||||||
///
|
///
|
||||||
#define EFI_DEP_SOR 0x09
|
#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
|
// Restore previous packing rules
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ USTATUS FfsParser::parse(const UByteArray & buffer)
|
|||||||
|
|
||||||
USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & index)
|
USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (buffer.isEmpty()) {
|
if (buffer.isEmpty()) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
@ -756,7 +756,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
|
|||||||
|
|
||||||
// Parse PDR region as BIOS space
|
// Parse PDR region as BIOS space
|
||||||
USTATUS result = parseRawArea(index);
|
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 result;
|
||||||
|
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
@ -910,8 +910,8 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
|
|||||||
prevItemType = itemType;
|
prevItemType = itemType;
|
||||||
result = findNextRawAreaItem(index, itemOffset + prevItemSize, itemType, itemOffset, itemSize, itemAltSize);
|
result = findNextRawAreaItem(index, itemOffset + prevItemSize, itemType, itemOffset, itemSize, itemAltSize);
|
||||||
|
|
||||||
// Silence value not used after assignment warning
|
// Silence value not used after assignment warning
|
||||||
(void)prevItemType;
|
(void)prevItemType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Padding at the end of RAW area
|
// 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);
|
UINT32 usedSpace = *(UINT32*)(volume.constData() + 12);
|
||||||
if (appleCrc32 != 0) {
|
if (appleCrc32 != 0) {
|
||||||
// Calculate CRC32 of the volume body
|
// 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) {
|
if (crc == appleCrc32) {
|
||||||
hasAppleCrc32 = true;
|
hasAppleCrc32 = true;
|
||||||
}
|
}
|
||||||
@ -1161,26 +1161,34 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
|
|||||||
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
||||||
const UINT32* currentPos = (const UINT32*)(data.constData() + offset);
|
const UINT32* currentPos = (const UINT32*)(data.constData() + offset);
|
||||||
const UINT32 restSize = dataSize - 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
|
// Check data size
|
||||||
if (restSize < sizeof(INTEL_MICROCODE_HEADER))
|
if (restSize < sizeof(INTEL_MICROCODE_HEADER))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check microcode size
|
// Check microcode size
|
||||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
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
|
// Check reserved bytes
|
||||||
bool reservedBytesValid = true;
|
bool reservedBytesValid = true;
|
||||||
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
|
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;
|
reservedBytesValid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!reservedBytesValid)
|
if (!reservedBytesValid)
|
||||||
continue;
|
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
|
// All checks passed, microcode found
|
||||||
nextItemType = Types::Microcode;
|
nextItemType = Types::Microcode;
|
||||||
nextItemSize = ucodeHeader->TotalSize;
|
nextItemSize = ucodeHeader->TotalSize;
|
||||||
@ -1442,7 +1450,6 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
if (file.isEmpty()) {
|
if (file.isEmpty()) {
|
||||||
return U_INVALID_PARAMETER;
|
return U_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER)) {
|
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER)) {
|
||||||
return U_INVALID_FILE;
|
return U_INVALID_FILE;
|
||||||
}
|
}
|
||||||
@ -1480,14 +1487,16 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
}
|
}
|
||||||
|
|
||||||
UINT32 alignment = (UINT32)(1UL << alignmentPower);
|
UINT32 alignment = (UINT32)(1UL << alignmentPower);
|
||||||
if ((localOffset + header.size()) % alignment)
|
if ((localOffset + header.size()) % alignment) {
|
||||||
msgUnalignedFile = true;
|
msgUnalignedFile = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check file alignment agains volume alignment
|
// Check file alignment agains volume alignment
|
||||||
bool msgFileAlignmentIsGreaterThanVolumeAlignment = false;
|
bool msgFileAlignmentIsGreaterThanVolumeAlignment = false;
|
||||||
if (!isWeakAligned && volumeAlignment < alignment)
|
if (!isWeakAligned && volumeAlignment < alignment) {
|
||||||
msgFileAlignmentIsGreaterThanVolumeAlignment = true;
|
msgFileAlignmentIsGreaterThanVolumeAlignment = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get file body
|
// Get file body
|
||||||
UByteArray body = file.mid(header.size());
|
UByteArray body = file.mid(header.size());
|
||||||
|
|
||||||
@ -1508,9 +1517,10 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
// Check header checksum
|
// Check header checksum
|
||||||
UINT8 calculatedHeader = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State);
|
UINT8 calculatedHeader = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State);
|
||||||
bool msgInvalidHeaderChecksum = false;
|
bool msgInvalidHeaderChecksum = false;
|
||||||
if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader)
|
if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader) {
|
||||||
msgInvalidHeaderChecksum = true;
|
msgInvalidHeaderChecksum = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check data checksum
|
// Check data checksum
|
||||||
// Data checksum must be calculated
|
// Data checksum must be calculated
|
||||||
bool msgInvalidDataChecksum = false;
|
bool msgInvalidDataChecksum = false;
|
||||||
@ -1526,9 +1536,10 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
calculatedData = FFS_FIXED_CHECKSUM2;
|
calculatedData = FFS_FIXED_CHECKSUM2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileHeader->IntegrityCheck.Checksum.File != calculatedData)
|
if (fileHeader->IntegrityCheck.Checksum.File != calculatedData) {
|
||||||
msgInvalidDataChecksum = true;
|
msgInvalidDataChecksum = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check file type
|
// Check file type
|
||||||
bool msgUnknownType = false;
|
bool msgUnknownType = false;
|
||||||
if (fileHeader->Type > EFI_FV_FILETYPE_MM_CORE_STANDALONE && fileHeader->Type != EFI_FV_FILETYPE_PAD) {
|
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"));
|
model->setText(index, UString("NVAR store"));
|
||||||
return nvramParser->parseNvarStore(index);
|
return nvramParser->parseNvarStore(index);
|
||||||
}
|
}
|
||||||
|
else if (fileGuid == NVRAM_NVAR_PEI_EXTERNAL_DEFAULTS_FILE_GUID) {
|
||||||
if (fileGuid == NVRAM_NVAR_PEI_EXTERNAL_DEFAULTS_FILE_GUID) {
|
|
||||||
model->setText(index, UString("NVRAM external defaults"));
|
model->setText(index, UString("NVRAM external defaults"));
|
||||||
return nvramParser->parseNvarStore(index);
|
return nvramParser->parseNvarStore(index);
|
||||||
}
|
}
|
||||||
|
else if (fileGuid == NVRAM_NVAR_BB_DEFAULTS_FILE_GUID) {
|
||||||
if (fileGuid == NVRAM_NVAR_BB_DEFAULTS_FILE_GUID) {
|
|
||||||
model->setText(index, UString("NVAR bb defaults"));
|
model->setText(index, UString("NVAR bb defaults"));
|
||||||
return nvramParser->parseNvarStore(index);
|
return nvramParser->parseNvarStore(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse vendor hash file
|
// 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);
|
return parseVendorHashFile(fileGuid, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2081,7 +2089,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
|
|||||||
UINT32 crc = *(UINT32*)(section.constData() + headerSize);
|
UINT32 crc = *(UINT32*)(section.constData() + headerSize);
|
||||||
additionalInfo += UString("\nChecksum type: CRC32");
|
additionalInfo += UString("\nChecksum type: CRC32");
|
||||||
// Calculate CRC32 of section data
|
// 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) {
|
if (crc == calculated) {
|
||||||
additionalInfo += usprintf("\nChecksum: %08Xh, valid", crc);
|
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();
|
const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size();
|
||||||
addressDiff = 0xFFFFFFFFULL - model->base(lastVtf) - vtfSize + 1;
|
addressDiff = 0xFFFFFFFFULL - model->base(lastVtf) - vtfSize + 1;
|
||||||
|
|
||||||
|
// Parse reset vector data
|
||||||
|
parseResetVectorData();
|
||||||
|
|
||||||
// Find and parse FIT
|
// Find and parse FIT
|
||||||
parseFit(index);
|
parseFit(index);
|
||||||
|
|
||||||
@ -3007,6 +3018,37 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index)
|
|||||||
return U_SUCCESS;
|
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)
|
USTATUS FfsParser::checkTeImageBase(const UModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// 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);
|
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;
|
return U_INVALID_MICROCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reservedBytesValid = true;
|
bool reservedBytesValid = true;
|
||||||
for (UINT8 i = 0; i < sizeof(header->Reserved); i++)
|
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;
|
reservedBytesValid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3632,13 +3674,21 @@ USTATUS FfsParser::parseFitEntryMicrocode(const UByteArray & microcode, const UI
|
|||||||
return U_INVALID_MICROCODE;
|
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;
|
UINT32 mcSize = header->TotalSize;
|
||||||
if ((UINT32)microcode.size() < localOffset + mcSize) {
|
if ((UINT32)microcode.size() < localOffset + mcSize) {
|
||||||
return U_INVALID_MICROCODE;
|
return U_INVALID_MICROCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid microcode found
|
// 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->CpuSignature,
|
||||||
header->Revision,
|
header->Revision,
|
||||||
header->DateDay,
|
header->DateDay,
|
||||||
@ -3678,34 +3728,33 @@ USTATUS FfsParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOf
|
|||||||
|
|
||||||
// Add ACM header info
|
// Add ACM header info
|
||||||
UString acmInfo;
|
UString acmInfo;
|
||||||
acmInfo += usprintf(
|
acmInfo += usprintf(" found at base %Xh\n"
|
||||||
" found at base %Xh\n"
|
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n"
|
||||||
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n"
|
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
|
||||||
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
|
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n"
|
||||||
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n"
|
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
|
||||||
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
|
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
|
||||||
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
|
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh",
|
||||||
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh",
|
model->base(parent) + localOffset,
|
||||||
model->base(parent) + localOffset,
|
header->ModuleType,
|
||||||
header->ModuleType,
|
header->ModuleSubtype,
|
||||||
header->ModuleSubtype,
|
header->ModuleSize * sizeof(UINT32),
|
||||||
header->ModuleSize * sizeof(UINT32),
|
header->HeaderVersion,
|
||||||
header->HeaderVersion,
|
header->ChipsetId,
|
||||||
header->ChipsetId,
|
header->Flags,
|
||||||
header->Flags,
|
header->ModuleVendor,
|
||||||
header->ModuleVendor,
|
header->DateDay, header->DateMonth, header->DateYear,
|
||||||
header->DateDay, header->DateMonth, header->DateYear,
|
header->ModuleSize * sizeof(UINT32),
|
||||||
header->ModuleSize * sizeof(UINT32),
|
header->EntryPoint,
|
||||||
header->EntryPoint,
|
header->AcmSvn,
|
||||||
header->AcmSvn,
|
header->Unknown1,
|
||||||
header->Unknown1,
|
header->Unknown2,
|
||||||
header->Unknown2,
|
header->GdtBase,
|
||||||
header->GdtBase,
|
header->GdtMax,
|
||||||
header->GdtMax,
|
header->SegmentSel,
|
||||||
header->SegmentSel,
|
header->KeySize * sizeof(UINT32),
|
||||||
header->KeySize * sizeof(UINT32),
|
header->Unknown4 * sizeof(UINT32)
|
||||||
header->Unknown4 * sizeof(UINT32)
|
);
|
||||||
);
|
|
||||||
// Add PubKey
|
// Add PubKey
|
||||||
acmInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", header->RsaPubExp);
|
acmInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", header->RsaPubExp);
|
||||||
for (UINT16 i = 0; i < sizeof(header->RsaPubKey); i++) {
|
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)
|
USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||||
{
|
{
|
||||||
const UINT32 dataSize = (const UINT32)microcode.size();
|
// We have enough data to fit the header
|
||||||
|
if ((UINT32)microcode.size() < sizeof(INTEL_MICROCODE_HEADER)) {
|
||||||
if (dataSize < sizeof(INTEL_MICROCODE_HEADER)) {
|
|
||||||
//msg(usprintf("%s: input is too small even for Intel microcode header", __FUNCTION__), parent);
|
|
||||||
return U_INVALID_MICROCODE;
|
return U_INVALID_MICROCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)microcode.constData();
|
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);
|
// Header version is 1
|
||||||
return U_INVALID_MICROCODE;
|
if (ucodeHeader->Version != INTEL_MICROCODE_HEADER_VERSION_1) {
|
||||||
}
|
|
||||||
|
|
||||||
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(ucodeHeader)) {
|
|
||||||
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
|
|
||||||
return U_INVALID_MICROCODE;
|
return U_INVALID_MICROCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reserved bytes are all zeroes
|
||||||
bool reservedBytesValid = true;
|
bool reservedBytesValid = true;
|
||||||
for (UINT8 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
|
for (UINT8 i = 0; i < sizeof(ucodeHeader->Reserved); i++) {
|
||||||
if (ucodeHeader->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
|
if (ucodeHeader->Reserved[i] != 0x00) {
|
||||||
reservedBytesValid = false;
|
reservedBytesValid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!reservedBytesValid) {
|
if (!reservedBytesValid) {
|
||||||
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
|
|
||||||
return U_INVALID_MICROCODE;
|
return U_INVALID_MICROCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataSize < ucodeHeader->TotalSize) {
|
// Data size is multiple of 4
|
||||||
//msg(usprintf("%s: input is too small for the whole Intel microcode", __FUNCTION__), parent);
|
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;
|
return U_INVALID_MICROCODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid microcode found
|
// 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 header = microcode.left(sizeof(INTEL_MICROCODE_HEADER));
|
||||||
UByteArray body = microcode.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize);
|
UByteArray body = microcode.mid(sizeof(INTEL_MICROCODE_HEADER), dataSize);
|
||||||
|
UByteArray tail = microcode.mid(sizeof(INTEL_MICROCODE_HEADER) + dataSize);
|
||||||
//TODO: recalculate microcode checksum
|
|
||||||
|
// 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
|
// Add info
|
||||||
UString name("Intel microcode");
|
UString name("Intel microcode");
|
||||||
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n"
|
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\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh",
|
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh\nChecksum: %08Xh, ",
|
||||||
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
|
dataSize, dataSize,
|
||||||
header.size(), header.size(),
|
header.size(), header.size(),
|
||||||
body.size(), body.size(),
|
body.size(), body.size(),
|
||||||
ucodeHeader->DateDay,
|
tail.size(), tail.size(),
|
||||||
ucodeHeader->DateMonth,
|
ucodeHeader->DateDay,
|
||||||
ucodeHeader->DateYear,
|
ucodeHeader->DateMonth,
|
||||||
ucodeHeader->CpuSignature,
|
ucodeHeader->DateYear,
|
||||||
ucodeHeader->Revision,
|
ucodeHeader->CpuSignature,
|
||||||
ucodeHeader->Checksum,
|
ucodeHeader->Revision,
|
||||||
ucodeHeader->LoaderRevision,
|
ucodeHeader->LoaderRevision,
|
||||||
ucodeHeader->CpuFlags);
|
ucodeHeader->CpuFlags,
|
||||||
|
ucodeHeader->Checksum)
|
||||||
|
+ (ucodeHeader->Checksum == calculated ? UString("valid") : usprintf("invalid, should be %08Xh", calculated))
|
||||||
|
+ extendedHeaderInfo;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, tail, Fixed, parent);
|
||||||
|
if (msgInvalidChecksum)
|
||||||
// No need to parse body further for now
|
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;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,7 @@ private:
|
|||||||
USTATUS checkProtectedRanges(const UModelIndex & index);
|
USTATUS checkProtectedRanges(const UModelIndex & index);
|
||||||
USTATUS markProtectedRangeRecursive(const UModelIndex & index, const BG_PROTECTED_RANGE & range);
|
USTATUS markProtectedRangeRecursive(const UModelIndex & index, const BG_PROTECTED_RANGE & range);
|
||||||
|
|
||||||
|
USTATUS parseResetVectorData();
|
||||||
USTATUS parseFit(const UModelIndex & index);
|
USTATUS parseFit(const UModelIndex & index);
|
||||||
USTATUS parseVendorHashFile(const UByteArray & fileGuid, const UModelIndex & index);
|
USTATUS parseVendorHashFile(const UByteArray & fileGuid, const UModelIndex & index);
|
||||||
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||||
|
@ -49,7 +49,7 @@ USTATUS FfsReport::generateRecursive(std::vector<UString> & report, const UModel
|
|||||||
|
|
||||||
// Calculate item CRC32
|
// Calculate item CRC32
|
||||||
UByteArray data = model->header(index) + model->body(index) + model->tail(index);
|
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
|
// Information on current item
|
||||||
UString text = model->text(index);
|
UString text = model->text(index);
|
||||||
|
63
common/fit.h
Normal file → Executable file
63
common/fit.h
Normal file → Executable file
@ -50,21 +50,6 @@ typedef struct FIT_ENTRY_ {
|
|||||||
UINT8 Checksum;
|
UINT8 Checksum;
|
||||||
} FIT_ENTRY;
|
} 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 {
|
typedef struct {
|
||||||
UINT16 IndexRegisterAddress;
|
UINT16 IndexRegisterAddress;
|
||||||
UINT16 DataRegisterAddress;
|
UINT16 DataRegisterAddress;
|
||||||
@ -73,9 +58,51 @@ typedef struct {
|
|||||||
UINT16 Index;
|
UINT16 Index;
|
||||||
} FIT_ENTRY_VERSION_0_CONFIG_POLICY;
|
} FIT_ENTRY_VERSION_0_CONFIG_POLICY;
|
||||||
|
|
||||||
#define INTEL_MICROCODE_HEADER_VERSION 0x00000001
|
// This scructure is described in Section 9.11.1 of the Intel Software Developer manual Volume 3A Part 1
|
||||||
#define INTEL_MICROCODE_HEADER_RESERVED_BYTE 0x00
|
typedef struct INTEL_MICROCODE_HEADER_ {
|
||||||
#define INTEL_MICROCODE_HEADER_SIZES_VALID(ptr) (((INTEL_MICROCODE_HEADER*)ptr)->TotalSize - ((INTEL_MICROCODE_HEADER*)ptr)->DataSize == sizeof(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)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
1169
common/meparser.cpp
Executable file
1169
common/meparser.cpp
Executable file
File diff suppressed because it is too large
Load Diff
230
common/meparser.h
Normal file → Executable file
230
common/meparser.h
Normal file → Executable file
@ -21,10 +21,235 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "ustring.h"
|
#include "ustring.h"
|
||||||
#include "ubytearray.h"
|
#include "ubytearray.h"
|
||||||
#include "treemodel.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
|
class MeParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -40,4 +265,5 @@ public:
|
|||||||
// ME parsing
|
// ME parsing
|
||||||
USTATUS parseMeRegionBody(const UModelIndex & index) { U_UNUSED_PARAMETER(index); return U_SUCCESS; }
|
USTATUS parseMeRegionBody(const UModelIndex & index) { U_UNUSED_PARAMETER(index); return U_SUCCESS; }
|
||||||
};
|
};
|
||||||
|
#endif // U_ENABLE_ME_PARSING_SUPPORT
|
||||||
#endif // MEPARSER_H
|
#endif // MEPARSER_H
|
||||||
|
1
common/nvram.h
Normal file → Executable file
1
common/nvram.h
Normal file → Executable file
@ -86,6 +86,7 @@ const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
|
|||||||
|
|
||||||
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
|
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
|
||||||
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
|
#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_FSYS_STORE_SIGNATURE 0x73797346 // Fsys
|
||||||
#define NVRAM_APPLE_GAID_STORE_SIGNATURE 0x64696147 // Gaid
|
#define NVRAM_APPLE_GAID_STORE_SIGNATURE 0x64696147 // Gaid
|
||||||
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA
|
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA
|
||||||
|
52
common/nvramparser.cpp
Normal file → Executable file
52
common/nvramparser.cpp
Normal file → Executable file
@ -536,7 +536,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
|||||||
UINT32 offset = storeOffset;
|
UINT32 offset = storeOffset;
|
||||||
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
||||||
const UINT32* currentPos = (const UINT32*)(volume.constData() + 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;
|
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)currentPos;
|
||||||
if (vssHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) {
|
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);
|
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
|
// All checks passed, store found
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (*currentPos == INTEL_MICROCODE_HEADER_VERSION) {// Intel microcode
|
else if (*currentPos == INTEL_MICROCODE_HEADER_VERSION_1) {// Intel microcode
|
||||||
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(currentPos)) // Check header sizes
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check reserved bytes
|
// Check reserved bytes
|
||||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
||||||
bool reservedBytesValid = true;
|
bool reservedBytesValid = true;
|
||||||
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
|
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;
|
reservedBytesValid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!reservedBytesValid)
|
if (!reservedBytesValid)
|
||||||
continue;
|
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
|
// All checks passed, store found
|
||||||
break;
|
break;
|
||||||
@ -710,7 +717,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
|||||||
USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize)
|
USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize)
|
||||||
{
|
{
|
||||||
const UINT32* signature = (const UINT32*)(data.constData() + storeOffset);
|
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;
|
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
||||||
storeSize = vssHeader->Size;
|
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;
|
const OEM_ACTIVATION_MARKER* markerHeader = (const OEM_ACTIVATION_MARKER*)signature;
|
||||||
storeSize = markerHeader->Size;
|
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;
|
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)signature;
|
||||||
storeSize = ucodeHeader->TotalSize;
|
storeSize = ucodeHeader->TotalSize;
|
||||||
} else {
|
} 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));
|
UByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), storeSize - sizeof(VSS_VARIABLE_STORE_HEADER));
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
bool isSvsStore = (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE);
|
UString name;
|
||||||
UString name = isSvsStore ? UString("SVS store") : UString("VSS store");
|
if (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
|
||||||
UString info = usprintf("Signature: %s\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
|
name = UString("SVS store");
|
||||||
isSvsStore ? "$SVS" : "$VSS",
|
}
|
||||||
|
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,
|
storeSize, storeSize,
|
||||||
header.size(), header.size(),
|
header.size(), header.size(),
|
||||||
body.size(), body.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();
|
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)header.data();
|
||||||
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
|
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
|
||||||
crcFtwBlockHeader->State = emptyByte ? 0xFF : 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
|
// Add info
|
||||||
UString name("FTW store");
|
UString name("FTW store");
|
||||||
@ -996,7 +1012,7 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32
|
|||||||
|
|
||||||
// Check store checksum
|
// Check store checksum
|
||||||
UINT32 storedCrc = *(UINT32*)store.right(sizeof(UINT32)).constData();
|
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
|
// Add info
|
||||||
bool isGaidStore = (fsysStoreHeader->Signature == NVRAM_APPLE_GAID_STORE_SIGNATURE);
|
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
|
// Check signature and run parser function needed
|
||||||
// VSS/SVS store
|
// VSS/SVS/NSS store
|
||||||
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)
|
||||||
return parseVssStoreHeader(store, localOffset, false, parent, index);
|
return parseVssStoreHeader(store, localOffset, false, parent, index);
|
||||||
// VSS2 store
|
// VSS2 store
|
||||||
if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1)
|
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);
|
return parseSlicMarkerHeader(store, localOffset, parent, index);
|
||||||
// Intel microcode
|
// Intel microcode
|
||||||
// Must be checked after SLIC marker because of the same *signature values
|
// 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);
|
return ffsParser->parseIntelMicrocodeHeader(store, localOffset, parent, index);
|
||||||
|
|
||||||
msg(usprintf("parseStoreHeader: don't know how to parse a header with signature %08Xh", *signature), parent);
|
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
|
// Calculate CRC32 of the variable data
|
||||||
storedCrc32 = appleVariableHeader->DataCrc32;
|
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
34
common/types.cpp
Normal file → Executable file
@ -66,6 +66,20 @@ UString itemTypeToUString(const UINT8 type)
|
|||||||
case Types::FlashMapEntry: return UString("FlashMap entry");
|
case Types::FlashMapEntry: return UString("FlashMap entry");
|
||||||
case Types::Microcode: return UString("Microcode");
|
case Types::Microcode: return UString("Microcode");
|
||||||
case Types::SlicData: return UString("SLIC data");
|
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");
|
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::IntelMicrocode) return UString("Intel");
|
||||||
if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
|
if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
|
||||||
break;
|
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();
|
return UString();
|
||||||
|
38
common/types.h
Normal file → Executable file
38
common/types.h
Normal file → Executable file
@ -58,6 +58,20 @@ namespace Types {
|
|||||||
FlashMapEntry,
|
FlashMapEntry,
|
||||||
Microcode,
|
Microcode,
|
||||||
SlicData,
|
SlicData,
|
||||||
|
// ME-specific
|
||||||
|
IfwiHeader,
|
||||||
|
IfwiPartition,
|
||||||
|
FptStore,
|
||||||
|
FptEntry,
|
||||||
|
FptPartition,
|
||||||
|
BpdtStore,
|
||||||
|
BpdtEntry,
|
||||||
|
BpdtPartition,
|
||||||
|
CpdStore,
|
||||||
|
CpdEntry,
|
||||||
|
CpdPartition,
|
||||||
|
CpdExtension,
|
||||||
|
CpdSpiEntry
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +164,30 @@ namespace Subtypes {
|
|||||||
PubkeySlicData = 190,
|
PubkeySlicData = 190,
|
||||||
MarkerSlicData
|
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
|
// *ToUString conversion routines
|
||||||
|
25
common/utility.cpp
Normal file → Executable file
25
common/utility.cpp
Normal file → Executable file
@ -141,6 +141,7 @@ UString errorCodeToUString(USTATUS errorCode)
|
|||||||
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
|
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
|
||||||
case U_INVALID_CAPSULE: return UString("Invalid capsule");
|
case U_INVALID_CAPSULE: return UString("Invalid capsule");
|
||||||
case U_STORES_NOT_FOUND: return UString("Stores not found");
|
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);
|
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)
|
USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionType, UINT8 & algorithm, UINT32 & dictionarySize, UByteArray & decompressedData, UByteArray & efiDecompressedData)
|
||||||
{
|
{
|
||||||
const UINT8* data;
|
const UINT8* data;
|
||||||
UINT32 dataSize;
|
UINT32 dataSize;
|
||||||
UINT8* decompressed;
|
UINT8* decompressed;
|
||||||
UINT8* efiDecompressed;
|
UINT8* efiDecompressed;
|
||||||
UINT32 decompressedSize = 0;
|
UINT32 decompressedSize = 0;
|
||||||
UINT8* scratch;
|
UINT8* scratch;
|
||||||
UINT32 scratchSize = 0;
|
UINT32 scratchSize = 0;
|
||||||
const EFI_TIANO_HEADER* header;
|
const EFI_TIANO_HEADER* header;
|
||||||
|
|
||||||
// For all but LZMA dictionary size is 0
|
// For all but LZMA dictionary size is 0
|
||||||
@ -333,6 +334,24 @@ UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize)
|
|||||||
return (UINT16)(0x10000 - counter);
|
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
|
// Get padding type for a given padding
|
||||||
UINT8 getPaddingType(const UByteArray & padding)
|
UINT8 getPaddingType(const UByteArray & padding)
|
||||||
{
|
{
|
||||||
|
3
common/utility.h
Normal file → Executable file
3
common/utility.h
Normal file → Executable file
@ -44,6 +44,9 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
|||||||
// 16bit checksum calculation routine
|
// 16bit checksum calculation routine
|
||||||
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
|
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
|
// Return padding type from it's contents
|
||||||
UINT8 getPaddingType(const UByteArray & padding);
|
UINT8 getPaddingType(const UByteArray & padding);
|
||||||
|
|
||||||
|
@ -417,6 +417,9 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
|
|||||||
z_size_t len;
|
z_size_t len;
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
|
|
||||||
|
if (nitems == 0 || size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* get internal structure */
|
/* get internal structure */
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -280,6 +280,9 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
|
|||||||
z_size_t len;
|
z_size_t len;
|
||||||
gz_statep state;
|
gz_statep state;
|
||||||
|
|
||||||
|
if (nitems == 0 || size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* get internal structure */
|
/* get internal structure */
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* version.h
|
/* version.h
|
||||||
|
|
||||||
Copyright (c) 2018, LongSoft. All rights reserved.
|
Copyright (c) 2019, Nikolaj Schlej. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -14,6 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#ifndef VERSION_H
|
#ifndef VERSION_H
|
||||||
#define VERSION_H
|
#define VERSION_H
|
||||||
|
|
||||||
#define PROGRAM_VERSION "NE alpha 55" " (" __DATE__ ")"
|
#define PROGRAM_VERSION "NE alpha 56" " (" __DATE__ ")"
|
||||||
|
|
||||||
#endif // VERSION_H
|
#endif // VERSION_H
|
||||||
|
Loading…
Reference in New Issue
Block a user