diff --git a/common/basetypes.h b/common/basetypes.h index a16030f..5b9bb0c 100644 --- a/common/basetypes.h +++ b/common/basetypes.h @@ -125,14 +125,14 @@ typedef ptrdiff_t INTN; #define EFI_ERROR(X) (X) // Compression algorithms -#define COMPRESSION_ALGORITHM_UNKNOWN 0 -#define COMPRESSION_ALGORITHM_NONE 1 -#define COMPRESSION_ALGORITHM_EFI11 2 -#define COMPRESSION_ALGORITHM_TIANO 3 -#define COMPRESSION_ALGORITHM_UNDECIDED 4 -#define COMPRESSION_ALGORITHM_LZMA 5 -#define COMPRESSION_ALGORITHM_IMLZMA 6 -#define COMPRESSION_ALGORITHM_GZIP 7 +#define COMPRESSION_ALGORITHM_UNKNOWN 0 +#define COMPRESSION_ALGORITHM_NONE 1 +#define COMPRESSION_ALGORITHM_EFI11 2 +#define COMPRESSION_ALGORITHM_TIANO 3 +#define COMPRESSION_ALGORITHM_UNDECIDED 4 +#define COMPRESSION_ALGORITHM_LZMA 5 +#define COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY 6 +#define COMPRESSION_ALGORITHM_GZIP 7 // Item create modes #define CREATE_MODE_APPEND 0 diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index f9c9df1..7e830fe 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -1312,10 +1312,13 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l // Check microcode header candidate const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos; - if (FALSE == microcodeHeaderValid(ucodeHeader)) { continue; } + + // Check size candidate + if (ucodeHeader->TotalSize == 0) + continue; // All checks passed, microcode found nextItemType = Types::Microcode; @@ -1399,8 +1402,9 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l } // No more stores found - if (offset >= dataSize - sizeof(UINT32)) + if (offset >= dataSize - sizeof(UINT32)) { return U_STORES_NOT_FOUND; + } return U_SUCCESS; } @@ -2683,7 +2687,7 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index) // Add info model->addInfo(index, UString("\nCompression algorithm: ") + compressionTypeToUString(algorithm)); - if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_IMLZMA) { + if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY) { model->addInfo(index, usprintf("\nLZMA dictionary size: %Xh", dictionarySize)); } @@ -3146,7 +3150,7 @@ USTATUS FfsParser::parseTeImageSectionBody(const UModelIndex & index) // Update parsing data TE_IMAGE_SECTION_PARSING_DATA pdata; pdata.imageBaseType = EFI_IMAGE_TE_BASE_OTHER; // Will be determined later - pdata.imageBase = (UINT32)teHeader->ImageBase; + pdata.originalImageBase = (UINT32)teHeader->ImageBase; pdata.adjustedImageBase = (UINT32)(teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER)); model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); @@ -3236,16 +3240,16 @@ USTATUS FfsParser::checkTeImageBase(const UModelIndex & index) if (model->hasEmptyParsingData(index) == false) { UByteArray data = model->parsingData(index); const TE_IMAGE_SECTION_PARSING_DATA* pdata = (const TE_IMAGE_SECTION_PARSING_DATA*)data.constData(); - originalImageBase = readUnaligned(pdata).imageBase; + originalImageBase = readUnaligned(pdata).originalImageBase; adjustedImageBase = readUnaligned(pdata).adjustedImageBase; } - if (imageBase != 0) { - // Check data memory address to be equal to either ImageBase or AdjustedImageBase + if (originalImageBase != 0 || adjustedImageBase != 0) { + // Check data memory address to be equal to either OriginalImageBase or AdjustedImageBase UINT64 address = addressDiff + model->base(index); UINT32 base = (UINT32)address + model->header(index).size(); - if (imageBase == base) { + if (originalImageBase == base) { imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL; } else if (adjustedImageBase == base) { @@ -3253,7 +3257,7 @@ USTATUS FfsParser::checkTeImageBase(const UModelIndex & index) } else { // Check for one-bit difference - UINT32 xored = base ^ imageBase; // XOR result can't be zero + UINT32 xored = base ^ originalImageBase; // XOR result can't be zero if ((xored & (xored - 1)) == 0) { // Check that XOR result is a power of 2, i.e. has exactly one bit set imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL; } @@ -3266,13 +3270,14 @@ USTATUS FfsParser::checkTeImageBase(const UModelIndex & index) } // Show message if imageBaseType is still unknown - if (imageBaseType == EFI_IMAGE_TE_BASE_OTHER) + if (imageBaseType == EFI_IMAGE_TE_BASE_OTHER) { msg(usprintf("%s: TE image base is neither zero, nor original, nor adjusted, nor top-swapped", __FUNCTION__), index); + } // Update parsing data TE_IMAGE_SECTION_PARSING_DATA pdata; pdata.imageBaseType = imageBaseType; - pdata.imageBase = originalImageBase; + pdata.originalImageBase = originalImageBase; pdata.adjustedImageBase = adjustedImageBase; model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); } diff --git a/common/parsingdata.h b/common/parsingdata.h index ad3ca54..9179171 100644 --- a/common/parsingdata.h +++ b/common/parsingdata.h @@ -54,7 +54,7 @@ typedef struct COMPRESSED_SECTION_PARSING_DATA_ { } COMPRESSED_SECTION_PARSING_DATA; typedef struct TE_IMAGE_SECTION_PARSING_DATA_ { - UINT32 imageBase; + UINT32 originalImageBase; UINT32 adjustedImageBase; UINT8 imageBaseType; } TE_IMAGE_SECTION_PARSING_DATA; diff --git a/common/types.cpp b/common/types.cpp index ca365ba..1deb862 100755 --- a/common/types.cpp +++ b/common/types.cpp @@ -174,12 +174,12 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype) UString compressionTypeToUString(const UINT8 algorithm) { switch (algorithm) { - case COMPRESSION_ALGORITHM_NONE: return UString("None"); - case COMPRESSION_ALGORITHM_EFI11: return UString("EFI 1.1"); - case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano"); - case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1"); - case COMPRESSION_ALGORITHM_LZMA: return UString("LZMA"); - case COMPRESSION_ALGORITHM_IMLZMA: return UString("Intel LZMA"); + case COMPRESSION_ALGORITHM_NONE: return UString("None"); + case COMPRESSION_ALGORITHM_EFI11: return UString("EFI 1.1"); + case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano"); + case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1"); + case COMPRESSION_ALGORITHM_LZMA: return UString("LZMA"); + case COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY: return UString("Intel legacy LZMA"); } return UString("Unknown"); diff --git a/common/utility.cpp b/common/utility.cpp index 929e16d..f7b0fb3 100755 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -235,56 +235,39 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp data = (const UINT8*)compressedData.constData(); dataSize = compressedData.size(); - // Get info - if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) - return U_CUSTOMIZED_DECOMPRESSION_FAILED; + // Get info as normal LZMA section + if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) { + // Get info as Intel legacy LZMA section + data += sizeof(UINT32); + if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) { + return U_CUSTOMIZED_DECOMPRESSION_FAILED; + } + else { + algorithm = COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY; + } + } + else { + algorithm = COMPRESSION_ALGORITHM_LZMA; + } // Allocate memory decompressed = (UINT8*)malloc(decompressedSize); if (!decompressed) { - return U_STANDARD_DECOMPRESSION_FAILED; + return U_OUT_OF_MEMORY; } // Decompress section data if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) { - // Intel modified LZMA workaround - // Decompress section data once again - - // VERIFY: might be wrong assumption, 0.2x had a different code here - // See: https://github.com/LongSoft/UEFITool/blob/4bee991c949b458739ffa96b88dbc589192c7689/ffsengine.cpp#L2814-L2823 - data += sizeof(UINT32); - - // Get info again - if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) { - free(decompressed); - return U_CUSTOMIZED_DECOMPRESSION_FAILED; - } - - // Decompress section data again - if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) { - free(decompressed); - return U_CUSTOMIZED_DECOMPRESSION_FAILED; - } - else { - if (decompressedSize > INT32_MAX) { - free(decompressed); - return U_CUSTOMIZED_DECOMPRESSION_FAILED; - } - algorithm = COMPRESSION_ALGORITHM_IMLZMA; - 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); - } - } - else { - if (decompressedSize > INT32_MAX) { - free(decompressed); - return U_CUSTOMIZED_DECOMPRESSION_FAILED; - } - algorithm = COMPRESSION_ALGORITHM_LZMA; - 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); + return U_CUSTOMIZED_DECOMPRESSION_FAILED; } + if (decompressedSize > INT32_MAX) { + 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: