mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Import legacy bugfixes found over time
- Fix mishandling empty microcode entries - Fix mishandling TE image base - Fix Intel legacy LZMA support
This commit is contained in:
parent
f2e343d8bf
commit
1b2ea8c276
@ -131,7 +131,7 @@ typedef ptrdiff_t INTN;
|
||||
#define COMPRESSION_ALGORITHM_TIANO 3
|
||||
#define COMPRESSION_ALGORITHM_UNDECIDED 4
|
||||
#define COMPRESSION_ALGORITHM_LZMA 5
|
||||
#define COMPRESSION_ALGORITHM_IMLZMA 6
|
||||
#define COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY 6
|
||||
#define COMPRESSION_ALGORITHM_GZIP 7
|
||||
|
||||
// Item create modes
|
||||
|
@ -1312,11 +1312,14 @@ 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;
|
||||
nextItemSize = ucodeHeader->TotalSize;
|
||||
@ -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)));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -179,7 +179,7 @@ UString compressionTypeToUString(const UINT8 algorithm)
|
||||
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_LZMA_INTEL_LEGACY: return UString("Intel legacy LZMA");
|
||||
}
|
||||
|
||||
return UString("Unknown");
|
||||
|
@ -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))
|
||||
// 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);
|
||||
}
|
||||
|
||||
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:
|
||||
|
Loading…
Reference in New Issue
Block a user