From f6c429f00c80f505cc159aaf65f2eb95f966a47e Mon Sep 17 00:00:00 2001
From: Nikolaj Schlej <schlej@live.de>
Date: Sun, 13 Sep 2015 16:36:43 +0200
Subject: [PATCH] NE alpha10

- added FIT messages widget and related messages
- corrected small text issues
---
 UEFITool/uefitool.cpp | 39 ++++++++++++++++++++++++++++++++++-----
 UEFITool/uefitool.h   |  1 +
 UEFITool/uefitool.ui  | 14 ++++++++++++--
 common/ffsparser.cpp  | 29 ++++++++++++++++++-----------
 common/fitparser.cpp  | 38 ++++++++++++++++++++++++++------------
 common/fitparser.h    |  9 +++++++++
 6 files changed, 100 insertions(+), 30 deletions(-)

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 &current)
@@ -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<QPair<QString, QModelIndex> > messages = fitParser->getMessages();
+    QPair<QString, QModelIndex> 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<MessageListItem*>(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 @@
       </widget>
       <widget class="QTabWidget" name="messagesTabWidget">
        <property name="currentIndex">
-        <number>0</number>
+        <number>2</number>
        </property>
        <widget class="QWidget" name="parserTab">
         <attribute name="title">
@@ -223,7 +223,17 @@
           <number>5</number>
          </property>
          <item>
-          <widget class="QTableWidget" name="fitTableWidget"/>
+          <widget class="QSplitter" name="splitter">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <widget class="QTableWidget" name="fitTableWidget"/>
+           <widget class="QListWidget" name="fitMessagesListWidget">
+            <property name="mouseTracking">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </widget>
          </item>
         </layout>
        </widget>
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<QString, QModelIndex>(message, index));
+}
+
+QVector<QPair<QString, QModelIndex> > 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<QString> 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<QPair<QString, QModelIndex> > getMessages() const;
+    // Clears messages
+    void clearMessages();
+
     STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf);
     QVector<QVector<QString> > getFitTable() const { return fitTable; }
 
 private:
     TreeModel *model;
+    QVector<QPair<QString, QModelIndex> > messagesVector;
     QModelIndex lastVtf;
     QVector<QVector<QString> > 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