From c0a5cd0c0f5f4a5fd2d1fb6b943afec3e0fe4257 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Thu, 14 Apr 2016 20:36:59 +0200 Subject: [PATCH] UT NE A25.1 - added support for all Phoenix SCT stuff from NVRAM volume: Intel microcodes, CMDB block, SLIC pubkey/marker. - added support for EVSA extended variables (bigger than 0xFFFF) - better EVSA parsing (invalid data vars are shown now) - FlashMap entries now have human-readable types - various small fixes and refactorings --- UEFITool/ffsfinder.cpp | 24 --- UEFITool/ffsfinder.h | 12 +- UEFITool/uefitool.cpp | 7 +- common/ffsbuilder.cpp | 24 --- common/ffsbuilder.h | 12 +- common/ffsparser.cpp | 383 ++++++++++++++++++++++++++++++++++------- common/ffsparser.h | 12 +- common/fit.h | 4 + common/fitparser.cpp | 25 --- common/fitparser.h | 12 +- common/nvram.cpp | 27 +++ common/nvram.h | 153 ++++++++++++++-- common/types.cpp | 122 +++++++------ common/types.h | 14 ++ 14 files changed, 611 insertions(+), 220 deletions(-) diff --git a/UEFITool/ffsfinder.cpp b/UEFITool/ffsfinder.cpp index fd29670..d53878d 100644 --- a/UEFITool/ffsfinder.cpp +++ b/UEFITool/ffsfinder.cpp @@ -13,30 +13,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "ffsfinder.h" -FfsFinder::FfsFinder(const TreeModel* treeModel) - : model(treeModel) -{ -} - -FfsFinder::~FfsFinder() -{ -} - -void FfsFinder::msg(const QString & message, const QModelIndex & index) -{ - messagesVector.push_back(std::pair(message, index)); -} - -std::vector > FfsFinder::getMessages() const -{ - return messagesVector; -} - -void FfsFinder::clearMessages() -{ - messagesVector.clear(); -} - STATUS FfsFinder::findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode) { if (!index.isValid()) diff --git a/UEFITool/ffsfinder.h b/UEFITool/ffsfinder.h index 13d345a..c341a1f 100644 --- a/UEFITool/ffsfinder.h +++ b/UEFITool/ffsfinder.h @@ -28,11 +28,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. class FfsFinder { public: - explicit FfsFinder(const TreeModel * treeModel); - ~FfsFinder(); + FfsFinder(const TreeModel * treeModel) : model(treeModel) {} + ~FfsFinder() {} - std::vector > getMessages() const; - void clearMessages(); + std::vector > getMessages() const { return messagesVector; } + void clearMessages() { messagesVector.clear(); } STATUS findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode); STATUS findGuidPattern(const QModelIndex & index, const QByteArray & guidPattern, const UINT8 mode); @@ -42,7 +42,9 @@ private: const TreeModel* model; std::vector > messagesVector; - void msg(const QString & message, const QModelIndex &index = QModelIndex()); + void msg(const QString & message, const QModelIndex &index = QModelIndex()) { + messagesVector.push_back(std::pair(message, index)); + } }; #endif // FFSFINDER_H diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index 3e6cc08..d9c56d1 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -175,7 +175,8 @@ void UEFITool::populateUi(const QModelIndex ¤t) ui->menuVariableActions->setEnabled(type == Types::NvramVariableNvar || type == Types::NvramVariableVss || type == Types::NvramEntryFsys || type == Types::NvramEntryEvsa || type == Types::NvramEntryFlashMap); ui->menuStoreActions->setEnabled(type == Types::NvramStoreVss || type == Types::NvramStoreFdc || type == Types::NvramStoreFsys - || type == Types::NvramStoreEvsa || type == Types::NvramStoreFtw || type == Types::NvramStoreFlashMap); + || type == Types::NvramStoreEvsa || type == Types::NvramStoreFtw || type == Types::NvramStoreFlashMap || type == Types::NvramStoreCmdb + || type == Types::Microcode || type == Types::SlicPubkey || type == Types::SlicMarker); // Enable actions ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current)); @@ -995,6 +996,10 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event) case Types::NvramStoreEvsa: case Types::NvramStoreFtw: case Types::NvramStoreFlashMap: + case Types::NvramStoreCmdb: + case Types::Microcode: + case Types::SlicPubkey: + case Types::SlicMarker: ui->menuStoreActions->exec(event->globalPos()); break; } diff --git a/common/ffsbuilder.cpp b/common/ffsbuilder.cpp index b3befea..46d97c4 100644 --- a/common/ffsbuilder.cpp +++ b/common/ffsbuilder.cpp @@ -12,30 +12,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */ #include "ffsbuilder.h" -FfsBuilder::FfsBuilder(const TreeModel* treeModel) - : model(treeModel) -{ -} - -FfsBuilder::~FfsBuilder() -{ -} - -void FfsBuilder::msg(const QString & message, const QModelIndex & index) -{ - messagesVector.push_back(std::pair(message, index)); -} - -std::vector > FfsBuilder::getMessages() const -{ - return messagesVector; -} - -void FfsBuilder::clearMessages() -{ - messagesVector.clear(); -} - STATUS FfsBuilder::erase(const QModelIndex & index, QByteArray & erased) { // Sanity check diff --git a/common/ffsbuilder.h b/common/ffsbuilder.h index 08701b7..b7f8236 100644 --- a/common/ffsbuilder.h +++ b/common/ffsbuilder.h @@ -30,18 +30,20 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. class FfsBuilder { public: - explicit FfsBuilder(const TreeModel * treeModel); - ~FfsBuilder(); + FfsBuilder(const TreeModel * treeModel) : model(treeModel) {} + ~FfsBuilder() {} - std::vector > getMessages() const; - void clearMessages(); + std::vector > getMessages() const { return messagesVector; } + void clearMessages() { messagesVector.clear(); } STATUS build(const QModelIndex & root, QByteArray & image); private: const TreeModel* model; std::vector > messagesVector; - void msg(const QString & message, const QModelIndex &index = QModelIndex()); + void msg(const QString & message, const QModelIndex &index = QModelIndex()) { + messagesVector.push_back(std::pair(message, index)); + } STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule); STATUS buildIntelImage(const QModelIndex & index, QByteArray & intelImage); diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 8af277a..c5087b3 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -24,30 +24,6 @@ struct REGION_INFO { friend bool operator< (const REGION_INFO & lhs, const REGION_INFO & rhs){ return lhs.offset < rhs.offset; } }; -FfsParser::FfsParser(TreeModel* treeModel) - : model(treeModel), capsuleOffsetFixup(0) -{ -} - -FfsParser::~FfsParser() -{ -} - -void FfsParser::msg(const QString & message, const QModelIndex & index) -{ - messagesVector.push_back(std::pair(message, index)); -} - -std::vector > FfsParser::getMessages() const -{ - return messagesVector; -} - -void FfsParser::clearMessages() -{ - messagesVector.clear(); -} - // Firmware image parsing functions STATUS FfsParser::parse(const QByteArray & buffer) { @@ -3370,6 +3346,10 @@ STATUS FfsParser::parseStoreArea(const QByteArray & data, const QModelIndex & in parseFlashMapBody(current); break; case Types::NvramStoreFtw: + case Types::NvramStoreCmdb: + case Types::Microcode: + case Types::SlicPubkey: + case Types::SlicMarker: case Types::Padding: // No parsing required break; @@ -3423,8 +3403,9 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da break; } else if (*currentPos == NVRAM_EVSA_STORE_SIGNATURE) { //EVSA signature found - if (offset < 4) + if (offset < sizeof(UINT32)) continue; + const EVSA_STORE_ENTRY* evsaHeader = (const EVSA_STORE_ENTRY*)(currentPos - 1); if (evsaHeader->Header.Type != NVRAM_EVSA_ENTRY_TYPE_STORE) { msg(QObject::tr("findNextStore: EVSA store candidate at offset %1h skipped, has invalid type %2h").hexarg(parentOffset + offset - 4).hexarg2(evsaHeader->Header.Type, 2), index); @@ -3435,7 +3416,7 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da continue; } // All checks passed, store found - offset -= 4; + offset -= sizeof(UINT32); break; } else if (*currentPos == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *currentPos == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1) { //Possible FTW block signature found @@ -3460,7 +3441,7 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da } else // Unknown header continue; - + // All checks passed, store found break; } @@ -3472,6 +3453,68 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da // All checks passed, store found break; } + else if (*currentPos == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE) { // Phoenix SCT CMDB store + const PHOENIX_CMDB_HEADER* cmdbHeader = (const PHOENIX_CMDB_HEADER*)currentPos; + + // Check size + if (cmdbHeader->HeaderSize != sizeof(PHOENIX_CMDB_HEADER)) + continue; + + // 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; + + // Check reserved bytes + const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos; + bool reservedBytesValid = true; + for (int i = 0; i < sizeof(ucodeHeader->Reserved); i++) + if (ucodeHeader->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) { + reservedBytesValid = false; + break; + } + if (!reservedBytesValid) + continue; + + // All checks passed, store found + break; + } + else if (*currentPos == OEM_ACTIVATION_PUBKEY_MAGIC) { // SLIC pubkey + if (offset < 4 * sizeof(UINT32)) + continue; + + const OEM_ACTIVATION_PUBKEY* pubkeyHeader = (const OEM_ACTIVATION_PUBKEY*)(currentPos - 4); + // Check type + if (pubkeyHeader->Type != OEM_ACTIVATION_PUBKEY_TYPE) + continue; + + // All checks passed, store found + offset -= 4 * sizeof(UINT32); + break; + } + else if (*currentPos == OEM_ACTIVATION_MARKER_WINDOWS_FLAG_PART1) { // SLIC marker + if (offset >= dataSize - sizeof(UINT64) || + *(const UINT64*)currentPos != OEM_ACTIVATION_MARKER_WINDOWS_FLAG || + offset < 26) // Check full windows flag and structure size + continue; + + const OEM_ACTIVATION_MARKER* markerHeader = (const OEM_ACTIVATION_MARKER*)(data.constData() + offset - 26); + // Check reserved bytes + bool reservedBytesValid = true; + for (int i = 0; i < sizeof(markerHeader->Reserved); i++) + if (markerHeader->Reserved[i] != OEM_ACTIVATION_MARKER_RESERVED_BYTE) { + reservedBytesValid = false; + break; + } + if (!reservedBytesValid) + continue; + + // All checks passed, store found + offset -= 26; + break; + } } // No more stores found if (offset >= dataSize - sizeof(UINT32)) @@ -3515,14 +3558,26 @@ STATUS FfsParser::getStoreSize(const QByteArray & data, const UINT32 storeOffset const PHOENIX_FLASH_MAP_HEADER* flashMapHeader = (const PHOENIX_FLASH_MAP_HEADER*)signature; storeSize = sizeof(PHOENIX_FLASH_MAP_HEADER) + sizeof(PHOENIX_FLASH_MAP_ENTRY) * flashMapHeader->NumEntries; } + else if (*signature == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE) { // Phoenix SCT CMDB store + storeSize = NVRAM_PHOENIX_CMDB_SIZE; // It's a predefined max size, no need to calculate + } + else if (*(signature + 4) == OEM_ACTIVATION_PUBKEY_MAGIC) { // SLIC pubkey + const OEM_ACTIVATION_PUBKEY* pubkeyHeader = (const OEM_ACTIVATION_PUBKEY*)signature; + storeSize = pubkeyHeader->Size; + } + else if (*(const UINT64*)(data.constData() + storeOffset + 26) == OEM_ACTIVATION_MARKER_WINDOWS_FLAG) { // SLIC marker + 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 + const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)signature; + storeSize = ucodeHeader->TotalSize; + } return ERR_SUCCESS; } STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { - // Parse VSS volume like raw area - //Seen for now: $VSS, $SVS, Fsys, FTW block, _FDC, EVSA, _FLASH_MAP and paddings - const UINT32 dataSize = (UINT32)store.size(); const UINT32* signature = (const UINT32*)store.constData(); if (dataSize < sizeof(UINT32)) { @@ -3825,7 +3880,7 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent QByteArray body = store.mid(sizeof(PHOENIX_FLASH_MAP_HEADER), flashMapSize - sizeof(PHOENIX_FLASH_MAP_HEADER)); // Add info - QString name = QObject::tr("Phoenix SCT FlashMap"); + QString name = QObject::tr("Phoenix SCT flash map"); QString info = QObject::tr("Signature: _FLASH_MAP\nFull size: %1h (%2)\nHeader size: %3h (%4)\nBody size: %5h (%6)\nNumber of entries: %7") .hexarg(flashMapSize).arg(flashMapSize) .hexarg(header.size()).arg(header.size()) @@ -3838,6 +3893,168 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent // Add tree item index = model->addItem(Types::NvramStoreFlashMap, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); } + else if (*signature == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE) { // Phoenix SCT CMDB store + if (dataSize < sizeof(PHOENIX_CMDB_HEADER)) { + msg(QObject::tr("parseStoreHeader: volume body is too small even for CMDB store header"), parent); + return ERR_SUCCESS; + } + + // Check store size + UINT32 cmdbSize = NVRAM_PHOENIX_CMDB_SIZE; + if (dataSize < cmdbSize) { + msg(QObject::tr("parseStoreHeader: CMDB store size %1h (%2) is greater than volume body size %3h (%4)") + .hexarg(cmdbSize).arg(cmdbSize) + .hexarg(dataSize).arg(dataSize), parent); + return ERR_SUCCESS; + } + + // Get CMBD store header + const PHOENIX_CMDB_HEADER* cmdbHeader = (const PHOENIX_CMDB_HEADER*)signature; + + // Get parsing data + PARSING_DATA pdata = parsingDataFromQModelIndex(parent); + + // Construct header and body + QByteArray header = store.left(cmdbHeader->TotalSize); + QByteArray body = store.mid(cmdbHeader->TotalSize, cmdbSize - cmdbHeader->TotalSize); + + // Add info + QString name = QObject::tr("CMDB store"); + QString info = QObject::tr("Signature: CMDB\nFull size: %1h (%2)\nHeader size: %3h (%4)\nBody size: %5h (%6)") + .hexarg(cmdbSize).arg(cmdbSize) + .hexarg(header.size()).arg(header.size()) + .hexarg(body.size()).arg(body.size()); + + // Add correct offset + pdata.offset = parentOffset; + + // Add tree item + index = model->addItem(Types::NvramStoreCmdb, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); + } + else if (*(signature + 4) == OEM_ACTIVATION_PUBKEY_MAGIC) { // SLIC pubkey + if (dataSize < sizeof(OEM_ACTIVATION_PUBKEY)) { + msg(QObject::tr("parseStoreHeader: volume body is too small even for SLIC pubkey header"), parent); + return ERR_SUCCESS; + } + + // Get SLIC pubkey header + const OEM_ACTIVATION_PUBKEY* pubkeyHeader = (const OEM_ACTIVATION_PUBKEY*)signature; + + // Check store size + if (dataSize < pubkeyHeader->Size) { + msg(QObject::tr("parseStoreHeader: SLIC pubkey size %1h (%2) is greater than volume body size %3h (%4)") + .hexarg(pubkeyHeader->Size).arg(pubkeyHeader->Size) + .hexarg(dataSize).arg(dataSize), parent); + return ERR_SUCCESS; + } + + // Get parsing data + PARSING_DATA pdata = parsingDataFromQModelIndex(parent); + + // Construct header and body + QByteArray header = store.left(sizeof(OEM_ACTIVATION_PUBKEY)); + + // Add info + QString name = QObject::tr("SLIC pubkey"); + QString info = QObject::tr("Type: 0h\nFull size: %1h (%2)\nHeader size: %3h (%4)\nBody size: 0h (0)\n" + "Key type :%5h\nVersion: %6h\nAlgorithm: %7h\nMagic: RSA1\nBit length: %8h\nExponent:%9h") + .hexarg(pubkeyHeader->Size).arg(pubkeyHeader->Size) + .hexarg(header.size()).arg(header.size()) + .hexarg2(pubkeyHeader->KeyType, 2) + .hexarg2(pubkeyHeader->Version, 2) + .hexarg2(pubkeyHeader->Algorithm, 8) + .hexarg2(pubkeyHeader->BitLength, 8) + .hexarg2(pubkeyHeader->Exponent, 8); + + // Add correct offset + pdata.offset = parentOffset; + + // Add tree item + index = model->addItem(Types::SlicPubkey, 0, name, QString(), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), parent); + } + else if (*(const UINT64*)(store.constData() + 26) == OEM_ACTIVATION_MARKER_WINDOWS_FLAG) { // SLIC marker + if (dataSize < sizeof(OEM_ACTIVATION_MARKER)) { + msg(QObject::tr("parseStoreHeader: volume body is too small even for SLIC marker header"), parent); + return ERR_SUCCESS; + } + + // Get SLIC marker header + const OEM_ACTIVATION_MARKER* markerHeader = (const OEM_ACTIVATION_MARKER*)signature; + + // Check store size + if (dataSize < markerHeader->Size) { + msg(QObject::tr("parseStoreHeader: SLIC marker size %1h (%2) is greater than volume body size %3h (%4)") + .hexarg(markerHeader->Size).arg(markerHeader->Size) + .hexarg(dataSize).arg(dataSize), parent); + return ERR_SUCCESS; + } + + // Get parsing data + PARSING_DATA pdata = parsingDataFromQModelIndex(parent); + + // Construct header and body + QByteArray header = store.left(sizeof(OEM_ACTIVATION_MARKER)); + + // Add info + QString name = QObject::tr("SLIC marker"); + QString info = QObject::tr("Type: 1h\nFull size: %1h (%2)\nHeader size: %3h (%4)\nBody size: 0h (0)\n" + "Version :%5h\nOEM ID: %6\nOEM table ID: %7\nWindows flag: WINDOWS\nSLIC version: %8h") + .hexarg(markerHeader->Size).arg(markerHeader->Size) + .hexarg(header.size()).arg(header.size()) + .hexarg2(markerHeader->Version, 8) + .arg(QLatin1String((const char*)&(markerHeader->OemId), sizeof(markerHeader->OemId))) + .arg(QLatin1String((const char*)&(markerHeader->OemTableId), sizeof(markerHeader->OemTableId))) + .hexarg2(markerHeader->SlicVersion, 8); + + // Add correct offset + pdata.offset = parentOffset; + + // Add tree item + index = model->addItem(Types::SlicMarker, 0, name, QString(), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), parent); + } + else if (*signature == INTEL_MICROCODE_HEADER_VERSION) { // Intel microcode, , must be checked after SLIC marker because of the same *signature values + if (dataSize < sizeof(INTEL_MICROCODE_HEADER)) { + msg(QObject::tr("parseStoreHeader: volume body is too small even for Intel microcode header"), parent); + return ERR_SUCCESS; + } + + // Get Intel microcode header + const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)signature; + + // Check store size + if (dataSize < ucodeHeader->TotalSize) { + msg(QObject::tr("parseStoreHeader: Intel microcode size %1h (%2) is greater than volume body size %3h (%4)") + .hexarg(ucodeHeader->TotalSize).arg(ucodeHeader->TotalSize) + .hexarg(dataSize).arg(dataSize), parent); + return ERR_SUCCESS; + } + + // Get parsing data + PARSING_DATA pdata = parsingDataFromQModelIndex(parent); + + // Construct header and body + QByteArray header = store.left(sizeof(INTEL_MICROCODE_HEADER)); + QByteArray body = store.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize); + + // Add info + QString name = QObject::tr("Intel microcode"); + QString info = QObject::tr("Revision: 1h\nFull size: %1h (%2)\nHeader size: %3h (%4)\nBody size: %5h (%6)\n" + "Date: %7\nCPU signature: %8h\nChecksum: %9h\nLoader revision: %10h\nCPU flags: %11h") + .hexarg(ucodeHeader->TotalSize).arg(ucodeHeader->TotalSize) + .hexarg(header.size()).arg(header.size()) + .hexarg(body.size()).arg(body.size()) + .hexarg2(ucodeHeader->Date, 8) + .hexarg2(ucodeHeader->CpuSignature, 8) + .hexarg2(ucodeHeader->Checksum, 8) + .hexarg2(ucodeHeader->LoaderRevision, 8) + .hexarg2(ucodeHeader->CpuFlags, 8); + + // Add correct offset + pdata.offset = parentOffset; + + // Add tree item + index = model->addItem(Types::Microcode, Subtypes::IntelMicrocode, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); + } return ERR_SUCCESS; } @@ -4187,20 +4404,29 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index) // Check variable size variableSize = sizeof(EVSA_ENTRY_HEADER); if (unparsedSize < variableSize || unparsedSize < entryHeader->Size) { - // Last variable is bad, add the rest as padding and return QByteArray body = data.mid(offset); QString info = QObject::tr("Full size: %1h (%2)") .hexarg(body.size()).arg(body.size()); + // Check type + QString name = QObject::tr("Free space"); + UINT8 type = Types::FreeSpace; + UINT8 subtype = 0; + if (getPaddingType(body) == Subtypes::DataPadding) { + name = QObject::tr("Padding"); + type = Types::Padding; + subtype = Subtypes::DataPadding; + } + // Add correct offset to parsing data pdata.offset = parentOffset + offset; // Add free space tree item - model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); - + QModelIndex itemIndex = model->addItem(type, subtype, name, QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); + // Show message - if (unparsedSize < entryHeader->Size) - msg(QObject::tr("parseEvsaStoreBody: next variable appears too big, added as padding"), index); + if (type == Types::Padding) + msg(QObject::tr("parseEvsaStoreBody: variable parsing failed, rest of unparsed store added as padding"), itemIndex); break; } @@ -4251,15 +4477,25 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index) // Data entry else if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA1 || entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA2 || - entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA3) { + entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID) { const EVSA_DATA_ENTRY* dataHeader = (const EVSA_DATA_ENTRY*)entryHeader; - header = data.mid(offset, sizeof(EVSA_DATA_ENTRY)); - body = data.mid(offset + sizeof(EVSA_DATA_ENTRY), dataHeader->Header.Size - sizeof(EVSA_DATA_ENTRY)); + // Check for extended header + UINT32 headerSize = sizeof(EVSA_DATA_ENTRY); + UINT32 dataSize = dataHeader->Header.Size - sizeof(EVSA_DATA_ENTRY); + if (dataHeader->Attributes & NVRAM_EVSA_DATA_ATTRIBUTE_EXTENDED_HEADER) { + const EVSA_DATA_ENTRY_EXTENDED* dataHeaderExtended = (const EVSA_DATA_ENTRY_EXTENDED*)entryHeader; + headerSize = sizeof(EVSA_DATA_ENTRY_EXTENDED); + dataSize = dataHeaderExtended->DataSize; + variableSize = headerSize + dataSize; + } + + header = data.mid(offset, headerSize); + body = data.mid(offset + headerSize, dataSize); name = QObject::tr("Data"); info = QObject::tr("Full size: %1h (%2)\nHeader size %3h (%4)\nBody size: %5h (%6)\nType: %7h\nChecksum: %8\nVarId: %9h\nGuidId: %10h\nAttributes: %11h") .hexarg(variableSize).arg(variableSize) - .hexarg(header.size()).arg(header.size()) - .hexarg(body.size()).arg(body.size()) + .hexarg(headerSize).arg(headerSize) + .hexarg(dataSize).arg(dataSize) .hexarg2(dataHeader->Header.Type, 2) .arg(dataHeader->Header.Checksum == calculated ? QObject::tr("%1h, valid").hexarg2(calculated, 2) : @@ -4269,20 +4505,32 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index) .hexarg2(dataHeader->Attributes, 8); subtype = Subtypes::DataEvsaEntry; } - // Unknown entry + // Unknown entry or free space else { - header = data.mid(offset, sizeof(EVSA_ENTRY_HEADER)); - body = data.mid(offset + sizeof(EVSA_ENTRY_HEADER), entryHeader->Size - sizeof(EVSA_ENTRY_HEADER)); - name = QObject::tr("Unknown"); - info = QObject::tr("Full size: %1h (%2)\nHeader size %3h (%4)\nBody size: %5h (%6)\nType: %7h\nChecksum: %8") - .hexarg(variableSize).arg(variableSize) - .hexarg(header.size()).arg(header.size()) - .hexarg(body.size()).arg(body.size()) - .hexarg2(entryHeader->Type, 2) - .arg(entryHeader->Checksum == calculated ? - QObject::tr("%1h, valid").hexarg2(calculated, 2) : - QObject::tr("%1h, invalid, should be %2h").hexarg2(entryHeader->Checksum, 2).hexarg2(calculated, 2)); - subtype = Subtypes::UnknownEvsaEntry; + QByteArray body = data.mid(offset); + QString info = QObject::tr("Full size: %1h (%2)") + .hexarg(body.size()).arg(body.size()); + + // Check type + QString name = QObject::tr("Free space"); + UINT8 type = Types::FreeSpace; + UINT8 subtype = 0; + if (getPaddingType(body) == Subtypes::DataPadding) { + name = QObject::tr("Padding"); + type = Types::Padding; + subtype = Subtypes::DataPadding; + } + + // Add correct offset to parsing data + pdata.offset = parentOffset + offset; + + // Add free space tree item + QModelIndex itemIndex = model->addItem(type, subtype, name, QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); + + // Show message + if (type == Types::Padding) + msg(QObject::tr("parseEvsaStoreBody: unknown variable of type %1h found at offset %2h, the rest of unparsed store added as padding").hexarg2(entryHeader->Type, 2).hexarg(offset), itemIndex); + break; } // Add correct offset to parsing data @@ -4326,7 +4574,13 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index) msg(QObject::tr("parseEvsaStoreBody: data variable with invalid VarId"), current); } else { // Variable is OK, rename it - model->setName(current, guid); + if (dataHeader->Header.Type == NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID) { + model->setSubtype(current, Subtypes::InvalidEvsaEntry); + model->setName(current, QObject::tr("Invalid")); + } + else { + model->setName(current, guid); + } model->setText(current, name); } } @@ -4381,10 +4635,10 @@ STATUS FfsParser::parseFlashMapBody(const QModelIndex & index) QByteArray header = data.mid(offset, sizeof(PHOENIX_FLASH_MAP_ENTRY)); // Add info - QString info = QObject::tr("Entry GUID: %1\nFull size: 24h (36)\nHeader size %2h (%3)\nBody size: 0h (0)\nType %4h\nMemory address: %5h\nSize: %6h\nOffset: %7h") + QString info = QObject::tr("Entry GUID: %1\nFull size: 24h (36)\nHeader size: 24h (36)\nBody size: 0h (0)\nEntry type: %2h\nData type: %3h\nMemory address: %4h\nSize: %5h\nOffset: %6h") .arg(name) - .hexarg(header.size()).arg(header.size()) - .hexarg2(entryHeader->Type, 8) + .hexarg2(entryHeader->EntryType, 4) + .hexarg2(entryHeader->DataType, 4) .hexarg2(entryHeader->PhysicalAddress, 8) .hexarg2(entryHeader->Size, 8) .hexarg2(entryHeader->Offset, 8); @@ -4392,8 +4646,19 @@ STATUS FfsParser::parseFlashMapBody(const QModelIndex & index) // Add correct offset to parsing data pdata.offset = parentOffset + offset; + // Determine subtype + UINT8 subtype = 0; + switch (entryHeader->DataType) { + case NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_VOLUME: + subtype = Subtypes::VolumeFlashMapEntry; + break; + case NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_DATA_BLOCK: + subtype = Subtypes::DataBlockFlashMapEntry; + break; + } + // Add tree item - model->addItem(Types::NvramEntryFlashMap, 0, name, QString(), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), index); + model->addItem(Types::NvramEntryFlashMap, subtype, name, flashMapGuidToQString(entryHeader->Guid), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), index); // Move to next variable offset += sizeof(PHOENIX_FLASH_MAP_ENTRY); diff --git a/common/ffsparser.h b/common/ffsparser.h index f070029..d852b15 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -39,13 +39,13 @@ class FfsParser { public: // Default constructor and destructor - FfsParser(TreeModel* treeModel); - ~FfsParser(); + FfsParser(TreeModel* treeModel) : model(treeModel), capsuleOffsetFixup(0) {} + ~FfsParser() {} // Returns messages - std::vector > getMessages() const; + std::vector > getMessages() const { return messagesVector; } // Clears messages - void clearMessages(); + void clearMessages() { messagesVector.clear(); } // Firmware image parsing STATUS parse(const QByteArray &buffer); @@ -119,7 +119,9 @@ private: STATUS parseFlashMapBody(const QModelIndex & index); // Message helper - void msg(const QString & message, const QModelIndex &index = QModelIndex()); + void msg(const QString & message, const QModelIndex &index = QModelIndex()) { + messagesVector.push_back(std::pair(message, index)); + }; }; #endif // FFSPARSER_H diff --git a/common/fit.h b/common/fit.h index 2c5e7bc..1be4815 100644 --- a/common/fit.h +++ b/common/fit.h @@ -61,6 +61,10 @@ typedef struct INTEL_MICROCODE_HEADER_ { UINT8 Reserved[12]; } INTEL_MICROCODE_HEADER; +#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)) + #pragma pack(pop) #endif // FIT_H diff --git a/common/fitparser.cpp b/common/fitparser.cpp index 9dd81ab..94f1d96 100644 --- a/common/fitparser.cpp +++ b/common/fitparser.cpp @@ -11,31 +11,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */ #include "fitparser.h" - -FitParser::FitParser(TreeModel* treeModel) - : model(treeModel) -{ -} - -FitParser::~FitParser() -{ -} - -void FitParser::msg(const QString & message, const QModelIndex & index) -{ - messagesVector.push_back(std::pair(message, index)); -} - -std::vector > FitParser::getMessages() const -{ - return messagesVector; -} - -void FitParser::clearMessages() -{ - messagesVector.clear(); -} - STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIndex) { // Check sanity diff --git a/common/fitparser.h b/common/fitparser.h index 232b11f..f9cbad7 100644 --- a/common/fitparser.h +++ b/common/fitparser.h @@ -32,13 +32,13 @@ class FitParser { public: // Default constructor and destructor - FitParser(TreeModel* treeModel); - ~FitParser(); + FitParser(TreeModel* treeModel) : model(treeModel) {} + ~FitParser() {} // Returns messages - std::vector > getMessages() const; + std::vector > getMessages() const { return messagesVector; }; // Clears messages - void clearMessages(); + void clearMessages() { messagesVector.clear(); } STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf); std::vector > getFitTable() const { return fitTable; } @@ -53,7 +53,9 @@ private: QString fitEntryTypeToQString(UINT8 type); // Message helper - void msg(const QString & message, const QModelIndex &index = QModelIndex()); + void msg(const QString & message, const QModelIndex &index = QModelIndex()) { + messagesVector.push_back(std::pair(message, index)); + } }; #endif // FITPARSER_H diff --git a/common/nvram.cpp b/common/nvram.cpp index b3cd8eb..59a5d72 100644 --- a/common/nvram.cpp +++ b/common/nvram.cpp @@ -52,3 +52,30 @@ QString efiTimeToQString(const EFI_TIME & time) .arg(time.Second, 2, 10, QLatin1Char('0')) .arg(time.Nanosecond); } + +QString flashMapGuidToQString(const EFI_GUID & guid) +{ + const QByteArray baGuid((const char*)&guid, sizeof(EFI_GUID)); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_VOLUME_HEADER) + return QObject::tr("Volume header"); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_MICROCODES_GUID) + return QObject::tr("Microcodes"); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_CMDB_GUID) + return QObject::tr("CMDB"); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_PUBKEY1_GUID || baGuid == NVRAM_PHOENIX_FLASH_MAP_PUBKEY2_GUID) + return QObject::tr("SLIC pubkey"); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_MARKER1_GUID || baGuid == NVRAM_PHOENIX_FLASH_MAP_MARKER2_GUID) + return QObject::tr("SLIC marker"); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA1_GUID || + baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA2_GUID || + baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA3_GUID || + baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA4_GUID || + baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA5_GUID || + baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID || + baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID) + return QObject::tr("EVSA store"); + if (baGuid == NVRAM_PHOENIX_FLASH_MAP_SELF_GUID) + return QObject::tr("Flash map"); + return QString(); +} + diff --git a/common/nvram.h b/common/nvram.h index 7fc72df..8f15e6a 100644 --- a/common/nvram.h +++ b/common/nvram.h @@ -19,8 +19,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include "basetypes.h" +// Make sure we use right packing rules +#pragma pack(push, 1) + // -// NVAR store +// NVAR store and variables // // CEF5B9A3-476D-497F-9FDC-E98143E0422C @@ -35,9 +38,6 @@ extern QString nvarAttributesToQString(const UINT8 attributes); extern QString efiTimeToQString(const EFI_TIME & time); -// Make sure we use right packing rules -#pragma pack(push, 1) - // Variable header typedef struct NVAR_VARIABLE_HEADER_ { UINT32 Signature; // NVAR @@ -67,7 +67,7 @@ typedef struct NVAR_VARIABLE_HEADER_ { // -// TianoCore VSS and it's variations +// TianoCore VSS store and variables // // FFF12B8D-7696-4C8B-A985-2747075B4F50 @@ -158,9 +158,10 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ { #define NVRAM_VSS_VARIABLE_APPEND_WRITE 0x00000040 #define NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM 0x80000000 -// FDC region can be found in Insyde VSS volumes -// It has another VSS volume inside -// _FDC header structure +// +// FDC region +// + #define NVRAM_FDC_VOLUME_SIGNATURE 0x4344465F typedef struct FDC_VOLUME_HEADER_ { @@ -171,8 +172,9 @@ typedef struct FDC_VOLUME_HEADER_ { //VSS_VARIABLE_STORE_HEADER VssHeader; } FDC_VOLUME_HEADER; +// // FTW block -// EFI Fault tolerant working block header +// #define EFI_FAULT_TOLERANT_WORKING_BLOCK_VALID 0x1 #define EFI_FAULT_TOLERANT_WORKING_BLOCK_INVALID 0x2 @@ -202,7 +204,7 @@ typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64_ { } EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64; // -// Apple Fsys +// Apple Fsys store // typedef struct APPLE_FSYS_STORE_HEADER_ { @@ -221,7 +223,7 @@ typedef struct APPLE_FSYS_STORE_HEADER_ { // Has CRC32 of the whole store without checksum field at the end // -// EVSA +// EVSA store and variables // #define NVRAM_EVSA_STORE_SIGNATURE 0x41535645 @@ -233,7 +235,7 @@ typedef struct APPLE_FSYS_STORE_HEADER_ { #define NVRAM_EVSA_ENTRY_TYPE_NAME2 0xE2 #define NVRAM_EVSA_ENTRY_TYPE_DATA1 0xEF #define NVRAM_EVSA_ENTRY_TYPE_DATA2 0xE3 -#define NVRAM_EVSA_ENTRY_TYPE_DATA3 0x83 +#define NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID 0x83 typedef struct EVSA_ENTRY_HEADER_ { UINT8 Type; @@ -269,6 +271,16 @@ typedef struct EVSA_DATA_ENTRY_ { //UINT8 Data[]; } EVSA_DATA_ENTRY; +#define NVRAM_EVSA_DATA_ATTRIBUTE_EXTENDED_HEADER 0x10000000 + +typedef struct EVSA_DATA_ENTRY_EXTENDED { + EVSA_ENTRY_HEADER Header; + UINT16 GuidId; + UINT16 VarId; + UINT32 Attributes; + UINT32 DataSize; + //UINT8 Data[]; +} EVSA_DATA_ENTRY_EXTENDED; // // Phoenix SCT Flash Map @@ -289,15 +301,130 @@ typedef struct PHOENIX_FLASH_MAP_HEADER_ { typedef struct PHOENIX_FLASH_MAP_ENTRY_ { EFI_GUID Guid; - UINT32 Type; + UINT16 DataType; + UINT16 EntryType; UINT64 PhysicalAddress; UINT32 Size; UINT32 Offset; } PHOENIX_FLASH_MAP_ENTRY; +#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_VOLUME 0x0000 +#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_DATA_BLOCK 0x0001 +extern QString flashMapGuidToQString(const EFI_GUID & guid); +// B091E7D2-05A0-4198-94F0-74B7B8C55459 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_VOLUME_HEADER +("\xD2\xE7\x91\xB0\xA0\x05\x98\x41\x94\xF0\x74\xB7\xB8\xC5\x54\x59", 16); +// FD3F690E-B4B0-4D68-89DB-19A1A3318F90 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_MICROCODES_GUID +("\x0E\x69\x3F\xFD\xB0\xB4\x68\x4D\x89\xDB\x19\xA1\xA3\x31\x8F\x90", 16); + +// 46310243-7B03-4132-BE44-2243FACA7CDD +const QByteArray NVRAM_PHOENIX_FLASH_MAP_CMDB_GUID +("\x43\x02\x31\x46\x03\x7B\x32\x41\xBE\x44\x22\x43\xFA\xCA\x7C\xDD", 16); + +// 1B2C4952-D778-4B64-BDA1-15A36F5FA545 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_PUBKEY1_GUID +("\x52\x49\x2C\x1B\x78\xD7\x64\x4B\xBD\xA1\x15\xA3\x6F\x5F\xA5\x45", 16); + +// 127C1C4E-9135-46E3-B006-F9808B0559A5 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_MARKER1_GUID +("\x4E\x1C\x7C\x12\x35\x91\xE3\x46\xB0\x06\xF9\x80\x8B\x05\x59\xA5", 16); + +// 7CE75114-8272-45AF-B536-761BD38852CE +const QByteArray NVRAM_PHOENIX_FLASH_MAP_PUBKEY2_GUID +("\x14\x51\xE7\x7C\x72\x82\xAF\x45\xB5\x36\x76\x1B\xD3\x88\x52\xCE", 16); + +// 071A3DBE-CFF4-4B73-83F0-598C13DCFDD5 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_MARKER2_GUID +("\xBE\x3D\x1A\x07\xF4\xCF\x73\x4B\x83\xF0\x59\x8C\x13\xDC\xFD\xD5", 16); + +// FACFB110-7BFD-4EFB-873E-88B6B23B97EA +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA1_GUID +("\x10\xB1\xCF\xFA\xFD\x7B\xFB\x4E\x87\x3E\x88\xB6\xB2\x3B\x97\xEA", 16); + +// E68DC11A-A5F4-4AC3-AA2E-29E298BFF645 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA2_GUID +("\x1A\xC1\x8D\xE6\xF4\xA5\xC3\x4A\xAA\x2E\x29\xE2\x98\xBF\xF6\x45", 16); + +// 4B3828AE-0ACE-45B6-8CDB-DAFC28BBF8C5 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA3_GUID +("\xAE\x28\x38\x4B\xCE\x0A\xB6\x45\x8C\xDB\xDA\xFC\x28\xBB\xF8\xC5", 16); + +// C22E6B8A-8159-49A3-B353-E84B79DF19C0 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA4_GUID +("\x8A\x6B\x2E\xC2\x59\x81\xA3\x49\xB3\x53\xE8\x4B\x79\xDF\x19\xC0", 16); + +// B6B5FAB9-75C4-4AAE-8314-7FFFA7156EAA +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA5_GUID +("\xB9\xFA\xB5\xB6\xC4\x75\xAE\x4A\x83\x14\x7F\xFF\xA7\x15\x6E\xAA", 16); + +// 919B9699-8DD0-4376-AA0B-0E54CCA47D8F +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID +("\x99\x96\x9B\x91\xD0\x8D\x76\x43\xAA\x0B\x0E\x54\xCC\xA4\x7D\x8F", 16); + +// 58A90A52-929F-44F8-AC35-A7E1AB18AC91 +const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID +("\x52\x0A\xA9\x58\x9F\x92\xF8\x44\xAC\x35\xA7\xE1\xAB\x18\xAC\x91", 16); + +// 8CB71915-531F-4AF5-82BF-A09140817BAA +const QByteArray NVRAM_PHOENIX_FLASH_MAP_SELF_GUID +("\x15\x19\xB7\x8C\x1F\x53\xF5\x4A\x82\xBF\xA0\x91\x40\x81\x7B\xAA", 16); + +// +// SLIC pubkey and marker +// + +typedef struct OEM_ACTIVATION_PUBKEY_ { + UINT32 Type; // 0 + UINT32 Size; // 0x9C + UINT8 KeyType; + UINT8 Version; + UINT16 Reserved; + UINT32 Algorithm; + UINT32 Magic; // RSA1 + UINT32 BitLength; + UINT32 Exponent; + UINT8 Modulus[128]; +} OEM_ACTIVATION_PUBKEY; + +#define OEM_ACTIVATION_PUBKEY_TYPE 0x00000000 +#define OEM_ACTIVATION_PUBKEY_MAGIC 0x31415352 // RSA1 + +typedef struct OEM_ACTIVATION_MARKER_ { + UINT32 Type; // 1 + UINT32 Size; // 0xB6 + UINT32 Version; + UINT8 OemId[6]; + UINT8 OemTableId[8]; + UINT64 WindowsFlag; + UINT32 SlicVersion; + UINT8 Reserved[16]; + UINT8 Signature[128]; +} OEM_ACTIVATION_MARKER; + +#define OEM_ACTIVATION_MARKER_TYPE 0x00000001 +#define OEM_ACTIVATION_MARKER_WINDOWS_FLAG_PART1 0x444E4957 +#define OEM_ACTIVATION_MARKER_WINDOWS_FLAG 0x2053574F444E4957UL +#define OEM_ACTIVATION_MARKER_RESERVED_BYTE 0x00 + +// +// Phoenix CMDB, no londer used, requires no parsing +// + +typedef struct PHOENIX_CMDB_HEADER_ { + UINT32 Signature; // CMDB + UINT32 HeaderSize; // Size of this header + UINT32 TotalSize; // Total size of header and chunks, without strings + // UINT8 StartChunk[3]; + // UINT8 StringChunk[5][x]; + // C_STR Strings[2*x + 1]; +} PHOENIX_CMDB_HEADER; + +#define NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE 0x42444D43 +#define NVRAM_PHOENIX_CMDB_SIZE 0x100; // Restore previous packing rules #pragma pack(pop) diff --git a/common/types.cpp b/common/types.cpp index a05018d..e413229 100644 --- a/common/types.cpp +++ b/common/types.cpp @@ -75,6 +75,8 @@ QString itemTypeToQString(const UINT8 type) return QObject::tr("EVSA store"); case Types::NvramStoreFtw: return QObject::tr("FTW store"); + case Types::NvramStoreCmdb: + return QObject::tr("CMDB store"); case Types::NvramStoreFlashMap: return QObject::tr("FlashMap store"); case Types::NvramVariableNvar: @@ -87,6 +89,12 @@ QString itemTypeToQString(const UINT8 type) return QObject::tr("EVSA entry"); case Types::NvramEntryFlashMap: return QObject::tr("FlashMap entry"); + case Types::Microcode: + return QObject::tr("Microcode"); + case Types::SlicPubkey: + return QObject::tr("SLIC pubkey"); + case Types::SlicMarker: + return QObject::tr("SLIC marker"); default: return QObject::tr("Unknown"); } @@ -96,61 +104,58 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) { switch (type) { case Types::Root: - case Types::Image: - if (subtype == Subtypes::IntelImage) - return QObject::tr("Intel"); - else if (Subtypes::UefiImage) - return QObject::tr("UEFI"); - else - return QObject::tr("Unknown subtype"); - case Types::Padding: - if (subtype == Subtypes::ZeroPadding) - return QObject::tr("Empty (0x00)"); - else if (subtype == Subtypes::OnePadding) - return QObject::tr("Empty (0xFF)"); - else if (subtype == Subtypes::DataPadding) - return QObject::tr("Non-empty"); - else - return QObject::tr("Unknown subtype"); - case Types::Volume: - if (subtype == Subtypes::UnknownVolume) - return QObject::tr("Unknown"); - else if (subtype == Subtypes::Ffs2Volume) - return QObject::tr("FFSv2"); - else if (subtype == Subtypes::Ffs3Volume) - return QObject::tr("FFSv3"); - else if (subtype == Subtypes::NvramVolume) - return QObject::tr("NVRAM"); - else - return QObject::tr("Unknown subtype"); - case Types::Capsule: - if (subtype == Subtypes::AptioSignedCapsule) - return QObject::tr("Aptio signed"); - else if (subtype == Subtypes::AptioUnsignedCapsule) - return QObject::tr("Aptio unsigned"); - else if (subtype == Subtypes::UefiCapsule) - return QObject::tr("UEFI 2.0"); - else if (subtype == Subtypes::ToshibaCapsule) - return QObject::tr("Toshiba"); - else - return QObject::tr("Unknown subtype"); - case Types::Region: - return regionTypeToQString(subtype); - case Types::File: - return fileTypeToQString(subtype); - case Types::Section: - return sectionTypeToQString(subtype); case Types::FreeSpace: - return QString(); case Types::NvramStoreVss: case Types::NvramStoreFdc: case Types::NvramStoreFsys: case Types::NvramStoreEvsa: case Types::NvramStoreFtw: case Types::NvramStoreFlashMap: + case Types::NvramStoreCmdb: case Types::NvramEntryFsys: - case Types::NvramEntryFlashMap: + case Types::SlicPubkey: + case Types::SlicMarker: return QString(); + case Types::Image: + if (subtype == Subtypes::IntelImage) + return QObject::tr("Intel"); + if (Subtypes::UefiImage) + return QObject::tr("UEFI"); + break; + case Types::Padding: + if (subtype == Subtypes::ZeroPadding) + return QObject::tr("Empty (0x00)"); + if (subtype == Subtypes::OnePadding) + return QObject::tr("Empty (0xFF)"); + if (subtype == Subtypes::DataPadding) + return QObject::tr("Non-empty"); + break; + case Types::Volume: + if (subtype == Subtypes::UnknownVolume) + return QObject::tr("Unknown"); + if (subtype == Subtypes::Ffs2Volume) + return QObject::tr("FFSv2"); + if (subtype == Subtypes::Ffs3Volume) + return QObject::tr("FFSv3"); + if (subtype == Subtypes::NvramVolume) + return QObject::tr("NVRAM"); + break; + case Types::Capsule: + if (subtype == Subtypes::AptioSignedCapsule) + return QObject::tr("Aptio signed"); + if (subtype == Subtypes::AptioUnsignedCapsule) + return QObject::tr("Aptio unsigned"); + if (subtype == Subtypes::UefiCapsule) + return QObject::tr("UEFI 2.0"); + if (subtype == Subtypes::ToshibaCapsule) + return QObject::tr("Toshiba"); + break; + case Types::Region: + return regionTypeToQString(subtype); + case Types::File: + return fileTypeToQString(subtype); + case Types::Section: + return sectionTypeToQString(subtype); case Types::NvramVariableNvar: if (subtype == Subtypes::InvalidNvarVariable) return QObject::tr("Invalid"); @@ -162,8 +167,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) return QObject::tr("Data"); if (subtype == Subtypes::FullNvarVariable) return QObject::tr("Full"); - else - return QObject::tr("Unknown subtype"); + break; case Types::NvramVariableVss: if (subtype == Subtypes::InvalidVssVariable) return QObject::tr("Invalid"); @@ -173,8 +177,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) return QObject::tr("Apple CRC32"); if (subtype == Subtypes::AuthVssVariable) return QObject::tr("Auth"); - else - return QObject::tr("Unknown subtype"); + break; case Types::NvramEntryEvsa: if (subtype == Subtypes::InvalidEvsaEntry) return QObject::tr("Invalid"); @@ -186,11 +189,22 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) return QObject::tr("Name"); if (subtype == Subtypes::DataEvsaEntry) return QObject::tr("Data"); - else - return QObject::tr("Unknown subtype"); - default: - return QObject::tr("Unknown subtype"); + break; + case Types::NvramEntryFlashMap: + if (subtype == Subtypes::VolumeFlashMapEntry) + return QObject::tr("Volume"); + if (subtype == Subtypes::DataBlockFlashMapEntry) + return QObject::tr("Data block"); + break; + case Types::Microcode: + if (subtype == Subtypes::IntelMicrocode) + return QObject::tr("Intel"); + if (subtype == Subtypes::AmdMicrocode) + return QObject::tr("AMD"); + break; } + + return QObject::tr("Unknown subtype"); } QString compressionTypeToQString(const UINT8 algorithm) diff --git a/common/types.h b/common/types.h index 20cf0d5..ad887b1 100644 --- a/common/types.h +++ b/common/types.h @@ -49,11 +49,15 @@ namespace Types { NvramStoreEvsa, NvramStoreFlashMap, NvramStoreFtw, + NvramStoreCmdb, NvramVariableNvar, NvramVariableVss, NvramEntryFsys, NvramEntryEvsa, NvramEntryFlashMap, + Microcode, + SlicPubkey, + SlicMarker, }; } @@ -118,6 +122,16 @@ namespace Subtypes { NameEvsaEntry, DataEvsaEntry, }; + + enum FlashMapEntrySubtypes { + VolumeFlashMapEntry = 160, + DataBlockFlashMapEntry + }; + + enum MicrocodeSubtypes { + IntelMicrocode = 170, + AmdMicrocode + }; }; // *ToQString conversion routines