- thanks to NVAR extended headers, item tails are back
- fixed a bug with "Extract uncompressed" producing incorrect results
for multiple sections
- fixed detection and parsing of NVRAM external defaults file
- fixed "Extract as is" on NVAR entries not including extended header
- small bugfixes and refactorings
This commit is contained in:
Nikolaj Schlej 2016-04-20 22:41:18 +02:00
parent 323245154a
commit cd1cc09b39
10 changed files with 163 additions and 150 deletions

View File

@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) : UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::UEFITool), ui(new Ui::UEFITool),
version(tr("0.30.0_alpha26")) version(tr("0.30.0_alpha27"))
{ {
clipboard = QApplication::clipboard(); clipboard = QApplication::clipboard();

View File

@ -149,11 +149,11 @@ typedef struct EFI_TIME_ {
UINT8 Hour; // Hour: 0 - 23 UINT8 Hour; // Hour: 0 - 23
UINT8 Minute; // Minute: 0 - 59 UINT8 Minute; // Minute: 0 - 59
UINT8 Second; // Second: 0 - 59 UINT8 Second; // Second: 0 - 59
UINT8: 8; UINT8 : 8;
UINT32 Nanosecond; // Nanosecond: 0 - 999,999,999 UINT32 Nanosecond; // Nanosecond: 0 - 999,999,999
INT16 TimeZone; // TimeZone: -1440 to 1440 or UNSPECIFIED (0x07FF) INT16 TimeZone; // TimeZone: -1440 to 1440 or UNSPECIFIED (0x07FF)
UINT8 Daylight; // Daylight: ADJUST_DAYLIGHT (1) or IN_DAYLIGHT (2) UINT8 Daylight; // Daylight: ADJUST_DAYLIGHT (1) or IN_DAYLIGHT (2)
UINT8: 8; UINT8 : 8;
} EFI_TIME; } EFI_TIME;
#define ALIGN4(Value) (((Value)+3) & ~3) #define ALIGN4(Value) (((Value)+3) & ~3)

View File

@ -53,11 +53,7 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
extracted.clear(); extracted.clear();
extracted.append(model->header(index)); extracted.append(model->header(index));
extracted.append(model->body(index)); extracted.append(model->body(index));
// Handle file tail extracted.append(model->tail(index));
if (model->type(index) == Types::File) {
if (pdata.file.hasTail)
extracted.append(pdata.file.tailArray[0]).append(pdata.file.tailArray[1]);
}
} }
else if (mode == EXTRACT_MODE_BODY) { else if (mode == EXTRACT_MODE_BODY) {
name += QObject::tr("_body"); name += QObject::tr("_body");
@ -72,8 +68,12 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
// There is no need to redo decompression, we can use child items // There is no need to redo decompression, we can use child items
for (int i = 0; i < model->rowCount(index); i++) { for (int i = 0; i < model->rowCount(index); i++) {
QModelIndex childIndex = index.child(i, 0); QModelIndex childIndex = index.child(i, 0);
// Ensure 4-byte alignment of current section
extracted.append(QByteArray('\x00', ALIGN4((UINT32)extracted.size()) - (UINT32)extracted.size()));
// Add current section header, body and tail
extracted.append(model->header(childIndex)); extracted.append(model->header(childIndex));
extracted.append(model->body(childIndex)); extracted.append(model->body(childIndex));
extracted.append(model->tail(childIndex));
} }
} }
else else

View File

@ -88,7 +88,7 @@ STATUS FfsParser::performFirstPass(const QByteArray & buffer, QModelIndex & inde
capsuleOffsetFixup = capsuleHeaderSize; capsuleOffsetFixup = capsuleHeaderSize;
// Add tree item // Add tree item
index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, true); index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, QByteArray(), true);
} }
// Check buffer for being Toshiba capsule header // Check buffer for being Toshiba capsule header
else if (buffer.startsWith(TOSHIBA_CAPSULE_GUID)) { else if (buffer.startsWith(TOSHIBA_CAPSULE_GUID)) {
@ -122,7 +122,7 @@ STATUS FfsParser::performFirstPass(const QByteArray & buffer, QModelIndex & inde
capsuleOffsetFixup = capsuleHeaderSize; capsuleOffsetFixup = capsuleHeaderSize;
// Add tree item // Add tree item
index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, name, QString(), info, header, body, true); index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, name, QString(), info, header, body, QByteArray(), true);
} }
// Check buffer for being extended Aptio capsule header // Check buffer for being extended Aptio capsule header
else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) { else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) {
@ -161,7 +161,7 @@ STATUS FfsParser::performFirstPass(const QByteArray & buffer, QModelIndex & inde
capsuleOffsetFixup = capsuleHeaderSize; capsuleOffsetFixup = capsuleHeaderSize;
// Add tree item // Add tree item
index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, QString(), info, header, body, true); index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, QString(), info, header, body, QByteArray(), true);
// Show message about possible Aptio signature break // Show message about possible Aptio signature break
if (signedCapsule) { if (signedCapsule) {
@ -197,7 +197,7 @@ STATUS FfsParser::performFirstPass(const QByteArray & buffer, QModelIndex & inde
pdata.offset = capsuleHeaderSize; pdata.offset = capsuleHeaderSize;
// Add tree item // Add tree item
QModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, QString(), info, QByteArray(), flashImage, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, QString(), info, QByteArray(), flashImage, QByteArray(), true, parsingDataToQByteArray(pdata), index);
// Parse the image // Parse the image
result = parseRawArea(biosIndex); result = parseRawArea(biosIndex);
@ -467,7 +467,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const UINT32 pa
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add Intel image tree item // Add Intel image tree item
index = model->addItem(Types::Image, Subtypes::IntelImage, name, QString(), info, QByteArray(), intelImage, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Image, Subtypes::IntelImage, name, QString(), info, QByteArray(), intelImage, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
// Descriptor // Descriptor
// Get descriptor info // Get descriptor info
@ -557,7 +557,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const UINT32 pa
} }
// Add descriptor tree item // Add descriptor tree item
QModelIndex regionIndex = model->addItem(Types::Region, Subtypes::DescriptorRegion, name, QString(), info, QByteArray(), body, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex regionIndex = model->addItem(Types::Region, Subtypes::DescriptorRegion, name, QString(), info, QByteArray(), body, QByteArray(), true, parsingDataToQByteArray(pdata), index);
// Parse regions // Parse regions
UINT8 result = ERR_SUCCESS; UINT8 result = ERR_SUCCESS;
@ -602,7 +602,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const UINT32 pa
pdata.offset = parentOffset + region.offset; pdata.offset = parentOffset + region.offset;
// Add tree item // Add tree item
regionIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); regionIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
result = ERR_SUCCESS; result = ERR_SUCCESS;
} break; } break;
default: default:
@ -647,7 +647,7 @@ STATUS FfsParser::parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffs
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::Region, Subtypes::GbeRegion, name, QString(), info, QByteArray(), gbe, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Region, Subtypes::GbeRegion, name, QString(), info, QByteArray(), gbe, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -706,7 +706,7 @@ STATUS FfsParser::parseMeRegion(const QByteArray & me, const UINT32 parentOffset
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::Region, Subtypes::MeRegion, name, QString(), info, QByteArray(), me, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Region, Subtypes::MeRegion, name, QString(), info, QByteArray(), me, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
// Show messages // Show messages
if (emptyRegion) { if (emptyRegion) {
@ -737,7 +737,7 @@ STATUS FfsParser::parsePdrRegion(const QByteArray & pdr, const UINT32 parentOffs
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::Region, Subtypes::PdrRegion, name, QString(), info, QByteArray(), pdr, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Region, Subtypes::PdrRegion, name, QString(), info, QByteArray(), pdr, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
// Parse PDR region as BIOS space // Parse PDR region as BIOS space
UINT8 result = parseRawArea(index); UINT8 result = parseRawArea(index);
@ -765,7 +765,7 @@ STATUS FfsParser::parseGeneralRegion(const UINT8 subtype, const QByteArray & reg
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::Region, subtype, name, QString(), info, QByteArray(), region, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Region, subtype, name, QString(), info, QByteArray(), region, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -788,7 +788,7 @@ STATUS FfsParser::parseBiosRegion(const QByteArray & bios, const UINT32 parentOf
pdata.offset += parentOffset; pdata.offset += parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::Region, Subtypes::BiosRegion, name, QString(), info, QByteArray(), bios, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Region, Subtypes::BiosRegion, name, QString(), info, QByteArray(), bios, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return parseRawArea(index); return parseRawArea(index);
} }
@ -838,7 +838,7 @@ STATUS FfsParser::parseRawArea(const QModelIndex & index)
pdata.offset = offset; pdata.offset = offset;
// Add tree item // Add tree item
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
} }
// Search for and parse all volumes // Search for and parse all volumes
@ -862,7 +862,7 @@ STATUS FfsParser::parseRawArea(const QModelIndex & index)
pdata.offset = offset + paddingOffset; pdata.offset = offset + paddingOffset;
// Add tree item // Add tree item
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
} }
// Get volume size // Get volume size
@ -894,7 +894,7 @@ STATUS FfsParser::parseRawArea(const QModelIndex & index)
pdata.offset = offset + volumeOffset; pdata.offset = offset + volumeOffset;
// Add tree item // Add tree item
QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
msg(QObject::tr("parseRawArea: one of volumes inside overlaps the end of data"), paddingIndex); msg(QObject::tr("parseRawArea: one of volumes inside overlaps the end of data"), paddingIndex);
// Update variables // Update variables
@ -937,7 +937,7 @@ STATUS FfsParser::parseRawArea(const QModelIndex & index)
pdata.offset = offset + headerSize + volumeOffset; pdata.offset = offset + headerSize + volumeOffset;
// Add tree item // Add tree item
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
} }
// Parse bodies // Parse bodies
@ -1159,7 +1159,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
else if (isNvramVolume) else if (isNvramVolume)
subtype = Subtypes::NvramVolume; subtype = Subtypes::NvramVolume;
} }
index = model->addItem(Types::Volume, subtype, name, text, info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Volume, subtype, name, text, info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
// Show messages // Show messages
if (isUnknown) if (isUnknown)
@ -1276,7 +1276,7 @@ STATUS FfsParser::parseVolumeNonUefiData(const QByteArray & data, const UINT32 p
QString info = QObject::tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()); QString info = QObject::tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size());
// Add padding tree item // Add padding tree item
QModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
msg(QObject::tr("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex); msg(QObject::tr("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex);
if (vtfIndex >= 0) { if (vtfIndex >= 0) {
@ -1299,7 +1299,7 @@ STATUS FfsParser::parseVolumeNonUefiData(const QByteArray & data, const UINT32 p
QString info = QObject::tr("Full size: %1h (%2)").hexarg(vtf.size()).arg(vtf.size()); QString info = QObject::tr("Full size: %1h (%2)").hexarg(vtf.size()).arg(vtf.size());
// Add padding tree item // Add padding tree item
QModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), vtf, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), vtf, QByteArray(), true, parsingDataToQByteArray(pdata), index);
msg(QObject::tr("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex); msg(QObject::tr("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex);
} }
} }
@ -1367,7 +1367,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
QString info = QObject::tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()); QString info = QObject::tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size());
// Add free space item // Add free space item
model->addItem(Types::FreeSpace, 0, QObject::tr("Volume free space"), "", info, QByteArray(), free, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FreeSpace, 0, QObject::tr("Volume free space"), "", info, QByteArray(), free, QByteArray(), false, parsingDataToQByteArray(pdata), index);
} }
// Parse non-UEFI data // Parse non-UEFI data
@ -1381,7 +1381,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
QString info = QObject::tr("Full size: %1h (%2)").hexarg(freeSpace.size()).arg(freeSpace.size()); QString info = QObject::tr("Full size: %1h (%2)").hexarg(freeSpace.size()).arg(freeSpace.size());
// Add free space item // Add free space item
model->addItem(Types::FreeSpace, 0, QObject::tr("Volume free space"), "", info, QByteArray(), freeSpace, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FreeSpace, 0, QObject::tr("Volume free space"), "", info, QByteArray(), freeSpace, QByteArray(), false, parsingDataToQByteArray(pdata), index);
} }
break; // Exit from parsing loop break; // Exit from parsing loop
} }
@ -1417,17 +1417,26 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
// Skip non-file entries and pad files // Skip non-file entries and pad files
if (model->type(current) != Types::File || model->subtype(current) == EFI_FV_FILETYPE_PAD) if (model->type(current) != Types::File || model->subtype(current) == EFI_FV_FILETYPE_PAD)
continue; continue;
QByteArray currentGuid = model->header(current).left(sizeof(EFI_GUID));
// Get current file parsing data
PARSING_DATA currentPdata = parsingDataFromQModelIndex(current);
QByteArray currentGuid((const char*)&currentPdata.file.guid, sizeof(EFI_GUID));
// Check files after current for having an equal GUID // Check files after current for having an equal GUID
for (int j = i + 1; j < model->rowCount(index); j++) { for (int j = i + 1; j < model->rowCount(index); j++) {
QModelIndex another = index.child(j, 0); QModelIndex another = index.child(j, 0);
// Skip non-file entries // Skip non-file entries
if (model->type(another) != Types::File) if (model->type(another) != Types::File)
continue; continue;
// Get another file parsing data
PARSING_DATA anotherPdata = parsingDataFromQModelIndex(another);
QByteArray anotherGuid((const char*)&anotherPdata.file.guid, sizeof(EFI_GUID));
// Check GUIDs for being equal // Check GUIDs for being equal
QByteArray anotherGuid = model->header(another).left(sizeof(EFI_GUID));
if (currentGuid == anotherGuid) { if (currentGuid == anotherGuid) {
msg(QObject::tr("parseVolumeBody: file with duplicate GUID %1").arg(guidToQString(*(const EFI_GUID*)anotherGuid.constData())), another); msg(QObject::tr("parseVolumeBody: file with duplicate GUID %1").arg(guidToQString(anotherPdata.file.guid)), another);
} }
} }
} }
@ -1548,19 +1557,17 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf
QByteArray body = file.mid(header.size()); QByteArray body = file.mid(header.size());
// Check for file tail presence // Check for file tail presence
UINT16 tail = 0; QByteArray tail;
bool msgInvalidTailValue = false; bool msgInvalidTailValue = false;
bool hasTail = false;
if (pdata.volume.revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) if (pdata.volume.revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT))
{ {
hasTail = true;
//Check file tail; //Check file tail;
tail = *(UINT16*)body.right(sizeof(UINT16)).constData(); UINT16 tailValue = *(UINT16*)body.right(sizeof(UINT16)).constData();
if (fileHeader->IntegrityCheck.TailReference != (UINT16)~tail) if (fileHeader->IntegrityCheck.TailReference != (UINT16)~tailValue)
msgInvalidTailValue = true; msgInvalidTailValue = true;
// Remove tail from file body // Get tail and remove it from file body
tail = body.right(sizeof(UINT16));
body = body.left(body.size() - sizeof(UINT16)); body = body.left(body.size() - sizeof(UINT16));
} }
@ -1572,47 +1579,42 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf
else else
name = QObject::tr("Pad-file"); name = QObject::tr("Pad-file");
info = QObject::tr("File GUID: %1\nType: %2h\nAttributes: %3h\nFull size: %4h (%5)\nHeader size: %6h (%7)\nBody size: %8h (%9)\nState: %10h\nHeader checksum: %11h, %12\nData checksum: %13h, %14") info = QObject::tr("File GUID: %1\nType: %2h\nAttributes: %3h\nFull size: %4h (%5)\nHeader size: %6h (%7)\nBody size: %8h (%9)\nTail size: %10h (%11)\n"
"State: %12h\nHeader checksum: %13h, %14\nData checksum: %15h, %16")
.arg(guidToQString(fileHeader->Name)) .arg(guidToQString(fileHeader->Name))
.hexarg2(fileHeader->Type, 2) .hexarg2(fileHeader->Type, 2)
.hexarg2(fileHeader->Attributes, 2) .hexarg2(fileHeader->Attributes, 2)
.hexarg(header.size() + body.size()).arg(header.size() + body.size()) .hexarg(header.size() + body.size() + tail.size()).arg(header.size() + body.size() + tail.size())
.hexarg(header.size()).arg(header.size()) .hexarg(header.size()).arg(header.size())
.hexarg(body.size()).arg(body.size()) .hexarg(body.size()).arg(body.size())
.hexarg(tail.size()).arg(tail.size())
.hexarg2(fileHeader->State, 2) .hexarg2(fileHeader->State, 2)
.hexarg2(fileHeader->IntegrityCheck.Checksum.Header, 2) .hexarg2(fileHeader->IntegrityCheck.Checksum.Header, 2)
.arg(msgInvalidHeaderChecksum ? QObject::tr("invalid, should be %1h").hexarg2(calculatedHeader, 2) : QObject::tr("valid")) .arg(msgInvalidHeaderChecksum ? QObject::tr("invalid, should be %1h").hexarg2(calculatedHeader, 2) : QObject::tr("valid"))
.hexarg2(fileHeader->IntegrityCheck.Checksum.File, 2) .hexarg2(fileHeader->IntegrityCheck.Checksum.File, 2)
.arg(msgInvalidDataChecksum ? QObject::tr("invalid, should be %1h").hexarg2(calculatedData, 2) : QObject::tr("valid")); .arg(msgInvalidDataChecksum ? QObject::tr("invalid, should be %1h").hexarg2(calculatedData, 2) : QObject::tr("valid"));
// Set raw file format to unknown by default // Add file GUID to parsing data
pdata.file.format = RAW_FILE_FORMAT_UNKNOWN; pdata.file.guid = fileHeader->Name;
QString text; QString text;
bool isVtf = false; bool isVtf = false;
QByteArray guid = header.left(sizeof(EFI_GUID));
// Check if the file is a Volume Top File // Check if the file is a Volume Top File
if (guid == EFI_FFS_VOLUME_TOP_FILE_GUID) { if (QByteArray((const char*)&fileHeader->Name, sizeof(EFI_GUID)) == EFI_FFS_VOLUME_TOP_FILE_GUID) {
// Mark it as the last VTF // Mark it as the last VTF
// This information will later be used to determine memory addresses of uncompressed image elements // This information will later be used to determine memory addresses of uncompressed image elements
// Because the last byte of the last VFT is mapped to 0xFFFFFFFF physical memory address // Because the last byte of the last VFT is mapped to 0xFFFFFFFF physical memory address
isVtf = true; isVtf = true;
text = QObject::tr("Volume Top File"); text = QObject::tr("Volume Top File");
} }
// Check if the file is NVRAM store with NVAR format
else if (guid == NVRAM_NVAR_STORE_FILE_GUID || guid == NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID) {
// Mark the file as NVAR store
pdata.file.format = RAW_FILE_FORMAT_NVAR_STORE;
}
// Construct parsing data // Construct parsing data
bool fixed = fileHeader->Attributes & FFS_ATTRIB_FIXED; bool fixed = fileHeader->Attributes & FFS_ATTRIB_FIXED;
pdata.offset += parentOffset; pdata.offset += parentOffset;
pdata.file.hasTail = hasTail ? TRUE : FALSE;
pdata.file.tail = tail;
// Add tree item // Add tree item
index = model->addItem(Types::File, fileHeader->Type, name, text, info, header, body, fixed, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parsingDataToQByteArray(pdata), parent);
// Overwrite lastVtf, if needed // Overwrite lastVtf, if needed
if (isVtf) { if (isVtf) {
@ -1678,8 +1680,8 @@ STATUS FfsParser::parseFileBody(const QModelIndex & index)
PARSING_DATA pdata = parsingDataFromQModelIndex(index); PARSING_DATA pdata = parsingDataFromQModelIndex(index);
// Parse NVAR store // Parse NVAR store
if (pdata.file.format == RAW_FILE_FORMAT_NVAR_STORE) if (QByteArray((const char*)&pdata.file.guid, sizeof(EFI_GUID)) == NVRAM_NVAR_STORE_FILE_GUID)
return parseNvarStore(model->body(index), index); return parseNvarStore(index);
return parseRawArea(index); return parseRawArea(index);
} }
@ -1726,7 +1728,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index)
pdata.offset += model->header(index).size(); pdata.offset += model->header(index).size();
// Add tree item // Add tree item
model->addItem(Types::FreeSpace, 0, QObject::tr("Free space"), QString(), info, QByteArray(), free, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FreeSpace, 0, QObject::tr("Free space"), QString(), info, QByteArray(), free, QByteArray(), false, parsingDataToQByteArray(pdata), index);
} }
else else
i = 0; i = 0;
@ -1741,7 +1743,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index)
pdata.offset += i; pdata.offset += i;
// Add tree item // Add tree item
QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
// Show message // Show message
msg(QObject::tr("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex); msg(QObject::tr("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex);
@ -1784,7 +1786,7 @@ STATUS FfsParser::parseSections(const QByteArray & sections, const QModelIndex &
// Final parsing // Final parsing
if (!preparse) { if (!preparse) {
// Add tree item // Add tree item
QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, QObject::tr("Non-UEFI data"), "", info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
// Show message // Show message
msg(QObject::tr("parseSections: non-UEFI data found in sections area"), dataIndex); msg(QObject::tr("parseSections: non-UEFI data found in sections area"), dataIndex);
@ -1894,7 +1896,7 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN
// Add tree item // Add tree item
if (!preparse) { if (!preparse) {
index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
} }
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -1943,7 +1945,7 @@ STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const
// Add tree item // Add tree item
if (!preparse) { if (!preparse) {
index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
} }
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2077,7 +2079,7 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN
// Add tree item // Add tree item
if (!preparse) { if (!preparse) {
index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent);
// Show messages // Show messages
if (msgSignedSectionFound) if (msgSignedSectionFound)
@ -2139,7 +2141,7 @@ STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, c
// Add tree item // Add tree item
if (!preparse) { if (!preparse) {
index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent);
// Rename section // Rename section
model->setName(index, guidToQString(guid)); model->setName(index, guidToQString(guid));
@ -2186,7 +2188,7 @@ STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UI
// Add tree item // Add tree item
if (!preparse) { if (!preparse) {
index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent);
} }
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2230,7 +2232,7 @@ STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const U
// Add tree item // Add tree item
if (!preparse) { if (!preparse) {
index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent);
} }
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2592,7 +2594,11 @@ STATUS FfsParser::parseRawSectionBody(const QModelIndex & index)
// Check for apriori file // Check for apriori file
QModelIndex parentFile = model->findParentOfType(index, Types::File); QModelIndex parentFile = model->findParentOfType(index, Types::File);
QByteArray parentFileGuid = model->header(parentFile).left(sizeof(EFI_GUID));
// Get parent file parsing data
PARSING_DATA pdata = parsingDataFromQModelIndex(parentFile);
QByteArray parentFileGuid((const char*)&pdata.file.guid, sizeof(EFI_GUID));
if (parentFileGuid == EFI_PEI_APRIORI_FILE_GUID) { // PEI apriori file if (parentFileGuid == EFI_PEI_APRIORI_FILE_GUID) { // PEI apriori file
// Parse apriori file list // Parse apriori file list
QString str; QString str;
@ -2617,6 +2623,13 @@ STATUS FfsParser::parseRawSectionBody(const QModelIndex & index)
return ERR_SUCCESS; return ERR_SUCCESS;
} }
else if (parentFileGuid == NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID) {
// Parse NVAR area
parseNvarStore(index);
// Set parent file text
model->setText(parentFile, QObject::tr("NVRAM external defaults"));
}
// Parse as raw area // Parse as raw area
return parseRawArea(index); return parseRawArea(index);
@ -2773,7 +2786,7 @@ STATUS FfsParser::performSecondPass(const QModelIndex & index)
PARSING_DATA pdata = parsingDataFromQModelIndex(lastVtf); PARSING_DATA pdata = parsingDataFromQModelIndex(lastVtf);
// Calculate address difference // Calculate address difference
const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + (pdata.file.hasTail ? sizeof(UINT16) : 0); const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size();
const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1; const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1;
// Apply address information to index and all it's child items // Apply address information to index and all it's child items
@ -2861,7 +2874,7 @@ STATUS FfsParser::addOffsetsRecursive(const QModelIndex & index)
return ERR_SUCCESS; return ERR_SUCCESS;
} }
STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & index) STATUS FfsParser::parseNvarStore(const QModelIndex & index)
{ {
// Sanity check // Sanity check
if (!index.isValid()) if (!index.isValid())
@ -2871,6 +2884,9 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
PARSING_DATA pdata = parsingDataFromQModelIndex(index); PARSING_DATA pdata = parsingDataFromQModelIndex(index);
UINT32 parentOffset = pdata.offset + model->header(index).size(); UINT32 parentOffset = pdata.offset + model->header(index).size();
// Get item data
const QByteArray data = model->body(index);
// Rename parent file // Rename parent file
model->setText(model->findParentOfType(index, Types::File), QObject::tr("NVAR store")); model->setText(model->findParentOfType(index, Types::File), QObject::tr("NVAR store"));
@ -2894,7 +2910,7 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
UINT32 guidIndex = 0; UINT32 guidIndex = 0;
UINT8 storedChecksum = 0; UINT8 storedChecksum = 0;
UINT8 calculatedChecksum = 0; UINT8 calculatedChecksum = 0;
UINT16 extendedHeaderSize = 0; UINT32 extendedHeaderSize = 0;
UINT8 extendedAttributes = 0; UINT8 extendedAttributes = 0;
UINT64 timestamp = 0; UINT64 timestamp = 0;
QByteArray hash; QByteArray hash;
@ -2904,7 +2920,7 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
QString text; QString text;
QByteArray header; QByteArray header;
QByteArray body; QByteArray body;
QByteArray extendedData; QByteArray tail;
UINT32 guidAreaSize = guidsInStore * sizeof(EFI_GUID); UINT32 guidAreaSize = guidsInStore * sizeof(EFI_GUID);
UINT32 unparsedSize = (UINT32)data.size() - offset - guidAreaSize; UINT32 unparsedSize = (UINT32)data.size() - offset - guidAreaSize;
@ -2945,7 +2961,7 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
// Construct parsing data // Construct parsing data
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add tree item // Add tree item
model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Add GUID store area // Add GUID store area
QByteArray guidArea = data.right(guidAreaSize); QByteArray guidArea = data.right(guidAreaSize);
@ -2957,7 +2973,7 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
// Construct parsing data // Construct parsing data
pdata.offset = parentOffset + offset + padding.size(); pdata.offset = parentOffset + offset + padding.size();
// Add tree item // Add tree item
model->addItem(Types::Padding, getPaddingType(guidArea), name, QString(), info, QByteArray(), guidArea, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(guidArea), name, QString(), info, QByteArray(), guidArea, QByteArray(), false, parsingDataToQByteArray(pdata), index);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2990,7 +3006,7 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
msgUnknownExtDataFormat = true; msgUnknownExtDataFormat = true;
extendedHeaderSize = *(UINT16*)(body.constData() + body.size() - sizeof(UINT16)); extendedHeaderSize = *(UINT16*)(body.constData() + body.size() - sizeof(UINT16));
if (extendedHeaderSize > body.size()) { if (extendedHeaderSize > (UINT32)body.size()) {
msgExtHeaderTooLong = true; msgExtHeaderTooLong = true;
isInvalid = true; isInvalid = true;
// Do not parse further // Do not parse further
@ -3023,20 +3039,20 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
msgUnknownExtDataFormat = false; msgUnknownExtDataFormat = false;
} }
extendedData = body.mid(body.size() - extendedHeaderSize + sizeof(UINT8), extendedHeaderSize - sizeof(UINT16) - sizeof(UINT8) - (hasChecksum ? 1 : 0)); tail = body.mid(body.size() - extendedHeaderSize);
body = body.left(body.size() - extendedHeaderSize); body = body.left(body.size() - extendedHeaderSize);
// Entry with authenticated write (for SecureBoot) // Entry with authenticated write (for SecureBoot)
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE) { if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE) {
if ((UINT32)extendedData.size() < sizeof(UINT64) + SHA256_HASH_SIZE) { if ((UINT32)tail.size() < sizeof(UINT64) + SHA256_HASH_SIZE) {
msgExtDataTooShort = true; msgExtDataTooShort = true;
isInvalid = true; isInvalid = true;
// Do not parse further // Do not parse further
goto parsing_done; goto parsing_done;
} }
timestamp = *(UINT64*)(extendedData.constData()); timestamp = *(UINT64*)(tail.constData() + sizeof(UINT8));
hash = extendedData.mid(sizeof(UINT64), SHA256_HASH_SIZE); hash = tail.mid(sizeof(UINT64) + sizeof(UINT8), SHA256_HASH_SIZE);
hasTimestampAndHash = true; hasTimestampAndHash = true;
msgUnknownExtDataFormat = false; msgUnknownExtDataFormat = false;
} }
@ -3072,7 +3088,7 @@ STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & in
// Get entry name // Get entry name
{ {
UINT32 nameOffset = (entryHeader->Attributes & NVRAM_NVAR_ENTRY_GUID) ? sizeof(EFI_GUID) : 1; // GUID can be stored with the variable or in a separate store, so there will only be an index of it UINT32 nameOffset = (entryHeader->Attributes & NVRAM_NVAR_ENTRY_GUID) ? sizeof(EFI_GUID) : sizeof(UINT8); // GUID can be stored with the variable or in a separate store, so there will only be an index of it
CHAR8* namePtr = (CHAR8*)(entryHeader + 1) + nameOffset; CHAR8* namePtr = (CHAR8*)(entryHeader + 1) + nameOffset;
UINT32 nameSize = 0; UINT32 nameSize = 0;
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_ASCII_NAME) { // Name is stored as ASCII string of CHAR8s if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_ASCII_NAME) { // Name is stored as ASCII string of CHAR8s
@ -3127,7 +3143,7 @@ parsing_done:
info += QObject::tr("GUID index: %1\n").arg(guidIndex); info += QObject::tr("GUID index: %1\n").arg(guidIndex);
// Add header, body and extended data info // Add header, body and extended data info
info += QObject::tr("Full size: %1h (%2)\nHeader size %3h (%4)\nBody size: %5h (%6)") info += QObject::tr("Full size: %1h (%2)\nHeader size: %3h (%4)\nBody size: %5h (%6)")
.hexarg(entryHeader->Size).arg(entryHeader->Size) .hexarg(entryHeader->Size).arg(entryHeader->Size)
.hexarg(header.size()).arg(header.size()) .hexarg(header.size()).arg(header.size())
.hexarg(body.size()).arg(body.size()); .hexarg(body.size()).arg(body.size());
@ -3154,15 +3170,10 @@ parsing_done:
if (hasChecksum) if (hasChecksum)
info += QObject::tr("\nChecksum: %1h%2").hexarg2(storedChecksum, 2) info += QObject::tr("\nChecksum: %1h%2").hexarg2(storedChecksum, 2)
.arg(calculatedChecksum ? QObject::tr(", invalid, should be %1h").hexarg2(0x100 - calculatedChecksum, 2) : QObject::tr(", valid")); .arg(calculatedChecksum ? QObject::tr(", invalid, should be %1h").hexarg2(0x100 - calculatedChecksum, 2) : QObject::tr(", valid"));
// Extended data
if (!extendedData.isEmpty())
info += QObject::tr("\nExtended data size: %1h (%2)")
.hexarg(extendedData.size()).arg(extendedData.size());
// Authentication data // Authentication data
if (hasTimestampAndHash) { if (hasTimestampAndHash) {
info += QObject::tr("\nTimestamp: %1h\nHash: %2") info += QObject::tr("\nTimestamp: %1h\nHash: %2")
.hexarg2(timestamp, 16).arg(QString(hash.toHex())); .hexarg(timestamp).arg(QString(hash.toHex().toUpper()));
} }
} }
@ -3170,19 +3181,19 @@ parsing_done:
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add tree item // Add tree item
QModelIndex varIndex = model->addItem(Types::NvarEntry, subtype, name, text, info, header, body, FALSE, parsingDataToQByteArray(pdata), index); QModelIndex varIndex = model->addItem(Types::NvarEntry, subtype, name, text, info, header, body, tail, false, parsingDataToQByteArray(pdata), index);
// Show messages // Show messages
if (msgUnknownExtDataFormat) msg(QObject::tr("parseNvarStore: unknown extended data format"), varIndex); if (msgUnknownExtDataFormat) msg(QObject::tr("parseNvarStore: unknown extended data format"), varIndex);
if (msgExtHeaderTooLong) msg(QObject::tr("parseNvarStore: extended header size (%1h) is greater than body size (%2h)") if (msgExtHeaderTooLong) msg(QObject::tr("parseNvarStore: extended header size (%1h) is greater than body size (%2h)")
.hexarg(extendedHeaderSize).hexarg(body.size()), varIndex); .hexarg(extendedHeaderSize).hexarg(body.size()), varIndex);
if (msgExtDataTooShort) msg(QObject::tr("parseNvarStore: extended data size (%1h) is smaller than required for timestamp and hash (0x28)") if (msgExtDataTooShort) msg(QObject::tr("parseNvarStore: extended header size (%1h) is too small for timestamp and hash")
.hexarg(extendedData.size()), varIndex); .hexarg(tail.size()), varIndex);
// Try parsing the entry data as NVAR storage if it begins with NVAR signature // Try parsing the entry data as NVAR storage if it begins with NVAR signature
if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry) if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry)
&& *(const UINT32*)body.constData() == NVRAM_NVAR_ENTRY_SIGNATURE) && *(const UINT32*)body.constData() == NVRAM_NVAR_ENTRY_SIGNATURE)
parseNvarStore(body, varIndex); parseNvarStore(varIndex);
// Move to next exntry // Move to next exntry
offset += entryHeader->Size; offset += entryHeader->Size;
@ -3225,7 +3236,7 @@ STATUS FfsParser::parseNvramVolumeBody(const QModelIndex & index)
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
} }
// Search for and parse all stores // Search for and parse all stores
@ -3249,7 +3260,7 @@ STATUS FfsParser::parseNvramVolumeBody(const QModelIndex & index)
pdata.offset = parentOffset + paddingOffset; pdata.offset = parentOffset + paddingOffset;
// Add tree item // Add tree item
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
} }
// Get store size // Get store size
@ -3274,7 +3285,7 @@ STATUS FfsParser::parseNvramVolumeBody(const QModelIndex & index)
pdata.offset = parentOffset + storeOffset; pdata.offset = parentOffset + storeOffset;
// Add tree item // Add tree item
QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
msg(QObject::tr("parseNvramVolumeBody: one of stores inside overlaps the end of data"), paddingIndex); msg(QObject::tr("parseNvramVolumeBody: one of stores inside overlaps the end of data"), paddingIndex);
// Update variables // Update variables
@ -3329,7 +3340,7 @@ STATUS FfsParser::parseNvramVolumeBody(const QModelIndex & index)
pdata.offset = parentOffset + storeOffset; pdata.offset = parentOffset + storeOffset;
// Add tree item // Add tree item
model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index); model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, QByteArray(), true, parsingDataToQByteArray(pdata), index);
} }
// Parse bodies // Parse bodies
@ -3606,7 +3617,7 @@ STATUS FfsParser::parseVssStoreHeader(const QByteArray & store, const UINT32 par
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::VssStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::VssStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3674,7 +3685,7 @@ STATUS FfsParser::parseFtwStoreHeader(const QByteArray & store, const UINT32 par
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::FtwStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::FtwStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3747,7 +3758,7 @@ STATUS FfsParser::parseFdcStoreHeader(const QByteArray & store, const UINT32 par
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::FdcStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::FdcStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3800,7 +3811,7 @@ STATUS FfsParser::parseFsysStoreHeader(const QByteArray & store, const UINT32 pa
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::FsysStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::FsysStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3852,7 +3863,7 @@ STATUS FfsParser::parseEvsaStoreHeader(const QByteArray & store, const UINT32 pa
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::EvsaStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::EvsaStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3898,7 +3909,7 @@ STATUS FfsParser::parseFlashMapStoreHeader(const QByteArray & store, const UINT3
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::FlashMapStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::FlashMapStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3942,7 +3953,7 @@ STATUS FfsParser::parseCmdbStoreHeader(const QByteArray & store, const UINT32 pa
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::CmdbStore, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::CmdbStore, 0, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -3990,7 +4001,7 @@ STATUS FfsParser::parseSlicPubkeyHeader(const QByteArray & store, const UINT32 p
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::SlicData, Subtypes::PubkeySlicData, name, QString(), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::SlicData, Subtypes::PubkeySlicData, name, QString(), info, header, QByteArray(), QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -4037,7 +4048,7 @@ STATUS FfsParser::parseSlicMarkerHeader(const QByteArray & store, const UINT32 p
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::SlicData, Subtypes::MarkerSlicData, name, QString(), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::SlicData, Subtypes::MarkerSlicData, name, QString(), info, header, QByteArray(), QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -4089,7 +4100,7 @@ STATUS FfsParser::parseIntelMicrocodeHeader(const QByteArray & store, const UINT
pdata.offset = parentOffset; pdata.offset = parentOffset;
// Add tree item // Add tree item
index = model->addItem(Types::Microcode, Subtypes::IntelMicrocode, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent); index = model->addItem(Types::Microcode, Subtypes::IntelMicrocode, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -4287,7 +4298,7 @@ STATUS FfsParser::parseVssStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add tree item // Add tree item
model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, QByteArray(), false, parsingDataToQByteArray(pdata), index);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -4337,7 +4348,7 @@ STATUS FfsParser::parseVssStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add tree item // Add tree item
model->addItem(Types::VssEntry, subtype, name, text, info, header, body, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::VssEntry, subtype, name, text, info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Move to next variable // Move to next variable
offset += variableSize; offset += variableSize;
@ -4387,7 +4398,7 @@ STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add EOF tree item // Add EOF tree item
model->addItem(Types::FsysEntry, 0, name, QString(), info, header, QByteArray(), FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FsysEntry, 0, name, QString(), info, header, QByteArray(), QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Add free space // Add free space
offset += header.size(); offset += header.size();
@ -4400,7 +4411,7 @@ STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add free space tree item // Add free space tree item
model->addItem(Types::FreeSpace, 0, QObject::tr("Free space"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FreeSpace, 0, QObject::tr("Free space"), QString(), info, QByteArray(), body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -4421,7 +4432,7 @@ STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add free space tree item // Add free space tree item
model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Show message // Show message
msg(QObject::tr("parseFsysStoreBody: next variable appears too big, added as padding"), index); msg(QObject::tr("parseFsysStoreBody: next variable appears too big, added as padding"), index);
@ -4443,7 +4454,7 @@ STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add tree item // Add tree item
model->addItem(Types::FsysEntry, 0, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FsysEntry, 0, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Move to next variable // Move to next variable
offset += variableSize; offset += variableSize;
@ -4504,7 +4515,7 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add free space tree item // Add free space tree item
QModelIndex itemIndex = model->addItem(type, subtype, name, QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); QModelIndex itemIndex = model->addItem(type, subtype, name, QString(), info, QByteArray(), body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Show message // Show message
if (type == Types::Padding) if (type == Types::Padding)
@ -4609,7 +4620,7 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add free space tree item // Add free space tree item
QModelIndex itemIndex = model->addItem(type, subtype, name, QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); QModelIndex itemIndex = model->addItem(type, subtype, name, QString(), info, QByteArray(), body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Show message // Show message
if (type == Types::Padding) if (type == Types::Padding)
@ -4621,7 +4632,7 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add tree item // Add tree item
model->addItem(Types::EvsaEntry, subtype, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::EvsaEntry, subtype, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Move to next variable // Move to next variable
offset += variableSize; offset += variableSize;
@ -4705,7 +4716,7 @@ STATUS FfsParser::parseFlashMapBody(const QModelIndex & index)
pdata.offset = parentOffset + offset; pdata.offset = parentOffset + offset;
// Add free space tree item // Add free space tree item
model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index); model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, QByteArray(), false, parsingDataToQByteArray(pdata), index);
// Show message // Show message
if (unparsedSize < entryHeader->Size) if (unparsedSize < entryHeader->Size)
@ -4743,7 +4754,7 @@ STATUS FfsParser::parseFlashMapBody(const QModelIndex & index)
} }
// Add tree item // Add tree item
model->addItem(Types::FlashMapEntry, subtype, name, flashMapGuidToQString(entryHeader->Guid), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), index); model->addItem(Types::FlashMapEntry, subtype, name, flashMapGuidToQString(entryHeader->Guid), info, header, QByteArray(), QByteArray(), true, parsingDataToQByteArray(pdata), index);
// Move to next variable // Move to next variable
offset += sizeof(PHOENIX_FLASH_MAP_ENTRY); offset += sizeof(PHOENIX_FLASH_MAP_ENTRY);

View File

@ -116,7 +116,7 @@ private:
STATUS getStoreSize(const QByteArray & data, const UINT32 storeOffset, UINT32 & storeSize); STATUS getStoreSize(const QByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
STATUS parseStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index); STATUS parseStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseNvarStore(const QByteArray & data, const QModelIndex & index); STATUS parseNvarStore(const QModelIndex & index);
STATUS parseVssStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index); STATUS parseVssStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFtwStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index); STATUS parseFtwStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFdcStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index); STATUS parseFdcStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);

View File

@ -19,15 +19,6 @@ routines without the need of backward traversal
#include "basetypes.h" #include "basetypes.h"
//typedef struct CAPSULE_PARSING_DATA_ {
//} CAPSULE_PARSING_DATA;
//typedef struct IMAGE_PARSING_DATA_ {
//} IMAGE_PARSING_DATA;
//typedef struct PADDING_PARSING_DATA_ {
//} PADDING_PARSING_DATA;
typedef struct VOLUME_PARSING_DATA_ { typedef struct VOLUME_PARSING_DATA_ {
EFI_GUID extendedHeaderGuid; EFI_GUID extendedHeaderGuid;
UINT32 alignment; UINT32 alignment;
@ -38,21 +29,10 @@ typedef struct VOLUME_PARSING_DATA_ {
BOOLEAN isWeakAligned; BOOLEAN isWeakAligned;
} VOLUME_PARSING_DATA; } VOLUME_PARSING_DATA;
//typedef struct FREE_SPACE_PARSING_DATA_ {
//} FREE_SPACE_PARSING_DATA;
typedef struct FILE_PARSING_DATA_ { typedef struct FILE_PARSING_DATA_ {
union { EFI_GUID guid;
UINT8 tailArray[2];
UINT16 tail;
};
BOOLEAN hasTail;
UINT8 format;
} FILE_PARSING_DATA; } FILE_PARSING_DATA;
#define RAW_FILE_FORMAT_UNKNOWN 0
#define RAW_FILE_FORMAT_NVAR_STORE 1
typedef struct COMPRESSED_SECTION_PARSING_DATA_ { typedef struct COMPRESSED_SECTION_PARSING_DATA_ {
UINT32 uncompressedSize; UINT32 uncompressedSize;
UINT8 compressionType; UINT8 compressionType;
@ -83,8 +63,8 @@ typedef struct SECTION_PARSING_DATA_ {
} SECTION_PARSING_DATA; } SECTION_PARSING_DATA;
typedef struct NVAR_ENTRY_PARSING_DATA_ { typedef struct NVAR_ENTRY_PARSING_DATA_ {
UINT32 next;
BOOLEAN isValid; BOOLEAN isValid;
UINT32 next;
} NVAR_ENTRY_PARSING_DATA; } NVAR_ENTRY_PARSING_DATA;
typedef struct PARSING_DATA_ { typedef struct PARSING_DATA_ {

View File

@ -17,7 +17,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, TreeItem::TreeItem(const UINT8 type, const UINT8 subtype,
const QString & name, const QString & text, const QString & info, const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const BOOLEAN fixed, const BOOLEAN compressed, const QByteArray & parsingData, const BOOLEAN fixed, const BOOLEAN compressed, const QByteArray & parsingData,
TreeItem *parent) : TreeItem *parent) :
itemAction(Actions::NoAction), itemAction(Actions::NoAction),
@ -28,6 +28,7 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype,
itemInfo(info), itemInfo(info),
itemHeader(header), itemHeader(header),
itemBody(body), itemBody(body),
itemTail(tail),
itemParsingData(parsingData), itemParsingData(parsingData),
itemFixed(fixed), itemFixed(fixed),
itemCompressed(compressed), itemCompressed(compressed),

View File

@ -24,9 +24,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
class TreeItem class TreeItem
{ {
public: public:
TreeItem(const UINT8 type, const UINT8 subtype = 0, const QString &name = QString(), const QString &text = QString(), const QString &info = QString(), TreeItem(const UINT8 type, const UINT8 subtype, const QString &name, const QString &text, const QString &info,
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const BOOLEAN fixed = FALSE, const BOOLEAN compressed = FALSE, const QByteArray & parsingData = QByteArray(), const BOOLEAN fixed, const BOOLEAN compressed, const QByteArray & parsingData,
TreeItem *parent = 0); TreeItem *parent = 0);
~TreeItem() { qDeleteAll(childItems); } ~TreeItem() { qDeleteAll(childItems); }
@ -63,6 +63,9 @@ public:
QByteArray body() const { return itemBody; }; QByteArray body() const { return itemBody; };
bool hasEmptyBody() const { return itemBody.isEmpty(); } bool hasEmptyBody() const { return itemBody.isEmpty(); }
QByteArray tail() const { return itemTail; };
bool hasEmptyTail() const { return itemTail.isEmpty(); }
QByteArray parsingData() const { return itemParsingData; } QByteArray parsingData() const { return itemParsingData; }
bool hasEmptyParsingData() const { return itemParsingData.isEmpty(); } bool hasEmptyParsingData() const { return itemParsingData.isEmpty(); }
void setParsingData(const QByteArray & data) { itemParsingData = data; } void setParsingData(const QByteArray & data) { itemParsingData = data; }
@ -90,6 +93,7 @@ private:
QString itemInfo; QString itemInfo;
QByteArray itemHeader; QByteArray itemHeader;
QByteArray itemBody; QByteArray itemBody;
QByteArray itemTail;
QByteArray itemParsingData; QByteArray itemParsingData;
bool itemFixed; bool itemFixed;
bool itemCompressed; bool itemCompressed;

View File

@ -17,7 +17,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
TreeModel::TreeModel(QObject *parent) TreeModel::TreeModel(QObject *parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
{ {
rootItem = new TreeItem(Types::Root); rootItem = new TreeItem(Types::Root, 0, QString(), QString(), QString(), QByteArray(), QByteArray(), QByteArray(), TRUE, FALSE, QByteArray());
} }
TreeModel::~TreeModel() TreeModel::~TreeModel()
@ -79,8 +79,7 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
return QVariant(); return QVariant();
} }
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
const
{ {
if (!hasIndex(row, column, parent)) if (!hasIndex(row, column, parent))
return QModelIndex(); return QModelIndex();
@ -178,6 +177,22 @@ bool TreeModel::hasEmptyBody(const QModelIndex &index) const
return item->hasEmptyBody(); return item->hasEmptyBody();
} }
QByteArray TreeModel::tail(const QModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->tail();
}
bool TreeModel::hasEmptyTail(const QModelIndex &index) const
{
if (!index.isValid())
return true;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->hasEmptyTail();
}
QByteArray TreeModel::parsingData(const QModelIndex &index) const QByteArray TreeModel::parsingData(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())
@ -360,7 +375,7 @@ void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data)
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype,
const QString & name, const QString & text, const QString & info, const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const bool fixed, const QByteArray & parsingData, const bool fixed, const QByteArray & parsingData,
const QModelIndex & parent, const UINT8 mode) const QModelIndex & parent, const UINT8 mode)
{ {
@ -383,7 +398,7 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype,
} }
} }
TreeItem *newItem = new TreeItem(type, subtype, name, text, info, header, body, fixed, this->compressed(parent), parsingData, parentItem); TreeItem *newItem = new TreeItem(type, subtype, name, text, info, header, body, tail, fixed, this->compressed(parent), parsingData, parentItem);
if (mode == CREATE_MODE_APPEND) { if (mode == CREATE_MODE_APPEND) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
@ -424,7 +439,7 @@ QModelIndex TreeModel::findParentOfType(const QModelIndex& index, UINT8 type) co
for (item = static_cast<TreeItem*>(parent.internalPointer()); for (item = static_cast<TreeItem*>(parent.internalPointer());
item != NULL && item != rootItem && item->type() != type; item != NULL && item != rootItem && item->type() != type;
item = static_cast<TreeItem*>(parent.internalPointer())) item = static_cast<TreeItem*>(parent.internalPointer()))
parent = parent.parent(); parent = parent.parent();
if (item != NULL && item != rootItem) if (item != NULL && item != rootItem)
return parent; return parent;

View File

@ -62,6 +62,8 @@ public:
bool hasEmptyHeader(const QModelIndex &index) const; bool hasEmptyHeader(const QModelIndex &index) const;
QByteArray body(const QModelIndex &index) const; QByteArray body(const QModelIndex &index) const;
bool hasEmptyBody(const QModelIndex &index) const; bool hasEmptyBody(const QModelIndex &index) const;
QByteArray tail(const QModelIndex &index) const;
bool hasEmptyTail(const QModelIndex &index) const;
QByteArray parsingData(const QModelIndex &index) const; QByteArray parsingData(const QModelIndex &index) const;
bool hasEmptyParsingData(const QModelIndex &index) const; bool hasEmptyParsingData(const QModelIndex &index) const;
UINT8 action(const QModelIndex &index) const; UINT8 action(const QModelIndex &index) const;
@ -69,10 +71,10 @@ public:
bool compressed(const QModelIndex &index) const; bool compressed(const QModelIndex &index) const;
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, QModelIndex addItem(const UINT8 type, const UINT8 subtype,
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(), const QString & name, const QString & text, const QString & info,
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const bool fixed = false, const QByteArray & parsingData = QByteArray(), const bool fixed, const QByteArray & parsingData = QByteArray(),
const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const; QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;