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
.mr.developer.cfg .mr.developer.cfg
#############
## qmake / make
#############
*.o
Makefile
UEFIExtract/UEFIExtract
UEFIFind/UEFIFind
UEFIPatch/UEFIPatch
UEFITool

View File

@ -38,7 +38,7 @@ Usage
Known issues 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. * 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. * 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. * 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_COMPRESSION: return QObject::tr("Compressed");
case EFI_SECTION_GUID_DEFINED: return QObject::tr("GUID defined"); case EFI_SECTION_GUID_DEFINED: return QObject::tr("GUID defined");
case EFI_SECTION_DISPOSABLE: return QObject::tr("Disposable"); 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_PIC: return QObject::tr("PIC image");
case EFI_SECTION_TE: return QObject::tr("TE image"); case EFI_SECTION_TE: return QObject::tr("TE image");
case EFI_SECTION_DXE_DEPEX: return QObject::tr("DXE dependency"); 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__ #ifndef __PE_IMAGE_H__
#define __PE_IMAGE_H__ #define __PE_IMAGE_H__
#include <QString>
#include "basetypes.h"
// Make sure we use right packing rules // Make sure we use right packing rules
#pragma pack(push,1) #pragma pack(push,1)
extern QString machineTypeToQString(UINT16 machineType);
// //
// PE32+ Subsystem type for EFI images // 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 // PE32+ Machine type for EFI images
// //
#define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_IA64 0x0200 #define IMAGE_FILE_MACHINE_ARM 0x01c0
#define IMAGE_FILE_MACHINE_EBC 0x0EBC #define IMAGE_FILE_MACHINE_ARMV7 0x01c4
#define IMAGE_FILE_MACHINE_X64 0x8664 #define IMAGE_FILE_MACHINE_EBC 0x0ebc
#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2 #define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_IA64 0x0200
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
// //
// EXE file formats // EXE file formats

View File

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

View File

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

View File

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

View File

@ -44,25 +44,28 @@ public:
void setAction(const QModelIndex &index, const UINT8 action); void setAction(const QModelIndex &index, const UINT8 action);
void setType(const QModelIndex &index, const UINT8 type); 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 setName(const QModelIndex &index, const QString &name);
void setText(const QModelIndex &index, const QString &text); void setText(const QModelIndex &index, const QString &text);
void setParsingData(const QModelIndex &index, const QByteArray &data);
QString name(const QModelIndex &index) const; QString name(const QModelIndex &index) const;
QString text(const QModelIndex &index) const; QString text(const QModelIndex &index) const;
QString info(const QModelIndex &index) const; QString info(const QModelIndex &index) const;
UINT8 type(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; QByteArray header(const QModelIndex &index) const;
bool hasEmptyHeader(const QModelIndex &index) const; bool hasEmptyHeader(const QModelIndex &index) const;
QByteArray body(const QModelIndex &index) const; QByteArray body(const QModelIndex &index) const;
bool hasEmptyBody(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 action(const QModelIndex &index) const;
UINT8 compression(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 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); const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const; QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;

View File

@ -19,15 +19,15 @@ QString regionTypeToQString(const UINT8 type)
{ {
switch (type) switch (type)
{ {
case ATTR_REGION_TYPE_DESCRIPTOR: case Subtypes::DescriptorRegion:
return QObject::tr("Descriptor"); return QObject::tr("Descriptor");
case ATTR_REGION_TYPE_GBE: case Subtypes::GbeRegion:
return QObject::tr("GbE"); return QObject::tr("GbE");
case ATTR_REGION_TYPE_ME: case Subtypes::MeRegion:
return QObject::tr("ME/TXE"); return QObject::tr("ME/TXE");
case ATTR_REGION_TYPE_BIOS: case Subtypes::BiosRegion:
return QObject::tr("BIOS"); return QObject::tr("BIOS");
case ATTR_REGION_TYPE_PDR: case Subtypes::PdrRegion:
return QObject::tr("PDR"); return QObject::tr("PDR");
default: default:
return QObject::tr("Unknown"); return QObject::tr("Unknown");
@ -53,77 +53,61 @@ QString itemTypeToQString(const UINT8 type)
return QObject::tr("File"); return QObject::tr("File");
case Types::Section: case Types::Section:
return QObject::tr("Section"); return QObject::tr("Section");
case Types::FreeSpace:
return QObject::tr("Free space");
default: default:
return QObject::tr("Unknown"); return QObject::tr("Unknown");
} }
} }
QString itemAttributesToQString(const UINT8 type, const UINT8 attributes) QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
{ {
switch (type) { switch (type) {
case Types::Root: case Types::Root:
case Types::Image: case Types::Image:
if (attributes == ATTR_IMAGE_TYPE_DESCRIPTOR) if (subtype == Subtypes::IntelImage)
return QObject::tr("Intel"); return QObject::tr("Intel");
else if (attributes == ATTR_IMAGE_TYPE_UEFI) else if (Subtypes::UefiImage)
return QObject::tr("UEFI"); return QObject::tr("UEFI");
else else
return QObject::tr("Unknown"); return QObject::tr("Unknown subtype");
case Types::Padding: case Types::Padding:
if (attributes == ATTR_PADDING_ZERO_EMPTY) if (subtype == Subtypes::ZeroPadding)
return QObject::tr("Empty (0x00)"); return QObject::tr("Empty (0x00)");
else if (attributes == ATTR_PADDING_ONE_EMPTY) else if (subtype == Subtypes::OnePadding)
return QObject::tr("Empty (0xFF)"); return QObject::tr("Empty (0xFF)");
else if (attributes == ATTR_PADDING_DATA) else if (subtype == Subtypes::DataPadding)
return QObject::tr("Non-empty"); return QObject::tr("Non-empty");
else else
return QObject::tr("Unknown subtype");
case Types::Volume:
if (subtype == Subtypes::UnknownVolume)
return QObject::tr("Unknown"); return QObject::tr("Unknown");
case Types::Volume: { else if (subtype == Subtypes::Ffs2Volume)
QString string; return QObject::tr("FFSv2");
VOLUME_ATTRIBUTES* volumeAttr = (VOLUME_ATTRIBUTES*)&attributes; else if (subtype == Subtypes::Ffs3Volume)
if (volumeAttr->ZeroVectorCrc) return QObject::tr("FFSv3");
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 else
return QObject::tr("Unknown FFS version"); return QObject::tr("Unknown subtype");
case Types::Capsule:
return string; if (subtype == Subtypes::AptioSignedCapsule)
} return QObject::tr("Aptio signed");
case Types::Capsule: { else if (subtype == Subtypes::AptioUnsignedCapsule)
QString string; return QObject::tr("Aptio unsigned");
CAPSULE_ATTRIBUTES* capsuleAttr = (CAPSULE_ATTRIBUTES*)&attributes; else if (subtype == Subtypes::UefiCapsule)
if (capsuleAttr->Type == ATTR_CAPSULE_TYPE_APTIO) return QObject::tr("UEFI 2.0 ");
string += QObject::tr("Aptio ");
else if (capsuleAttr->Type == ATTR_CAPSULE_TYPE_UEFI20)
string += QObject::tr("UEFI 2.0 ");
else else
return QObject::tr("Unknown type"); return QObject::tr("Unknown subtype");
if (capsuleAttr->Signed)
string += QObject::tr("signed");
else
string += QObject::tr("unsigned");
return string;
}
case Types::Region: case Types::Region:
return regionTypeToQString(attributes); return regionTypeToQString(subtype);
case Types::File: case Types::File:
return fileTypeToQString(attributes); return fileTypeToQString(subtype);
case Types::Section: case Types::Section:
return sectionTypeToQString(attributes); return sectionTypeToQString(subtype);
case Types::FreeSpace:
return QString();
default: 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" #include "basetypes.h"
#pragma pack(push, 1)
// Actions // Actions
namespace Actions namespace Actions
{ {
@ -42,61 +40,70 @@ namespace Types {
Padding, Padding,
Volume, Volume,
File, File,
Section Section,
FreeSpace
}; };
} }
// Capsule attributes namespace Subtypes {
typedef struct _CAPSULE_ATTRIBUTES { enum ImageSubtypes{
UINT32 Type : 7; IntelImage = 70,
UINT32 Signed : 1; UefiImage
UINT32 Reserved : 24; };
} CAPSULE_ATTRIBUTES;
#define ATTR_CAPSULE_TYPE_UEFI20 0
#define ATTR_CAPSULE_TYPE_APTIO 1
typedef struct _IMAGE_ATTRIBUTES { enum CapsuleSubtypes {
UINT32 IntelDescriptor : 1; AptioSignedCapsule = 80,
UINT32 Reserved : 31; AptioUnsignedCapsule,
} IMAGE_ATTRIBUTES; UefiCapsule
#define ATTR_IMAGE_TYPE_UEFI 0 };
#define ATTR_IMAGE_TYPE_DESCRIPTOR 1
typedef struct _REGION_ATTRIBUTES { enum VolumeSubtypes {
UINT32 Type : 7; UnknownVolume = 90,
UINT32 Empty : 1; Ffs2Volume,
UINT32 Reserved : 24; Ffs3Volume
} REGION_ATTRIBUTES; };
#define ATTR_REGION_TYPE_DESCRIPTOR 0 enum RegionSubtypes {
#define ATTR_REGION_TYPE_GBE 1 DescriptorRegion = 100,
#define ATTR_REGION_TYPE_ME 2 GbeRegion,
#define ATTR_REGION_TYPE_BIOS 3 MeRegion,
#define ATTR_REGION_TYPE_PDR 4 BiosRegion,
PdrRegion
};
typedef struct _VOLUME_ATTRIBUTES { enum PaddingSubtypes {
UINT32 Unknown : 1; ZeroPadding = 110,
UINT32 VtfPresent : 1; OnePadding,
UINT32 ZeroVectorCrc : 1; DataPadding
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)
// *ToQString conversion routines // *ToQString conversion routines
extern QString actionTypeToQString(const UINT8 action); extern QString actionTypeToQString(const UINT8 action);
extern QString itemTypeToQString(const UINT8 type); 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 compressionTypeToQString(const UINT8 algorithm);
extern QString regionTypeToQString(const UINT8 type); 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 #endif

View File

@ -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.20.0")) version(tr("0.20.1"))
{ {
clipboard = QApplication::clipboard(); clipboard = QApplication::clipboard();
@ -123,7 +123,7 @@ void UEFITool::populateUi(const QModelIndex &current)
TreeModel* model = ffsEngine->treeModel(); TreeModel* model = ffsEngine->treeModel();
UINT8 type = model->type(current); UINT8 type = model->type(current);
UINT32 attributes = model->attributes(current); UINT8 subtype = model->subtype(current);
// Set info text // Set info text
ui->infoEdit->setPlainText(model->info(current)); 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->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionExtractBody->setDisabled(model->hasEmptyBody(current)); ui->actionExtractBody->setDisabled(model->hasEmptyBody(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 && ((VOLUME_ATTRIBUTES*)&attributes)->Unknown == 0) || ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) ||
(type == Types::File && attributes != EFI_FV_FILETYPE_ALL && attributes != EFI_FV_FILETYPE_RAW && attributes != EFI_FV_FILETYPE_PAD) || (type == Types::File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD) ||
(type == Types::Section && (attributes == EFI_SECTION_COMPRESSION || attributes == EFI_SECTION_GUID_DEFINED || attributes == EFI_SECTION_DISPOSABLE))); (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->actionInsertBefore->setEnabled(type == Types::File || type == Types::Section);
ui->actionInsertAfter->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->actionReplaceBody->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionMessagesCopy->setEnabled(false); 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 (*)"); 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) { 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 (*)"); 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; return;
else else
path = QFileDialog::getOpenFileName(this, tr("Select FFS file body to replace body"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)"); 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 (*)"); 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) { 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 (*)"); 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 (*)"); 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 (*)"); path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"), currentDir, "Raw files (*.raw *.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 (*)");
@ -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 (*)"); path = QFileDialog::getSaveFileName(this, tr("Save volume body to file"), currentDir, "Volume body files (*.vbd *.bin);;All files (*)");
break; break;
case Types::File: { 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 (*)"); path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to raw file"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else else
path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to file"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)"); path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to file"), currentDir, "FFS file body files (*.fbd *.bin);;All files (*)");
} }
break; break;
case Types::Section: { 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 (*)"); 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 (*)"); 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 (*)"); path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else else
path = QFileDialog::getSaveFileName(this, tr("Save section body to file"), currentDir, "Binary files (*.bin);;All files (*)"); 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 \ types.cpp \
descriptor.cpp \ descriptor.cpp \
ffs.cpp \ ffs.cpp \
peimage.cpp \
ffsengine.cpp \ ffsengine.cpp \
treeitem.cpp \ treeitem.cpp \
treemodel.cpp \ treemodel.cpp \