mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-25 01:18:22 +08:00
NE_alpha7
- ported cumulative changes from 0.20.8 - added "Extract body uncompressed" action for compressed and GUID-defined sections
This commit is contained in:
parent
41f46631a7
commit
8283ee9f29
@ -94,6 +94,17 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
|
|||||||
extracted.clear();
|
extracted.clear();
|
||||||
extracted.append(model->body(index));
|
extracted.append(model->body(index));
|
||||||
}
|
}
|
||||||
|
else if (mode == EXTRACT_MODE_BODY_UNCOMPRESSED) {
|
||||||
|
name += tr("_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++) {
|
||||||
|
QModelIndex childIndex = index.child(i, 0);
|
||||||
|
extracted.append(model->header(childIndex));
|
||||||
|
extracted.append(model->body(childIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return ERR_UNKNOWN_EXTRACT_MODE;
|
return ERR_UNKNOWN_EXTRACT_MODE;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
UEFITool::UEFITool(QWidget *parent) :
|
UEFITool::UEFITool(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui(new Ui::UEFITool),
|
ui(new Ui::UEFITool),
|
||||||
version(tr("0.30.0_alpha6"))
|
version(tr("0.30.0_alpha7"))
|
||||||
{
|
{
|
||||||
clipboard = QApplication::clipboard();
|
clipboard = QApplication::clipboard();
|
||||||
|
|
||||||
@ -35,10 +35,12 @@ version(tr("0.30.0_alpha6"))
|
|||||||
|
|
||||||
// Connect signals to slots
|
// Connect signals to slots
|
||||||
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
|
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
|
||||||
|
connect(ui->actionOpenImageFileInNewWindow, SIGNAL(triggered()), this, SLOT(openImageFileInNewWindow()));
|
||||||
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
|
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
|
||||||
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
|
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
|
||||||
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
|
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
|
||||||
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
|
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
|
||||||
|
connect(ui->actionExtractBodyUncompressed, SIGNAL(triggered()), this, SLOT(extractBodyUncompressed()));
|
||||||
connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
|
connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
|
||||||
connect(ui->actionInsertBefore, SIGNAL(triggered()), this, SLOT(insertBefore()));
|
connect(ui->actionInsertBefore, SIGNAL(triggered()), this, SLOT(insertBefore()));
|
||||||
connect(ui->actionInsertAfter, SIGNAL(triggered()), this, SLOT(insertAfter()));
|
connect(ui->actionInsertAfter, SIGNAL(triggered()), this, SLOT(insertAfter()));
|
||||||
@ -93,6 +95,11 @@ UEFITool::~UEFITool()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UEFITool::setProgramPath(QString path)
|
||||||
|
{
|
||||||
|
currentProgramPath = path;
|
||||||
|
};
|
||||||
|
|
||||||
void UEFITool::init()
|
void UEFITool::init()
|
||||||
{
|
{
|
||||||
// Clear components
|
// Clear components
|
||||||
@ -162,6 +169,7 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
|
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
|
||||||
//ui->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
|
//ui->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
|
||||||
ui->actionExtractBody->setDisabled(model->hasEmptyBody(current));
|
ui->actionExtractBody->setDisabled(model->hasEmptyBody(current));
|
||||||
|
ui->actionExtractBodyUncompressed->setEnabled(enableExtractBodyUncompressed(current));
|
||||||
//ui->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
|
//ui->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
|
||||||
//ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) ||
|
//ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) ||
|
||||||
// (type == Types::File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD) ||
|
// (type == Types::File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD) ||
|
||||||
@ -173,6 +181,30 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
ui->actionMessagesCopy->setEnabled(false);
|
ui->actionMessagesCopy->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UEFITool::enableExtractBodyUncompressed(const QModelIndex ¤t)
|
||||||
|
{
|
||||||
|
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 = parsingDataFromQModelIndex(current);
|
||||||
|
|
||||||
|
if (model->subtype(current) == EFI_SECTION_COMPRESSION &&
|
||||||
|
pdata.section.compressed.algorithm != COMPRESSION_ALGORITHM_NONE &&
|
||||||
|
pdata.section.compressed.algorithm != COMPRESSION_ALGORITHM_UNKNOWN) { //Compressed section
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (model->subtype(current) == EFI_SECTION_GUID_DEFINED &&
|
||||||
|
(pdata.section.guidDefined.attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
void UEFITool::search()
|
void UEFITool::search()
|
||||||
{
|
{
|
||||||
if (searchDialog->exec() != QDialog::Accepted)
|
if (searchDialog->exec() != QDialog::Accepted)
|
||||||
@ -378,6 +410,8 @@ void UEFITool::replace(const UINT8 mode)
|
|||||||
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
|
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
|
||||||
else if (model->subtype(index) == EFI_SECTION_RAW)
|
else if (model->subtype(index) == EFI_SECTION_RAW)
|
||||||
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
|
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"), 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 body"), currentDir, "EFI executable files (*.efi *.dxe *.pei *.bin);;All files (*)");
|
||||||
else
|
else
|
||||||
path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)");
|
path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)");
|
||||||
}
|
}
|
||||||
@ -425,6 +459,11 @@ void UEFITool::extractBody()
|
|||||||
extract(EXTRACT_MODE_BODY);
|
extract(EXTRACT_MODE_BODY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UEFITool::extractBodyUncompressed()
|
||||||
|
{
|
||||||
|
extract(EXTRACT_MODE_BODY_UNCOMPRESSED);
|
||||||
|
}
|
||||||
|
|
||||||
void UEFITool::extract(const UINT8 mode)
|
void UEFITool::extract(const UINT8 mode)
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
@ -439,7 +478,7 @@ void UEFITool::extract(const UINT8 mode)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = currentDir + QDir::separator() + name;
|
name = QDir::toNativeSeparators(currentDir + QDir::separator() + name);
|
||||||
|
|
||||||
UINT8 type = model->type(index);
|
UINT8 type = model->type(index);
|
||||||
QString path;
|
QString path;
|
||||||
@ -470,7 +509,7 @@ void UEFITool::extract(const UINT8 mode)
|
|||||||
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == EXTRACT_MODE_BODY) {
|
else if (mode == EXTRACT_MODE_BODY || mode == EXTRACT_MODE_BODY_UNCOMPRESSED) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Types::Capsule:
|
case Types::Capsule:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"), name + ".rom", "Image files (*.rom *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"), name + ".rom", "Image files (*.rom *.bin);;All files (*)");
|
||||||
@ -492,6 +531,8 @@ void UEFITool::extract(const UINT8 mode)
|
|||||||
path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"), name + ".vol", "Volume files (*.vol *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"), name + ".vol", "Volume files (*.vol *.bin);;All files (*)");
|
||||||
else if (model->subtype(index) == EFI_SECTION_RAW)
|
else if (model->subtype(index) == EFI_SECTION_RAW)
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"), name + ".raw", "Raw files (*.raw *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"), name + ".raw", "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::getSaveFileName(this, tr("Save section body to EFI executable file"), name + ".efi", "EFI executable files (*.efi *.dxe *.pei *.bin);;All files (*)");
|
||||||
else
|
else
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save section body to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save section body to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
||||||
}
|
}
|
||||||
@ -573,10 +614,18 @@ void UEFITool::saveImageFile()
|
|||||||
|
|
||||||
void UEFITool::openImageFile()
|
void UEFITool::openImageFile()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi *.dec);;All files (*)");
|
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
|
||||||
openImageFile(path);
|
openImageFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UEFITool::openImageFileInNewWindow()
|
||||||
|
{
|
||||||
|
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file in new window"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
|
||||||
|
if (path.trimmed().isEmpty())
|
||||||
|
return;
|
||||||
|
QProcess::startDetached(currentProgramPath, QStringList(path));
|
||||||
|
}
|
||||||
|
|
||||||
void UEFITool::openImageFile(QString path)
|
void UEFITool::openImageFile(QString path)
|
||||||
{
|
{
|
||||||
if (path.trimmed().isEmpty())
|
if (path.trimmed().isEmpty())
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
#include <QProcess>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -56,6 +57,7 @@ public:
|
|||||||
~UEFITool();
|
~UEFITool();
|
||||||
|
|
||||||
void openImageFile(QString path);
|
void openImageFile(QString path);
|
||||||
|
void setProgramPath(QString path);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void init();
|
void init();
|
||||||
@ -63,12 +65,14 @@ private slots:
|
|||||||
void scrollTreeView(QListWidgetItem* item);
|
void scrollTreeView(QListWidgetItem* item);
|
||||||
|
|
||||||
void openImageFile();
|
void openImageFile();
|
||||||
|
void openImageFileInNewWindow();
|
||||||
void saveImageFile();
|
void saveImageFile();
|
||||||
void search();
|
void search();
|
||||||
|
|
||||||
void extract(const UINT8 mode);
|
void extract(const UINT8 mode);
|
||||||
void extractAsIs();
|
void extractAsIs();
|
||||||
void extractBody();
|
void extractBody();
|
||||||
|
void extractBodyUncompressed();
|
||||||
|
|
||||||
void insert(const UINT8 mode);
|
void insert(const UINT8 mode);
|
||||||
void insertInto();
|
void insertInto();
|
||||||
@ -104,8 +108,11 @@ private:
|
|||||||
SearchDialog* searchDialog;
|
SearchDialog* searchDialog;
|
||||||
QClipboard* clipboard;
|
QClipboard* clipboard;
|
||||||
QString currentDir;
|
QString currentDir;
|
||||||
|
QString currentProgramPath;
|
||||||
const QString version;
|
const QString version;
|
||||||
|
|
||||||
|
bool enableExtractBodyUncompressed(const QModelIndex ¤t);
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent* event);
|
void dragEnterEvent(QDragEnterEvent* event);
|
||||||
void dropEvent(QDropEvent* event);
|
void dropEvent(QDropEvent* event);
|
||||||
void contextMenuEvent(QContextMenuEvent* event);
|
void contextMenuEvent(QContextMenuEvent* event);
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
<string>&File</string>
|
<string>&File</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionOpenImageFile"/>
|
<addaction name="actionOpenImageFile"/>
|
||||||
|
<addaction name="actionOpenImageFileInNewWindow"/>
|
||||||
<addaction name="actionSaveImageFile"/>
|
<addaction name="actionSaveImageFile"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionSearch"/>
|
<addaction name="actionSearch"/>
|
||||||
@ -329,6 +330,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<addaction name="actionExtract"/>
|
<addaction name="actionExtract"/>
|
||||||
<addaction name="actionExtractBody"/>
|
<addaction name="actionExtractBody"/>
|
||||||
|
<addaction name="actionExtractBodyUncompressed"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionRebuild"/>
|
<addaction name="actionRebuild"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@ -581,6 +583,28 @@
|
|||||||
<string>Ctrl+Alt+C</string>
|
<string>Ctrl+Alt+C</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionOpenImageFileInNewWindow">
|
||||||
|
<property name="text">
|
||||||
|
<string>O&pen image file in new window...</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+Shift+O</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionExtractBodyUncompressed">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Extract &body uncompressed...</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Uncompress and extract body of selected object to file</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+Alt+E</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -23,6 +23,7 @@ int main(int argc, char *argv[])
|
|||||||
a.setApplicationName("UEFITool");
|
a.setApplicationName("UEFITool");
|
||||||
|
|
||||||
UEFITool w;
|
UEFITool w;
|
||||||
|
w.setProgramPath(a.arguments().at(0));
|
||||||
if (a.arguments().length() > 1)
|
if (a.arguments().length() > 1)
|
||||||
w.openImageFile(a.arguments().at(1));
|
w.openImageFile(a.arguments().at(1));
|
||||||
w.show();
|
w.show();
|
||||||
|
@ -77,6 +77,7 @@ typedef UINT8 STATUS;
|
|||||||
#define ERR_UNKNOWN_RELOCATION_TYPE 31
|
#define ERR_UNKNOWN_RELOCATION_TYPE 31
|
||||||
#define ERR_DIR_ALREADY_EXIST 32
|
#define ERR_DIR_ALREADY_EXIST 32
|
||||||
#define ERR_DIR_CREATE 33
|
#define ERR_DIR_CREATE 33
|
||||||
|
#define ERR_TRUNCATED_IMAGE 34
|
||||||
#define ERR_NOT_IMPLEMENTED 0xFF
|
#define ERR_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
// UDK porting definitions
|
// UDK porting definitions
|
||||||
@ -107,6 +108,7 @@ typedef UINT8 STATUS;
|
|||||||
// Item extract modes
|
// Item extract modes
|
||||||
#define EXTRACT_MODE_AS_IS 0
|
#define EXTRACT_MODE_AS_IS 0
|
||||||
#define EXTRACT_MODE_BODY 1
|
#define EXTRACT_MODE_BODY 1
|
||||||
|
#define EXTRACT_MODE_BODY_UNCOMPRESSED 2
|
||||||
|
|
||||||
// Item replace modes
|
// Item replace modes
|
||||||
#define REPLACE_MODE_AS_IS 0
|
#define REPLACE_MODE_AS_IS 0
|
||||||
|
20
common/ffs.h
20
common/ffs.h
@ -49,6 +49,26 @@ typedef struct _EFI_CAPSULE_HEADER {
|
|||||||
const QByteArray EFI_CAPSULE_GUID
|
const QByteArray EFI_CAPSULE_GUID
|
||||||
("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16);
|
("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16);
|
||||||
|
|
||||||
|
// Intel capsule GUID
|
||||||
|
const QByteArray INTEL_CAPSULE_GUID
|
||||||
|
("\xB9\x82\x91\x53\xB5\xAB\x91\x43\xB6\x9A\xE3\xA9\x43\xF7\x2F\xCC", 16);
|
||||||
|
|
||||||
|
// Lenovo capsule GUID
|
||||||
|
const QByteArray LENOVO_CAPSULE_GUID
|
||||||
|
("\x8B\xA6\x3C\x4A\x23\x77\xFB\x48\x80\x3D\x57\x8C\xC1\xFE\xC4\x4D", 16);
|
||||||
|
|
||||||
|
// Toshiba EFI Capsule header
|
||||||
|
typedef struct _TOSHIBA_CAPSULE_HEADER {
|
||||||
|
EFI_GUID CapsuleGuid;
|
||||||
|
UINT32 HeaderSize;
|
||||||
|
UINT32 FullSize;
|
||||||
|
UINT32 Flags;
|
||||||
|
} TOSHIBA_CAPSULE_HEADER;
|
||||||
|
|
||||||
|
// Toshiba capsule GUID
|
||||||
|
const QByteArray TOSHIBA_CAPSULE_GUID
|
||||||
|
("\x62\x70\xE0\x3B\x51\x1D\xD2\x45\x83\x2B\xF0\x93\x25\x7E\xD4\x61", 16);
|
||||||
|
|
||||||
// AMI Aptio extended capsule header
|
// AMI Aptio extended capsule header
|
||||||
typedef struct _APTIO_CAPSULE_HEADER {
|
typedef struct _APTIO_CAPSULE_HEADER {
|
||||||
EFI_CAPSULE_HEADER CapsuleHeader;
|
EFI_CAPSULE_HEADER CapsuleHeader;
|
||||||
|
@ -70,7 +70,9 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
// Check buffer for being normal EFI capsule header
|
// Check buffer for being normal EFI capsule header
|
||||||
UINT32 capsuleHeaderSize = 0;
|
UINT32 capsuleHeaderSize = 0;
|
||||||
QModelIndex index;
|
QModelIndex index;
|
||||||
if (buffer.startsWith(EFI_CAPSULE_GUID)) {
|
if (buffer.startsWith(EFI_CAPSULE_GUID)
|
||||||
|
|| buffer.startsWith(INTEL_CAPSULE_GUID)
|
||||||
|
|| buffer.startsWith(LENOVO_CAPSULE_GUID)) {
|
||||||
// Get info
|
// Get info
|
||||||
const EFI_CAPSULE_HEADER* capsuleHeader = (const EFI_CAPSULE_HEADER*)buffer.constData();
|
const EFI_CAPSULE_HEADER* capsuleHeader = (const EFI_CAPSULE_HEADER*)buffer.constData();
|
||||||
capsuleHeaderSize = capsuleHeader->HeaderSize;
|
capsuleHeaderSize = capsuleHeader->HeaderSize;
|
||||||
@ -91,6 +93,28 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root);
|
index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root);
|
||||||
}
|
}
|
||||||
|
// Check buffer for being Toshiba capsule header
|
||||||
|
else if (buffer.startsWith(TOSHIBA_CAPSULE_GUID)) {
|
||||||
|
// Get info
|
||||||
|
const TOSHIBA_CAPSULE_HEADER* capsuleHeader = (const TOSHIBA_CAPSULE_HEADER*)buffer.constData();
|
||||||
|
capsuleHeaderSize = capsuleHeader->HeaderSize;
|
||||||
|
QByteArray header = buffer.left(capsuleHeaderSize);
|
||||||
|
QByteArray body = buffer.right(buffer.size() - capsuleHeaderSize);
|
||||||
|
QString name = tr("UEFI capsule");
|
||||||
|
QString info = tr("Offset: 0h\nCapsule GUID: %1\nFull size: %2h (%3)\nHeader size: %4h (%5)\nImage size: %6h (%7)\nFlags: %8h")
|
||||||
|
.arg(guidToQString(capsuleHeader->CapsuleGuid))
|
||||||
|
.hexarg(buffer.size()).arg(buffer.size())
|
||||||
|
.hexarg(capsuleHeader->HeaderSize).arg(capsuleHeader->HeaderSize)
|
||||||
|
.hexarg(capsuleHeader->FullSize - capsuleHeader->HeaderSize).arg(capsuleHeader->FullSize - capsuleHeader->HeaderSize)
|
||||||
|
.hexarg2(capsuleHeader->Flags, 8);
|
||||||
|
|
||||||
|
// Construct parsing data
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(QModelIndex());
|
||||||
|
pdata.fixed = TRUE;
|
||||||
|
|
||||||
|
// Add tree item
|
||||||
|
index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root);
|
||||||
|
}
|
||||||
// Check buffer for being extended Aptio signed capsule header
|
// Check buffer for being extended Aptio signed capsule header
|
||||||
else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) {
|
else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) {
|
||||||
bool signedCapsule = buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID);
|
bool signedCapsule = buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID);
|
||||||
@ -411,6 +435,44 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const UINT32 pa
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the data after the last region as padding
|
||||||
|
UINT32 IntelDataEnd = 0;
|
||||||
|
UINT32 LastRegionOffset = offsets.last();
|
||||||
|
if (LastRegionOffset == gbeBegin)
|
||||||
|
IntelDataEnd = gbeEnd;
|
||||||
|
else if (LastRegionOffset == meBegin)
|
||||||
|
IntelDataEnd = meEnd;
|
||||||
|
else if (LastRegionOffset == biosBegin)
|
||||||
|
IntelDataEnd = biosEnd;
|
||||||
|
else if (LastRegionOffset == pdrBegin)
|
||||||
|
IntelDataEnd = pdrEnd;
|
||||||
|
|
||||||
|
if (IntelDataEnd > (UINT32)intelImage.size()) { // Image file is truncated
|
||||||
|
msg(tr("parseIntelImage: image size %1 (%2) is smaller than the end of last region %3 (%4), may be damaged")
|
||||||
|
.hexarg(intelImage.size()).arg(intelImage.size())
|
||||||
|
.hexarg(IntelDataEnd).arg(IntelDataEnd), index);
|
||||||
|
return ERR_TRUNCATED_IMAGE;
|
||||||
|
}
|
||||||
|
else if (IntelDataEnd < (UINT32)intelImage.size()) { // Insert padding
|
||||||
|
QByteArray padding = bios.right(intelImage.size() - IntelDataEnd);
|
||||||
|
|
||||||
|
// Get parent's parsing data
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
|
// Get info
|
||||||
|
name = tr("Padding");
|
||||||
|
info = tr("Full size: %1h (%2)")
|
||||||
|
.hexarg(padding.size()).arg(padding.size());
|
||||||
|
|
||||||
|
// Construct parsing data
|
||||||
|
pdata.fixed = TRUE;
|
||||||
|
pdata.offset = IntelDataEnd;
|
||||||
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
|
// Add tree item
|
||||||
|
QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the last VTF is found
|
// Check if the last VTF is found
|
||||||
if (!lastVtf.isValid()) {
|
if (!lastVtf.isValid()) {
|
||||||
msg(tr("parseIntelImage: not a single Volume Top File is found, the image may be corrupted"), index);
|
msg(tr("parseIntelImage: not a single Volume Top File is found, the image may be corrupted"), index);
|
||||||
@ -831,16 +893,23 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
// Determine value of empty byte
|
// Determine value of empty byte
|
||||||
UINT8 emptyByte = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
UINT8 emptyByte = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||||
|
|
||||||
// Check for Apple CRC32 in ZeroVector
|
// Check for AppleCRC32 and AppleFreeSpaceOffset in ZeroVector
|
||||||
bool hasAppleCrc32 = false;
|
bool hasAppleCrc32 = false;
|
||||||
|
bool hasAppleFSO = false;
|
||||||
UINT32 volumeSize = volume.size();
|
UINT32 volumeSize = volume.size();
|
||||||
UINT32 appleCrc32 = *(UINT32*)(volume.constData() + 8);
|
UINT32 appleCrc32 = *(UINT32*)(volume.constData() + 8);
|
||||||
|
UINT32 appleFSO = *(UINT32*)(volume.constData() + 12);
|
||||||
if (appleCrc32 != 0) {
|
if (appleCrc32 != 0) {
|
||||||
// Calculate CRC32 of the volume body
|
// Calculate CRC32 of the volume body
|
||||||
UINT32 crc = crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
|
UINT32 crc = crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
|
||||||
if (crc == appleCrc32) {
|
if (crc == appleCrc32) {
|
||||||
hasAppleCrc32 = true;
|
hasAppleCrc32 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if FreeSpaceOffset is non-zero
|
||||||
|
if (appleFSO != 0) {
|
||||||
|
hasAppleFSO = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check header checksum by recalculating it
|
// Check header checksum by recalculating it
|
||||||
@ -884,6 +953,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
pdata.volume.alignment = alignment;
|
pdata.volume.alignment = alignment;
|
||||||
pdata.volume.revision = volumeHeader->Revision;
|
pdata.volume.revision = volumeHeader->Revision;
|
||||||
pdata.volume.hasAppleCrc32 = hasAppleCrc32;
|
pdata.volume.hasAppleCrc32 = hasAppleCrc32;
|
||||||
|
pdata.volume.hasAppleFSO = hasAppleFSO;
|
||||||
pdata.volume.isWeakAligned = (volumeHeader->Revision > 1 && (volumeHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT));
|
pdata.volume.isWeakAligned = (volumeHeader->Revision > 1 && (volumeHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT));
|
||||||
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
@ -891,6 +961,8 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
QString text;
|
QString text;
|
||||||
if (hasAppleCrc32)
|
if (hasAppleCrc32)
|
||||||
text += tr("AppleCRC32 ");
|
text += tr("AppleCRC32 ");
|
||||||
|
if (hasAppleFSO)
|
||||||
|
text += tr("AppleFSO ");
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
UINT8 subtype = Subtypes::UnknownVolume;
|
UINT8 subtype = Subtypes::UnknownVolume;
|
||||||
|
@ -97,7 +97,9 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
|||||||
else if (subtype == Subtypes::AptioUnsignedCapsule)
|
else if (subtype == Subtypes::AptioUnsignedCapsule)
|
||||||
return QObject::tr("Aptio unsigned");
|
return QObject::tr("Aptio unsigned");
|
||||||
else if (subtype == Subtypes::UefiCapsule)
|
else if (subtype == Subtypes::UefiCapsule)
|
||||||
return QObject::tr("UEFI 2.0 ");
|
return QObject::tr("UEFI 2.0");
|
||||||
|
else if (subtype == Subtypes::ToshibaCapsule)
|
||||||
|
return QObject::tr("Toshiba");
|
||||||
else
|
else
|
||||||
return QObject::tr("Unknown subtype");
|
return QObject::tr("Unknown subtype");
|
||||||
case Types::Region:
|
case Types::Region:
|
||||||
|
@ -56,7 +56,8 @@ namespace Subtypes {
|
|||||||
enum CapsuleSubtypes {
|
enum CapsuleSubtypes {
|
||||||
AptioSignedCapsule = 80,
|
AptioSignedCapsule = 80,
|
||||||
AptioUnsignedCapsule,
|
AptioUnsignedCapsule,
|
||||||
UefiCapsule
|
UefiCapsule,
|
||||||
|
ToshibaCapsule
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VolumeSubtypes {
|
enum VolumeSubtypes {
|
||||||
|
@ -92,6 +92,7 @@ QString errorCodeToQString(UINT8 errorCode)
|
|||||||
//case ERR_INVALID_SYMBOL: return QObject::tr("Invalid symbol");
|
//case ERR_INVALID_SYMBOL: return QObject::tr("Invalid symbol");
|
||||||
//case ERR_NOTHING_TO_PATCH: return QObject::tr("Nothing to patch");
|
//case ERR_NOTHING_TO_PATCH: return QObject::tr("Nothing to patch");
|
||||||
case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed");
|
case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed");
|
||||||
|
case ERR_TRUNCATED_IMAGE: return QObject::tr("Image is truncated");
|
||||||
default: return QObject::tr("Unknown error %1").arg(errorCode);
|
default: return QObject::tr("Unknown error %1").arg(errorCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user