mirror of
https://github.com/LongSoft/UEFITool.git
synced 2025-05-13 06:34:42 -04:00
UT 0.20.8
- data after the latest region of Intel image is in tree now - added Intel, Lenovo and Toshiba-specific capsule GUIDs to the list of known GUIDs - fixed bogus "File with invalid size" message while working on almost full volumes - pressing Cancel on "Open in new window" dialog now works as expected Big thanks to Lordkag for spotting most of the issues (#31).
This commit is contained in:
parent
63e5a4dd1c
commit
9c4ddbec62
6 changed files with 159 additions and 61 deletions
|
@ -85,6 +85,7 @@ typedef unsigned int UINTN;
|
|||
#define ERR_INVALID_SYMBOL 40
|
||||
#define ERR_NOTHING_TO_PATCH 41
|
||||
#define ERR_DEPEX_PARSE_FAILED 42
|
||||
#define ERR_TRUNCATED_IMAGE 43
|
||||
#define ERR_NOT_IMPLEMENTED 0xFF
|
||||
|
||||
// UDK porting definitions
|
||||
|
|
22
ffs.h
22
ffs.h
|
@ -32,7 +32,7 @@ extern QString sectionTypeToQString(const UINT8 type);
|
|||
//*****************************************************************************
|
||||
// EFI Capsule
|
||||
//*****************************************************************************
|
||||
// Capsule header
|
||||
// Standard EFI Capsule header
|
||||
typedef struct _EFI_CAPSULE_HEADER {
|
||||
EFI_GUID CapsuleGuid;
|
||||
UINT32 HeaderSize;
|
||||
|
@ -49,6 +49,26 @@ typedef struct _EFI_CAPSULE_HEADER {
|
|||
const QByteArray EFI_CAPSULE_GUID
|
||||
("\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
|
||||
typedef struct _APTIO_CAPSULE_HEADER {
|
||||
EFI_CAPSULE_HEADER CapsuleHeader;
|
||||
|
|
|
@ -75,6 +75,7 @@ QString errorMessage(UINT8 errorCode)
|
|||
case ERR_INVALID_SYMBOL: return QObject::tr("Invalid symbol");
|
||||
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_TRUNCATED_IMAGE: return QObject::tr("Image is truncated");
|
||||
default: return QObject::tr("Unknown error %1").arg(errorCode);
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +154,9 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer)
|
|||
// Check buffer for being normal EFI capsule header
|
||||
UINT32 capsuleHeaderSize = 0;
|
||||
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
|
||||
const EFI_CAPSULE_HEADER* capsuleHeader = (const EFI_CAPSULE_HEADER*)buffer.constData();
|
||||
capsuleHeaderSize = capsuleHeader->HeaderSize;
|
||||
|
@ -170,7 +173,24 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer)
|
|||
// Add tree item
|
||||
index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
|
||||
}
|
||||
// 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("Capsule 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);
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
|
||||
}
|
||||
// Check buffer for being extended Aptio signed capsule header
|
||||
else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) {
|
||||
// Get info
|
||||
|
@ -458,6 +478,34 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in
|
|||
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 info
|
||||
name = tr("Padding");
|
||||
info = tr("Full size: %1h (%2)")
|
||||
.hexarg(padding.size()).arg(padding.size());
|
||||
// Add tree item
|
||||
model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, index);
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -495,7 +543,7 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const
|
|||
return ERR_EMPTY_REGION;
|
||||
|
||||
// Get info
|
||||
QString name = tr("ME/TXE region");
|
||||
QString name = tr("ME region");
|
||||
QString info = tr("Full size: %1h (%2)").
|
||||
hexarg(me.size()).arg(me.size());
|
||||
|
||||
|
@ -536,10 +584,10 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const
|
|||
|
||||
// Show messages
|
||||
if (emptyRegion) {
|
||||
msg(tr("parseRegion: ME/TXE region is empty"), index);
|
||||
msg(tr("parseRegion: ME region is empty"), index);
|
||||
}
|
||||
else if (!versionFound) {
|
||||
msg(tr("parseRegion: ME/TXE region version is unknown, it can be damaged"), index);
|
||||
msg(tr("parseRegion: ME region version is unknown, it can be damaged"), index);
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
|
@ -874,6 +922,22 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
|
|||
bool msgUnalignedFile = false;
|
||||
bool msgDuplicateGuid = false;
|
||||
|
||||
// Check if it's possibly the latest file in the volume
|
||||
if (volumeSize - fileOffset < sizeof(EFI_FFS_FILE_HEADER)) {
|
||||
// No files are possible after this point
|
||||
// All the rest is either free space or non-UEFI data
|
||||
QByteArray rest = volume.right(volumeSize - fileOffset);
|
||||
if (rest.count(empty) == rest.size()) { // It's a free space
|
||||
model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index, mode);
|
||||
}
|
||||
else { //It's non-UEFI data
|
||||
QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index, mode);
|
||||
msg(tr("parseVolume: non-UEFI data found in volume's free space"), dataIndex);
|
||||
}
|
||||
// Exit from loop
|
||||
break;
|
||||
}
|
||||
|
||||
result = getFileSize(volume, fileOffset, fileSize);
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -2657,12 +2721,20 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec
|
|||
char empty = '\xFF';
|
||||
for (int i = 1; i < model->rowCount(index); i++) {
|
||||
QByteArray region;
|
||||
|
||||
// Padding after the end of all Intel regions
|
||||
if (model->type(index.child(i, 0)) == Types::Padding) {
|
||||
region = model->body(index.child(i, 0));
|
||||
reconstructed.append(region);
|
||||
offset += region.size();
|
||||
continue;
|
||||
}
|
||||
|
||||
result = reconstructRegion(index.child(i, 0), region);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
UINT8 type = model->subtype(index.child(i, 0));
|
||||
switch (type)
|
||||
switch (model->subtype(index.child(i, 0)))
|
||||
{
|
||||
case Subtypes::GbeRegion:
|
||||
gbe = region;
|
||||
|
|
|
@ -24,7 +24,7 @@ QString regionTypeToQString(const UINT8 type)
|
|||
case Subtypes::GbeRegion:
|
||||
return QObject::tr("GbE");
|
||||
case Subtypes::MeRegion:
|
||||
return QObject::tr("ME/TXE");
|
||||
return QObject::tr("ME");
|
||||
case Subtypes::BiosRegion:
|
||||
return QObject::tr("BIOS");
|
||||
case Subtypes::PdrRegion:
|
||||
|
@ -96,6 +96,8 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
|||
return QObject::tr("Aptio unsigned");
|
||||
else if (subtype == Subtypes::UefiCapsule)
|
||||
return QObject::tr("UEFI 2.0");
|
||||
else if (subtype == Subtypes::ToshibaCapsule)
|
||||
return QObject::tr("Toshiba");
|
||||
else
|
||||
return QObject::tr("Unknown subtype");
|
||||
case Types::Region:
|
||||
|
|
3
types.h
3
types.h
|
@ -54,7 +54,8 @@ namespace Subtypes {
|
|||
enum CapsuleSubtypes {
|
||||
AptioSignedCapsule = 80,
|
||||
AptioUnsignedCapsule,
|
||||
UefiCapsule
|
||||
UefiCapsule,
|
||||
ToshibaCapsule
|
||||
};
|
||||
|
||||
enum VolumeSubtypes {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
UEFITool::UEFITool(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::UEFITool),
|
||||
version(tr("0.20.7"))
|
||||
version(tr("0.20.8"))
|
||||
{
|
||||
clipboard = QApplication::clipboard();
|
||||
|
||||
|
@ -567,6 +567,8 @@ void UEFITool::openImageFile()
|
|||
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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue