UEFIFind 0.1.0

- added UEFIFind utility to find a count or a list of FFS files with a
specified pattern. The utility is developed for UBU Project.
This commit is contained in:
Nikolaj Schlej 2014-12-19 09:20:36 +01:00
parent a927c51df1
commit 4988ea8a9f
5 changed files with 328 additions and 14 deletions

146
UEFIFind/uefifind.cpp Normal file
View File

@ -0,0 +1,146 @@
/* uefifind.cpp
Copyright (c) 2014, 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)
{
ffsEngine = new FfsEngine(this);
model = ffsEngine->treeModel();
initDone = false;
}
UEFIFind::~UEFIFind()
{
model = NULL;
delete ffsEngine;
}
UINT8 UEFIFind::init(const QString & path)
{
UINT8 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 = ffsEngine->parseImageFile(buffer);
if (result)
return result;
initDone = true;
return ERR_SUCCESS;
}
UINT8 UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result)
{
QModelIndex root = model->index(0, 0);
QSet<QModelIndex> files;
result.clear();
UINT8 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;
}
QModelIndex index;
Q_FOREACH(index, files) {
QByteArray data = model->header(index).left(16);
UINT32 u32 = *(UINT32*)data.constData();
UINT16 u16_1 = *(UINT16*)(data.constData() + 4);
UINT16 u16_2 = *(UINT16*)(data.constData() + 6);
UINT8 u8_1 = *(UINT8*)(data.constData() + 8);
UINT8 u8_2 = *(UINT8*)(data.constData() + 9);
UINT8 u8_3 = *(UINT8*)(data.constData() + 10);
UINT8 u8_4 = *(UINT8*)(data.constData() + 11);
UINT8 u8_5 = *(UINT8*)(data.constData() + 12);
UINT8 u8_6 = *(UINT8*)(data.constData() + 13);
UINT8 u8_7 = *(UINT8*)(data.constData() + 14);
UINT8 u8_8 = *(UINT8*)(data.constData() + 15);
QString guid = QString("%1-%2-%3-%4%5%6%7%8%9%10%11\n").hexarg(u32, 8).hexarg(u16_1, 4).hexarg(u16_2, 4).hexarg(u8_1, 2).hexarg(u8_2, 2)
.hexarg(u8_3, 2).hexarg(u8_4, 2).hexarg(u8_5, 2).hexarg(u8_6, 2).hexarg(u8_7, 2).hexarg(u8_8, 2);
result.append(guid);
}
return ERR_SUCCESS;
}
UINT8 UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<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)).append(model->tail(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);
files.insert(ffs);
}
else
files.insert(index);
break;
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
}

49
UEFIFind/uefifind.h Normal file
View File

@ -0,0 +1,49 @@
/* uefifind.h
Copyright (c) 2014, 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 <QSet>
#include <QString>
#include <QUuid>
#include "../basetypes.h"
#include "../ffsengine.h"
class UEFIFind : public QObject
{
Q_OBJECT
public:
explicit UEFIFind(QObject *parent = 0);
~UEFIFind();
UINT8 init(const QString & path);
UINT8 find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
private:
UINT8 findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QModelIndex> & files);
FfsEngine* ffsEngine;
TreeModel* model;
QFileInfo fileInfo;
bool initDone;
};
#endif

42
UEFIFind/uefifind.pro Normal file
View File

@ -0,0 +1,42 @@
QT += core
QT -= gui
TARGET = UEFIFind
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
DEFINES += _CONSOLE _DISABLE_ENGINE_MESSAGES
SOURCES += uefifind_main.cpp \
uefifind.cpp \
../types.cpp \
../descriptor.cpp \
../ffs.cpp \
../ffsengine.cpp \
../treeitem.cpp \
../treemodel.cpp \
../LZMA/LzmaCompress.c \
../LZMA/LzmaDecompress.c \
../LZMA/SDK/C/LzFind.c \
../LZMA/SDK/C/LzmaDec.c \
../LZMA/SDK/C/LzmaEnc.c \
../Tiano/EfiTianoDecompress.c \
../Tiano/EfiTianoCompress.c \
../Tiano/EfiTianoCompressLegacy.c
HEADERS += uefifind.h \
../basetypes.h \
../descriptor.h \
../gbe.h \
../me.h \
../ffs.h \
../peimage.h \
../types.h \
../ffsengine.h \
../treeitem.h \
../treemodel.h \
../LZMA/LzmaCompress.h \
../LZMA/LzmaDecompress.h \
../Tiano/EfiTianoDecompress.h \
../Tiano/EfiTianoCompress.h

View File

@ -0,0 +1,72 @@
/* uefifind_main.cpp
Copyright (c) 2014, 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) {
result = w.init(a.arguments().at(4));
if (result)
return result;
// 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;
// Go find the supplied pattern
QString found;
result = w.find(mode, count, a.arguments().at(3), found);
if (result)
return result;
// Nothing was found
if (found.isEmpty())
return ERR_ITEM_NOT_FOUND;
// Print result
std::cout << found.toStdString();
return ERR_SUCCESS;
}
else {
std::cout << "UEFIFind 0.1.0" << std::endl << std::endl <<
"Usage: uefifind {header | body | all} {list | count} pattern imagefile\n";
return ERR_INVALID_PARAMETER;
}
}

View File

@ -194,12 +194,17 @@ TreeModel* FfsEngine::treeModel() const
void FfsEngine::msg(const QString & message, const QModelIndex & index) void FfsEngine::msg(const QString & message, const QModelIndex & index)
{ {
#ifndef _DISABLE_ENGINE_MESSAGES
#ifndef _CONSOLE #ifndef _CONSOLE
messageItems.enqueue(MessageListItem(message, NULL, 0, index)); messageItems.enqueue(MessageListItem(message, NULL, 0, index));
#else #else
(void) index; (void) index;
std::cout << message.toLatin1().constData() << std::endl; std::cout << message.toLatin1().constData() << std::endl;
#endif #endif
#else
(void)message;
(void)index;
#endif
} }
#ifndef _CONSOLE #ifndef _CONSOLE
@ -3271,10 +3276,14 @@ UINT8 FfsEngine::reconstructImageFile(QByteArray & reconstructed)
// Search routines // Search routines
UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode) UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode)
{ {
if (!index.isValid())
return ERR_SUCCESS;
if (hexPattern.isEmpty()) if (hexPattern.isEmpty())
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
if (!index.isValid()) // Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS; return ERR_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0); bool hasChildren = (model->rowCount(index) > 0);
@ -3289,17 +3298,13 @@ UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & he
} }
else { else {
if (mode == SEARCH_MODE_HEADER) if (mode == SEARCH_MODE_HEADER)
data.append(model->header(index)).append(model->tail(index)); data.append(model->header(index));
else if (mode == SEARCH_MODE_BODY) else if (mode == SEARCH_MODE_BODY)
data.append(model->body(index)); data.append(model->body(index));
else else
data.append(model->header(index)).append(model->body(index)).append(model->tail(index)); data.append(model->header(index)).append(model->body(index)).append(model->tail(index));
} }
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
QString hexBody = QString(data.toHex()); QString hexBody = QString(data.toHex());
QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive); QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody); INT32 offset = regexp.indexIn(hexBody);
@ -3339,7 +3344,7 @@ UINT8 FfsEngine::findGuidPattern(const QModelIndex & index, const QByteArray & g
} }
else { else {
if (mode == SEARCH_MODE_HEADER) if (mode == SEARCH_MODE_HEADER)
data.append(model->header(index)).append(model->tail(index)); data.append(model->header(index));
else if (mode == SEARCH_MODE_BODY) else if (mode == SEARCH_MODE_BODY)
data.append(model->body(index)); data.append(model->body(index));
else else
@ -3495,13 +3500,13 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base)
return ERR_SUCCESS; return ERR_SUCCESS;
} }
EFI_IMAGE_BASE_RELOCATION *RelocBase; EFI_IMAGE_BASE_RELOCATION *RelocBase;
EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
UINT16 *Reloc; UINT16 *Reloc;
UINT16 *RelocEnd; UINT16 *RelocEnd;
UINT16 *F16; UINT16 *F16;
UINT32 *F32; UINT32 *F32;
UINT64 *F64; UINT64 *F64;
// Run the whole relocation block // Run the whole relocation block
RelocBase = (EFI_IMAGE_BASE_RELOCATION*)(file.data() + relocOffset - teFixup); RelocBase = (EFI_IMAGE_BASE_RELOCATION*)(file.data() + relocOffset - teFixup);