Engine 0.20.1

-reverted some changes done in 0.20.0 update
-added proper handling of non-standard data in volume's free space
- new type "Free space" added
- added machine type information
- solved a typo in DOS/PE signature check
This commit is contained in:
Nikolaj Schlej 2015-02-06 09:47:19 +01:00
parent 64a7c2ce2c
commit 2ec7ce1c30
14 changed files with 554 additions and 398 deletions

10
.gitignore vendored
View File

@ -224,3 +224,13 @@ pip-log.txt
#Mr Developer
.mr.developer.cfg
#############
## qmake / make
#############
*.o
Makefile
UEFIExtract/UEFIExtract
UEFIFind/UEFIFind
UEFIPatch/UEFIPatch
UEFITool

View File

@ -38,7 +38,7 @@ Usage
Known issues
------------
* Some images has non-standard calculation of base address of TE images, so the program can rebase them incorrectly after modifications. Will be solved ASAP.
* Some images may not work after modification because of no FIT table support implemented yet. It's on my high priority features list, so I hope it will be corrected soon.
* The program is meant to work with BIOS images, not some vendor-specific BIOS update files, that is why some of that update file either can\t be opened at all or return errors on reconstruction. If someone wants to write an unpacker for such crappy files - I will be glad to use it.
* Search is searching only inside leaf elements of the tree, that is why some information can be found with hex editor but not with UEFITool. It's an intended behaviour and the tool tries to warn if there are some data in unusual places that must be empty by specifications (like the data inside padding files or after the last file of the UEFI volume).
* AMI-specific features like NCBs, ROM_AREA structure and other things like that can't be implemented by me because of the NDA I have.

View File

@ -128,7 +128,7 @@ QString sectionTypeToQString(const UINT8 type)
case EFI_SECTION_COMPRESSION: return QObject::tr("Compressed");
case EFI_SECTION_GUID_DEFINED: return QObject::tr("GUID defined");
case EFI_SECTION_DISPOSABLE: return QObject::tr("Disposable");
case EFI_SECTION_PE32: return QObject::tr("PE32(+) image");
case EFI_SECTION_PE32: return QObject::tr("PE32 image");
case EFI_SECTION_PIC: return QObject::tr("PIC image");
case EFI_SECTION_TE: return QObject::tr("TE image");
case EFI_SECTION_DXE_DEPEX: return QObject::tr("DXE dependency");

File diff suppressed because it is too large Load Diff

30
peimage.cpp Normal file
View File

@ -0,0 +1,30 @@
/* peimage.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 <QObject>
#include "peimage.h"
QString machineTypeToQString(UINT16 machineType)
{
switch (machineType){
case IMAGE_FILE_MACHINE_AMD64: return QObject::tr("x86-64");
case IMAGE_FILE_MACHINE_ARM: return QObject::tr("ARM");
case IMAGE_FILE_MACHINE_ARMV7: return QObject::tr("ARMv7");
case IMAGE_FILE_MACHINE_EBC: return QObject::tr("EBC");
case IMAGE_FILE_MACHINE_I386: return QObject::tr("x86");
case IMAGE_FILE_MACHINE_IA64: return QObject::tr("IA64");
case IMAGE_FILE_MACHINE_THUMB: return QObject::tr("Thumb");
default: return QObject::tr("Unknown %1").hexarg2(machineType, 4);
}
}

View File

@ -16,9 +16,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __PE_IMAGE_H__
#define __PE_IMAGE_H__
#include <QString>
#include "basetypes.h"
// Make sure we use right packing rules
#pragma pack(push,1)
extern QString machineTypeToQString(UINT16 machineType);
//
// PE32+ Subsystem type for EFI images
//
@ -30,11 +36,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// PE32+ Machine type for EFI images
//
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_IA64 0x0200
#define IMAGE_FILE_MACHINE_EBC 0x0EBC
#define IMAGE_FILE_MACHINE_X64 0x8664
#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_ARM 0x01c0
#define IMAGE_FILE_MACHINE_ARMV7 0x01c4
#define IMAGE_FILE_MACHINE_EBC 0x0ebc
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_IA64 0x0200
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
//
// EXE file formats

View File

@ -15,19 +15,20 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "treeitem.h"
#include "types.h"
TreeItem::TreeItem(const UINT8 type, const UINT32 attributes, const UINT8 compression,
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body,
const QByteArray & header, const QByteArray & body, const QByteArray & parsingData,
TreeItem *parent) :
itemAction(Actions::NoAction),
itemType(type),
itemAttributes(attributes),
itemSubtype(subtype),
itemCompression(compression),
itemName(name),
itemText(text),
itemInfo(info),
itemHeader(header),
itemBody(body),
itemParsingData(parsingData),
parentItem(parent)
{
}
@ -37,12 +38,6 @@ TreeItem::~TreeItem()
qDeleteAll(childItems);
}
/*void TreeItem::setDefaultNames()
{
itemTypeName = itemTypeToQString(itemType);
itemSubtypeName = itemSubtypeToQString(itemType, itemSubtype);
}*/
void TreeItem::appendChild(TreeItem *item)
{
childItems.append(item);
@ -96,8 +91,8 @@ QVariant TreeItem::data(int column) const
return actionTypeToQString(itemAction);
case 2: // Type
return itemTypeToQString(itemType);
case 3: // Attributes
return itemAttributesToQString(itemType, itemAttributes);
case 3: // Subtype
return itemSubtypeToQString(itemType, itemSubtype);
case 4: // Text
return itemText;
default:
@ -163,14 +158,14 @@ void TreeItem::setType(const UINT8 type)
itemType = type;
}
UINT32 TreeItem::attributes() const
UINT8 TreeItem::subtype() const
{
return itemAttributes;
return itemSubtype;
}
void TreeItem::setAttributes(const UINT32 attributes)
void TreeItem::setSubtype(const UINT8 subtype)
{
itemAttributes = attributes;
itemSubtype = subtype;
}
@ -189,6 +184,11 @@ QByteArray TreeItem::body() const
return itemBody;
}
QByteArray TreeItem::parsingData() const
{
return itemParsingData;
}
bool TreeItem::hasEmptyHeader() const
{
return itemHeader.isEmpty();
@ -199,6 +199,16 @@ bool TreeItem::hasEmptyBody() const
return itemBody.isEmpty();
}
bool TreeItem::hasEmptyParsingData() const
{
return itemParsingData.isEmpty();
}
void TreeItem::setParsingData(const QByteArray & data)
{
itemParsingData = data;
}
UINT8 TreeItem::action() const
{
return itemAction;

View File

@ -24,9 +24,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
class TreeItem
{
public:
TreeItem(const UINT8 type, const UINT32 attributes = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString &name = QString(), const QString &text = QString(), const QString &info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(),
TreeItem *parent = 0);
~TreeItem();
@ -51,8 +51,8 @@ public:
UINT8 type() const;
void setType(const UINT8 type);
UINT32 attributes() const;
void setAttributes(const UINT32 attributes);
UINT8 subtype() const;
void setSubtype(const UINT8 subtype);
QString text() const;
void setText(const QString &text);
@ -62,7 +62,11 @@ public:
QByteArray body() const;
bool hasEmptyBody() const;
QByteArray parsingData() const;
bool hasEmptyParsingData() const;
void setParsingData(const QByteArray & data);
QString info() const;
void addInfo(const QString &info);
void setInfo(const QString &info);
@ -76,13 +80,14 @@ private:
QList<TreeItem*> childItems;
UINT8 itemAction;
UINT8 itemType;
UINT32 itemAttributes;
UINT8 itemSubtype;
UINT8 itemCompression;
QString itemName;
QString itemText;
QString itemInfo;
QByteArray itemHeader;
QByteArray itemBody;
QByteArray itemParsingData;
TreeItem *parentItem;
};

View File

@ -138,12 +138,12 @@ UINT8 TreeModel::type(const QModelIndex &index) const
return item->type();
}
UINT32 TreeModel::attributes(const QModelIndex &index) const
UINT8 TreeModel::subtype(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->attributes();
return item->subtype();
}
QByteArray TreeModel::header(const QModelIndex &index) const
@ -178,6 +178,22 @@ bool TreeModel::hasEmptyBody(const QModelIndex &index) const
return item->hasEmptyBody();
}
QByteArray TreeModel::parsingData(const QModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->parsingData();
}
bool TreeModel::hasEmptyParsingData(const QModelIndex &index) const
{
if (!index.isValid())
return true;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->hasEmptyParsingData();
}
QString TreeModel::name(const QModelIndex &index) const
{
if (!index.isValid())
@ -218,13 +234,13 @@ UINT8 TreeModel::compression(const QModelIndex &index) const
return item->compression();
}
void TreeModel::setAttributes(const QModelIndex & index, const UINT32 attributes)
void TreeModel::setSubtype(const QModelIndex & index, const UINT8 subtype)
{
if (!index.isValid())
return;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setAttributes(attributes);
item->setSubtype(subtype);
emit dataChanged(index, index);
}
@ -258,15 +274,6 @@ void TreeModel::setText(const QModelIndex &index, const QString &data)
emit dataChanged(index, index);
}
/*QString TreeModel::name(const QModelIndex &index) const
{
if (!index.isValid())
return QString();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->name();
}*/
void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
{
if (!index.isValid())
@ -277,9 +284,19 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
emit dataChanged(this->index(0, 0), index);
}
QModelIndex TreeModel::addItem(const UINT8 type, const UINT32 attributes, const UINT8 compression,
void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data)
{
if (!index.isValid())
return;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setParsingData(data);
emit dataChanged(this->index(0, 0), index);
}
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body,
const QByteArray & header, const QByteArray & body, const QByteArray & parsingData,
const QModelIndex & parent, const UINT8 mode)
{
TreeItem *item = 0;
@ -301,7 +318,7 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT32 attributes, const
}
}
TreeItem *newItem = new TreeItem(type, attributes, compression, name, text, info, header, body, parentItem);
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parsingData, parentItem);
if (mode == CREATE_MODE_APPEND) {
emit layoutAboutToBeChanged();
parentItem->appendChild(newItem);

View File

@ -44,25 +44,28 @@ public:
void setAction(const QModelIndex &index, const UINT8 action);
void setType(const QModelIndex &index, const UINT8 type);
void setAttributes(const QModelIndex &index, const UINT32 attributes);
void setSubtype(const QModelIndex &index, const UINT8 subtype);
void setName(const QModelIndex &index, const QString &name);
void setText(const QModelIndex &index, const QString &text);
void setParsingData(const QModelIndex &index, const QByteArray &data);
QString name(const QModelIndex &index) const;
QString text(const QModelIndex &index) const;
QString info(const QModelIndex &index) const;
UINT8 type(const QModelIndex &index) const;
UINT32 attributes(const QModelIndex &index) const;
UINT8 subtype(const QModelIndex &index) const;
QByteArray header(const QModelIndex &index) const;
bool hasEmptyHeader(const QModelIndex &index) const;
QByteArray body(const QModelIndex &index) const;
bool hasEmptyBody(const QModelIndex &index) const;
QByteArray parsingData(const QModelIndex &index) const;
bool hasEmptyParsingData(const QModelIndex &index) const;
UINT8 action(const QModelIndex &index) const;
UINT8 compression(const QModelIndex &index) const;
QModelIndex addItem(const UINT8 type, const UINT32 attributes = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(),
const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;

View File

@ -19,15 +19,15 @@ QString regionTypeToQString(const UINT8 type)
{
switch (type)
{
case ATTR_REGION_TYPE_DESCRIPTOR:
case Subtypes::DescriptorRegion:
return QObject::tr("Descriptor");
case ATTR_REGION_TYPE_GBE:
case Subtypes::GbeRegion:
return QObject::tr("GbE");
case ATTR_REGION_TYPE_ME:
case Subtypes::MeRegion:
return QObject::tr("ME/TXE");
case ATTR_REGION_TYPE_BIOS:
case Subtypes::BiosRegion:
return QObject::tr("BIOS");
case ATTR_REGION_TYPE_PDR:
case Subtypes::PdrRegion:
return QObject::tr("PDR");
default:
return QObject::tr("Unknown");
@ -53,77 +53,61 @@ QString itemTypeToQString(const UINT8 type)
return QObject::tr("File");
case Types::Section:
return QObject::tr("Section");
case Types::FreeSpace:
return QObject::tr("Free space");
default:
return QObject::tr("Unknown");
}
}
QString itemAttributesToQString(const UINT8 type, const UINT8 attributes)
QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
{
switch (type) {
case Types::Root:
case Types::Image:
if (attributes == ATTR_IMAGE_TYPE_DESCRIPTOR)
if (subtype == Subtypes::IntelImage)
return QObject::tr("Intel");
else if (attributes == ATTR_IMAGE_TYPE_UEFI)
else if (Subtypes::UefiImage)
return QObject::tr("UEFI");
else
return QObject::tr("Unknown");
return QObject::tr("Unknown subtype");
case Types::Padding:
if (attributes == ATTR_PADDING_ZERO_EMPTY)
if (subtype == Subtypes::ZeroPadding)
return QObject::tr("Empty (0x00)");
else if (attributes == ATTR_PADDING_ONE_EMPTY)
else if (subtype == Subtypes::OnePadding)
return QObject::tr("Empty (0xFF)");
else if (attributes == ATTR_PADDING_DATA)
else if (subtype == Subtypes::DataPadding)
return QObject::tr("Non-empty");
else
return QObject::tr("Unknown subtype");
case Types::Volume:
if (subtype == Subtypes::UnknownVolume)
return QObject::tr("Unknown");
case Types::Volume: {
QString string;
VOLUME_ATTRIBUTES* volumeAttr = (VOLUME_ATTRIBUTES*)&attributes;
if (volumeAttr->ZeroVectorCrc)
string += QObject::tr("ZVCRC ");
if (volumeAttr->VtfPresent)
string += QObject::tr("Boot ");
if (volumeAttr->Unknown) {
string += QObject::tr("Unknown");
return string;
}
if (volumeAttr->FsVersion == 2 || volumeAttr->FsVersion == 3)
string += QObject::tr("FFSv%1").arg(volumeAttr->FsVersion);
else if (subtype == Subtypes::Ffs2Volume)
return QObject::tr("FFSv2");
else if (subtype == Subtypes::Ffs3Volume)
return QObject::tr("FFSv3");
else
return QObject::tr("Unknown FFS version");
return string;
}
case Types::Capsule: {
QString string;
CAPSULE_ATTRIBUTES* capsuleAttr = (CAPSULE_ATTRIBUTES*)&attributes;
if (capsuleAttr->Type == ATTR_CAPSULE_TYPE_APTIO)
string += QObject::tr("Aptio ");
else if (capsuleAttr->Type == ATTR_CAPSULE_TYPE_UEFI20)
string += QObject::tr("UEFI 2.0 ");
return QObject::tr("Unknown subtype");
case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule)
return QObject::tr("Aptio signed");
else if (subtype == Subtypes::AptioUnsignedCapsule)
return QObject::tr("Aptio unsigned");
else if (subtype == Subtypes::UefiCapsule)
return QObject::tr("UEFI 2.0 ");
else
return QObject::tr("Unknown type");
if (capsuleAttr->Signed)
string += QObject::tr("signed");
else
string += QObject::tr("unsigned");
return string;
}
return QObject::tr("Unknown subtype");
case Types::Region:
return regionTypeToQString(attributes);
return regionTypeToQString(subtype);
case Types::File:
return fileTypeToQString(attributes);
return fileTypeToQString(subtype);
case Types::Section:
return sectionTypeToQString(attributes);
return sectionTypeToQString(subtype);
case Types::FreeSpace:
return QString();
default:
return QObject::tr("Unknown");
return QObject::tr("Unknown subtype");
}
}

99
types.h
View File

@ -16,8 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "basetypes.h"
#pragma pack(push, 1)
// Actions
namespace Actions
{
@ -42,61 +40,70 @@ namespace Types {
Padding,
Volume,
File,
Section
Section,
FreeSpace
};
}
// Capsule attributes
typedef struct _CAPSULE_ATTRIBUTES {
UINT32 Type : 7;
UINT32 Signed : 1;
UINT32 Reserved : 24;
} CAPSULE_ATTRIBUTES;
#define ATTR_CAPSULE_TYPE_UEFI20 0
#define ATTR_CAPSULE_TYPE_APTIO 1
namespace Subtypes {
enum ImageSubtypes{
IntelImage = 70,
UefiImage
};
typedef struct _IMAGE_ATTRIBUTES {
UINT32 IntelDescriptor : 1;
UINT32 Reserved : 31;
} IMAGE_ATTRIBUTES;
#define ATTR_IMAGE_TYPE_UEFI 0
#define ATTR_IMAGE_TYPE_DESCRIPTOR 1
enum CapsuleSubtypes {
AptioSignedCapsule = 80,
AptioUnsignedCapsule,
UefiCapsule
};
typedef struct _REGION_ATTRIBUTES {
UINT32 Type : 7;
UINT32 Empty : 1;
UINT32 Reserved : 24;
} REGION_ATTRIBUTES;
enum VolumeSubtypes {
UnknownVolume = 90,
Ffs2Volume,
Ffs3Volume
};
#define ATTR_REGION_TYPE_DESCRIPTOR 0
#define ATTR_REGION_TYPE_GBE 1
#define ATTR_REGION_TYPE_ME 2
#define ATTR_REGION_TYPE_BIOS 3
#define ATTR_REGION_TYPE_PDR 4
enum RegionSubtypes {
DescriptorRegion = 100,
GbeRegion,
MeRegion,
BiosRegion,
PdrRegion
};
typedef struct _VOLUME_ATTRIBUTES {
UINT32 Unknown : 1;
UINT32 VtfPresent : 1;
UINT32 ZeroVectorCrc : 1;
UINT32 FsVersion : 5;
UINT32 Reserved : 24;
} VOLUME_ATTRIBUTES;
typedef struct _PADDING_ATTRIBUTES {
UINT32 Empty : 1;
UINT32 ErasePolarity : 1;
UINT32 Reserved : 30;
} PADDING_ATTRIBUTES;
#define ATTR_PADDING_DATA 0
#define ATTR_PADDING_ZERO_EMPTY 1
#define ATTR_PADDING_ONE_EMPTY 3
#pragma pack(pop)
enum PaddingSubtypes {
ZeroPadding = 110,
OnePadding,
DataPadding
};
};
// *ToQString conversion routines
extern QString actionTypeToQString(const UINT8 action);
extern QString itemTypeToQString(const UINT8 type);
extern QString itemAttributesToQString(const UINT8 type, const UINT8 attributes);
extern QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype);
extern QString compressionTypeToQString(const UINT8 algorithm);
extern QString regionTypeToQString(const UINT8 type);
enum ParsingDataTypes {
UnknownParsingData,
VolumeParsingData,
FileParsingData
};
typedef union _PARSING_DATA_UNION {
struct _PARSING_DATA_UNION_VOLUME {
bool HasZeroVectorCRC;
} Volume;
struct _PARSING_DATA_UNION_FILE {
UINT32 Offset;
} File;
} PARSING_DATA_UNION;
typedef struct _PARSING_DATA {
UINT8 Type;
PARSING_DATA_UNION Data;
} PARSING_DATA;
#endif

View File

@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr("0.20.0"))
version(tr("0.20.1"))
{
clipboard = QApplication::clipboard();
@ -123,7 +123,7 @@ void UEFITool::populateUi(const QModelIndex &current)
TreeModel* model = ffsEngine->treeModel();
UINT8 type = model->type(current);
UINT32 attributes = model->attributes(current);
UINT8 subtype = model->subtype(current);
// Set info text
ui->infoEdit->setPlainText(model->info(current));
@ -142,12 +142,12 @@ void UEFITool::populateUi(const QModelIndex &current)
ui->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionExtractBody->setDisabled(model->hasEmptyBody(current));
ui->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionInsertInto->setEnabled((type == Types::Volume && ((VOLUME_ATTRIBUTES*)&attributes)->Unknown == 0) ||
(type == Types::File && attributes != EFI_FV_FILETYPE_ALL && attributes != EFI_FV_FILETYPE_RAW && attributes != EFI_FV_FILETYPE_PAD) ||
(type == Types::Section && (attributes == EFI_SECTION_COMPRESSION || attributes == EFI_SECTION_GUID_DEFINED || attributes == EFI_SECTION_DISPOSABLE)));
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::Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE)));
ui->actionInsertBefore->setEnabled(type == Types::File || type == Types::Section);
ui->actionInsertAfter->setEnabled(type == Types::File || type == Types::Section);
ui->actionReplace->setEnabled((type == Types::Region && ((REGION_ATTRIBUTES*)&attributes)->Type != ATTR_REGION_TYPE_DESCRIPTOR) || type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionReplaceBody->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionMessagesCopy->setEnabled(false);
}
@ -336,9 +336,10 @@ void UEFITool::replace(const UINT8 mode)
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to replace selected object"), currentDir, "FFS files (*.ffs *.bin);;All files (*)");
}
else if (mode == REPLACE_MODE_BODY) {
if (model->attributes(index) == EFI_FV_FILETYPE_ALL || model->attributes(index) == EFI_FV_FILETYPE_RAW)
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 body"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else if (model->attributes(index) == EFI_FV_FILETYPE_PAD) // Pad file body can't be replaced
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 body"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
@ -351,11 +352,11 @@ void UEFITool::replace(const UINT8 mode)
path = QFileDialog::getOpenFileName(this, tr("Select section file to replace selected object"), currentDir, "Section files (*.sec *.bin);;All files (*)");
}
else if (mode == REPLACE_MODE_BODY) {
if (model->attributes(index) == EFI_SECTION_COMPRESSION || model->attributes(index) == EFI_SECTION_GUID_DEFINED || model->attributes(index) == EFI_SECTION_DISPOSABLE)
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 body"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
else if (model->attributes(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
else if (model->attributes(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 (*)");
else
path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)");
@ -450,18 +451,18 @@ void UEFITool::extract(const UINT8 mode)
path = QFileDialog::getSaveFileName(this, tr("Save volume body to file"), currentDir, "Volume body files (*.vbd *.bin);;All files (*)");
break;
case Types::File: {
if (model->attributes(index) == EFI_FV_FILETYPE_ALL || model->attributes(index) == EFI_FV_FILETYPE_RAW)
if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW)
path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to raw file"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else
path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to file"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
}
break;
case Types::Section: {
if (model->attributes(index) == EFI_SECTION_COMPRESSION || model->attributes(index) == EFI_SECTION_GUID_DEFINED || model->attributes(index) == EFI_SECTION_DISPOSABLE)
if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)
path = QFileDialog::getSaveFileName(this, tr("Save encapsulation section body to FFS body file"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
else if (model->attributes(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
else if (model->attributes(index) == EFI_SECTION_RAW)
else if (model->subtype(index) == EFI_SECTION_RAW)
path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else
path = QFileDialog::getSaveFileName(this, tr("Save section body to file"), currentDir, "Binary files (*.bin);;All files (*)");

View File

@ -10,6 +10,7 @@ SOURCES += uefitool_main.cpp \
types.cpp \
descriptor.cpp \
ffs.cpp \
peimage.cpp \
ffsengine.cpp \
treeitem.cpp \
treemodel.cpp \