UT NE A32

- improved parsing of volume's non-UEFI data
- improved detection of top-swap for TE images
- other minor fixes
This commit is contained in:
Nikolaj Schlej 2016-07-16 07:02:33 +02:00
parent 5b43099d78
commit fe56c5c84c
6 changed files with 102 additions and 143 deletions

View File

@ -502,7 +502,6 @@ typedef struct POSTCODE_SECTION_ {
//***************************************************************************** //*****************************************************************************
// EFI Dependency Expression // EFI Dependency Expression
//***************************************************************************** //*****************************************************************************
#define EFI_DEP_OPCODE_SIZE 1 #define EFI_DEP_OPCODE_SIZE 1
/// ///

View File

@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "treemodel.h" #include "treemodel.h"
#include "descriptor.h" #include "descriptor.h"
#include "ffs.h" #include "ffs.h"
#include "peimage.h"
#include "utility.h" #include "utility.h"
class FfsBuilder class FfsBuilder

View File

@ -1034,25 +1034,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par
msgAlignmentBitsSet = true; msgAlignmentBitsSet = true;
} }
// Do not check for volume alignment on revision 1 volumes // Do not check for volume alignment on revision 1 volumes
// No one gives a single crap about setting it correctly // No one gives a single damn about setting it correctly
/*else {
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_2) alignment = 2;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_4) alignment = 4;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_8) alignment = 8;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_16) alignment = 16;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_32) alignment = 32;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_64) alignment = 64;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_128) alignment = 128;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_256) alignment = 256;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_512) alignment = 512;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_1K) alignment = 1024;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_2K) alignment = 2048;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_4K) alignment = 4096;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_8K) alignment = 8192;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_16K) alignment = 16384;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_32K) alignment = 32768;
if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_64K) alignment = 65536;
}*/
} }
else if (volumeHeader->Revision == 2) { else if (volumeHeader->Revision == 2) {
// Acquire alignment // Acquire alignment
@ -1249,61 +1231,18 @@ USTATUS FfsParser::parseVolumeNonUefiData(const UByteArray & data, const UINT32
// Get parsing data // Get parsing data
PARSING_DATA pdata = parsingDataFromUModelIndex(index); PARSING_DATA pdata = parsingDataFromUModelIndex(index);
// Modify it // Add parent offset
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Search for VTF GUID backwards in received data
UByteArray padding = data;
UByteArray vtf;
INT32 vtfIndex = data.lastIndexOf(EFI_FFS_VOLUME_TOP_FILE_GUID);
if (vtfIndex >= 0) { // VTF candidate found inside non-UEFI data
padding = data.left(vtfIndex);
vtf = data.mid(vtfIndex);
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)vtf.constData();
if ((UINT32)vtf.size() < sizeof(EFI_FFS_FILE_HEADER) // VTF candidate is too small to be a real VTF in FFSv1/v2 volume
|| (pdata.ffsVersion == 3
&& (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)
&& (UINT32)vtf.size() < sizeof(EFI_FFS_FILE_HEADER2))) { // VTF candidate is too small to be a real VTF in FFSv3 volume
vtfIndex = -1;
padding = data;
vtf.clear();
}
}
// Add non-UEFI data first
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); UString info = usprintf("Full size: %Xh (%u)", data.size(), data.size());
// Add padding tree item // Add padding tree item
UModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); UModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), true, parsingDataToUByteArray(pdata), index);
msg(UString("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex); msg(UString("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex);
if (vtfIndex >= 0) { // Parse contents as RAW area
// Get VTF file header return parseRawArea(paddingIndex);
UByteArray header = vtf.left(sizeof(EFI_FFS_FILE_HEADER));
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
if (pdata.ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
header = vtf.left(sizeof(EFI_FFS_FILE_HEADER2));
}
//Parse VTF file header
UModelIndex fileIndex;
USTATUS result = parseFileHeader(vtf, parentOffset + vtfIndex, index, fileIndex);
if (result) {
msg(UString("parseVolumeNonUefiData: VTF file header parsing failed with error ") + errorCodeToUString(result), index);
// Add the rest as non-UEFI data too
pdata.offset += vtfIndex;
// Get info
UString info = usprintf("Full size: %Xh (%u)", vtf.size(), vtf.size());
// Add padding tree item
UModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), vtf, UByteArray(), true, parsingDataToUByteArray(pdata), index);
msg(("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex);
}
}
return U_SUCCESS;
} }
USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
@ -1366,7 +1305,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size());
// Add free space item // Add free space item
model->addItem(Types::FreeSpace, 0, UString("Volume free space"), "", info, UByteArray(), free, UByteArray(), false, parsingDataToUByteArray(pdata), index); model->addItem(Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), false, parsingDataToUByteArray(pdata), index);
} }
// Parse non-UEFI data // Parse non-UEFI data
@ -1380,7 +1319,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
UString info = usprintf("Full size: %Xh (%u)", freeSpace.size(), freeSpace.size()); UString info = usprintf("Full size: %Xh (%u)", freeSpace.size(), freeSpace.size());
// Add free space item // Add free space item
model->addItem(Types::FreeSpace, 0, UString("Volume free space"), "", info, UByteArray(), freeSpace, UByteArray(), false, parsingDataToUByteArray(pdata), index); model->addItem(Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), false, parsingDataToUByteArray(pdata), index);
} }
break; // Exit from parsing loop break; // Exit from parsing loop
} }
@ -1683,7 +1622,7 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index)
} }
// Parse sections // Parse sections
return parseSections(model->body(index), index); return parseSections(model->body(index), index, true);
} }
USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
@ -1739,7 +1678,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
pdata.offset += i; pdata.offset += i;
// Add tree item // Add tree item
UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index);
// Show message // Show message
msg(UString("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex); msg(UString("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex);
@ -1750,7 +1689,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex & index, const bool preparse) USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree)
{ {
// Sanity check // Sanity check
if (!index.isValid()) if (!index.isValid())
@ -1771,34 +1710,35 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
// Check section size // Check section size
if (sectionSize < sizeof(EFI_COMMON_SECTION_HEADER) || sectionSize > (bodySize - sectionOffset)) { if (sectionSize < sizeof(EFI_COMMON_SECTION_HEADER) || sectionSize > (bodySize - sectionOffset)) {
// Add padding to fill the rest of sections
UByteArray padding = sections.mid(sectionOffset);
// Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size());
// Constuct parsing data
pdata.offset += headerSize + sectionOffset;
// Final parsing // Final parsing
if (!preparse) { if (insertIntoTree) {
// Add padding to fill the rest of sections
UByteArray padding = sections.mid(sectionOffset);
// Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size());
// Constuct parsing data
pdata.offset += headerSize + sectionOffset;
// Add tree item // Add tree item
UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index);
// Show message // Show message
msg(UString("parseSections: non-UEFI data found in sections area"), dataIndex); msg(UString("parseSections: non-UEFI data found in sections area"), dataIndex);
// Exit from parsing loop
break;
} }
// Preparsing // Preparsing
else { else
return U_INVALID_SECTION; return U_INVALID_SECTION;
}
break; // Exit from parsing loop
} }
// Parse section header // Parse section header
UModelIndex sectionIndex; UModelIndex sectionIndex;
result = parseSectionHeader(sections.mid(sectionOffset, sectionSize), headerSize + sectionOffset, index, sectionIndex, preparse); result = parseSectionHeader(sections.mid(sectionOffset, sectionSize), headerSize + sectionOffset, index, sectionIndex, insertIntoTree);
if (result) { if (result) {
if (!preparse) if (insertIntoTree)
msg(UString("parseSections: section header parsing failed with error ") + errorCodeToUString(result), index); msg(UString("parseSections: section header parsing failed with error ") + errorCodeToUString(result), index);
else else
return U_INVALID_SECTION; return U_INVALID_SECTION;
@ -1808,7 +1748,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
sectionOffset = ALIGN4(sectionOffset); sectionOffset = ALIGN4(sectionOffset);
} }
//Parse bodies, will be skipped on preparse phase // Parse bodies, will be skipped if insertIntoTree is not required
for (int i = 0; i < model->rowCount(index); i++) { for (int i = 0; i < model->rowCount(index); i++) {
UModelIndex current = index.child(i, 0); UModelIndex current = index.child(i, 0);
switch (model->type(current)) { switch (model->type(current)) {
@ -1826,7 +1766,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -1835,12 +1775,12 @@ USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 p
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
switch (sectionHeader->Type) { switch (sectionHeader->Type) {
// Special // Special
case EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, parentOffset, parent, index, preparse); case EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, parentOffset, parent, index, insertIntoTree);
case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, parentOffset, parent, index, preparse); case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, parentOffset, parent, index, insertIntoTree);
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, parentOffset, parent, index, preparse); case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, parentOffset, parent, index, insertIntoTree);
case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, parentOffset, parent, index, preparse); case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, parentOffset, parent, index, insertIntoTree);
case PHOENIX_SECTION_POSTCODE: case PHOENIX_SECTION_POSTCODE:
case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, parentOffset, parent, index, preparse); case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, parentOffset, parent, index, insertIntoTree);
// Common // Common
case EFI_SECTION_DISPOSABLE: case EFI_SECTION_DISPOSABLE:
case EFI_SECTION_DXE_DEPEX: case EFI_SECTION_DXE_DEPEX:
@ -1852,16 +1792,16 @@ USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 p
case EFI_SECTION_COMPATIBILITY16: case EFI_SECTION_COMPATIBILITY16:
case EFI_SECTION_USER_INTERFACE: case EFI_SECTION_USER_INTERFACE:
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
case EFI_SECTION_RAW: return parseCommonSectionHeader(section, parentOffset, parent, index, preparse); case EFI_SECTION_RAW: return parseCommonSectionHeader(section, parentOffset, parent, index, insertIntoTree);
// Unknown // Unknown
default: default:
USTATUS result = parseCommonSectionHeader(section, parentOffset, parent, index, preparse); USTATUS result = parseCommonSectionHeader(section, parentOffset, parent, index, insertIntoTree);
msg(usprintf("parseSectionHeader: section with unknown type %02Xh", sectionHeader->Type), index); msg(usprintf("parseSectionHeader: section with unknown type %02Xh", sectionHeader->Type), index);
return result; return result;
} }
} }
USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -1905,13 +1845,13 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
if (!preparse) { if (insertIntoTree) {
index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent);
} }
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -1972,13 +1912,13 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons
pdata.section.compressed.uncompressedSize = uncompressedLength; pdata.section.compressed.uncompressedSize = uncompressedLength;
// Add tree item // Add tree item
if (!preparse) { if (insertIntoTree) {
index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent);
} }
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2127,7 +2067,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
pdata.section.guidDefined.guid = guid; pdata.section.guidDefined.guid = guid;
// Add tree item // Add tree item
if (!preparse) { if (insertIntoTree) {
index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent);
// Show messages // Show messages
@ -2150,7 +2090,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2209,7 +2149,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section,
pdata.section.freeformSubtypeGuid.guid = guid; pdata.section.freeformSubtypeGuid.guid = guid;
// Add tree item // Add tree item
if (!preparse) { if (insertIntoTree) {
index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent);
// Rename section // Rename section
@ -2218,7 +2158,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section,
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2274,13 +2214,13 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
if (!preparse) { if (insertIntoTree) {
index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent);
} }
return U_SUCCESS; return U_SUCCESS;
} }
USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
{ {
// Check sanity // Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2336,7 +2276,7 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
if (!preparse) { if (insertIntoTree) {
index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent);
} }
return U_SUCCESS; return U_SUCCESS;
@ -2357,7 +2297,7 @@ USTATUS FfsParser::parseSectionBody(const UModelIndex & index)
// Encapsulation // Encapsulation
case EFI_SECTION_COMPRESSION: return parseCompressedSectionBody(index); case EFI_SECTION_COMPRESSION: return parseCompressedSectionBody(index);
case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionBody(index); case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionBody(index);
case EFI_SECTION_DISPOSABLE: return parseSections(model->body(index), index); case EFI_SECTION_DISPOSABLE: return parseSections(model->body(index), index, true);
// Leaf // Leaf
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseRawArea(index); case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseRawArea(index);
case EFI_SECTION_VERSION: return parseVersionSectionBody(index); case EFI_SECTION_VERSION: return parseVersionSectionBody(index);
@ -2411,11 +2351,11 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index)
// Check for undecided compression algorithm, this is a special case // Check for undecided compression algorithm, this is a special case
if (algorithm == COMPRESSION_ALGORITHM_UNDECIDED) { if (algorithm == COMPRESSION_ALGORITHM_UNDECIDED) {
// Try preparse of sections decompressed with Tiano algorithm // Try preparse of sections decompressed with Tiano algorithm
if (U_SUCCESS == parseSections(decompressed, index, true)) { if (U_SUCCESS == parseSections(decompressed, index, false)) {
algorithm = COMPRESSION_ALGORITHM_TIANO; algorithm = COMPRESSION_ALGORITHM_TIANO;
} }
// Try preparse of sections decompressed with EFI 1.1 algorithm // Try preparse of sections decompressed with EFI 1.1 algorithm
else if (U_SUCCESS == parseSections(efiDecompressed, index, true)) { else if (U_SUCCESS == parseSections(efiDecompressed, index, false)) {
algorithm = COMPRESSION_ALGORITHM_EFI11; algorithm = COMPRESSION_ALGORITHM_EFI11;
decompressed = efiDecompressed; decompressed = efiDecompressed;
} }
@ -2434,7 +2374,7 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index)
model->setParsingData(index, parsingDataToUByteArray(pdata)); model->setParsingData(index, parsingDataToUByteArray(pdata));
// Parse decompressed data // Parse decompressed data
return parseSections(decompressed, index); return parseSections(decompressed, index, true);
} }
USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
@ -2466,11 +2406,11 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
// Check for undecided compression algorithm, this is a special case // Check for undecided compression algorithm, this is a special case
if (algorithm == COMPRESSION_ALGORITHM_UNDECIDED) { if (algorithm == COMPRESSION_ALGORITHM_UNDECIDED) {
// Try preparse of sections decompressed with Tiano algorithm // Try preparse of sections decompressed with Tiano algorithm
if (U_SUCCESS == parseSections(processed, index, true)) { if (U_SUCCESS == parseSections(processed, index, false)) {
algorithm = COMPRESSION_ALGORITHM_TIANO; algorithm = COMPRESSION_ALGORITHM_TIANO;
} }
// Try preparse of sections decompressed with EFI 1.1 algorithm // Try preparse of sections decompressed with EFI 1.1 algorithm
else if (U_SUCCESS == parseSections(efiDecompressed, index, true)) { else if (U_SUCCESS == parseSections(efiDecompressed, index, false)) {
algorithm = COMPRESSION_ALGORITHM_EFI11; algorithm = COMPRESSION_ALGORITHM_EFI11;
processed = efiDecompressed; processed = efiDecompressed;
} }
@ -2516,7 +2456,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
return U_SUCCESS; return U_SUCCESS;
} }
return parseSections(processed, index); return parseSections(processed, index, true);
} }
USTATUS FfsParser::parseVersionSectionBody(const UModelIndex & index) USTATUS FfsParser::parseVersionSectionBody(const UModelIndex & index)
@ -2912,9 +2852,6 @@ USTATUS FfsParser::addFixedAndCompressedRecursive(const UModelIndex & index) {
if (!index.isValid()) if (!index.isValid())
return U_INVALID_PARAMETER; return U_INVALID_PARAMETER;
// Get parsing data for the current item
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
// Add fixed and compressed info // Add fixed and compressed info
model->addInfo(index, usprintf("\nCompressed: %s", model->compressed(index) ? "Yes" : "No")); model->addInfo(index, usprintf("\nCompressed: %s", model->compressed(index) ? "Yes" : "No"));
model->addInfo(index, usprintf("\nFixed: %s", model->fixed(index) ? "Yes" : "No")); model->addInfo(index, usprintf("\nFixed: %s", model->fixed(index) ? "Yes" : "No"));
@ -2959,8 +2896,9 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff)
FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data(); FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data();
tempFitHeader->Checksum = 0; tempFitHeader->Checksum = 0;
UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize); UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize);
calculated |= 0x80; // Set checksum flag on calculated checksum
if (calculated != fitHeader->Checksum) { if (calculated != fitHeader->Checksum) {
msg(usprintf("Invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex); msg(usprintf("parseFit: invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex);
} }
} }
@ -2987,7 +2925,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff)
// Check entry type // Check entry type
switch (currentEntry->Type & 0x7F) { switch (currentEntry->Type & 0x7F) {
case FIT_TYPE_HEADER: case FIT_TYPE_HEADER:
msg(UString("Second FIT header found, the table is damaged"), fitIndex); msg(UString("parseFit: second FIT header found, the table is damaged"), fitIndex);
break; break;
case FIT_TYPE_EMPTY: case FIT_TYPE_EMPTY:
@ -3016,7 +2954,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff)
} }
if (msgModifiedImageMayNotWork) if (msgModifiedImageMayNotWork)
msg(UString("Opened image may not work after any modification"), fitIndex); msg(UString("parseFit: opened image may not work after any modification"), fitIndex);
return U_SUCCESS; return U_SUCCESS;
} }
@ -3050,11 +2988,11 @@ USTATUS FfsParser::findFitRecursive(const UModelIndex & index, const UINT32 diff
if (fitAddress == storedFitAddress) { if (fitAddress == storedFitAddress) {
found = index; found = index;
fitOffset = offset; fitOffset = offset;
msg(usprintf("Real FIT table found at physical address %08Xh", fitAddress), found); msg(usprintf("findFitRecursive: real FIT table found at physical address %08Xh", fitAddress), found);
return U_SUCCESS; return U_SUCCESS;
} }
else if (model->rowCount(index) == 0) // Show messages only to leaf items else if (model->rowCount(index) == 0) // Show messages only to leaf items
msg(UString("FIT table candidate found, but not referenced from the last VTF"), index); msg(UString("findFitRecursive: FIT table candidate found, but not referenced from the last VTF"), index);
} }
return U_SUCCESS; return U_SUCCESS;
@ -3087,16 +3025,32 @@ USTATUS FfsParser::addMemoryAddressesRecursive(const UModelIndex & index, const
// Special case of uncompressed TE image sections // Special case of uncompressed TE image sections
if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_TE) { if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_TE) {
// Check data memory address to be equal to either ImageBase or AdjustedImageBase // Check data memory address to be equal to either ImageBase or AdjustedImageBase
if (pdata.section.teImage.imageBase == pdata.address + headerSize) { UINT32 base = pdata.address + headerSize;
pdata.section.teImage.revision = 1; pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_OTHER;
if (pdata.section.teImage.imageBase == base) {
pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL;
} }
else if (pdata.section.teImage.adjustedImageBase == pdata.address + headerSize) { else if (pdata.section.teImage.adjustedImageBase == base) {
pdata.section.teImage.revision = 2; pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED;
} }
else { else {
msg(UString("addMemoryAddressesRecursive: image base is neither original nor adjusted, it's likely a part of backup PEI volume or DXE volume, but can also be damaged"), index); // Check for one-bit difference
pdata.section.teImage.revision = 0; UINT32 xored = base ^ pdata.section.teImage.imageBase; // 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
pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL;
}
else { // The same check for adjustedImageBase
xored = base ^ pdata.section.teImage.adjustedImageBase;
if ((xored & (xored - 1)) == 0) {
pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED;
}
}
} }
// Show message if imageBaseType is still unknown
if (pdata.section.teImage.imageBase != 0 && pdata.section.teImage.imageBaseType == EFI_IMAGE_TE_BASE_OTHER)
msg(UString("addMemoryAddressesRecursive: TE image base is neither zero, nor original, nor adjusted, nor top-swapped"), index);
} }
// Set modified parsing data // Set modified parsing data

View File

@ -70,7 +70,7 @@ private:
USTATUS parseVolumeBody(const UModelIndex & index); USTATUS parseVolumeBody(const UModelIndex & index);
USTATUS parseFileHeader(const UByteArray & file, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); USTATUS parseFileHeader(const UByteArray & file, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFileBody(const UModelIndex & index); USTATUS parseFileBody(const UModelIndex & index);
USTATUS parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse = false); USTATUS parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseSectionBody(const UModelIndex & index); USTATUS parseSectionBody(const UModelIndex & index);
USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & root); USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & root);
@ -83,13 +83,13 @@ private:
USTATUS parsePadFileBody(const UModelIndex & index); USTATUS parsePadFileBody(const UModelIndex & index);
USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 parentOffset, const UModelIndex & index); USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 parentOffset, const UModelIndex & index);
USTATUS parseSections(const UByteArray & sections, const UModelIndex & index, const bool preparse = false); USTATUS parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree);
USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseCompressedSectionBody(const UModelIndex & index); USTATUS parseCompressedSectionBody(const UModelIndex & index);
USTATUS parseGuidedSectionBody(const UModelIndex & index); USTATUS parseGuidedSectionBody(const UModelIndex & index);
@ -100,12 +100,12 @@ private:
USTATUS parsePeImageSectionBody(const UModelIndex & index); USTATUS parsePeImageSectionBody(const UModelIndex & index);
USTATUS parseTeImageSectionBody(const UModelIndex & index); USTATUS parseTeImageSectionBody(const UModelIndex & index);
UINT8 getPaddingType(const UByteArray & padding); UINT8 getPaddingType(const UByteArray & padding);
USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed); USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed);
USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
USTATUS getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize); USTATUS getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize);
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion); UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion); UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
// NVRAM parsing // NVRAM parsing
USTATUS parseNvramVolumeBody(const UModelIndex & index); USTATUS parseNvramVolumeBody(const UModelIndex & index);

View File

@ -50,7 +50,7 @@ typedef struct FREEFORM_GUIDED_SECTION_PARSING_DATA_ {
typedef struct TE_IMAGE_SECTION_PARSING_DATA_ { typedef struct TE_IMAGE_SECTION_PARSING_DATA_ {
UINT32 imageBase; UINT32 imageBase;
UINT32 adjustedImageBase; UINT32 adjustedImageBase;
UINT8 revision; UINT8 imageBaseType;
} TE_IMAGE_SECTION_PARSING_DATA; } TE_IMAGE_SECTION_PARSING_DATA;
typedef struct SECTION_PARSING_DATA_ { typedef struct SECTION_PARSING_DATA_ {

View File

@ -728,6 +728,11 @@ typedef struct {
#define EFI_IMAGE_TE_SIGNATURE 0x5A56 // VZ #define EFI_IMAGE_TE_SIGNATURE 0x5A56 // VZ
// Image base types
#define EFI_IMAGE_TE_BASE_OTHER 0
#define EFI_IMAGE_TE_BASE_ORIGINAL 1
#define EFI_IMAGE_TE_BASE_ADJUSTED 2
// //
// Data directory indexes in our TE image header // Data directory indexes in our TE image header
// //