mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-21 23:48:22 +08:00
A45
+ FFSv3 support with large files and large sections + proper names for Flash Descriptor v2 regions (#89) + better alignment calculations (#96) + improved NVRAM parser + post IBB hash support for Boot Guard + bugfixes + companion tool updated
This commit is contained in:
parent
02369442a2
commit
63088afd87
@ -19,6 +19,7 @@ SET(PROJECT_SOURCES
|
||||
../common/LZMA/SDK/C/LzmaDec.c
|
||||
../common/Tiano/EfiTianoDecompress.c
|
||||
../common/ustring.cpp
|
||||
../common/sha256.c
|
||||
../common/bstrlib/bstrlib.c
|
||||
../common/bstrlib/bstrwrap.cpp
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* uefidump_main.cpp
|
||||
|
||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
||||
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
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
|
||||
@ -29,7 +29,7 @@ int main(int argc, char *argv[])
|
||||
return (uefidumper.dump(buffer, UString(argv[1])) != U_SUCCESS);
|
||||
}
|
||||
|
||||
std::cout << "UEFIDump 0.1.5" << std::endl << std::endl
|
||||
std::cout << "UEFIDump 0.1.6" << std::endl << std::endl
|
||||
<< "Usage: UEFIDump imagefile" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ SOURCES += \
|
||||
../common/LZMA/SDK/C/LzmaDec.c \
|
||||
../common/Tiano/EfiTianoDecompress.c \
|
||||
../common/ustring.cpp
|
||||
../common/sha256.c
|
||||
|
||||
HEADERS += \
|
||||
ffsdumper.h \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* uefiextract_main.cpp
|
||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
||||
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
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
|
||||
@ -20,8 +20,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
a.setOrganizationName("CodeRush");
|
||||
a.setOrganizationDomain("coderush.me");
|
||||
a.setOrganizationName("LongSoft");
|
||||
a.setOrganizationDomain("longsoft.me");
|
||||
a.setApplicationName("UEFIExtract");
|
||||
|
||||
if (a.arguments().length() > 32) {
|
||||
@ -63,17 +63,17 @@ int main(int argc, char *argv[])
|
||||
// Get last VTF
|
||||
std::vector<std::pair<std::vector<QString>, QModelIndex > > fitTable = ffsParser.getFitTable();
|
||||
if (fitTable.size()) {
|
||||
std::cout << "---------------------------------------------------------------------------" << std::endl;
|
||||
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
|
||||
std::cout << "---------------------------------------------------------------------------" << std::endl;
|
||||
for (size_t i = 0; i < fitTable.size(); i++) {
|
||||
std::cout << fitTable[i].first[0].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[1].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[2].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[3].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[4].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[5].toLatin1().constData() << std::endl;
|
||||
}
|
||||
std::cout << "---------------------------------------------------------------------------" << std::endl;
|
||||
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
|
||||
std::cout << "---------------------------------------------------------------------------" << std::endl;
|
||||
for (size_t i = 0; i < fitTable.size(); i++) {
|
||||
std::cout << fitTable[i].first[0].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[1].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[2].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[3].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[4].toLatin1().constData() << " | "
|
||||
<< fitTable[i].first[5].toLatin1().constData() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ int main(int argc, char *argv[])
|
||||
if (a.arguments().length() == 3 && a.arguments().at(2) == QString("dump")) {
|
||||
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS);
|
||||
}
|
||||
else if (a.arguments().length() > 3 ||
|
||||
else if (a.arguments().length() > 3 ||
|
||||
(a.arguments().length() == 3 && a.arguments().at(2) != QString("all") && a.arguments().at(2) != QString("report"))) { // Dump specific files, without report
|
||||
UINT32 returned = 0;
|
||||
for (int i = 2; i < a.arguments().length(); i++) {
|
||||
@ -94,7 +94,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
return returned;
|
||||
}
|
||||
|
||||
|
||||
// Create ffsReport
|
||||
FfsReport ffsReport(&model);
|
||||
std::vector<QString> report = ffsReport.generate();
|
||||
@ -108,7 +108,7 @@ int main(int argc, char *argv[])
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Dump all non-leaf elements, with report, default
|
||||
if (a.arguments().length() == 2) {
|
||||
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS);
|
||||
@ -121,12 +121,12 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
// If parameters are different, show version and usage information
|
||||
std::cout << "UEFIExtract 0.13.4" << std::endl << std::endl
|
||||
<< "Usage: UEFIExtract imagefile - generate report and dump only leaf tree items into .dump folder." << std::endl
|
||||
<< " UEFIExtract imagefile all - generate report and dump all tree items." << std::endl
|
||||
<< " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl
|
||||
<< " UEFIExtract imagefile report - only generate report, no dump needed." << std::endl
|
||||
<< " UEFIExtract imagefile GUID_1 GUID_2 ... GUID_31 - dump only FFS file(s) with specific GUID(s), without report." << std::endl
|
||||
<< "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise." << std::endl;
|
||||
std::cout << "UEFIExtract 0.13.5" << std::endl << std::endl
|
||||
<< "Usage: UEFIExtract imagefile - generate report and dump only leaf tree items into .dump folder." << std::endl
|
||||
<< " UEFIExtract imagefile all - generate report and dump all tree items." << std::endl
|
||||
<< " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl
|
||||
<< " UEFIExtract imagefile report - only generate report, no dump needed." << std::endl
|
||||
<< " UEFIExtract imagefile GUID_1 GUID_2 ... GUID_31 - dump only FFS file(s) with specific GUID(s), without report." << std::endl
|
||||
<< "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise." << std::endl;
|
||||
return 1;
|
||||
}
|
@ -21,7 +21,8 @@ SOURCES += uefifind_main.cpp \
|
||||
../common/LZMA/LzmaDecompress.c \
|
||||
../common/LZMA/SDK/C/LzmaDec.c \
|
||||
../common/Tiano/EfiTianoDecompress.c \
|
||||
../common/ustring.cpp
|
||||
../common/ustring.cpp \
|
||||
../common/sha256.c
|
||||
|
||||
HEADERS += uefifind.h \
|
||||
../common/guiddatabase.h \
|
||||
@ -41,5 +42,5 @@ HEADERS += uefifind.h \
|
||||
../common/Tiano/EfiTianoDecompress.h \
|
||||
../common/ustring.h \
|
||||
../common/ubytearray.h \
|
||||
../common/bootguard.h \
|
||||
../common/bootguard.h \
|
||||
../common/sha256.h
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* uefifind_main.cpp
|
||||
|
||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
||||
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
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
|
||||
@ -17,8 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
a.setOrganizationName("CodeRush");
|
||||
a.setOrganizationDomain("coderush.me");
|
||||
a.setOrganizationName("LongSoft");
|
||||
a.setOrganizationDomain("longsoft.me");
|
||||
a.setApplicationName("UEFIFind");
|
||||
|
||||
UEFIFind w;
|
||||
@ -148,7 +148,7 @@ int main(int argc, char *argv[])
|
||||
return U_SUCCESS;
|
||||
}
|
||||
else {
|
||||
std::cout << "UEFIFind 0.10.9" << std::endl << std::endl <<
|
||||
std::cout << "UEFIFind 0.10.10" << std::endl << std::endl <<
|
||||
"Usage: UEFIFind {header | body | all} {list | count} pattern imagefile" << std::endl <<
|
||||
" or UEFIFind file patternsfile imagefile" << std::endl;
|
||||
return U_INVALID_PARAMETER;
|
||||
|
@ -17,7 +17,7 @@
|
||||
UEFITool::UEFITool(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::UEFITool),
|
||||
version(tr("NE alpha 44"))
|
||||
version(tr("NE alpha 45"))
|
||||
{
|
||||
clipboard = QApplication::clipboard();
|
||||
|
||||
@ -150,6 +150,10 @@ void UEFITool::init()
|
||||
delete ffsParser;
|
||||
ffsParser = new FfsParser(model);
|
||||
|
||||
// Set proper marking state
|
||||
model->setMarkingEnabled(markingEnabled);
|
||||
ui->actionToggleBootGuardMarking->setChecked(markingEnabled);
|
||||
|
||||
// Connect
|
||||
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
|
||||
this, SLOT(populateUi(const QModelIndex &)));
|
||||
@ -199,7 +203,7 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
||||
|| type == Types::EvsaEntry
|
||||
|| type == Types::FlashMapEntry);
|
||||
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
||||
|| type == Types::LenovoVssStore
|
||||
|| type == Types::Vss2Store
|
||||
|| type == Types::FdcStore
|
||||
|| type == Types::FsysStore
|
||||
|| type == Types::EvsaStore
|
||||
@ -631,7 +635,7 @@ void UEFITool::extract(const UINT8 mode)
|
||||
case Types::EvsaEntry: path = QFileDialog::getSaveFileName(this, tr("Save EVSA entry to file"), name + ".evse", "EVSA entry files (*.evse *.bin);;All files (*)"); break;
|
||||
case Types::FlashMapEntry: path = QFileDialog::getSaveFileName(this, tr("Save FlashMap entry to file"), name + ".fme", "FlashMap entry files (*.fme *.bin);;All files (*)"); break;
|
||||
case Types::VssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break;
|
||||
case Types::LenovoVssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break;
|
||||
case Types::Vss2Store: path = QFileDialog::getSaveFileName(this, tr("Save VSS2 store to file"), name + ".vss2", "VSS2 store files (*.vss2 *.bin);;All files (*)"); break;
|
||||
case Types::FdcStore: path = QFileDialog::getSaveFileName(this, tr("Save FDC store to file"), name + ".fdc", "FDC store files (*.fdc *.bin);;All files (*)"); break;
|
||||
case Types::FsysStore: path = QFileDialog::getSaveFileName(this, tr("Save Fsys store to file"), name + ".fsys", "Fsys store files (*.fsys *.bin);;All files (*)"); break;
|
||||
case Types::EvsaStore: path = QFileDialog::getSaveFileName(this, tr("Save EVSA store to file"), name + ".evsa", "EVSA store files (*.evsa *.bin);;All files (*)"); break;
|
||||
@ -672,7 +676,7 @@ void UEFITool::extract(const UINT8 mode)
|
||||
case Types::FlashMapEntry:
|
||||
case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save entry body to file"), name + ".bin", "Binary files (*.bin);;All files (*)"); break;
|
||||
case Types::VssStore:
|
||||
case Types::LenovoVssStore:
|
||||
case Types::Vss2Store:
|
||||
case Types::FtwStore:
|
||||
case Types::FdcStore:
|
||||
case Types::FsysStore:
|
||||
@ -921,6 +925,7 @@ void UEFITool::clearMessages()
|
||||
void UEFITool::toggleBootGuardMarking(bool enabled)
|
||||
{
|
||||
model->setMarkingEnabled(enabled);
|
||||
markingEnabled = enabled;
|
||||
}
|
||||
|
||||
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
||||
@ -1041,7 +1046,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
||||
case Types::EvsaEntry:
|
||||
case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break;
|
||||
case Types::VssStore:
|
||||
case Types::LenovoVssStore:
|
||||
case Types::Vss2Store:
|
||||
case Types::FdcStore:
|
||||
case Types::FsysStore:
|
||||
case Types::EvsaStore:
|
||||
@ -1069,6 +1074,7 @@ void UEFITool::readSettings()
|
||||
ui->structureTreeView->setColumnWidth(1, settings.value("tree/columnWidth1", ui->structureTreeView->columnWidth(1)).toInt());
|
||||
ui->structureTreeView->setColumnWidth(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
|
||||
ui->structureTreeView->setColumnWidth(3, settings.value("tree/columnWidth3", ui->structureTreeView->columnWidth(3)).toInt());
|
||||
markingEnabled = settings.value("tree/markingEnabled", true).toBool();
|
||||
}
|
||||
|
||||
void UEFITool::writeSettings()
|
||||
@ -1084,6 +1090,7 @@ void UEFITool::writeSettings()
|
||||
settings.setValue("tree/columnWidth1", ui->structureTreeView->columnWidth(1));
|
||||
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
|
||||
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
|
||||
settings.setValue("tree/markingEnabled", markingEnabled);
|
||||
}
|
||||
|
||||
void UEFITool::showFitTable()
|
||||
|
@ -134,6 +134,7 @@ private:
|
||||
QString currentPath;
|
||||
QString currentProgramPath;
|
||||
const QString version;
|
||||
bool markingEnabled;
|
||||
|
||||
bool enableExtractBodyUncompressed(const QModelIndex ¤t);
|
||||
|
||||
|
@ -25,13 +25,13 @@ const UINT8* calculateAddress16(const UINT8* baseAddress, const UINT16 baseOrLim
|
||||
return baseAddress + baseOrLimit * 0x1000;
|
||||
}
|
||||
|
||||
// Calculate offset of region using its base
|
||||
// Calculate offset of region using it's base
|
||||
UINT32 calculateRegionOffset(const UINT16 base)
|
||||
{
|
||||
return base * 0x1000;
|
||||
}
|
||||
|
||||
//Calculate size of region using its base and limit
|
||||
//Calculate size of region using it's base and limit
|
||||
UINT32 calculateRegionSize(const UINT16 base, const UINT16 limit)
|
||||
{
|
||||
if (limit)
|
||||
|
@ -106,25 +106,37 @@ typedef struct FLASH_DESCRIPTOR_COMPONENT_SECTION_ {
|
||||
// If limit is zero - region is not present
|
||||
typedef struct FLASH_DESCRIPTOR_REGION_SECTION_ {
|
||||
UINT16 DescriptorBase; // Descriptor
|
||||
UINT16 DescriptorLimit; //
|
||||
UINT16 DescriptorLimit; //
|
||||
UINT16 BiosBase; // BIOS
|
||||
UINT16 BiosLimit; //
|
||||
UINT16 MeBase; // ME
|
||||
UINT16 MeBase; // Management Engine
|
||||
UINT16 MeLimit; //
|
||||
UINT16 GbeBase; // GbE
|
||||
UINT16 GbeBase; // Gigabit Ethernet
|
||||
UINT16 GbeLimit; //
|
||||
UINT16 PdrBase; // PDR
|
||||
UINT16 PdrBase; // Platform Data
|
||||
UINT16 PdrLimit; //
|
||||
UINT16 Reserved1Base; // Reserved1
|
||||
UINT16 Reserved1Limit; //
|
||||
UINT16 Reserved2Base; // Reserved2
|
||||
UINT16 Reserved2Limit; //
|
||||
UINT16 Reserved3Base; // Reserved3
|
||||
UINT16 Reserved3Limit; //
|
||||
UINT16 EcBase; // EC
|
||||
UINT16 DevExp1Base; // Device Expansion 1
|
||||
UINT16 DevExp1Limit; //
|
||||
UINT16 Bios2Base; // Secondary BIOS
|
||||
UINT16 Bios2Limit; //
|
||||
UINT16 MicrocodeBase; // CPU microcode
|
||||
UINT16 MicrocodeLimit; //
|
||||
UINT16 EcBase; // Embedded Controller
|
||||
UINT16 EcLimit; //
|
||||
UINT16 Reserved4Base; // Reserved4
|
||||
UINT16 Reserved4Limit; //
|
||||
UINT16 DevExp2Base; // Device Expansion 2
|
||||
UINT16 DevExp2Limit; //
|
||||
UINT16 IeBase; // Innovation Engine
|
||||
UINT16 IeLimit; //
|
||||
UINT16 Tgbe1Base; // 10 Gigabit Ethernet 1
|
||||
UINT16 Tgbe1Limit; //
|
||||
UINT16 Tgbe2Base; // 10 Gigabit Ethernet 2
|
||||
UINT16 Tgbe2Limit; //
|
||||
UINT16 Reserved1Base; // Reserved 1
|
||||
UINT16 Reserved1Limit; //
|
||||
UINT16 Reserved2Base; // Reserved 2
|
||||
UINT16 Reserved2Limit; //
|
||||
UINT16 PttBase; // Platform Trust Technology
|
||||
UINT16 PttLimit; //
|
||||
} FLASH_DESCRIPTOR_REGION_SECTION;
|
||||
|
||||
// Master section
|
||||
|
@ -32,6 +32,9 @@ const std::vector<UByteArray> FFSv3Volumes(1, EFI_FIRMWARE_FILE_SYSTEM3_GUID);
|
||||
const UINT8 ffsAlignmentTable[] =
|
||||
{ 0, 4, 7, 9, 10, 12, 15, 16 };
|
||||
|
||||
const UINT8 ffsAlignment2Table[] =
|
||||
{ 17, 18, 19, 20, 21, 22, 23, 24 };
|
||||
|
||||
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
||||
{
|
||||
ffsSize[2] = (UINT8)((size) >> 16);
|
||||
|
17
common/ffs.h
17
common/ffs.h
@ -288,7 +288,7 @@ UINT8 Type;
|
||||
UINT8 Attributes;
|
||||
UINT8 Size[3]; // Set to 0xFFFFFF
|
||||
UINT8 State;
|
||||
UINT32 ExtendedSize;
|
||||
UINT64 ExtendedSize;
|
||||
} EFI_FFS_FILE_HEADER2;
|
||||
|
||||
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
||||
@ -324,6 +324,7 @@ UINT32 ExtendedSize;
|
||||
#define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
|
||||
#define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes
|
||||
#define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes
|
||||
#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 // Volaid only for revision 2 volumes, added in UEFI PI 1.6
|
||||
#define FFS_ATTRIB_FIXED 0x04
|
||||
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
||||
#define FFS_ATTRIB_CHECKSUM 0x40
|
||||
@ -331,6 +332,10 @@ UINT32 ExtendedSize;
|
||||
// FFS alignment table
|
||||
extern const UINT8 ffsAlignmentTable[];
|
||||
|
||||
// Extended FFS alignment table, added in UEFI PI 1.6
|
||||
extern const UINT8 ffsAlignment2Table[];
|
||||
|
||||
|
||||
// File states
|
||||
#define EFI_FILE_HEADER_CONSTRUCTION 0x01
|
||||
#define EFI_FILE_HEADER_VALID 0x02
|
||||
@ -338,7 +343,7 @@ extern const UINT8 ffsAlignmentTable[];
|
||||
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
|
||||
#define EFI_FILE_DELETED 0x10
|
||||
#define EFI_FILE_HEADER_INVALID 0x20
|
||||
#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI Vol3
|
||||
#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI
|
||||
|
||||
// PEI apriori file
|
||||
const UByteArray EFI_PEI_APRIORI_FILE_GUID
|
||||
@ -356,10 +361,14 @@ const UByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
|
||||
const UByteArray EFI_FFS_PAD_FILE_GUID
|
||||
("\x85\x65\x53\xE4\x09\x79\x60\x4A\xB5\xC6\xEC\xDE\xA6\xEB\xFB\x54", 16);
|
||||
|
||||
// DXE core file
|
||||
const UByteArray EFI_DXE_CORE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
|
||||
// AMI DXE core file
|
||||
const UByteArray AMI_CORE_DXE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
|
||||
("\x7E\xF3\xE3\x5A\xAE\x4E\xAE\x41\x82\x40\x35\x46\x5B\x5E\x81\xEB", 16);
|
||||
|
||||
// EDK2 DXE code file
|
||||
const UByteArray EFI_DXE_CORE_GUID // D6A2CB7F-6A18-4E2F-B43B-9920A733700A
|
||||
("\x7F\xCB\xA2\xD6\x18\x6A\x2F\x4E\xB4\x3B\x99\x20\xA7\x33\x70\x0A", 16);
|
||||
|
||||
// FFS size conversion routines
|
||||
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
|
||||
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
|
||||
|
@ -193,13 +193,19 @@ USTATUS FfsBuilder::buildIntelImage(const UModelIndex & index, UByteArray & inte
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
case Subtypes::GbeRegion:
|
||||
case Subtypes::MeRegion:
|
||||
case Subtypes::GbeRegion:
|
||||
case Subtypes::DevExp1Region:
|
||||
case Subtypes::Bios2Region:
|
||||
case Subtypes::MicrocodeRegion:
|
||||
case Subtypes::EcRegion:
|
||||
case Subtypes::DevExp2Region:
|
||||
case Subtypes::IeRegion:
|
||||
case Subtypes::Tgbe1Region:
|
||||
case Subtypes::Tgbe2Region:
|
||||
case Subtypes::Reserved1Region:
|
||||
case Subtypes::Reserved2Region:
|
||||
case Subtypes::Reserved3Region:
|
||||
case Subtypes::Reserved4Region:
|
||||
case Subtypes::PttRegion:
|
||||
// Add region as is
|
||||
region = model->header(currentRegion).append(model->body(currentRegion));
|
||||
break;
|
||||
|
@ -28,6 +28,18 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "parsingdata.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "nvramparser.h"
|
||||
#include "meparser.h"
|
||||
|
||||
#ifndef QT_CORE_LIB
|
||||
namespace Qt {
|
||||
enum GlobalColor {
|
||||
red = 7,
|
||||
cyan = 10,
|
||||
yellow = 12,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
// Region info structure definition
|
||||
struct REGION_INFO {
|
||||
@ -38,6 +50,30 @@ struct REGION_INFO {
|
||||
friend bool operator< (const REGION_INFO & lhs, const REGION_INFO & rhs){ return lhs.offset < rhs.offset; }
|
||||
};
|
||||
|
||||
// Constructor
|
||||
FfsParser::FfsParser(TreeModel* treeModel) : model(treeModel),
|
||||
capsuleOffsetFixup(0), addressDiff(0x100000000ULL),
|
||||
bgAcmFound(false), bgKeyManifestFound(false), bgBootPolicyFound(false), bgFirstVolumeOffset(0x100000000ULL) {
|
||||
nvramParser = new NvramParser(treeModel, this);
|
||||
meParser = new MeParser(treeModel);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
FfsParser::~FfsParser() {
|
||||
delete nvramParser;
|
||||
delete meParser;
|
||||
}
|
||||
|
||||
// Obtain parser messages
|
||||
std::vector<std::pair<UString, UModelIndex> > FfsParser::getMessages() const {
|
||||
std::vector<std::pair<UString, UModelIndex> > meVector = meParser->getMessages();
|
||||
std::vector<std::pair<UString, UModelIndex> > nvramVector = nvramParser->getMessages();
|
||||
std::vector<std::pair<UString, UModelIndex> > resultVector = messagesVector;
|
||||
resultVector.insert(resultVector.end(), meVector.begin(), meVector.end());
|
||||
resultVector.insert(resultVector.end(), nvramVector.begin(), nvramVector.end());
|
||||
return resultVector;
|
||||
}
|
||||
|
||||
// Firmware image parsing functions
|
||||
USTATUS FfsParser::parse(const UByteArray & buffer)
|
||||
{
|
||||
@ -286,11 +322,9 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
||||
}
|
||||
|
||||
// BIOS region
|
||||
REGION_INFO bios;
|
||||
bios.type = Subtypes::BiosRegion;
|
||||
bios.offset = 0;
|
||||
bios.length = 0;
|
||||
if (regionSection->BiosLimit) {
|
||||
REGION_INFO bios;
|
||||
bios.type = Subtypes::BiosRegion;
|
||||
bios.offset = calculateRegionOffset(regionSection->BiosBase);
|
||||
bios.length = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit);
|
||||
|
||||
@ -317,93 +351,22 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
||||
return U_INVALID_FLASH_DESCRIPTOR;
|
||||
}
|
||||
|
||||
// GbE region
|
||||
REGION_INFO gbe;
|
||||
gbe.type = Subtypes::GbeRegion;
|
||||
gbe.offset = 0;
|
||||
gbe.length = 0;
|
||||
if (regionSection->GbeLimit) {
|
||||
gbe.offset = calculateRegionOffset(regionSection->GbeBase);
|
||||
gbe.length = calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit);
|
||||
gbe.data = intelImage.mid(gbe.offset, gbe.length);
|
||||
regions.push_back(gbe);
|
||||
}
|
||||
// Add all other regions
|
||||
for (UINT8 i = Subtypes::GbeRegion; i <= Subtypes::PttRegion; i++) {
|
||||
if (descriptorVersion == 1 && i == Subtypes::MicrocodeRegion)
|
||||
break; // Do not parse Microcode and other following regions for old descriptors
|
||||
|
||||
// PDR region
|
||||
REGION_INFO pdr;
|
||||
pdr.type = Subtypes::PdrRegion;
|
||||
pdr.offset = 0;
|
||||
pdr.length = 0;
|
||||
if (regionSection->PdrLimit) {
|
||||
pdr.offset = calculateRegionOffset(regionSection->PdrBase);
|
||||
pdr.length = calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit);
|
||||
pdr.data = intelImage.mid(pdr.offset, pdr.length);
|
||||
regions.push_back(pdr);
|
||||
}
|
||||
|
||||
// Reserved1 region
|
||||
REGION_INFO reserved1;
|
||||
reserved1.type = Subtypes::Reserved1Region;
|
||||
reserved1.offset = 0;
|
||||
reserved1.length = 0;
|
||||
if (regionSection->Reserved1Limit && regionSection->Reserved1Base != 0xFFFF && regionSection->Reserved1Limit != 0xFFFF) {
|
||||
reserved1.offset = calculateRegionOffset(regionSection->Reserved1Base);
|
||||
reserved1.length = calculateRegionSize(regionSection->Reserved1Base, regionSection->Reserved1Limit);
|
||||
reserved1.data = intelImage.mid(reserved1.offset, reserved1.length);
|
||||
regions.push_back(reserved1);
|
||||
}
|
||||
|
||||
// Reserved2 region
|
||||
REGION_INFO reserved2;
|
||||
reserved2.type = Subtypes::Reserved2Region;
|
||||
reserved2.offset = 0;
|
||||
reserved2.length = 0;
|
||||
if (regionSection->Reserved2Limit && regionSection->Reserved2Base != 0xFFFF && regionSection->Reserved2Limit != 0xFFFF) {
|
||||
reserved2.offset = calculateRegionOffset(regionSection->Reserved2Base);
|
||||
reserved2.length = calculateRegionSize(regionSection->Reserved2Base, regionSection->Reserved2Limit);
|
||||
reserved2.data = intelImage.mid(reserved2.offset, reserved2.length);
|
||||
regions.push_back(reserved2);
|
||||
}
|
||||
|
||||
// Reserved3 region
|
||||
REGION_INFO reserved3;
|
||||
reserved3.type = Subtypes::Reserved3Region;
|
||||
reserved3.offset = 0;
|
||||
reserved3.length = 0;
|
||||
|
||||
// EC region
|
||||
REGION_INFO ec;
|
||||
ec.type = Subtypes::EcRegion;
|
||||
ec.offset = 0;
|
||||
ec.length = 0;
|
||||
|
||||
// Reserved4 region
|
||||
REGION_INFO reserved4;
|
||||
reserved3.type = Subtypes::Reserved4Region;
|
||||
reserved4.offset = 0;
|
||||
reserved4.length = 0;
|
||||
|
||||
// Check for EC and reserved region 4 only for v2 descriptor
|
||||
if (descriptorVersion == 2) {
|
||||
if (regionSection->Reserved3Limit) {
|
||||
reserved3.offset = calculateRegionOffset(regionSection->Reserved3Base);
|
||||
reserved3.length = calculateRegionSize(regionSection->Reserved3Base, regionSection->Reserved3Limit);
|
||||
reserved3.data = intelImage.mid(reserved3.offset, reserved3.length);
|
||||
regions.push_back(reserved3);
|
||||
}
|
||||
|
||||
if (regionSection->EcLimit) {
|
||||
ec.offset = calculateRegionOffset(regionSection->EcBase);
|
||||
ec.length = calculateRegionSize(regionSection->EcBase, regionSection->EcLimit);
|
||||
ec.data = intelImage.mid(ec.offset, ec.length);
|
||||
regions.push_back(ec);
|
||||
}
|
||||
|
||||
if (regionSection->Reserved4Limit) {
|
||||
reserved4.offset = calculateRegionOffset(regionSection->Reserved4Base);
|
||||
reserved4.length = calculateRegionSize(regionSection->Reserved4Base, regionSection->Reserved4Limit);
|
||||
reserved4.data = intelImage.mid(reserved4.offset, reserved4.length);
|
||||
regions.push_back(reserved4);
|
||||
const UINT16* RegionBase = ((const UINT16*)regionSection) + 2 * i;
|
||||
const UINT16* RegionLimit = ((const UINT16*)regionSection) + 2 * i + 1;
|
||||
if (*RegionLimit && !(*RegionBase == 0xFFFF && *RegionLimit == 0xFFFF)) {
|
||||
REGION_INFO region;
|
||||
region.type = i;
|
||||
region.offset = calculateRegionOffset(*RegionBase);
|
||||
region.length = calculateRegionSize(*RegionBase, *RegionLimit);
|
||||
if (region.length != 0) {
|
||||
region.data = intelImage.mid(region.offset, region.length);
|
||||
regions.push_back(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,10 +519,10 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
||||
const VSCC_TABLE_ENTRY* vsccTableEntry = (const VSCC_TABLE_ENTRY*)(descriptor + ((UINT16)upperMap->VsccTableBase << 4));
|
||||
info += UString("\nFlash chips in VSCC table:");
|
||||
UINT8 vsscTableSize = upperMap->VsccTableSize * sizeof(UINT32) / sizeof(VSCC_TABLE_ENTRY);
|
||||
UString jedecId = jedecIdToUString(vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1);
|
||||
for (UINT8 i = 0; i < vsscTableSize; i++) {
|
||||
info += usprintf("\n%02X%02X%02X (",
|
||||
vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1)
|
||||
+ jedecIdToUString(vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1)
|
||||
info += usprintf("\n%02X%02X%02X (", vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1)
|
||||
+ jedecId
|
||||
+ UString(")");
|
||||
vsccTableEntry++;
|
||||
}
|
||||
@ -567,6 +530,11 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
||||
// Add descriptor tree item
|
||||
UModelIndex regionIndex = model->addItem(localOffset, Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
|
||||
|
||||
// Show messages
|
||||
if (jedecId == UString("Unknown")) {
|
||||
msg(usprintf("SPI flash with unknown JEDEC ID %02X%02X%02X found in VSCC table", vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1), regionIndex);
|
||||
}
|
||||
|
||||
// Parse regions
|
||||
UINT8 result = U_SUCCESS;
|
||||
UINT8 parseResult = U_SUCCESS;
|
||||
@ -585,12 +553,18 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
||||
case Subtypes::PdrRegion:
|
||||
result = parsePdrRegion(region.data, region.offset, index, regionIndex);
|
||||
break;
|
||||
case Subtypes::DevExp1Region:
|
||||
case Subtypes::Bios2Region:
|
||||
case Subtypes::MicrocodeRegion:
|
||||
case Subtypes::EcRegion:
|
||||
case Subtypes::DevExp2Region:
|
||||
case Subtypes::IeRegion:
|
||||
case Subtypes::Tgbe1Region:
|
||||
case Subtypes::Tgbe2Region:
|
||||
case Subtypes::Reserved1Region:
|
||||
case Subtypes::Reserved2Region:
|
||||
case Subtypes::Reserved3Region:
|
||||
case Subtypes::EcRegion:
|
||||
case Subtypes::Reserved4Region:
|
||||
result = parseGeneralRegion(region.type, region.data, region.offset, index, regionIndex);
|
||||
case Subtypes::PttRegion:
|
||||
result = parseGenericRegion(region.type, region.data, region.offset, index, regionIndex);
|
||||
break;
|
||||
case Subtypes::ZeroPadding:
|
||||
case Subtypes::OnePadding:
|
||||
@ -702,7 +676,7 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset
|
||||
msg(UString("parseMeRegion: ME version is unknown, it can be damaged"), index);
|
||||
}
|
||||
else {
|
||||
meParser.parseMeRegionBody(index);
|
||||
meParser->parseMeRegionBody(index);
|
||||
}
|
||||
|
||||
return U_SUCCESS;
|
||||
@ -729,7 +703,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
// Check sanity
|
||||
if (region.isEmpty())
|
||||
@ -1184,7 +1158,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
|
||||
|
||||
// Parse VSS NVRAM volumes with a dedicated function
|
||||
if (model->subtype(index) == Subtypes::NvramVolume)
|
||||
return nvramParser.parseNvramVolumeBody(index);
|
||||
return nvramParser->parseNvramVolumeBody(index);
|
||||
|
||||
// Get required values from parsing data
|
||||
UINT8 emptyByte = 0xFF;
|
||||
@ -1351,7 +1325,7 @@ UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset
|
||||
return 0;
|
||||
const EFI_FFS_FILE_HEADER2* fileHeader = (const EFI_FFS_FILE_HEADER2*)(volume.constData() + fileOffset);
|
||||
if (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)
|
||||
return fileHeader->ExtendedSize;
|
||||
return (UINT32) fileHeader->ExtendedSize;
|
||||
else
|
||||
return uint24ToUint32(fileHeader->Size);
|
||||
}
|
||||
@ -1384,17 +1358,24 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
||||
|
||||
// Get file header
|
||||
UByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
|
||||
if (ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
|
||||
bool largeFile = false;
|
||||
EFI_FFS_FILE_HEADER* tempFileHeader = (EFI_FFS_FILE_HEADER*)header.data();
|
||||
if (ffsVersion == 3 && (tempFileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
|
||||
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2))
|
||||
return U_INVALID_FILE;
|
||||
header = file.left(sizeof(EFI_FFS_FILE_HEADER2));
|
||||
largeFile = true;
|
||||
}
|
||||
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
|
||||
|
||||
// Check file alignment
|
||||
bool msgUnalignedFile = false;
|
||||
UINT8 alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3];
|
||||
UINT32 alignment = (UINT32)pow(2.0, alignmentPower);
|
||||
if (volumeRevision > 1 && (fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2)) {
|
||||
alignmentPower = ffsAlignment2Table[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3];
|
||||
}
|
||||
|
||||
UINT32 alignment = (UINT32)(1UL << alignmentPower);
|
||||
if ((localOffset + header.size()) % alignment)
|
||||
msgUnalignedFile = true;
|
||||
|
||||
@ -1403,45 +1384,6 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
||||
if (!isWeakAligned && volumeAlignment < alignment)
|
||||
msgFileAlignmentIsGreaterThanVolumeAlignment = true;
|
||||
|
||||
// Check header checksum
|
||||
UByteArray tempHeader = header;
|
||||
EFI_FFS_FILE_HEADER* tempFileHeader = (EFI_FFS_FILE_HEADER*)(tempHeader.data());
|
||||
tempFileHeader->IntegrityCheck.Checksum.Header = 0;
|
||||
tempFileHeader->IntegrityCheck.Checksum.File = 0;
|
||||
UINT8 calculatedHeader = calculateChecksum8((const UINT8*)tempFileHeader, header.size() - 1);
|
||||
bool msgInvalidHeaderChecksum = false;
|
||||
if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader)
|
||||
msgInvalidHeaderChecksum = true;
|
||||
|
||||
// Check data checksum
|
||||
// Data checksum must be calculated
|
||||
bool msgInvalidDataChecksum = false;
|
||||
UINT8 calculatedData = 0;
|
||||
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
UINT32 bufferSize = file.size() - header.size();
|
||||
// Exclude file tail from data checksum calculation
|
||||
if (volumeRevision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT))
|
||||
bufferSize -= sizeof(UINT16);
|
||||
calculatedData = calculateChecksum8((const UINT8*)(file.constData() + header.size()), bufferSize);
|
||||
if (fileHeader->IntegrityCheck.Checksum.File != calculatedData)
|
||||
msgInvalidDataChecksum = true;
|
||||
}
|
||||
// Data checksum must be one of predefined values
|
||||
else if (volumeRevision == 1 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
|
||||
calculatedData = FFS_FIXED_CHECKSUM;
|
||||
msgInvalidDataChecksum = true;
|
||||
}
|
||||
else if (volumeRevision == 2 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) {
|
||||
calculatedData = FFS_FIXED_CHECKSUM2;
|
||||
msgInvalidDataChecksum = true;
|
||||
}
|
||||
|
||||
// Check file type
|
||||
bool msgUnknownType = false;
|
||||
if (fileHeader->Type > EFI_FV_FILETYPE_MM_CORE_STANDALONE && fileHeader->Type != EFI_FV_FILETYPE_PAD) {
|
||||
msgUnknownType = true;
|
||||
};
|
||||
|
||||
// Get file body
|
||||
UByteArray body = file.mid(header.size());
|
||||
|
||||
@ -1459,6 +1401,36 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
||||
body = body.left(body.size() - sizeof(UINT16));
|
||||
}
|
||||
|
||||
// Check header checksum
|
||||
UINT8 calculatedHeader = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State);
|
||||
bool msgInvalidHeaderChecksum = false;
|
||||
if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader)
|
||||
msgInvalidHeaderChecksum = true;
|
||||
|
||||
// Check data checksum
|
||||
// Data checksum must be calculated
|
||||
bool msgInvalidDataChecksum = false;
|
||||
UINT8 calculatedData = 0;
|
||||
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
calculatedData = calculateChecksum8((const UINT8*)body.constData(), body.size());
|
||||
}
|
||||
// Data checksum must be one of predefined values
|
||||
else if (volumeRevision == 1) {
|
||||
calculatedData = FFS_FIXED_CHECKSUM;
|
||||
}
|
||||
else {
|
||||
calculatedData = FFS_FIXED_CHECKSUM2;
|
||||
}
|
||||
|
||||
if (fileHeader->IntegrityCheck.Checksum.File != calculatedData)
|
||||
msgInvalidDataChecksum = true;
|
||||
|
||||
// Check file type
|
||||
bool msgUnknownType = false;
|
||||
if (fileHeader->Type > EFI_FV_FILETYPE_MM_CORE_STANDALONE && fileHeader->Type != EFI_FV_FILETYPE_PAD) {
|
||||
msgUnknownType = true;
|
||||
};
|
||||
|
||||
// Get info
|
||||
UString name;
|
||||
UString info;
|
||||
@ -1492,9 +1464,9 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
||||
text = UString("Volume Top File");
|
||||
}
|
||||
// Check if the file is the first DXE Core
|
||||
else if (fileGuid == EFI_DXE_CORE_GUID) {
|
||||
// Mark is as first DXE code
|
||||
// This information may be used to determine DXE volume offset for old AMI protected ranges
|
||||
else if (fileGuid == EFI_DXE_CORE_GUID || fileGuid == AMI_CORE_DXE_GUID) {
|
||||
// Mark is as first DXE core
|
||||
// This information may be used to determine DXE volume offset for old AMI or post-IBB protected ranges
|
||||
isDxeCore = true;
|
||||
}
|
||||
|
||||
@ -1579,7 +1551,7 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index)
|
||||
|
||||
// Parse NVAR store
|
||||
if (fileGuid == NVRAM_NVAR_STORE_FILE_GUID)
|
||||
return nvramParser.parseNvarStore(index);
|
||||
return nvramParser->parseNvarStore(index);
|
||||
|
||||
// Parse vendor hash file
|
||||
else if (fileGuid == BG_VENDOR_HASH_FILE_GUID_PHOENIX)
|
||||
@ -2699,7 +2671,7 @@ USTATUS FfsParser::parseRawSectionBody(const UModelIndex & index)
|
||||
}
|
||||
else if (parentFileGuid == NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID) { // AMI NVRAM external defaults
|
||||
// Parse NVAR area
|
||||
nvramParser.parseNvarStore(index);
|
||||
nvramParser->parseNvarStore(index);
|
||||
|
||||
// Set parent file text
|
||||
model->setText(parentFile, UString("NVRAM external defaults"));
|
||||
@ -2709,7 +2681,6 @@ USTATUS FfsParser::parseRawSectionBody(const UModelIndex & index)
|
||||
parseVendorHashFile(parentFileGuid, index);
|
||||
}
|
||||
|
||||
|
||||
// Parse as raw area
|
||||
return parseRawArea(index);
|
||||
}
|
||||
@ -3009,9 +2980,9 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
UByteArray protectedParts;
|
||||
bool bgProtectedRangeFound = false;
|
||||
for (UINT32 i = 0; i < (UINT32)bgProtectedRanges.size(); i++) {
|
||||
if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD) {
|
||||
if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB) {
|
||||
bgProtectedRangeFound = true;
|
||||
bgProtectedRanges[i].Offset -= addressDiff;
|
||||
bgProtectedRanges[i].Offset -= (UINT32)addressDiff;
|
||||
protectedParts += openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||
}
|
||||
@ -3019,7 +2990,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
|
||||
if (bgProtectedRangeFound) {
|
||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
||||
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||
|
||||
if (digest != bgBpDigest) {
|
||||
msg(UString("checkProtectedRanges: BG-protected ranges hash mismatch, opened image may refuse to boot"), index);
|
||||
@ -3031,7 +3002,8 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
|
||||
// Calculate digests for vendor-protected ranges
|
||||
for (UINT32 i = 0; i < (UINT32)bgProtectedRanges.size(); i++) {
|
||||
if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD) {
|
||||
if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD
|
||||
&& bgProtectedRanges[i].Size != 0 && bgProtectedRanges[i].Size != 0xFFFFFFFF) {
|
||||
if (!bgDxeCoreIndex.isValid()) {
|
||||
msg(UString("checkProtectedRanges: can't determine DXE volume offset, old AMI protected range hash can't be checked"), index);
|
||||
}
|
||||
@ -3046,10 +3018,10 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||
|
||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
||||
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||
|
||||
if (digest != bgProtectedRanges[i].Hash) {
|
||||
msg(usprintf("checkProtectedRanges: AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||
msg(usprintf("checkProtectedRanges: old AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||
bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size),
|
||||
model->findByOffset(bgProtectedRanges[i].Offset));
|
||||
}
|
||||
@ -3058,12 +3030,44 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW) {
|
||||
bgProtectedRanges[i].Offset -= addressDiff;
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_POST_IBB) {
|
||||
if (!bgDxeCoreIndex.isValid()) {
|
||||
msg(UString("checkProtectedRanges: can't determine DXE volume offset, post-IBB protected range hash can't be checked"), index);
|
||||
}
|
||||
else {
|
||||
// Offset will be determined as the offset of root volume with first DXE core
|
||||
UModelIndex dxeRootVolumeIndex = model->findLastParentOfType(bgDxeCoreIndex, Types::Volume);
|
||||
if (!dxeRootVolumeIndex.isValid()) {
|
||||
msg(UString("checkProtectedRanges: can't determine DXE volume offset, post-IBB protected range hash can't be checked"), index);
|
||||
}
|
||||
else
|
||||
{
|
||||
bgProtectedRanges[i].Offset = model->offset(dxeRootVolumeIndex);
|
||||
bgProtectedRanges[i].Size = model->header(dxeRootVolumeIndex).size() + model->body(dxeRootVolumeIndex).size() + model->tail(dxeRootVolumeIndex).size();
|
||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||
|
||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||
|
||||
if (digest != bgProtectedRanges[i].Hash) {
|
||||
msg(usprintf("checkProtectedRanges: post-IBB protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||
bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size),
|
||||
model->findByOffset(bgProtectedRanges[i].Offset));
|
||||
}
|
||||
|
||||
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW
|
||||
&& bgProtectedRanges[i].Size != 0 && bgProtectedRanges[i].Size != 0xFFFFFFFF
|
||||
&& bgProtectedRanges[i].Offset != 0 && bgProtectedRanges[i].Offset != 0xFFFFFFFF) {
|
||||
|
||||
bgProtectedRanges[i].Offset -= (UINT32)addressDiff;
|
||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||
|
||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
||||
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||
|
||||
if (digest != bgProtectedRanges[i].Hash) {
|
||||
msg(usprintf("checkProtectedRanges: AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||
@ -3073,12 +3077,14 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
|
||||
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||
}
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX) {
|
||||
bgProtectedRanges[i].Offset += bgFirstVolumeOffset;
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX
|
||||
&& bgProtectedRanges[i].Size != 0 && bgProtectedRanges[i].Size != 0xFFFFFFFF
|
||||
&& bgProtectedRanges[i].Offset != 0xFFFFFFFF) {
|
||||
bgProtectedRanges[i].Offset += (UINT32)bgFirstVolumeOffset;
|
||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||
|
||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
||||
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||
|
||||
if (digest != bgProtectedRanges[i].Hash) {
|
||||
msg(usprintf("checkProtectedRanges: Phoenix protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||
@ -3088,12 +3094,14 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
||||
|
||||
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||
}
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT) {
|
||||
bgProtectedRanges[i].Offset -= addressDiff;
|
||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT
|
||||
&& bgProtectedRanges[i].Size != 0 && bgProtectedRanges[i].Size != 0xFFFFFFFF
|
||||
&& bgProtectedRanges[i].Offset != 0 && bgProtectedRanges[i].Offset != 0xFFFFFFFF) {
|
||||
bgProtectedRanges[i].Offset -= (UINT32)addressDiff;
|
||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||
|
||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
||||
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||
|
||||
if (digest != bgProtectedRanges[i].Hash) {
|
||||
msg(usprintf("checkProtectedRanges: Microsoft protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||
@ -3125,7 +3133,7 @@ USTATUS FfsParser::markProtectedRangeRecursive(const UModelIndex & index, const
|
||||
|
||||
if (std::min(currentOffset + currentSize, range.Offset + range.Size) > std::max(currentOffset, range.Offset)) {
|
||||
if (range.Offset <= currentOffset && currentOffset + currentSize <= range.Offset + range.Size) { // Mark as fully in range
|
||||
model->setMarking(index, range.Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD ? Qt::red : Qt::cyan);
|
||||
model->setMarking(index, range.Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB ? Qt::red : Qt::cyan);
|
||||
}
|
||||
else { // Mark as partially in range
|
||||
model->setMarking(index, Qt::yellow);
|
||||
@ -3579,6 +3587,15 @@ USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest
|
||||
header->KmSvn,
|
||||
header->KmId
|
||||
);
|
||||
|
||||
// Add hash of Key Manifest PubKey, this hash will be written to FPFs
|
||||
UINT8 hash[SHA256_DIGEST_SIZE];
|
||||
sha256(&header->KeyManifestSignature.PubKey.Modulus, sizeof(header->KeyManifestSignature.PubKey.Modulus), hash);
|
||||
bootGuardInfo += UString("\n\nKey Manifest RSA Public Key Hash:\n");
|
||||
for (UINT8 i = 0; i < sizeof(hash); i++) {
|
||||
bootGuardInfo += usprintf("%02X", hash[i]);
|
||||
}
|
||||
|
||||
// Add BpKeyHash
|
||||
bootGuardInfo += UString("\n\nBoot Policy RSA Public Key Hash:\n");
|
||||
for (UINT8 i = 0; i < sizeof(header->BpKeyHash.HashBuffer); i++) {
|
||||
@ -3702,11 +3719,22 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy,
|
||||
elementHeader->PmrlLimit,
|
||||
elementHeader->EntryPoint
|
||||
);
|
||||
|
||||
// Add PostIbbHash
|
||||
bootGuardInfo += UString("\n\nPost IBB Hash:\n");
|
||||
for (UINT8 i = 0; i < sizeof(elementHeader->IbbHash.HashBuffer); i++) {
|
||||
bootGuardInfo += usprintf("%02X", elementHeader->IbbHash.HashBuffer[i]);
|
||||
}
|
||||
|
||||
// Check for non-empry PostIbbHash
|
||||
UByteArray postIbbHash((const char*)elementHeader->IbbHash.HashBuffer, sizeof(elementHeader->IbbHash.HashBuffer));
|
||||
if (postIbbHash.count('\x00') != postIbbHash.size() && postIbbHash.count('\xFF') != postIbbHash.size()) {
|
||||
BG_PROTECTED_RANGE range;
|
||||
range.Type = BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_POST_IBB;
|
||||
range.Hash = postIbbHash;
|
||||
bgProtectedRanges.push_back(range);
|
||||
}
|
||||
|
||||
// Add Digest
|
||||
bgBpDigest = UByteArray((const char*)elementHeader->Digest.HashBuffer, sizeof(elementHeader->Digest.HashBuffer));
|
||||
bootGuardInfo += UString("\n\nIBB Digest:\n");
|
||||
@ -3724,7 +3752,7 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy,
|
||||
BG_PROTECTED_RANGE range;
|
||||
range.Offset = segments[i].Base;
|
||||
range.Size = segments[i].Size;
|
||||
range.Type = BG_PROTECTED_RANGE_INTEL_BOOT_GUARD;
|
||||
range.Type = BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB;
|
||||
bgProtectedRanges.push_back(range);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ffsparser.h
|
||||
|
||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
||||
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||
This program and the accompanying materials
|
||||
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
|
||||
@ -19,8 +19,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "ustring.h"
|
||||
#include "ubytearray.h"
|
||||
#include "treemodel.h"
|
||||
#include "nvramparser.h"
|
||||
#include "meparser.h"
|
||||
#include "bootguard.h"
|
||||
|
||||
typedef struct BG_PROTECTED_RANGE_
|
||||
@ -31,31 +29,25 @@ typedef struct BG_PROTECTED_RANGE_
|
||||
UByteArray Hash;
|
||||
} BG_PROTECTED_RANGE;
|
||||
|
||||
#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD 0x01
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX 0x02
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD 0x03
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW 0x04
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT 0x05
|
||||
#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB 0x01
|
||||
#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_POST_IBB 0x02
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX 0x03
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD 0x04
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW 0x05
|
||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT 0x06
|
||||
|
||||
class NvramParser;
|
||||
class MeParser;
|
||||
|
||||
class FfsParser
|
||||
{
|
||||
public:
|
||||
// Default constructor and destructor
|
||||
FfsParser(TreeModel* treeModel) : model(treeModel), nvramParser(treeModel), meParser(treeModel),
|
||||
capsuleOffsetFixup(0), addressDiff(0x100000000ULL),
|
||||
bgAcmFound(false), bgKeyManifestFound(false), bgBootPolicyFound(false), bgFirstVolumeOffset(0x100000000ULL) {}
|
||||
~FfsParser() {}
|
||||
// Constructor and destructor
|
||||
FfsParser(TreeModel* treeModel);
|
||||
~FfsParser();
|
||||
|
||||
// Obtain parser messages
|
||||
std::vector<std::pair<UString, UModelIndex> > getMessages() const {
|
||||
std::vector<std::pair<UString, UModelIndex> > meVector = meParser.getMessages();
|
||||
std::vector<std::pair<UString, UModelIndex> > nvramVector = nvramParser.getMessages();
|
||||
std::vector<std::pair<UString, UModelIndex> > resultVector = messagesVector;
|
||||
resultVector.insert(resultVector.end(), meVector.begin(), meVector.end());
|
||||
resultVector.insert(resultVector.end(), nvramVector.begin(), nvramVector.end());
|
||||
return resultVector;
|
||||
}
|
||||
|
||||
std::vector<std::pair<UString, UModelIndex> > getMessages() const;
|
||||
// Clear messages
|
||||
void clearMessages() { messagesVector.clear(); }
|
||||
|
||||
@ -78,8 +70,8 @@ private:
|
||||
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
|
||||
};
|
||||
|
||||
NvramParser nvramParser;
|
||||
MeParser meParser;
|
||||
NvramParser* nvramParser;
|
||||
MeParser* meParser;
|
||||
|
||||
UByteArray openedImage;
|
||||
UModelIndex lastVtf;
|
||||
@ -114,7 +106,7 @@ private:
|
||||
USTATUS parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
USTATUS parsePadFileBody(const UModelIndex & index);
|
||||
USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 localOffset, const UModelIndex & index);
|
||||
@ -163,6 +155,10 @@ private:
|
||||
USTATUS parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
|
||||
USTATUS findNextElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize);
|
||||
#endif
|
||||
|
||||
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
||||
friend class NvramParser; // Make FFS parsing routines accessible to NvramParser
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FFSPARSER_H
|
||||
|
@ -171,29 +171,32 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ {
|
||||
extern UString vssAttributesToUString(const UINT32 attributes);
|
||||
|
||||
//
|
||||
// Lenovo VSS variables
|
||||
// VSS2 variables
|
||||
//
|
||||
|
||||
//aaf32c78-947b-439a-a180-2e144ec37792
|
||||
#define LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 0xaaf32c78
|
||||
const UByteArray LENOVO_AUTH_VAR_KEY_DATABASE_GUID
|
||||
// aaf32c78-947b-439a-a180-2e144ec37792
|
||||
#define NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 0xaaf32c78
|
||||
const UByteArray NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID
|
||||
("\x78\x2C\xF3\xAA\x7B\x94\x9A\x43\xA1\x80\x2E\x14\x4E\xC3\x77\x92");
|
||||
|
||||
#define LENOVO_VSS_STORE_GUID_PART1 0xddcf3617
|
||||
const UByteArray LENOVO_VSS_STORE_GUID
|
||||
#define NVRAM_VSS2_STORE_GUID_PART1 0xddcf3617
|
||||
const UByteArray NVRAM_VSS2_STORE_GUID
|
||||
("\x17\x36\xCF\xDD\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D");
|
||||
|
||||
const UByteArray NVRAM_FDC_STORE_GUID
|
||||
("\x16\x36\xCF\xDD\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D");
|
||||
|
||||
// Variable store header
|
||||
typedef struct LENOVO_VSS_VARIABLE_STORE_HEADER_ {
|
||||
EFI_GUID Signature;
|
||||
typedef struct VSS2_VARIABLE_STORE_HEADER_ {
|
||||
EFI_GUID Signature; // VSS2 Store Guid
|
||||
UINT32 Size; // Size of variable store, including store header
|
||||
UINT8 Format; // Store format state
|
||||
UINT8 State; // Store health state
|
||||
UINT16 Unknown;
|
||||
UINT32 : 32;
|
||||
} LENOVO_VSS_VARIABLE_STORE_HEADER;
|
||||
} VSS2_VARIABLE_STORE_HEADER;
|
||||
|
||||
// VSS entries are 4-bytes aligned in Lenovo stores
|
||||
// VSS2 entries are 4-bytes aligned in VSS2 stores
|
||||
|
||||
//
|
||||
// _FDC region
|
||||
@ -220,7 +223,7 @@ const UByteArray EDKII_WORKING_BLOCK_SIGNATURE_GUID
|
||||
("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\x0A\xCE\x65\x00\xFD\x9F\x1B\x95", 16);
|
||||
|
||||
// 9E58292B-7C68-497D-A0CE6500FD9F1B95
|
||||
const UByteArray LENOVO_WORKING_BLOCK_SIGNATURE_GUID
|
||||
const UByteArray VSS2_WORKING_BLOCK_SIGNATURE_GUID
|
||||
("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\xA0\xCE\x65\x00\xFD\x9F\x1B\x95", 16);
|
||||
|
||||
#define NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 0xFFF12B8D
|
||||
|
@ -78,13 +78,13 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
UByteArray header;
|
||||
UByteArray body;
|
||||
UByteArray tail;
|
||||
|
||||
|
||||
UINT32 guidAreaSize = guidsInStore * sizeof(EFI_GUID);
|
||||
UINT32 unparsedSize = (UINT32)data.size() - offset - guidAreaSize;
|
||||
|
||||
// Get entry header
|
||||
const NVAR_ENTRY_HEADER* entryHeader = (const NVAR_ENTRY_HEADER*)(data.constData() + offset);
|
||||
|
||||
|
||||
// Check header size and signature
|
||||
if (unparsedSize < sizeof(NVAR_ENTRY_HEADER) ||
|
||||
entryHeader->Signature != NVRAM_NVAR_ENTRY_SIGNATURE ||
|
||||
@ -109,7 +109,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
// Add tree item
|
||||
model->addItem(localOffset + offset, Types::Padding, getPaddingType(padding), UString("Padding"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
||||
}
|
||||
|
||||
|
||||
// Add GUID store area
|
||||
UByteArray guidArea = data.right(guidAreaSize);
|
||||
// Get info
|
||||
@ -122,13 +122,13 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// Contruct generic header and body
|
||||
header = data.mid(offset, sizeof(NVAR_ENTRY_HEADER));
|
||||
body = data.mid(offset + sizeof(NVAR_ENTRY_HEADER), entryHeader->Size - sizeof(NVAR_ENTRY_HEADER));
|
||||
|
||||
UINT32 lastVariableFlag = emptyByte ? 0xFFFFFF : 0;
|
||||
|
||||
|
||||
// Set default next to predefined last value
|
||||
NVAR_ENTRY_PARSING_DATA pdata;
|
||||
pdata.emptyByte = emptyByte;
|
||||
@ -146,7 +146,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
subtype = Subtypes::LinkNvarEntry;
|
||||
pdata.next = entryHeader->Next;
|
||||
}
|
||||
|
||||
|
||||
// Entry with extended header
|
||||
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_EXT_HEADER) {
|
||||
hasExtendedHeader = true;
|
||||
@ -181,7 +181,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
}
|
||||
// Include entry attributes
|
||||
calculatedChecksum += entryHeader->Attributes;
|
||||
|
||||
|
||||
hasChecksum = true;
|
||||
msgUnknownExtDataFormat = false;
|
||||
}
|
||||
@ -204,7 +204,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
msgUnknownExtDataFormat = false;
|
||||
}
|
||||
else { // Full or link variable have hash
|
||||
if ((UINT32)tail.size() < sizeof(UINT64) + SHA256_HASH_SIZE) {
|
||||
if ((UINT32)tail.size() < sizeof(UINT64) + SHA256_HASH_SIZE) {
|
||||
msgExtDataTooShort = true;
|
||||
isInvalid = true;
|
||||
// Do not parse further
|
||||
@ -287,7 +287,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||
header = data.mid(offset, sizeof(NVAR_ENTRY_HEADER) + nameOffset + nameSize);
|
||||
body = body.mid(nameOffset + nameSize);
|
||||
}
|
||||
parsing_done:
|
||||
parsing_done:
|
||||
UString info;
|
||||
|
||||
// Rename invalid entries according to their types
|
||||
@ -304,7 +304,7 @@ parsing_done:
|
||||
}
|
||||
else // Add GUID info for valid entries
|
||||
info += UString("Variable GUID: ") + guid + UString("\n");
|
||||
|
||||
|
||||
// Add GUID index information
|
||||
if (hasGuidIndex)
|
||||
info += usprintf("GUID index: %u\n", guidIndex);
|
||||
@ -314,13 +314,13 @@ parsing_done:
|
||||
entryHeader->Size, entryHeader->Size,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size());
|
||||
|
||||
|
||||
// Add attributes info
|
||||
info += usprintf("\nAttributes: %02Xh", entryHeader->Attributes);
|
||||
// Translate attributes to text
|
||||
if (entryHeader->Attributes && entryHeader->Attributes != 0xFF)
|
||||
info += UString(" (") + nvarAttributesToUString(entryHeader->Attributes) + UString(")");
|
||||
|
||||
|
||||
// Add next node info
|
||||
if (!isInvalid && entryHeader->Next != lastVariableFlag)
|
||||
info += usprintf("\nNext node at offset: %Xh", localOffset + offset + entryHeader->Next);
|
||||
@ -334,17 +334,17 @@ parsing_done:
|
||||
// Add checksum
|
||||
if (hasChecksum)
|
||||
info += usprintf("\nChecksum: %02Xh", storedChecksum) +
|
||||
(calculatedChecksum ? usprintf(", invalid, should be %02Xh", 0x100 - calculatedChecksum) : UString(", valid"));
|
||||
|
||||
(calculatedChecksum ? usprintf(", invalid, should be %02Xh", 0x100 - calculatedChecksum) : UString(", valid"));
|
||||
|
||||
// Add timestamp
|
||||
if (hasTimestamp)
|
||||
if (hasTimestamp)
|
||||
info += usprintf("\nTimestamp: %" PRIX64 "h", timestamp);
|
||||
|
||||
|
||||
// Add hash
|
||||
if (hasHash)
|
||||
if (hasHash)
|
||||
info += UString("\nHash: ") + UString(hash.toHex().constData());
|
||||
}
|
||||
|
||||
|
||||
// Add tree item
|
||||
UModelIndex varIndex = model->addItem(localOffset + offset, Types::NvarEntry, subtype, name, text, info, header, body, tail, Movable, index);
|
||||
|
||||
@ -354,19 +354,19 @@ parsing_done:
|
||||
// Show messages
|
||||
if (msgUnknownExtDataFormat) msg(UString("parseNvarStore: unknown extended data format"), varIndex);
|
||||
if (msgExtHeaderTooLong) msg(usprintf("parseNvarStore: extended header size (%Xh) is greater than body size (%Xh)",
|
||||
extendedHeaderSize, body.size()), varIndex);
|
||||
extendedHeaderSize, body.size()), varIndex);
|
||||
if (msgExtDataTooShort) msg(usprintf("parseNvarStore: extended header size (%Xh) is too small for timestamp and hash",
|
||||
tail.size()), varIndex);
|
||||
tail.size()), varIndex);
|
||||
|
||||
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
|
||||
if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry)
|
||||
if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry)
|
||||
&& *(const UINT32*)body.constData() == NVRAM_NVAR_ENTRY_SIGNATURE)
|
||||
parseNvarStore(varIndex);
|
||||
|
||||
|
||||
// Move to next exntry
|
||||
offset += entryHeader->Size;
|
||||
}
|
||||
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
@ -496,15 +496,15 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
UModelIndex current = index.child(i, 0);
|
||||
switch (model->type(current)) {
|
||||
case Types::VssStore:
|
||||
case Types::FdcStore: parseVssStoreBody(current, 0); break;
|
||||
case Types::LenovoVssStore: parseVssStoreBody(current, 4); break;
|
||||
case Types::FsysStore: parseFsysStoreBody(current); break;
|
||||
case Types::EvsaStore: parseEvsaStoreBody(current); break;
|
||||
case Types::FlashMapStore: parseFlashMapBody(current); break;
|
||||
case Types::FdcStore: return parseFdcStoreBody(current);
|
||||
case Types::VssStore: return parseVssStoreBody(current, 0);
|
||||
case Types::Vss2Store: return parseVssStoreBody(current, 4);
|
||||
case Types::FsysStore: return parseFsysStoreBody(current);
|
||||
case Types::EvsaStore: return parseEvsaStoreBody(current);
|
||||
case Types::FlashMapStore: return parseFlashMapBody(current);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
@ -531,18 +531,18 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
||||
// All checks passed, store found
|
||||
break;
|
||||
}
|
||||
else if (*currentPos == LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *currentPos == LENOVO_VSS_STORE_GUID_PART1) { //Lenovo VSS store signatures found, perform checks
|
||||
else if (*currentPos == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *currentPos == NVRAM_VSS2_STORE_GUID_PART1) { //VSS2 store signatures found, perform checks
|
||||
UByteArray guid = UByteArray(volume.constData() + offset, sizeof(EFI_GUID));
|
||||
if (guid != LENOVO_AUTH_VAR_KEY_DATABASE_GUID && guid != LENOVO_VSS_STORE_GUID) // Check the whole signature
|
||||
if (guid != NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID && guid != NVRAM_VSS2_STORE_GUID) // Check the whole signature
|
||||
continue;
|
||||
|
||||
const LENOVO_VSS_VARIABLE_STORE_HEADER* vssHeader = (const LENOVO_VSS_VARIABLE_STORE_HEADER*)currentPos;
|
||||
const VSS2_VARIABLE_STORE_HEADER* vssHeader = (const VSS2_VARIABLE_STORE_HEADER*)currentPos;
|
||||
if (vssHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) {
|
||||
msg(usprintf("findNextStore: Lenovo VSS store candidate at offset %Xh skipped, has invalid format %02Xh", localOffset + offset, vssHeader->Format), index);
|
||||
msg(usprintf("findNextStore: VSS2 store candidate at offset %Xh skipped, has invalid format %02Xh", localOffset + offset, vssHeader->Format), index);
|
||||
continue;
|
||||
}
|
||||
if (vssHeader->Size == 0 || vssHeader->Size == 0xFFFFFFFF) {
|
||||
msg(usprintf("findNextStore: Lenovo VSS store candidate at offset %Xh skipped, has invalid size %Xh", localOffset + offset, vssHeader->Size), index);
|
||||
msg(usprintf("findNextStore: VSS2 store candidate at offset %Xh skipped, has invalid size %Xh", localOffset + offset, vssHeader->Size), index);
|
||||
continue;
|
||||
}
|
||||
// All checks passed, store found
|
||||
@ -585,7 +585,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
||||
}
|
||||
else if (*currentPos == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *currentPos == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1) { //Possible FTW block signature found
|
||||
UByteArray guid = UByteArray(volume.constData() + offset, sizeof(EFI_GUID));
|
||||
if (guid != NVRAM_MAIN_STORE_VOLUME_GUID && guid != EDKII_WORKING_BLOCK_SIGNATURE_GUID && guid != LENOVO_WORKING_BLOCK_SIGNATURE_GUID) // Check the whole signature
|
||||
if (guid != NVRAM_MAIN_STORE_VOLUME_GUID && guid != EDKII_WORKING_BLOCK_SIGNATURE_GUID && guid != VSS2_WORKING_BLOCK_SIGNATURE_GUID) // Check the whole signature
|
||||
continue;
|
||||
|
||||
// Detect header variant based on WriteQueueSize
|
||||
@ -659,11 +659,11 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
||||
break;
|
||||
}
|
||||
else if (*currentPos == OEM_ACTIVATION_MARKER_WINDOWS_FLAG_PART1) { // SLIC marker
|
||||
if (offset >= dataSize - sizeof(UINT64) ||
|
||||
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*)(volume.constData() + offset - 26);
|
||||
// Check reserved bytes
|
||||
bool reservedBytesValid = true;
|
||||
@ -696,8 +696,8 @@ USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOff
|
||||
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
||||
storeSize = vssHeader->Size;
|
||||
}
|
||||
else if (*signature == LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == LENOVO_VSS_STORE_GUID_PART1) {
|
||||
const LENOVO_VSS_VARIABLE_STORE_HEADER* vssHeader = (const LENOVO_VSS_VARIABLE_STORE_HEADER*)signature;
|
||||
else if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1) {
|
||||
const VSS2_VARIABLE_STORE_HEADER* vssHeader = (const VSS2_VARIABLE_STORE_HEADER*)signature;
|
||||
storeSize = vssHeader->Size;
|
||||
}
|
||||
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
||||
@ -744,10 +744,10 @@ USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOff
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
const UINT32 dataSize = (const UINT32)store.size();
|
||||
|
||||
|
||||
// Check store size
|
||||
if (dataSize < sizeof(VSS_VARIABLE_STORE_HEADER)) {
|
||||
msg(UString("parseVssStoreHeader: volume body is too small even for VSS store header"), parent);
|
||||
@ -757,28 +757,34 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
|
||||
// Get VSS store header
|
||||
const VSS_VARIABLE_STORE_HEADER* vssStoreHeader = (const VSS_VARIABLE_STORE_HEADER*)store.constData();
|
||||
|
||||
// Check for size override
|
||||
UINT32 storeSize = vssStoreHeader->Size;
|
||||
if (sizeOverride) {
|
||||
storeSize = dataSize;
|
||||
}
|
||||
|
||||
// Check store size
|
||||
if (dataSize < vssStoreHeader->Size) {
|
||||
if (dataSize < storeSize) {
|
||||
msg(usprintf("parseVssStoreHeader: VSS store size %Xh (%u) is greater than volume body size %Xh (%u)",
|
||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
||||
storeSize, storeSize,
|
||||
dataSize, dataSize), parent);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
// Construct header and body
|
||||
UByteArray header = store.left(sizeof(VSS_VARIABLE_STORE_HEADER));
|
||||
UByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), vssStoreHeader->Size - sizeof(VSS_VARIABLE_STORE_HEADER));
|
||||
UByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), storeSize - sizeof(VSS_VARIABLE_STORE_HEADER));
|
||||
|
||||
// Add info
|
||||
bool isSvsStore = (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE);
|
||||
UString name = isSvsStore ? UString("SVS store") : UString("VSS store");
|
||||
UString info = usprintf("Signature: %s\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
|
||||
isSvsStore ? "$SVS" : "$VSS",
|
||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
||||
storeSize, storeSize,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
vssStoreHeader->Format,
|
||||
vssStoreHeader->State,
|
||||
vssStoreHeader->State,
|
||||
vssStoreHeader->Unknown);
|
||||
|
||||
// Add tree item
|
||||
@ -787,44 +793,50 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS NvramParser::parseLenovoVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
USTATUS NvramParser::parseVss2StoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
const UINT32 dataSize = (const UINT32)store.size();
|
||||
|
||||
// Check store size
|
||||
if (dataSize < sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER)) {
|
||||
msg(UString("parseLenovoVssStoreHeader: volume body is too small even for VSS store header"), parent);
|
||||
if (dataSize < sizeof(VSS2_VARIABLE_STORE_HEADER)) {
|
||||
msg(UString("parseVss2StoreHeader: volume body is too small even for VSS2 store header"), parent);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
// Get VSS store header
|
||||
const LENOVO_VSS_VARIABLE_STORE_HEADER* vssStoreHeader = (const LENOVO_VSS_VARIABLE_STORE_HEADER*)store.constData();
|
||||
// Get VSS2 store header
|
||||
const VSS2_VARIABLE_STORE_HEADER* vssStoreHeader = (const VSS2_VARIABLE_STORE_HEADER*)store.constData();
|
||||
|
||||
// Check for size override
|
||||
UINT32 storeSize = vssStoreHeader->Size;
|
||||
if (sizeOverride) {
|
||||
storeSize = dataSize;
|
||||
}
|
||||
|
||||
// Check store size
|
||||
if (dataSize < vssStoreHeader->Size) {
|
||||
msg(usprintf("parseLenovoVssStoreHeader: VSS store size %Xh (%u) is greater than volume body size %Xh (%u)",
|
||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
||||
if (dataSize < storeSize) {
|
||||
msg(usprintf("parseVssStoreHeader: VSS2 store size %Xh (%u) is greater than volume body size %Xh (%u)",
|
||||
storeSize, storeSize,
|
||||
dataSize, dataSize), parent);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
// Construct header and body
|
||||
UByteArray header = store.left(sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER));
|
||||
UByteArray body = store.mid(sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER), vssStoreHeader->Size - sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER));
|
||||
UByteArray header = store.left(sizeof(VSS2_VARIABLE_STORE_HEADER));
|
||||
UByteArray body = store.mid(sizeof(VSS2_VARIABLE_STORE_HEADER), storeSize - sizeof(VSS2_VARIABLE_STORE_HEADER));
|
||||
|
||||
// Add info
|
||||
UString name = UString("Lenovo VSS store");
|
||||
UString name = UString("VSS2 store");
|
||||
UString info = UString("Signature: ") + guidToUString(vssStoreHeader->Signature, false) +
|
||||
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
|
||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
vssStoreHeader->Format,
|
||||
vssStoreHeader->State,
|
||||
vssStoreHeader->Unknown);
|
||||
storeSize, storeSize,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
vssStoreHeader->Format,
|
||||
vssStoreHeader->State,
|
||||
vssStoreHeader->Unknown);
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(localOffset, Types::LenovoVssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
index = model->addItem(localOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
@ -886,12 +898,12 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32
|
||||
UString name("FTW store");
|
||||
UString info = UString("Signature: ") + guidToUString(ftw32BlockHeader->Signature, false) +
|
||||
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh",
|
||||
ftwBlockSize, ftwBlockSize,
|
||||
headerSize, headerSize,
|
||||
body.size(), body.size(),
|
||||
ftw32BlockHeader->State,
|
||||
ftw32BlockHeader->Crc) +
|
||||
(ftw32BlockHeader->Crc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
|
||||
ftwBlockSize, ftwBlockSize,
|
||||
headerSize, headerSize,
|
||||
body.size(), body.size(),
|
||||
ftw32BlockHeader->State,
|
||||
ftw32BlockHeader->Crc) +
|
||||
(ftw32BlockHeader->Crc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(localOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
@ -920,29 +932,11 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
// Determine internal volume header size
|
||||
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(fdcStoreHeader + 1);
|
||||
UINT32 headerSize;
|
||||
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
||||
const EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (const EFI_FIRMWARE_VOLUME_EXT_HEADER*)((const UINT8*)volumeHeader + volumeHeader->ExtHeaderOffset);
|
||||
headerSize = volumeHeader->ExtHeaderOffset + extendedHeader->ExtHeaderSize;
|
||||
}
|
||||
else
|
||||
headerSize = volumeHeader->HeaderLength;
|
||||
|
||||
// Extended header end can be unaligned
|
||||
headerSize = ALIGN8(headerSize);
|
||||
|
||||
// Add VSS store header
|
||||
headerSize += sizeof(VSS_VARIABLE_STORE_HEADER);
|
||||
|
||||
// Add FDC header
|
||||
headerSize += sizeof(FDC_VOLUME_HEADER);
|
||||
|
||||
// Check sanity of combined header size
|
||||
// Check header size
|
||||
UINT32 headerSize = sizeof(FDC_VOLUME_HEADER);
|
||||
if (dataSize < headerSize) {
|
||||
msg(usprintf("parseFdcStoreHeader: FDC store header size %Xh (%u) is greater than volume body size %Xh (%u)",
|
||||
fdcStoreHeader->Size,fdcStoreHeader->Size,
|
||||
fdcStoreHeader->Size, fdcStoreHeader->Size,
|
||||
dataSize, dataSize), parent);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
@ -958,8 +952,6 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size());
|
||||
|
||||
// TODO: add internal headers info
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(localOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
|
||||
@ -1003,7 +995,7 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32
|
||||
fsysStoreHeader->Size, fsysStoreHeader->Size,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
fsysStoreHeader->Unknown0,
|
||||
fsysStoreHeader->Unknown0,
|
||||
fsysStoreHeader->Unknown1)
|
||||
+ (storedCrc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
|
||||
|
||||
@ -1101,7 +1093,7 @@ USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UI
|
||||
USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
const UINT32 dataSize = (const UINT32)store.size();
|
||||
|
||||
|
||||
// Check store size
|
||||
if (dataSize < sizeof(PHOENIX_CMDB_HEADER)) {
|
||||
msg(UString("parseCmdbStoreHeader: volume body is too small even for CMDB store header"), parent);
|
||||
@ -1208,7 +1200,7 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3
|
||||
"Version: %08Xh\nOEM ID: %s\nOEM table ID: %s\nWindows flag: WINDOWS\nSLIC version: %08Xh",
|
||||
markerHeader->Size, markerHeader->Size,
|
||||
header.size(), header.size(),
|
||||
markerHeader->Version,
|
||||
markerHeader->Version,
|
||||
(const char*)UString((const char*)&(markerHeader->OemId)).left(6).toLocal8Bit(),
|
||||
(const char*)UString((const char*)&(markerHeader->OemTableId)).left(8).toLocal8Bit(),
|
||||
markerHeader->SlicVersion);
|
||||
@ -1257,10 +1249,10 @@ USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const U
|
||||
ucodeHeader->DateDay,
|
||||
ucodeHeader->DateMonth,
|
||||
ucodeHeader->DateYear,
|
||||
ucodeHeader->CpuSignature,
|
||||
ucodeHeader->CpuSignature,
|
||||
ucodeHeader->Revision,
|
||||
ucodeHeader->Checksum,
|
||||
ucodeHeader->LoaderRevision,
|
||||
ucodeHeader->Checksum,
|
||||
ucodeHeader->LoaderRevision,
|
||||
ucodeHeader->CpuFlags);
|
||||
|
||||
// Add tree item
|
||||
@ -1281,28 +1273,28 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
|
||||
|
||||
// Check signature and run parser function needed
|
||||
// VSS/SVS store
|
||||
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
|
||||
return parseVssStoreHeader(store, localOffset, parent, index);
|
||||
// Lenovo VSS store
|
||||
if (*signature == LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == LENOVO_VSS_STORE_GUID_PART1)
|
||||
return parseLenovoVssStoreHeader(store, localOffset, parent, index);
|
||||
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
|
||||
return parseVssStoreHeader(store, localOffset, false, parent, index);
|
||||
// VSS2 store
|
||||
if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1)
|
||||
return parseVss2StoreHeader(store, localOffset, false, parent, index);
|
||||
// FTW store
|
||||
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *signature == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1)
|
||||
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *signature == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1)
|
||||
return parseFtwStoreHeader(store, localOffset, parent, index);
|
||||
// FDC store
|
||||
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE)
|
||||
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE)
|
||||
return parseFdcStoreHeader(store, localOffset, parent, index);
|
||||
// Apple Fsys/Gaid store
|
||||
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *signature == NVRAM_APPLE_GAID_STORE_SIGNATURE)
|
||||
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *signature == NVRAM_APPLE_GAID_STORE_SIGNATURE)
|
||||
return parseFsysStoreHeader(store, localOffset, parent, index);
|
||||
// EVSA store
|
||||
else if (*(signature + 1) == NVRAM_EVSA_STORE_SIGNATURE)
|
||||
else if (*(signature + 1) == NVRAM_EVSA_STORE_SIGNATURE)
|
||||
return parseEvsaStoreHeader(store, localOffset, parent, index);
|
||||
// Phoenix SCT flash map
|
||||
else if (*signature == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1)
|
||||
else if (*signature == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1)
|
||||
return parseFlashMapStoreHeader(store, localOffset, parent, index);
|
||||
// Phoenix CMDB store
|
||||
else if (*signature == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE)
|
||||
else if (*signature == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE)
|
||||
return parseCmdbStoreHeader(store, localOffset, parent, index);
|
||||
// SLIC pubkey
|
||||
else if (*(signature + 4) == OEM_ACTIVATION_PUBKEY_MAGIC)
|
||||
@ -1319,6 +1311,49 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS NvramParser::parseFdcStoreBody(const UModelIndex & index)
|
||||
{
|
||||
// Sanity check
|
||||
if (!index.isValid())
|
||||
return U_INVALID_PARAMETER;
|
||||
|
||||
// Get item data
|
||||
const UByteArray data = model->body(index);
|
||||
|
||||
// Get local offset
|
||||
UINT32 localOffset = model->offset(index) + model->header(index).size();
|
||||
|
||||
// The body is a firmware volume with either a VSS or VSS2 store
|
||||
UModelIndex volumeIndex;
|
||||
USTATUS status = ffsParser->parseVolumeHeader(data, localOffset, index, volumeIndex);
|
||||
if (status || !volumeIndex.isValid()) {
|
||||
msg(UString("parseFdcStoreBody: store can't be parsed as FDC store"), index);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
// Determine if it's a VSS or VSS2 store inside
|
||||
UByteArray store = model->body(volumeIndex);
|
||||
if (store.size() >= sizeof(UINT32) && *(const UINT32*)store.constData() == NVRAM_VSS_STORE_SIGNATURE) {
|
||||
UModelIndex vssIndex;
|
||||
status = parseVssStoreHeader(store, localOffset + model->header(volumeIndex).size(), true, volumeIndex, vssIndex);
|
||||
if (status)
|
||||
return status;
|
||||
return parseVssStoreBody(vssIndex, 0);
|
||||
}
|
||||
else if (store.size() >= sizeof(EFI_GUID) && store.left(sizeof(EFI_GUID)) == NVRAM_FDC_STORE_GUID) {
|
||||
UModelIndex vss2Index;
|
||||
status = parseVss2StoreHeader(store, localOffset + model->header(volumeIndex).size(), true, volumeIndex, vss2Index);
|
||||
if (status)
|
||||
return status;
|
||||
return parseVssStoreBody(vss2Index, 0);
|
||||
}
|
||||
else {
|
||||
msg(UString("parseFdcStoreBody: internal volume can't be parsed as VSS/VSS2 store"), index);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignment)
|
||||
{
|
||||
// Sanity check
|
||||
@ -1346,7 +1381,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
|
||||
msg(UString("parseVssStoreBody: store body is too small even for VSS variable header"), index);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UINT32 offset = 0;
|
||||
|
||||
// Parse all variables
|
||||
@ -1355,7 +1390,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
|
||||
bool isAuthenticated = false;
|
||||
bool isAppleCrc32 = false;
|
||||
bool isIntelSpecial = false;
|
||||
|
||||
|
||||
UINT32 storedCrc32 = 0;
|
||||
UINT32 calculatedCrc32 = 0;
|
||||
UINT64 monotonicCounter = 0;
|
||||
@ -1489,7 +1524,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
|
||||
}
|
||||
|
||||
UString info;
|
||||
|
||||
|
||||
// Rename invalid variables
|
||||
if (isInvalid) {
|
||||
name = UString("Invalid");
|
||||
@ -1504,7 +1539,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
|
||||
info += usprintf("Full size: %Xh (%u)\nHeader size %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nReserved: %02Xh\nAttributes: %08Xh (",
|
||||
variableSize, variableSize,
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
body.size(), body.size(),
|
||||
variableHeader->State,
|
||||
variableHeader->Reserved,
|
||||
variableHeader->Attributes) + vssAttributesToUString(variableHeader->Attributes) + UString(")");
|
||||
@ -1568,7 +1603,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
|
||||
UINT8 nameSize = *(UINT8*)(data.constData() + offset);
|
||||
bool valid = !(nameSize & 0x80); // Last bit is a validity bit, 0 means valid
|
||||
nameSize &= 0x7F;
|
||||
|
||||
|
||||
// Check sanity
|
||||
if (unparsedSize >= nameSize + sizeof(UINT8)) {
|
||||
variableSize = nameSize + sizeof(UINT8);
|
||||
@ -1582,7 +1617,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
|
||||
// There is no data afterward, add EOF variable and free space and return
|
||||
UByteArray header = data.mid(offset, sizeof(UINT8) + nameSize);
|
||||
UString info = usprintf("Full size: %Xh (%u)", header.size(), header.size());
|
||||
|
||||
|
||||
// Add EOF tree item
|
||||
model->addItem(localOffset + offset, Types::FsysEntry, Subtypes::NormalFsysEntry, UString("EOF"), UString(), info, header, UByteArray(), UByteArray(), Fixed, index);
|
||||
|
||||
@ -1610,7 +1645,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
|
||||
|
||||
// Add padding tree item
|
||||
model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
|
||||
|
||||
|
||||
// Show message
|
||||
msg(UString("parseFsysStoreBody: next variable appears too big, added as padding"), index);
|
||||
|
||||
@ -1633,7 +1668,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
|
||||
// Move to next variable
|
||||
offset += variableSize;
|
||||
}
|
||||
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1703,7 +1738,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
|
||||
calculated = calculateChecksum8(((const UINT8*)entryHeader) + 2, entryHeader->Size - 2);
|
||||
|
||||
// GUID entry
|
||||
if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_GUID1 ||
|
||||
if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_GUID1 ||
|
||||
entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_GUID2) {
|
||||
const EVSA_GUID_ENTRY* guidHeader = (const EVSA_GUID_ENTRY*)entryHeader;
|
||||
header = data.mid(offset, sizeof(EVSA_GUID_ENTRY));
|
||||
@ -1733,7 +1768,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
nameHeader->Header.Type,
|
||||
nameHeader->Header.Checksum)
|
||||
nameHeader->Header.Checksum)
|
||||
+ (nameHeader->Header.Checksum != calculated ? usprintf(", invalid, should be %02Xh", calculated) : UString(", valid"))
|
||||
+ usprintf("\nVarId: %04Xh", nameHeader->VarId);
|
||||
subtype = Subtypes::NameEvsaEntry;
|
||||
@ -1765,9 +1800,9 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
|
||||
dataHeader->Header.Checksum)
|
||||
+ (dataHeader->Header.Checksum != calculated ? usprintf(", invalid, should be %02Xh", calculated) : UString(", valid"))
|
||||
+ usprintf("\nVarId: %04Xh\nGuidId: %04Xh\nAttributes: %08Xh (",
|
||||
dataHeader->VarId,
|
||||
dataHeader->GuidId,
|
||||
dataHeader->Attributes)
|
||||
dataHeader->VarId,
|
||||
dataHeader->GuidId,
|
||||
dataHeader->Attributes)
|
||||
+ evsaAttributesToUString(dataHeader->Attributes) + UString(")");
|
||||
subtype = Subtypes::DataEvsaEntry;
|
||||
}
|
||||
@ -1786,7 +1821,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
|
||||
|
||||
// Show message
|
||||
msg(usprintf("parseEvsaStoreBody: unknown variable of type %02Xh found at offset %Xh, the rest of unparsed store added as padding", entryHeader->Type, offset), itemIndex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1805,12 +1840,12 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
|
||||
UByteArray header = model->header(current);
|
||||
const EVSA_DATA_ENTRY* dataHeader = (const EVSA_DATA_ENTRY*)header.constData();
|
||||
UString guid;
|
||||
if (guidMap.count(dataHeader->GuidId))
|
||||
if (guidMap.count(dataHeader->GuidId))
|
||||
guid = guidToUString(guidMap[dataHeader->GuidId], false);
|
||||
UString name;
|
||||
if (nameMap.count(dataHeader->VarId))
|
||||
name = nameMap[dataHeader->VarId];
|
||||
|
||||
|
||||
// Check for variable validity
|
||||
if (guid.isEmpty() && name.isEmpty()) { // Both name and guid aren't found
|
||||
model->setSubtype(current, Subtypes::InvalidEvsaEntry);
|
||||
@ -1855,7 +1890,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index)
|
||||
UINT32 localOffset = model->offset(index) + model->header(index).size();
|
||||
const UByteArray data = model->body(index);
|
||||
|
||||
|
||||
|
||||
const UINT32 dataSize = (UINT32)data.size();
|
||||
UINT32 offset = 0;
|
||||
UINT32 unparsedSize = dataSize;
|
||||
@ -1880,18 +1915,19 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index)
|
||||
}
|
||||
|
||||
UString name = guidToUString(entryHeader->Guid);
|
||||
|
||||
|
||||
// Construct header
|
||||
UByteArray header = data.mid(offset, sizeof(PHOENIX_FLASH_MAP_ENTRY));
|
||||
|
||||
// Add info
|
||||
UString info = UString("Entry GUID: ") + guidToUString(entryHeader->Guid, false) + usprintf("\nFull size: 24h (36)\nHeader size: 24h (36)\nBody size: 0h (0)\n"
|
||||
"Entry type: %04Xh\nData type: %04Xh\nMemory address: %08Xh\nSize: %08Xh\nOffset: %08Xh",
|
||||
entryHeader->EntryType,
|
||||
entryHeader->DataType,
|
||||
entryHeader->PhysicalAddress,
|
||||
entryHeader->Size,
|
||||
entryHeader->Offset);
|
||||
UString info = UString("Entry GUID: ") + guidToUString(entryHeader->Guid, false) +
|
||||
usprintf("\nFull size: 24h (36)\nHeader size: 24h (36)\nBody size: 0h (0)\n"
|
||||
"Entry type: %04Xh\nData type: %04Xh\nMemory address: %08Xh\nSize: %08Xh\nOffset: %08Xh",
|
||||
entryHeader->EntryType,
|
||||
entryHeader->DataType,
|
||||
entryHeader->PhysicalAddress,
|
||||
entryHeader->Size,
|
||||
entryHeader->Offset);
|
||||
|
||||
// Determine subtype
|
||||
UINT8 subtype = 0;
|
||||
|
@ -21,13 +21,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "ustring.h"
|
||||
#include "ubytearray.h"
|
||||
#include "treemodel.h"
|
||||
#include "ffsparser.h"
|
||||
|
||||
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
||||
class NvramParser
|
||||
{
|
||||
public:
|
||||
// Default constructor and destructor
|
||||
NvramParser(TreeModel* treeModel) : model(treeModel) {}
|
||||
NvramParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {}
|
||||
~NvramParser() {}
|
||||
|
||||
// Returns messages
|
||||
@ -41,6 +42,7 @@ public:
|
||||
|
||||
private:
|
||||
TreeModel *model;
|
||||
FfsParser *ffsParser;
|
||||
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));
|
||||
@ -50,8 +52,8 @@ private:
|
||||
USTATUS getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
|
||||
USTATUS parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseLenovoVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseVss2StoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
@ -62,6 +64,7 @@ private:
|
||||
USTATUS parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
USTATUS parseFdcStoreBody(const UModelIndex & index);
|
||||
USTATUS parseVssStoreBody(const UModelIndex & index, const UINT8 alignment);
|
||||
USTATUS parseFsysStoreBody(const UModelIndex & index);
|
||||
USTATUS parseEvsaStoreBody(const UModelIndex & index);
|
||||
@ -72,7 +75,7 @@ class NvramParser
|
||||
{
|
||||
public:
|
||||
// Default constructor and destructor
|
||||
NvramParser(TreeModel* treeModel) { U_UNUSED_PARAMETER(treeModel); }
|
||||
NvramParser(TreeModel* treeModel, FfsParser* parser) { U_UNUSED_PARAMETER(treeModel); U_UNUSED_PARAMETER(parser); }
|
||||
~NvramParser() {}
|
||||
|
||||
// Returns messages
|
||||
|
@ -26,11 +26,13 @@ QVariant TreeModel::data(const UModelIndex &index, int role) const
|
||||
if (role == Qt::DisplayRole) {
|
||||
return (const char*)item->data(index.column()).toLocal8Bit();
|
||||
}
|
||||
#if defined (QT_GUI_LIB)
|
||||
else if (role == Qt::BackgroundRole) {
|
||||
if (markingEnabled && marking(index) > 0) {
|
||||
if (markingEnabledFlag && marking(index) > 0) {
|
||||
return QBrush((Qt::GlobalColor)marking(index));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (role == Qt::UserRole) {
|
||||
return (const char*)item->info().toLocal8Bit();
|
||||
}
|
||||
@ -50,18 +52,12 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return tr("Name");
|
||||
case 1:
|
||||
return tr("Action");
|
||||
case 2:
|
||||
return tr("Type");
|
||||
case 3:
|
||||
return tr("Subtype");
|
||||
case 4:
|
||||
return tr("Text");
|
||||
switch (section) {
|
||||
case 0: return tr("Name");
|
||||
case 1: return tr("Action");
|
||||
case 2: return tr("Type");
|
||||
case 3: return tr("Subtype");
|
||||
case 4: return tr("Text");
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,16 +86,11 @@ UString TreeModel::headerData(int section, int orientation,
|
||||
if (orientation == 1 && role == 0) {
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return UString("Name");
|
||||
case 1:
|
||||
return UString("Action");
|
||||
case 2:
|
||||
return UString("Type");
|
||||
case 3:
|
||||
return UString("Subtype");
|
||||
case 4:
|
||||
return UString("Text");
|
||||
case 0: return UString("Name");
|
||||
case 1: return UString("Action");
|
||||
case 2: return UString("Type");
|
||||
case 3: return UString("Subtype");
|
||||
case 4: return UString("Text");
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +321,9 @@ void TreeModel::setCompressed(const UModelIndex &index, const bool compressed)
|
||||
|
||||
void TreeModel::TreeModel::setMarkingEnabled(const bool enabled)
|
||||
{
|
||||
markingEnabled = enabled; emit dataChanged(QModelIndex(), QModelIndex());
|
||||
markingEnabledFlag = enabled;
|
||||
|
||||
emit dataChanged(UModelIndex(), UModelIndex());
|
||||
}
|
||||
|
||||
void TreeModel::setMarking(const UModelIndex &index, const UINT8 marking)
|
||||
|
@ -25,7 +25,9 @@ enum ItemFixedState {
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QObject>
|
||||
#if defined(QT_GUI_LIB)
|
||||
#include <QBrush>
|
||||
#endif
|
||||
|
||||
#include "ustring.h"
|
||||
#include "ubytearray.h"
|
||||
@ -86,15 +88,15 @@ class TreeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
bool markingEnabled;
|
||||
TreeItem *rootItem;
|
||||
bool markingEnabledFlag;
|
||||
|
||||
public:
|
||||
QVariant data(const UModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const UModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
TreeModel(QObject *parent = 0) : QAbstractItemModel(parent), markingEnabled(true) {
|
||||
TreeModel(QObject *parent = 0) : QAbstractItemModel(parent), markingEnabledFlag(true) {
|
||||
rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), true, false);
|
||||
}
|
||||
|
||||
@ -105,6 +107,8 @@ class TreeModel
|
||||
{
|
||||
private:
|
||||
TreeItem *rootItem;
|
||||
bool markingEnabledFlag;
|
||||
|
||||
void dataChanged(const UModelIndex &, const UModelIndex &) {}
|
||||
void layoutAboutToBeChanged() {}
|
||||
void layoutChanged() {}
|
||||
@ -130,6 +134,9 @@ public:
|
||||
delete rootItem;
|
||||
}
|
||||
|
||||
bool markingEnabled() { return markingEnabledFlag; }
|
||||
void setMarkingEnabled(const bool enabled);
|
||||
|
||||
UModelIndex index(int row, int column, const UModelIndex &parent = UModelIndex()) const;
|
||||
UModelIndex parent(const UModelIndex &index) const;
|
||||
int rowCount(const UModelIndex &parent = UModelIndex()) const;
|
||||
@ -145,7 +152,6 @@ public:
|
||||
void addInfo(const UModelIndex &index, const UString &info, const bool append = TRUE);
|
||||
void setFixed(const UModelIndex &index, const bool fixed);
|
||||
void setCompressed(const UModelIndex &index, const bool compressed);
|
||||
void setMarkingEnabled(const bool enabled);
|
||||
void setMarking(const UModelIndex &index, const UINT8 marking);
|
||||
|
||||
UINT32 offset(const UModelIndex &index) const;
|
||||
@ -163,7 +169,6 @@ public:
|
||||
bool fixed(const UModelIndex &index) const;
|
||||
bool compressed(const UModelIndex &index) const;
|
||||
UINT8 marking(const UModelIndex &index) const;
|
||||
|
||||
UINT8 action(const UModelIndex &index) const;
|
||||
|
||||
UByteArray parsingData(const UModelIndex &index) const;
|
||||
|
@ -23,11 +23,17 @@ UString regionTypeToUString(const UINT8 type)
|
||||
case Subtypes::MeRegion: return UString("ME");
|
||||
case Subtypes::GbeRegion: return UString("GbE");
|
||||
case Subtypes::PdrRegion: return UString("PDR");
|
||||
case Subtypes::DevExp1Region: return UString("DevExp1");
|
||||
case Subtypes::Bios2Region: return UString("BIOS2");
|
||||
case Subtypes::MicrocodeRegion: return UString("Microcode");
|
||||
case Subtypes::EcRegion: return UString("EC");
|
||||
case Subtypes::DevExp2Region: return UString("DevExp2");
|
||||
case Subtypes::IeRegion: return UString("IE");
|
||||
case Subtypes::Tgbe1Region: return UString("10GbE1");
|
||||
case Subtypes::Tgbe2Region: return UString("10GbE2");
|
||||
case Subtypes::Reserved1Region: return UString("Reserved1");
|
||||
case Subtypes::Reserved2Region: return UString("Reserved2");
|
||||
case Subtypes::Reserved3Region: return UString("Reserved3");
|
||||
case Subtypes::EcRegion: return UString("EC");
|
||||
case Subtypes::Reserved4Region: return UString("Reserved4");
|
||||
case Subtypes::PttRegion: return UString("PTT");
|
||||
};
|
||||
|
||||
return UString("Unknown");
|
||||
@ -46,7 +52,7 @@ UString itemTypeToUString(const UINT8 type)
|
||||
case Types::Section: return UString("Section");
|
||||
case Types::FreeSpace: return UString("Free space");
|
||||
case Types::VssStore: return UString("VSS store");
|
||||
case Types::LenovoVssStore: return UString("Lenovo VSS store");
|
||||
case Types::Vss2Store: return UString("VSS2 store");
|
||||
case Types::FtwStore: return UString("FTW store");
|
||||
case Types::FdcStore: return UString("FDC store");
|
||||
case Types::FsysStore: return UString("Fsys store");
|
||||
@ -71,7 +77,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
|
||||
case Types::Root:
|
||||
case Types::FreeSpace:
|
||||
case Types::VssStore:
|
||||
case Types::LenovoVssStore:
|
||||
case Types::Vss2Store:
|
||||
case Types::FdcStore:
|
||||
case Types::FsysStore:
|
||||
case Types::EvsaStore:
|
||||
@ -149,7 +155,7 @@ UString compressionTypeToUString(const UINT8 algorithm)
|
||||
case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano");
|
||||
case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1");
|
||||
case COMPRESSION_ALGORITHM_LZMA: return UString("LZMA");
|
||||
case COMPRESSION_ALGORITHM_IMLZMA: return UString("Intel modified LZMA");
|
||||
case COMPRESSION_ALGORITHM_IMLZMA: return UString("Intel LZMA");
|
||||
}
|
||||
|
||||
return UString("Unknown");
|
||||
@ -173,16 +179,17 @@ UString actionTypeToUString(const UINT8 action)
|
||||
UString fitEntryTypeToUString(const UINT8 type)
|
||||
{
|
||||
switch (type & 0x7F) {
|
||||
case FIT_TYPE_HEADER: return ("FIT Header");
|
||||
case FIT_TYPE_MICROCODE: return ("Microcode");
|
||||
case FIT_TYPE_BIOS_AC_MODULE: return ("BIOS ACM");
|
||||
case FIT_TYPE_BIOS_INIT_MODULE: return ("BIOS Init");
|
||||
case FIT_TYPE_TPM_POLICY: return ("TPM Policy");
|
||||
case FIT_TYPE_BIOS_POLICY_DATA: return ("BIOS Policy Data");
|
||||
case FIT_TYPE_TXT_CONF_POLICY: return ("TXT Configuration Policy");
|
||||
case FIT_TYPE_AC_KEY_MANIFEST: return ("BootGuard Key Manifest");
|
||||
case FIT_TYPE_AC_BOOT_POLICY: return ("BootGuard Boot Policy");
|
||||
case FIT_TYPE_EMPTY: return ("Empty");
|
||||
default: return ("Unknown");
|
||||
case FIT_TYPE_HEADER: return UString("FIT Header");
|
||||
case FIT_TYPE_MICROCODE: return UString("Microcode");
|
||||
case FIT_TYPE_BIOS_AC_MODULE: return UString("BIOS ACM");
|
||||
case FIT_TYPE_BIOS_INIT_MODULE: return UString("BIOS Init");
|
||||
case FIT_TYPE_TPM_POLICY: return UString("TPM Policy");
|
||||
case FIT_TYPE_BIOS_POLICY_DATA: return UString("BIOS Policy Data");
|
||||
case FIT_TYPE_TXT_CONF_POLICY: return UString("TXT Configuration Policy");
|
||||
case FIT_TYPE_AC_KEY_MANIFEST: return UString("BootGuard Key Manifest");
|
||||
case FIT_TYPE_AC_BOOT_POLICY: return UString("BootGuard Boot Policy");
|
||||
case FIT_TYPE_EMPTY: return UString("Empty");
|
||||
}
|
||||
|
||||
return UString("Unknown");
|
||||
}
|
@ -44,7 +44,7 @@ namespace Types {
|
||||
Section,
|
||||
FreeSpace,
|
||||
VssStore,
|
||||
LenovoVssStore,
|
||||
Vss2Store,
|
||||
FtwStore,
|
||||
FdcStore,
|
||||
FsysStore,
|
||||
@ -87,11 +87,17 @@ namespace Subtypes {
|
||||
MeRegion,
|
||||
GbeRegion,
|
||||
PdrRegion,
|
||||
DevExp1Region,
|
||||
Bios2Region,
|
||||
MicrocodeRegion,
|
||||
EcRegion,
|
||||
DevExp2Region,
|
||||
IeRegion,
|
||||
Tgbe1Region,
|
||||
Tgbe2Region,
|
||||
Reserved1Region,
|
||||
Reserved2Region,
|
||||
Reserved3Region,
|
||||
EcRegion,
|
||||
Reserved4Region
|
||||
PttRegion
|
||||
};
|
||||
|
||||
enum PaddingSubtypes {
|
||||
|
@ -300,8 +300,8 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp
|
||||
}
|
||||
}
|
||||
|
||||
// 8bit checksum calculation routine
|
||||
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
||||
// 8bit sum calculation routine
|
||||
UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize)
|
||||
{
|
||||
if (!buffer)
|
||||
return 0;
|
||||
@ -311,7 +311,16 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
||||
while (bufferSize--)
|
||||
counter += buffer[bufferSize];
|
||||
|
||||
return (UINT8)(0x100 - counter);
|
||||
return counter;
|
||||
}
|
||||
|
||||
// 8bit checksum calculation routine
|
||||
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
||||
{
|
||||
if (!buffer)
|
||||
return 0;
|
||||
|
||||
return (UINT8)0x100 - calculateSum8(buffer, bufferSize);
|
||||
}
|
||||
|
||||
// 16bit checksum calculation routine
|
||||
|
@ -34,6 +34,9 @@ USTATUS decompress(const UByteArray & compressed, const UINT8 compressionType, U
|
||||
// CRC32 calculation routine
|
||||
UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length);
|
||||
|
||||
// 8bit sum calculation routine
|
||||
UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize);
|
||||
|
||||
// 8bit checksum calculation routine
|
||||
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user