mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-21 23:48:22 +08:00
Add workaround for Lenovo large files inside FFSv2 volumes
This commit is contained in:
parent
ad8a841f43
commit
acc913769b
36
common/ffs.h
36
common/ffs.h
@ -280,11 +280,22 @@ EFI_GUID Name;
|
|||||||
EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
|
EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
|
||||||
UINT8 Type;
|
UINT8 Type;
|
||||||
UINT8 Attributes;
|
UINT8 Attributes;
|
||||||
UINT8 Size[3]; // Set to 0xFFFFFF
|
UINT8 Size[3]; // Set to 0xFFFFFF or 0x000000
|
||||||
UINT8 State;
|
UINT8 State;
|
||||||
UINT64 ExtendedSize;
|
UINT64 ExtendedSize;
|
||||||
} EFI_FFS_FILE_HEADER2;
|
} EFI_FFS_FILE_HEADER2;
|
||||||
|
|
||||||
|
// Lenovo large file header
|
||||||
|
typedef struct EFI_FFS_FILE_HEADER_LENOVO_ {
|
||||||
|
EFI_GUID Name;
|
||||||
|
EFI_FFS_INTEGRITY_CHECK IntegrityCheck;
|
||||||
|
UINT8 Type;
|
||||||
|
UINT8 Attributes;
|
||||||
|
UINT8 Size[3]; // Set to 0x000000
|
||||||
|
UINT8 State;
|
||||||
|
UINT32 ExtendedSize;
|
||||||
|
} EFI_FFS_FILE_HEADER2_LENOVO;
|
||||||
|
|
||||||
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
||||||
#define FFS_FIXED_CHECKSUM 0x5A
|
#define FFS_FIXED_CHECKSUM 0x5A
|
||||||
#define FFS_FIXED_CHECKSUM2 0xAA
|
#define FFS_FIXED_CHECKSUM2 0xAA
|
||||||
@ -317,8 +328,8 @@ UINT64 ExtendedSize;
|
|||||||
// File attributes
|
// File attributes
|
||||||
#define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
|
#define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
|
||||||
#define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes
|
#define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes
|
||||||
#define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes
|
#define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes or FFSv2 volumes with Lenovo large files
|
||||||
#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 // Volaid only for revision 2 volumes, added in UEFI PI 1.6
|
#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 // Valid only for revision 2 volumes, added in UEFI PI 1.6
|
||||||
#define FFS_ATTRIB_FIXED 0x04
|
#define FFS_ATTRIB_FIXED 0x04
|
||||||
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
||||||
#define FFS_ATTRIB_CHECKSUM 0x40
|
#define FFS_ATTRIB_CHECKSUM 0x40
|
||||||
@ -377,13 +388,6 @@ typedef struct EFI_COMMON_SECTION_HEADER2_ {
|
|||||||
UINT32 ExtendedSize;
|
UINT32 ExtendedSize;
|
||||||
} EFI_COMMON_SECTION_HEADER2;
|
} EFI_COMMON_SECTION_HEADER2;
|
||||||
|
|
||||||
// Apple common section header
|
|
||||||
typedef struct EFI_COMMON_SECTION_HEADER_APPLE {
|
|
||||||
UINT8 Size[3];
|
|
||||||
UINT8 Type;
|
|
||||||
UINT32 Reserved; // Must be 0x7FFF for this header to be used
|
|
||||||
} EFI_COMMON_SECTION_HEADER_APPLE;
|
|
||||||
|
|
||||||
// Section2 usage indicator
|
// Section2 usage indicator
|
||||||
#define EFI_SECTION2_IS_USED 0xFFFFFF
|
#define EFI_SECTION2_IS_USED 0xFFFFFF
|
||||||
|
|
||||||
@ -417,11 +421,6 @@ typedef struct EFI_COMPRESSION_SECTION_ {
|
|||||||
UINT8 CompressionType;
|
UINT8 CompressionType;
|
||||||
} EFI_COMPRESSION_SECTION;
|
} EFI_COMPRESSION_SECTION;
|
||||||
|
|
||||||
typedef struct EFI_COMPRESSION_SECTION_APPLE_ {
|
|
||||||
UINT32 UncompressedLength;
|
|
||||||
UINT32 CompressionType;
|
|
||||||
} EFI_COMPRESSION_SECTION_APPLE;
|
|
||||||
|
|
||||||
// Compression types
|
// Compression types
|
||||||
#define EFI_NOT_COMPRESSED 0x00
|
#define EFI_NOT_COMPRESSED 0x00
|
||||||
#define EFI_STANDARD_COMPRESSION 0x01
|
#define EFI_STANDARD_COMPRESSION 0x01
|
||||||
@ -435,13 +434,6 @@ typedef struct EFI_GUID_DEFINED_SECTION_ {
|
|||||||
UINT16 Attributes;
|
UINT16 Attributes;
|
||||||
} EFI_GUID_DEFINED_SECTION;
|
} EFI_GUID_DEFINED_SECTION;
|
||||||
|
|
||||||
typedef struct EFI_GUID_DEFINED_SECTION_APPLE_ {
|
|
||||||
EFI_GUID SectionDefinitionGuid;
|
|
||||||
UINT16 DataOffset;
|
|
||||||
UINT16 Attributes;
|
|
||||||
UINT32 Reserved;
|
|
||||||
} EFI_GUID_DEFINED_SECTION_APPLE;
|
|
||||||
|
|
||||||
// Attributes for GUID defined section
|
// Attributes for GUID defined section
|
||||||
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
|
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
|
||||||
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
|
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
|
||||||
|
@ -1469,12 +1469,14 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
|
|||||||
UINT8 emptyByte = 0xFF;
|
UINT8 emptyByte = 0xFF;
|
||||||
UINT8 ffsVersion = 2;
|
UINT8 ffsVersion = 2;
|
||||||
UINT32 usedSpace = 0;
|
UINT32 usedSpace = 0;
|
||||||
|
UINT8 revision = 2;
|
||||||
if (model->hasEmptyParsingData(index) == false) {
|
if (model->hasEmptyParsingData(index) == false) {
|
||||||
UByteArray data = model->parsingData(index);
|
UByteArray data = model->parsingData(index);
|
||||||
const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData();
|
const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData();
|
||||||
emptyByte = pdata->emptyByte;
|
emptyByte = pdata->emptyByte;
|
||||||
ffsVersion = pdata->ffsVersion;
|
ffsVersion = pdata->ffsVersion;
|
||||||
usedSpace = pdata->usedSpace;
|
usedSpace = pdata->usedSpace;
|
||||||
|
revision = pdata->revision;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for unknown FFS version
|
// Check for unknown FFS version
|
||||||
@ -1488,7 +1490,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
|
|||||||
UINT32 fileOffset = 0;
|
UINT32 fileOffset = 0;
|
||||||
|
|
||||||
while (fileOffset < volumeBodySize) {
|
while (fileOffset < volumeBodySize) {
|
||||||
UINT32 fileSize = getFileSize(volumeBody, fileOffset, ffsVersion);
|
UINT32 fileSize = getFileSize(volumeBody, fileOffset, ffsVersion, revision);
|
||||||
|
|
||||||
if (fileSize == 0) {
|
if (fileSize == 0) {
|
||||||
msg(usprintf("%s: file header parsing failed with invalid size", __FUNCTION__), index);
|
msg(usprintf("%s: file header parsing failed with invalid size", __FUNCTION__), index);
|
||||||
@ -1628,7 +1630,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
|
|||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion)
|
UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion, const UINT8 revision)
|
||||||
{
|
{
|
||||||
if ((UINT32)volume.size() < fileOffset + sizeof(EFI_FFS_FILE_HEADER)) {
|
if ((UINT32)volume.size() < fileOffset + sizeof(EFI_FFS_FILE_HEADER)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -1637,7 +1639,18 @@ UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset
|
|||||||
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)(volume.constData() + fileOffset);
|
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)(volume.constData() + fileOffset);
|
||||||
|
|
||||||
if (ffsVersion == 2) {
|
if (ffsVersion == 2) {
|
||||||
return uint24ToUint32(fileHeader->Size);
|
UINT32 size = uint24ToUint32(fileHeader->Size);
|
||||||
|
// Special case of Lenovo large file insize FFSv2 Rev2 volume
|
||||||
|
if (revision == 2 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
|
||||||
|
if ((UINT32)volume.size() < fileOffset + sizeof(EFI_FFS_FILE_HEADER2_LENOVO)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EFI_FFS_FILE_HEADER2_LENOVO* fileHeader2Lenovo = (const EFI_FFS_FILE_HEADER2_LENOVO*)(volume.constData() + fileOffset);
|
||||||
|
return (UINT32)fileHeader2Lenovo->ExtendedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
else if (ffsVersion == 3) {
|
else if (ffsVersion == 3) {
|
||||||
if (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
|
if (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
|
||||||
@ -1646,7 +1659,7 @@ UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset
|
|||||||
}
|
}
|
||||||
|
|
||||||
const EFI_FFS_FILE_HEADER2* fileHeader2 = (const EFI_FFS_FILE_HEADER2*)(volume.constData() + fileOffset);
|
const EFI_FFS_FILE_HEADER2* fileHeader2 = (const EFI_FFS_FILE_HEADER2*)(volume.constData() + fileOffset);
|
||||||
return (UINT32) fileHeader2->ExtendedSize;
|
return (UINT32)fileHeader2->ExtendedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return uint24ToUint32(fileHeader->Size);
|
return uint24ToUint32(fileHeader->Size);
|
||||||
@ -1683,10 +1696,17 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
|
|||||||
// Get file header
|
// Get file header
|
||||||
UByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
UByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||||
EFI_FFS_FILE_HEADER* tempFileHeader = (EFI_FFS_FILE_HEADER*)header.data();
|
EFI_FFS_FILE_HEADER* tempFileHeader = (EFI_FFS_FILE_HEADER*)header.data();
|
||||||
if (ffsVersion == 3 && (tempFileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
|
if (tempFileHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
|
||||||
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2))
|
if (ffsVersion == 2 && volumeRevision == 2) {
|
||||||
return U_INVALID_FILE;
|
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2_LENOVO))
|
||||||
header = file.left(sizeof(EFI_FFS_FILE_HEADER2));
|
return U_INVALID_FILE;
|
||||||
|
header = file.left(sizeof(EFI_FFS_FILE_HEADER2_LENOVO));
|
||||||
|
}
|
||||||
|
if (ffsVersion == 3) {
|
||||||
|
if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2))
|
||||||
|
return U_INVALID_FILE;
|
||||||
|
header = file.left(sizeof(EFI_FFS_FILE_HEADER2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
|
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ private:
|
|||||||
|
|
||||||
USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed);
|
USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed);
|
||||||
USTATUS findNextRawAreaItem(const UModelIndex & index, const UINT32 localOffset, UINT8 & nextItemType, UINT32 & nextItemOffset, UINT32 & nextItemSize, UINT32 & nextItemAlternativeSize);
|
USTATUS findNextRawAreaItem(const UModelIndex & index, const UINT32 localOffset, UINT8 & nextItemType, UINT32 & nextItemOffset, UINT32 & nextItemSize, UINT32 & nextItemAlternativeSize);
|
||||||
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
|
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion, const UINT8 revision);
|
||||||
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
|
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
|
||||||
|
|
||||||
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
|
||||||
|
Loading…
Reference in New Issue
Block a user