diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index c4def60..68683b9 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_alpha10")) +version(tr("0.30.0_alpha11")) { clipboard = QApplication::clipboard(); @@ -107,6 +107,8 @@ void UEFITool::init() ui->parserMessagesListWidget->clear(); ui->finderMessagesListWidget->clear(); ui->fitTableWidget->clear(); + ui->fitTableWidget->setRowCount(0); + ui->fitTableWidget->setColumnCount(0); ui->infoEdit->clear(); // Set window title @@ -261,11 +263,11 @@ void UEFITool::search() void UEFITool::rebuild() { - QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); + /*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; - /*UINT8 result = ffsEngine->rebuild(index); + UINT8 result = ffsEngine->rebuild(index); if (result == ERR_SUCCESS) ui->actionSaveImageFile->setEnabled(true);*/ @@ -273,11 +275,11 @@ void UEFITool::rebuild() void UEFITool::remove() { - QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); + /*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; - /*UINT8 result = ffsEngine->remove(index); + UINT8 result = ffsEngine->remove(index); if (result == ERR_SUCCESS) ui->actionSaveImageFile->setEnabled(true);*/ @@ -285,7 +287,7 @@ void UEFITool::remove() void UEFITool::insert(const UINT8 mode) { - QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); + /*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; @@ -329,7 +331,7 @@ void UEFITool::insert(const UINT8 mode) QByteArray buffer = inputFile.readAll(); inputFile.close(); - /*UINT8 result = ffsEngine->insert(index, buffer, mode); + UINT8 result = ffsEngine->insert(index, buffer, mode); if (result) { QMessageBox::critical(this, tr("Insertion failed"), errorMessage(result), QMessageBox::Ok); return; @@ -364,7 +366,7 @@ void UEFITool::replaceBody() void UEFITool::replace(const UINT8 mode) { - QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); + /*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; @@ -444,7 +446,7 @@ void UEFITool::replace(const UINT8 mode) QByteArray buffer = inputFile.readAll(); inputFile.close(); - /*UINT8 result = ffsEngine->replace(index, buffer, mode); + UINT8 result = ffsEngine->replace(index, buffer, mode); if (result) { QMessageBox::critical(this, tr("Replacing failed"), errorMessage(result), QMessageBox::Ok); return; @@ -657,13 +659,14 @@ void UEFITool::openImageFile(QString path) UINT8 result = ffsParser->parseImageFile(buffer, model->index(0,0)); showParserMessages(); - if (result) + if (result) { QMessageBox::critical(this, tr("Image parsing failed"), errorCodeToQString(result), QMessageBox::Ok); + return; + } else ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName())); // Parse FIT - //!TODO: expand and chek errors result = fitParser->parse(model->index(0, 0), ffsParser->getLastVtf()); showFitMessages(); if (!result) { @@ -733,6 +736,10 @@ void UEFITool::clearMessages() ffsFinder->clearMessages(); ui->finderMessagesListWidget->clear(); } + else if (ui->messagesTabWidget->currentIndex() == 2) { // FIT tab + fitParser->clearMessages(); + ui->fitMessagesListWidget->clear(); + } ui->actionMessagesCopy->setEnabled(false); ui->actionMessagesCopyAll->setEnabled(false); } @@ -793,7 +800,6 @@ void UEFITool::showFitMessages() ui->fitMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second)); } - ui->messagesTabWidget->setCurrentIndex(2); ui->fitMessagesListWidget->scrollToBottom(); } diff --git a/UEFITool/uefitool.ui b/UEFITool/uefitool.ui index 8e3349e..7c16b7e 100644 --- a/UEFITool/uefitool.ui +++ b/UEFITool/uefitool.ui @@ -142,7 +142,7 @@ - 2 + 0 diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index fe311e6..9218b4a 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -22,7 +22,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "fit.h" FfsParser::FfsParser(TreeModel* treeModel, QObject *parent) - : QObject(parent), model(treeModel) + : QObject(parent), model(treeModel), capsuleOffsetFixup(0) { } @@ -61,6 +61,9 @@ BOOLEAN FfsParser::hasIntersection(const UINT32 begin1, const UINT32 end1, const // Firmware image parsing functions STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & root) { + // Reset capsule offset fixeup value + capsuleOffsetFixup = 0; + // Check buffer size to be more then or equal to size of EFI_CAPSULE_HEADER if ((UINT32)buffer.size() <= sizeof(EFI_CAPSULE_HEADER)) { msg(tr("parseImageFile: image file is smaller then minimum size of %1h (%2) bytes").hexarg(sizeof(EFI_CAPSULE_HEADER)).arg(sizeof(EFI_CAPSULE_HEADER))); @@ -89,6 +92,9 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & PARSING_DATA pdata = parsingDataFromQModelIndex(QModelIndex()); pdata.fixed = TRUE; + // Set capsule offset fixup for correct volume allignment warnings + capsuleOffsetFixup = capsuleHeader->HeaderSize; + // Add tree item index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root); } @@ -111,6 +117,9 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & PARSING_DATA pdata = parsingDataFromQModelIndex(QModelIndex()); pdata.fixed = TRUE; + // Set capsule offset fixup for correct volume allignment warnings + capsuleOffsetFixup = capsuleHeader->HeaderSize; + // Add tree item index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root); } @@ -134,6 +143,9 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & PARSING_DATA pdata = parsingDataFromQModelIndex(QModelIndex()); pdata.fixed = TRUE; + // Set capsule offset fixup for correct volume allignment warnings + capsuleOffsetFixup = capsuleHeaderSize; + // Add tree item index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root); @@ -781,7 +793,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde STATUS result; UINT32 prevVolumeOffset; - result = findNextVolume(data, 0, prevVolumeOffset); + result = findNextVolume(index, data, 0, prevVolumeOffset); if (result) return result; @@ -880,7 +892,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde // Go to next volume prevVolumeOffset = volumeOffset; prevVolumeSize = volumeSize; - result = findNextVolume(data, volumeOffset + prevVolumeSize, volumeOffset); + result = findNextVolume(index, data, volumeOffset + prevVolumeSize, volumeOffset); } // Padding at the end of BIOS space @@ -1001,7 +1013,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare // Acquire alignment alignment = (UINT32)pow(2.0, (int)(volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); // Check alignment - if (!isUnknown && pdata.isOnFlash && ((pdata.offset + parentOffset) % alignment)) + if (!isUnknown && pdata.isOnFlash && ((pdata.offset + parentOffset - capsuleOffsetFixup) % alignment)) msgUnaligned = true; } else @@ -1109,12 +1121,34 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare return ERR_SUCCESS; } -STATUS FfsParser::findNextVolume(const QByteArray & bios, UINT32 volumeOffset, UINT32 & nextVolumeOffset) +STATUS FfsParser::findNextVolume(const QModelIndex index, const QByteArray & bios, UINT32 volumeOffset, UINT32 & nextVolumeOffset) { int nextIndex = bios.indexOf(EFI_FV_SIGNATURE, volumeOffset); if (nextIndex < EFI_FV_SIGNATURE_OFFSET) return ERR_VOLUMES_NOT_FOUND; + // Check volume header to be sane + for (; nextIndex > 0; nextIndex = bios.indexOf(EFI_FV_SIGNATURE, volumeOffset + nextIndex + 1)) { + const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(bios.constData() + nextIndex - EFI_FV_SIGNATURE_OFFSET); + if (volumeHeader->FvLength >= 0xFFFFFFFFUL) { + msg(tr("findNextVolume: volume candidate skipped, has invalid FvLength %1h").hexarg2(volumeHeader->FvLength, 16), index); + continue; + } + if (volumeHeader->Reserved != 0xFF && volumeHeader->Reserved != 0x00) { + msg(tr("findNextVolume: volume candidate skipped, has invalid Reserved byte value %1").hexarg2(volumeHeader->Reserved, 2), index); + continue; + } + if (volumeHeader->Revision != 1 && volumeHeader->Revision != 2) { + msg(tr("findNextVolume: volume candidate skipped, has invalid Revision byte value %1").hexarg2(volumeHeader->Revision, 2), index); + continue; + } + // All checks passed, volume found + break; + } + // No additional volumes found + if (nextIndex < EFI_FV_SIGNATURE_OFFSET) + return ERR_VOLUMES_NOT_FOUND; + nextVolumeOffset = nextIndex - EFI_FV_SIGNATURE_OFFSET; return ERR_SUCCESS; } diff --git a/common/ffsparser.h b/common/ffsparser.h index 9be8f35..7ef0341 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -60,6 +60,7 @@ private: TreeModel *model; QVector > messagesVector; QModelIndex lastVtf; + UINT32 capsuleOffsetFixup; STATUS parseIntelImage(const QByteArray & intelImage, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & root); STATUS parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index); @@ -89,15 +90,13 @@ private: UINT8 getPaddingType(const QByteArray & padding); STATUS parseAprioriRawSection(const QByteArray & body, QString & parsed); - STATUS findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); + STATUS findNextVolume(const QModelIndex index, const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); STATUS getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize); UINT32 getFileSize(const QByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion); UINT32 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion); STATUS performSecondPass(const QModelIndex & index); STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff); - /*STATUS parseFit(const QModelIndex & index); - STATUS findFitRecursive(const QModelIndex & index, QModelIndex & found);*/ // Internal operations BOOLEAN hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2); diff --git a/common/fitparser.cpp b/common/fitparser.cpp index 6c87c0f..37c8f26 100644 --- a/common/fitparser.cpp +++ b/common/fitparser.cpp @@ -184,8 +184,8 @@ STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & foun 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); + else if (model->rowCount(index) == 0) // Show messages only to leaf items + msg(tr("FIT table candidate found, but not referenced from the last VTF"), index); } return ERR_SUCCESS;