Engine update 0.20.2

- Intel signed section identified as EFI_FIRMWARE_CONTENTS_SIGNED GUIDed
section
- solved a bug with no element for "Non-UEFI data inside pad-file"
message
- HP postcode section renamed to Insyde postcode (found in non-HP
images)
- various small fixes
- this is the latest release without FFSv3 support, which requires
massive refactoring round and can possibly last long
This commit is contained in:
Nikolaj Schlej 2015-02-12 20:51:23 +01:00
parent 39ab1e5f06
commit df03531ca7
9 changed files with 263 additions and 95 deletions

View file

@ -1,6 +1,6 @@
/* uefiextract_main.cpp /* uefiextract_main.cpp
Copyright (c) 2014, Nikolaj Schlej. All rights reserved. Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -52,7 +52,7 @@ int main(int argc, char *argv[])
} }
else { else {
std::cout << "UEFIExtract 0.4.1" << std::endl << std::endl << std::cout << "UEFIExtract 0.4.2" << std::endl << std::endl <<
"Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << std::endl << "Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << std::endl <<
"Returned value is a bit mask where 0 on position N meant File with GUID_N was found and unpacked, 1 otherwise" << std::endl; "Returned value is a bit mask where 0 on position N meant File with GUID_N was found and unpacked, 1 otherwise" << std::endl;
return 1; return 1;

View file

@ -53,10 +53,28 @@ UINT8 UEFIFind::init(const QString & path)
return ERR_SUCCESS; return ERR_SUCCESS;
} }
QString UEFIFind::guidToQString(const UINT8* guid)
{
const UINT32 u32 = *(const UINT32*)guid;
const UINT16 u16_1 = *(const UINT16*)(guid + 4);
const UINT16 u16_2 = *(const UINT16*)(guid + 6);
const UINT8 u8_1 = *(const UINT8*)(guid + 8);
const UINT8 u8_2 = *(const UINT8*)(guid + 9);
const UINT8 u8_3 = *(const UINT8*)(guid + 10);
const UINT8 u8_4 = *(const UINT8*)(guid + 11);
const UINT8 u8_5 = *(const UINT8*)(guid + 12);
const UINT8 u8_6 = *(const UINT8*)(guid + 13);
const UINT8 u8_7 = *(const UINT8*)(guid + 14);
const UINT8 u8_8 = *(const UINT8*)(guid + 15);
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11").hexarg2(u32, 8).hexarg2(u16_1, 4).hexarg2(u16_2, 4).hexarg2(u8_1, 2).hexarg2(u8_2, 2)
.hexarg2(u8_3, 2).hexarg2(u8_4, 2).hexarg2(u8_5, 2).hexarg2(u8_6, 2).hexarg2(u8_7, 2).hexarg2(u8_8, 2);
}
UINT8 UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result) UINT8 UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result)
{ {
QModelIndex root = model->index(0, 0); QModelIndex root = model->index(0, 0);
QSet<QModelIndex> files; QSet<QPair<QModelIndex, QModelIndex> > files;
result.clear(); result.clear();
@ -70,31 +88,24 @@ UINT8 UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPatt
return ERR_SUCCESS; return ERR_SUCCESS;
} }
QModelIndex index; QPair<QModelIndex, QModelIndex> indexes;
Q_FOREACH(index, files) { Q_FOREACH(indexes, files) {
QByteArray data = model->header(index).left(16); QByteArray data = model->header(indexes.first).left(16);
result.append(guidToQString((const UINT8*)data.constData()));
UINT32 u32 = *(UINT32*)data.constData(); // Special case of freeform subtype GUID files
UINT16 u16_1 = *(UINT16*)(data.constData() + 4); if (indexes.second.isValid() && model->subtype(indexes.second) == EFI_SECTION_FREEFORM_SUBTYPE_GUID) {
UINT16 u16_2 = *(UINT16*)(data.constData() + 6); data = model->header(indexes.second).left(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION));
UINT8 u8_1 = *(UINT8*)(data.constData() + 8); result.append(" ").append(guidToQString((const UINT8*)data.constData() + sizeof(EFI_COMMON_SECTION_HEADER)));
UINT8 u8_2 = *(UINT8*)(data.constData() + 9); }
UINT8 u8_3 = *(UINT8*)(data.constData() + 10);
UINT8 u8_4 = *(UINT8*)(data.constData() + 11); result.append("\n");
UINT8 u8_5 = *(UINT8*)(data.constData() + 12);
UINT8 u8_6 = *(UINT8*)(data.constData() + 13);
UINT8 u8_7 = *(UINT8*)(data.constData() + 14);
UINT8 u8_8 = *(UINT8*)(data.constData() + 15);
QString guid = QString("%1-%2-%3-%4%5-%6%7%8%9%10%11\n").hexarg2(u32, 8).hexarg2(u16_1, 4).hexarg2(u16_2, 4).hexarg2(u8_1, 2).hexarg2(u8_2, 2)
.hexarg2(u8_3, 2).hexarg2(u8_4, 2).hexarg2(u8_5, 2).hexarg2(u8_6, 2).hexarg2(u8_7, 2).hexarg2(u8_8, 2);
result.append(guid);
} }
return ERR_SUCCESS; return ERR_SUCCESS;
} }
UINT8 UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QModelIndex> & files) UINT8 UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files)
{ {
if (!index.isValid()) if (!index.isValid())
return ERR_SUCCESS; return ERR_SUCCESS;
@ -132,10 +143,13 @@ UINT8 UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPa
if (offset % 2 == 0) { if (offset % 2 == 0) {
if (model->type(index) != Types::File) { if (model->type(index) != Types::File) {
QModelIndex ffs = model->findParentOfType(index, Types::File); QModelIndex ffs = model->findParentOfType(index, Types::File);
files.insert(ffs); if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID)
files.insert(QPair<QModelIndex, QModelIndex>(ffs, index));
else
files.insert(QPair<QModelIndex, QModelIndex>(ffs, QModelIndex()));
} }
else else
files.insert(index); files.insert(QPair<QModelIndex, QModelIndex>(index, QModelIndex()));
break; break;
} }

View file

@ -19,12 +19,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QString> #include <QString>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QPair>
#include <QSet> #include <QSet>
#include <QString> #include <QString>
#include <QUuid> #include <QUuid>
#include "../basetypes.h" #include "../basetypes.h"
#include "../ffsengine.h" #include "../ffsengine.h"
#include "../ffs.h"
class UEFIFind : public QObject class UEFIFind : public QObject
{ {
@ -38,7 +40,8 @@ public:
UINT8 find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result); UINT8 find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
private: private:
UINT8 findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QModelIndex> & files); UINT8 findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files);
QString UEFIFind::guidToQString(const UINT8* guid);
FfsEngine* ffsEngine; FfsEngine* ffsEngine;
TreeModel* model; TreeModel* model;

View file

@ -1,6 +1,6 @@
/* uefifind_main.cpp /* uefifind_main.cpp
Copyright (c) 2014, Nikolaj Schlej. All rights reserved. Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -64,7 +64,7 @@ int main(int argc, char *argv[])
return ERR_SUCCESS; return ERR_SUCCESS;
} }
else { else {
std::cout << "UEFIFind 0.2.0" << std::endl << std::endl << std::cout << "UEFIFind 0.3.0" << std::endl << std::endl <<
"Usage: uefifind {header | body | all} {list | count} pattern imagefile\n"; "Usage: uefifind {header | body | all} {list | count} pattern imagefile\n";
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
} }

View file

@ -1,6 +1,6 @@
/* uefipatch_main.cpp /* uefipatch_main.cpp
Copyright (c) 2014, Nikolaj Schlej. All rights reserved. Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -31,7 +31,7 @@ int main(int argc, char *argv[])
result = w.patchFromFile(a.arguments().at(1)); result = w.patchFromFile(a.arguments().at(1));
} }
else { else {
std::cout << "UEFIPatch 0.3.1 - UEFI image file patching utility" << std::endl << std::endl << std::cout << "UEFIPatch 0.3.2 - UEFI image file patching utility" << std::endl << std::endl <<
"Usage: UEFIPatch image_file" << std::endl << std::endl << "Usage: UEFIPatch image_file" << std::endl << std::endl <<
"Patches will be read from patches.txt file\n"; "Patches will be read from patches.txt file\n";
return ERR_SUCCESS; return ERR_SUCCESS;

64
ffs.cpp
View file

@ -23,6 +23,10 @@ const QVector<QByteArray> FFSv2Volumes =
<< EFI_INTEL_FILE_SYSTEM2_GUID << EFI_INTEL_FILE_SYSTEM2_GUID
<< EFI_SONY_FILE_SYSTEM_GUID; << EFI_SONY_FILE_SYSTEM_GUID;
const QVector<QByteArray> FFSv3Volumes =
QVector<QByteArray>()
<< EFI_FIRMWARE_FILE_SYSTEM3_GUID;
const UINT8 ffsAlignmentTable[] = const UINT8 ffsAlignmentTable[] =
{ 0, 4, 7, 9, 10, 12, 15, 16 }; { 0, 4, 7, 9, 10, 12, 15, 16 };
@ -140,7 +144,7 @@ QString sectionTypeToQString(const UINT8 type)
case EFI_SECTION_RAW: return QObject::tr("Raw"); case EFI_SECTION_RAW: return QObject::tr("Raw");
case EFI_SECTION_PEI_DEPEX: return QObject::tr("PEI dependency"); case EFI_SECTION_PEI_DEPEX: return QObject::tr("PEI dependency");
case EFI_SECTION_SMM_DEPEX: return QObject::tr("SMM dependency"); case EFI_SECTION_SMM_DEPEX: return QObject::tr("SMM dependency");
case HP_SECTION_POSTCODE: return QObject::tr("HP postcode"); case INSYDE_SECTION_POSTCODE: return QObject::tr("Insyde postcode");
case SCT_SECTION_POSTCODE: return QObject::tr("SCT postcode"); case SCT_SECTION_POSTCODE: return QObject::tr("SCT postcode");
default: return QObject::tr("Unknown"); default: return QObject::tr("Unknown");
} }
@ -151,27 +155,47 @@ UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header)
if (!header) if (!header)
return 0; return 0;
bool extended = false;
/*if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) {
extended = true;
}*/
switch (header->Type) switch (header->Type)
{ {
case EFI_SECTION_GUID_DEFINED: { case EFI_SECTION_GUID_DEFINED: {
const EFI_GUID_DEFINED_SECTION* gdsHeader = (const EFI_GUID_DEFINED_SECTION*)header; if (!extended) {
return gdsHeader->DataOffset; } const EFI_GUID_DEFINED_SECTION* gdsHeader = (const EFI_GUID_DEFINED_SECTION*)header;
case EFI_SECTION_COMPRESSION: return sizeof(EFI_COMPRESSION_SECTION); if (QByteArray((const char*)&gdsHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) {
case EFI_SECTION_DISPOSABLE: return sizeof(EFI_DISPOSABLE_SECTION); const WIN_CERTIFICATE* certificateHeader = (const WIN_CERTIFICATE*)(gdsHeader + 1);
case EFI_SECTION_PE32: return sizeof(EFI_PE32_SECTION); return gdsHeader->DataOffset + certificateHeader->Length;
case EFI_SECTION_PIC: return sizeof(EFI_PIC_SECTION); }
case EFI_SECTION_TE: return sizeof(EFI_TE_SECTION); return gdsHeader->DataOffset;
case EFI_SECTION_DXE_DEPEX: return sizeof(EFI_DXE_DEPEX_SECTION); }
case EFI_SECTION_VERSION: return sizeof(EFI_VERSION_SECTION); else {
case EFI_SECTION_USER_INTERFACE: return sizeof(EFI_USER_INTERFACE_SECTION); const EFI_GUID_DEFINED_SECTION2* gdsHeader = (const EFI_GUID_DEFINED_SECTION2*)header;
case EFI_SECTION_COMPATIBILITY16: return sizeof(EFI_COMPATIBILITY16_SECTION); if (QByteArray((const char*)&gdsHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) {
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION); const WIN_CERTIFICATE* certificateHeader = (const WIN_CERTIFICATE*)(gdsHeader + 1);
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION); return gdsHeader->DataOffset + certificateHeader->Length;
case EFI_SECTION_RAW: return sizeof(EFI_RAW_SECTION); }
case EFI_SECTION_PEI_DEPEX: return sizeof(EFI_PEI_DEPEX_SECTION); return gdsHeader->DataOffset;
case EFI_SECTION_SMM_DEPEX: return sizeof(EFI_SMM_DEPEX_SECTION); }
case HP_SECTION_POSTCODE: return sizeof(POSTCODE_SECTION); }
case SCT_SECTION_POSTCODE: return sizeof(POSTCODE_SECTION); case EFI_SECTION_COMPRESSION: return extended ? sizeof(EFI_COMPRESSION_SECTION2) : sizeof(EFI_COMPRESSION_SECTION);
default: return sizeof(EFI_COMMON_SECTION_HEADER); case EFI_SECTION_DISPOSABLE: return extended ? sizeof(EFI_DISPOSABLE_SECTION2) : sizeof(EFI_DISPOSABLE_SECTION);
case EFI_SECTION_PE32: return extended ? sizeof(EFI_PE32_SECTION2) : sizeof(EFI_PE32_SECTION);
case EFI_SECTION_PIC: return extended ? sizeof(EFI_PIC_SECTION2) : sizeof(EFI_PIC_SECTION);
case EFI_SECTION_TE: return extended ? sizeof(EFI_TE_SECTION2) : sizeof(EFI_TE_SECTION);
case EFI_SECTION_DXE_DEPEX: return extended ? sizeof(EFI_DXE_DEPEX_SECTION2) : sizeof(EFI_DXE_DEPEX_SECTION);
case EFI_SECTION_VERSION: return extended ? sizeof(EFI_VERSION_SECTION2) : sizeof(EFI_VERSION_SECTION);
case EFI_SECTION_USER_INTERFACE: return extended ? sizeof(EFI_USER_INTERFACE_SECTION2) : sizeof(EFI_USER_INTERFACE_SECTION);
case EFI_SECTION_COMPATIBILITY16: return extended ? sizeof(EFI_COMPATIBILITY16_SECTION2) : sizeof(EFI_COMPATIBILITY16_SECTION);
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return extended ? sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION2) : sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION);
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return extended ? sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION2) : sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION);
case EFI_SECTION_RAW: return extended ? sizeof(EFI_RAW_SECTION2) : sizeof(EFI_RAW_SECTION);
case EFI_SECTION_PEI_DEPEX: return extended ? sizeof(EFI_PEI_DEPEX_SECTION2) : sizeof(EFI_PEI_DEPEX_SECTION);
case EFI_SECTION_SMM_DEPEX: return extended ? sizeof(EFI_SMM_DEPEX_SECTION2) : sizeof(EFI_SMM_DEPEX_SECTION);
case INSYDE_SECTION_POSTCODE: return extended ? sizeof(POSTCODE_SECTION2) : sizeof(POSTCODE_SECTION);
case SCT_SECTION_POSTCODE: return extended ? sizeof(POSTCODE_SECTION2) : sizeof(POSTCODE_SECTION);
default: return extended ? sizeof(EFI_COMMON_SECTION_HEADER2) : sizeof(EFI_COMMON_SECTION_HEADER);
} }
} }

139
ffs.h
View file

@ -108,18 +108,23 @@ const QByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16); ("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16);
const QByteArray EFI_INTEL_FILE_SYSTEM_GUID const QByteArray EFI_INTEL_FILE_SYSTEM_GUID
("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16); ("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16);
//AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0 //Intel 1 // AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0 // Intel 1
const QByteArray EFI_INTEL_FILE_SYSTEM2_GUID const QByteArray EFI_INTEL_FILE_SYSTEM2_GUID
("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16); ("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16);
//D6A1CD70-4B33-4994-A6EA-375F2CCC5437 //Intel 2 // D6A1CD70-4B33-4994-A6EA-375F2CCC5437 // Intel 2
const QByteArray EFI_SONY_FILE_SYSTEM_GUID const QByteArray EFI_SONY_FILE_SYSTEM_GUID
("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16); ("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16);
//4F494156-AED6-4D64-A537-B8A5557BCEEC //Sony 1 // 4F494156-AED6-4D64-A537-B8A5557BCEEC // Sony 1
// Vector of volume GUIDs with FFSv2-compatible files
//Vector of volume GUIDs with FFSv2-compatible files
extern const QVector<QByteArray> FFSv2Volumes; extern const QVector<QByteArray> FFSv2Volumes;
const QByteArray EFI_FIRMWARE_FILE_SYSTEM3_GUID // 5473C07A-3DCB-4dca-BD6F-1E9689E7349A
("\x7A\xC0\x73\x54\xCB\x3D\xCA\x4D\xBD\x6F\x1E\x96\x89\xE7\x34\x9A", 16);
// Vector of volume GUIDs with FFSv3-compatible files
extern const QVector<QByteArray> FFSv3Volumes;
// Firmware volume signature // Firmware volume signature
const QByteArray EFI_FV_SIGNATURE("_FVH", 4); const QByteArray EFI_FV_SIGNATURE("_FVH", 4);
#define EFI_FV_SIGNATURE_OFFSET 0x28 #define EFI_FV_SIGNATURE_OFFSET 0x28
@ -214,21 +219,21 @@ typedef struct _EFI_FIRMWARE_VOLUME_EXT_HEADER {
// Extended header entry // Extended header entry
// The extended header entries follow each other and are // The extended header entries follow each other and are
// terminated by ExtHeaderType EFI_FV_EXT_TYPE_END // terminated by ExtHeaderType EFI_FV_EXT_TYPE_END
#define EFI_FV_EXT_TYPE_END 0x00 #define EFI_FV_EXT_TYPE_END 0x0000
typedef struct _EFI_FIRMWARE_VOLUME_EXT_ENTRY { typedef struct _EFI_FIRMWARE_VOLUME_EXT_ENTRY {
UINT16 ExtEntrySize; UINT16 ExtEntrySize;
UINT16 ExtEntryType; UINT16 ExtEntryType;
} EFI_FIRMWARE_VOLUME_EXT_ENTRY; } EFI_FIRMWARE_VOLUME_EXT_ENTRY;
// GUID that maps OEM file types to GUIDs // GUID that maps OEM file types to GUIDs
#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01 #define EFI_FV_EXT_TYPE_OEM_TYPE 0x0001
typedef struct _EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE { typedef struct _EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE {
EFI_FIRMWARE_VOLUME_EXT_ENTRY Header; EFI_FIRMWARE_VOLUME_EXT_ENTRY Header;
UINT32 TypeMask; UINT32 TypeMask;
//EFI_GUID Types[1]; //EFI_GUID Types[1];
} EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE; } EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE;
#define EFI_FV_EXT_TYPE_GUID_TYPE 0x02 #define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002
typedef struct _EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE { typedef struct _EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE {
EFI_FIRMWARE_VOLUME_EXT_ENTRY Header; EFI_FIRMWARE_VOLUME_EXT_ENTRY Header;
EFI_GUID FormatType; EFI_GUID FormatType;
@ -269,7 +274,7 @@ EFI_GUID Name;
EFI_FFS_INTEGRITY_CHECK IntegrityCheck; EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
UINT8 Type; UINT8 Type;
UINT8 Attributes; UINT8 Attributes;
UINT8 Size[3]; UINT8 Size[3]; // Set to 0xFFFFFF
UINT8 State; UINT8 State;
UINT32 ExtendedSize; UINT32 ExtendedSize;
} EFI_FFS_FILE_HEADER2; } EFI_FFS_FILE_HEADER2;
@ -302,8 +307,9 @@ UINT32 ExtendedSize;
#define EFI_FV_FILETYPE_FFS_MAX 0xFF #define EFI_FV_FILETYPE_FFS_MAX 0xFF
// File attributes // File attributes
#define FFS_ATTRIB_TAIL_PRESENT 0x01 #define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
#define FFS_ATTRIB_RECOVERY 0x02 #define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes
#define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes
#define FFS_ATTRIB_FIXED 0x04 #define FFS_ATTRIB_FIXED 0x04
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38 #define FFS_ATTRIB_DATA_ALIGNMENT 0x38
#define FFS_ATTRIB_CHECKSUM 0x40 #define FFS_ATTRIB_CHECKSUM 0x40
@ -357,6 +363,9 @@ typedef struct _EFI_COMMON_SECTION_HEADER2 {
UINT32 ExtendedSize; UINT32 ExtendedSize;
} EFI_COMMON_SECTION_HEADER2; } EFI_COMMON_SECTION_HEADER2;
// Section2 usage indicator
#define EFI_SECTION2_IS_USED 0xFFFFFF
// File section types // File section types
#define EFI_SECTION_ALL 0x00 // Impossible attribute for file in the FS #define EFI_SECTION_ALL 0x00 // Impossible attribute for file in the FS
@ -379,7 +388,7 @@ typedef struct _EFI_COMMON_SECTION_HEADER2 {
#define EFI_SECTION_PEI_DEPEX 0x1B #define EFI_SECTION_PEI_DEPEX 0x1B
#define EFI_SECTION_SMM_DEPEX 0x1C #define EFI_SECTION_SMM_DEPEX 0x1C
#define SCT_SECTION_POSTCODE 0xF0 // Specific to Phoenix SCT images #define SCT_SECTION_POSTCODE 0xF0 // Specific to Phoenix SCT images
#define HP_SECTION_POSTCODE 0x20 // Specific to HP images #define INSYDE_SECTION_POSTCODE 0x20 // Specific to Insyde images
// Compression section // Compression section
typedef struct _EFI_COMPRESSION_SECTION { typedef struct _EFI_COMPRESSION_SECTION {
@ -389,6 +398,14 @@ typedef struct _EFI_COMPRESSION_SECTION {
UINT8 CompressionType; UINT8 CompressionType;
} EFI_COMPRESSION_SECTION; } EFI_COMPRESSION_SECTION;
typedef struct _EFI_COMPRESSION_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
UINT32 UncompressedLength;
UINT8 CompressionType;
} EFI_COMPRESSION_SECTION2;
// Compression types // Compression types
#define EFI_NOT_COMPRESSED 0x00 #define EFI_NOT_COMPRESSED 0x00
#define EFI_STANDARD_COMPRESSION 0x01 #define EFI_STANDARD_COMPRESSION 0x01
@ -403,6 +420,15 @@ typedef struct _EFI_GUID_DEFINED_SECTION {
UINT16 Attributes; UINT16 Attributes;
} EFI_GUID_DEFINED_SECTION; } EFI_GUID_DEFINED_SECTION;
typedef struct _EFI_GUID_DEFINED_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
EFI_GUID SectionDefinitionGuid;
UINT16 DataOffset;
UINT16 Attributes;
} EFI_GUID_DEFINED_SECTION2;
// Attributes for GUID defined section // Attributes for GUID defined section
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 #define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 #define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
@ -417,7 +443,7 @@ const QByteArray EFI_GUIDED_SECTION_TIANO // A31280AD-481E-41B6-95E8-127F4C98477
const QByteArray EFI_GUIDED_SECTION_LZMA // EE4E5898-3914-4259-9D6E-DC7BD79403CF const QByteArray EFI_GUIDED_SECTION_LZMA // EE4E5898-3914-4259-9D6E-DC7BD79403CF
("\x98\x58\x4E\xEE\x14\x39\x59\x42\x9D\x6E\xDC\x7B\xD7\x94\x03\xCF", 16); ("\x98\x58\x4E\xEE\x14\x39\x59\x42\x9D\x6E\xDC\x7B\xD7\x94\x03\xCF", 16);
const QByteArray EFI_GUIDED_SECTION_INTEL_SIGNED //0F9D89E8-9259-4F76-A5AF-0C89E34023DF const QByteArray EFI_FIRMWARE_CONTENTS_SIGNED_GUID //0F9D89E8-9259-4F76-A5AF-0C89E34023DF
("\xE8\x89\x9D\x0F\x59\x92\x76\x4F\xA5\xAF\x0C\x89\xE3\x40\x23\xDF", 16); ("\xE8\x89\x9D\x0F\x59\x92\x76\x4F\xA5\xAF\x0C\x89\xE3\x40\x23\xDF", 16);
// Version section // Version section
@ -427,6 +453,13 @@ typedef struct _EFI_VERSION_SECTION {
UINT16 BuildNumber; UINT16 BuildNumber;
} EFI_VERSION_SECTION; } EFI_VERSION_SECTION;
typedef struct _EFI_VERSION_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
UINT16 BuildNumber;
} EFI_VERSION_SECTION2;
// Freeform subtype GUID section // Freeform subtype GUID section
typedef struct _EFI_FREEFORM_SUBTYPE_GUID_SECTION { typedef struct _EFI_FREEFORM_SUBTYPE_GUID_SECTION {
UINT8 Size[3]; UINT8 Size[3];
@ -434,6 +467,13 @@ typedef struct _EFI_FREEFORM_SUBTYPE_GUID_SECTION {
EFI_GUID SubTypeGuid; EFI_GUID SubTypeGuid;
} EFI_FREEFORM_SUBTYPE_GUID_SECTION; } EFI_FREEFORM_SUBTYPE_GUID_SECTION;
typedef struct _EFI_FREEFORM_SUBTYPE_GUID_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
EFI_GUID SubTypeGuid;
} EFI_FREEFORM_SUBTYPE_GUID_SECTION2;
// Phoenix SCT and HP postcode section // Phoenix SCT and HP postcode section
typedef struct _POSTCODE_SECTION { typedef struct _POSTCODE_SECTION {
UINT8 Size[3]; UINT8 Size[3];
@ -441,18 +481,36 @@ typedef struct _POSTCODE_SECTION {
UINT32 Postcode; UINT32 Postcode;
} POSTCODE_SECTION; } POSTCODE_SECTION;
typedef struct _POSTCODE_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
UINT32 Postcode;
} POSTCODE_SECTION2;
// Other sections // Other sections
typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION; typedef EFI_COMMON_SECTION_HEADER2 EFI_DISPOSABLE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION; typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION; typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION; typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION; typedef EFI_COMMON_SECTION_HEADER2 EFI_SMM_DEPEX_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_USER_INTERFACE_SECTION2;
//Section routines //Section routines
extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header); extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header);
@ -490,6 +548,39 @@ extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header);
/// ///
#define EFI_DEP_SOR 0x09 #define EFI_DEP_SOR 0x09
//*****************************************************************************
// UEFI Crypto-signed Stuff
//*****************************************************************************
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
#define WIN_CERT_TYPE_EFI_GUID 0x0EF1
typedef struct _WIN_CERTIFICATE {
UINT32 Length;
UINT16 Revision;
UINT16 CertificateType;
//UINT8 CertData[];
} WIN_CERTIFICATE;
typedef struct _WIN_CERTIFICATE_UEFI_GUID {
WIN_CERTIFICATE Header; // Standard WIN_CERTIFICATE
EFI_GUID CertType; // Determines format of CertData
// UINT8 CertData[]; // Certificate data follows
} WIN_CERTIFICATE_UEFI_GUID;
// WIN_CERTIFICATE_UEFI_GUID.CertType
const QByteArray EFI_CERT_TYPE_RSA2048_SHA256_GUID
("\x14\x74\x71\xA7\x16\xC6\x77\x49\x94\x20\x84\x47\x12\xA7\x35\xBF");
const QByteArray EFI_CERT_TYPE_PKCS7_GUID
("\x9D\xD2\xAF\x4A\xDF\x68\xEE\x49\x8A\xA9\x34\x7D\x37\x56\x65\xA7");
// WIN_CERTIFICATE_UEFI_GUID.CertData
typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
UINT32 HashType;
UINT8 PublicKey[256];
UINT8 Signature[256];
} EFI_CERT_BLOCK_RSA_2048_SHA256;
// Restore previous packing rules // Restore previous packing rules
#pragma pack(pop) #pragma pack(pop)

View file

@ -784,8 +784,12 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
volumeFfsVersion = 2; volumeFfsVersion = 2;
} }
//!TODO:Check for FFS v3 volume // Check for FFS v3 volume
/*if (FFSv3Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))) {
volumeIsUnknown = false;
volumeFfsVersion = 3;
}*/
// Check attributes // Check attributes
// Determine value of empty byte // Determine value of empty byte
char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00'; char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
@ -896,7 +900,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
// Check free space to be actually free // Check free space to be actually free
QByteArray freeSpace = volume.mid(fileOffset); QByteArray freeSpace = volume.mid(fileOffset);
if (freeSpace.count(empty) != freeSpace.count()) { if (freeSpace.count(empty) != freeSpace.count()) {
msg(tr("parseVolume: non-standard data found in volume's free space"), index); msg(tr("parseVolume: non-UEFI data found in volume's free space"), index);
// Search for the first non-empty byte // Search for the first non-empty byte
UINT32 i; UINT32 i;
@ -1085,7 +1089,6 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U
// Check for non-empty pad file // Check for non-empty pad file
else if (fileHeader->Type == EFI_FV_FILETYPE_PAD) { else if (fileHeader->Type == EFI_FV_FILETYPE_PAD) {
parseAsNonEmptyPadFile = true; parseAsNonEmptyPadFile = true;
msg(tr("parseFile: non-empty pad-file contents will be destroyed after volume modifications"), index);
} }
// Get info // Get info
@ -1139,7 +1142,11 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U
} }
// ... and all bytes after as a padding // ... and all bytes after as a padding
QByteArray padding = body.mid(i); QByteArray padding = body.mid(i);
model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, QByteArray(), index, mode); QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, QByteArray(), index, mode);
// Show message
msg(tr("parseFile: non-empty pad-file contents will be destroyed after volume modifications"), dataIndex);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -1360,6 +1367,9 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
bool msgUnknownGuid = false; bool msgUnknownGuid = false;
bool msgInvalidCrc = false; bool msgInvalidCrc = false;
bool msgUnknownAuth = false; bool msgUnknownAuth = false;
bool msgSigned = false;
bool msgUnknownSignature = false;
bool msgUnknownUefiGuidSignature = false;
const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader; const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader;
header = section.left(sizeof(EFI_GUID_DEFINED_SECTION)); header = section.left(sizeof(EFI_GUID_DEFINED_SECTION));
@ -1368,7 +1378,6 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(header.constData()); guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(header.constData());
body = section.mid(guidDefinedSectionHeader->DataOffset, sectionSize - guidDefinedSectionHeader->DataOffset); body = section.mid(guidDefinedSectionHeader->DataOffset, sectionSize - guidDefinedSectionHeader->DataOffset);
QByteArray processed = body; QByteArray processed = body;
QByteArray signature;
// Get info // Get info
name = guidToQString(guidDefinedSectionHeader->SectionDefinitionGuid); name = guidToQString(guidDefinedSectionHeader->SectionDefinitionGuid);
@ -1418,11 +1427,39 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
else else
info += tr("\nCompression type: unknown"); info += tr("\nCompression type: unknown");
} }
// Intel signed section // Signed section
else if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_INTEL_SIGNED) { else if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) {
UINT32 signatureSize = *(const UINT32*)body.constData(); msgSigned = true;
signature = body.left(signatureSize); const WIN_CERTIFICATE* certificateHeader = (const WIN_CERTIFICATE*)body.constData();
processed = body.mid(signatureSize); if (certificateHeader->CertificateType == WIN_CERT_TYPE_EFI_GUID) {
info += tr("\nSignature type: UEFI");
const WIN_CERTIFICATE_UEFI_GUID* guidCertificateHeader = (const WIN_CERTIFICATE_UEFI_GUID*)certificateHeader;
if (QByteArray((const char*)&guidCertificateHeader->CertType, sizeof(EFI_GUID)) == EFI_CERT_TYPE_RSA2048_SHA256_GUID) {
info += tr("\nSignature subtype: RSA2048/SHA256");
// TODO: show signature info in Information panel
}
else if (QByteArray((const char*)&guidCertificateHeader->CertType, sizeof(EFI_GUID)) == EFI_CERT_TYPE_PKCS7_GUID) {
info += tr("\nSignature subtype: PCKS7");
// TODO: show signature info in Information panel
}
else {
info += tr("\nSignature subtype: unknown");
msgUnknownUefiGuidSignature = true;
}
}
else if (certificateHeader->CertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
info += tr("\nSignature type: PCKS7");
// TODO: show signature info in Information panel
}
else {
info += tr("\nSignature type: unknown");
msgUnknownSignature = true;
}
// Add additional to the header
header.append(body.left(certificateHeader->Length));
// Get new body
processed = body = body.mid(certificateHeader->Length);
} }
// Unknown GUIDed section // Unknown GUIDed section
else { else {
@ -1461,18 +1498,17 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
msg(tr("parseSection: GUID defined section with unknown authentication method"), index); msg(tr("parseSection: GUID defined section with unknown authentication method"), index);
if (msgInvalidCrc) if (msgInvalidCrc)
msg(tr("parseSection: GUID defined section with invalid CRC32"), index); msg(tr("parseSection: GUID defined section with invalid CRC32"), index);
if (msgSigned)
msg(tr("parseSection: signature may become invalid after any modification"), index);
if (msgUnknownUefiGuidSignature)
msg(tr("parseSection: GUID defined section with unknown signature subtype"), index);
if (msgUnknownSignature)
msg(tr("parseSection: GUID defined section with unknown signature type"), index);
if (!parseCurrentSection) { if (!parseCurrentSection) {
msg(tr("parseSection: GUID defined section can not be processed"), index); msg(tr("parseSection: GUID defined section can not be processed"), index);
} }
else { // Parse processed data else { // Parse processed data
if (!signature.isEmpty()) {
// Add Intel signature padding to the tree
QModelIndex signatureIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Intel signature"), "", tr("Full size: %1h (%2)").hexarg(signature.size()).arg(signature.size()), QByteArray(), signature, QByteArray(), index, mode);
// Show message
msg(tr("parseSection: Intel signature may become invalid after any modification of the following sections"), signatureIndex);
}
result = parseSections(processed, index); result = parseSections(processed, index);
if (result) if (result)
return result; return result;
@ -1824,7 +1860,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
} break; } break;
case SCT_SECTION_POSTCODE: case SCT_SECTION_POSTCODE:
case HP_SECTION_POSTCODE: { case INSYDE_SECTION_POSTCODE: {
header = section.left(sizeof(POSTCODE_SECTION)); header = section.left(sizeof(POSTCODE_SECTION));
body = section.mid(sizeof(POSTCODE_SECTION), sectionSize - sizeof(POSTCODE_SECTION)); body = section.mid(sizeof(POSTCODE_SECTION), sectionSize - sizeof(POSTCODE_SECTION));
@ -3358,7 +3394,7 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
} }
// Check for Intel signed section // Check for Intel signed section
if (guidDefinedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED if (guidDefinedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED
&& QByteArray((const char*)&guidDefinedHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_INTEL_SIGNED) { && QByteArray((const char*)&guidDefinedHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) {
msg(tr("reconstructSection: GUID defined section signature can become invalid") msg(tr("reconstructSection: GUID defined section signature can become invalid")
.arg(guidToQString(guidDefinedHeader->SectionDefinitionGuid)), index); .arg(guidToQString(guidDefinedHeader->SectionDefinitionGuid)), index);
} }

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.1")) version(tr("0.20.2"))
{ {
clipboard = QApplication::clipboard(); clipboard = QApplication::clipboard();
@ -349,7 +349,7 @@ void UEFITool::replace(const UINT8 mode)
} }
else if (model->type(index) == Types::Section) { else if (model->type(index) == Types::Section) {
if (mode == REPLACE_MODE_AS_IS) { if (mode == REPLACE_MODE_AS_IS) {
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 (*.sct *.bin);;All files (*)");
} }
else if (mode == REPLACE_MODE_BODY) { else if (mode == REPLACE_MODE_BODY) {
if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE) if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)