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
@ -125,14 +125,14 @@ typedef ptrdiff_t INTN;
|
|||||||
#define EFI_ERROR(X) (X)
|
#define EFI_ERROR(X) (X)
|
||||||
|
|
||||||
// Compression algorithms
|
// Compression algorithms
|
||||||
#define COMPRESSION_ALGORITHM_UNKNOWN 0
|
#define COMPRESSION_ALGORITHM_UNKNOWN 0
|
||||||
#define COMPRESSION_ALGORITHM_NONE 1
|
#define COMPRESSION_ALGORITHM_NONE 1
|
||||||
#define COMPRESSION_ALGORITHM_EFI11 2
|
#define COMPRESSION_ALGORITHM_EFI11 2
|
||||||
#define COMPRESSION_ALGORITHM_TIANO 3
|
#define COMPRESSION_ALGORITHM_TIANO 3
|
||||||
#define COMPRESSION_ALGORITHM_UNDECIDED 4
|
#define COMPRESSION_ALGORITHM_UNDECIDED 4
|
||||||
#define COMPRESSION_ALGORITHM_LZMA 5
|
#define COMPRESSION_ALGORITHM_LZMA 5
|
||||||
#define COMPRESSION_ALGORITHM_IMLZMA 6
|
#define COMPRESSION_ALGORITHM_LZMA_INTEL_LEGACY 6
|
||||||
#define COMPRESSION_ALGORITHM_GZIP 7
|
#define COMPRESSION_ALGORITHM_GZIP 7
|
||||||
|
|
||||||
// Item create modes
|
// Item create modes
|
||||||
#define CREATE_MODE_APPEND 0
|
#define CREATE_MODE_APPEND 0
|
||||||
|
@ -1312,10 +1312,13 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
|
|||||||
|
|
||||||
// Check microcode header candidate
|
// Check microcode header candidate
|
||||||
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
|
||||||
|
|
||||||
if (FALSE == microcodeHeaderValid(ucodeHeader)) {
|
if (FALSE == microcodeHeaderValid(ucodeHeader)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check size candidate
|
||||||
|
if (ucodeHeader->TotalSize == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
// All checks passed, microcode found
|
// All checks passed, microcode found
|
||||||
nextItemType = Types::Microcode;
|
nextItemType = Types::Microcode;
|
||||||
@ -1399,8 +1402,9 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No more stores found
|
// No more stores found
|
||||||
if (offset >= dataSize - sizeof(UINT32))
|
if (offset >= dataSize - sizeof(UINT32)) {
|
||||||
return U_STORES_NOT_FOUND;
|
return U_STORES_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -2683,7 +2687,7 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index)
|
|||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
model->addInfo(index, UString("\nCompression algorithm: ") + compressionTypeToUString(algorithm));
|
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));
|
model->addInfo(index, usprintf("\nLZMA dictionary size: %Xh", dictionarySize));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3146,7 +3150,7 @@ USTATUS FfsParser::parseTeImageSectionBody(const UModelIndex & index)
|
|||||||
// Update parsing data
|
// Update parsing data
|
||||||
TE_IMAGE_SECTION_PARSING_DATA pdata;
|
TE_IMAGE_SECTION_PARSING_DATA pdata;
|
||||||
pdata.imageBaseType = EFI_IMAGE_TE_BASE_OTHER; // Will be determined later
|
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));
|
pdata.adjustedImageBase = (UINT32)(teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER));
|
||||||
model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata)));
|
model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata)));
|
||||||
|
|
||||||
@ -3236,16 +3240,16 @@ USTATUS FfsParser::checkTeImageBase(const UModelIndex & index)
|
|||||||
if (model->hasEmptyParsingData(index) == false) {
|
if (model->hasEmptyParsingData(index) == false) {
|
||||||
UByteArray data = model->parsingData(index);
|
UByteArray data = model->parsingData(index);
|
||||||
const TE_IMAGE_SECTION_PARSING_DATA* pdata = (const TE_IMAGE_SECTION_PARSING_DATA*)data.constData();
|
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;
|
adjustedImageBase = readUnaligned(pdata).adjustedImageBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageBase != 0) {
|
if (originalImageBase != 0 || adjustedImageBase != 0) {
|
||||||
// Check data memory address to be equal to either ImageBase or AdjustedImageBase
|
// Check data memory address to be equal to either OriginalImageBase or AdjustedImageBase
|
||||||
UINT64 address = addressDiff + model->base(index);
|
UINT64 address = addressDiff + model->base(index);
|
||||||
UINT32 base = (UINT32)address + model->header(index).size();
|
UINT32 base = (UINT32)address + model->header(index).size();
|
||||||
|
|
||||||
if (imageBase == base) {
|
if (originalImageBase == base) {
|
||||||
imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL;
|
imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL;
|
||||||
}
|
}
|
||||||
else if (adjustedImageBase == base) {
|
else if (adjustedImageBase == base) {
|
||||||
@ -3253,7 +3257,7 @@ USTATUS FfsParser::checkTeImageBase(const UModelIndex & index)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Check for one-bit difference
|
// 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
|
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;
|
imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL;
|
||||||
}
|
}
|
||||||
@ -3266,13 +3270,14 @@ USTATUS FfsParser::checkTeImageBase(const UModelIndex & index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show message if imageBaseType is still unknown
|
// 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);
|
msg(usprintf("%s: TE image base is neither zero, nor original, nor adjusted, nor top-swapped", __FUNCTION__), index);
|
||||||
|
}
|
||||||
|
|
||||||
// Update parsing data
|
// Update parsing data
|
||||||
TE_IMAGE_SECTION_PARSING_DATA pdata;
|
TE_IMAGE_SECTION_PARSING_DATA pdata;
|
||||||
pdata.imageBaseType = imageBaseType;
|
pdata.imageBaseType = imageBaseType;
|
||||||
pdata.imageBase = originalImageBase;
|
pdata.originalImageBase = originalImageBase;
|
||||||
pdata.adjustedImageBase = adjustedImageBase;
|
pdata.adjustedImageBase = adjustedImageBase;
|
||||||
model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata)));
|
model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata)));
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ typedef struct COMPRESSED_SECTION_PARSING_DATA_ {
|
|||||||
} COMPRESSED_SECTION_PARSING_DATA;
|
} COMPRESSED_SECTION_PARSING_DATA;
|
||||||
|
|
||||||
typedef struct TE_IMAGE_SECTION_PARSING_DATA_ {
|
typedef struct TE_IMAGE_SECTION_PARSING_DATA_ {
|
||||||
UINT32 imageBase;
|
UINT32 originalImageBase;
|
||||||
UINT32 adjustedImageBase;
|
UINT32 adjustedImageBase;
|
||||||
UINT8 imageBaseType;
|
UINT8 imageBaseType;
|
||||||
} TE_IMAGE_SECTION_PARSING_DATA;
|
} TE_IMAGE_SECTION_PARSING_DATA;
|
||||||
|
@ -174,12 +174,12 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
|
|||||||
UString compressionTypeToUString(const UINT8 algorithm)
|
UString compressionTypeToUString(const UINT8 algorithm)
|
||||||
{
|
{
|
||||||
switch (algorithm) {
|
switch (algorithm) {
|
||||||
case COMPRESSION_ALGORITHM_NONE: return UString("None");
|
case COMPRESSION_ALGORITHM_NONE: return UString("None");
|
||||||
case COMPRESSION_ALGORITHM_EFI11: return UString("EFI 1.1");
|
case COMPRESSION_ALGORITHM_EFI11: return UString("EFI 1.1");
|
||||||
case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano");
|
case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano");
|
||||||
case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1");
|
case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1");
|
||||||
case COMPRESSION_ALGORITHM_LZMA: return UString("LZMA");
|
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");
|
return UString("Unknown");
|
||||||
|
@ -235,56 +235,39 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp
|
|||||||
data = (const UINT8*)compressedData.constData();
|
data = (const UINT8*)compressedData.constData();
|
||||||
dataSize = compressedData.size();
|
dataSize = compressedData.size();
|
||||||
|
|
||||||
// Get info
|
// Get info as normal LZMA section
|
||||||
if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize))
|
if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) {
|
||||||
return U_CUSTOMIZED_DECOMPRESSION_FAILED;
|
// 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
|
// Allocate memory
|
||||||
decompressed = (UINT8*)malloc(decompressedSize);
|
decompressed = (UINT8*)malloc(decompressedSize);
|
||||||
if (!decompressed) {
|
if (!decompressed) {
|
||||||
return U_STANDARD_DECOMPRESSION_FAILED;
|
return U_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress section data
|
// Decompress section data
|
||||||
if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
|
if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
|
||||||
// Intel modified LZMA workaround
|
return U_CUSTOMIZED_DECOMPRESSION_FAILED;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
free(decompressed);
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user