Merge recent updates but without broken builder and with minor refactoring and bugfixes

This commit is contained in:
vit9696 2018-10-08 12:58:12 +03:00
parent b064495db8
commit 0a634ebcbd
37 changed files with 712 additions and 8665 deletions

4
.gitignore vendored
View File

@ -3,6 +3,7 @@
#################
moc_*.*
ui_*.*
qrc_*.*
#################
## Qt Creator
@ -234,6 +235,8 @@ Makefile
uefitool_plugin_import.cpp
UEFITool.app/
UEFITool/Info.plist
UEFITool/XCBuildData
UEFIDump/UEFIDump
UEFIExtract/UEFIExtract
UEFIFind/UEFIFind
@ -245,3 +248,4 @@ DerivedData
*.xcodeproj
compile_commands.json
CMakeScripts
UEFITool/qrc_uefitool.cpp

View File

@ -35,6 +35,7 @@ There are some other projects that use UEFITool's engine:
## Alternatives
Right now there are some alternatives to UEFITool that you could find useful too:
* **[Fiano](https://github.com/linuxboot/fiano) by Google. Go-based cross-platform open source toolset for modifying UEFI firmware images.
* **[PhoenixTool](http://forums.mydigitallife.info/threads/13194-Tool-to-Insert-Replace-SLIC-in-Phoenix-Insyde-Dell-EFI-BIOSes)** by [AndyP](http://forums.mydigitallife.info/members/39295-andyp). Windows-only freeware GUI application written in C#. Used mostly for SLIC-related modifications, but it not limited to this task. Requires Microsoft .NET 3.5 to work properly. Supports unpacking firmware images from various vendor-specific formats like encrypted HP update files and Dell installers.
* **[uefi-firmware-parser](https://github.com/theopolis/uefi-firmware-parser)** by [Teddy Reed](https://github.com/theopolis). Cross-platform open source console application written in Python. Very tinker-friendly due to use of Python. Can be used in scripts to automate firmware patching.
* **[Chipsec](https://github.com/chipsec/chipsec)** by Intel. Cross-platform partially open source console application written in Python and C. Can be used to test Intel-based platforms for various security-related misconfigurations, but also has NVRAM parser and other components aimed to firmware modification.
@ -46,7 +47,7 @@ Right now there are some alternatives to UEFITool that you could find useful too
You can either use [pre-built binaries for Windows and macOS](https://github.com/LongSoft/UEFITool/releases) or build a binary yourself.
* To build a binary that uses Qt library (UEFITool) you need a C++ compiler and an instance of [Qt5](https://www.qt.io) library. Install both of them, get the sources, generate makefiles using qmake (`qmake UEFITool.pro`) and use your system's make command on that generated files (i.e. `nmake release`, `make release` and so on).
* To build a binary that doesn't use Qt (UEFIExtract, UEFIFind), you need a C++ compiler and [CMAKE](https://cmake.org) utility to generate a makefile for your OS and build environment. Install both of them, get the sources, generate makefiles using cmake (`cmake UEFIDump`) and use your system's make command on that generated files (i.e. `nmake release`, `make release` and so on).
* To build a binary that doesn't use Qt (UEFIExtract, UEFIFind), you need a C++ compiler and [CMAKE](https://cmake.org) utility to generate a makefile for your OS and build environment. Install both of them, get the sources, generate makefiles using cmake (`cmake UEFIExtract`) and use your system's make command on that generated files (i.e. `nmake release`, `make release` and so on).
## Known issues

View File

@ -23,7 +23,7 @@ USTATUS FfsDumper::dump(const UModelIndex & root, const UString & path, const Du
if (changeDirectory(path))
return U_DIR_ALREADY_EXIST;
UINT8 result = recursiveDump(root, path, dumpMode, sectionType, guid);
USTATUS result = recursiveDump(root, path, dumpMode, sectionType, guid);
if (result)
return result;
else if (!dumped)
@ -123,7 +123,7 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
dumped = true;
}
UINT8 result;
USTATUS result;
for (int i = 0; i < model->rowCount(index); i++) {
UModelIndex childIndex = index.child(i, 0);
bool useText = FALSE;

View File

@ -1,6 +1,6 @@
/* ffsdumper.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, 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
@ -90,7 +90,7 @@ USTATUS UEFIDumper::dump(const UByteArray & buffer, const UString & inPath, cons
return U_DIR_CHANGE;
dumped = false;
UINT8 result = recursiveDump(model.index(0,0));
USTATUS result = recursiveDump(model.index(0,0));
if (result)
return result;
else if (!dumped)
@ -133,7 +133,7 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
if (!data.isEmpty()) {
std::ofstream file;
UString str = name + UString("_header.bin");
file.open((const char*)str, std::ios::out | std::ios::binary);
file.open(str.toLocal8Bit(), std::ios::out | std::ios::binary);
file.write(data.constData(), data.size());
file.close();
}
@ -143,7 +143,7 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
if (!data.isEmpty()) {
std::ofstream file;
UString str = name + UString("_body.bin");
file.open((const char*)str, std::ios::out | std::ios::binary);
file.open(str.toLocal8Bit(), std::ios::out | std::ios::binary);
file.write(data.constData(), data.size());
file.close();
}
@ -157,15 +157,15 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
std::ofstream file;
UString str = name + UString("_info.txt");
file.open((const char*)str, std::ios::out);
file.write((const char*)info, info.length());
file.open(str.toLocal8Bit(), std::ios::out);
file.write(info.toLocal8Bit(), info.length());
file.close();
dumped = true;
//}
// Process child items
UINT8 result;
USTATUS result;
for (int i = 0; i < model.rowCount(index); i++) {
result = recursiveDump(index.child(i, 0));
if (result)

View File

@ -1,6 +1,6 @@
/* uefidump.h
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, 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

View File

@ -36,17 +36,12 @@ int main(int argc, char *argv[])
if (argc > 1) {
// Check that input file exists
USTATUS result;
UByteArray buffer;
UString path = argv[1];
if (!isExistOnFs(path))
return U_FILE_OPEN;
// Open the input file
std::ifstream inputFile(argv[1], std::ios::in | std::ios::binary);
if (!inputFile)
return U_FILE_OPEN;
std::vector<char> buffer(std::istreambuf_iterator<char>(inputFile),
(std::istreambuf_iterator<char>()));
inputFile.close();
result = readFileIntoBuffer(path, buffer);
if (result)
return result;
// Hack to support legacy UEFIDump mode.
if (argc == 3 && !std::strcmp(argv[2], "unpack")) {
@ -58,7 +53,7 @@ int main(int argc, char *argv[])
TreeModel model;
FfsParser ffsParser(&model);
// Parse input buffer
USTATUS result = ffsParser.parse(buffer);
result = ffsParser.parse(buffer);
if (result)
return result;

View File

@ -32,16 +32,10 @@ UEFIFind::~UEFIFind()
USTATUS UEFIFind::init(const UString & path)
{
USTATUS result;
if (!isExistOnFs(path))
return U_FILE_OPEN;
std::ifstream inputFile(path.toLocal8Bit(), std::ios::in | std::ios::binary);
if (!inputFile)
return U_FILE_OPEN;
std::vector<char> buffer(std::istreambuf_iterator<char>(inputFile),
(std::istreambuf_iterator<char>()));
inputFile.close();
UByteArray buffer;
result = readFileIntoBuffer(path, buffer);
if (result)
return result;
result = ffsParser->parse(buffer);
if (result)

View File

@ -22,7 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[])
{
UEFIFind w;
UINT8 result;
USTATUS result;
initGuidDatabase("guids.csv");

View File

@ -112,7 +112,7 @@ int QHexEdit::addressWidth()
if (size > Q_INT64_C(0x100000000)){ n += 8; size /= Q_INT64_C(0x100000000);}
if (size > 0x10000){ n += 4; size /= 0x10000;}
if (size > 0x100){ n += 2; size /= 0x100;}
if (size > 0x10){ n += 1; size /= 0x10;}
if (size > 0x10){ n += 1; }
if (n > _addressWidth)
return n;

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,8 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr(PROGRAM_VERSION))
version(tr(PROGRAM_VERSION)),
markingEnabled(true)
{
clipboard = QApplication::clipboard();
@ -72,7 +73,7 @@ version(tr(PROGRAM_VERSION))
setAcceptDrops(true);
// Disable Builder tab, doesn't work right now
ui->messagesTabWidget->setTabEnabled(4, false);
ui->messagesTabWidget->setTabEnabled(TAB_BUILDER, false);
// Set current directory
currentDir = ".";
@ -109,9 +110,11 @@ void UEFITool::init()
ui->fitTableWidget->setRowCount(0);
ui->fitTableWidget->setColumnCount(0);
ui->infoEdit->clear();
ui->bootGuardEdit->clear();
ui->messagesTabWidget->setTabEnabled(1, false);
ui->messagesTabWidget->setTabEnabled(2, false);
ui->securityEdit->clear();
ui->messagesTabWidget->setTabEnabled(TAB_FIT, false);
ui->messagesTabWidget->setTabEnabled(TAB_SECURITY, false);
ui->messagesTabWidget->setTabEnabled(TAB_SEARCH, false);
ui->messagesTabWidget->setTabEnabled(TAB_BUILDER, false);
// Set window title
setWindowTitle(tr("UEFITool %1").arg(version));
@ -233,25 +236,6 @@ bool UEFITool::enableExtractBodyUncompressed(const QModelIndex &current)
{
// TODO: rewrite based on model->compressed()
U_UNUSED_PARAMETER(current);
/*if (current.isValid() && model->type(current) == Types::Section &&
(model->subtype(current) == EFI_SECTION_COMPRESSION || model->subtype(current) == EFI_SECTION_GUID_DEFINED)) {
// Get parsing data
PARSING_DATA pdata = parsingDataFromUModelIndex(current);
if (model->subtype(current) == EFI_SECTION_COMPRESSION &&
pdata.section.compressed.algorithm != COMPRESSION_ALGORITHM_NONE &&
pdata.section.compressed.algorithm != COMPRESSION_ALGORITHM_UNKNOWN &&
pdata.section.compressed.algorithm != COMPRESSION_ALGORITHM_UNDECIDED) { //Compressed section
return true;
}
else if (model->subtype(current) == EFI_SECTION_GUID_DEFINED) {
QByteArray guid = QByteArray((const char*)&pdata.section.guidDefined.guid, sizeof(EFI_GUID));
if (guid == EFI_GUIDED_SECTION_TIANO || guid == EFI_GUIDED_SECTION_LZMA) {
return true;
}
}
}*/
return false;
}
@ -400,57 +384,6 @@ void UEFITool::goToData()
void UEFITool::insert(const UINT8 mode)
{
U_UNUSED_PARAMETER(mode);
/*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
UINT8 type;
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
type = model->type(index.parent());
else
type = model->type(index);
QString path;
switch (type) {
case Types::Volume:
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"), currentDir, "FFS files (*.ffs *.bin);;All files (*)");
break;
case Types::File:
case Types::Section:
path = QFileDialog::getOpenFileName(this, tr("Select section file to insert"), currentDir, "Section files (*.sct *.bin);;All files (*)");
break;
default:
return;
}
if (path.trimmed().isEmpty())
return;
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists()) {
ui->statusBar->showMessage(tr("Please select existing file"));
return;
}
QFile inputFile;
inputFile.setFileName(path);
if (!inputFile.open(QFile::ReadOnly)) {
QMessageBox::critical(this, tr("Insertion failed"), tr("Can't open output file for reading"), QMessageBox::Ok);
return;
}
QByteArray buffer = inputFile.readAll();
inputFile.close();
UINT8 result = ffsEngine->insert(index, buffer, mode);
if (result) {
QMessageBox::critical(this, tr("Insertion failed"), errorMessage(result), QMessageBox::Ok);
return;
}
ui->actionSaveImageFile->setEnabled(true);*/
}
void UEFITool::insertInto()
@ -482,97 +415,6 @@ void UEFITool::replace(const UINT8 mode)
{
U_UNUSED_PARAMETER(mode);
/*
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
QString path;
if (model->type(index) == Types::Region) {
if (mode == REPLACE_MODE_AS_IS) {
path = QFileDialog::getOpenFileName(this, tr("Select region file to replace %1").arg(model->name(index)), currentDir, "Region files (*.rgn *.bin);;All files (*)");
}
else
return;
}
else if (model->type(index) == Types::Volume) {
if (mode == REPLACE_MODE_AS_IS) {
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace selected volume"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
}
else if (mode == REPLACE_MODE_BODY) {
path = QFileDialog::getOpenFileName(this, tr("Select volume body file to replace the body of selected volume"), currentDir, "Volume body files (*.vbd *.bin);;All files (*)");
}
else
return;
}
else if (model->type(index) == Types::File) {
if (mode == REPLACE_MODE_AS_IS) {
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to replace %1 file").arg(model->text(index).isEmpty() ? model->name(index) : model->text(index)),
currentDir, "FFS files (*.ffs *.bin);;All files (*)");
}
else if (mode == REPLACE_MODE_BODY) {
if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW)
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace the body of %1 file").arg(model->text(index).isEmpty() ? model->name(index) : model->text(index)),
currentDir, "Raw files (*.raw *.bin);;All files (*)");
else if (model->subtype(index) == EFI_FV_FILETYPE_PAD) // Pad file body can't be replaced
//!TODO: handle non-empty pad files
return;
else
path = QFileDialog::getOpenFileName(this, tr("Select FFS file body to replace the body of %1 file").arg(model->text(index).isEmpty() ? model->name(index) : model->text(index)),
currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
}
else
return;
}
else if (model->type(index) == Types::Section) {
if (mode == REPLACE_MODE_AS_IS) {
path = QFileDialog::getOpenFileName(this, tr("Select section file to replace selected section"), currentDir, "Section files (*.sct *.bin);;All files (*)");
}
else if (mode == REPLACE_MODE_BODY) {
if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)
path = QFileDialog::getOpenFileName(this, tr("Select FFS file body file to replace the body of selected section"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace the body of selected section"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
else if (model->subtype(index) == EFI_SECTION_RAW)
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace the body of selected section"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else if (model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE || model->subtype(index) == EFI_SECTION_PIC)
path = QFileDialog::getOpenFileName(this, tr("Select EFI executable file to replace the body of selected section"), currentDir, "EFI executable files (*.efi *.dxe *.pei *.bin);;All files (*)");
else
path = QFileDialog::getOpenFileName(this, tr("Select file to replace the body of selected section"), currentDir, "Binary files (*.bin);;All files (*)");
}
else
return;
}
else
return;
if (path.trimmed().isEmpty())
return;
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists()) {
ui->statusBar->showMessage(tr("Please select an existing file"));
return;
}
QFile inputFile;
inputFile.setFileName(path);
if (!inputFile.open(QFile::ReadOnly)) {
QMessageBox::critical(this, tr("Replacing failed"), tr("Can't open input file for reading"), QMessageBox::Ok);
return;
}
QByteArray buffer = inputFile.readAll();
inputFile.close();
UINT8 result = ffsOps->replace(index, buffer, mode);
if (result) {
QMessageBox::critical(this, tr("Replacing failed"), errorCodeToUString(result), QMessageBox::Ok);
return;
}
ui->actionSaveImageFile->setEnabled(true);
*/
}
void UEFITool::extractAsIs()
@ -699,26 +541,12 @@ void UEFITool::extract(const UINT8 mode)
void UEFITool::rebuild()
{
/*
UModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
if (U_SUCCESS == ffsOps->rebuild(index))
ui->actionSaveImageFile->setEnabled(true);
*/
}
void UEFITool::remove()
{
/*
UModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
if (U_SUCCESS == ffsOps->remove(index))
ui->actionSaveImageFile->setEnabled(true);
*/
}
void UEFITool::about()
@ -748,35 +576,7 @@ void UEFITool::exit()
void UEFITool::saveImageFile()
{
/*QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, tr("BIOS image files (*.rom *.bin *.cap *.scap *.bio *.fd *.wph *.dec);;All files (*)"));
if (path.isEmpty())
return;
QByteArray reconstructed;
// Create ffsBuilder
delete ffsBuilder;
ffsBuilder = new FfsBuilder(model);
USTATUS result = ffsBuilder->build(model->index(0,0), reconstructed);
showBuilderMessages();
if (result) {
QMessageBox::critical(this, tr("Image build failed"), errorCodeToUString(result), QMessageBox::Ok);
return;
}
QFile outputFile;
outputFile.setFileName(path);
if (!outputFile.open(QFile::WriteOnly)) {
QMessageBox::critical(this, tr("Image build failed"), tr("Can't open output file for rewriting"), QMessageBox::Ok);
return;
}
outputFile.resize(0);
outputFile.write(reconstructed);
outputFile.close();
if (QMessageBox::Yes == QMessageBox::information(this, tr("Image build successful"), tr("Open the resulting file?"), QMessageBox::Yes, QMessageBox::No))
openImageFile(path);
*/
}
void UEFITool::openImageFile()
@ -832,6 +632,9 @@ void UEFITool::openImageFile(QString path)
// Enable or disable FIT tab
showFitTable();
// Enable or disable Security tab
showSecurityInfo();
// Enable search ...
delete ffsFinder;
ffsFinder = new FfsFinder(model);
@ -869,11 +672,11 @@ void UEFITool::enableMessagesCopyActions(QListWidgetItem* item)
void UEFITool::copyMessage()
{
clipboard->clear();
if (ui->messagesTabWidget->currentIndex() == 0) // Parser tab
if (ui->messagesTabWidget->currentIndex() == TAB_PARSER) // Parser tab
clipboard->setText(ui->parserMessagesListWidget->currentItem()->text());
else if (ui->messagesTabWidget->currentIndex() == 3) // Search tab
else if (ui->messagesTabWidget->currentIndex() == TAB_SEARCH) // Search tab
clipboard->setText(ui->finderMessagesListWidget->currentItem()->text());
else if (ui->messagesTabWidget->currentIndex() == 4) // Builder tab
else if (ui->messagesTabWidget->currentIndex() == TAB_BUILDER) // Builder tab
clipboard->setText(ui->builderMessagesListWidget->currentItem()->text());
}
@ -881,17 +684,17 @@ void UEFITool::copyAllMessages()
{
QString text;
clipboard->clear();
if (ui->messagesTabWidget->currentIndex() == 0) { // Parser tab
if (ui->messagesTabWidget->currentIndex() == TAB_PARSER) { // Parser tab
for (INT32 i = 0; i < ui->parserMessagesListWidget->count(); i++)
text.append(ui->parserMessagesListWidget->item(i)->text()).append("\n");
clipboard->setText(text);
}
else if (ui->messagesTabWidget->currentIndex() == 3) { // Search tab
else if (ui->messagesTabWidget->currentIndex() == TAB_SEARCH) { // Search tab
for (INT32 i = 0; i < ui->finderMessagesListWidget->count(); i++)
text.append(ui->finderMessagesListWidget->item(i)->text()).append("\n");
clipboard->setText(text);
}
else if (ui->messagesTabWidget->currentIndex() == 4) { // Builder tab
else if (ui->messagesTabWidget->currentIndex() == TAB_BUILDER) { // Builder tab
for (INT32 i = 0; i < ui->builderMessagesListWidget->count(); i++)
text.append(ui->builderMessagesListWidget->item(i)->text()).append("\n");
clipboard->setText(text);
@ -900,15 +703,15 @@ void UEFITool::copyAllMessages()
void UEFITool::clearMessages()
{
if (ui->messagesTabWidget->currentIndex() == 0) { // Parser tab
if (ui->messagesTabWidget->currentIndex() == TAB_PARSER) { // Parser tab
if (ffsParser) ffsParser->clearMessages();
ui->parserMessagesListWidget->clear();
}
else if (ui->messagesTabWidget->currentIndex() == 3) { // Search tab
else if (ui->messagesTabWidget->currentIndex() == TAB_SEARCH) { // Search tab
if (ffsFinder) ffsFinder->clearMessages();
ui->finderMessagesListWidget->clear();
}
else if (ui->messagesTabWidget->currentIndex() == 4) { // Builder tab
else if (ui->messagesTabWidget->currentIndex() == TAB_BUILDER) { // Builder tab
if (ffsBuilder) ffsBuilder->clearMessages();
ui->builderMessagesListWidget->clear();
}
@ -951,7 +754,7 @@ void UEFITool::showParserMessages()
ui->parserMessagesListWidget->addItem(item);
}
ui->messagesTabWidget->setCurrentIndex(0);
ui->messagesTabWidget->setCurrentIndex(TAB_PARSER);
ui->parserMessagesListWidget->scrollToBottom();
}
@ -969,7 +772,8 @@ void UEFITool::showFinderMessages()
ui->finderMessagesListWidget->addItem(item);
}
ui->messagesTabWidget->setCurrentIndex(3);
ui->messagesTabWidget->setTabEnabled(TAB_SEARCH, true);
ui->messagesTabWidget->setCurrentIndex(TAB_SEARCH);
ui->finderMessagesListWidget->scrollToBottom();
}
@ -987,7 +791,8 @@ void UEFITool::showBuilderMessages()
ui->builderMessagesListWidget->addItem(item);
}
ui->messagesTabWidget->setCurrentIndex(4);
ui->messagesTabWidget->setTabEnabled(TAB_BUILDER, true);
ui->messagesTabWidget->setCurrentIndex(TAB_BUILDER);
ui->builderMessagesListWidget->scrollToBottom();
}
@ -1013,16 +818,19 @@ void UEFITool::scrollTreeView(QTableWidgetItem* item)
void UEFITool::contextMenuEvent(QContextMenuEvent* event)
{
if (ui->parserMessagesListWidget->underMouse() ||
ui->finderMessagesListWidget->underMouse() ||
ui->builderMessagesListWidget->underMouse()) {
// The checks involving underMouse do not work well enough on macOS, and result in right-click sometimes
// not showing any context menu at all. Most likely it is a bug in Qt, which does not affect other systems.
// For this reason we reimplement this manually.
if (ui->parserMessagesListWidget->rect().contains(ui->parserMessagesListWidget->mapFromGlobal(event->globalPos())) ||
ui->finderMessagesListWidget->rect().contains(ui->finderMessagesListWidget->mapFromGlobal(event->globalPos())) ||
ui->builderMessagesListWidget->rect().contains(ui->builderMessagesListWidget->mapFromGlobal(event->globalPos()))) {
ui->menuMessageActions->exec(event->globalPos());
return;
}
if (!ui->structureTreeView->underMouse()) {
if (!ui->structureTreeView->rect().contains(ui->structureTreeView->mapFromGlobal(event->globalPos())))
return;
}
QPoint pt = event->pos();
QModelIndex index = ui->structureTreeView->indexAt(ui->structureTreeView->viewport()->mapFrom(this, pt));
@ -1039,11 +847,6 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
case Types::Volume: ui->menuVolumeActions->exec(event->globalPos()); break;
case Types::File: ui->menuFileActions->exec(event->globalPos()); break;
case Types::Section: ui->menuSectionActions->exec(event->globalPos()); break;
case Types::NvarEntry:
case Types::VssEntry:
case Types::FsysEntry:
case Types::EvsaEntry:
case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break;
case Types::VssStore:
case Types::Vss2Store:
case Types::FdcStore:
@ -1051,9 +854,9 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
case Types::EvsaStore:
case Types::FtwStore:
case Types::FlashMapStore:
case Types::CmdbStore:
case Types::Microcode:
case Types::SlicData: ui->menuStoreActions->exec(event->globalPos()); break;
case Types::CmdbStore: ui->menuStoreActions->exec(event->globalPos()); break;
case Types::FreeSpace: break;
default: ui->menuEntryActions->exec(event->globalPos()); break;
}
}
@ -1095,7 +898,7 @@ void UEFITool::readSettings()
ui->finderMessagesListWidget->setFont(currentFont);
ui->builderMessagesListWidget->setFont(currentFont);
ui->fitTableWidget->setFont(currentFont);
ui->bootGuardEdit->setFont(currentFont);
ui->securityEdit->setFont(currentFont);
ui->structureTreeView->setFont(currentFont);
searchDialog->ui->guidEdit->setFont(currentFont);
searchDialog->ui->hexEdit->setFont(currentFont);
@ -1127,14 +930,12 @@ void UEFITool::showFitTable()
std::vector<std::pair<std::vector<UString>, UModelIndex> > fitTable = ffsParser->getFitTable();
if (fitTable.empty()) {
// Disable FIT tab
ui->messagesTabWidget->setTabEnabled(1, false);
// Disable BootGuard tab
ui->messagesTabWidget->setTabEnabled(2, false);
ui->messagesTabWidget->setTabEnabled(TAB_FIT, false);
return;
}
// Enable FIT tab
ui->messagesTabWidget->setTabEnabled(1, true);
ui->messagesTabWidget->setTabEnabled(TAB_FIT, true);
// Set up the FIT table
ui->fitTableWidget->clear();
@ -1157,19 +958,21 @@ void UEFITool::showFitTable()
ui->fitTableWidget->resizeColumnsToContents();
ui->fitTableWidget->resizeRowsToContents();
ui->messagesTabWidget->setCurrentIndex(1);
ui->messagesTabWidget->setCurrentIndex(TAB_FIT);
}
// Get BootGuard info
UString bgInfo = ffsParser->getBootGuardInfo();
if (bgInfo.isEmpty()) {
// Disable BootGuard tab
ui->messagesTabWidget->setTabEnabled(2, false);
void UEFITool::showSecurityInfo()
{
// Get security info
UString secInfo = ffsParser->getSecurityInfo();
if (secInfo.isEmpty()) {
ui->messagesTabWidget->setTabEnabled(TAB_SECURITY, false);
return;
}
ui->messagesTabWidget->setTabEnabled(2, true);
ui->bootGuardEdit->setPlainText(bgInfo);
ui->messagesTabWidget->setCurrentIndex(2);
ui->messagesTabWidget->setTabEnabled(TAB_SECURITY, true);
ui->securityEdit->setPlainText(secInfo);
ui->messagesTabWidget->setCurrentIndex(TAB_SECURITY);
}
void UEFITool::currentTabChanged(int index)
@ -1206,8 +1009,6 @@ void UEFITool::loadDefaultGuidDatabase()
openImageFile(currentPath);
}
void UEFITool::generateReport()
{
QString path = QFileDialog::getSaveFileName(this, tr("Save report to text file"), currentPath + ".report.txt", tr("Text files (*.txt);;All files (*)"));

View File

@ -152,7 +152,16 @@ private:
void showParserMessages();
void showFinderMessages();
void showFitTable();
void showSecurityInfo();
void showBuilderMessages();
enum {
TAB_PARSER,
TAB_FIT,
TAB_SECURITY,
TAB_SEARCH,
TAB_BUILDER
};
};
#endif // UEFITOOL_H

View File

@ -203,12 +203,12 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="bootGuardTab">
<widget class="QWidget" name="securityTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>BootGuard</string>
<string>Security</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
@ -227,7 +227,7 @@
<number>5</number>
</property>
<item>
<widget class="QPlainTextEdit" name="bootGuardEdit">
<widget class="QPlainTextEdit" name="securityEdit">
<property name="acceptDrops">
<bool>false</bool>
</property>

View File

@ -536,41 +536,16 @@ Returns: (VOID)
--*/
{
if (mText) {
free (mText);
}
if (mLevel) {
free (mLevel);
}
if (mChildCount) {
free (mChildCount);
}
if (mPosition) {
free (mPosition);
}
if (mParent) {
free (mParent);
}
if (mPrev) {
free (mPrev);
}
if (mNext) {
free (mNext);
}
if (mBuf) {
free (mBuf);
}
return;
}
STATIC
VOID

View File

@ -580,41 +580,16 @@ VOID
--*/
{
if (mText != NULL) {
free (mText);
}
if (mLevel != NULL) {
free (mLevel);
}
if (mChildCount != NULL) {
free (mChildCount);
}
if (mPosition != NULL) {
free (mPosition);
}
if (mParent != NULL) {
free (mParent);
}
if (mPrev != NULL) {
free (mPrev);
}
if (mNext != NULL) {
free (mNext);
}
if (mBuf != NULL) {
free (mBuf);
}
return ;
}
STATIC
VOID
InitSlide (

View File

@ -65,7 +65,8 @@ typedef size_t USTATUS;
#define U_INVALID_ACM 43
#define U_INVALID_BG_KEY_MANIFEST 44
#define U_INVALID_BG_BOOT_POLICY 45
#define U_ELEMENTS_NOT_FOUND 46
#define U_INVALID_TXT_CONF 46
#define U_ELEMENTS_NOT_FOUND 47
#define U_NOT_IMPLEMENTED 0xFF
// UDK porting definitions
@ -87,6 +88,10 @@ typedef ptrdiff_t INTN;
#define VOID void
#define STATIC static
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif
#ifndef TRUE
#define TRUE ((BOOLEAN)(1==1))
#endif

View File

@ -72,11 +72,15 @@ typedef struct BG_MICROSOFT_PMDA_ENTRY_
// Intel ACM
//
#define INTEL_ACM_MODULE_TYPE 0x00030002
#define INTEL_ACM_MODULE_TYPE 0x2
#define INTEL_ACM_MODULE_SUBTYPE_TXT_ACM 0x0
#define INTEL_ACM_MODULE_SUBTYPE_S_ACM 0x1
#define INTEL_ACM_MODULE_SUBTYPE_BOOTGUARD 0x3
#define INTEL_ACM_MODULE_VENDOR 0x8086
typedef struct INTEL_ACM_HEADER_ {
UINT32 ModuleType;
UINT16 ModuleType;
UINT16 ModuleSubtype;
UINT32 HeaderType;
UINT32 HeaderVersion;
UINT16 ChipsetId;

View File

@ -363,6 +363,7 @@ struct CBString : public tagbstring {
// QString compatibility methods
const char *toLocal8Bit() const { return *this; }
bool contains(const char *str) { return find(str) >= 0; }
bool isEmpty() const { return slen == 0; }
void clear() { *this = ""; }
CBString left(int len) const { return midstr(0, len); }

View File

@ -10,6 +10,8 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <cstdio>
#include "ffs.h"
#include "guiddatabase.h"
@ -17,8 +19,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
const UByteArray FFSv2VolumesInt[] = {
EFI_FIRMWARE_FILE_SYSTEM_GUID,
EFI_FIRMWARE_FILE_SYSTEM2_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID,
EFI_APPLE_AUTHENTICATION_FV_GUID,
EFI_APPLE_IMMUTABLE_FV_GUID,
EFI_INTEL_FILE_SYSTEM_GUID,
EFI_INTEL_FILE_SYSTEM2_GUID,
EFI_SONY_FILE_SYSTEM_GUID
@ -69,6 +71,32 @@ UString guidToUString(const EFI_GUID & guid, bool convertToString)
guid.Data4[7]);
}
bool ustringToGuid(const UString & str, EFI_GUID & guid)
{
unsigned long p0;
int p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
int err = std::sscanf(str.toLocal8Bit(), "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
&p0, &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10);
if (err == 0)
return false;
guid.Data1 = p0;
guid.Data2 = p1;
guid.Data3 = p2;
guid.Data4[0] = p3;
guid.Data4[1] = p4;
guid.Data4[2] = p5;
guid.Data4[3] = p6;
guid.Data4[4] = p7;
guid.Data4[5] = p8;
guid.Data4[6] = p9;
guid.Data4[7] = p10;
return true;
}
UString fileTypeToUString(const UINT8 type)
{
switch (type)

View File

@ -23,9 +23,11 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#pragma pack(push,1)
extern UString guidToUString(const EFI_GUID& guid, bool convertToString = true);
extern bool ustringToGuid(const UString& str, EFI_GUID& guid);
extern UString fileTypeToUString(const UINT8 type);
extern UString sectionTypeToUString(const UINT8 type);
//*****************************************************************************
// EFI Capsule
//*****************************************************************************
@ -113,38 +115,43 @@ typedef struct EFI_FIRMWARE_VOLUME_HEADER_ {
} EFI_FIRMWARE_VOLUME_HEADER;
// Standard file system GUIDs
const UByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID
const UByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID // 7A9354D9-0468-444A-81CE-0BF617D890DF
("\xD9\x54\x93\x7A\x68\x04\x4A\x44\x81\xCE\x0B\xF6\x17\xD8\x90\xDF", 16);
const UByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID
const UByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID // 8C8CE578-8A3D-4F1C-9935-896185C32DD3
("\x78\xE5\x8C\x8C\x3D\x8A\x1C\x4F\x99\x35\x89\x61\x85\xC3\x2D\xD3", 16);
// Vendor-specific file system GUIDs
const UByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID
("\xAD\xEE\xAD\x04\xFF\x61\x31\x4D\xB6\xBA\x64\xF8\xBF\x90\x1F\x5A", 16);
const UByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16);
// AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0 // Intel 1
const UByteArray EFI_INTEL_FILE_SYSTEM_GUID
("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16);
// D6A1CD70-4B33-4994-A6EA-375F2CCC5437 // Intel 2
const UByteArray EFI_INTEL_FILE_SYSTEM2_GUID
("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16);
// 4F494156-AED6-4D64-A537-B8A5557BCEEC // Sony 1
const UByteArray EFI_SONY_FILE_SYSTEM_GUID
("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16);
// Vector of volume GUIDs with FFSv2-compatible files
extern const std::vector<UByteArray> FFSv2Volumes;
const UByteArray EFI_FIRMWARE_FILE_SYSTEM3_GUID // 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
("\x7A\xC0\x73\x54\xCB\x3D\xCA\x4D\xBD\x6F\x1E\x96\x89\xE7\x34\x9A", 16);
// Vendor-specific file system GUIDs
const UByteArray EFI_APPLE_IMMUTABLE_FV_GUID // 04ADEEAD-61FF-4D31-B6BA-64F8BF901F5A
("\xAD\xEE\xAD\x04\xFF\x61\x31\x4D\xB6\xBA\x64\xF8\xBF\x90\x1F\x5A", 16);
const UByteArray EFI_APPLE_AUTHENTICATION_FV_GUID // BD001B8C-6A71-487B-A14F-0C2A2DCF7A5D
("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16);
const UByteArray EFI_APPLE_MICROCODE_VOLUME_GUID // 153D2197-29BD-44DC-AC59-887F70E41A6B
("\x97\x21\x3D\x15\xBD\x29\xDC\x44\xAC\x59\x88\x7F\x70\xE4\x1A\x6B", 16);
#define EFI_APPLE_MICROCODE_VOLUME_HEADER_SIZE 0x100
const UByteArray EFI_INTEL_FILE_SYSTEM_GUID // AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0
("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16);
const UByteArray EFI_INTEL_FILE_SYSTEM2_GUID // D6A1CD70-4B33-4994-A6EA-375F2CCC5437
("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16);
const UByteArray EFI_SONY_FILE_SYSTEM_GUID // 4F494156-AED6-4D64-A537-B8A5557BCEEC
("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16);
// Vector of volume GUIDs with FFSv2-compatible files
extern const std::vector<UByteArray> FFSv2Volumes;
// Vector of volume GUIDs with FFSv3-compatible files
extern const std::vector<UByteArray> FFSv3Volumes;
// Firmware volume signature
const UByteArray EFI_FV_SIGNATURE("_FVH", 4);
#define EFI_FV_SIGNATURE 0x4856465F // _FVH
#define EFI_FV_SIGNATURE_OFFSET 0x28
// Firmware volume attributes
@ -369,6 +376,10 @@ const UByteArray AMI_CORE_DXE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
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);
// TXT ACM
const UByteArray EFI_TXT_ACM_GUID // 2D27C618-7DCD-41F5-BB10-21166BE7E143
("\x18\xC6\x27\x2D\xCD\x7D\xF5\x41\xBB\x10\x21\x16\x6B\xE7\xE1\x43", 16);
// FFS size conversion routines
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
extern UINT32 uint24ToUint32(const UINT8* ffsSize);

View File

@ -1,4 +1,4 @@
/* fssbuilder.cpp
/* fssbuilder.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
@ -16,6 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffs.h"
#include "peimage.h"
#include "utility.h"
#include "nvram.h"
#include <cstring>
USTATUS FfsBuilder::erase(const UModelIndex & index, UByteArray & erased)
{
@ -36,7 +39,7 @@ USTATUS FfsBuilder::erase(const UModelIndex & index, UByteArray & erased)
}
}
erased = QByteArray(model->header(index).size() + model->body(index).size() + model->tail(index).size(), emptyByte);
erased = UByteArray(model->header(index).size() + model->body(index).size() + model->tail(index).size(), emptyByte);
return U_SUCCESS;
}
@ -112,7 +115,7 @@ USTATUS FfsBuilder::buildCapsule(const UModelIndex & index, UByteArray & capsule
return result;
}
else
capsule.append(imageData);
capsule += imageData;
}
else {
msg(UString("buildCapsule: unexpected item type ") + itemTypeToUString(model->type(imageIndex)), imageIndex);
@ -176,7 +179,7 @@ USTATUS FfsBuilder::buildIntelImage(const UModelIndex & index, UByteArray & inte
UINT8 type = model->type(currentRegion);
if (type == Types::Padding) {
// Add padding as is
intelImage.append(model->header(currentRegion) + model->body(currentRegion) + model->tail(currentRegion));
intelImage += model->header(currentRegion) + model->body(currentRegion) + model->tail(currentRegion);
continue;
}
@ -207,7 +210,7 @@ USTATUS FfsBuilder::buildIntelImage(const UModelIndex & index, UByteArray & inte
case Subtypes::Reserved2Region:
case Subtypes::PttRegion:
// Add region as is
region = model->header(currentRegion).append(model->body(currentRegion));
region = model->header(currentRegion) + model->body(currentRegion);
break;
default:
msg(UString("buildIntelImage: unknown region type"), currentRegion);
@ -215,7 +218,7 @@ USTATUS FfsBuilder::buildIntelImage(const UModelIndex & index, UByteArray & inte
}
// Append the resulting region
intelImage.append(region);
intelImage += region;
}
// Check size of new image, it must be same as old one
@ -285,7 +288,7 @@ USTATUS FfsBuilder::buildRawArea(const UModelIndex & index, UByteArray & rawArea
return result;
}
// Append current data
rawArea.append(currentData);
rawArea += currentData;
}
// Check size of new raw area, it must be same as original one

View File

@ -28,29 +28,29 @@ USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteA
if (mode == EXTRACT_MODE_AS_IS) {
// Extract as is, with header body and tail
extracted.clear();
extracted.append(model->header(index));
extracted.append(model->body(index));
extracted.append(model->tail(index));
extracted += model->header(index);
extracted += model->body(index);
extracted += model->tail(index);
}
else if (mode == EXTRACT_MODE_BODY) {
name += QObject::tr("_body");
name += UString("_body");
// Extract without header and tail
extracted.clear();
extracted.append(model->body(index));
extracted += model->body(index);
}
else if (mode == EXTRACT_MODE_BODY_UNCOMPRESSED) {
name += QObject::tr("_body_unc");
name += UString("_body_unc");
// Extract without header and tail, uncompressed
extracted.clear();
// There is no need to redo decompression, we can use child items
for (int i = 0; i < model->rowCount(index); i++) {
UModelIndex childIndex = index.child(i, 0);
// Ensure 4-byte alignment of current section
extracted.append(UByteArray('\x00', ALIGN4((UINT32)extracted.size()) - (UINT32)extracted.size()));
extracted += UByteArray(ALIGN4((UINT32)extracted.size()) - (UINT32)extracted.size(), '\x00');
// Add current section header, body and tail
extracted.append(model->header(childIndex));
extracted.append(model->body(childIndex));
extracted.append(model->tail(childIndex));
extracted += model->header(childIndex);
extracted += model->body(childIndex);
extracted += model->tail(childIndex);
}
}
else
@ -59,7 +59,7 @@ USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteA
return U_SUCCESS;
}
USTATUS FfsOperations::replace(const UModelIndex & index, const UString & data, const UINT8 mode)
USTATUS FfsOperations::replace(const UModelIndex & index, UByteArray & data, const UINT8 mode)
{
U_UNUSED_PARAMETER(data);

View File

@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ubytearray.h"
#include "ustring.h"
#include "treemodel.h"
#include "ffsparser.h"
class FfsOperations
{
@ -32,13 +33,14 @@ public:
void clearMessages() { messagesVector.clear(); }
USTATUS extract(const UModelIndex & index, UString & name, UByteArray & extracted, const UINT8 mode);
USTATUS replace(const UModelIndex & index, const UString & data, const UINT8 mode);
USTATUS replace(const UModelIndex & index, UByteArray & data, const UINT8 mode);
USTATUS remove(const UModelIndex & index);
USTATUS rebuild(const UModelIndex & index);
private:
TreeModel * model;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {

File diff suppressed because it is too large Load Diff

View File

@ -20,9 +20,9 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ubytearray.h"
#include "treemodel.h"
#include "bootguard.h"
#include "fit.h"
typedef struct BG_PROTECTED_RANGE_
{
typedef struct BG_PROTECTED_RANGE_ {
UINT32 Offset;
UINT32 Size;
UINT8 Type;
@ -57,8 +57,8 @@ public:
// Obtain parsed FIT table
std::vector<std::pair<std::vector<UString>, UModelIndex> > getFitTable() const { return fitTable; }
// Obtain BootGuardInfo
UString getBootGuardInfo() const { return bootGuardInfo; }
// Obtain Security Info
UString getSecurityInfo() const { return securityInfo; }
// Obtain offset/address difference
UINT64 getAddressDiff() { return addressDiff; }
@ -79,7 +79,7 @@ private:
UINT64 addressDiff;
std::vector<std::pair<std::vector<UString>, UModelIndex> > fitTable;
UString bootGuardInfo;
UString securityInfo;
bool bgAcmFound;
bool bgKeyManifestFound;
bool bgBootPolicyFound;
@ -87,19 +87,20 @@ private:
UByteArray bgBpHash;
UByteArray bgBpDigest;
std::vector<BG_PROTECTED_RANGE> bgProtectedRanges;
UINT64 bgFirstVolumeOffset;
UINT64 bgProtectedRegionsBase;
UModelIndex bgDxeCoreIndex;
// First pass
USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index);
USTATUS parseCapsule(const UByteArray & capsule, UModelIndex & index);
USTATUS parseCapsule(const UByteArray & capsule, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseGenericImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseRawArea(const UModelIndex & index);
USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseVolumeBody(const UModelIndex & index);
USTATUS parseMicrocodeVolumeBody(const UModelIndex & index);
USTATUS parseFileHeader(const UByteArray & file, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFileBody(const UModelIndex & index);
USTATUS parseSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
@ -132,8 +133,7 @@ private:
USTATUS parseTeImageSectionBody(const UModelIndex & index);
USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed);
USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 globalOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
USTATUS getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize);
USTATUS findNextRawAreaItem(const UModelIndex & index, const UINT32 localOffset, UINT8 & nextItemType, UINT32 & nextItemOffset, UINT32 & nextItemSize, UINT32 & nextItemAlternativeSize);
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
@ -147,16 +147,17 @@ private:
USTATUS parseFit(const UModelIndex & index);
USTATUS parseVendorHashFile(const UByteArray & fileGuid, const UModelIndex & index);
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
#ifdef U_ENABLE_FIT_PARSING_SUPPORT
USTATUS findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset);
// FIT entries
USTATUS parseIntelMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseIntelAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseIntelBootGuardKeyManifest(const UByteArray & keyManifest, 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 parseFitEntryMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryBootGuardKeyManifest(const UByteArray & keyManifest, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS findNextBootGuardBootPolicyElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize);
#endif
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT

View File

@ -16,7 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "basetypes.h"
#include "ustring.h"
#include "ubytearray.h"
#include <sys/stat.h>
#include <fstream>
#ifdef WIN32
#include <direct.h>
@ -48,4 +50,20 @@ static inline bool changeDirectory(const UString & dir) {
}
#endif
static inline USTATUS readFileIntoBuffer(const UString & inPath, UByteArray &buf) {
if (!isExistOnFs(inPath))
return U_FILE_OPEN;
std::ifstream inputFile(inPath.toLocal8Bit(), std::ios::in | std::ios::binary);
if (!inputFile)
return U_FILE_OPEN;
std::vector<char> buffer(std::istreambuf_iterator<char>(inputFile),
(std::istreambuf_iterator<char>()));
inputFile.close();
buf = buffer;
return U_SUCCESS;
}
#endif

View File

@ -65,6 +65,14 @@ typedef struct INTEL_MICROCODE_HEADER_ {
UINT8 Reserved[12];
} INTEL_MICROCODE_HEADER;
typedef struct {
UINT16 IndexRegisterAddress;
UINT16 DataRegisterAddress;
UINT8 AccessWidth;
UINT8 BitPosition;
UINT16 Index;
} FIT_ENTRY_VERSION_0_CONFIG_POLICY;
#define INTEL_MICROCODE_HEADER_VERSION 0x00000001
#define INTEL_MICROCODE_HEADER_RESERVED_BYTE 0x00
#define INTEL_MICROCODE_HEADER_SIZES_VALID(ptr) (((INTEL_MICROCODE_HEADER*)ptr)->TotalSize - ((INTEL_MICROCODE_HEADER*)ptr)->DataSize == sizeof(INTEL_MICROCODE_HEADER))

View File

@ -12,14 +12,15 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "guiddatabase.h"
#include "ubytearray.h"
#include "ffs.h"
#if defined(U_ENABLE_GUID_DATABASE_SUPPORT)
#include <map>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdio>
struct OperatorLessForGuids : public std::binary_function<EFI_GUID, EFI_GUID, bool>
{
@ -86,27 +87,9 @@ void initGuidDatabase(const UString & path, UINT32* numEntries)
continue;
EFI_GUID guid;
unsigned long p0;
int p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
int err = std::sscanf(lineParts[0].toLocal8Bit(), "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
&p0, &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10);
if (err == 0)
if (!ustringToGuid(lineParts[0], guid))
continue;
guid.Data1 = p0;
guid.Data2 = p1;
guid.Data3 = p2;
guid.Data4[0] = p3;
guid.Data4[1] = p4;
guid.Data4[2] = p5;
guid.Data4[3] = p6;
guid.Data4[4] = p7;
guid.Data4[5] = p8;
guid.Data4[6] = p9;
guid.Data4[7] = p10;
gGuidToUStringMap.insert(GuidToUStringMap::value_type(guid, lineParts[1]));
}

View File

@ -22,12 +22,12 @@ const UByteArray ME_VERSION_SIGNATURE("\x24\x4D\x41\x4E", 4); //$MAN
const UByteArray ME_VERSION_SIGNATURE2("\x24\x4D\x4E\x32", 4); //$MN2
typedef struct ME_VERSION_ {
UINT32 signature;
UINT32 reserved;
UINT16 major;
UINT16 minor;
UINT16 bugfix;
UINT16 build;
UINT32 Signature;
UINT32 Reserved;
UINT16 Major;
UINT16 Minor;
UINT16 Bugfix;
UINT16 Build;
} ME_VERSION;
// Restore previous packing rules

View File

@ -108,6 +108,6 @@ UString flashMapGuidToUString(const EFI_GUID & guid)
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID) return UString("EVSA store");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_SELF_GUID) return UString("Flash map");
return UString();
return UString("Unknown");
}

View File

@ -156,7 +156,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
hasExtendedHeader = true;
msgUnknownExtDataFormat = true;
extendedHeaderSize = *(UINT16*)(body.constData() + body.size() - sizeof(UINT16));
extendedHeaderSize = readMisaligned((UINT16*)(body.constData() + body.size() - sizeof(UINT16)));
if (extendedHeaderSize > (UINT32)body.size()) {
msgExtHeaderTooLong = true;
isInvalid = true;
@ -203,7 +203,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
goto parsing_done;
}
timestamp = *(UINT64*)(tail.constData() + sizeof(UINT8));
timestamp = readMisaligned(tail.constData() + sizeof(UINT8));
hasTimestamp = true;
msgUnknownExtDataFormat = false;
}
@ -215,7 +215,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
goto parsing_done;
}
timestamp = *(UINT64*)(tail.constData() + sizeof(UINT8));
timestamp = readMisaligned((UINT64*)(tail.constData()) + sizeof(UINT8));
hash = tail.mid(sizeof(UINT64) + sizeof(UINT8), SHA256_HASH_SIZE);
hasTimestamp = true;
hasHash = true;
@ -272,8 +272,8 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
// Get entry GUID
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_GUID) { // GUID is strored in the variable itself
name = guidToUString(*(EFI_GUID*)(entryHeader + 1));
guid = guidToUString(*(EFI_GUID*)(entryHeader + 1), false);
name = guidToUString(readMisaligned((EFI_GUID*)(entryHeader + 1)));
guid = guidToUString(readMisaligned((EFI_GUID*)(entryHeader + 1)), false);
}
// GUID is stored in GUID list at the end of the store
else {
@ -283,8 +283,8 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
// The list begins at the end of the store and goes backwards
const EFI_GUID* guidPtr = (const EFI_GUID*)(data.constData() + data.size()) - 1 - guidIndex;
name = guidToUString(*guidPtr);
guid = guidToUString(*guidPtr, false);
name = guidToUString(readMisaligned(guidPtr));
guid = guidToUString(readMisaligned(guidPtr), false);
hasGuidIndex = true;
}
@ -365,7 +365,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry)
&& *(const UINT32*)body.constData() == NVRAM_NVAR_ENTRY_SIGNATURE)
&& body.size() >= 4 && *(const UINT32*)body.constData() == NVRAM_NVAR_ENTRY_SIGNATURE)
parseNvarStore(varIndex);
// Move to next exntry
@ -1223,55 +1223,6 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3
return U_SUCCESS;
}
USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
{
const UINT32 dataSize = (const UINT32)store.size();
// Check data size
if (dataSize < sizeof(INTEL_MICROCODE_HEADER)) {
msg(usprintf("%s: volume body is too small even for Intel microcode header", __FUNCTION__), parent);
return U_SUCCESS;
}
// Get Intel microcode header
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)store.constData();
// Check store size
if (dataSize < ucodeHeader->TotalSize) {
msg(usprintf("%s: Intel microcode size %Xh (%u) is greater than volume body size %Xh (%u)", __FUNCTION__,
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
dataSize, dataSize), parent);
return U_SUCCESS;
}
// Construct header and body
UByteArray header = store.left(sizeof(INTEL_MICROCODE_HEADER));
UByteArray body = store.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize);
//TODO: recalculate microcode checksum
// Add info
UString name("Intel microcode");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n"
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh",
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
header.size(), header.size(),
body.size(), body.size(),
ucodeHeader->DateDay,
ucodeHeader->DateMonth,
ucodeHeader->DateYear,
ucodeHeader->CpuSignature,
ucodeHeader->Revision,
ucodeHeader->Checksum,
ucodeHeader->LoaderRevision,
ucodeHeader->CpuFlags);
// Add tree item
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent);
return U_SUCCESS;
}
USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1316,7 +1267,7 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
// Intel microcode
// Must be checked after SLIC marker because of the same *signature values
else if (*signature == INTEL_MICROCODE_HEADER_VERSION)
return parseIntelMicrocodeHeader(store, localOffset, parent, index);
return ffsParser->parseIntelMicrocodeHeader(store, localOffset, parent, index);
msg(usprintf("parseStoreHeader: don't know how to parse a header with signature %08Xh", *signature), parent);
return U_SUCCESS;
@ -1545,8 +1496,8 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
name = UString("Invalid");
}
else { // Add GUID and text for valid variables
name = guidToUString(*variableGuid);
info += UString("Variable GUID: ") + guidToUString(*variableGuid, false) + UString("\n");
name = guidToUString(readMisaligned(variableGuid));
info += UString("Variable GUID: ") + guidToUString(readMisaligned(variableGuid), false) + UString("\n");
text = UString::fromUtf16(variableName);
}

View File

@ -62,7 +62,6 @@ private:
USTATUS parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseSlicPubkeyHeader(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 parseFdcStoreBody(const UModelIndex & index);
USTATUS parseVssStoreBody(const UModelIndex & index, const UINT8 alignment);

View File

@ -187,7 +187,7 @@ int sha256_done(struct sha256_state *md, unsigned char *out)
if (md->curlen >= sizeof(md->buf))
return -1;
/* increase the length of the message */
md->length += md->curlen * 8;
md->length += (uint64_t)md->curlen * 8;
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char) 0x80;
/* if the length is currently above 56 bytes we append zeros

View File

@ -74,17 +74,6 @@ UString itemTypeToUString(const UINT8 type)
UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
{
switch (type) {
case Types::Root:
case Types::FreeSpace:
case Types::VssStore:
case Types::Vss2Store:
case Types::FdcStore:
case Types::FsysStore:
case Types::EvsaStore:
case Types::FtwStore:
case Types::FlashMapStore:
case Types::CmdbStore:
case Types::SlicData: return UString();
case Types::Image:
if (subtype == Subtypes::IntelImage) return UString("Intel");
if (subtype == Subtypes::UefiImage) return UString("UEFI");
@ -99,6 +88,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
if (subtype == Subtypes::Ffs2Volume) return UString("FFSv2");
if (subtype == Subtypes::Ffs3Volume) return UString("FFSv3");
if (subtype == Subtypes::NvramVolume) return UString("NVRAM");
if (subtype == Subtypes::MicrocodeVolume) return UString("Microcode");
break;
case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed");
@ -144,7 +134,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
break;
}
return UString("Unknown");
return UString();
}
UString compressionTypeToUString(const UINT8 algorithm)

View File

@ -78,7 +78,8 @@ namespace Subtypes {
UnknownVolume = 110,
Ffs2Volume,
Ffs3Volume,
NvramVolume
NvramVolume,
MicrocodeVolume
};
enum RegionSubtypes {

View File

@ -55,4 +55,12 @@ BOOLEAN makePattern(const CHAR8 *textPattern, std::vector<UINT8> &pattern, std::
INTN findPattern(const UINT8 *pattern, const UINT8 *patternMask, UINTN patternSize,
const UINT8 *data, UINTN dataSize, UINTN dataOff);
// Safely dereferences misaligned pointers
template <typename T>
inline T readMisaligned(const T *v) {
T tmp;
memcpy(&tmp, v, sizeof(T));
return tmp;
}
#endif // UTILITY_H

View File

@ -1,6 +1,6 @@
/* types.h
/* version.h
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, 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
@ -14,6 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __VERSION_H__
#define __VERSION_H__
#define PROGRAM_VERSION "NE alpha 51"
#define PROGRAM_VERSION "NE alpha 52"
#endif