mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58: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/LZMA/SDK/C/LzmaDec.c
|
||||||
../common/Tiano/EfiTianoDecompress.c
|
../common/Tiano/EfiTianoDecompress.c
|
||||||
../common/ustring.cpp
|
../common/ustring.cpp
|
||||||
|
../common/sha256.c
|
||||||
../common/bstrlib/bstrlib.c
|
../common/bstrlib/bstrlib.c
|
||||||
../common/bstrlib/bstrwrap.cpp
|
../common/bstrlib/bstrwrap.cpp
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* uefidump_main.cpp
|
/* uefidump_main.cpp
|
||||||
|
|
||||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -29,7 +29,7 @@ int main(int argc, char *argv[])
|
|||||||
return (uefidumper.dump(buffer, UString(argv[1])) != U_SUCCESS);
|
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;
|
<< "Usage: UEFIDump imagefile" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ SOURCES += \
|
|||||||
../common/LZMA/SDK/C/LzmaDec.c \
|
../common/LZMA/SDK/C/LzmaDec.c \
|
||||||
../common/Tiano/EfiTianoDecompress.c \
|
../common/Tiano/EfiTianoDecompress.c \
|
||||||
../common/ustring.cpp
|
../common/ustring.cpp
|
||||||
|
../common/sha256.c
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
ffsdumper.h \
|
ffsdumper.h \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* uefiextract_main.cpp
|
/* uefiextract_main.cpp
|
||||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -20,8 +20,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication a(argc, argv);
|
QCoreApplication a(argc, argv);
|
||||||
a.setOrganizationName("CodeRush");
|
a.setOrganizationName("LongSoft");
|
||||||
a.setOrganizationDomain("coderush.me");
|
a.setOrganizationDomain("longsoft.me");
|
||||||
a.setApplicationName("UEFIExtract");
|
a.setApplicationName("UEFIExtract");
|
||||||
|
|
||||||
if (a.arguments().length() > 32) {
|
if (a.arguments().length() > 32) {
|
||||||
@ -121,7 +121,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If parameters are different, show version and usage information
|
// If parameters are different, show version and usage information
|
||||||
std::cout << "UEFIExtract 0.13.4" << std::endl << 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
|
<< "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 all - generate report and dump all tree items." << std::endl
|
||||||
<< " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl
|
<< " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl
|
||||||
|
@ -21,7 +21,8 @@ SOURCES += uefifind_main.cpp \
|
|||||||
../common/LZMA/LzmaDecompress.c \
|
../common/LZMA/LzmaDecompress.c \
|
||||||
../common/LZMA/SDK/C/LzmaDec.c \
|
../common/LZMA/SDK/C/LzmaDec.c \
|
||||||
../common/Tiano/EfiTianoDecompress.c \
|
../common/Tiano/EfiTianoDecompress.c \
|
||||||
../common/ustring.cpp
|
../common/ustring.cpp \
|
||||||
|
../common/sha256.c
|
||||||
|
|
||||||
HEADERS += uefifind.h \
|
HEADERS += uefifind.h \
|
||||||
../common/guiddatabase.h \
|
../common/guiddatabase.h \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* uefifind_main.cpp
|
/* uefifind_main.cpp
|
||||||
|
|
||||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -17,8 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication a(argc, argv);
|
QCoreApplication a(argc, argv);
|
||||||
a.setOrganizationName("CodeRush");
|
a.setOrganizationName("LongSoft");
|
||||||
a.setOrganizationDomain("coderush.me");
|
a.setOrganizationDomain("longsoft.me");
|
||||||
a.setApplicationName("UEFIFind");
|
a.setApplicationName("UEFIFind");
|
||||||
|
|
||||||
UEFIFind w;
|
UEFIFind w;
|
||||||
@ -148,7 +148,7 @@ int main(int argc, char *argv[])
|
|||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
else {
|
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 <<
|
"Usage: UEFIFind {header | body | all} {list | count} pattern imagefile" << std::endl <<
|
||||||
" or UEFIFind file patternsfile imagefile" << std::endl;
|
" or UEFIFind file patternsfile imagefile" << std::endl;
|
||||||
return U_INVALID_PARAMETER;
|
return U_INVALID_PARAMETER;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
UEFITool::UEFITool(QWidget *parent) :
|
UEFITool::UEFITool(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui(new Ui::UEFITool),
|
ui(new Ui::UEFITool),
|
||||||
version(tr("NE alpha 44"))
|
version(tr("NE alpha 45"))
|
||||||
{
|
{
|
||||||
clipboard = QApplication::clipboard();
|
clipboard = QApplication::clipboard();
|
||||||
|
|
||||||
@ -150,6 +150,10 @@ void UEFITool::init()
|
|||||||
delete ffsParser;
|
delete ffsParser;
|
||||||
ffsParser = new FfsParser(model);
|
ffsParser = new FfsParser(model);
|
||||||
|
|
||||||
|
// Set proper marking state
|
||||||
|
model->setMarkingEnabled(markingEnabled);
|
||||||
|
ui->actionToggleBootGuardMarking->setChecked(markingEnabled);
|
||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
|
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
|
||||||
this, SLOT(populateUi(const QModelIndex &)));
|
this, SLOT(populateUi(const QModelIndex &)));
|
||||||
@ -199,7 +203,7 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
|| type == Types::EvsaEntry
|
|| type == Types::EvsaEntry
|
||||||
|| type == Types::FlashMapEntry);
|
|| type == Types::FlashMapEntry);
|
||||||
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
||||||
|| type == Types::LenovoVssStore
|
|| type == Types::Vss2Store
|
||||||
|| type == Types::FdcStore
|
|| type == Types::FdcStore
|
||||||
|| type == Types::FsysStore
|
|| type == Types::FsysStore
|
||||||
|| type == Types::EvsaStore
|
|| 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::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::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::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::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::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;
|
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::FlashMapEntry:
|
||||||
case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save entry body to file"), name + ".bin", "Binary files (*.bin);;All files (*)"); break;
|
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::VssStore:
|
||||||
case Types::LenovoVssStore:
|
case Types::Vss2Store:
|
||||||
case Types::FtwStore:
|
case Types::FtwStore:
|
||||||
case Types::FdcStore:
|
case Types::FdcStore:
|
||||||
case Types::FsysStore:
|
case Types::FsysStore:
|
||||||
@ -921,6 +925,7 @@ void UEFITool::clearMessages()
|
|||||||
void UEFITool::toggleBootGuardMarking(bool enabled)
|
void UEFITool::toggleBootGuardMarking(bool enabled)
|
||||||
{
|
{
|
||||||
model->setMarkingEnabled(enabled);
|
model->setMarkingEnabled(enabled);
|
||||||
|
markingEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
||||||
@ -1041,7 +1046,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
case Types::EvsaEntry:
|
case Types::EvsaEntry:
|
||||||
case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break;
|
case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break;
|
||||||
case Types::VssStore:
|
case Types::VssStore:
|
||||||
case Types::LenovoVssStore:
|
case Types::Vss2Store:
|
||||||
case Types::FdcStore:
|
case Types::FdcStore:
|
||||||
case Types::FsysStore:
|
case Types::FsysStore:
|
||||||
case Types::EvsaStore:
|
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(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(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
|
||||||
ui->structureTreeView->setColumnWidth(3, settings.value("tree/columnWidth3", ui->structureTreeView->columnWidth(3)).toInt());
|
ui->structureTreeView->setColumnWidth(3, settings.value("tree/columnWidth3", ui->structureTreeView->columnWidth(3)).toInt());
|
||||||
|
markingEnabled = settings.value("tree/markingEnabled", true).toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::writeSettings()
|
void UEFITool::writeSettings()
|
||||||
@ -1084,6 +1090,7 @@ void UEFITool::writeSettings()
|
|||||||
settings.setValue("tree/columnWidth1", ui->structureTreeView->columnWidth(1));
|
settings.setValue("tree/columnWidth1", ui->structureTreeView->columnWidth(1));
|
||||||
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
|
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
|
||||||
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
|
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
|
||||||
|
settings.setValue("tree/markingEnabled", markingEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::showFitTable()
|
void UEFITool::showFitTable()
|
||||||
|
@ -134,6 +134,7 @@ private:
|
|||||||
QString currentPath;
|
QString currentPath;
|
||||||
QString currentProgramPath;
|
QString currentProgramPath;
|
||||||
const QString version;
|
const QString version;
|
||||||
|
bool markingEnabled;
|
||||||
|
|
||||||
bool enableExtractBodyUncompressed(const QModelIndex ¤t);
|
bool enableExtractBodyUncompressed(const QModelIndex ¤t);
|
||||||
|
|
||||||
|
@ -25,13 +25,13 @@ const UINT8* calculateAddress16(const UINT8* baseAddress, const UINT16 baseOrLim
|
|||||||
return baseAddress + baseOrLimit * 0x1000;
|
return baseAddress + baseOrLimit * 0x1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate offset of region using its base
|
// Calculate offset of region using it's base
|
||||||
UINT32 calculateRegionOffset(const UINT16 base)
|
UINT32 calculateRegionOffset(const UINT16 base)
|
||||||
{
|
{
|
||||||
return base * 0x1000;
|
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)
|
UINT32 calculateRegionSize(const UINT16 base, const UINT16 limit)
|
||||||
{
|
{
|
||||||
if (limit)
|
if (limit)
|
||||||
|
@ -109,22 +109,34 @@ typedef struct FLASH_DESCRIPTOR_REGION_SECTION_ {
|
|||||||
UINT16 DescriptorLimit; //
|
UINT16 DescriptorLimit; //
|
||||||
UINT16 BiosBase; // BIOS
|
UINT16 BiosBase; // BIOS
|
||||||
UINT16 BiosLimit; //
|
UINT16 BiosLimit; //
|
||||||
UINT16 MeBase; // ME
|
UINT16 MeBase; // Management Engine
|
||||||
UINT16 MeLimit; //
|
UINT16 MeLimit; //
|
||||||
UINT16 GbeBase; // GbE
|
UINT16 GbeBase; // Gigabit Ethernet
|
||||||
UINT16 GbeLimit; //
|
UINT16 GbeLimit; //
|
||||||
UINT16 PdrBase; // PDR
|
UINT16 PdrBase; // Platform Data
|
||||||
UINT16 PdrLimit; //
|
UINT16 PdrLimit; //
|
||||||
|
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 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 Reserved1Base; // Reserved 1
|
||||||
UINT16 Reserved1Limit; //
|
UINT16 Reserved1Limit; //
|
||||||
UINT16 Reserved2Base; // Reserved 2
|
UINT16 Reserved2Base; // Reserved 2
|
||||||
UINT16 Reserved2Limit; //
|
UINT16 Reserved2Limit; //
|
||||||
UINT16 Reserved3Base; // Reserved3
|
UINT16 PttBase; // Platform Trust Technology
|
||||||
UINT16 Reserved3Limit; //
|
UINT16 PttLimit; //
|
||||||
UINT16 EcBase; // EC
|
|
||||||
UINT16 EcLimit; //
|
|
||||||
UINT16 Reserved4Base; // Reserved4
|
|
||||||
UINT16 Reserved4Limit; //
|
|
||||||
} FLASH_DESCRIPTOR_REGION_SECTION;
|
} FLASH_DESCRIPTOR_REGION_SECTION;
|
||||||
|
|
||||||
// Master section
|
// Master section
|
||||||
|
@ -32,6 +32,9 @@ const std::vector<UByteArray> FFSv3Volumes(1, EFI_FIRMWARE_FILE_SYSTEM3_GUID);
|
|||||||
const UINT8 ffsAlignmentTable[] =
|
const UINT8 ffsAlignmentTable[] =
|
||||||
{ 0, 4, 7, 9, 10, 12, 15, 16 };
|
{ 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)
|
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
||||||
{
|
{
|
||||||
ffsSize[2] = (UINT8)((size) >> 16);
|
ffsSize[2] = (UINT8)((size) >> 16);
|
||||||
|
17
common/ffs.h
17
common/ffs.h
@ -288,7 +288,7 @@ UINT8 Type;
|
|||||||
UINT8 Attributes;
|
UINT8 Attributes;
|
||||||
UINT8 Size[3]; // Set to 0xFFFFFF
|
UINT8 Size[3]; // Set to 0xFFFFFF
|
||||||
UINT8 State;
|
UINT8 State;
|
||||||
UINT32 ExtendedSize;
|
UINT64 ExtendedSize;
|
||||||
} EFI_FFS_FILE_HEADER2;
|
} EFI_FFS_FILE_HEADER2;
|
||||||
|
|
||||||
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
// 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_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
|
||||||
#define FFS_ATTRIB_RECOVERY 0x02 // 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_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_FIXED 0x04
|
||||||
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
||||||
#define FFS_ATTRIB_CHECKSUM 0x40
|
#define FFS_ATTRIB_CHECKSUM 0x40
|
||||||
@ -331,6 +332,10 @@ UINT32 ExtendedSize;
|
|||||||
// FFS alignment table
|
// FFS alignment table
|
||||||
extern const UINT8 ffsAlignmentTable[];
|
extern const UINT8 ffsAlignmentTable[];
|
||||||
|
|
||||||
|
// Extended FFS alignment table, added in UEFI PI 1.6
|
||||||
|
extern const UINT8 ffsAlignment2Table[];
|
||||||
|
|
||||||
|
|
||||||
// File states
|
// File states
|
||||||
#define EFI_FILE_HEADER_CONSTRUCTION 0x01
|
#define EFI_FILE_HEADER_CONSTRUCTION 0x01
|
||||||
#define EFI_FILE_HEADER_VALID 0x02
|
#define EFI_FILE_HEADER_VALID 0x02
|
||||||
@ -338,7 +343,7 @@ extern const UINT8 ffsAlignmentTable[];
|
|||||||
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
|
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
|
||||||
#define EFI_FILE_DELETED 0x10
|
#define EFI_FILE_DELETED 0x10
|
||||||
#define EFI_FILE_HEADER_INVALID 0x20
|
#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
|
// PEI apriori file
|
||||||
const UByteArray EFI_PEI_APRIORI_FILE_GUID
|
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
|
const UByteArray EFI_FFS_PAD_FILE_GUID
|
||||||
("\x85\x65\x53\xE4\x09\x79\x60\x4A\xB5\xC6\xEC\xDE\xA6\xEB\xFB\x54", 16);
|
("\x85\x65\x53\xE4\x09\x79\x60\x4A\xB5\xC6\xEC\xDE\xA6\xEB\xFB\x54", 16);
|
||||||
|
|
||||||
// DXE core file
|
// AMI DXE core file
|
||||||
const UByteArray EFI_DXE_CORE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
|
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);
|
("\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
|
// FFS size conversion routines
|
||||||
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
|
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
|
||||||
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
|
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
|
||||||
|
@ -193,13 +193,19 @@ USTATUS FfsBuilder::buildIntelImage(const UModelIndex & index, UByteArray & inte
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Subtypes::GbeRegion:
|
|
||||||
case Subtypes::MeRegion:
|
case Subtypes::MeRegion:
|
||||||
|
case Subtypes::GbeRegion:
|
||||||
|
case Subtypes::DevExp1Region:
|
||||||
|
case Subtypes::Bios2Region:
|
||||||
|
case Subtypes::MicrocodeRegion:
|
||||||
case Subtypes::EcRegion:
|
case Subtypes::EcRegion:
|
||||||
|
case Subtypes::DevExp2Region:
|
||||||
|
case Subtypes::IeRegion:
|
||||||
|
case Subtypes::Tgbe1Region:
|
||||||
|
case Subtypes::Tgbe2Region:
|
||||||
case Subtypes::Reserved1Region:
|
case Subtypes::Reserved1Region:
|
||||||
case Subtypes::Reserved2Region:
|
case Subtypes::Reserved2Region:
|
||||||
case Subtypes::Reserved3Region:
|
case Subtypes::PttRegion:
|
||||||
case Subtypes::Reserved4Region:
|
|
||||||
// Add region as is
|
// Add region as is
|
||||||
region = model->header(currentRegion).append(model->body(currentRegion));
|
region = model->header(currentRegion).append(model->body(currentRegion));
|
||||||
break;
|
break;
|
||||||
|
@ -28,6 +28,18 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "parsingdata.h"
|
#include "parsingdata.h"
|
||||||
#include "types.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
|
// Region info structure definition
|
||||||
struct REGION_INFO {
|
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; }
|
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
|
// Firmware image parsing functions
|
||||||
USTATUS FfsParser::parse(const UByteArray & buffer)
|
USTATUS FfsParser::parse(const UByteArray & buffer)
|
||||||
{
|
{
|
||||||
@ -286,11 +322,9 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BIOS region
|
// BIOS region
|
||||||
|
if (regionSection->BiosLimit) {
|
||||||
REGION_INFO bios;
|
REGION_INFO bios;
|
||||||
bios.type = Subtypes::BiosRegion;
|
bios.type = Subtypes::BiosRegion;
|
||||||
bios.offset = 0;
|
|
||||||
bios.length = 0;
|
|
||||||
if (regionSection->BiosLimit) {
|
|
||||||
bios.offset = calculateRegionOffset(regionSection->BiosBase);
|
bios.offset = calculateRegionOffset(regionSection->BiosBase);
|
||||||
bios.length = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit);
|
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;
|
return U_INVALID_FLASH_DESCRIPTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GbE region
|
// Add all other regions
|
||||||
REGION_INFO gbe;
|
for (UINT8 i = Subtypes::GbeRegion; i <= Subtypes::PttRegion; i++) {
|
||||||
gbe.type = Subtypes::GbeRegion;
|
if (descriptorVersion == 1 && i == Subtypes::MicrocodeRegion)
|
||||||
gbe.offset = 0;
|
break; // Do not parse Microcode and other following regions for old descriptors
|
||||||
gbe.length = 0;
|
|
||||||
if (regionSection->GbeLimit) {
|
const UINT16* RegionBase = ((const UINT16*)regionSection) + 2 * i;
|
||||||
gbe.offset = calculateRegionOffset(regionSection->GbeBase);
|
const UINT16* RegionLimit = ((const UINT16*)regionSection) + 2 * i + 1;
|
||||||
gbe.length = calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit);
|
if (*RegionLimit && !(*RegionBase == 0xFFFF && *RegionLimit == 0xFFFF)) {
|
||||||
gbe.data = intelImage.mid(gbe.offset, gbe.length);
|
REGION_INFO region;
|
||||||
regions.push_back(gbe);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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));
|
const VSCC_TABLE_ENTRY* vsccTableEntry = (const VSCC_TABLE_ENTRY*)(descriptor + ((UINT16)upperMap->VsccTableBase << 4));
|
||||||
info += UString("\nFlash chips in VSCC table:");
|
info += UString("\nFlash chips in VSCC table:");
|
||||||
UINT8 vsscTableSize = upperMap->VsccTableSize * sizeof(UINT32) / sizeof(VSCC_TABLE_ENTRY);
|
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++) {
|
for (UINT8 i = 0; i < vsscTableSize; i++) {
|
||||||
info += usprintf("\n%02X%02X%02X (",
|
info += usprintf("\n%02X%02X%02X (", vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1)
|
||||||
vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1)
|
+ jedecId
|
||||||
+ jedecIdToUString(vsccTableEntry->VendorId, vsccTableEntry->DeviceId0, vsccTableEntry->DeviceId1)
|
|
||||||
+ UString(")");
|
+ UString(")");
|
||||||
vsccTableEntry++;
|
vsccTableEntry++;
|
||||||
}
|
}
|
||||||
@ -567,6 +530,11 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
|||||||
// Add descriptor tree item
|
// Add descriptor tree item
|
||||||
UModelIndex regionIndex = model->addItem(localOffset, Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
|
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
|
// Parse regions
|
||||||
UINT8 result = U_SUCCESS;
|
UINT8 result = U_SUCCESS;
|
||||||
UINT8 parseResult = U_SUCCESS;
|
UINT8 parseResult = U_SUCCESS;
|
||||||
@ -585,12 +553,18 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
|
|||||||
case Subtypes::PdrRegion:
|
case Subtypes::PdrRegion:
|
||||||
result = parsePdrRegion(region.data, region.offset, index, regionIndex);
|
result = parsePdrRegion(region.data, region.offset, index, regionIndex);
|
||||||
break;
|
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::Reserved1Region:
|
||||||
case Subtypes::Reserved2Region:
|
case Subtypes::Reserved2Region:
|
||||||
case Subtypes::Reserved3Region:
|
case Subtypes::PttRegion:
|
||||||
case Subtypes::EcRegion:
|
result = parseGenericRegion(region.type, region.data, region.offset, index, regionIndex);
|
||||||
case Subtypes::Reserved4Region:
|
|
||||||
result = parseGeneralRegion(region.type, region.data, region.offset, index, regionIndex);
|
|
||||||
break;
|
break;
|
||||||
case Subtypes::ZeroPadding:
|
case Subtypes::ZeroPadding:
|
||||||
case Subtypes::OnePadding:
|
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);
|
msg(UString("parseMeRegion: ME version is unknown, it can be damaged"), index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
meParser.parseMeRegionBody(index);
|
meParser->parseMeRegionBody(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
@ -729,7 +703,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
|
|||||||
return U_SUCCESS;
|
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
|
// Check sanity
|
||||||
if (region.isEmpty())
|
if (region.isEmpty())
|
||||||
@ -1184,7 +1158,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
|
|||||||
|
|
||||||
// Parse VSS NVRAM volumes with a dedicated function
|
// Parse VSS NVRAM volumes with a dedicated function
|
||||||
if (model->subtype(index) == Subtypes::NvramVolume)
|
if (model->subtype(index) == Subtypes::NvramVolume)
|
||||||
return nvramParser.parseNvramVolumeBody(index);
|
return nvramParser->parseNvramVolumeBody(index);
|
||||||
|
|
||||||
// Get required values from parsing data
|
// Get required values from parsing data
|
||||||
UINT8 emptyByte = 0xFF;
|
UINT8 emptyByte = 0xFF;
|
||||||
@ -1351,7 +1325,7 @@ UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset
|
|||||||
return 0;
|
return 0;
|
||||||
const EFI_FFS_FILE_HEADER2* fileHeader = (const EFI_FFS_FILE_HEADER2*)(volume.constData() + fileOffset);
|
const EFI_FFS_FILE_HEADER2* fileHeader = (const EFI_FFS_FILE_HEADER2*)(volume.constData() + fileOffset);
|
||||||
if (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)
|
if (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)
|
||||||
return fileHeader->ExtendedSize;
|
return (UINT32) fileHeader->ExtendedSize;
|
||||||
else
|
else
|
||||||
return uint24ToUint32(fileHeader->Size);
|
return uint24ToUint32(fileHeader->Size);
|
||||||
}
|
}
|
||||||
@ -1384,17 +1358,24 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
|
|
||||||
// Get file header
|
// Get file header
|
||||||
UByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
UByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||||
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
|
bool largeFile = false;
|
||||||
if (ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
|
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))
|
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2))
|
||||||
return U_INVALID_FILE;
|
return U_INVALID_FILE;
|
||||||
header = file.left(sizeof(EFI_FFS_FILE_HEADER2));
|
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
|
// Check file alignment
|
||||||
bool msgUnalignedFile = false;
|
bool msgUnalignedFile = false;
|
||||||
UINT8 alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3];
|
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)
|
if ((localOffset + header.size()) % alignment)
|
||||||
msgUnalignedFile = true;
|
msgUnalignedFile = true;
|
||||||
|
|
||||||
@ -1403,45 +1384,6 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
if (!isWeakAligned && volumeAlignment < alignment)
|
if (!isWeakAligned && volumeAlignment < alignment)
|
||||||
msgFileAlignmentIsGreaterThanVolumeAlignment = true;
|
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
|
// Get file body
|
||||||
UByteArray body = file.mid(header.size());
|
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));
|
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
|
// Get info
|
||||||
UString name;
|
UString name;
|
||||||
UString info;
|
UString info;
|
||||||
@ -1492,9 +1464,9 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
text = UString("Volume Top File");
|
text = UString("Volume Top File");
|
||||||
}
|
}
|
||||||
// Check if the file is the first DXE Core
|
// Check if the file is the first DXE Core
|
||||||
else if (fileGuid == EFI_DXE_CORE_GUID) {
|
else if (fileGuid == EFI_DXE_CORE_GUID || fileGuid == AMI_CORE_DXE_GUID) {
|
||||||
// Mark is as first DXE code
|
// Mark is as first DXE core
|
||||||
// This information may be used to determine DXE volume offset for old AMI protected ranges
|
// This information may be used to determine DXE volume offset for old AMI or post-IBB protected ranges
|
||||||
isDxeCore = true;
|
isDxeCore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1579,7 +1551,7 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index)
|
|||||||
|
|
||||||
// Parse NVAR store
|
// Parse NVAR store
|
||||||
if (fileGuid == NVRAM_NVAR_STORE_FILE_GUID)
|
if (fileGuid == NVRAM_NVAR_STORE_FILE_GUID)
|
||||||
return nvramParser.parseNvarStore(index);
|
return nvramParser->parseNvarStore(index);
|
||||||
|
|
||||||
// Parse vendor hash file
|
// Parse vendor hash file
|
||||||
else if (fileGuid == BG_VENDOR_HASH_FILE_GUID_PHOENIX)
|
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
|
else if (parentFileGuid == NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID) { // AMI NVRAM external defaults
|
||||||
// Parse NVAR area
|
// Parse NVAR area
|
||||||
nvramParser.parseNvarStore(index);
|
nvramParser->parseNvarStore(index);
|
||||||
|
|
||||||
// Set parent file text
|
// Set parent file text
|
||||||
model->setText(parentFile, UString("NVRAM external defaults"));
|
model->setText(parentFile, UString("NVRAM external defaults"));
|
||||||
@ -2709,7 +2681,6 @@ USTATUS FfsParser::parseRawSectionBody(const UModelIndex & index)
|
|||||||
parseVendorHashFile(parentFileGuid, index);
|
parseVendorHashFile(parentFileGuid, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse as raw area
|
// Parse as raw area
|
||||||
return parseRawArea(index);
|
return parseRawArea(index);
|
||||||
}
|
}
|
||||||
@ -3009,9 +2980,9 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
|||||||
UByteArray protectedParts;
|
UByteArray protectedParts;
|
||||||
bool bgProtectedRangeFound = false;
|
bool bgProtectedRangeFound = false;
|
||||||
for (UINT32 i = 0; i < (UINT32)bgProtectedRanges.size(); i++) {
|
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;
|
bgProtectedRangeFound = true;
|
||||||
bgProtectedRanges[i].Offset -= addressDiff;
|
bgProtectedRanges[i].Offset -= (UINT32)addressDiff;
|
||||||
protectedParts += openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
protectedParts += openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||||
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||||
}
|
}
|
||||||
@ -3019,7 +2990,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
|||||||
|
|
||||||
if (bgProtectedRangeFound) {
|
if (bgProtectedRangeFound) {
|
||||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
||||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
sha256(protectedParts.constData(), protectedParts.size(), digest.data());
|
||||||
|
|
||||||
if (digest != bgBpDigest) {
|
if (digest != bgBpDigest) {
|
||||||
msg(UString("checkProtectedRanges: BG-protected ranges hash mismatch, opened image may refuse to boot"), index);
|
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
|
// Calculate digests for vendor-protected ranges
|
||||||
for (UINT32 i = 0; i < (UINT32)bgProtectedRanges.size(); i++) {
|
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()) {
|
if (!bgDxeCoreIndex.isValid()) {
|
||||||
msg(UString("checkProtectedRanges: can't determine DXE volume offset, old AMI protected range hash can't be checked"), index);
|
msg(UString("checkProtectedRanges: can't determine DXE volume offset, old AMI protected range hash can't be checked"), index);
|
||||||
}
|
}
|
||||||
@ -3046,7 +3018,56 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
|||||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||||
|
|
||||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
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: 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.size(), digest.data());
|
||||||
|
|
||||||
if (digest != bgProtectedRanges[i].Hash) {
|
if (digest != bgProtectedRanges[i].Hash) {
|
||||||
msg(usprintf("checkProtectedRanges: AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
msg(usprintf("checkProtectedRanges: AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
||||||
@ -3056,29 +3077,14 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index)
|
|||||||
|
|
||||||
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||||
}
|
}
|
||||||
}
|
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX
|
||||||
}
|
&& bgProtectedRanges[i].Size != 0 && bgProtectedRanges[i].Size != 0xFFFFFFFF
|
||||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW) {
|
&& bgProtectedRanges[i].Offset != 0xFFFFFFFF) {
|
||||||
bgProtectedRanges[i].Offset -= addressDiff;
|
bgProtectedRanges[i].Offset += (UINT32)bgFirstVolumeOffset;
|
||||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||||
|
|
||||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
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",
|
|
||||||
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_PHOENIX) {
|
|
||||||
bgProtectedRanges[i].Offset += bgFirstVolumeOffset;
|
|
||||||
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
|
||||||
|
|
||||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
|
||||||
sha256(protectedParts.constData(), protectedParts.length(), digest.data());
|
|
||||||
|
|
||||||
if (digest != bgProtectedRanges[i].Hash) {
|
if (digest != bgProtectedRanges[i].Hash) {
|
||||||
msg(usprintf("checkProtectedRanges: Phoenix protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
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]);
|
markProtectedRangeRecursive(index, bgProtectedRanges[i]);
|
||||||
}
|
}
|
||||||
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT) {
|
else if (bgProtectedRanges[i].Type == BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT
|
||||||
bgProtectedRanges[i].Offset -= addressDiff;
|
&& 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);
|
protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size);
|
||||||
|
|
||||||
UByteArray digest(SHA256_DIGEST_SIZE, '\x00');
|
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) {
|
if (digest != bgProtectedRanges[i].Hash) {
|
||||||
msg(usprintf("checkProtectedRanges: Microsoft protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot",
|
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 (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
|
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
|
else { // Mark as partially in range
|
||||||
model->setMarking(index, Qt::yellow);
|
model->setMarking(index, Qt::yellow);
|
||||||
@ -3579,6 +3587,15 @@ USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest
|
|||||||
header->KmSvn,
|
header->KmSvn,
|
||||||
header->KmId
|
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
|
// Add BpKeyHash
|
||||||
bootGuardInfo += UString("\n\nBoot Policy RSA Public Key Hash:\n");
|
bootGuardInfo += UString("\n\nBoot Policy RSA Public Key Hash:\n");
|
||||||
for (UINT8 i = 0; i < sizeof(header->BpKeyHash.HashBuffer); i++) {
|
for (UINT8 i = 0; i < sizeof(header->BpKeyHash.HashBuffer); i++) {
|
||||||
@ -3702,11 +3719,22 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy,
|
|||||||
elementHeader->PmrlLimit,
|
elementHeader->PmrlLimit,
|
||||||
elementHeader->EntryPoint
|
elementHeader->EntryPoint
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add PostIbbHash
|
// Add PostIbbHash
|
||||||
bootGuardInfo += UString("\n\nPost IBB Hash:\n");
|
bootGuardInfo += UString("\n\nPost IBB Hash:\n");
|
||||||
for (UINT8 i = 0; i < sizeof(elementHeader->IbbHash.HashBuffer); i++) {
|
for (UINT8 i = 0; i < sizeof(elementHeader->IbbHash.HashBuffer); i++) {
|
||||||
bootGuardInfo += usprintf("%02X", 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
|
// Add Digest
|
||||||
bgBpDigest = UByteArray((const char*)elementHeader->Digest.HashBuffer, sizeof(elementHeader->Digest.HashBuffer));
|
bgBpDigest = UByteArray((const char*)elementHeader->Digest.HashBuffer, sizeof(elementHeader->Digest.HashBuffer));
|
||||||
bootGuardInfo += UString("\n\nIBB Digest:\n");
|
bootGuardInfo += UString("\n\nIBB Digest:\n");
|
||||||
@ -3724,7 +3752,7 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy,
|
|||||||
BG_PROTECTED_RANGE range;
|
BG_PROTECTED_RANGE range;
|
||||||
range.Offset = segments[i].Base;
|
range.Offset = segments[i].Base;
|
||||||
range.Size = segments[i].Size;
|
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);
|
bgProtectedRanges.push_back(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* ffsparser.h
|
/* ffsparser.h
|
||||||
|
|
||||||
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
|
Copyright (c) 2017, LongSoft. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -19,8 +19,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "ustring.h"
|
#include "ustring.h"
|
||||||
#include "ubytearray.h"
|
#include "ubytearray.h"
|
||||||
#include "treemodel.h"
|
#include "treemodel.h"
|
||||||
#include "nvramparser.h"
|
|
||||||
#include "meparser.h"
|
|
||||||
#include "bootguard.h"
|
#include "bootguard.h"
|
||||||
|
|
||||||
typedef struct BG_PROTECTED_RANGE_
|
typedef struct BG_PROTECTED_RANGE_
|
||||||
@ -31,31 +29,25 @@ typedef struct BG_PROTECTED_RANGE_
|
|||||||
UByteArray Hash;
|
UByteArray Hash;
|
||||||
} BG_PROTECTED_RANGE;
|
} BG_PROTECTED_RANGE;
|
||||||
|
|
||||||
#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD 0x01
|
#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB 0x01
|
||||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX 0x02
|
#define BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_POST_IBB 0x02
|
||||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD 0x03
|
#define BG_PROTECTED_RANGE_VENDOR_HASH_PHOENIX 0x03
|
||||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW 0x04
|
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_OLD 0x04
|
||||||
#define BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT 0x05
|
#define BG_PROTECTED_RANGE_VENDOR_HASH_AMI_NEW 0x05
|
||||||
|
#define BG_PROTECTED_RANGE_VENDOR_HASH_MICROSOFT 0x06
|
||||||
|
|
||||||
|
class NvramParser;
|
||||||
|
class MeParser;
|
||||||
|
|
||||||
class FfsParser
|
class FfsParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Default constructor and destructor
|
// Constructor and destructor
|
||||||
FfsParser(TreeModel* treeModel) : model(treeModel), nvramParser(treeModel), meParser(treeModel),
|
FfsParser(TreeModel* treeModel);
|
||||||
capsuleOffsetFixup(0), addressDiff(0x100000000ULL),
|
~FfsParser();
|
||||||
bgAcmFound(false), bgKeyManifestFound(false), bgBootPolicyFound(false), bgFirstVolumeOffset(0x100000000ULL) {}
|
|
||||||
~FfsParser() {}
|
|
||||||
|
|
||||||
// Obtain parser messages
|
// Obtain parser messages
|
||||||
std::vector<std::pair<UString, UModelIndex> > getMessages() const {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear messages
|
// Clear messages
|
||||||
void clearMessages() { messagesVector.clear(); }
|
void clearMessages() { messagesVector.clear(); }
|
||||||
|
|
||||||
@ -78,8 +70,8 @@ private:
|
|||||||
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
|
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
|
||||||
};
|
};
|
||||||
|
|
||||||
NvramParser nvramParser;
|
NvramParser* nvramParser;
|
||||||
MeParser meParser;
|
MeParser* meParser;
|
||||||
|
|
||||||
UByteArray openedImage;
|
UByteArray openedImage;
|
||||||
UModelIndex lastVtf;
|
UModelIndex lastVtf;
|
||||||
@ -114,7 +106,7 @@ private:
|
|||||||
USTATUS parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
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 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 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 parsePadFileBody(const UModelIndex & index);
|
||||||
USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 localOffset, 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 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);
|
USTATUS findNextElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
||||||
|
friend class NvramParser; // Make FFS parsing routines accessible to NvramParser
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FFSPARSER_H
|
#endif // FFSPARSER_H
|
||||||
|
@ -171,29 +171,32 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ {
|
|||||||
extern UString vssAttributesToUString(const UINT32 attributes);
|
extern UString vssAttributesToUString(const UINT32 attributes);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lenovo VSS variables
|
// VSS2 variables
|
||||||
//
|
//
|
||||||
|
|
||||||
// aaf32c78-947b-439a-a180-2e144ec37792
|
// aaf32c78-947b-439a-a180-2e144ec37792
|
||||||
#define LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 0xaaf32c78
|
#define NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 0xaaf32c78
|
||||||
const UByteArray LENOVO_AUTH_VAR_KEY_DATABASE_GUID
|
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");
|
("\x78\x2C\xF3\xAA\x7B\x94\x9A\x43\xA1\x80\x2E\x14\x4E\xC3\x77\x92");
|
||||||
|
|
||||||
#define LENOVO_VSS_STORE_GUID_PART1 0xddcf3617
|
#define NVRAM_VSS2_STORE_GUID_PART1 0xddcf3617
|
||||||
const UByteArray LENOVO_VSS_STORE_GUID
|
const UByteArray NVRAM_VSS2_STORE_GUID
|
||||||
("\x17\x36\xCF\xDD\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D");
|
("\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
|
// Variable store header
|
||||||
typedef struct LENOVO_VSS_VARIABLE_STORE_HEADER_ {
|
typedef struct VSS2_VARIABLE_STORE_HEADER_ {
|
||||||
EFI_GUID Signature;
|
EFI_GUID Signature; // VSS2 Store Guid
|
||||||
UINT32 Size; // Size of variable store, including store header
|
UINT32 Size; // Size of variable store, including store header
|
||||||
UINT8 Format; // Store format state
|
UINT8 Format; // Store format state
|
||||||
UINT8 State; // Store health state
|
UINT8 State; // Store health state
|
||||||
UINT16 Unknown;
|
UINT16 Unknown;
|
||||||
UINT32 : 32;
|
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
|
// _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);
|
("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\x0A\xCE\x65\x00\xFD\x9F\x1B\x95", 16);
|
||||||
|
|
||||||
// 9E58292B-7C68-497D-A0CE6500FD9F1B95
|
// 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);
|
("\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
|
#define NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 0xFFF12B8D
|
||||||
|
@ -496,12 +496,12 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
|
|||||||
for (int i = 0; i < model->rowCount(index); i++) {
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
UModelIndex current = index.child(i, 0);
|
UModelIndex current = index.child(i, 0);
|
||||||
switch (model->type(current)) {
|
switch (model->type(current)) {
|
||||||
case Types::VssStore:
|
case Types::FdcStore: return parseFdcStoreBody(current);
|
||||||
case Types::FdcStore: parseVssStoreBody(current, 0); break;
|
case Types::VssStore: return parseVssStoreBody(current, 0);
|
||||||
case Types::LenovoVssStore: parseVssStoreBody(current, 4); break;
|
case Types::Vss2Store: return parseVssStoreBody(current, 4);
|
||||||
case Types::FsysStore: parseFsysStoreBody(current); break;
|
case Types::FsysStore: return parseFsysStoreBody(current);
|
||||||
case Types::EvsaStore: parseEvsaStoreBody(current); break;
|
case Types::EvsaStore: return parseEvsaStoreBody(current);
|
||||||
case Types::FlashMapStore: parseFlashMapBody(current); break;
|
case Types::FlashMapStore: return parseFlashMapBody(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,18 +531,18 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
|
|||||||
// All checks passed, store found
|
// All checks passed, store found
|
||||||
break;
|
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));
|
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;
|
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) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (vssHeader->Size == 0 || vssHeader->Size == 0xFFFFFFFF) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
// All checks passed, store found
|
// 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
|
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));
|
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;
|
continue;
|
||||||
|
|
||||||
// Detect header variant based on WriteQueueSize
|
// Detect header variant based on WriteQueueSize
|
||||||
@ -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;
|
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
||||||
storeSize = vssHeader->Size;
|
storeSize = vssHeader->Size;
|
||||||
}
|
}
|
||||||
else if (*signature == LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == LENOVO_VSS_STORE_GUID_PART1) {
|
else if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1) {
|
||||||
const LENOVO_VSS_VARIABLE_STORE_HEADER* vssHeader = (const LENOVO_VSS_VARIABLE_STORE_HEADER*)signature;
|
const VSS2_VARIABLE_STORE_HEADER* vssHeader = (const VSS2_VARIABLE_STORE_HEADER*)signature;
|
||||||
storeSize = vssHeader->Size;
|
storeSize = vssHeader->Size;
|
||||||
}
|
}
|
||||||
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
||||||
@ -744,7 +744,7 @@ USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOff
|
|||||||
return U_SUCCESS;
|
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();
|
const UINT32 dataSize = (const UINT32)store.size();
|
||||||
|
|
||||||
@ -757,24 +757,30 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
|
|||||||
// Get VSS store header
|
// Get VSS store header
|
||||||
const VSS_VARIABLE_STORE_HEADER* vssStoreHeader = (const VSS_VARIABLE_STORE_HEADER*)store.constData();
|
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
|
// 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)",
|
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);
|
dataSize, dataSize), parent);
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct header and body
|
// Construct header and body
|
||||||
UByteArray header = store.left(sizeof(VSS_VARIABLE_STORE_HEADER));
|
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
|
// Add info
|
||||||
bool isSvsStore = (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE);
|
bool isSvsStore = (vssStoreHeader->Signature == NVRAM_APPLE_SVS_STORE_SIGNATURE);
|
||||||
UString name = isSvsStore ? UString("SVS store") : UString("VSS store");
|
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",
|
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",
|
isSvsStore ? "$SVS" : "$VSS",
|
||||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
storeSize, storeSize,
|
||||||
header.size(), header.size(),
|
header.size(), header.size(),
|
||||||
body.size(), body.size(),
|
body.size(), body.size(),
|
||||||
vssStoreHeader->Format,
|
vssStoreHeader->Format,
|
||||||
@ -787,36 +793,42 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
|
|||||||
return U_SUCCESS;
|
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();
|
const UINT32 dataSize = (const UINT32)store.size();
|
||||||
|
|
||||||
// Check store size
|
// Check store size
|
||||||
if (dataSize < sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER)) {
|
if (dataSize < sizeof(VSS2_VARIABLE_STORE_HEADER)) {
|
||||||
msg(UString("parseLenovoVssStoreHeader: volume body is too small even for VSS store header"), parent);
|
msg(UString("parseVss2StoreHeader: volume body is too small even for VSS2 store header"), parent);
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get VSS store header
|
// Get VSS2 store header
|
||||||
const LENOVO_VSS_VARIABLE_STORE_HEADER* vssStoreHeader = (const LENOVO_VSS_VARIABLE_STORE_HEADER*)store.constData();
|
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
|
// Check store size
|
||||||
if (dataSize < vssStoreHeader->Size) {
|
if (dataSize < storeSize) {
|
||||||
msg(usprintf("parseLenovoVssStoreHeader: VSS store size %Xh (%u) is greater than volume body size %Xh (%u)",
|
msg(usprintf("parseVssStoreHeader: VSS2 store size %Xh (%u) is greater than volume body size %Xh (%u)",
|
||||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
storeSize, storeSize,
|
||||||
dataSize, dataSize), parent);
|
dataSize, dataSize), parent);
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct header and body
|
// Construct header and body
|
||||||
UByteArray header = store.left(sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER));
|
UByteArray header = store.left(sizeof(VSS2_VARIABLE_STORE_HEADER));
|
||||||
UByteArray body = store.mid(sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER), vssStoreHeader->Size - sizeof(LENOVO_VSS_VARIABLE_STORE_HEADER));
|
UByteArray body = store.mid(sizeof(VSS2_VARIABLE_STORE_HEADER), storeSize - sizeof(VSS2_VARIABLE_STORE_HEADER));
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
UString name = UString("Lenovo VSS store");
|
UString name = UString("VSS2 store");
|
||||||
UString info = UString("Signature: ") + guidToUString(vssStoreHeader->Signature, false) +
|
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",
|
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
|
||||||
vssStoreHeader->Size, vssStoreHeader->Size,
|
storeSize, storeSize,
|
||||||
header.size(), header.size(),
|
header.size(), header.size(),
|
||||||
body.size(), body.size(),
|
body.size(), body.size(),
|
||||||
vssStoreHeader->Format,
|
vssStoreHeader->Format,
|
||||||
@ -824,7 +836,7 @@ USTATUS NvramParser::parseLenovoVssStoreHeader(const UByteArray & store, const U
|
|||||||
vssStoreHeader->Unknown);
|
vssStoreHeader->Unknown);
|
||||||
|
|
||||||
// Add tree item
|
// 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;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -920,26 +932,8 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32
|
|||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine internal volume header size
|
// Check header size
|
||||||
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(fdcStoreHeader + 1);
|
UINT32 headerSize = sizeof(FDC_VOLUME_HEADER);
|
||||||
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
|
|
||||||
if (dataSize < headerSize) {
|
if (dataSize < headerSize) {
|
||||||
msg(usprintf("parseFdcStoreHeader: FDC store header size %Xh (%u) is greater than volume body size %Xh (%u)",
|
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,
|
||||||
@ -958,8 +952,6 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32
|
|||||||
header.size(), header.size(),
|
header.size(), header.size(),
|
||||||
body.size(), body.size());
|
body.size(), body.size());
|
||||||
|
|
||||||
// TODO: add internal headers info
|
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(localOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
index = model->addItem(localOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||||
|
|
||||||
@ -1282,10 +1274,10 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
|
|||||||
// Check signature and run parser function needed
|
// Check signature and run parser function needed
|
||||||
// VSS/SVS store
|
// VSS/SVS store
|
||||||
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
|
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
|
||||||
return parseVssStoreHeader(store, localOffset, parent, index);
|
return parseVssStoreHeader(store, localOffset, false, parent, index);
|
||||||
// Lenovo VSS store
|
// VSS2 store
|
||||||
if (*signature == LENOVO_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == LENOVO_VSS_STORE_GUID_PART1)
|
if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1)
|
||||||
return parseLenovoVssStoreHeader(store, localOffset, parent, index);
|
return parseVss2StoreHeader(store, localOffset, false, parent, index);
|
||||||
// FTW store
|
// 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);
|
return parseFtwStoreHeader(store, localOffset, parent, index);
|
||||||
@ -1319,6 +1311,49 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
|
|||||||
return U_SUCCESS;
|
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)
|
USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignment)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
@ -1885,7 +1920,8 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index)
|
|||||||
UByteArray header = data.mid(offset, sizeof(PHOENIX_FLASH_MAP_ENTRY));
|
UByteArray header = data.mid(offset, sizeof(PHOENIX_FLASH_MAP_ENTRY));
|
||||||
|
|
||||||
// Add info
|
// 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"
|
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",
|
"Entry type: %04Xh\nData type: %04Xh\nMemory address: %08Xh\nSize: %08Xh\nOffset: %08Xh",
|
||||||
entryHeader->EntryType,
|
entryHeader->EntryType,
|
||||||
entryHeader->DataType,
|
entryHeader->DataType,
|
||||||
|
@ -21,13 +21,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "ustring.h"
|
#include "ustring.h"
|
||||||
#include "ubytearray.h"
|
#include "ubytearray.h"
|
||||||
#include "treemodel.h"
|
#include "treemodel.h"
|
||||||
|
#include "ffsparser.h"
|
||||||
|
|
||||||
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
||||||
class NvramParser
|
class NvramParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Default constructor and destructor
|
// Default constructor and destructor
|
||||||
NvramParser(TreeModel* treeModel) : model(treeModel) {}
|
NvramParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {}
|
||||||
~NvramParser() {}
|
~NvramParser() {}
|
||||||
|
|
||||||
// Returns messages
|
// Returns messages
|
||||||
@ -41,6 +42,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
TreeModel *model;
|
TreeModel *model;
|
||||||
|
FfsParser *ffsParser;
|
||||||
std::vector<std::pair<UString, UModelIndex> > messagesVector;
|
std::vector<std::pair<UString, UModelIndex> > messagesVector;
|
||||||
void msg(const UString message, const UModelIndex index = UModelIndex()) {
|
void msg(const UString message, const UModelIndex index = UModelIndex()) {
|
||||||
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
|
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 getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
|
||||||
USTATUS parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
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 parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index);
|
||||||
USTATUS parseLenovoVssStoreHeader(const UByteArray & store, const UINT32 localOffset, 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 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 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);
|
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 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 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 parseVssStoreBody(const UModelIndex & index, const UINT8 alignment);
|
||||||
USTATUS parseFsysStoreBody(const UModelIndex & index);
|
USTATUS parseFsysStoreBody(const UModelIndex & index);
|
||||||
USTATUS parseEvsaStoreBody(const UModelIndex & index);
|
USTATUS parseEvsaStoreBody(const UModelIndex & index);
|
||||||
@ -72,7 +75,7 @@ class NvramParser
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Default constructor and destructor
|
// 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() {}
|
~NvramParser() {}
|
||||||
|
|
||||||
// Returns messages
|
// Returns messages
|
||||||
|
@ -26,11 +26,13 @@ QVariant TreeModel::data(const UModelIndex &index, int role) const
|
|||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
return (const char*)item->data(index.column()).toLocal8Bit();
|
return (const char*)item->data(index.column()).toLocal8Bit();
|
||||||
}
|
}
|
||||||
|
#if defined (QT_GUI_LIB)
|
||||||
else if (role == Qt::BackgroundRole) {
|
else if (role == Qt::BackgroundRole) {
|
||||||
if (markingEnabled && marking(index) > 0) {
|
if (markingEnabledFlag && marking(index) > 0) {
|
||||||
return QBrush((Qt::GlobalColor)marking(index));
|
return QBrush((Qt::GlobalColor)marking(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else if (role == Qt::UserRole) {
|
else if (role == Qt::UserRole) {
|
||||||
return (const char*)item->info().toLocal8Bit();
|
return (const char*)item->info().toLocal8Bit();
|
||||||
}
|
}
|
||||||
@ -50,18 +52,12 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
int role) const
|
int role) const
|
||||||
{
|
{
|
||||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||||
switch (section)
|
switch (section) {
|
||||||
{
|
case 0: return tr("Name");
|
||||||
case 0:
|
case 1: return tr("Action");
|
||||||
return tr("Name");
|
case 2: return tr("Type");
|
||||||
case 1:
|
case 3: return tr("Subtype");
|
||||||
return tr("Action");
|
case 4: return tr("Text");
|
||||||
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) {
|
if (orientation == 1 && role == 0) {
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: return UString("Name");
|
||||||
return UString("Name");
|
case 1: return UString("Action");
|
||||||
case 1:
|
case 2: return UString("Type");
|
||||||
return UString("Action");
|
case 3: return UString("Subtype");
|
||||||
case 2:
|
case 4: return UString("Text");
|
||||||
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)
|
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)
|
void TreeModel::setMarking(const UModelIndex &index, const UINT8 marking)
|
||||||
|
@ -25,7 +25,9 @@ enum ItemFixedState {
|
|||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#if defined(QT_GUI_LIB)
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ustring.h"
|
#include "ustring.h"
|
||||||
#include "ubytearray.h"
|
#include "ubytearray.h"
|
||||||
@ -86,15 +88,15 @@ class TreeModel : public QAbstractItemModel
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
bool markingEnabled;
|
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
|
bool markingEnabledFlag;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QVariant data(const UModelIndex &index, int role) const;
|
QVariant data(const UModelIndex &index, int role) const;
|
||||||
Qt::ItemFlags flags(const UModelIndex &index) const;
|
Qt::ItemFlags flags(const UModelIndex &index) const;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation,
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
int role = Qt::DisplayRole) const;
|
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);
|
rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +107,8 @@ class TreeModel
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
|
bool markingEnabledFlag;
|
||||||
|
|
||||||
void dataChanged(const UModelIndex &, const UModelIndex &) {}
|
void dataChanged(const UModelIndex &, const UModelIndex &) {}
|
||||||
void layoutAboutToBeChanged() {}
|
void layoutAboutToBeChanged() {}
|
||||||
void layoutChanged() {}
|
void layoutChanged() {}
|
||||||
@ -130,6 +134,9 @@ public:
|
|||||||
delete rootItem;
|
delete rootItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool markingEnabled() { return markingEnabledFlag; }
|
||||||
|
void setMarkingEnabled(const bool enabled);
|
||||||
|
|
||||||
UModelIndex index(int row, int column, const UModelIndex &parent = UModelIndex()) const;
|
UModelIndex index(int row, int column, const UModelIndex &parent = UModelIndex()) const;
|
||||||
UModelIndex parent(const UModelIndex &index) const;
|
UModelIndex parent(const UModelIndex &index) const;
|
||||||
int rowCount(const UModelIndex &parent = UModelIndex()) 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 addInfo(const UModelIndex &index, const UString &info, const bool append = TRUE);
|
||||||
void setFixed(const UModelIndex &index, const bool fixed);
|
void setFixed(const UModelIndex &index, const bool fixed);
|
||||||
void setCompressed(const UModelIndex &index, const bool compressed);
|
void setCompressed(const UModelIndex &index, const bool compressed);
|
||||||
void setMarkingEnabled(const bool enabled);
|
|
||||||
void setMarking(const UModelIndex &index, const UINT8 marking);
|
void setMarking(const UModelIndex &index, const UINT8 marking);
|
||||||
|
|
||||||
UINT32 offset(const UModelIndex &index) const;
|
UINT32 offset(const UModelIndex &index) const;
|
||||||
@ -163,7 +169,6 @@ public:
|
|||||||
bool fixed(const UModelIndex &index) const;
|
bool fixed(const UModelIndex &index) const;
|
||||||
bool compressed(const UModelIndex &index) const;
|
bool compressed(const UModelIndex &index) const;
|
||||||
UINT8 marking(const UModelIndex &index) const;
|
UINT8 marking(const UModelIndex &index) const;
|
||||||
|
|
||||||
UINT8 action(const UModelIndex &index) const;
|
UINT8 action(const UModelIndex &index) const;
|
||||||
|
|
||||||
UByteArray parsingData(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::MeRegion: return UString("ME");
|
||||||
case Subtypes::GbeRegion: return UString("GbE");
|
case Subtypes::GbeRegion: return UString("GbE");
|
||||||
case Subtypes::PdrRegion: return UString("PDR");
|
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::Reserved1Region: return UString("Reserved1");
|
||||||
case Subtypes::Reserved2Region: return UString("Reserved2");
|
case Subtypes::Reserved2Region: return UString("Reserved2");
|
||||||
case Subtypes::Reserved3Region: return UString("Reserved3");
|
case Subtypes::PttRegion: return UString("PTT");
|
||||||
case Subtypes::EcRegion: return UString("EC");
|
|
||||||
case Subtypes::Reserved4Region: return UString("Reserved4");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return UString("Unknown");
|
return UString("Unknown");
|
||||||
@ -46,7 +52,7 @@ UString itemTypeToUString(const UINT8 type)
|
|||||||
case Types::Section: return UString("Section");
|
case Types::Section: return UString("Section");
|
||||||
case Types::FreeSpace: return UString("Free space");
|
case Types::FreeSpace: return UString("Free space");
|
||||||
case Types::VssStore: return UString("VSS store");
|
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::FtwStore: return UString("FTW store");
|
||||||
case Types::FdcStore: return UString("FDC store");
|
case Types::FdcStore: return UString("FDC store");
|
||||||
case Types::FsysStore: return UString("Fsys 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::Root:
|
||||||
case Types::FreeSpace:
|
case Types::FreeSpace:
|
||||||
case Types::VssStore:
|
case Types::VssStore:
|
||||||
case Types::LenovoVssStore:
|
case Types::Vss2Store:
|
||||||
case Types::FdcStore:
|
case Types::FdcStore:
|
||||||
case Types::FsysStore:
|
case Types::FsysStore:
|
||||||
case Types::EvsaStore:
|
case Types::EvsaStore:
|
||||||
@ -149,7 +155,7 @@ UString compressionTypeToUString(const UINT8 algorithm)
|
|||||||
case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano");
|
case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano");
|
||||||
case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1");
|
case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1");
|
||||||
case COMPRESSION_ALGORITHM_LZMA: return UString("LZMA");
|
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");
|
return UString("Unknown");
|
||||||
@ -173,16 +179,17 @@ UString actionTypeToUString(const UINT8 action)
|
|||||||
UString fitEntryTypeToUString(const UINT8 type)
|
UString fitEntryTypeToUString(const UINT8 type)
|
||||||
{
|
{
|
||||||
switch (type & 0x7F) {
|
switch (type & 0x7F) {
|
||||||
case FIT_TYPE_HEADER: return ("FIT Header");
|
case FIT_TYPE_HEADER: return UString("FIT Header");
|
||||||
case FIT_TYPE_MICROCODE: return ("Microcode");
|
case FIT_TYPE_MICROCODE: return UString("Microcode");
|
||||||
case FIT_TYPE_BIOS_AC_MODULE: return ("BIOS ACM");
|
case FIT_TYPE_BIOS_AC_MODULE: return UString("BIOS ACM");
|
||||||
case FIT_TYPE_BIOS_INIT_MODULE: return ("BIOS Init");
|
case FIT_TYPE_BIOS_INIT_MODULE: return UString("BIOS Init");
|
||||||
case FIT_TYPE_TPM_POLICY: return ("TPM Policy");
|
case FIT_TYPE_TPM_POLICY: return UString("TPM Policy");
|
||||||
case FIT_TYPE_BIOS_POLICY_DATA: return ("BIOS Policy Data");
|
case FIT_TYPE_BIOS_POLICY_DATA: return UString("BIOS Policy Data");
|
||||||
case FIT_TYPE_TXT_CONF_POLICY: return ("TXT Configuration Policy");
|
case FIT_TYPE_TXT_CONF_POLICY: return UString("TXT Configuration Policy");
|
||||||
case FIT_TYPE_AC_KEY_MANIFEST: return ("BootGuard Key Manifest");
|
case FIT_TYPE_AC_KEY_MANIFEST: return UString("BootGuard Key Manifest");
|
||||||
case FIT_TYPE_AC_BOOT_POLICY: return ("BootGuard Boot Policy");
|
case FIT_TYPE_AC_BOOT_POLICY: return UString("BootGuard Boot Policy");
|
||||||
case FIT_TYPE_EMPTY: return ("Empty");
|
case FIT_TYPE_EMPTY: return UString("Empty");
|
||||||
default: return ("Unknown");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return UString("Unknown");
|
||||||
}
|
}
|
@ -44,7 +44,7 @@ namespace Types {
|
|||||||
Section,
|
Section,
|
||||||
FreeSpace,
|
FreeSpace,
|
||||||
VssStore,
|
VssStore,
|
||||||
LenovoVssStore,
|
Vss2Store,
|
||||||
FtwStore,
|
FtwStore,
|
||||||
FdcStore,
|
FdcStore,
|
||||||
FsysStore,
|
FsysStore,
|
||||||
@ -87,11 +87,17 @@ namespace Subtypes {
|
|||||||
MeRegion,
|
MeRegion,
|
||||||
GbeRegion,
|
GbeRegion,
|
||||||
PdrRegion,
|
PdrRegion,
|
||||||
|
DevExp1Region,
|
||||||
|
Bios2Region,
|
||||||
|
MicrocodeRegion,
|
||||||
|
EcRegion,
|
||||||
|
DevExp2Region,
|
||||||
|
IeRegion,
|
||||||
|
Tgbe1Region,
|
||||||
|
Tgbe2Region,
|
||||||
Reserved1Region,
|
Reserved1Region,
|
||||||
Reserved2Region,
|
Reserved2Region,
|
||||||
Reserved3Region,
|
PttRegion
|
||||||
EcRegion,
|
|
||||||
Reserved4Region
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PaddingSubtypes {
|
enum PaddingSubtypes {
|
||||||
|
@ -300,8 +300,8 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8bit checksum calculation routine
|
// 8bit sum calculation routine
|
||||||
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize)
|
||||||
{
|
{
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return 0;
|
return 0;
|
||||||
@ -311,7 +311,16 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
|||||||
while (bufferSize--)
|
while (bufferSize--)
|
||||||
counter += buffer[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
|
// 16bit checksum calculation routine
|
||||||
|
@ -34,6 +34,9 @@ USTATUS decompress(const UByteArray & compressed, const UINT8 compressionType, U
|
|||||||
// CRC32 calculation routine
|
// CRC32 calculation routine
|
||||||
UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length);
|
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
|
// 8bit checksum calculation routine
|
||||||
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user