diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index f2ef7cb..c4def60 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.30.0_alpha9")) +version(tr("0.30.0_alpha10")) { clipboard = QApplication::clipboard(); @@ -72,6 +72,7 @@ version(tr("0.30.0_alpha9")) ui->infoEdit->setFont(font); ui->parserMessagesListWidget->setFont(font); ui->finderMessagesListWidget->setFont(font); + ui->fitMessagesListWidget->setFont(font); ui->fitTableWidget->setFont(font); ui->structureTreeView->setFont(font); searchDialog->ui->guidEdit->setFont(font); @@ -143,6 +144,8 @@ void UEFITool::init() connect(ui->parserMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); connect(ui->finderMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); connect(ui->finderMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); + connect(ui->fitMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); + connect(ui->fitMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); } void UEFITool::populateUi(const QModelIndex ¤t) @@ -662,8 +665,11 @@ void UEFITool::openImageFile(QString path) // Parse FIT //!TODO: expand and chek errors result = fitParser->parse(model->index(0, 0), ffsParser->getLastVtf()); - if (!result) + showFitMessages(); + if (!result) { showFitTable(); + } + // Enable search ... if (ffsFinder) @@ -686,6 +692,8 @@ void UEFITool::copyMessage() clipboard->setText(ui->parserMessagesListWidget->currentItem()->text()); else if (ui->messagesTabWidget->currentIndex() == 1) // Search tab clipboard->setText(ui->finderMessagesListWidget->currentItem()->text()); + else if (ui->messagesTabWidget->currentIndex() == 2) // Search tab + clipboard->setText(ui->fitMessagesListWidget->currentItem()->text()); } void UEFITool::copyAllMessages() @@ -702,6 +710,11 @@ void UEFITool::copyAllMessages() text.append(ui->finderMessagesListWidget->item(i)->text()).append("\n"); clipboard->setText(text); } + else if (ui->messagesTabWidget->currentIndex() == 2) { // FIT tab + for (INT32 i = 0; i < ui->fitMessagesListWidget->count(); i++) + text.append(ui->fitMessagesListWidget->item(i)->text()).append("\n"); + clipboard->setText(text); + } } void UEFITool::enableMessagesCopyActions(QListWidgetItem* item) @@ -768,6 +781,22 @@ void UEFITool::showFinderMessages() ui->finderMessagesListWidget->scrollToBottom(); } +void UEFITool::showFitMessages() +{ + ui->fitMessagesListWidget->clear(); + if (!fitParser) + return; + + QVector > messages = fitParser->getMessages(); + QPair msg; + foreach(msg, messages) { + ui->fitMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second)); + } + + ui->messagesTabWidget->setCurrentIndex(2); + ui->fitMessagesListWidget->scrollToBottom(); +} + void UEFITool::scrollTreeView(QListWidgetItem* item) { MessageListItem* messageItem = static_cast(item); @@ -862,9 +891,9 @@ void UEFITool::showFitTable() // Set up the FIT table ui->fitTableWidget->clear(); ui->fitTableWidget->setRowCount(fitTable.length()); - ui->fitTableWidget->setColumnCount(6); + ui->fitTableWidget->setColumnCount(5); //ui->fitTableWidget->verticalHeader()->setVisible(false); - ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Type") << tr("Checksum") << tr("Remark")); + ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Type") << tr("Checksum")); ui->fitTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->fitTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); @@ -872,7 +901,7 @@ void UEFITool::showFitTable() // Add all data to the table widget for (INT32 i = 0; i < fitTable.length(); i++) { - for (UINT8 j = 0; j < 6; j++) { + for (UINT8 j = 0; j < 5; j++) { ui->fitTableWidget->setItem(i, j, new QTableWidgetItem(fitTable[i][j])); } } diff --git a/UEFITool/uefitool.h b/UEFITool/uefitool.h index 321199a..c8856a5 100644 --- a/UEFITool/uefitool.h +++ b/UEFITool/uefitool.h @@ -119,6 +119,7 @@ private: void readSettings(); void showParserMessages(); void showFinderMessages(); + void showFitMessages(); void showFitTable(); }; diff --git a/UEFITool/uefitool.ui b/UEFITool/uefitool.ui index a620127..8e3349e 100644 --- a/UEFITool/uefitool.ui +++ b/UEFITool/uefitool.ui @@ -142,7 +142,7 @@ - 0 + 2 @@ -223,7 +223,17 @@ 5 - + + + Qt::Horizontal + + + + + true + + + diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 61c0a65..fe311e6 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -99,7 +99,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & capsuleHeaderSize = capsuleHeader->HeaderSize; QByteArray header = buffer.left(capsuleHeaderSize); QByteArray body = buffer.right(buffer.size() - capsuleHeaderSize); - QString name = tr("UEFI capsule"); + QString name = tr("Toshiba capsule"); QString info = tr("Offset: 0h\nCapsule GUID: %1\nFull size: %2h (%3)\nHeader size: %4h (%5)\nImage size: %6h (%7)\nFlags: %8h") .arg(guidToQString(capsuleHeader->CapsuleGuid)) .hexarg(buffer.size()).arg(buffer.size()) @@ -417,7 +417,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const UINT32 pa if (descriptorVersion == 1) { const FLASH_DESCRIPTOR_MASTER_SECTION* masterSection = (const FLASH_DESCRIPTOR_MASTER_SECTION*)calculateAddress8(descriptor, descriptorMap->MasterBase); info += tr("\nRegion access settings:"); - info += tr("\nBIOS:%1h %2h ME:%3h %4h GbE:%5h %6h") + info += tr("\nBIOS: %1h %2h ME: %3h %4h\nGbE: %5h %6h") .hexarg2(masterSection->BiosRead, 2) .hexarg2(masterSection->BiosWrite, 2) .hexarg2(masterSection->MeRead, 2) @@ -563,7 +563,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const UINT32 pa if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); + model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); } // Check if the last VTF is found @@ -902,7 +902,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); } - //Parse bodies + // Parse bodies for (int i = 0; i < model->rowCount(index); i++) { QModelIndex current = index.child(i, 0); switch (model->type(current)) { @@ -1040,7 +1040,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare QByteArray body = volume.mid(headerSize); QString name = guidToQString(volumeHeader->FileSystemGuid); QString info = tr("ZeroVector:\n%1 %2 %3 %4 %5 %6 %7 %8\n%9 %10 %11 %12 %13 %14 %15 %16\nFileSystem GUID: %17\nFull size: %18h (%19)\n" - "Header size: %20h (%21)\nBody size: %22h (%23)\nRevision: %24\nAttributes: %25h\nErase polarity: %26") + "Header size: %20h (%21)\nBody size: %22h (%23)\nRevision: %24\nAttributes: %25h\nErase polarity: %26\nChecksum: %27h, %28") .hexarg2(volumeHeader->ZeroVector[0], 2).hexarg2(volumeHeader->ZeroVector[1], 2).hexarg2(volumeHeader->ZeroVector[2], 2).hexarg2(volumeHeader->ZeroVector[3], 2) .hexarg2(volumeHeader->ZeroVector[4], 2).hexarg2(volumeHeader->ZeroVector[5], 2).hexarg2(volumeHeader->ZeroVector[6], 2).hexarg2(volumeHeader->ZeroVector[7], 2) .hexarg2(volumeHeader->ZeroVector[8], 2).hexarg2(volumeHeader->ZeroVector[9], 2).hexarg2(volumeHeader->ZeroVector[10], 2).hexarg2(volumeHeader->ZeroVector[11], 2) @@ -1051,7 +1051,9 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare .hexarg(volumeSize - headerSize).arg(volumeSize - headerSize) .arg(volumeHeader->Revision) .hexarg2(volumeHeader->Attributes, 8) - .arg(emptyByte ? "1" : "0"); + .arg(emptyByte ? "1" : "0") + .hexarg2(volumeHeader->Checksum, 4) + .arg(msgInvalidChecksum ? tr("invalid") : tr("valid")); // Extended header present if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) { @@ -1415,14 +1417,18 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf else name = tr("Pad-file"); - info = tr("File GUID: %1\nType: %2h\nAttributes: %3h\nFull size: %4h (%5)\nHeader size: %6h (%7)\nBody size: %8h (%9)\nState: %10h") + info = 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") .arg(guidToQString(fileHeader->Name)) .hexarg2(fileHeader->Type, 2) .hexarg2(fileHeader->Attributes, 2) .hexarg(header.size() + body.size()).arg(header.size() + body.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) - .hexarg2(fileHeader->State, 2); + .hexarg2(fileHeader->State, 2) + .hexarg2(fileHeader->IntegrityCheck.Checksum.Header, 2) + .arg(msgInvalidHeaderChecksum ? tr("invalid") : tr("valid")) + .hexarg2(fileHeader->IntegrityCheck.Checksum.File, 2) + .arg(msgInvalidDataChecksum ? tr("invalid") : tr("valid")); // Check if the file is a Volume Top File QString text; @@ -2111,11 +2117,12 @@ STATUS FfsParser::parseGuidedSectionBody(const QModelIndex & index) QByteArray body = model->body(index); UINT32 crc = crc32(0, (const UINT8*)body.constData(), body.size()); // Check stored CRC32 - if (crc == *(const UINT32*)(model->header(index).constData() + sizeof(EFI_GUID_DEFINED_SECTION))) { - info += tr("\nChecksum: valid"); + UINT32 stored = *(const UINT32*)(model->header(index).constData() + sizeof(EFI_GUID_DEFINED_SECTION)); + if (crc == stored) { + info += tr("\nChecksum %1h: valid").hexarg2(stored, 8); } else { - info += tr("\nChecksum: invalid"); + info += tr("\nChecksum %1h: invalid").hexarg2(stored, 8); msg(tr("parseGuidedSectionBody: GUID defined section with invalid CRC32"), index); } } diff --git a/common/fitparser.cpp b/common/fitparser.cpp index ef1d575..6c87c0f 100644 --- a/common/fitparser.cpp +++ b/common/fitparser.cpp @@ -23,6 +23,21 @@ FitParser::~FitParser() { } +void FitParser::msg(const QString & message, const QModelIndex & index) +{ + messagesVector.push_back(QPair(message, index)); +} + +QVector > FitParser::getMessages() const +{ + return messagesVector; +} + +void FitParser::clearMessages() +{ + messagesVector.clear(); +} + STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIndex) { // Check sanity @@ -53,7 +68,6 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn model->setParsingData(fitIndex, parsingDataToQByteArray(pdata)); // Special case of FIT header - QString remark; const FIT_ENTRY* fitHeader = (const FIT_ENTRY*)(model->body(fitIndex).constData() + fitOffset); // Check FIT checksum, if present @@ -62,19 +76,15 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn // Calculate FIT entry checksum UINT8 calculated = calculateChecksum8((const UINT8*)fitHeader, fitSize); if (calculated) { - remark.append(tr("Invalid FIT table checksum, ")); + msg(tr("Invalid FIT table checksum"), fitIndex); } } // Check fit header type if ((fitHeader->Type & 0x7F) != FIT_TYPE_HEADER) { - remark.append(tr("Invalid FIT header type, ")); + msg(tr("Invalid FIT header type"), fitIndex); } - // Remove the last ", " from remark string, if needed - if (!remark.isEmpty()) - remark = remark.left(remark.length() - 2); - // Add FIT header to fitTable QVector currentStrings; currentStrings += tr("_FIT_ "); @@ -82,19 +92,18 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn currentStrings += tr("%1").hexarg2(fitHeader->Version, 4); currentStrings += fitEntryTypeToQString(fitHeader->Type); currentStrings += tr("%1").hexarg2(fitHeader->Checksum, 2); - currentStrings += remark; fitTable.append(currentStrings); // Process all other entries + bool modifiedImageMayNotWork = false; for (UINT32 i = 1; i < fitHeader->Size; i++) { currentStrings.clear(); - remark.clear(); const FIT_ENTRY* currentEntry = fitHeader + i; // Check entry type switch (currentEntry->Type & 0x7F) { case FIT_TYPE_HEADER: - remark.append(tr("Second FIT header found, the table is damaged")); + msg(tr("Second FIT header found, the table is damaged"), fitIndex); break; case FIT_TYPE_EMPTY: @@ -109,7 +118,7 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn case FIT_TYPE_AC_KEY_MANIFEST: case FIT_TYPE_AC_BOOT_POLICY: default: - remark.append(tr("Modified image may not work")); + modifiedImageMayNotWork = true; break; } @@ -119,10 +128,12 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn currentStrings += tr("%1").hexarg2(currentEntry->Version, 4); currentStrings += fitEntryTypeToQString(currentEntry->Type); currentStrings += tr("%1").hexarg2(currentEntry->Checksum, 2); - currentStrings += remark; fitTable.append(currentStrings); } + if (modifiedImageMayNotWork) + msg(tr("Opened image may not work after any modification")); + return ERR_SUCCESS; } @@ -170,8 +181,11 @@ STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & foun if (*(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET) == fitAddress) { found = index; fitOffset = offset; + msg(tr("Real FIT table found at physical address %1h").hexarg(fitAddress), found); return ERR_SUCCESS; } + else + msg(tr("FIT table candidate found, but not referenced from LastVtf"), found); } return ERR_SUCCESS; diff --git a/common/fitparser.h b/common/fitparser.h index 419e3f2..312ee04 100644 --- a/common/fitparser.h +++ b/common/fitparser.h @@ -36,16 +36,25 @@ public: FitParser(TreeModel* treeModel, QObject *parent = 0); ~FitParser(); + // Returns messages + QVector > getMessages() const; + // Clears messages + void clearMessages(); + STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf); QVector > getFitTable() const { return fitTable; } private: TreeModel *model; + QVector > messagesVector; QModelIndex lastVtf; QVector > fitTable; STATUS findFitRecursive(const QModelIndex & index, QModelIndex & found, UINT32 & fitOffset); QString fitEntryTypeToQString(UINT8 type); + + // Message helper + void msg(const QString & message, const QModelIndex &index = QModelIndex()); }; #endif