Skip to content

Commit

Permalink
A45
Browse files Browse the repository at this point in the history
+ 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
  • Loading branch information
matrosov committed Dec 11, 2017
1 parent 0236944 commit 63088af
Show file tree
Hide file tree
Showing 24 changed files with 577 additions and 447 deletions.
1 change: 1 addition & 0 deletions UEFIDump/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ SET(PROJECT_SOURCES
../common/LZMA/SDK/C/LzmaDec.c
../common/Tiano/EfiTianoDecompress.c
../common/ustring.cpp
../common/sha256.c
../common/bstrlib/bstrlib.c
../common/bstrlib/bstrwrap.cpp
)
Expand Down
4 changes: 2 additions & 2 deletions UEFIDump/uefidump_main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* uefidump_main.cpp
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
Copyright (c) 2017, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
Expand Down Expand Up @@ -29,7 +29,7 @@ int main(int argc, char *argv[])
return (uefidumper.dump(buffer, UString(argv[1])) != U_SUCCESS);
}

std::cout << "UEFIDump 0.1.5" << std::endl << std::endl
std::cout << "UEFIDump 0.1.6" << std::endl << std::endl
<< "Usage: UEFIDump imagefile" << std::endl;
return 0;
}
1 change: 1 addition & 0 deletions UEFIExtract/uefiextract.pro
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ SOURCES += \
../common/LZMA/SDK/C/LzmaDec.c \
../common/Tiano/EfiTianoDecompress.c \
../common/ustring.cpp
../common/sha256.c

HEADERS += \
ffsdumper.h \
Expand Down
48 changes: 24 additions & 24 deletions UEFIExtract/uefiextract_main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* uefiextract_main.cpp
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
Copyright (c) 2017, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
Expand All @@ -20,8 +20,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setOrganizationName("LongSoft");
a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIExtract");

if (a.arguments().length() > 32) {
Expand Down Expand Up @@ -63,17 +63,17 @@ int main(int argc, char *argv[])
// Get last VTF
std::vector<std::pair<std::vector<QString>, QModelIndex > > fitTable = ffsParser.getFitTable();
if (fitTable.size()) {
std::cout << "---------------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
std::cout << "---------------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout << fitTable[i].first[0].toLatin1().constData() << " | "
<< fitTable[i].first[1].toLatin1().constData() << " | "
<< fitTable[i].first[2].toLatin1().constData() << " | "
<< fitTable[i].first[3].toLatin1().constData() << " | "
<< fitTable[i].first[4].toLatin1().constData() << " | "
<< fitTable[i].first[5].toLatin1().constData() << std::endl;
}
std::cout << "---------------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
std::cout << "---------------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout << fitTable[i].first[0].toLatin1().constData() << " | "
<< fitTable[i].first[1].toLatin1().constData() << " | "
<< fitTable[i].first[2].toLatin1().constData() << " | "
<< fitTable[i].first[3].toLatin1().constData() << " | "
<< fitTable[i].first[4].toLatin1().constData() << " | "
<< fitTable[i].first[5].toLatin1().constData() << std::endl;
}
}


Expand All @@ -84,7 +84,7 @@ int main(int argc, char *argv[])
if (a.arguments().length() == 3 && a.arguments().at(2) == QString("dump")) {
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS);
}
else if (a.arguments().length() > 3 ||
else if (a.arguments().length() > 3 ||
(a.arguments().length() == 3 && a.arguments().at(2) != QString("all") && a.arguments().at(2) != QString("report"))) { // Dump specific files, without report
UINT32 returned = 0;
for (int i = 2; i < a.arguments().length(); i++) {
Expand All @@ -94,7 +94,7 @@ int main(int argc, char *argv[])
}
return returned;
}

// Create ffsReport
FfsReport ffsReport(&model);
std::vector<QString> report = ffsReport.generate();
Expand All @@ -108,7 +108,7 @@ int main(int argc, char *argv[])
file.close();
}
}

// Dump all non-leaf elements, with report, default
if (a.arguments().length() == 2) {
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS);
Expand All @@ -121,12 +121,12 @@ int main(int argc, char *argv[])
}
}
// If parameters are different, show version and usage information
std::cout << "UEFIExtract 0.13.4" << std::endl << std::endl
<< "Usage: UEFIExtract imagefile - generate report and dump only leaf tree items into .dump folder." << std::endl
<< " UEFIExtract imagefile all - generate report and dump all tree items." << std::endl
<< " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl
<< " UEFIExtract imagefile report - only generate report, no dump needed." << std::endl
<< " UEFIExtract imagefile GUID_1 GUID_2 ... GUID_31 - dump only FFS file(s) with specific GUID(s), without report." << std::endl
<< "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise." << std::endl;
std::cout << "UEFIExtract 0.13.5" << std::endl << std::endl
<< "Usage: UEFIExtract imagefile - generate report and dump only leaf tree items into .dump folder." << std::endl
<< " UEFIExtract imagefile all - generate report and dump all tree items." << std::endl
<< " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl
<< " UEFIExtract imagefile report - only generate report, no dump needed." << std::endl
<< " UEFIExtract imagefile GUID_1 GUID_2 ... GUID_31 - dump only FFS file(s) with specific GUID(s), without report." << std::endl
<< "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise." << std::endl;
return 1;
}
5 changes: 3 additions & 2 deletions UEFIFind/uefifind.pro
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ SOURCES += uefifind_main.cpp \
../common/LZMA/LzmaDecompress.c \
../common/LZMA/SDK/C/LzmaDec.c \
../common/Tiano/EfiTianoDecompress.c \
../common/ustring.cpp
../common/ustring.cpp \
../common/sha256.c

HEADERS += uefifind.h \
../common/guiddatabase.h \
Expand All @@ -41,5 +42,5 @@ HEADERS += uefifind.h \
../common/Tiano/EfiTianoDecompress.h \
../common/ustring.h \
../common/ubytearray.h \
../common/bootguard.h \
../common/bootguard.h \
../common/sha256.h
8 changes: 4 additions & 4 deletions UEFIFind/uefifind_main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* uefifind_main.cpp
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
Copyright (c) 2017, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
Expand All @@ -17,8 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setOrganizationName("LongSoft");
a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIFind");

UEFIFind w;
Expand Down Expand Up @@ -148,7 +148,7 @@ int main(int argc, char *argv[])
return U_SUCCESS;
}
else {
std::cout << "UEFIFind 0.10.9" << std::endl << std::endl <<
std::cout << "UEFIFind 0.10.10" << std::endl << std::endl <<
"Usage: UEFIFind {header | body | all} {list | count} pattern imagefile" << std::endl <<
" or UEFIFind file patternsfile imagefile" << std::endl;
return U_INVALID_PARAMETER;
Expand Down
17 changes: 12 additions & 5 deletions UEFITool/uefitool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr("NE alpha 44"))
version(tr("NE alpha 45"))
{
clipboard = QApplication::clipboard();

Expand Down Expand Up @@ -150,6 +150,10 @@ void UEFITool::init()
delete ffsParser;
ffsParser = new FfsParser(model);

// Set proper marking state
model->setMarkingEnabled(markingEnabled);
ui->actionToggleBootGuardMarking->setChecked(markingEnabled);

// Connect
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &)));
Expand Down Expand Up @@ -199,7 +203,7 @@ void UEFITool::populateUi(const QModelIndex &current)
|| type == Types::EvsaEntry
|| type == Types::FlashMapEntry);
ui->menuStoreActions->setEnabled(type == Types::VssStore
|| type == Types::LenovoVssStore
|| type == Types::Vss2Store
|| type == Types::FdcStore
|| type == Types::FsysStore
|| type == Types::EvsaStore
Expand Down Expand Up @@ -631,7 +635,7 @@ void UEFITool::extract(const UINT8 mode)
case Types::EvsaEntry: path = QFileDialog::getSaveFileName(this, tr("Save EVSA entry to file"), name + ".evse", "EVSA entry files (*.evse *.bin);;All files (*)"); break;
case Types::FlashMapEntry: path = QFileDialog::getSaveFileName(this, tr("Save FlashMap entry to file"), name + ".fme", "FlashMap entry files (*.fme *.bin);;All files (*)"); break;
case Types::VssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break;
case Types::LenovoVssStore: path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)"); break;
case Types::Vss2Store: path = QFileDialog::getSaveFileName(this, tr("Save VSS2 store to file"), name + ".vss2", "VSS2 store files (*.vss2 *.bin);;All files (*)"); break;
case Types::FdcStore: path = QFileDialog::getSaveFileName(this, tr("Save FDC store to file"), name + ".fdc", "FDC store files (*.fdc *.bin);;All files (*)"); break;
case Types::FsysStore: path = QFileDialog::getSaveFileName(this, tr("Save Fsys store to file"), name + ".fsys", "Fsys store files (*.fsys *.bin);;All files (*)"); break;
case Types::EvsaStore: path = QFileDialog::getSaveFileName(this, tr("Save EVSA store to file"), name + ".evsa", "EVSA store files (*.evsa *.bin);;All files (*)"); break;
Expand Down Expand Up @@ -672,7 +676,7 @@ void UEFITool::extract(const UINT8 mode)
case Types::FlashMapEntry:
case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save entry body to file"), name + ".bin", "Binary files (*.bin);;All files (*)"); break;
case Types::VssStore:
case Types::LenovoVssStore:
case Types::Vss2Store:
case Types::FtwStore:
case Types::FdcStore:
case Types::FsysStore:
Expand Down Expand Up @@ -921,6 +925,7 @@ void UEFITool::clearMessages()
void UEFITool::toggleBootGuardMarking(bool enabled)
{
model->setMarkingEnabled(enabled);
markingEnabled = enabled;
}

void UEFITool::dragEnterEvent(QDragEnterEvent* event)
Expand Down Expand Up @@ -1041,7 +1046,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
case Types::EvsaEntry:
case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break;
case Types::VssStore:
case Types::LenovoVssStore:
case Types::Vss2Store:
case Types::FdcStore:
case Types::FsysStore:
case Types::EvsaStore:
Expand Down Expand Up @@ -1069,6 +1074,7 @@ void UEFITool::readSettings()
ui->structureTreeView->setColumnWidth(1, settings.value("tree/columnWidth1", ui->structureTreeView->columnWidth(1)).toInt());
ui->structureTreeView->setColumnWidth(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
ui->structureTreeView->setColumnWidth(3, settings.value("tree/columnWidth3", ui->structureTreeView->columnWidth(3)).toInt());
markingEnabled = settings.value("tree/markingEnabled", true).toBool();
}

void UEFITool::writeSettings()
Expand All @@ -1084,6 +1090,7 @@ void UEFITool::writeSettings()
settings.setValue("tree/columnWidth1", ui->structureTreeView->columnWidth(1));
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
settings.setValue("tree/markingEnabled", markingEnabled);
}

void UEFITool::showFitTable()
Expand Down
1 change: 1 addition & 0 deletions UEFITool/uefitool.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ private slots:
QString currentPath;
QString currentProgramPath;
const QString version;
bool markingEnabled;

bool enableExtractBodyUncompressed(const QModelIndex &current);

Expand Down
4 changes: 2 additions & 2 deletions common/descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ const UINT8* calculateAddress16(const UINT8* baseAddress, const UINT16 baseOrLim
return baseAddress + baseOrLimit * 0x1000;
}

// Calculate offset of region using its base
// Calculate offset of region using it's base
UINT32 calculateRegionOffset(const UINT16 base)

This comment has been minimized.

Copy link
@skochinsky

skochinsky Dec 11, 2017

"its" is actually the correct spelling in this context

{
return base * 0x1000;
}

//Calculate size of region using its base and limit
//Calculate size of region using it's base and limit
UINT32 calculateRegionSize(const UINT16 base, const UINT16 limit)
{
if (limit)
Expand Down
36 changes: 24 additions & 12 deletions common/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,25 +106,37 @@ typedef struct FLASH_DESCRIPTOR_COMPONENT_SECTION_ {
// If limit is zero - region is not present
typedef struct FLASH_DESCRIPTOR_REGION_SECTION_ {
UINT16 DescriptorBase; // Descriptor
UINT16 DescriptorLimit; //
UINT16 DescriptorLimit; //
UINT16 BiosBase; // BIOS
UINT16 BiosLimit; //
UINT16 MeBase; // ME
UINT16 MeBase; // Management Engine
UINT16 MeLimit; //
UINT16 GbeBase; // GbE
UINT16 GbeBase; // Gigabit Ethernet
UINT16 GbeLimit; //
UINT16 PdrBase; // PDR
UINT16 PdrBase; // Platform Data
UINT16 PdrLimit; //
UINT16 Reserved1Base; // Reserved1
UINT16 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 Reserved1Limit; //
UINT16 Reserved2Base; // Reserved2
UINT16 Reserved2Base; // Reserved 2
UINT16 Reserved2Limit; //
UINT16 Reserved3Base; // Reserved3
UINT16 Reserved3Limit; //
UINT16 EcBase; // EC
UINT16 EcLimit; //
UINT16 Reserved4Base; // Reserved4
UINT16 Reserved4Limit; //
UINT16 PttBase; // Platform Trust Technology
UINT16 PttLimit; //
} FLASH_DESCRIPTOR_REGION_SECTION;

// Master section
Expand Down
3 changes: 3 additions & 0 deletions common/ffs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const std::vector<UByteArray> FFSv3Volumes(1, EFI_FIRMWARE_FILE_SYSTEM3_GUID);
const UINT8 ffsAlignmentTable[] =
{ 0, 4, 7, 9, 10, 12, 15, 16 };

const UINT8 ffsAlignment2Table[] =
{ 17, 18, 19, 20, 21, 22, 23, 24 };

VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
{
ffsSize[2] = (UINT8)((size) >> 16);
Expand Down
17 changes: 13 additions & 4 deletions common/ffs.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ UINT8 Type;
UINT8 Attributes;
UINT8 Size[3]; // Set to 0xFFFFFF
UINT8 State;
UINT32 ExtendedSize;
UINT64 ExtendedSize;
} EFI_FFS_FILE_HEADER2;

// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
Expand Down Expand Up @@ -324,21 +324,26 @@ UINT32 ExtendedSize;
#define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
#define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes
#define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes
#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 // Volaid only for revision 2 volumes, added in UEFI PI 1.6

This comment has been minimized.

Copy link
@skochinsky

skochinsky Dec 11, 2017

typo, should be "Valid".

#define FFS_ATTRIB_FIXED 0x04
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
#define FFS_ATTRIB_CHECKSUM 0x40

// FFS alignment table
extern const UINT8 ffsAlignmentTable[];

// Extended FFS alignment table, added in UEFI PI 1.6
extern const UINT8 ffsAlignment2Table[];


// File states
#define EFI_FILE_HEADER_CONSTRUCTION 0x01
#define EFI_FILE_HEADER_VALID 0x02
#define EFI_FILE_DATA_VALID 0x04
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
#define EFI_FILE_DELETED 0x10
#define EFI_FILE_HEADER_INVALID 0x20
#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI Vol3
#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI

// PEI apriori file
const UByteArray EFI_PEI_APRIORI_FILE_GUID
Expand All @@ -356,10 +361,14 @@ const UByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
const UByteArray EFI_FFS_PAD_FILE_GUID
("\x85\x65\x53\xE4\x09\x79\x60\x4A\xB5\xC6\xEC\xDE\xA6\xEB\xFB\x54", 16);

// DXE core file
const UByteArray EFI_DXE_CORE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
// AMI DXE core file
const UByteArray AMI_CORE_DXE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
("\x7E\xF3\xE3\x5A\xAE\x4E\xAE\x41\x82\x40\x35\x46\x5B\x5E\x81\xEB", 16);

// EDK2 DXE code file

This comment has been minimized.

Copy link
@skochinsky

skochinsky Dec 11, 2017

"DXE core" I assume

const UByteArray EFI_DXE_CORE_GUID // D6A2CB7F-6A18-4E2F-B43B-9920A733700A
("\x7F\xCB\xA2\xD6\x18\x6A\x2F\x4E\xB4\x3B\x99\x20\xA7\x33\x70\x0A", 16);

// FFS size conversion routines
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
Expand Down
Loading

0 comments on commit 63088af

Please sign in to comment.