mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-24 08:58:23 +08:00
Add support for IFWI 1.7 and 2.0 layouts, improve ME parser, fix small issues spotted by static analysis
This commit is contained in:
parent
d95e533441
commit
90ff19692d
@ -12,6 +12,7 @@ SET(PROJECT_SOURCES
|
||||
../common/ffs.cpp
|
||||
../common/nvram.cpp
|
||||
../common/nvramparser.cpp
|
||||
../common/meparser.cpp
|
||||
../common/ffsparser.cpp
|
||||
../common/ffsreport.cpp
|
||||
../common/peimage.cpp
|
||||
@ -83,6 +84,6 @@ SET(PROJECT_HEADERS
|
||||
../version.h
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS(-DU_ENABLE_NVRAM_PARSING_SUPPORT -DU_ENABLE_FIT_PARSING_SUPPORT -DU_ENABLE_GUID_DATABASE_SUPPORT)
|
||||
ADD_DEFINITIONS(-DU_ENABLE_NVRAM_PARSING_SUPPORT -DU_ENABLE_ME_PARSING_SUPPORT -DU_ENABLE_FIT_PARSING_SUPPORT -DU_ENABLE_GUID_DATABASE_SUPPORT)
|
||||
|
||||
ADD_EXECUTABLE(UEFIExtract ${PROJECT_SOURCES} ${PROJECT_HEADERS})
|
@ -17,35 +17,42 @@
|
||||
|
||||
class UEFIToolApplication : public QApplication
|
||||
{
|
||||
UEFITool tool;
|
||||
UEFITool* tool;
|
||||
|
||||
public:
|
||||
UEFIToolApplication(int &argc, char **argv)
|
||||
: QApplication(argc, argv)
|
||||
{
|
||||
setOrganizationName("LongSoft");
|
||||
setOrganizationDomain("longsoft.org");
|
||||
setApplicationName("UEFITool");
|
||||
setApplicationName("UEFITool NE");
|
||||
|
||||
tool = new UEFITool();
|
||||
}
|
||||
|
||||
virtual ~UEFIToolApplication() {
|
||||
delete tool;
|
||||
}
|
||||
|
||||
virtual bool event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
|
||||
tool->openImageFile(openEvent->file());
|
||||
}
|
||||
|
||||
return QApplication::event(event);
|
||||
}
|
||||
|
||||
int startup()
|
||||
{
|
||||
tool.setProgramPath(arguments().at(0));
|
||||
tool->setProgramPath(arguments().at(0));
|
||||
if (arguments().length() > 1)
|
||||
tool.openImageFile(arguments().at(1));
|
||||
tool.show();
|
||||
tool->openImageFile(arguments().at(1));
|
||||
tool->show();
|
||||
|
||||
return exec();
|
||||
}
|
||||
|
||||
bool event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
|
||||
tool.openImageFile(openEvent->file());
|
||||
}
|
||||
|
||||
return QApplication::event(event);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -102,7 +102,7 @@ static int snapUpSize (int i) {
|
||||
|
||||
/* int balloc (bstring b, int len)
|
||||
*
|
||||
* Increase the size of the memory backing the bstring b to at least len.
|
||||
* Increase the size of the memory backing the bstring b to at least olen + 1.
|
||||
*/
|
||||
int balloc (bstring b, int olen) {
|
||||
int len;
|
||||
@ -124,14 +124,14 @@ int balloc (bstring b, int olen) {
|
||||
|
||||
reallocStrategy:;
|
||||
|
||||
x = (unsigned char *) bstr__realloc (b->data, (size_t) len);
|
||||
x = (unsigned char *) bstr__realloc (b->data, (size_t) len + 1);
|
||||
if (x == NULL) {
|
||||
|
||||
/* Since we failed, try allocating the tighest possible
|
||||
allocation */
|
||||
|
||||
len = olen;
|
||||
x = (unsigned char *) bstr__realloc (b->data, (size_t) olen);
|
||||
x = (unsigned char *) bstr__realloc (b->data, (size_t) len + 1);
|
||||
if (NULL == x) {
|
||||
return BSTR_ERR;
|
||||
}
|
||||
@ -142,7 +142,7 @@ int balloc (bstring b, int olen) {
|
||||
the extra bytes that are allocated, but not considered part of
|
||||
the string */
|
||||
|
||||
if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) {
|
||||
if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len + 1))) {
|
||||
|
||||
/* Perhaps there is no available memory for the two
|
||||
allocations to be in memory at once */
|
||||
|
@ -15,6 +15,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "ustring.h"
|
||||
#include "ubytearray.h"
|
||||
|
||||
// Make sure we use right packing rules
|
||||
#pragma pack(push,1)
|
||||
|
@ -101,8 +101,7 @@ bool ustringToGuid(const UString & str, EFI_GUID & guid)
|
||||
|
||||
UString fileTypeToUString(const UINT8 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case EFI_FV_FILETYPE_RAW: return UString("Raw");
|
||||
case EFI_FV_FILETYPE_FREEFORM: return UString("Freeform");
|
||||
case EFI_FV_FILETYPE_SECURITY_CORE: return UString("SEC core");
|
||||
@ -119,14 +118,13 @@ UString fileTypeToUString(const UINT8 type)
|
||||
case EFI_FV_FILETYPE_MM_STANDALONE: return UString("MM standalone module");
|
||||
case EFI_FV_FILETYPE_MM_CORE_STANDALONE: return UString("MM standalone core");
|
||||
case EFI_FV_FILETYPE_PAD: return UString("Pad");
|
||||
default: return UString("Unknown");
|
||||
default: return usprintf("Unknown %u", type);
|
||||
};
|
||||
}
|
||||
|
||||
UString sectionTypeToUString(const UINT8 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case EFI_SECTION_COMPRESSION: return UString("Compressed");
|
||||
case EFI_SECTION_GUID_DEFINED: return UString("GUID defined");
|
||||
case EFI_SECTION_DISPOSABLE: return UString("Disposable");
|
||||
@ -144,7 +142,73 @@ UString sectionTypeToUString(const UINT8 type)
|
||||
case EFI_SECTION_MM_DEPEX: return UString("MM dependency");
|
||||
case INSYDE_SECTION_POSTCODE: return UString("Insyde postcode");
|
||||
case PHOENIX_SECTION_POSTCODE: return UString("Phoenix postcode");
|
||||
default: return UString("Unknown");
|
||||
default: return usprintf("Unknown %u", type);
|
||||
}
|
||||
}
|
||||
|
||||
UString bpdtEntryTypeToUString(const UINT16 type)
|
||||
{
|
||||
switch (type) {
|
||||
case BPDT_ENTRY_TYPE_OEM_SMIP: return UString("OEM SMIP");
|
||||
case BPDT_ENTRY_TYPE_OEM_RBE: return UString("CSE RBE");
|
||||
case BPDT_ENTRY_TYPE_CSE_BUP: return UString("CSE BUP");
|
||||
case BPDT_ENTRY_TYPE_UCODE: return UString("uCode");
|
||||
case BPDT_ENTRY_TYPE_IBB: return UString("IBB");
|
||||
case BPDT_ENTRY_TYPE_SBPDT: return UString("S-BPDT");
|
||||
case BPDT_ENTRY_TYPE_OBB: return UString("OBB");
|
||||
case BPDT_ENTRY_TYPE_CSE_MAIN: return UString("CSE Main");
|
||||
case BPDT_ENTRY_TYPE_ISH: return UString("ISH");
|
||||
case BPDT_ENTRY_TYPE_CSE_IDLM: return UString("CSE IDLM");
|
||||
case BPDT_ENTRY_TYPE_IFP_OVERRIDE: return UString("IFP Override");
|
||||
case BPDT_ENTRY_TYPE_DEBUG_TOKENS: return UString("Debug Tokens");
|
||||
case BPDT_ENTRY_TYPE_USF_PHY_CONFIG: return UString("USF Phy Config");
|
||||
case BPDT_ENTRY_TYPE_USB_GPP_LUN_ID: return UString("USF GPP LUN ID");
|
||||
case BPDT_ENTRY_TYPE_PMC: return UString("PMC");
|
||||
case BPDT_ENTRY_TYPE_IUNIT: return UString("iUnit");
|
||||
case BPDT_ENTRY_TYPE_NVM_CONFIG: return UString("NVM Config");
|
||||
case BPDT_ENTRY_TYPE_UEP: return UString("UEP");
|
||||
case BPDT_ENTRY_TYPE_WLAN_UCODE: return UString("WLAN uCode");
|
||||
case BPDT_ENTRY_TYPE_LOCL_SPRITES: return UString("LOCL Sprites");
|
||||
case BPDT_ENTRY_TYPE_OEM_KEY_MANIFEST: return UString("OEM Key Manifest");
|
||||
case BPDT_ENTRY_TYPE_DEFAULTS: return UString("Defaults");
|
||||
case BPDT_ENTRY_TYPE_PAVP: return UString("PAVP");
|
||||
case BPDT_ENTRY_TYPE_TCSS_FW_IOM: return UString("TCSS FW IOM");
|
||||
case BPDT_ENTRY_TYPE_TCSS_FW_PHY: return UString("TCSS FW PHY");
|
||||
case BPDT_ENTRY_TYPE_TBT: return UString("TCSS TBT");
|
||||
default: return usprintf("Unknown %u", type);
|
||||
}
|
||||
}
|
||||
|
||||
UString cpdExtensionTypeToUstring(const UINT32 type)
|
||||
{
|
||||
switch (type) {
|
||||
case CPD_EXT_TYPE_SYSTEM_INFO: return UString("System Info");
|
||||
case CPD_EXT_TYPE_INIT_SCRIPT: return UString("Init Script");
|
||||
case CPD_EXT_TYPE_FEATURE_PERMISSIONS: return UString("Feature Permissions");
|
||||
case CPD_EXT_TYPE_PARTITION_INFO: return UString("Partition Info");
|
||||
case CPD_EXT_TYPE_SHARED_LIB_ATTRIBUTES: return UString("Shared Lib Attributes");
|
||||
case CPD_EXT_TYPE_PROCESS_ATTRIBUTES: return UString("Process Attributes");
|
||||
case CPD_EXT_TYPE_THREAD_ATTRIBUTES: return UString("Thread Attributes");
|
||||
case CPD_EXT_TYPE_DEVICE_TYPE: return UString("Device Type");
|
||||
case CPD_EXT_TYPE_MMIO_RANGE: return UString("MMIO Range");
|
||||
case CPD_EXT_TYPE_SPEC_FILE_PRODUCER: return UString("Spec File Producer");
|
||||
case CPD_EXT_TYPE_MODULE_ATTRIBUTES: return UString("Module Attributes");
|
||||
case CPD_EXT_TYPE_LOCKED_RANGES: return UString("Locked Ranges");
|
||||
case CPD_EXT_TYPE_CLIENT_SYSTEM_INFO: return UString("Client System Info");
|
||||
case CPD_EXT_TYPE_USER_INFO: return UString("User Info");
|
||||
case CPD_EXT_TYPE_KEY_MANIFEST: return UString("Key Manifest");
|
||||
case CPD_EXT_TYPE_SIGNED_PACKAGE_INFO: return UString("Signed Package Info");
|
||||
case CPD_EXT_TYPE_ANTI_CLONING_SKU_ID: return UString("Anti-cloning SKU ID");
|
||||
case CPD_EXT_TYPE_CAVS: return UString("cAVS");
|
||||
case CPD_EXT_TYPE_IMR_INFO: return UString("IMR Info");
|
||||
case CPD_EXT_TYPE_RCIP_INFO: return UString("RCIP Info");
|
||||
case CPD_EXT_TYPE_BOOT_POLICY: return UString("Boot Policy");
|
||||
case CPD_EXT_TYPE_SECURE_TOKEN: return UString("Secure Token");
|
||||
case CPD_EXT_TYPE_IFWI_PARTITION_MANIFEST: return UString("IFWI Partition Manifest");
|
||||
case CPD_EXT_TYPE_FD_HASH: return UString("FD Hash");
|
||||
case CPD_EXT_TYPE_IOM_METADATA: return UString("IOM Metadata");
|
||||
case CPD_EXT_TYPE_MGP_METADATA: return UString("MGP Metadata");
|
||||
case CPD_EXT_TYPE_TBT_METADATA: return UString("TBT Metadata");
|
||||
default: return usprintf("Unknown %u", type);
|
||||
}
|
||||
}
|
||||
|
218
common/ffs.h
218
common/ffs.h
@ -26,8 +26,8 @@ extern UString guidToUString(const EFI_GUID& guid, bool convertToString = true);
|
||||
extern bool ustringToGuid(const UString& str, EFI_GUID& guid);
|
||||
extern UString fileTypeToUString(const UINT8 type);
|
||||
extern UString sectionTypeToUString(const UINT8 type);
|
||||
|
||||
|
||||
extern UString bpdtEntryTypeToUString(const UINT16 type);
|
||||
extern UString cpdExtensionTypeToUstring(const UINT32 type);
|
||||
//*****************************************************************************
|
||||
// EFI Capsule
|
||||
//*****************************************************************************
|
||||
@ -586,6 +586,220 @@ typedef struct X86_RESET_VECTOR_DATA_ {
|
||||
|
||||
#define X86_RESET_VECTOR_DATA_UNPOPULATED 0x12345678
|
||||
|
||||
//*****************************************************************************
|
||||
// IFWI
|
||||
//*****************************************************************************
|
||||
|
||||
// BPDT
|
||||
#define BPDT_GREEN_SIGNATURE 0x000055AA
|
||||
#define BPDT_YELLOW_SIGNATURE 0x00AA55AA
|
||||
|
||||
typedef struct BPDT_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT16 NumEntries;
|
||||
UINT8 HeaderVersion;
|
||||
UINT8 RedundancyFlag; // Reserved zero in version 1
|
||||
UINT32 Checksum;
|
||||
UINT32 IfwiVersion;
|
||||
UINT16 FitcMajor;
|
||||
UINT16 FitcMinor;
|
||||
UINT16 FitcHotfix;
|
||||
UINT16 FitcBuild;
|
||||
} BPDT_HEADER;
|
||||
|
||||
#define BPDT_HEADER_VERSION_1 1
|
||||
#define BPDT_HEADER_VERSION_2 2
|
||||
|
||||
typedef struct BPDT_ENTRY_ {
|
||||
UINT32 Type : 16;
|
||||
UINT32 SplitSubPartitionFirstPart : 1;
|
||||
UINT32 SplitSubPartitionSecondPart : 1;
|
||||
UINT32 CodeSubPartition : 1;
|
||||
UINT32 UmaCachable : 1;
|
||||
UINT32 Reserved: 12;
|
||||
UINT32 Offset;
|
||||
UINT32 Size;
|
||||
} BPDT_ENTRY;
|
||||
|
||||
#define BPDT_ENTRY_TYPE_OEM_SMIP 0
|
||||
#define BPDT_ENTRY_TYPE_OEM_RBE 1
|
||||
#define BPDT_ENTRY_TYPE_CSE_BUP 2
|
||||
#define BPDT_ENTRY_TYPE_UCODE 3
|
||||
#define BPDT_ENTRY_TYPE_IBB 4
|
||||
#define BPDT_ENTRY_TYPE_SBPDT 5
|
||||
#define BPDT_ENTRY_TYPE_OBB 6
|
||||
#define BPDT_ENTRY_TYPE_CSE_MAIN 7
|
||||
#define BPDT_ENTRY_TYPE_ISH 8
|
||||
#define BPDT_ENTRY_TYPE_CSE_IDLM 9
|
||||
#define BPDT_ENTRY_TYPE_IFP_OVERRIDE 10
|
||||
#define BPDT_ENTRY_TYPE_DEBUG_TOKENS 11
|
||||
#define BPDT_ENTRY_TYPE_USF_PHY_CONFIG 12
|
||||
#define BPDT_ENTRY_TYPE_USB_GPP_LUN_ID 13
|
||||
#define BPDT_ENTRY_TYPE_PMC 14
|
||||
#define BPDT_ENTRY_TYPE_IUNIT 15
|
||||
#define BPDT_ENTRY_TYPE_NVM_CONFIG 16
|
||||
#define BPDT_ENTRY_TYPE_UEP 17
|
||||
#define BPDT_ENTRY_TYPE_WLAN_UCODE 18
|
||||
#define BPDT_ENTRY_TYPE_LOCL_SPRITES 19
|
||||
#define BPDT_ENTRY_TYPE_OEM_KEY_MANIFEST 20
|
||||
#define BPDT_ENTRY_TYPE_DEFAULTS 21
|
||||
#define BPDT_ENTRY_TYPE_PAVP 22
|
||||
#define BPDT_ENTRY_TYPE_TCSS_FW_IOM 23
|
||||
#define BPDT_ENTRY_TYPE_TCSS_FW_PHY 24
|
||||
#define BPDT_ENTRY_TYPE_TBT 25
|
||||
#define BPDT_LAST_KNOWN_ENTRY_TYPE BPDT_ENTRY_TYPE_TBT
|
||||
|
||||
// CPD
|
||||
#define CPD_SIGNATURE 0x44504324 //$CPD
|
||||
|
||||
typedef struct CPD_REV1_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT32 NumEntries;
|
||||
UINT8 HeaderVersion; // 1
|
||||
UINT8 EntryVersion;
|
||||
UINT8 HeaderLength;
|
||||
UINT8 HeaderChecksum;
|
||||
UINT8 ShortName[4];
|
||||
} CPD_REV1_HEADER;
|
||||
|
||||
typedef struct CPD_REV2_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT32 NumEntries;
|
||||
UINT8 HeaderVersion; // 2
|
||||
UINT8 EntryVersion;
|
||||
UINT8 HeaderLength;
|
||||
UINT8 Reserved;
|
||||
UINT8 ShortName[4];
|
||||
UINT32 Checksum;
|
||||
} CPD_REV2_HEADER;
|
||||
|
||||
typedef struct CPD_ENTRY_ {
|
||||
UINT8 EntryName[12];
|
||||
struct {
|
||||
UINT32 Offset : 25;
|
||||
UINT32 HuffmanCompressed : 1;
|
||||
UINT32 Reserved : 6;
|
||||
} Offset;
|
||||
UINT32 Length;
|
||||
UINT32 Reserved;
|
||||
} CPD_ENTRY;
|
||||
|
||||
typedef struct CPD_MANIFEST_HEADER_ {
|
||||
UINT32 HeaderType;
|
||||
UINT32 HeaderLength;
|
||||
UINT32 HeaderVersion;
|
||||
UINT32 Flags;
|
||||
UINT32 Vendor;
|
||||
UINT32 Date;
|
||||
UINT32 Size;
|
||||
UINT32 HeaderId;
|
||||
UINT32 Reserved1;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
UINT16 VersionBugfix;
|
||||
UINT16 VersionBuild;
|
||||
UINT32 SecurityVersion;
|
||||
UINT8 Reserved2[8];
|
||||
UINT8 Reserved3[64];
|
||||
UINT32 ModulusSize;
|
||||
UINT32 ExponentSize;
|
||||
//manifest_rsa_key_t public_key;
|
||||
//manifest_signature_t signature;
|
||||
} CPD_MANIFEST_HEADER;
|
||||
|
||||
typedef struct CPD_EXTENTION_HEADER_ {
|
||||
UINT32 Type;
|
||||
UINT32 Length;
|
||||
} CPD_EXTENTION_HEADER;
|
||||
|
||||
#define CPD_EXT_TYPE_SYSTEM_INFO 0
|
||||
#define CPD_EXT_TYPE_INIT_SCRIPT 1
|
||||
#define CPD_EXT_TYPE_FEATURE_PERMISSIONS 2
|
||||
#define CPD_EXT_TYPE_PARTITION_INFO 3
|
||||
#define CPD_EXT_TYPE_SHARED_LIB_ATTRIBUTES 4
|
||||
#define CPD_EXT_TYPE_PROCESS_ATTRIBUTES 5
|
||||
#define CPD_EXT_TYPE_THREAD_ATTRIBUTES 6
|
||||
#define CPD_EXT_TYPE_DEVICE_TYPE 7
|
||||
#define CPD_EXT_TYPE_MMIO_RANGE 8
|
||||
#define CPD_EXT_TYPE_SPEC_FILE_PRODUCER 9
|
||||
#define CPD_EXT_TYPE_MODULE_ATTRIBUTES 10
|
||||
#define CPD_EXT_TYPE_LOCKED_RANGES 11
|
||||
#define CPD_EXT_TYPE_CLIENT_SYSTEM_INFO 12
|
||||
#define CPD_EXT_TYPE_USER_INFO 13
|
||||
#define CPD_EXT_TYPE_KEY_MANIFEST 14
|
||||
#define CPD_EXT_TYPE_SIGNED_PACKAGE_INFO 15
|
||||
#define CPD_EXT_TYPE_ANTI_CLONING_SKU_ID 16
|
||||
#define CPD_EXT_TYPE_CAVS 17
|
||||
#define CPD_EXT_TYPE_IMR_INFO 18
|
||||
#define CPD_EXT_TYPE_BOOT_POLICY 19
|
||||
#define CPD_EXT_TYPE_RCIP_INFO 20
|
||||
#define CPD_EXT_TYPE_SECURE_TOKEN 21
|
||||
#define CPD_EXT_TYPE_IFWI_PARTITION_MANIFEST 22
|
||||
#define CPD_EXT_TYPE_FD_HASH 23
|
||||
#define CPD_EXT_TYPE_IOM_METADATA 24
|
||||
#define CPD_EXT_TYPE_MGP_METADATA 25
|
||||
#define CPD_EXT_TYPE_TBT_METADATA 26
|
||||
#define CPD_LAST_KNOWN_EXT_TYPE CPD_EXT_TYPE_TBT_METADATA
|
||||
|
||||
typedef struct CPD_EXT_SIGNED_PACKAGE_INFO_MODULE_ {
|
||||
UINT8 Name[12];
|
||||
UINT8 Type;
|
||||
UINT8 HashAlgorithm;
|
||||
UINT16 HashSize;
|
||||
UINT32 MetadataSize;
|
||||
UINT8 MetadataHash[32];
|
||||
} CPD_EXT_SIGNED_PACKAGE_INFO_MODULE;
|
||||
|
||||
typedef struct CPD_EXT_SIGNED_PACKAGE_INFO_ {
|
||||
UINT32 ExtensionType;
|
||||
UINT32 ExtensionLength;
|
||||
UINT8 PackageName[4];
|
||||
UINT32 Vcn;
|
||||
UINT8 UsageBitmap[16];
|
||||
UINT32 Svn;
|
||||
UINT8 Reserved[16];
|
||||
// EXT_SIGNED_PACKAGE_INFO_MODULE Modules[];
|
||||
} CPD_EXT_SIGNED_PACKAGE_INFO;
|
||||
|
||||
typedef struct CPD_EXT_MODULE_ATTRIBUTES_ {
|
||||
UINT32 ExtensionType;
|
||||
UINT32 ExtensionLength;
|
||||
UINT8 CompressionType;
|
||||
UINT8 Reserved[3];
|
||||
UINT32 UncompressedSize;
|
||||
UINT32 CompressedSize;
|
||||
UINT32 GlobalModuleId;
|
||||
UINT8 ImageHash[32];
|
||||
} CPD_EXT_MODULE_ATTRIBUTES;
|
||||
|
||||
#define CPD_EXT_MODULE_COMPRESSION_TYPE_UNCOMPRESSED 0
|
||||
#define CPD_EXT_MODULE_COMPRESSION_TYPE_HUFFMAN 1
|
||||
#define CPD_EXT_MODULE_COMPRESSION_TYPE_LZMA 2
|
||||
|
||||
typedef struct CPD_EXT_IFWI_PARTITION_MANIFEST_ {
|
||||
UINT32 ExtensionType;
|
||||
UINT32 ExtensionLength;
|
||||
UINT8 PartitionName[4];
|
||||
UINT32 CompletePartitionLength;
|
||||
UINT16 PartitionVersionMinor;
|
||||
UINT16 PartitionVersionMajor;
|
||||
UINT32 DataFormatVersion;
|
||||
UINT32 InstanceId;
|
||||
UINT32 SupportMultipleInstances : 1;
|
||||
UINT32 SupportApiVersionBasedUpdate : 1;
|
||||
UINT32 ActionOnUpdate : 2;
|
||||
UINT32 ObeyFullUpdateRules : 1;
|
||||
UINT32 IfrEnableOnly : 1;
|
||||
UINT32 AllowCrossPointUpdate : 1;
|
||||
UINT32 AllowCrossHotfixUpdate : 1;
|
||||
UINT32 PartialUpdateOnly : 1;
|
||||
UINT32 ReservedFlags : 23;
|
||||
UINT32 HashAlgorithm : 8;
|
||||
UINT32 HashSize : 24;
|
||||
UINT8 CompletePartitionHash[32];
|
||||
UINT8 Reserved[20];
|
||||
} CPD_EXT_IFWI_PARTITION_MANIFEST;
|
||||
|
||||
// Restore previous packing rules
|
||||
#pragma pack(pop)
|
||||
|
||||
|
@ -39,13 +39,14 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
namespace Qt {
|
||||
enum GlobalColor {
|
||||
red = 7,
|
||||
green = 8,
|
||||
cyan = 10,
|
||||
yellow = 12,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
// Region info structure definition
|
||||
// Region info
|
||||
struct REGION_INFO {
|
||||
UINT32 offset;
|
||||
UINT32 length;
|
||||
@ -54,12 +55,28 @@ struct REGION_INFO {
|
||||
friend bool operator< (const REGION_INFO & lhs, const REGION_INFO & rhs){ return lhs.offset < rhs.offset; }
|
||||
};
|
||||
|
||||
// BPDT partition info
|
||||
struct BPDT_PARTITION_INFO {
|
||||
BPDT_ENTRY ptEntry;
|
||||
UINT8 type;
|
||||
UModelIndex index;
|
||||
friend bool operator< (const BPDT_PARTITION_INFO & lhs, const BPDT_PARTITION_INFO & rhs){ return lhs.ptEntry.Offset < rhs.ptEntry.Offset; }
|
||||
};
|
||||
|
||||
// CPD partition info
|
||||
struct CPD_PARTITION_INFO {
|
||||
CPD_ENTRY ptEntry;
|
||||
UINT8 type;
|
||||
UModelIndex index;
|
||||
friend bool operator< (const CPD_PARTITION_INFO & lhs, const CPD_PARTITION_INFO & rhs){ return lhs.ptEntry.Offset.Offset < rhs.ptEntry.Offset.Offset; }
|
||||
};
|
||||
|
||||
// Constructor
|
||||
FfsParser::FfsParser(TreeModel* treeModel) : model(treeModel),
|
||||
imageBase(0), addressDiff(0x100000000ULL),
|
||||
bgAcmFound(false), bgKeyManifestFound(false), bgBootPolicyFound(false), bgProtectedRegionsBase(0) {
|
||||
nvramParser = new NvramParser(treeModel, this);
|
||||
meParser = new MeParser(treeModel);
|
||||
meParser = new MeParser(treeModel, this);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -900,6 +917,23 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
|
||||
msg(usprintf("%s: microcode header parsing failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
|
||||
}
|
||||
}
|
||||
else if (itemType == Types::BpdtStore) {
|
||||
UByteArray bpdtStore = data.mid(itemOffset, itemSize);
|
||||
|
||||
// Get info
|
||||
name = UString("BPDT region");
|
||||
info = usprintf("Full size: %Xh (%u)", bpdtStore.size(), bpdtStore.size());
|
||||
|
||||
// Add tree item
|
||||
UModelIndex bpdtIndex = model->addItem(headerSize + itemOffset, Types::BpdtStore, 0, name, UString(), info, UByteArray(), bpdtStore, UByteArray(), Fixed, index);
|
||||
|
||||
// Parse BPDT region
|
||||
UModelIndex bpdtPtIndex;
|
||||
result = parseBpdtRegion(bpdtStore, 0, 0, bpdtIndex, bpdtPtIndex);
|
||||
if (result) {
|
||||
msg(usprintf("%s: BPDT store parsing failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return U_UNKNOWN_ITEM_TYPE;
|
||||
}
|
||||
@ -937,6 +971,12 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
|
||||
case Types::Microcode:
|
||||
// Parsing already done
|
||||
break;
|
||||
case Types::BpdtStore:
|
||||
// Parsing already done
|
||||
break;
|
||||
case Types::BpdtPartition:
|
||||
// Parsing already done
|
||||
break;
|
||||
case Types::Padding:
|
||||
// No parsing required
|
||||
break;
|
||||
@ -1226,6 +1266,48 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
|
||||
nextItemOffset = offset - EFI_FV_SIGNATURE_OFFSET;
|
||||
break;
|
||||
}
|
||||
else if (readUnaligned(currentPos) == BPDT_GREEN_SIGNATURE || readUnaligned(currentPos) == BPDT_YELLOW_SIGNATURE) {
|
||||
// Check data size
|
||||
if (restSize < sizeof(BPDT_HEADER))
|
||||
continue;
|
||||
|
||||
const BPDT_HEADER *bpdtHeader = (const BPDT_HEADER *)currentPos;
|
||||
// Check version
|
||||
if (bpdtHeader->HeaderVersion != BPDT_HEADER_VERSION_1) // IFWI 2.0 only for now
|
||||
continue;
|
||||
|
||||
UINT32 ptBodySize = bpdtHeader->NumEntries * sizeof(BPDT_ENTRY);
|
||||
UINT32 ptSize = sizeof(BPDT_HEADER) + ptBodySize;
|
||||
// Check data size again
|
||||
if (restSize < ptSize)
|
||||
continue;
|
||||
|
||||
UINT32 sizeCandidate = 0;
|
||||
// Parse partition table
|
||||
const BPDT_ENTRY* firstPtEntry = (const BPDT_ENTRY*)((const UINT8*)bpdtHeader + sizeof(BPDT_HEADER));
|
||||
for (UINT16 i = 0; i < bpdtHeader->NumEntries; i++) {
|
||||
// Populate entry header
|
||||
const BPDT_ENTRY* ptEntry = firstPtEntry + i;
|
||||
// Check that entry is present in the image
|
||||
if (ptEntry->Offset != 0
|
||||
&& ptEntry->Offset != 0xFFFFFFFF
|
||||
&& ptEntry->Size != 0
|
||||
&& sizeCandidate < ptEntry->Offset + ptEntry->Size) {
|
||||
sizeCandidate = ptEntry->Offset + ptEntry->Size;
|
||||
}
|
||||
}
|
||||
|
||||
// Check size candidate
|
||||
if (sizeCandidate == 0)
|
||||
continue;
|
||||
|
||||
// All checks passed, BPDT found
|
||||
nextItemType = Types::BpdtStore;
|
||||
nextItemSize = sizeCandidate;
|
||||
nextItemAlternativeSize = sizeCandidate;
|
||||
nextItemOffset = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No more stores found
|
||||
@ -1294,7 +1376,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
|
||||
UINT32 fileSize = getFileSize(volumeBody, fileOffset, ffsVersion);
|
||||
|
||||
// Check that we are at the empty space
|
||||
UByteArray header = volumeBody.mid(fileOffset, std::min(sizeof(EFI_FFS_FILE_HEADER), (size_t)volumeBodySize - fileOffset));
|
||||
UByteArray header = volumeBody.mid(fileOffset, (int)std::min(sizeof(EFI_FFS_FILE_HEADER), (size_t)volumeBodySize - fileOffset));
|
||||
if (header.count(emptyByte) == header.size()) { //Empty space
|
||||
// Check volume usedSpace entry to be valid
|
||||
if (usedSpace > 0 && usedSpace == fileOffset + volumeHeaderSize) {
|
||||
@ -3316,7 +3398,12 @@ USTATUS FfsParser::markProtectedRangeRecursive(const UModelIndex & index, const
|
||||
|
||||
if (std::min(currentOffset + currentSize, range.Offset + range.Size) > std::max(currentOffset, range.Offset)) {
|
||||
if (range.Offset <= currentOffset && currentOffset + currentSize <= range.Offset + range.Size) { // Mark as fully in range
|
||||
model->setMarking(index, range.Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB ? Qt::red : Qt::cyan);
|
||||
if (range.Type == BG_PROTECTED_RANGE_INTEL_BOOT_GUARD_IBB) {
|
||||
model->setMarking(index, Qt::red);
|
||||
}
|
||||
else {
|
||||
model->setMarking(index, Qt::cyan);
|
||||
}
|
||||
}
|
||||
else { // Mark as partially in range
|
||||
model->setMarking(index, Qt::yellow);
|
||||
@ -4251,3 +4338,746 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const
|
||||
// No need to parse the body further for now
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseBpdtRegion(const UByteArray & region, const UINT32 localOffset, const UINT32 sbpdtOffsetFixup, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
UINT32 regionSize = (UINT32)region.size();
|
||||
|
||||
// Check region size
|
||||
if (regionSize < sizeof(BPDT_HEADER)) {
|
||||
msg(usprintf("%s: BPDT region too small to fit BPDT partition table header", __FUNCTION__), parent);
|
||||
return U_INVALID_ME_PARTITION_TABLE;
|
||||
}
|
||||
|
||||
// Populate partition table header
|
||||
const BPDT_HEADER* ptHeader = (const BPDT_HEADER*)(region.constData());
|
||||
|
||||
// Check region size again
|
||||
UINT32 ptBodySize = ptHeader->NumEntries * sizeof(BPDT_ENTRY);
|
||||
UINT32 ptSize = sizeof(BPDT_HEADER) + ptBodySize;
|
||||
if (regionSize < ptSize) {
|
||||
msg(usprintf("%s: BPDT region too small to fit BPDT partition table", __FUNCTION__), parent);
|
||||
return U_INVALID_ME_PARTITION_TABLE;
|
||||
}
|
||||
|
||||
// Get info
|
||||
UByteArray header = region.left(sizeof(BPDT_HEADER));
|
||||
UByteArray body = region.mid(sizeof(BPDT_HEADER), ptBodySize);
|
||||
|
||||
UString name = UString("BPDT partition table");
|
||||
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nNumber of entries: %u\nVersion: %2Xh\n"
|
||||
"IFWI version: %Xh\nFITC version: %u.%u.%u.%u",
|
||||
ptSize, ptSize,
|
||||
header.size(), header.size(),
|
||||
ptBodySize, ptBodySize,
|
||||
ptHeader->NumEntries,
|
||||
ptHeader->HeaderVersion,
|
||||
ptHeader->IfwiVersion,
|
||||
ptHeader->FitcMajor, ptHeader->FitcMinor, ptHeader->FitcHotfix, ptHeader->FitcBuild);
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(localOffset, Types::BpdtStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
|
||||
// Adjust offset
|
||||
UINT32 offset = sizeof(BPDT_HEADER);
|
||||
|
||||
// Add partition table entries
|
||||
std::vector<BPDT_PARTITION_INFO> partitions;
|
||||
const BPDT_ENTRY* firstPtEntry = (const BPDT_ENTRY*)((const UINT8*)ptHeader + sizeof(BPDT_HEADER));
|
||||
for (UINT16 i = 0; i < ptHeader->NumEntries; i++) {
|
||||
// Populate entry header
|
||||
const BPDT_ENTRY* ptEntry = firstPtEntry + i;
|
||||
|
||||
// Get info
|
||||
name = bpdtEntryTypeToUString(ptEntry->Type);
|
||||
info = usprintf("Full size: %Xh (%u)\nType: %Xh\nPartition offset: %Xh\nPartition length: %Xh",
|
||||
sizeof(BPDT_ENTRY), sizeof(BPDT_ENTRY),
|
||||
ptEntry->Type,
|
||||
ptEntry->Offset,
|
||||
ptEntry->Size) +
|
||||
UString("\nSplit sub-partition first part: ") + (ptEntry->SplitSubPartitionFirstPart ? "Yes" : "No") +
|
||||
UString("\nSplit sub-partition second part: ") + (ptEntry->SplitSubPartitionSecondPart ? "Yes" : "No") +
|
||||
UString("\nCode sub-partition: ") + (ptEntry->CodeSubPartition ? "Yes" : "No") +
|
||||
UString("\nUMA cachable: ") + (ptEntry->UmaCachable ? "Yes" : "No");
|
||||
|
||||
// Add tree item
|
||||
UModelIndex entryIndex = model->addItem(localOffset + offset, Types::BpdtEntry, 0, name, UString(), info, UByteArray(), UByteArray((const char*)ptEntry, sizeof(BPDT_ENTRY)), UByteArray(), Fixed, index);
|
||||
|
||||
// Adjust offset
|
||||
offset += sizeof(BPDT_ENTRY);
|
||||
|
||||
if (ptEntry->Offset != 0 && ptEntry->Offset != 0xFFFFFFFF && ptEntry->Size != 0) {
|
||||
// Add to partitions vector
|
||||
BPDT_PARTITION_INFO partition;
|
||||
partition.type = Types::BpdtPartition;
|
||||
partition.ptEntry = *ptEntry;
|
||||
partition.ptEntry.Offset -= sbpdtOffsetFixup;
|
||||
partition.index = entryIndex;
|
||||
partitions.push_back(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding if there's no partions to add
|
||||
if (partitions.size() == 0) {
|
||||
UByteArray partition = region.mid(ptSize);
|
||||
|
||||
// Get info
|
||||
name = UString("Padding");
|
||||
info = usprintf("Full size: %Xh (%u)",
|
||||
partition.size(), partition.size());
|
||||
|
||||
// Add tree item
|
||||
model->addItem(localOffset + ptSize, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
make_partition_table_consistent:
|
||||
// Sort partitions by offset
|
||||
std::sort(partitions.begin(), partitions.end());
|
||||
|
||||
// Check for intersections and paddings between partitions
|
||||
BPDT_PARTITION_INFO padding;
|
||||
|
||||
// Check intersection with the partition table header
|
||||
if (partitions.front().ptEntry.Offset < ptSize) {
|
||||
msg(usprintf("%s: BPDT partition has intersection with BPDT partition table, skipped", __FUNCTION__),
|
||||
partitions.front().index);
|
||||
partitions.erase(partitions.begin());
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
// Check for padding between partition table and the first partition
|
||||
else if (partitions.front().ptEntry.Offset > ptSize) {
|
||||
padding.ptEntry.Offset = ptSize;
|
||||
padding.ptEntry.Size = partitions.front().ptEntry.Offset - padding.ptEntry.Offset;
|
||||
padding.type = Types::Padding;
|
||||
partitions.insert(partitions.begin(), padding);
|
||||
}
|
||||
// Check for intersections/paddings between partitions
|
||||
for (size_t i = 1; i < partitions.size(); i++) {
|
||||
UINT32 previousPartitionEnd = partitions[i - 1].ptEntry.Offset + partitions[i - 1].ptEntry.Size;
|
||||
|
||||
// Check that partition is fully present in the image
|
||||
if ((UINT64)partitions[i].ptEntry.Offset + (UINT64)partitions[i].ptEntry.Size > regionSize) {
|
||||
if ((UINT64)partitions[i].ptEntry.Offset >= (UINT64)region.size()) {
|
||||
msg(usprintf("%s: BPDT partition is located outside of the opened image, skipped", __FUNCTION__), partitions[i].index);
|
||||
partitions.erase(partitions.begin() + i);
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
else {
|
||||
msg(usprintf("%s: BPDT partition can't fit into it's region, truncated", __FUNCTION__), partitions[i].index);
|
||||
partitions[i].ptEntry.Size = regionSize - (UINT32)partitions[i].ptEntry.Offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for intersection with previous partition
|
||||
if (partitions[i].ptEntry.Offset < previousPartitionEnd) {
|
||||
// Check if current partition is located inside previous one
|
||||
if (partitions[i].ptEntry.Offset + partitions[i].ptEntry.Size <= previousPartitionEnd) {
|
||||
msg(usprintf("%s: BPDT partition is located inside another BPDT partition, skipped", __FUNCTION__),
|
||||
partitions[i].index);
|
||||
partitions.erase(partitions.begin() + i);
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
else {
|
||||
msg(usprintf("%s: BPDT partition intersects with prevous one, skipped", __FUNCTION__),
|
||||
partitions[i].index);
|
||||
partitions.erase(partitions.begin() + i);
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for padding between current and previous partitions
|
||||
else if (partitions[i].ptEntry.Offset > previousPartitionEnd) {
|
||||
padding.ptEntry.Offset = previousPartitionEnd;
|
||||
padding.ptEntry.Size = partitions[i].ptEntry.Offset - previousPartitionEnd;
|
||||
padding.type = Types::Padding;
|
||||
std::vector<BPDT_PARTITION_INFO>::iterator iter = partitions.begin();
|
||||
std::advance(iter, i);
|
||||
partitions.insert(iter, padding);
|
||||
}
|
||||
}
|
||||
|
||||
// Partition map is consistent
|
||||
for (size_t i = 0; i < partitions.size(); i++) {
|
||||
if (partitions[i].type == Types::BpdtPartition) {
|
||||
// Get info
|
||||
UString name = bpdtEntryTypeToUString(partitions[i].ptEntry.Type);
|
||||
UByteArray partition = region.mid(partitions[i].ptEntry.Offset, partitions[i].ptEntry.Size);
|
||||
UByteArray signature = partition.left(sizeof(UINT32));
|
||||
|
||||
UString info = usprintf("Full size: %Xh (%u)\nType: %Xh",
|
||||
partition.size(), partition.size(),
|
||||
partitions[i].ptEntry.Type) +
|
||||
UString("\nSplit sub-partition first part: ") + (partitions[i].ptEntry.SplitSubPartitionFirstPart ? "Yes" : "No") +
|
||||
UString("\nSplit sub-partition second part: ") + (partitions[i].ptEntry.SplitSubPartitionSecondPart ? "Yes" : "No") +
|
||||
UString("\nCode sub-partition: ") + (partitions[i].ptEntry.CodeSubPartition ? "Yes" : "No") +
|
||||
UString("\nUMA cachable: ") + (partitions[i].ptEntry.UmaCachable ? "Yes" : "No");
|
||||
|
||||
UString text = bpdtEntryTypeToUString(partitions[i].ptEntry.Type);
|
||||
|
||||
// Add tree item
|
||||
UModelIndex partitionIndex = model->addItem(localOffset + partitions[i].ptEntry.Offset, Types::BpdtPartition, 0, name, text, info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
|
||||
// Special case of S-BPDT
|
||||
if (partitions[i].ptEntry.Type == BPDT_ENTRY_TYPE_SBPDT) {
|
||||
UModelIndex sbpdtIndex;
|
||||
parseBpdtRegion(partition, 0, partitions[i].ptEntry.Offset, partitionIndex, sbpdtIndex); // Third parameter is a fixup for S-BPDT offset entries, because they are calculated from the start of BIOS region
|
||||
}
|
||||
|
||||
// Parse code partitions
|
||||
if (readUnaligned((const UINT32*)partition.constData()) == CPD_SIGNATURE) {
|
||||
// Parse code partition contents
|
||||
UModelIndex cpdIndex;
|
||||
parseCpdRegion(partition, localOffset, partitionIndex, cpdIndex);
|
||||
}
|
||||
|
||||
if (partitions[i].ptEntry.Type > BPDT_LAST_KNOWN_ENTRY_TYPE) {
|
||||
msg(usprintf("%s: BPDT entry of unknown type found", __FUNCTION__), partitionIndex);
|
||||
}
|
||||
}
|
||||
else if (partitions[i].type == Types::Padding) {
|
||||
UByteArray partition = region.mid(partitions[i].ptEntry.Offset, partitions[i].ptEntry.Size);
|
||||
|
||||
// Get info
|
||||
name = UString("Padding");
|
||||
info = usprintf("Full size: %Xh (%u)",
|
||||
partition.size(), partition.size());
|
||||
|
||||
// Add tree item
|
||||
model->addItem(localOffset + partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding after the last region
|
||||
if ((UINT64)partitions.back().ptEntry.Offset + (UINT64)partitions.back().ptEntry.Size < regionSize) {
|
||||
UByteArray partition = region.mid(partitions.back().ptEntry.Offset + partitions.back().ptEntry.Size, regionSize - padding.ptEntry.Offset);
|
||||
|
||||
// Get info
|
||||
name = UString("Padding");
|
||||
info = usprintf("Full size: %Xh (%u)",
|
||||
partition.size(), partition.size());
|
||||
|
||||
// Add tree item
|
||||
model->addItem(localOffset + partitions.back().ptEntry.Offset + partitions.back().ptEntry.Size, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
}
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
|
||||
{
|
||||
// Check directory size
|
||||
if ((UINT32)region.size() < sizeof(CPD_REV1_HEADER)) {
|
||||
msg(usprintf("%s: CPD too small to fit rev1 partition table header", __FUNCTION__), parent);
|
||||
return U_INVALID_ME_PARTITION_TABLE;
|
||||
}
|
||||
|
||||
// Populate partition table header
|
||||
const CPD_REV1_HEADER* cpdHeader = (const CPD_REV1_HEADER*)region.constData();
|
||||
|
||||
// Check header version to be known
|
||||
UINT32 ptHeaderSize = 0;
|
||||
if (cpdHeader->HeaderVersion == 2) {
|
||||
if ((UINT32)region.size() < sizeof(CPD_REV2_HEADER)) {
|
||||
msg(usprintf("%s: CPD too small to fit rev2 partition table header", __FUNCTION__), parent);
|
||||
return U_INVALID_ME_PARTITION_TABLE;
|
||||
}
|
||||
|
||||
ptHeaderSize = sizeof(CPD_REV2_HEADER);
|
||||
}
|
||||
else if (cpdHeader->HeaderVersion == 1) {
|
||||
ptHeaderSize = sizeof(CPD_REV1_HEADER);
|
||||
}
|
||||
|
||||
// Check directory size again
|
||||
UINT32 ptBodySize = cpdHeader->NumEntries * sizeof(CPD_ENTRY);
|
||||
UINT32 ptSize = ptHeaderSize + ptBodySize;
|
||||
if ((UINT32)region.size() < ptSize) {
|
||||
msg(usprintf("%s: CPD too small to fit the whole partition table", __FUNCTION__), parent);
|
||||
return U_INVALID_ME_PARTITION_TABLE;
|
||||
}
|
||||
|
||||
// Get info
|
||||
UByteArray header = region.left(ptHeaderSize);
|
||||
UByteArray body = region.mid(ptHeaderSize);
|
||||
UString name = usprintf("CPD partition table");
|
||||
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nNumber of entries: %u\n"
|
||||
"Header version: %02X\nEntry version: %02X",
|
||||
region.size(), region.size(),
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
cpdHeader->NumEntries,
|
||||
cpdHeader->HeaderVersion,
|
||||
cpdHeader->EntryVersion);
|
||||
|
||||
// Add tree item
|
||||
index = model->addItem(localOffset, Types::CpdStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
|
||||
// Add partition table entries
|
||||
std::vector<CPD_PARTITION_INFO> partitions;
|
||||
UINT32 offset = ptHeaderSize;
|
||||
const CPD_ENTRY* firstCpdEntry = (const CPD_ENTRY*)(body.constData());
|
||||
for (UINT32 i = 0; i < cpdHeader->NumEntries; i++) {
|
||||
// Populate entry header
|
||||
const CPD_ENTRY* cpdEntry = firstCpdEntry + i;
|
||||
UByteArray entry((const char*)cpdEntry, sizeof(CPD_ENTRY));
|
||||
|
||||
// Get info
|
||||
name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
cpdEntry->EntryName[0], cpdEntry->EntryName[1], cpdEntry->EntryName[2], cpdEntry->EntryName[3],
|
||||
cpdEntry->EntryName[4], cpdEntry->EntryName[5], cpdEntry->EntryName[6], cpdEntry->EntryName[7],
|
||||
cpdEntry->EntryName[8], cpdEntry->EntryName[9], cpdEntry->EntryName[10], cpdEntry->EntryName[11]);
|
||||
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
|
||||
entry.size(), entry.size(),
|
||||
cpdEntry->Offset.Offset,
|
||||
cpdEntry->Length)
|
||||
+ (cpdEntry->Offset.HuffmanCompressed ? "Yes" : "No");
|
||||
|
||||
// Add tree item
|
||||
UModelIndex entryIndex = model->addItem(offset, Types::CpdEntry, 0, name, UString(), info, UByteArray(), entry, UByteArray(), Fixed, index);
|
||||
|
||||
// Adjust offset
|
||||
offset += sizeof(CPD_ENTRY);
|
||||
|
||||
if (cpdEntry->Offset.Offset != 0 && cpdEntry->Length != 0) {
|
||||
// Add to partitions vector
|
||||
CPD_PARTITION_INFO partition;
|
||||
partition.type = Types::CpdPartition;
|
||||
partition.ptEntry = *cpdEntry;
|
||||
partition.index = entryIndex;
|
||||
partitions.push_back(partition);
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding if there's no partions to add
|
||||
if (partitions.size() == 0) {
|
||||
UByteArray partition = region.mid(ptSize);
|
||||
|
||||
// Get info
|
||||
name = UString("Padding");
|
||||
info = usprintf("Full size: %Xh (%u)",
|
||||
partition.size(), partition.size());
|
||||
|
||||
// Add tree item
|
||||
model->addItem(localOffset + ptSize, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
// Sort partitions by offset
|
||||
std::sort(partitions.begin(), partitions.end());
|
||||
|
||||
// Because lenghts for all Huffmann-compressed partitions mean nothing at all, we need to split all partitions into 2 classes:
|
||||
// 1. CPD manifest (should be the first)
|
||||
// 2. Metadata entries (should begin right after partition manifest and end before any code partition)
|
||||
UINT32 i = 1;
|
||||
while (i < partitions.size()) {
|
||||
name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
partitions[i].ptEntry.EntryName[0], partitions[i].ptEntry.EntryName[1], partitions[i].ptEntry.EntryName[2], partitions[i].ptEntry.EntryName[3],
|
||||
partitions[i].ptEntry.EntryName[4], partitions[i].ptEntry.EntryName[5], partitions[i].ptEntry.EntryName[6], partitions[i].ptEntry.EntryName[7],
|
||||
partitions[i].ptEntry.EntryName[8], partitions[i].ptEntry.EntryName[9], partitions[i].ptEntry.EntryName[10], partitions[i].ptEntry.EntryName[11]);
|
||||
|
||||
// Check if the current entry is metadata entry
|
||||
if (!name.contains(".met")) {
|
||||
// No need to parse further, all metadata partitions are parsed
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse into data block, find Module Attributes extension, and get compressed size from there
|
||||
UINT32 offset = 0;
|
||||
UINT32 length = 0xFFFFFFFF; // Special guardian value
|
||||
UByteArray partition = region.mid(partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Length);
|
||||
while (offset < (UINT32)partition.size()) {
|
||||
const CPD_EXTENTION_HEADER* extHeader = (const CPD_EXTENTION_HEADER*) (partition.constData() + offset);
|
||||
if (extHeader->Length <= ((UINT32)partition.size() - offset)) {
|
||||
if (extHeader->Type == CPD_EXT_TYPE_MODULE_ATTRIBUTES) {
|
||||
const CPD_EXT_MODULE_ATTRIBUTES* attrHeader = (const CPD_EXT_MODULE_ATTRIBUTES*)(partition.constData() + offset);
|
||||
length = attrHeader->CompressedSize;
|
||||
}
|
||||
offset += extHeader->Length;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
// Search down for corresponding code partition
|
||||
// Construct it's name by replacing last 4 non-zero butes of the name with zeros
|
||||
UINT32 j = 0;
|
||||
for (UINT32 k = 11; k > 0 && j < 4; k--) {
|
||||
if (name[k] != '\x00') {
|
||||
name[k] = '\x00';
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
// Search
|
||||
j = i + 1;
|
||||
while (j < partitions.size()) {
|
||||
if (name == usprintf("%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
partitions[j].ptEntry.EntryName[0], partitions[j].ptEntry.EntryName[1], partitions[j].ptEntry.EntryName[2], partitions[j].ptEntry.EntryName[3],
|
||||
partitions[j].ptEntry.EntryName[4], partitions[j].ptEntry.EntryName[5], partitions[j].ptEntry.EntryName[6], partitions[j].ptEntry.EntryName[7],
|
||||
partitions[j].ptEntry.EntryName[8], partitions[j].ptEntry.EntryName[9], partitions[j].ptEntry.EntryName[10], partitions[j].ptEntry.EntryName[11])) {
|
||||
// Found it, update it's Length if needed
|
||||
if (partitions[j].ptEntry.Offset.HuffmanCompressed) {
|
||||
partitions[j].ptEntry.Length = length;
|
||||
}
|
||||
else if (length != 0xFFFFFFFF && partitions[j].ptEntry.Length != length) {
|
||||
msg(usprintf("%s: partition size mismatch between partition table (%Xh) and partition metadata (%Xh)", __FUNCTION__,
|
||||
partitions[j].ptEntry.Length, length), partitions[j].index);
|
||||
partitions[j].ptEntry.Length = length; // Believe metadata
|
||||
}
|
||||
// No need to search further
|
||||
break;
|
||||
}
|
||||
// Check the next partition
|
||||
j++;
|
||||
}
|
||||
// Check the next partition
|
||||
i++;
|
||||
}
|
||||
|
||||
make_partition_table_consistent:
|
||||
// Sort partitions by offset
|
||||
std::sort(partitions.begin(), partitions.end());
|
||||
|
||||
// Check for intersections and paddings between partitions
|
||||
CPD_PARTITION_INFO padding;
|
||||
|
||||
// Check intersection with the partition table header
|
||||
if (partitions.front().ptEntry.Offset.Offset < ptSize) {
|
||||
msg(usprintf("%s: CPD partition has intersection with CPD partition table, skipped", __FUNCTION__),
|
||||
partitions.front().index);
|
||||
partitions.erase(partitions.begin());
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
// Check for padding between partition table and the first partition
|
||||
else if (partitions.front().ptEntry.Offset.Offset > ptSize) {
|
||||
padding.ptEntry.Offset.Offset = ptSize;
|
||||
padding.ptEntry.Length = partitions.front().ptEntry.Offset.Offset - padding.ptEntry.Offset.Offset;
|
||||
padding.type = Types::Padding;
|
||||
partitions.insert(partitions.begin(), padding);
|
||||
}
|
||||
// Check for intersections/paddings between partitions
|
||||
for (size_t i = 1; i < partitions.size(); i++) {
|
||||
UINT32 previousPartitionEnd = partitions[i - 1].ptEntry.Offset.Offset + partitions[i - 1].ptEntry.Length;
|
||||
|
||||
// Check that current region is fully present in the image
|
||||
if ((UINT64)partitions[i].ptEntry.Offset.Offset + (UINT64)partitions[i].ptEntry.Length > (UINT64)region.size()) {
|
||||
if ((UINT64)partitions[i].ptEntry.Offset.Offset >= (UINT64)region.size()) {
|
||||
msg(usprintf("%s: CPD partition is located outside of the opened image, skipped", __FUNCTION__), partitions[i].index);
|
||||
partitions.erase(partitions.begin() + i);
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
else {
|
||||
msg(usprintf("%s: CPD partition can't fit into it's region, truncated", __FUNCTION__), partitions[i].index);
|
||||
partitions[i].ptEntry.Length = (UINT32)region.size() - (UINT32)partitions[i].ptEntry.Offset.Offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for intersection with previous partition
|
||||
if (partitions[i].ptEntry.Offset.Offset < previousPartitionEnd) {
|
||||
// Check if current partition is located inside previous one
|
||||
if (partitions[i].ptEntry.Offset.Offset + partitions[i].ptEntry.Length <= previousPartitionEnd) {
|
||||
msg(usprintf("%s: CPD partition is located inside another CPD partition, skipped", __FUNCTION__),
|
||||
partitions[i].index);
|
||||
partitions.erase(partitions.begin() + i);
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
else {
|
||||
msg(usprintf("%s: CPD partition intersects with previous one, skipped", __FUNCTION__),
|
||||
partitions[i].index);
|
||||
partitions.erase(partitions.begin() + i);
|
||||
goto make_partition_table_consistent;
|
||||
}
|
||||
}
|
||||
// Check for padding between current and previous partitions
|
||||
else if (partitions[i].ptEntry.Offset.Offset > previousPartitionEnd) {
|
||||
padding.ptEntry.Offset.Offset = previousPartitionEnd;
|
||||
padding.ptEntry.Length = partitions[i].ptEntry.Offset.Offset - previousPartitionEnd;
|
||||
padding.type = Types::Padding;
|
||||
std::vector<CPD_PARTITION_INFO>::iterator iter = partitions.begin();
|
||||
std::advance(iter, i);
|
||||
partitions.insert(iter, padding);
|
||||
}
|
||||
}
|
||||
// Check for padding after the last region
|
||||
if ((UINT64)partitions.back().ptEntry.Offset.Offset + (UINT64)partitions.back().ptEntry.Length < (UINT64)region.size()) {
|
||||
padding.ptEntry.Offset.Offset = partitions.back().ptEntry.Offset.Offset + partitions.back().ptEntry.Length;
|
||||
padding.ptEntry.Length = (UINT32)region.size() - padding.ptEntry.Offset.Offset;
|
||||
padding.type = Types::Padding;
|
||||
partitions.push_back(padding);
|
||||
}
|
||||
|
||||
// Partition map is consistent
|
||||
for (size_t i = 0; i < partitions.size(); i++) {
|
||||
if (partitions[i].type == Types::CpdPartition) {
|
||||
UByteArray partition = region.mid(partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Length);
|
||||
|
||||
// Get info
|
||||
name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
partitions[i].ptEntry.EntryName[0], partitions[i].ptEntry.EntryName[1], partitions[i].ptEntry.EntryName[2], partitions[i].ptEntry.EntryName[3],
|
||||
partitions[i].ptEntry.EntryName[4], partitions[i].ptEntry.EntryName[5], partitions[i].ptEntry.EntryName[6], partitions[i].ptEntry.EntryName[7],
|
||||
partitions[i].ptEntry.EntryName[8], partitions[i].ptEntry.EntryName[9], partitions[i].ptEntry.EntryName[10], partitions[i].ptEntry.EntryName[11]);
|
||||
|
||||
// It's a manifest
|
||||
if (name.contains(".man")) {
|
||||
if (!partitions[i].ptEntry.Offset.HuffmanCompressed
|
||||
&& partitions[i].ptEntry.Length >= sizeof(CPD_MANIFEST_HEADER)) {
|
||||
const CPD_MANIFEST_HEADER* manifestHeader = (const CPD_MANIFEST_HEADER*) partition.constData();
|
||||
if (manifestHeader->HeaderId == ME_MANIFEST_HEADER_ID) {
|
||||
UByteArray header = partition.left(manifestHeader->HeaderLength * sizeof(UINT32));
|
||||
UByteArray body = partition.mid(header.size());
|
||||
|
||||
info += usprintf(
|
||||
"\nHeader type: %u\nHeader length: %Xh (%u)\nHeader version: %Xh\nFlags: %08Xh\nVendor: %Xh\n"
|
||||
"Date: %Xh\nSize: %Xh (%u)\nVersion: %u.%u.%u.%u\nSecurity version number: %u\nModulus size: %Xh (%u)\nExponent size: %Xh (%u)",
|
||||
manifestHeader->HeaderType,
|
||||
manifestHeader->HeaderLength * sizeof(UINT32), manifestHeader->HeaderLength * sizeof(UINT32),
|
||||
manifestHeader->HeaderVersion,
|
||||
manifestHeader->Flags,
|
||||
manifestHeader->Vendor,
|
||||
manifestHeader->Date,
|
||||
manifestHeader->Size * sizeof(UINT32), manifestHeader->Size * sizeof(UINT32),
|
||||
manifestHeader->VersionMajor, manifestHeader->VersionMinor, manifestHeader->VersionBugfix, manifestHeader->VersionBuild,
|
||||
manifestHeader->SecurityVersion,
|
||||
manifestHeader->ModulusSize * sizeof(UINT32), manifestHeader->ModulusSize * sizeof(UINT32),
|
||||
manifestHeader->ExponentSize * sizeof(UINT32), manifestHeader->ExponentSize * sizeof(UINT32));
|
||||
|
||||
// Add tree item
|
||||
UModelIndex partitionIndex = model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::CpdPartition, Subtypes::ManifestCpdPartition, name, UString(), info, header, body, UByteArray(), Fixed, parent);
|
||||
|
||||
// Parse data as extensions area
|
||||
parseCpdExtensionsArea(partitionIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
// It's a metadata
|
||||
else if (name.contains(".met")) {
|
||||
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
|
||||
partition.size(), partition.size(),
|
||||
partitions[i].ptEntry.Offset.Offset,
|
||||
partitions[i].ptEntry.Length)
|
||||
+ (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No");
|
||||
|
||||
// Calculate SHA256 hash over the metadata and add it to it's info
|
||||
UByteArray hash(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(partition.constData(), partition.size(), hash.data());
|
||||
info += UString("\nMetadata hash: ") + UString(hash.toHex().constData());
|
||||
|
||||
// Add three item
|
||||
UModelIndex partitionIndex = model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::CpdPartition, Subtypes::MetadataCpdPartition, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
|
||||
// Parse data as extensions area
|
||||
parseCpdExtensionsArea(partitionIndex);
|
||||
}
|
||||
// It's a key
|
||||
else if (name.contains(".key")) {
|
||||
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
|
||||
partition.size(), partition.size(),
|
||||
partitions[i].ptEntry.Offset.Offset,
|
||||
partitions[i].ptEntry.Length)
|
||||
+ (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No");
|
||||
|
||||
// Calculate SHA256 hash over the key and add it to it's info
|
||||
UByteArray hash(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(partition.constData(), partition.size(), hash.data());
|
||||
info += UString("\nHash: ") + UString(hash.toHex().constData());
|
||||
|
||||
// Add three item
|
||||
UModelIndex partitionIndex = model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::CpdPartition, Subtypes::KeyCpdPartition, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
|
||||
// Parse data as extensions area
|
||||
parseCpdExtensionsArea(partitionIndex);
|
||||
}
|
||||
// It's a code
|
||||
else {
|
||||
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
|
||||
partition.size(), partition.size(),
|
||||
partitions[i].ptEntry.Offset.Offset,
|
||||
partitions[i].ptEntry.Length)
|
||||
+ (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No");
|
||||
|
||||
// Calculate SHA256 hash over the code and add it to it's info
|
||||
UByteArray hash(SHA256_DIGEST_SIZE, '\x00');
|
||||
sha256(partition.constData(), partition.size(), hash.data());
|
||||
info += UString("\nHash: ") + UString(hash.toHex().constData());
|
||||
|
||||
UModelIndex codeIndex = model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::CpdPartition, Subtypes::CodeCpdPartition, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
parseRawArea(codeIndex);
|
||||
}
|
||||
}
|
||||
else if (partitions[i].type == Types::Padding) {
|
||||
UByteArray partition = region.mid(partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Length);
|
||||
|
||||
// Get info
|
||||
name = UString("Padding");
|
||||
info = usprintf("Full size: %Xh (%u)", partition.size(), partition.size());
|
||||
|
||||
// Add tree item
|
||||
model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
|
||||
}
|
||||
else {
|
||||
msg(usprintf("%s: CPD partition of unknown type found", __FUNCTION__), parent);
|
||||
return U_INVALID_ME_PARTITION_TABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseCpdExtensionsArea(const UModelIndex & index)
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return U_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
UByteArray body = model->body(index);
|
||||
UINT32 offset = 0;
|
||||
while (offset < (UINT32)body.size()) {
|
||||
const CPD_EXTENTION_HEADER* extHeader = (const CPD_EXTENTION_HEADER*) (body.constData() + offset);
|
||||
if (extHeader->Length <= ((UINT32)body.size() - offset)) {
|
||||
UByteArray partition = body.mid(offset, extHeader->Length);
|
||||
|
||||
UString name = cpdExtensionTypeToUstring(extHeader->Type);
|
||||
UString info = usprintf("Full size: %Xh (%u)\nType: %Xh", partition.size(), partition.size(), extHeader->Type);
|
||||
|
||||
// Parse Signed Package Info a bit further
|
||||
UModelIndex extIndex;
|
||||
if (extHeader->Type == CPD_EXT_TYPE_SIGNED_PACKAGE_INFO) {
|
||||
UByteArray header = partition.left(sizeof(CPD_EXT_SIGNED_PACKAGE_INFO));
|
||||
UByteArray data = partition.mid(header.size());
|
||||
|
||||
const CPD_EXT_SIGNED_PACKAGE_INFO* infoHeader = (const CPD_EXT_SIGNED_PACKAGE_INFO*)header.constData();
|
||||
|
||||
info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nType: %Xh\n"
|
||||
"Package name: %c%c%c%c\nVersion control number: %Xh\nSecurity version number: %Xh\n"
|
||||
"Usage bitmap: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
partition.size(), partition.size(),
|
||||
header.size(), header.size(),
|
||||
body.size(), body.size(),
|
||||
infoHeader->ExtensionType,
|
||||
infoHeader->PackageName[0], infoHeader->PackageName[1], infoHeader->PackageName[2], infoHeader->PackageName[3],
|
||||
infoHeader->Vcn,
|
||||
infoHeader->Svn,
|
||||
infoHeader->UsageBitmap[0], infoHeader->UsageBitmap[1], infoHeader->UsageBitmap[2], infoHeader->UsageBitmap[3],
|
||||
infoHeader->UsageBitmap[4], infoHeader->UsageBitmap[5], infoHeader->UsageBitmap[6], infoHeader->UsageBitmap[7],
|
||||
infoHeader->UsageBitmap[8], infoHeader->UsageBitmap[9], infoHeader->UsageBitmap[10], infoHeader->UsageBitmap[11],
|
||||
infoHeader->UsageBitmap[12], infoHeader->UsageBitmap[13], infoHeader->UsageBitmap[14], infoHeader->UsageBitmap[15]);
|
||||
|
||||
// Add tree item
|
||||
extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, header, data, UByteArray(), Fixed, index);
|
||||
parseSignedPackageInfoData(extIndex);
|
||||
}
|
||||
// Parse IFWI Partition Manifest a bit further
|
||||
else if (extHeader->Type == CPD_EXT_TYPE_IFWI_PARTITION_MANIFEST) {
|
||||
const CPD_EXT_IFWI_PARTITION_MANIFEST* attrHeader = (const CPD_EXT_IFWI_PARTITION_MANIFEST*)partition.constData();
|
||||
|
||||
// This hash is stored reversed
|
||||
// Need to reverse it back to normal
|
||||
UByteArray hash((const char*)&attrHeader->CompletePartitionHash, sizeof(attrHeader->CompletePartitionHash));
|
||||
std::reverse(hash.begin(), hash.end());
|
||||
|
||||
info = usprintf("Full size: %Xh (%u)\nType: %Xh\n"
|
||||
"Partition name: %c%c%c%c\nPartition length: %Xh\nPartition version major: %Xh\nPartition version minor: %Xh\n"
|
||||
"Data format version: %Xh\nInstance ID: %Xh\nHash algorithm: %Xh\nHash size: %Xh\nAction on update: %Xh",
|
||||
partition.size(), partition.size(),
|
||||
attrHeader->ExtensionType,
|
||||
attrHeader->PartitionName[0], attrHeader->PartitionName[1], attrHeader->PartitionName[2], attrHeader->PartitionName[3],
|
||||
attrHeader->CompletePartitionLength,
|
||||
attrHeader->PartitionVersionMajor, attrHeader->PartitionVersionMinor,
|
||||
attrHeader->DataFormatVersion,
|
||||
attrHeader->InstanceId,
|
||||
attrHeader->HashAlgorithm,
|
||||
attrHeader->HashSize,
|
||||
attrHeader->ActionOnUpdate)
|
||||
+ UString("\nSupport multiple instances: ") + (attrHeader->SupportMultipleInstances ? "Yes" : "No")
|
||||
+ UString("\nSupport API version based update: ") + (attrHeader->SupportApiVersionBasedUpdate ? "Yes" : "No")
|
||||
+ UString("\nObey full update rules: ") + (attrHeader->ObeyFullUpdateRules ? "Yes" : "No")
|
||||
+ UString("\nIFR enable only: ") + (attrHeader->IfrEnableOnly ? "Yes" : "No")
|
||||
+ UString("\nAllow cross point update: ") + (attrHeader->AllowCrossPointUpdate ? "Yes" : "No")
|
||||
+ UString("\nAllow cross hotfix update: ") + (attrHeader->AllowCrossHotfixUpdate ? "Yes" : "No")
|
||||
+ UString("\nPartial update only: ") + (attrHeader->PartialUpdateOnly ? "Yes" : "No")
|
||||
+ UString("\nPartition hash: ") + UString(hash.toHex().constData());
|
||||
|
||||
// Add tree item
|
||||
extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index);
|
||||
}
|
||||
// Parse Module Attributes a bit further
|
||||
else if (extHeader->Type == CPD_EXT_TYPE_MODULE_ATTRIBUTES) {
|
||||
const CPD_EXT_MODULE_ATTRIBUTES* attrHeader = (const CPD_EXT_MODULE_ATTRIBUTES*)partition.constData();
|
||||
|
||||
// This hash is stored reversed
|
||||
// Need to reverse it back to normal
|
||||
UByteArray hash((const char*)&attrHeader->ImageHash, sizeof(attrHeader->ImageHash));
|
||||
std::reverse(hash.begin(), hash.end());
|
||||
|
||||
info = usprintf("Full size: %Xh (%u)\nType: %Xh\n"
|
||||
"Compression type: %Xh\nUncompressed size: %Xh (%u)\nCompressed size: %Xh (%u)\nGlobal module ID: %Xh\nImage hash: ",
|
||||
partition.size(), partition.size(),
|
||||
attrHeader->ExtensionType,
|
||||
attrHeader->CompressionType,
|
||||
attrHeader->UncompressedSize, attrHeader->UncompressedSize,
|
||||
attrHeader->CompressedSize, attrHeader->CompressedSize,
|
||||
attrHeader->GlobalModuleId) + UString(hash.toHex().constData());
|
||||
|
||||
// Add tree item
|
||||
extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index);
|
||||
}
|
||||
// Parse everything else
|
||||
else {
|
||||
// Add tree item, if needed
|
||||
extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index);
|
||||
}
|
||||
|
||||
if (extHeader->Type > CPD_LAST_KNOWN_EXT_TYPE) {
|
||||
msg(usprintf("%s: CPD extention of unknown type found", __FUNCTION__), extIndex);
|
||||
}
|
||||
|
||||
offset += extHeader->Length;
|
||||
}
|
||||
else break;
|
||||
// TODO: add padding at the end
|
||||
}
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS FfsParser::parseSignedPackageInfoData(const UModelIndex & index)
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return U_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
UByteArray body = model->body(index);
|
||||
UINT32 offset = 0;
|
||||
while (offset < (UINT32)body.size()) {
|
||||
const CPD_EXT_SIGNED_PACKAGE_INFO_MODULE* moduleHeader = (const CPD_EXT_SIGNED_PACKAGE_INFO_MODULE*)(body.constData() + offset);
|
||||
if (sizeof(CPD_EXT_SIGNED_PACKAGE_INFO_MODULE) <= ((UINT32)body.size() - offset)) {
|
||||
UByteArray module((const char*)moduleHeader, sizeof(CPD_EXT_SIGNED_PACKAGE_INFO_MODULE));
|
||||
|
||||
UString name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
moduleHeader->Name[0], moduleHeader->Name[1], moduleHeader->Name[2], moduleHeader->Name[3],
|
||||
moduleHeader->Name[4], moduleHeader->Name[5], moduleHeader->Name[6], moduleHeader->Name[7],
|
||||
moduleHeader->Name[8], moduleHeader->Name[9], moduleHeader->Name[10],moduleHeader->Name[11]);
|
||||
|
||||
// This hash is stored reversed
|
||||
// Need to reverse it back to normal
|
||||
UByteArray hash((const char*)&moduleHeader->MetadataHash, sizeof(moduleHeader->MetadataHash));
|
||||
std::reverse(hash.begin(), hash.end());
|
||||
|
||||
UString info = usprintf("Full size: %X (%u)\nType: %Xh\nHash algorithm: %Xh\nHash size: %Xh (%u)\nMetadata size: %Xh (%u)\nMetadata hash: ",
|
||||
module.size(), module.size(),
|
||||
moduleHeader->Type,
|
||||
moduleHeader->HashAlgorithm,
|
||||
moduleHeader->HashSize, moduleHeader->HashSize,
|
||||
moduleHeader->MetadataSize, moduleHeader->MetadataSize) + UString(hash.toHex().constData());
|
||||
// Add tree otem
|
||||
model->addItem(offset, Types::CpdSpiEntry, 0, name, UString(), info, UByteArray(), module, UByteArray(), Fixed, index);
|
||||
|
||||
offset += module.size();
|
||||
}
|
||||
else break;
|
||||
// TODO: add padding at the end
|
||||
}
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
@ -97,6 +97,11 @@ private:
|
||||
USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseGenericImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
USTATUS parseBpdtRegion(const UByteArray & region, const UINT32 localOffset, const UINT32 sbpdtOffsetFixup, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseCpdRegion(const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseCpdExtensionsArea(const UModelIndex & index);
|
||||
USTATUS parseSignedPackageInfoData(const UModelIndex & index);
|
||||
|
||||
USTATUS parseRawArea(const UModelIndex & index);
|
||||
USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseVolumeBody(const UModelIndex & index);
|
||||
@ -163,6 +168,10 @@ private:
|
||||
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
||||
friend class NvramParser; // Make FFS parsing routines accessible to NvramParser
|
||||
#endif
|
||||
|
||||
#ifdef U_ENABLE_ME_PARSING_SUPPORT
|
||||
friend class MeParser; // Make FFS parsing routines accessible to MeParser
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FFSPARSER_H
|
||||
|
70
common/me.h
70
common/me.h
@ -18,9 +18,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
// Make sure we use right packing rules
|
||||
#pragma pack(push, 1)
|
||||
|
||||
const UByteArray ME_VERSION_SIGNATURE("\x24\x4D\x41\x4E", 4); //$MAN
|
||||
const UByteArray ME_VERSION_SIGNATURE2("\x24\x4D\x4E\x32", 4); //$MN2
|
||||
|
||||
typedef struct ME_VERSION_ {
|
||||
UINT32 Signature;
|
||||
UINT32 Reserved;
|
||||
@ -30,6 +27,73 @@ typedef struct ME_VERSION_ {
|
||||
UINT16 Build;
|
||||
} ME_VERSION;
|
||||
|
||||
const UByteArray ME_VERSION_SIGNATURE("\x24\x4D\x41\x4E", 4); //$MAN
|
||||
const UByteArray ME_VERSION_SIGNATURE2("\x24\x4D\x4E\x32", 4); //$MN2
|
||||
|
||||
// FPT
|
||||
#define ME_ROM_BYPASS_VECTOR_SIZE 0x10
|
||||
const UByteArray FPT_HEADER_SIGNATURE("\x24\x46\x50\x54", 4); //$FPT
|
||||
|
||||
typedef struct FPT_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT32 NumEntries;
|
||||
UINT8 HeaderVersion;
|
||||
UINT8 EntryVersion;
|
||||
UINT8 HeaderLength;
|
||||
UINT8 Checksum; // One bit for Redundant before IFWI
|
||||
UINT16 TicksToAdd;
|
||||
UINT16 TokensToAdd;
|
||||
UINT32 UmaSize; // Flags in SPS
|
||||
UINT32 FlashLayout; // Crc32 before IFWI
|
||||
UINT16 FitcMajor;
|
||||
UINT16 FitcMinor;
|
||||
UINT16 FitcHotfix;
|
||||
UINT16 FitcBuild;
|
||||
} FPT_HEADER;
|
||||
|
||||
typedef struct FPT_HEADER_ENTRY_{
|
||||
CHAR8 Name[4];
|
||||
CHAR8 Owner[4];
|
||||
UINT32 Offset;
|
||||
UINT32 Size;
|
||||
UINT32 Reserved[3];
|
||||
UINT8 Type : 7;
|
||||
UINT8 CopyToDramCache : 1;
|
||||
UINT8 Reserved1 : 7;
|
||||
UINT8 BuiltWithLength1 : 1;
|
||||
UINT8 BuiltWithLength2 : 1;
|
||||
UINT8 Reserved2 : 7;
|
||||
UINT8 EntryValid;
|
||||
} FPT_HEADER_ENTRY;
|
||||
|
||||
// IFWI
|
||||
typedef struct IFWI_HEADER_ENTRY_ {
|
||||
UINT32 Offset;
|
||||
UINT32 Size;
|
||||
} IFWI_HEADER_ENTRY;
|
||||
|
||||
// IFWI 1.6 (ME), 2.0 (BIOS)
|
||||
typedef struct IFWI_16_LAYOUT_HEADER_ {
|
||||
UINT8 RomBypassVector[16];
|
||||
IFWI_HEADER_ENTRY DataPartition;
|
||||
IFWI_HEADER_ENTRY BootPartition[5];
|
||||
UINT64 Checksum;
|
||||
} IFWI_16_LAYOUT_HEADER;
|
||||
|
||||
// IFWI 1.7 (ME)
|
||||
typedef struct IFWI_17_LAYOUT_HEADER_ {
|
||||
UINT8 RomBypassVector[16];
|
||||
UINT16 HeaderSize;
|
||||
UINT8 Flags;
|
||||
UINT8 Reserved;
|
||||
UINT32 Checksum;
|
||||
IFWI_HEADER_ENTRY DataPartition;
|
||||
IFWI_HEADER_ENTRY BootPartition[5];
|
||||
IFWI_HEADER_ENTRY TempPage;
|
||||
} IFWI_17_LAYOUT_HEADER;
|
||||
|
||||
#define ME_MANIFEST_HEADER_ID 0x324E4D24 //$MN2
|
||||
|
||||
// Restore previous packing rules
|
||||
#pragma pack(pop)
|
||||
|
||||
|
1040
common/meparser.cpp
1040
common/meparser.cpp
File diff suppressed because it is too large
Load Diff
@ -21,208 +21,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "ustring.h"
|
||||
#include "ubytearray.h"
|
||||
#include "treemodel.h"
|
||||
#include "ffsparser.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef U_ENABLE_ME_PARSING_SUPPORT
|
||||
|
||||
// FPT
|
||||
#define ME_ROM_BYPASS_VECTOR_SIZE 0x10
|
||||
|
||||
const UByteArray ME_FPT_HEADER_SIGNATURE("\x24\x46\x50\x54", 4); //$FPT
|
||||
|
||||
typedef struct ME_FPT_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT32 NumEntries;
|
||||
UINT8 HeaderVersion;
|
||||
UINT8 EntryVersion;
|
||||
UINT8 HeaderLength;
|
||||
UINT8 Checksum; // One bit for Redundant before IFWI
|
||||
UINT16 TicksToAdd;
|
||||
UINT16 TokensToAdd;
|
||||
UINT32 UmaSize; // Flags in SPS
|
||||
UINT32 FlashLayout; // Crc32 before IFWI
|
||||
UINT16 FitcMajor;
|
||||
UINT16 FitcMinor;
|
||||
UINT16 FitcHotfix;
|
||||
UINT16 FitcBuild;
|
||||
} ME_FPT_HEADER;
|
||||
|
||||
typedef struct ME_FPT_ENTRY_{
|
||||
CHAR8 PartitionName[4];
|
||||
UINT8 Reserved1;
|
||||
UINT32 Offset;
|
||||
UINT32 Length;
|
||||
UINT8 Reserved2[12];
|
||||
UINT32 PartitionType : 7;
|
||||
UINT32 CopyToDramCache : 1;
|
||||
UINT32 Reserved3 : 7;
|
||||
UINT32 BuiltWithLength1 : 1;
|
||||
UINT32 BuiltWithLength2 : 1;
|
||||
UINT32 Reserved4 : 7;
|
||||
UINT32 EntryValid : 8;
|
||||
} ME_FPT_ENTRY;
|
||||
|
||||
|
||||
// IFWI
|
||||
typedef struct ME_IFWI_LAYOUT_HEADER_ {
|
||||
UINT8 RomBypassVector[16];
|
||||
UINT32 DataPartitionOffset;
|
||||
UINT32 DataPartitionSize;
|
||||
UINT32 Boot1Offset;
|
||||
UINT32 Boot1Size;
|
||||
UINT32 Boot2Offset;
|
||||
UINT32 Boot2Size;
|
||||
UINT32 Boot3Offset;
|
||||
UINT32 Boot3Size;
|
||||
} ME_IFWI_LAYOUT_HEADER;
|
||||
|
||||
|
||||
// BPDT
|
||||
const UByteArray ME_BPDT_GREEN_SIGNATURE("\xAA\x55\x00\x00", 4); //0x000055AA
|
||||
const UByteArray ME_BPDT_YELLOW_SIGNATURE("\xAA\x55\xAA\x00", 4); //0x00AA55AA
|
||||
|
||||
typedef struct ME_BPDT_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT16 NumEntries;
|
||||
UINT16 Version;
|
||||
UINT32 Checksum;
|
||||
UINT32 IfwiVersion;
|
||||
UINT16 FitcMajor;
|
||||
UINT16 FitcMinor;
|
||||
UINT16 FitcHotfix;
|
||||
UINT16 FitcBuild;
|
||||
} ME_BPDT_HEADER ;
|
||||
|
||||
typedef struct ME_BPDT_ENTRY_ {
|
||||
UINT32 Type : 16;
|
||||
UINT32 SplitSubPartitionFirstPart : 1;
|
||||
UINT32 SplitSubPartitionSecondPart : 1;
|
||||
UINT32 CodeSubPartition : 1;
|
||||
UINT32 UmaCachable : 1;
|
||||
UINT32 Reserved: 12;
|
||||
UINT32 Offset;
|
||||
UINT32 Length;
|
||||
} ME_BPDT_ENTRY;
|
||||
|
||||
// CPD
|
||||
const UByteArray ME_CPD_SIGNATURE("\x24\x43\x50\x44", 4); //$CPD
|
||||
|
||||
typedef struct ME_CPD_HEADER_ {
|
||||
UINT32 Signature;
|
||||
UINT32 NumEntries;
|
||||
UINT8 HeaderVersion;
|
||||
UINT8 EntryVersion;
|
||||
UINT8 HeaderLength;
|
||||
UINT8 HeaderChecksum;
|
||||
UINT8 ShortName[4];
|
||||
} ME_CPD_HEADER;
|
||||
|
||||
typedef struct ME_BPDT_CPD_ENTRY_ {
|
||||
UINT8 EntryName[12];
|
||||
struct {
|
||||
UINT32 Offset : 25;
|
||||
UINT32 HuffmanCompressed : 1;
|
||||
UINT32 Reserved : 6;
|
||||
} Offset;
|
||||
UINT32 Length;
|
||||
UINT32 Reserved;
|
||||
} ME_BPDT_CPD_ENTRY;
|
||||
|
||||
typedef struct ME_CPD_MANIFEST_HEADER_ {
|
||||
UINT32 HeaderType;
|
||||
UINT32 HeaderLength;
|
||||
UINT32 HeaderVersion;
|
||||
UINT32 Flags;
|
||||
UINT32 Vendor;
|
||||
UINT32 Date;
|
||||
UINT32 Size;
|
||||
UINT32 HeaderId;
|
||||
UINT32 Reserved1;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
UINT16 VersionBugfix;
|
||||
UINT16 VersionBuild;
|
||||
UINT32 SecurityVersion;
|
||||
UINT8 Reserved2[8];
|
||||
UINT8 Reserved3[64];
|
||||
UINT32 ModulusSize;
|
||||
UINT32 ExponentSize;
|
||||
//manifest_rsa_key_t public_key;
|
||||
//manifest_signature_t signature;
|
||||
} ME_CPD_MANIFEST_HEADER;
|
||||
|
||||
typedef struct ME_CPD_EXTENTION_HEADER_ {
|
||||
UINT32 Type;
|
||||
UINT32 Length;
|
||||
} ME_CPD_EXTENTION_HEADER;
|
||||
|
||||
typedef struct ME_CPD_EXT_SIGNED_PACKAGE_INFO_MODULES_ {
|
||||
UINT8 Name[12];
|
||||
UINT8 Type;
|
||||
UINT8 HashAlgorithm;
|
||||
UINT16 HashSize;
|
||||
UINT32 MetadataSize;
|
||||
UINT8 MetadataHash[32];
|
||||
} ME_CPD_EXT_SIGNED_PACKAGE_INFO_MODULES;
|
||||
|
||||
typedef struct ME_CPD_EXT_SIGNED_PACKAGE_INFO_ {
|
||||
UINT32 ExtensionType;
|
||||
UINT32 ExtensionLength;
|
||||
UINT8 PackageName[4];
|
||||
UINT32 Vcn;
|
||||
UINT8 UsageBitmap[16];
|
||||
UINT32 Svn;
|
||||
UINT8 Reserved[16];
|
||||
// ME_EXT_SIGNED_PACKAGE_INFO_MODULES Modules[];
|
||||
} ME_CPD_EXT_SIGNED_PACKAGE_INFO;
|
||||
|
||||
typedef struct ME_CPD_EXT_MODULE_ATTRIBUTES_ {
|
||||
UINT32 ExtensionType;
|
||||
UINT32 ExtensionLength;
|
||||
UINT8 CompressionType;
|
||||
UINT8 Reserved[3];
|
||||
UINT32 UncompressedSize;
|
||||
UINT32 CompressedSize;
|
||||
UINT32 GlobalModuleId;
|
||||
UINT8 ImageHash[32];
|
||||
} ME_CPD_EXT_MODULE_ATTRIBUTES;
|
||||
|
||||
typedef struct ME_CPD_EXT_IFWI_PARTITION_MANIFEST_ {
|
||||
UINT32 ExtensionType;
|
||||
UINT32 ExtensionLength;
|
||||
UINT8 PartitionName[4];
|
||||
UINT32 CompletePartitionLength;
|
||||
UINT16 PartitionVersionMinor;
|
||||
UINT16 PartitionVersionMajor;
|
||||
UINT32 DataFormatVersion;
|
||||
UINT32 InstanceId;
|
||||
UINT32 SupportMultipleInstances : 1;
|
||||
UINT32 SupportApiVersionBasedUpdate : 1;
|
||||
UINT32 ActionOnUpdate : 2;
|
||||
UINT32 ObeyFullUpdateRules : 1;
|
||||
UINT32 IfrEnableOnly : 1;
|
||||
UINT32 AllowCrossPointUpdate : 1;
|
||||
UINT32 AllowCrossHotfixUpdate : 1;
|
||||
UINT32 PartialUpdateOnly : 1;
|
||||
UINT32 ReservedFlags : 23;
|
||||
UINT32 HashAlgorithm : 8;
|
||||
UINT32 HashSize : 24;
|
||||
UINT8 CompletePartitionHash[32];
|
||||
UINT8 Reserved[20];
|
||||
} ME_CPD_EXT_IFWI_PARTITION_MANIFEST;
|
||||
|
||||
#define ME_MODULE_COMPRESSION_TYPE_UNCOMPRESSED 0
|
||||
#define ME_MODULE_COMPRESSION_TYPE_HUFFMAN 1
|
||||
#define ME_MODULE_COMPRESSION_TYPE_LZMA 2
|
||||
|
||||
#define ME_MANIFEST_HEADER_ID 0x324E4D24 //$MN2
|
||||
|
||||
|
||||
class MeParser
|
||||
{
|
||||
public:
|
||||
// Default constructor and destructor
|
||||
MeParser(TreeModel* treeModel) : model(treeModel) {}
|
||||
MeParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {}
|
||||
~MeParser() {}
|
||||
|
||||
// Returns messages
|
||||
@ -232,9 +39,9 @@ public:
|
||||
|
||||
// ME parsing
|
||||
USTATUS parseMeRegionBody(const UModelIndex & index);
|
||||
|
||||
private:
|
||||
TreeModel *model;
|
||||
FfsParser *ffsParser;
|
||||
std::vector<std::pair<UString, UModelIndex> > messagesVector;
|
||||
|
||||
void msg(const UString message, const UModelIndex index = UModelIndex()) {
|
||||
@ -242,19 +49,15 @@ private:
|
||||
}
|
||||
|
||||
USTATUS parseFptRegion(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseIfwiRegion(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseBpdtRegion(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
|
||||
|
||||
USTATUS parseCodePartitionDirectory(const UByteArray & directory, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseExtensionsArea(const UModelIndex & index);
|
||||
USTATUS parseSignedPackageInfoData(const UModelIndex & index);
|
||||
USTATUS parseIfwi16Region(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
|
||||
USTATUS parseIfwi17Region(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
|
||||
};
|
||||
#else
|
||||
class MeParser
|
||||
{
|
||||
public:
|
||||
// Default constructor and destructor
|
||||
MeParser(TreeModel* treeModel) { U_UNUSED_PARAMETER(treeModel); }
|
||||
MeParser(TreeModel* treeModel, FfsParser* parser) { U_UNUSED_PARAMETER(treeModel); U_UNUSED_PARAMETER(parser); }
|
||||
~MeParser() {}
|
||||
|
||||
// Returns messages
|
||||
|
@ -86,6 +86,11 @@ public:
|
||||
return UByteArray(hex);
|
||||
}
|
||||
|
||||
std::basic_string<char>::iterator begin() {return d.begin();}
|
||||
std::basic_string<char>::iterator end() {return d.end();}
|
||||
std::basic_string<char>::const_iterator begin() const {return d.begin();}
|
||||
std::basic_string<char>::const_iterator end() const {return d.end();}
|
||||
|
||||
private:
|
||||
std::basic_string<char> d;
|
||||
};
|
||||
@ -97,3 +102,4 @@ inline const UByteArray operator+(const UByteArray &a1, const UByteArray &a2)
|
||||
|
||||
#endif // QT_CORE_LIB
|
||||
#endif // UBYTEARRAY_H
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user