UEFIFind 0.10.0

Port of UBU helper utility to new_engine branch
This commit is contained in:
Nikolaj Schlej 2015-09-13 14:15:26 +02:00
parent b8317ac4f2
commit 89c54dba8d
4 changed files with 406 additions and 0 deletions

160
UEFIFind/uefifind.cpp Normal file
View File

@ -0,0 +1,160 @@
/* uefifind.cpp
Copyright (c) 2015, Nikolaj Schlej. 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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "uefifind.h"
UEFIFind::UEFIFind(QObject *parent) :
QObject(parent)
{
model = new TreeModel();
ffsParser = new FfsParser(model, this);
initDone = false;
}
UEFIFind::~UEFIFind()
{
delete ffsParser;
delete model;
model = NULL;
}
STATUS UEFIFind::init(const QString & path)
{
STATUS result;
fileInfo = QFileInfo(path);
if (!fileInfo.exists())
return ERR_FILE_OPEN;
QFile inputFile;
inputFile.setFileName(path);
if (!inputFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
QByteArray buffer = inputFile.readAll();
inputFile.close();
result = ffsParser->parseImageFile(buffer, model->index(0,0));
if (result)
return result;
initDone = true;
return ERR_SUCCESS;
}
QString UEFIFind::guidToQString(const UINT8* guid)
{
const UINT32 u32 = *(const UINT32*)guid;
const UINT16 u16_1 = *(const UINT16*)(guid + 4);
const UINT16 u16_2 = *(const UINT16*)(guid + 6);
const UINT8 u8_1 = *(const UINT8*)(guid + 8);
const UINT8 u8_2 = *(const UINT8*)(guid + 9);
const UINT8 u8_3 = *(const UINT8*)(guid + 10);
const UINT8 u8_4 = *(const UINT8*)(guid + 11);
const UINT8 u8_5 = *(const UINT8*)(guid + 12);
const UINT8 u8_6 = *(const UINT8*)(guid + 13);
const UINT8 u8_7 = *(const UINT8*)(guid + 14);
const UINT8 u8_8 = *(const UINT8*)(guid + 15);
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11").hexarg2(u32, 8).hexarg2(u16_1, 4).hexarg2(u16_2, 4).hexarg2(u8_1, 2).hexarg2(u8_2, 2)
.hexarg2(u8_3, 2).hexarg2(u8_4, 2).hexarg2(u8_5, 2).hexarg2(u8_6, 2).hexarg2(u8_7, 2).hexarg2(u8_8, 2);
}
STATUS UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result)
{
QModelIndex root = model->index(0, 0);
QSet<QPair<QModelIndex, QModelIndex> > files;
result.clear();
STATUS returned = findFileRecursive(root, hexPattern, mode, files);
if (returned)
return returned;
if (count) {
if (files.count())
result.append(QString("%1\n").arg(files.count()));
return ERR_SUCCESS;
}
QPair<QModelIndex, QModelIndex> indexes;
Q_FOREACH(indexes, files) {
QByteArray data = model->header(indexes.first).left(16);
result.append(guidToQString((const UINT8*)data.constData()));
// Special case of freeform subtype GUID files
if (indexes.second.isValid() && model->subtype(indexes.second) == EFI_SECTION_FREEFORM_SUBTYPE_GUID) {
data = model->header(indexes.second).left(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION));
result.append(" ").append(guidToQString((const UINT8*)data.constData() + sizeof(EFI_COMMON_SECTION_HEADER)));
}
result.append("\n");
}
return ERR_SUCCESS;
}
STATUS UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files)
{
if (!index.isValid())
return ERR_SUCCESS;
if (hexPattern.isEmpty())
return ERR_INVALID_PARAMETER;
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findFileRecursive(index.child(i, index.column()), hexPattern, mode, files);
}
QByteArray data;
if (hasChildren) {
if (mode == SEARCH_MODE_HEADER || mode == SEARCH_MODE_ALL)
data.append(model->header(index));
}
else {
if (mode == SEARCH_MODE_HEADER)
data.append(model->header(index));
else if (mode == SEARCH_MODE_BODY)
data.append(model->body(index));
else
data.append(model->header(index)).append(model->body(index));
}
QString hexBody = QString(data.toHex());
QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
if (model->type(index) != Types::File) {
QModelIndex ffs = model->findParentOfType(index, Types::File);
if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID)
files.insert(QPair<QModelIndex, QModelIndex>(ffs, index));
else
files.insert(QPair<QModelIndex, QModelIndex>(ffs, QModelIndex()));
}
else
files.insert(QPair<QModelIndex, QModelIndex>(index, QModelIndex()));
break;
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
}

52
UEFIFind/uefifind.h Normal file
View File

@ -0,0 +1,52 @@
/* uefifind.h
Copyright (c) 2015, Nikolaj Schlej. 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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#ifndef __UEFIFIND_H__
#define __UEFIFIND_H__
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QDir>
#include <QFileInfo>
#include <QPair>
#include <QSet>
#include <QString>
#include <QUuid>
#include "../common/basetypes.h"
#include "../common/ffsparser.h"
#include "../common/ffs.h"
class UEFIFind : public QObject
{
Q_OBJECT
public:
explicit UEFIFind(QObject *parent = 0);
~UEFIFind();
STATUS init(const QString & path);
STATUS find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
private:
STATUS findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files);
QString guidToQString(const UINT8* guid);
FfsParser* ffsParser;
TreeModel* model;
QFileInfo fileInfo;
bool initDone;
};
#endif

37
UEFIFind/uefifind.pro Normal file
View File

@ -0,0 +1,37 @@
QT += core
QT -= gui
TARGET = UEFIFind
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
SOURCES += uefifind_main.cpp \
uefifind.cpp \
../common/types.cpp \
../common/descriptor.cpp \
../common/ffs.cpp \
../common/ffsparser.cpp \
../common/peimage.cpp \
../common/treeitem.cpp \
../common/treemodel.cpp \
../common/utility.cpp \
../common/LZMA/LzmaDecompress.c \
../common/LZMA/SDK/C/LzmaDec.c \
../common/Tiano/EfiTianoDecompress.c \
HEADERS += uefifind.h \
../common/basetypes.h \
../common/descriptor.h \
../common/gbe.h \
../common/me.h \
../common/ffs.h \
../common/ffsparser.h \
../common/peimage.h \
../common/types.h \
../common/treeitem.h \
../common/treemodel.h \
../common/utility.h \
../common/LZMA/LzmaDecompress.h \
../common/Tiano/EfiTianoDecompress.h

157
UEFIFind/uefifind_main.cpp Normal file
View File

@ -0,0 +1,157 @@
/* uefifind_main.cpp
Copyright (c) 2015, Nikolaj Schlej. 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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QCoreApplication>
#include <iostream>
#include "uefifind.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setApplicationName("UEFIFind");
UEFIFind w;
UINT8 result;
if (a.arguments().length() == 5) {
// Get search mode
UINT8 mode;
if (a.arguments().at(1) == QString("header"))
mode = SEARCH_MODE_HEADER;
else if (a.arguments().at(1) == QString("body"))
mode = SEARCH_MODE_BODY;
else if (a.arguments().at(1) == QString("all"))
mode = SEARCH_MODE_ALL;
else
return ERR_INVALID_PARAMETER;
// Get result type
bool count;
if (a.arguments().at(2) == QString("list"))
count = false;
else if (a.arguments().at(2) == QString("count"))
count = true;
else
return ERR_INVALID_PARAMETER;
// Parse input file
result = w.init(a.arguments().at(4));
if (result)
return result;
// Go find the supplied pattern
QString found;
result = w.find(mode, count, a.arguments().at(3), found);
if (result)
return result;
// Nothing is found
if (found.isEmpty())
return ERR_ITEM_NOT_FOUND;
// Print result
std::cout << found.toStdString();
return ERR_SUCCESS;
}
else if (a.arguments().length() == 4) {
// Get search mode
if (a.arguments().at(1) != QString("file"))
return ERR_INVALID_PARAMETER;
// Open patterns file
QFileInfo fileInfo(a.arguments().at(2));
if (!fileInfo.exists())
return ERR_FILE_OPEN;
QFile patternsFile;
patternsFile.setFileName(a.arguments().at(2));
if (!patternsFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
// Parse input file
result = w.init(a.arguments().at(3));
if (result)
return result;
// Perform searches
bool somethingFound = false;
while (!patternsFile.atEnd()) {
QByteArray line = patternsFile.readLine();
// Use sharp symbol as commentary
if (line.count() == 0 || line[0] == '#')
continue;
// Split the read line
QList<QByteArray> list = line.split(' ');
if (list.count() < 3) {
std::cout << line.toStdString() << "skipped, too few arguments" << std::endl;
continue;
}
// Get search mode
UINT8 mode;
if (list.at(0) == QString("header"))
mode = SEARCH_MODE_HEADER;
else if (list.at(0) == QString("body"))
mode = SEARCH_MODE_BODY;
else if (list.at(0) == QString("all"))
mode = SEARCH_MODE_ALL;
else {
std::cout << line.toStdString() << "skipped, invalid search mode" << std::endl;
continue;
}
// Get result type
bool count;
if (list.at(1) == QString("list"))
count = false;
else if (list.at(1) == QString("count"))
count = true;
else {
std::cout << line.toStdString() << "skipped, invalid result type" << std::endl;
continue;
}
// Go find the supplied pattern
QString found;
result = w.find(mode, count, list.at(2), found);
if (result) {
std::cout << line.toStdString() << "skipped, find failed with error " << result << std::endl;
continue;
}
if (found.isEmpty()) {
// Nothing is found
std::cout << line.toStdString() << "nothing found" << std::endl;
}
else {
// Print result
std::cout << line.toStdString() << found.toStdString() << std::endl;
somethingFound = true;
}
}
// Nothing is found
if (!somethingFound)
return ERR_ITEM_NOT_FOUND;
return ERR_SUCCESS;
}
else {
std::cout << "UEFIFind 0.10.0" << std::endl << std::endl <<
"Usage: uefifind {header | body | all} {list | count} pattern imagefile" << std::endl <<
" or uefitool file patternsfile imagefile" << std::endl;
return ERR_INVALID_PARAMETER;
}
}