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
This commit is contained in:
Nikolaj Schlej 2016-04-14 20:36:59 +02:00
parent 1100cead24
commit c0a5cd0c0f
14 changed files with 611 additions and 220 deletions

View File

@ -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<QString, QModelIndex>(message, index));
}
std::vector<std::pair<QString, QModelIndex> > 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())

View File

@ -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<std::pair<QString, QModelIndex> > getMessages() const;
void clearMessages();
std::vector<std::pair<QString, QModelIndex> > 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<std::pair<QString, QModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex());
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
}
};
#endif // FFSFINDER_H

View File

@ -175,7 +175,8 @@ void UEFITool::populateUi(const QModelIndex &current)
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;
}

View File

@ -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<QString, QModelIndex>(message, index));
}
std::vector<std::pair<QString, QModelIndex> > FfsBuilder::getMessages() const
{
return messagesVector;
}
void FfsBuilder::clearMessages()
{
messagesVector.clear();
}
STATUS FfsBuilder::erase(const QModelIndex & index, QByteArray & erased)
{
// Sanity check

View File

@ -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<std::pair<QString, QModelIndex> > getMessages() const;
void clearMessages();
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; }
void clearMessages() { messagesVector.clear(); }
STATUS build(const QModelIndex & root, QByteArray & image);
private:
const TreeModel* model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex());
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
}
STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule);
STATUS buildIntelImage(const QModelIndex & index, QByteArray & intelImage);

View File

@ -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<QString, QModelIndex>(message, index));
}
std::vector<std::pair<QString, QModelIndex> > 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);

View File

@ -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<std::pair<QString, QModelIndex> > getMessages() const;
std::vector<std::pair<QString, QModelIndex> > 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<QString, QModelIndex>(message, index));
};
};
#endif // FFSPARSER_H

View File

@ -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

View File

@ -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<QString, QModelIndex>(message, index));
}
std::vector<std::pair<QString, QModelIndex> > FitParser::getMessages() const
{
return messagesVector;
}
void FitParser::clearMessages()
{
messagesVector.clear();
}
STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIndex)
{
// Check sanity

View File

@ -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<std::pair<QString, QModelIndex> > getMessages() const;
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; };
// Clears messages
void clearMessages();
void clearMessages() { messagesVector.clear(); }
STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf);
std::vector<std::vector<QString> > 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<QString, QModelIndex>(message, index));
}
};
#endif // FITPARSER_H

View File

@ -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();
}

View File

@ -19,8 +19,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QString>
#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)

View File

@ -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)

View File

@ -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