diff --git a/UEFIExtract/ffsdumper.cpp b/UEFIExtract/ffsdumper.cpp index da731e2..cb4b617 100644 --- a/UEFIExtract/ffsdumper.cpp +++ b/UEFIExtract/ffsdumper.cpp @@ -30,7 +30,7 @@ USTATUS FfsDumper::dump(const UModelIndex & root, const UString & path, const Du USTATUS result = recursiveDump(root, path, dumpMode, sectionType, guid); if (result) { - printf("Error %lu returned from recursiveDump (directory \"%s\").\n", result, (const char*)path.toLocal8Bit()); + printf("Error %zu returned from recursiveDump (directory \"%s\").\n", result, (const char*)path.toLocal8Bit()); return result; } else if (!dumped) { removeDirectory(path); @@ -199,7 +199,7 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path } result = recursiveDump(childIndex, childPath, dumpMode, sectionType, guid); if (result) { - printf("Error %lu returned from recursiveDump (child directory \"%s\").\n", result, (const char*)childPath.toLocal8Bit()); + printf("Error %zu returned from recursiveDump (child directory \"%s\").\n", result, (const char*)childPath.toLocal8Bit()); return result; } } diff --git a/UEFITool/hexlineedit.cpp b/UEFITool/hexlineedit.cpp index 1416270..e646dde 100644 --- a/UEFITool/hexlineedit.cpp +++ b/UEFITool/hexlineedit.cpp @@ -83,9 +83,4 @@ void HexLineEdit::keyPressEvent(QKeyEvent * event) // Call original event handler QLineEdit::keyPressEvent(event); - - if (event == QKeySequence::Paste) - { - clipboard->setText(originalText); - } } diff --git a/common/basetypes.h b/common/basetypes.h index 7b56bb9..17d09e2 100644 --- a/common/basetypes.h +++ b/common/basetypes.h @@ -75,13 +75,14 @@ typedef size_t USTATUS; #define U_UNKNOWN_PATCH_TYPE 53 #define U_PATCH_OFFSET_OUT_OF_BOUNDS 54 #define U_INVALID_SYMBOL 55 +#define U_ZLIB_DECOMPRESSION_FAILED 56 #define U_INVALID_MANIFEST 251 #define U_UNKNOWN_MANIFEST_HEADER_VERSION 252 #define U_INVALID_ME_PARTITION_TABLE 253 #define U_INVALID_ME_PARTITION 254 -#define U_NOT_IMPLEMENTED 0xFF +#define U_NOT_IMPLEMENTED 255 // EDK2 porting definitions typedef uint8_t BOOLEAN; diff --git a/common/ffs.cpp b/common/ffs.cpp index ae8709c..3025df1 100644 --- a/common/ffs.cpp +++ b/common/ffs.cpp @@ -94,6 +94,8 @@ extern const UByteArray EFI_GUIDED_SECTION_LZMAF86 // D42AE6BD-1352-4BFB-909A-CA ("\xBD\xE6\x2A\xD4\x52\x13\xFB\x4B\x90\x9A\xCA\x72\xA6\xEA\xE8\x89", 16); extern const UByteArray EFI_GUIDED_SECTION_GZIP // 1D301FE9-BE79-4353-91C2-D23BC959AE0C ("\xE9\x1F\x30\x1D\x79\xBE\x53\x43\x91\xC2\xD2\x3B\xC9\x59\xAE\x0C", 16); +extern const UByteArray EFI_GUIDED_SECTION_ZLIB_AMD // CE3233F5-2CD6-4D87-9152-4A238BB6D1C4 +("\xF5\x33\x32\xCE\xD6\x2C\x87\x4D\x91\x52\x4A\x23\x8B\xB6\xD1\xC4", 16); extern const UByteArray 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); extern const UByteArray EFI_CERT_TYPE_RSA2048_SHA256_GUID // A7717414-C616-4977-9420-844712A735BF diff --git a/common/ffs.h b/common/ffs.h index 037be44..55822fb 100644 --- a/common/ffs.h +++ b/common/ffs.h @@ -33,10 +33,10 @@ extern UString cpdExtensionTypeToUstring(const UINT32 type); //***************************************************************************** // Capsule header typedef struct EFI_CAPSULE_HEADER_ { - EFI_GUID CapsuleGuid; - UINT32 HeaderSize; - UINT32 Flags; - UINT32 CapsuleImageSize; + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; } EFI_CAPSULE_HEADER; // Capsule flags @@ -61,10 +61,10 @@ extern const UByteArray LENOVO2_CAPSULE_GUID; // 25B5FE76-8243-4A5C-A9BD-7EE3246 // Toshiba EFI Capsule header typedef struct TOSHIBA_CAPSULE_HEADER_ { - EFI_GUID CapsuleGuid; - UINT32 HeaderSize; - UINT32 FullSize; - UINT32 Flags; + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 FullSize; + UINT32 Flags; } TOSHIBA_CAPSULE_HEADER; // Toshiba capsule GUID @@ -72,11 +72,11 @@ extern const UByteArray TOSHIBA_CAPSULE_GUID; // 3BE07062-1D51-45D2-832B-F093257 // AMI Aptio extended capsule header typedef struct APTIO_CAPSULE_HEADER_ { - EFI_CAPSULE_HEADER CapsuleHeader; - UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of the capsule volume - UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume that are included in the signature calculation - //FW_CERTIFICATE FWCert; - //ROM_AREA RomAreaMap[1]; + EFI_CAPSULE_HEADER CapsuleHeader; + UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of the capsule volume + UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume that are included in the signature calculation + //FW_CERTIFICATE FWCert; + //ROM_AREA RomAreaMap[]; } APTIO_CAPSULE_HEADER; // AMI Aptio signed extended capsule GUID @@ -91,22 +91,22 @@ extern const UByteArray APTIO_UNSIGNED_CAPSULE_GUID; // 14EEBB90-890A-43DB-AED1- // Firmware block map entry // FvBlockMap ends with an entry {0x00000000, 0x00000000} typedef struct EFI_FV_BLOCK_MAP_ENTRY_ { - UINT32 NumBlocks; - UINT32 Length; + UINT32 NumBlocks; + UINT32 Length; } EFI_FV_BLOCK_MAP_ENTRY; // Volume header typedef struct EFI_FIRMWARE_VOLUME_HEADER_ { - UINT8 ZeroVector[16]; - EFI_GUID FileSystemGuid; - UINT64 FvLength; - UINT32 Signature; - UINT32 Attributes; - UINT16 HeaderLength; - UINT16 Checksum; - UINT16 ExtHeaderOffset; //Reserved in Revision 1 - UINT8 Reserved; - UINT8 Revision; + UINT8 ZeroVector[16]; + EFI_GUID FileSystemGuid; + UINT64 FvLength; + UINT32 Signature; + UINT32 Attributes; + UINT16 HeaderLength; + UINT16 Checksum; + UINT16 ExtHeaderOffset; //Reserved in Revision 1 + UINT8 Reserved; + UINT8 Revision; //EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2]; } EFI_FIRMWARE_VOLUME_HEADER; @@ -224,8 +224,8 @@ extern const std::vector FFSv3Volumes; // Extended firmware volume header typedef struct EFI_FIRMWARE_VOLUME_EXT_HEADER_ { - EFI_GUID FvName; - UINT32 ExtHeaderSize; + EFI_GUID FvName; + UINT32 ExtHeaderSize; } EFI_FIRMWARE_VOLUME_EXT_HEADER; // Extended header entry @@ -233,16 +233,16 @@ typedef struct EFI_FIRMWARE_VOLUME_EXT_HEADER_ { // terminated by ExtHeaderType EFI_FV_EXT_TYPE_END #define EFI_FV_EXT_TYPE_END 0x0000 typedef struct EFI_FIRMWARE_VOLUME_EXT_ENTRY_ { - UINT16 ExtEntrySize; - UINT16 ExtEntryType; + UINT16 ExtEntrySize; + UINT16 ExtEntryType; } EFI_FIRMWARE_VOLUME_EXT_ENTRY; // GUID that maps OEM file types to GUIDs #define EFI_FV_EXT_TYPE_OEM_TYPE 0x0001 typedef struct EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE_ { - EFI_FIRMWARE_VOLUME_EXT_ENTRY Header; - UINT32 TypeMask; - //EFI_GUID Types[]; + EFI_FIRMWARE_VOLUME_EXT_ENTRY Header; + UINT32 TypeMask; + //EFI_GUID Types[]; } EFI_FIRMWARE_VOLUME_EXT_HEADER_OEM_TYPE; #define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002 @@ -340,7 +340,6 @@ extern const UINT8 ffsAlignmentTable[]; // Extended FFS alignment table, added in UEFI PI 1.6 extern const UINT8 ffsAlignment2Table[]; - // File states #define EFI_FILE_HEADER_CONSTRUCTION 0x01 #define EFI_FILE_HEADER_VALID 0x02 @@ -377,15 +376,15 @@ extern UINT32 uint24ToUint32(const UINT8* ffsSize); //***************************************************************************** // Common section header typedef struct EFI_COMMON_SECTION_HEADER_ { - UINT8 Size[3]; - UINT8 Type; + UINT8 Size[3]; + UINT8 Type; } EFI_COMMON_SECTION_HEADER; // Large file common section header typedef struct EFI_COMMON_SECTION_HEADER2_ { - UINT8 Size[3]; // Must be 0xFFFFFF for this header to be used - UINT8 Type; - UINT32 ExtendedSize; + UINT8 Size[3]; // Must be 0xFFFFFF for this header to be used + UINT8 Type; + UINT32 ExtendedSize; } EFI_COMMON_SECTION_HEADER2; // Section2 usage indicator @@ -417,8 +416,8 @@ typedef struct EFI_COMMON_SECTION_HEADER2_ { // Compression section typedef struct EFI_COMPRESSION_SECTION_ { - UINT32 UncompressedLength; - UINT8 CompressionType; + UINT32 UncompressedLength; + UINT8 CompressionType; } EFI_COMPRESSION_SECTION; // Compression types @@ -445,10 +444,18 @@ extern const UByteArray EFI_GUIDED_SECTION_LZMA; // EE4E5898-3914-4259-9D6E-DC7B extern const UByteArray EFI_GUIDED_SECTION_LZMA_HP; // 0ED85E23-F253-413F-A03C-901987B04397 extern const UByteArray EFI_GUIDED_SECTION_LZMAF86; // D42AE6BD-1352-4BFB-909A-CA72A6EAE889 extern const UByteArray EFI_GUIDED_SECTION_GZIP; // 1D301FE9-BE79-4353-91C2-D23BC959AE0C +extern const UByteArray EFI_GUIDED_SECTION_ZLIB_AMD; // CE3233F5-2CD6-4D87-9152-4A238BB6D1C4 extern const UByteArray EFI_FIRMWARE_CONTENTS_SIGNED_GUID; // 0F9D89E8-9259-4F76-A5AF-0C89E34023DF -//#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 -#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +// AMD Zlib-compressed section header +typedef struct EFI_AMD_ZLIB_SECTION_HEADER_ { + UINT8 ZeroHeader[0x14]; + UINT32 CompressedSize; + UINT8 ZeroFooter[0x100 - sizeof(UINT32) - 0x14]; + //UINT8 CompressedData[] +} EFI_AMD_ZLIB_SECTION_HEADER; typedef struct WIN_CERTIFICATE_ { UINT32 Length; @@ -458,9 +465,9 @@ typedef struct WIN_CERTIFICATE_ { } 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 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 @@ -468,16 +475,16 @@ extern const UByteArray EFI_CERT_TYPE_RSA2048_SHA256_GUID; // A7717414-C616-4977 // WIN_CERTIFICATE_UEFI_GUID.CertData typedef struct EFI_CERT_BLOCK_RSA2048_SHA256_ { - EFI_GUID HashType; - UINT8 PublicKey[256]; - UINT8 Signature[256]; + EFI_GUID HashType; + UINT8 PublicKey[256]; + UINT8 Signature[256]; } EFI_CERT_BLOCK_RSA2048_SHA256; extern const UByteArray EFI_HASH_ALGORITHM_SHA256_GUID; // 51AA59DE-FDF2-4EA3-BC63-875FB7842EE9 // Version section typedef struct EFI_VERSION_SECTION_ { - UINT16 BuildNumber; + UINT16 BuildNumber; } EFI_VERSION_SECTION; // Freeform subtype GUID section @@ -487,11 +494,11 @@ typedef struct EFI_FREEFORM_SUBTYPE_GUID_SECTION_ { // Phoenix SCT and Insyde postcode section typedef struct POSTCODE_SECTION_ { - UINT32 Postcode; + UINT32 Postcode; } POSTCODE_SECTION; //***************************************************************************** -// EFI Dependency Expression +// EFI DXE Dependency Expression //***************************************************************************** #define EFI_DEP_OPCODE_SIZE 1 diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index bd79cd1..9567362 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -46,32 +46,6 @@ enum GlobalColor { } #endif -// Region info -struct REGION_INFO { - UINT32 offset; - UINT32 length; - UINT8 type; - UByteArray data; - 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; - bool hasMetaData; - 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), protectedRegionsBase(0) { @@ -175,7 +149,8 @@ USTATUS FfsParser::parseGenericImage(const UByteArray & buffer, const UINT32 loc index = model->addItem(localOffset, Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), buffer, UByteArray(), Fixed, parent); // Parse the image as raw area - protectedRegionsBase = imageBase = model->base(parent) + localOffset; + imageBase = model->base(parent) + localOffset; + protectedRegionsBase = imageBase; return parseRawArea(index); } @@ -1372,8 +1347,10 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l nextItemAlternativeSize = 0; const EFI_FV_BLOCK_MAP_ENTRY* entry = (const EFI_FV_BLOCK_MAP_ENTRY*)(data.constData() + offset - EFI_FV_SIGNATURE_OFFSET + sizeof(EFI_FIRMWARE_VOLUME_HEADER)); while (entry->NumBlocks != 0 && entry->Length != 0) { - if ((void*)entry >= data.constData() + data.size()) { - continue; + // Check if we are past the end of the volume + if ((const void*)entry >= data.constData() + data.size()) { + // This volume is broken, but we can't use continue here because we need to continue the outer loop + goto continue_searching; } nextItemAlternativeSize += entry->NumBlocks * entry->Length; @@ -1385,6 +1362,7 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l nextItemSize = (UINT32)volumeHeader->FvLength; nextItemOffset = offset - EFI_FV_SIGNATURE_OFFSET; break; +continue_searching: {} } else if (readUnaligned(currentPos) == BPDT_GREEN_SIGNATURE || readUnaligned(currentPos) == BPDT_YELLOW_SIGNATURE) { @@ -2371,6 +2349,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI bool msgUnknownCertType = false; bool msgUnknownCertSubtype = false; bool msgProcessingRequiredAttributeOnUnknownGuidedSection = false; + bool msgInvalidCompressedSize = false; if (baGuid == EFI_GUIDED_SECTION_CRC32) { if ((attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == 0) { // Check that AuthStatusValid attribute is set on compressed GUIDed sections msgNoAuthStatusAttribute = true; @@ -2390,14 +2369,38 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI additionalInfo += usprintf("\nChecksum: %08Xh, invalid, should be %08Xh", crc, calculated); msgInvalidCrc = true; } - // No need to change dataOffset here + + // Adjust dataOffset + dataOffset += sizeof(UINT32); } - else if (baGuid == EFI_GUIDED_SECTION_LZMA || baGuid == EFI_GUIDED_SECTION_LZMA_HP || baGuid == EFI_GUIDED_SECTION_LZMAF86 || baGuid == EFI_GUIDED_SECTION_TIANO || baGuid == EFI_GUIDED_SECTION_GZIP) { + else if (baGuid == EFI_GUIDED_SECTION_LZMA + || baGuid == EFI_GUIDED_SECTION_LZMA_HP + || baGuid == EFI_GUIDED_SECTION_LZMAF86 + || baGuid == EFI_GUIDED_SECTION_TIANO + || baGuid == EFI_GUIDED_SECTION_GZIP) { if ((attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { // Check that ProcessingRequired attribute is set on compressed GUIDed sections msgNoProcessingRequiredAttributeCompressed = true; } // No need to change dataOffset here } + else if (baGuid == EFI_GUIDED_SECTION_ZLIB_AMD) { + if ((attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { // Check that ProcessingRequired attribute is set on compressed GUIDed sections + msgNoProcessingRequiredAttributeCompressed = true; + } + + if ((UINT32)section.size() < headerSize + sizeof(EFI_AMD_ZLIB_SECTION_HEADER)) + return U_INVALID_SECTION; + + const EFI_AMD_ZLIB_SECTION_HEADER* amdZlibSectionHeader = (const EFI_AMD_ZLIB_SECTION_HEADER*)(section.constData() + headerSize); + + // Check the compressed size to be sane + if ((UINT32)section.size() != headerSize + sizeof(EFI_AMD_ZLIB_SECTION_HEADER) + amdZlibSectionHeader->CompressedSize) { + msgInvalidCompressedSize = true; + } + + // Adjust dataOffset + dataOffset += sizeof(EFI_AMD_ZLIB_SECTION_HEADER); + } else if (baGuid == EFI_CERT_TYPE_RSA2048_SHA256_GUID) { if ((attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { // Check that ProcessingRequired attribute is set on signed GUIDed sections msgNoProcessingRequiredAttributeSigned = true; @@ -2465,12 +2468,11 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI // Get info UString name = guidToUString(guid); UString info = UString("Section GUID: ") + guidToUString(guid, false) + - usprintf("\nType: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nData offset: %Xh\nAttributes: %04Xh", + usprintf("\nType: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nAttributes: %04Xh", sectionHeader->Type, (UINT32)section.size(), (UINT32)section.size(), (UINT32)header.size(), (UINT32)header.size(), (UINT32)body.size(), (UINT32)body.size(), - dataOffset, attributes); // Append additional info @@ -2487,7 +2489,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI // Show messages if (msgSignedSectionFound) - msg(usprintf("%s: section signature may become invalid after any modification", __FUNCTION__), index); + msg(usprintf("%s: GUIDed section signature may become invalid after modification", __FUNCTION__), index); if (msgNoAuthStatusAttribute) msg(usprintf("%s: CRC32 GUIDed section without AuthStatusValid attribute", __FUNCTION__), index); if (msgNoProcessingRequiredAttributeCompressed) @@ -2495,13 +2497,15 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI if (msgNoProcessingRequiredAttributeSigned) msg(usprintf("%s: signed GUIDed section without ProcessingRequired attribute", __FUNCTION__), index); if (msgInvalidCrc) - msg(usprintf("%s: GUID defined section with invalid CRC32", __FUNCTION__), index); + msg(usprintf("%s: CRC32 GUIDed section with invalid checksum", __FUNCTION__), index); if (msgUnknownCertType) - msg(usprintf("%s: signed GUIDed section with unknown type", __FUNCTION__), index); + msg(usprintf("%s: signed GUIDed section with unknown certificate type", __FUNCTION__), index); if (msgUnknownCertSubtype) - msg(usprintf("%s: signed GUIDed section with unknown subtype", __FUNCTION__), index); + msg(usprintf("%s: signed GUIDed section with unknown certificate subtype", __FUNCTION__), index); if (msgProcessingRequiredAttributeOnUnknownGuidedSection) msg(usprintf("%s: processing required bit set for GUIDed section with unknown GUID", __FUNCTION__), index); + if (msgInvalidCompressedSize) + msg(usprintf("%s: AMD Zlib-compressed section with invalid compressed size", __FUNCTION__), index); } return U_SUCCESS; @@ -2706,11 +2710,11 @@ USTATUS FfsParser::parseSectionBody(const UModelIndex & index) const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(header.constData()); switch (sectionHeader->Type) { - // Encapsulation + // Encapsulation case EFI_SECTION_COMPRESSION: return parseCompressedSectionBody(index); case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionBody(index); case EFI_SECTION_DISPOSABLE: return parseSections(model->body(index), index, true); - // Leaf + // Leaf case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseRawArea(index); case EFI_SECTION_VERSION: return parseVersionSectionBody(index); case EFI_SECTION_DXE_DEPEX: @@ -2722,7 +2726,7 @@ USTATUS FfsParser::parseSectionBody(const UModelIndex & index) case EFI_SECTION_USER_INTERFACE: return parseUiSectionBody(index); case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return parseRawArea(index); case EFI_SECTION_RAW: return parseRawSectionBody(index); - // No parsing needed + // No parsing needed case EFI_SECTION_COMPATIBILITY16: case PHOENIX_SECTION_POSTCODE: case INSYDE_SECTION_POSTCODE: @@ -2906,6 +2910,17 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) info += UString("\nCompression algorithm: GZip"); info += usprintf("\nDecompressed size: %Xh (%u)", (UINT32)processed.size(), (UINT32)processed.size()); } + // Zlib compressed section + else if (baGuid == EFI_GUIDED_SECTION_ZLIB_AMD) { + USTATUS result = zlibDecompress(model->body(index), processed); + if (result) { + msg(usprintf("%s: decompression failed with error ", __FUNCTION__) + errorCodeToUString(result), index); + return U_SUCCESS; + } + + info += UString("\nCompression algorithm: Zlib"); + info += usprintf("\nDecompressed size: %Xh (%u)", (UINT32)processed.size(), (UINT32)processed.size()); + } // Add info model->addInfo(index, info); @@ -3212,7 +3227,7 @@ USTATUS FfsParser::parsePeImageSectionBody(const UModelIndex & index) imageFileHeader->NumberOfSections, imageFileHeader->Characteristics); - EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION optionalHeader; + EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION optionalHeader = {}; optionalHeader.H32 = (const EFI_IMAGE_OPTIONAL_HEADER32*)(imageFileHeader + 1); if (body.size() < (UINT8*)optionalHeader.H32 - (UINT8*)dosHeader) { info += UString("\nPE optional header: invalid"); diff --git a/common/ffsparser.h b/common/ffsparser.h index 162fda4..3cd6ab7 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -20,8 +20,36 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "ubytearray.h" #include "treemodel.h" #include "intel_microcode.h" +#include "ffs.h" #include "fitparser.h" +// Region info +typedef struct REGION_INFO_ { + UINT32 offset = 0; + UINT32 length = 0; + UINT8 type = 0; + UByteArray data; + friend bool operator< (const struct REGION_INFO_ & lhs, const struct REGION_INFO_ & rhs) { return lhs.offset < rhs.offset; } +} REGION_INFO; + +// BPDT partition info +typedef struct BPDT_PARTITION_INFO_ { + BPDT_ENTRY ptEntry = {}; + UINT8 type = 0; + UModelIndex index; + friend bool operator< (const struct BPDT_PARTITION_INFO_ & lhs, const struct BPDT_PARTITION_INFO_ & rhs) { return lhs.ptEntry.Offset < rhs.ptEntry.Offset; } +} BPDT_PARTITION_INFO; + +// CPD partition info +typedef struct CPD_PARTITION_INFO_ { + CPD_ENTRY ptEntry = {}; + UINT8 type = 0; + bool hasMetaData = false; + UModelIndex index; + friend bool operator< (const struct CPD_PARTITION_INFO_ & lhs, const struct CPD_PARTITION_INFO_ & rhs) { return lhs.ptEntry.Offset.Offset < rhs.ptEntry.Offset.Offset; } +} CPD_PARTITION_INFO; + +// Protected range typedef struct PROTECTED_RANGE_ { UINT32 Offset; UINT32 Size; diff --git a/common/utility.cpp b/common/utility.cpp index 6124d66..ba6d9c9 100755 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -526,20 +526,20 @@ USTATUS gzipDecompress(const UByteArray & input, UByteArray & output) if (input.size() == 0) return U_SUCCESS; - z_stream stream; + z_stream stream = {}; stream.next_in = (z_const Bytef *)input.data(); stream.avail_in = (uInt)input.size(); stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL; - // 15 for the maximum history buffer, 16 for gzip only input. + // 15 for the maximum history buffer, 16 for gzip only input int ret = inflateInit2(&stream, 15U | 16U); if (ret != Z_OK) return U_GZIP_DECOMPRESSION_FAILED; while (ret == Z_OK) { - Bytef out[4096]; + Bytef out[0x1000] = {}; stream.next_out = out; stream.avail_out = sizeof(out); @@ -551,3 +551,36 @@ USTATUS gzipDecompress(const UByteArray & input, UByteArray & output) inflateEnd(&stream); return ret == Z_STREAM_END ? U_SUCCESS : U_GZIP_DECOMPRESSION_FAILED; } + +USTATUS zlibDecompress(const UByteArray& input, UByteArray& output) +{ + output.clear(); + + if (input.size() == 0) + return U_SUCCESS; + + z_stream stream = {}; + stream.next_in = (z_const Bytef*)input.data(); + stream.avail_in = (uInt)input.size(); + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + + // 15 for the maximum history buffer + int ret = inflateInit2(&stream, 15U); + if (ret != Z_OK) + return U_ZLIB_DECOMPRESSION_FAILED; + + while (ret == Z_OK) { + Bytef out[0x1000] = {}; + stream.next_out = out; + stream.avail_out = sizeof(out); + + ret = inflate(&stream, Z_NO_FLUSH); + if ((ret == Z_OK || ret == Z_STREAM_END) && stream.avail_out != sizeof(out)) + output += UByteArray((char*)out, sizeof(out) - stream.avail_out); + } + + inflateEnd(&stream); + return ret == Z_STREAM_END ? U_SUCCESS : U_ZLIB_DECOMPRESSION_FAILED; +} \ No newline at end of file diff --git a/common/utility.h b/common/utility.h index b3583a6..8f8dfe2 100755 --- a/common/utility.h +++ b/common/utility.h @@ -41,6 +41,9 @@ USTATUS decompress(const UByteArray & compressed, const UINT8 compressionType, U // GZIP decompression routine USTATUS gzipDecompress(const UByteArray & compressed, UByteArray & decompressed); +// ZLIB decompression routine +USTATUS zlibDecompress(const UByteArray& compressed, UByteArray& decompressed); + // 8bit sum calculation routine UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize); @@ -66,7 +69,7 @@ INTN findPattern(const UINT8 *pattern, const UINT8 *patternMask, UINTN patternSi // Safely dereferences misaligned pointers template inline T readUnaligned(const T *v) { - T tmp; + T tmp = {}; memcpy(&tmp, v, sizeof(T)); return tmp; }