diff --git a/UEFIExtract/CMakeLists.txt b/UEFIExtract/CMakeLists.txt index 5cf1a01..5297c34 100644 --- a/UEFIExtract/CMakeLists.txt +++ b/UEFIExtract/CMakeLists.txt @@ -20,6 +20,7 @@ SET(PROJECT_SOURCES ../common/treemodel.cpp ../common/utility.cpp ../common/LZMA/LzmaDecompress.c + ../common/LZMA/SDK/C/Bra86.c ../common/LZMA/SDK/C/LzmaDec.c ../common/Tiano/EfiTianoDecompress.c ../common/ustring.cpp diff --git a/UEFIFind/CMakeLists.txt b/UEFIFind/CMakeLists.txt index 9ae59ee..efd8b80 100644 --- a/UEFIFind/CMakeLists.txt +++ b/UEFIFind/CMakeLists.txt @@ -19,6 +19,7 @@ SET(PROJECT_SOURCES ../common/treemodel.cpp ../common/utility.cpp ../common/LZMA/LzmaDecompress.c + ../common/LZMA/SDK/C/Bra86.c ../common/LZMA/SDK/C/LzmaDec.c ../common/Tiano/EfiTianoDecompress.c ../common/ustring.cpp diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro index 70b61a7..00dd530 100644 --- a/UEFITool/uefitool.pro +++ b/UEFITool/uefitool.pro @@ -86,6 +86,7 @@ SOURCES += uefitool_main.cpp \ ../common/treemodel.cpp \ ../common/LZMA/LzmaCompress.c \ ../common/LZMA/LzmaDecompress.c \ + ../common/LZMA/SDK/C/Bra86.c \ ../common/LZMA/SDK/C/LzFind.c \ ../common/LZMA/SDK/C/LzmaDec.c \ ../common/LZMA/SDK/C/LzmaEnc.c \ diff --git a/common/LZMA/LzmaDecompress.h b/common/LZMA/LzmaDecompress.h index 82a162c..1b9d8cf 100644 --- a/common/LZMA/LzmaDecompress.h +++ b/common/LZMA/LzmaDecompress.h @@ -16,6 +16,7 @@ #include "../basetypes.h" #include "SDK/C/LzmaDec.h" +#include "SDK/C/Bra.h" #ifdef __cplusplus extern "C" { diff --git a/common/basetypes.h b/common/basetypes.h index 5b9bb0c..0eeb69b 100644 --- a/common/basetypes.h +++ b/common/basetypes.h @@ -132,7 +132,9 @@ typedef ptrdiff_t INTN; #define COMPRESSION_ALGORITHM_UNDECIDED 4 #define COMPRESSION_ALGORITHM_LZMA 5 #define COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY 6 -#define COMPRESSION_ALGORITHM_GZIP 7 +#define COMPRESSION_ALGORITHM_LZMAF86 7 +#define COMPRESSION_ALGORITHM_GZIP 8 + // Item create modes #define CREATE_MODE_APPEND 0 diff --git a/common/ffs.h b/common/ffs.h index 441e09a..8cf6464 100644 --- a/common/ffs.h +++ b/common/ffs.h @@ -453,9 +453,10 @@ typedef struct EFI_COMPRESSION_SECTION_APPLE_ { } EFI_COMPRESSION_SECTION_APPLE; // Compression types -#define EFI_NOT_COMPRESSED 0x00 -#define EFI_STANDARD_COMPRESSION 0x01 -#define EFI_CUSTOMIZED_COMPRESSION 0x02 +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +#define EFI_CUSTOMIZED_COMPRESSION 0x02 +#define EFI_CUSTOMIZED_COMPRESSION_LZMAF86 0x86 //GUID defined section typedef struct EFI_GUID_DEFINED_SECTION_ { diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 4e0b663..5bc0ef8 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -2762,7 +2762,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) info += usprintf("\nDecompressed size: %Xh (%u)", processed.size(), processed.size()); } // LZMA compressed section - else if (baGuid == EFI_GUIDED_SECTION_LZMA || baGuid == EFI_GUIDED_SECTION_LZMAF86) { + else if (baGuid == EFI_GUIDED_SECTION_LZMA) { USTATUS result = decompress(model->body(index), EFI_CUSTOMIZED_COMPRESSION, algorithm, dictionarySize, processed, efiDecompressed); if (result) { msg(usprintf("%s: decompression failed with error ", __FUNCTION__) + errorCodeToUString(result), index); @@ -2779,6 +2779,24 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) parseCurrentSection = false; } } + // LZMAF86 compressed section + else if (baGuid == EFI_GUIDED_SECTION_LZMAF86) { + USTATUS result = decompress(model->body(index), EFI_CUSTOMIZED_COMPRESSION_LZMAF86, algorithm, dictionarySize, processed, efiDecompressed); + if (result) { + msg(usprintf("%s: decompression failed with error ", __FUNCTION__) + errorCodeToUString(result), index); + return U_SUCCESS; + } + + if (algorithm == COMPRESSION_ALGORITHM_LZMAF86) { + info += UString("\nCompression algorithm: LZMAF86"); + info += usprintf("\nDecompressed size: %Xh (%u)", processed.size(), processed.size()); + info += usprintf("\nLZMA dictionary size: %Xh", dictionarySize); + } + else { + info += UString("\nCompression algorithm: unknown"); + parseCurrentSection = false; + } + } // GZip compressed section else if (baGuid == EFI_GUIDED_SECTION_GZIP) { USTATUS result = gzipDecompress(model->body(index), processed); diff --git a/common/meparser.cpp b/common/meparser.cpp index bd04256..c53c2c6 100755 --- a/common/meparser.cpp +++ b/common/meparser.cpp @@ -283,7 +283,7 @@ make_partition_table_consistent: // Add tree item UINT8 type = Subtypes::CodeFptPartition + partitions[i].ptEntry.Type; partitionIndex = model->addItem(partitions[i].ptEntry.Offset, Types::FptPartition, type, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent); - if (type == Subtypes::CodeFptPartition && partition.size() >= sizeof(UINT32) && readUnaligned((const UINT32*)partition.constData()) == CPD_SIGNATURE) { + if (type == Subtypes::CodeFptPartition && partition.size() >= (int) sizeof(UINT32) && readUnaligned((const UINT32*)partition.constData()) == CPD_SIGNATURE) { // Parse code partition contents UModelIndex cpdIndex; ffsParser->parseCpdRegion(partition, partitions[i].ptEntry.Offset, partitionIndex, cpdIndex); diff --git a/common/utility.cpp b/common/utility.cpp index f08e028..b0d2df4 100755 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -163,10 +163,11 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp switch (compressionType) { - case EFI_NOT_COMPRESSED: + case EFI_NOT_COMPRESSED: { decompressedData = compressedData; algorithm = COMPRESSION_ALGORITHM_NONE; return U_SUCCESS; + } case EFI_STANDARD_COMPRESSION: { // Set default algorithm to unknown algorithm = COMPRESSION_ALGORITHM_UNKNOWN; @@ -226,8 +227,8 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp free(efiDecompressed); free(scratch); return result; - } - case EFI_CUSTOMIZED_COMPRESSION: + } + case EFI_CUSTOMIZED_COMPRESSION: { // Set default algorithm to unknown algorithm = COMPRESSION_ALGORITHM_UNKNOWN; @@ -271,12 +272,60 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp decompressedData = UByteArray((const char*)decompressed, (int)decompressedSize); free(decompressed); return U_SUCCESS; - default: + } + case EFI_CUSTOMIZED_COMPRESSION_LZMAF86: { + // Set default algorithm to unknown + algorithm = COMPRESSION_ALGORITHM_UNKNOWN; + + // Get buffer sizes + data = (const UINT8*)compressedData.constData(); + dataSize = compressedData.size(); + + // Get info as normal LZMA section + if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) { + return U_CUSTOMIZED_DECOMPRESSION_FAILED; + } + algorithm = COMPRESSION_ALGORITHM_LZMAF86; + + // Allocate memory + decompressed = (UINT8*)malloc(decompressedSize); + if (!decompressed) { + return U_OUT_OF_MEMORY; + } + + // Decompress section data + if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) { + free(decompressed); + return U_CUSTOMIZED_DECOMPRESSION_FAILED; + } + + if (decompressedSize > INT32_MAX) { + free(decompressed); + return U_CUSTOMIZED_DECOMPRESSION_FAILED; + } + + // After LZMA decompression, the data need to be converted to the raw data. + UINT32 state = 0; + const UINT8 x86LookAhead = 4; + if (decompressedSize != x86LookAhead + x86_Convert(decompressed, decompressedSize, 0, &state, 0)) { + free(decompressed); + return U_CUSTOMIZED_DECOMPRESSION_FAILED; + } + + dictionarySize = readUnaligned((UINT32*)(data + 1)); // LZMA dictionary size is stored in bytes 1-4 of LZMA properties header + decompressedData = UByteArray((const char*)decompressed, (int)decompressedSize); + free(decompressed); + return U_SUCCESS; + } + default: { algorithm = COMPRESSION_ALGORITHM_UNKNOWN; return U_UNKNOWN_COMPRESSION_TYPE; + } } } + + // 8bit sum calculation routine UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize) {