UEFITool 0.18.3

- added pattern-based search for hex patterns, '.' (dot) means "any hex
digit"
- added pattern-based search for GUIDs
- added copy action for messages
- focus is now setting properly for all search window tabs
This commit is contained in:
Nikolaj Schlej 2014-07-14 00:38:34 +02:00
parent fd578a8c70
commit 6e1f226aa0
8 changed files with 274 additions and 64 deletions

View file

@ -2961,9 +2961,9 @@ UINT8 FfsEngine::reconstructImageFile(QByteArray & reconstructed)
}
// Search routines
UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode)
UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode)
{
if (pattern.isEmpty())
if (hexPattern.isEmpty())
return ERR_INVALID_PARAMETER;
if (!index.isValid())
@ -2971,7 +2971,7 @@ UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & pa
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findHexPattern(index.child(i, index.column()), pattern, mode);
findHexPattern(index.child(i, index.column()), hexPattern, mode);
}
QByteArray data;
@ -2988,13 +2988,93 @@ UINT8 FfsEngine::findHexPattern(const QModelIndex & index, const QByteArray & pa
data.append(model->header(index)).append(model->body(index)).append(model->tail(index));
}
int offset = -1;
while ((offset = data.indexOf(pattern, offset + 1)) >= 0) {
msg(tr("Hex pattern \"%1\" found in %2 at offset %3")
.arg(QString(pattern.toHex()))
.arg(model->nameString(index))
.arg(offset, 8, 16, QChar('0')),
index);
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
QString hexBody = QString(data.toHex());
QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
msg(tr("Hex pattern \"%1\" found as \"%2\" in %3 at %4-offset %5")
.arg(QString(hexPattern))
.arg(hexBody.mid(offset, hexPattern.length()))
.arg(model->nameString(index))
.arg(mode == SEARCH_MODE_BODY ? tr("body") : tr("header"))
.arg(offset/2, 8, 16, QChar('0')),
index);
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
}
UINT8 FfsEngine::findGuidPattern(const QModelIndex & index, const QByteArray & guidPattern, const UINT8 mode)
{
if (guidPattern.isEmpty())
return ERR_INVALID_PARAMETER;
if (!index.isValid())
return ERR_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findGuidPattern(index.child(i, index.column()), guidPattern, mode);
}
QByteArray data;
if (hasChildren) {
if (mode != SEARCH_MODE_BODY)
data = model->header(index);
}
else {
if (mode == SEARCH_MODE_HEADER)
data.append(model->header(index)).append(model->tail(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());
QList<QByteArray> list = guidPattern.split('-');
if (list.count() != 5)
return ERR_INVALID_PARAMETER;
QByteArray hexPattern;
// Reverse first GUID block
hexPattern.append(list.at(0).mid(6, 2));
hexPattern.append(list.at(0).mid(4, 2));
hexPattern.append(list.at(0).mid(2, 2));
hexPattern.append(list.at(0).mid(0, 2));
// Reverse second GUID block
hexPattern.append(list.at(1).mid(2, 2));
hexPattern.append(list.at(1).mid(0, 2));
// Reverse third GUID block
hexPattern.append(list.at(2).mid(2, 2));
hexPattern.append(list.at(2).mid(0, 2));
// Append fourth and fifth GUID blocks as is
hexPattern.append(list.at(3)).append(list.at(4));
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
msg(tr("GUID pattern \"%1\" found as \"%2\" in %3 at %4-offset %5")
.arg(QString(guidPattern))
.arg(hexBody.mid(offset, hexPattern.length()))
.arg(model->nameString(index))
.arg(mode == SEARCH_MODE_BODY ? tr("body") : tr("header"))
.arg(offset / 2, 8, 16, QChar('0')),
index);
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
@ -3480,7 +3560,7 @@ UINT8 FfsEngine::patchViaOffset(QByteArray & data, const UINT32 offset, const QB
return ERR_SUCCESS;
}
UINT8 FfsEngine::patchViaPattern(QByteArray & data, const QByteArray hexFindPattern, const QByteArray & hexReplacePattern)
UINT8 FfsEngine::patchViaPattern(QByteArray & data, const QByteArray & hexFindPattern, const QByteArray & hexReplacePattern)
{
QByteArray body = data;
@ -3491,7 +3571,7 @@ UINT8 FfsEngine::patchViaPattern(QByteArray & data, const QByteArray hexFindPatt
// Convert file body to hex;
QString hexBody = QString(body.toHex());
QRegExp regexp = QRegExp(QString(hexFindPattern), Qt::CaseInsensitive);
INT64 offset = regexp.indexIn(hexBody);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
UINT8 result = patchViaOffset(body, offset/2, hexReplacePattern);

View file

@ -98,7 +98,8 @@ public:
UINT8 patch(const QModelIndex & index, const QVector<PatchData> & patches);
// Search routines
UINT8 findHexPattern(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode);
UINT8 findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode);
UINT8 findGuidPattern(const QModelIndex & index, const QByteArray & guidPattern, const UINT8 mode);
UINT8 findTextPattern(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
private:
@ -129,7 +130,7 @@ private:
// Patch helpers
UINT8 patchViaOffset(QByteArray & data, const UINT32 offset, const QByteArray & hexReplacePattern);
UINT8 patchViaPattern(QByteArray & data, const QByteArray hexFindPattern, const QByteArray & hexReplacePattern);
UINT8 patchViaPattern(QByteArray & data, const QByteArray & hexFindPattern, const QByteArray & hexReplacePattern);
#ifndef _CONSOLE
QQueue<MessageListItem> messageItems;

View file

@ -15,13 +15,34 @@
SearchDialog::SearchDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SearchDialog)
ui(new Ui::SearchDialog),
hexValidator(QRegExp("([0-9a-fA-F\\.])*")),
guidValidator(QRegExp("[0-9a-fA-F\\.]{8}-[0-9a-fA-F\\.]{4}-[0-9a-fA-F\\.]{4}-[0-9a-fA-F\\.]{4}-[0-9a-fA-F\\.]{12}"))
{
// Create UI
ui->setupUi(this);
ui->hexEdit->setValidator(&hexValidator);
ui->guidEdit->setValidator(&guidValidator);
// Connect
connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(setEditFocus(int)));
// Set initial focus
setEditFocus(ui->tabWidget->currentIndex());
}
SearchDialog::~SearchDialog()
{
delete ui;
}
void SearchDialog::setEditFocus(int index)
{
if (index == 0) // Hex pattern
ui->hexEdit->setFocus();
else if (index == 1) // GUID
ui->guidEdit->setFocus();
else if (index == 2) // Text
ui->textEdit->setFocus();
}

View file

@ -15,6 +15,7 @@
#define SEARCHDIALOG_H
#include <QDialog>
#include <QRegExpValidator>
#include "ui_searchdialog.h"
class SearchDialog : public QDialog
@ -27,8 +28,11 @@ public:
Ui::SearchDialog* ui;
private slots:
//void setEditMask();
void setEditFocus(int index);
private:
QRegExpValidator hexValidator;
QRegExpValidator guidValidator;
};
#endif

View file

@ -35,7 +35,17 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="hexEdit"/>
<widget class="QLineEdit" name="hexEdit">
<property name="font">
<font>
<family>Consolas</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="inputMask">
<string/>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="hexGroupBox">
@ -78,6 +88,78 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="guidTab">
<attribute name="title">
<string>GUID</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="guidLabel">
<property name="text">
<string>GUID:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="guidEdit">
<property name="font">
<font>
<family>Consolas</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="inputMask">
<string>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx; </string>
</property>
<property name="text">
<string>........-....-....-....-............</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="guidGroupBox">
<property name="title">
<string>Search scope</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QRadioButton" name="guidScopeFullRadioButton">
<property name="text">
<string>Header and body</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="guidScopeHeaderRadioButton">
<property name="text">
<string>Header only</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="guidScopeBodyRadioButton">
<property name="text">
<string>Body only</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="textTab">
<attribute name="title">
<string>Text</string>
@ -136,7 +218,15 @@
</layout>
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>hexEdit</tabstop>
<tabstop>hexScopeFullRadioButton</tabstop>
<tabstop>hexScopeHeaderRadioButton</tabstop>
<tabstop>hexScopeBodyRadioButton</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>textEdit</tabstop>
<tabstop>textUnicodeCheckBox</tabstop>
<tabstop>textCaseSensitiveCheckBox</tabstop>
</tabstops>
<resources/>
<connections>

View file

@ -18,6 +18,8 @@ UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool)
{
clipboard = QApplication::clipboard();
// Create UI
ui->setupUi(this);
searchDialog = new SearchDialog(this);
@ -36,6 +38,7 @@ UEFITool::UEFITool(QWidget *parent) :
connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody()));
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild()));
connect(ui->actionMessagesCopy, SIGNAL(triggered()), this, SLOT(copyMessage()));
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
@ -73,6 +76,7 @@ void UEFITool::init()
ui->menuVolumeActions->setDisabled(true);
ui->menuFileActions->setDisabled(true);
ui->menuSectionActions->setDisabled(true);
ui->actionMessagesCopy->setDisabled(true);
// Make new ffsEngine
if (ffsEngine)
@ -84,6 +88,7 @@ void UEFITool::init()
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &)));
connect(ui->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
connect(ui->messageListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyAction(QListWidgetItem*)));
}
void UEFITool::populateUi(const QModelIndex &current)
@ -119,6 +124,7 @@ void UEFITool::populateUi(const QModelIndex &current)
ui->actionInsertAfter->setEnabled(type == Types::File || type == Types::Section);
ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::File || type == Types::Section);
ui->actionReplaceBody->setEnabled(type == Types::File || type == Types::Section);
ui->actionMessagesCopy->setEnabled(false);
}
void UEFITool::search()
@ -130,7 +136,8 @@ void UEFITool::search()
int index = searchDialog->ui->tabWidget->currentIndex();
if (index == 0) { // Hex pattern
QByteArray pattern = QByteArray::fromHex(searchDialog->ui->hexEdit->text().toLatin1());
searchDialog->ui->hexEdit->setFocus();
QByteArray pattern = searchDialog->ui->hexEdit->text().toLatin1();
if (pattern.isEmpty())
return;
UINT8 mode;
@ -143,7 +150,23 @@ void UEFITool::search()
ffsEngine->findHexPattern(rootIndex, pattern, mode);
showMessages();
}
else if (index == 1) { // Text string
else if (index == 1) { // GUID
searchDialog->ui->guidEdit->setFocus();
QByteArray pattern = searchDialog->ui->guidEdit->text().toLatin1();
if (pattern.isEmpty())
return;
UINT8 mode;
if (searchDialog->ui->guidScopeHeaderRadioButton->isChecked())
mode = SEARCH_MODE_HEADER;
else if (searchDialog->ui->guidScopeBodyRadioButton->isChecked())
mode = SEARCH_MODE_BODY;
else
mode = SEARCH_MODE_ALL;
ffsEngine->findGuidPattern(rootIndex, pattern, mode);
showMessages();
}
else if (index == 2) { // Text string
searchDialog->ui->textEdit->setFocus();
QString pattern = searchDialog->ui->textEdit->text();
if (pattern.isEmpty())
return;
@ -526,11 +549,23 @@ void UEFITool::openImageFile(QString path)
ui->actionSearch->setEnabled(true);
}
void UEFITool::copyMessage()
{
clipboard->clear();
clipboard->setText(ui->messageListWidget->currentItem()->text());
}
void UEFITool::enableMessagesCopyAction(QListWidgetItem* item)
{
ui->actionMessagesCopy->setEnabled(item != NULL);
}
void UEFITool::clearMessages()
{
ffsEngine->clearMessages();
messageItems.clear();
ui->messageListWidget->clear();
ui->actionMessagesCopy->setEnabled(false);
}
void UEFITool::dragEnterEvent(QDragEnterEvent* event)

View file

@ -16,6 +16,7 @@
#include <QMainWindow>
#include <QByteArray>
#include <QClipboard>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QFile>
@ -54,7 +55,6 @@ public:
private slots:
void init();
void populateUi(const QModelIndex &current);
//void resizeTreeViewColumns();
void scrollTreeView(QListWidgetItem* item);
void openImageFile();
@ -78,8 +78,10 @@ private slots:
void remove();
void copyMessage();
void enableMessagesCopyAction(QListWidgetItem* item);
void clearMessages();
void about();
void aboutQt();
@ -90,8 +92,9 @@ private:
Ui::UEFITool* ui;
FfsEngine* ffsEngine;
SearchDialog* searchDialog;
QClipboard* clipboard;
QQueue<MessageListItem> messageItems;
void showMessages();
void dragEnterEvent(QDragEnterEvent* event);

View file

@ -20,7 +20,7 @@
<bool>true</bool>
</property>
<property name="windowTitle">
<string>UEFITool 0.18.2</string>
<string>UEFITool 0.18.3</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
@ -33,16 +33,7 @@
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>0</number>
</property>
<item>
@ -62,16 +53,7 @@
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>5</number>
</property>
<item>
@ -115,16 +97,7 @@
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>5</number>
</property>
<item>
@ -160,16 +133,7 @@
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>5</number>
</property>
<item>
@ -180,6 +144,9 @@
<pointsize>9</pointsize>
</font>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
@ -301,6 +268,7 @@
<property name="title">
<string>&amp;Messages</string>
</property>
<addaction name="actionMessagesCopy"/>
<addaction name="actionMessagesClear"/>
</widget>
<addaction name="menuCapsuleActions"/>
@ -494,7 +462,7 @@
</action>
<action name="actionMessagesClear">
<property name="text">
<string>&amp;Clear</string>
<string>Cl&amp;ear</string>
</property>
<property name="toolTip">
<string>Clear messages</string>
@ -517,6 +485,14 @@
<string>Ctrl+Shift+R</string>
</property>
</action>
<action name="actionMessagesCopy">
<property name="text">
<string>&amp;Copy</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+C</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>