mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 16:08:23 +08:00
UT NE A12
- added detection of VTF inside volume's non-UEFI data - corrected ImageSize information for EFI capsule - *.scap is added to the list of known Image file extensions - all FIT candidates in a tree item are checked for being referenced from the last VTF now
This commit is contained in:
parent
788397f60c
commit
6d8e5976f7
@ -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_alpha11"))
|
version(tr("0.30.0_alpha12"))
|
||||||
{
|
{
|
||||||
clipboard = QApplication::clipboard();
|
clipboard = QApplication::clipboard();
|
||||||
|
|
||||||
@ -619,13 +619,13 @@ void UEFITool::saveImageFile()
|
|||||||
|
|
||||||
void UEFITool::openImageFile()
|
void UEFITool::openImageFile()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
|
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *scap *.bio *.fd *.wph *.dec);;All files (*)");
|
||||||
openImageFile(path);
|
openImageFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::openImageFileInNewWindow()
|
void UEFITool::openImageFileInNewWindow()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file in new window"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
|
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file in new window"), currentDir, "BIOS image files (*.rom *.bin *.cap *scap *.bio *.fd *.wph *.dec);;All files (*)");
|
||||||
if (path.trimmed().isEmpty())
|
if (path.trimmed().isEmpty())
|
||||||
return;
|
return;
|
||||||
QProcess::startDetached(currentProgramPath, QStringList(path));
|
QProcess::startDetached(currentProgramPath, QStringList(path));
|
||||||
@ -695,7 +695,7 @@ void UEFITool::copyMessage()
|
|||||||
clipboard->setText(ui->parserMessagesListWidget->currentItem()->text());
|
clipboard->setText(ui->parserMessagesListWidget->currentItem()->text());
|
||||||
else if (ui->messagesTabWidget->currentIndex() == 1) // Search tab
|
else if (ui->messagesTabWidget->currentIndex() == 1) // Search tab
|
||||||
clipboard->setText(ui->finderMessagesListWidget->currentItem()->text());
|
clipboard->setText(ui->finderMessagesListWidget->currentItem()->text());
|
||||||
else if (ui->messagesTabWidget->currentIndex() == 2) // Search tab
|
else if (ui->messagesTabWidget->currentIndex() == 2) // FIT tab
|
||||||
clipboard->setText(ui->fitMessagesListWidget->currentItem()->text());
|
clipboard->setText(ui->fitMessagesListWidget->currentItem()->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -898,7 +898,6 @@ void UEFITool::showFitTable()
|
|||||||
ui->fitTableWidget->clear();
|
ui->fitTableWidget->clear();
|
||||||
ui->fitTableWidget->setRowCount(fitTable.length());
|
ui->fitTableWidget->setRowCount(fitTable.length());
|
||||||
ui->fitTableWidget->setColumnCount(5);
|
ui->fitTableWidget->setColumnCount(5);
|
||||||
//ui->fitTableWidget->verticalHeader()->setVisible(false);
|
|
||||||
ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Type") << tr("Checksum"));
|
ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Type") << tr("Checksum"));
|
||||||
ui->fitTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
ui->fitTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
@ -85,7 +85,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
.arg(guidToQString(capsuleHeader->CapsuleGuid))
|
.arg(guidToQString(capsuleHeader->CapsuleGuid))
|
||||||
.hexarg(buffer.size()).arg(buffer.size())
|
.hexarg(buffer.size()).arg(buffer.size())
|
||||||
.hexarg(capsuleHeader->HeaderSize).arg(capsuleHeader->HeaderSize)
|
.hexarg(capsuleHeader->HeaderSize).arg(capsuleHeader->HeaderSize)
|
||||||
.hexarg(capsuleHeader->CapsuleImageSize).arg(capsuleHeader->CapsuleImageSize)
|
.hexarg(capsuleHeader->CapsuleImageSize - capsuleHeader->HeaderSize).arg(capsuleHeader->CapsuleImageSize - capsuleHeader->HeaderSize)
|
||||||
.hexarg2(capsuleHeader->Flags, 8);
|
.hexarg2(capsuleHeader->Flags, 8);
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
@ -1178,6 +1178,66 @@ STATUS FfsParser::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UI
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATUS FfsParser::parseVolumeNonUefiData(const QByteArray & data, const UINT32 parentOffset, const QModelIndex & index)
|
||||||
|
{
|
||||||
|
// Sanity check
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Get parsing data
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
|
// Modify it
|
||||||
|
pdata.fixed = TRUE; // Non-UEFI data is fixed
|
||||||
|
pdata.offset += parentOffset;
|
||||||
|
|
||||||
|
// Search for VTF GUID backwards in received data
|
||||||
|
QByteArray padding = data;
|
||||||
|
QByteArray vtf;
|
||||||
|
INT32 vtfIndex = data.lastIndexOf(EFI_FFS_VOLUME_TOP_FILE_GUID);
|
||||||
|
if (vtfIndex > 0) { // VTF found inside non-UEFI data
|
||||||
|
padding = data.left(vtfIndex);
|
||||||
|
vtf = data.mid(vtfIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add non-UEFI data first
|
||||||
|
// Get info
|
||||||
|
QString info = tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size());
|
||||||
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
|
// Add padding tree item
|
||||||
|
QModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index);
|
||||||
|
msg(tr("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex);
|
||||||
|
|
||||||
|
if (vtfIndex > 0) {
|
||||||
|
// Get VTF file header
|
||||||
|
QByteArray header = vtf.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||||
|
const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData();
|
||||||
|
if (pdata.ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
|
||||||
|
header = vtf.left(sizeof(EFI_FFS_FILE_HEADER2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse VTF file header
|
||||||
|
QModelIndex fileIndex;
|
||||||
|
STATUS result = parseFileHeader(vtf, parentOffset + vtfIndex, index, fileIndex);
|
||||||
|
if (result) {
|
||||||
|
msg(tr("parseVolumeNonUefiData: VTF file header parsing failed with error \"%1\"").arg(errorCodeToQString(result)), index);
|
||||||
|
|
||||||
|
// Add the rest as non-UEFI data too
|
||||||
|
pdata.offset += vtfIndex;
|
||||||
|
// Get info
|
||||||
|
QString info = tr("Full size: %1h (%2)").hexarg(vtf.size()).arg(vtf.size());
|
||||||
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
|
// Add padding tree item
|
||||||
|
QModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), vtf, parsingDataToQByteArray(pdata), index);
|
||||||
|
msg(tr("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
@ -1227,7 +1287,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
|||||||
pdata.fixed = FALSE; // Free space is not fixed
|
pdata.fixed = FALSE; // Free space is not fixed
|
||||||
pdata.offset = offset + volumeHeaderSize + fileOffset;
|
pdata.offset = offset + volumeHeaderSize + fileOffset;
|
||||||
|
|
||||||
// Add all bytes before as free space...
|
// Add all bytes before as free space
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
QByteArray free = freeSpace.left(i);
|
QByteArray free = freeSpace.left(i);
|
||||||
|
|
||||||
@ -1238,18 +1298,9 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
|||||||
// Add free space item
|
// Add free space item
|
||||||
model->addItem(Types::FreeSpace, 0, tr("Volume free space"), "", info, QByteArray(), free, parsingDataToQByteArray(pdata), index);
|
model->addItem(Types::FreeSpace, 0, tr("Volume free space"), "", info, QByteArray(), free, parsingDataToQByteArray(pdata), index);
|
||||||
}
|
}
|
||||||
// ... and all bytes after as a padding
|
|
||||||
pdata.fixed = TRUE; // Non-UEFI data is fixed
|
|
||||||
pdata.offset += i;
|
|
||||||
QByteArray padding = freeSpace.mid(i);
|
|
||||||
|
|
||||||
// Get info
|
// Parse non-UEFI data
|
||||||
QString info = tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size());
|
parseVolumeNonUefiData(freeSpace.mid(i), volumeHeaderSize + fileOffset + i, index);
|
||||||
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
|
||||||
|
|
||||||
// Add padding tree item
|
|
||||||
QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index);
|
|
||||||
msg(tr("parseVolumeBody: non-UEFI data found in volume's free space"), dataIndex);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
@ -1266,21 +1317,8 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
|||||||
break; // Exit from parsing loop
|
break; // Exit from parsing loop
|
||||||
}
|
}
|
||||||
else { //File space
|
else { //File space
|
||||||
// Add padding to the end of the volume
|
// Parse non-UEFI data
|
||||||
pdata.fixed = TRUE; // Non-UEFI data is fixed
|
parseVolumeNonUefiData(volumeBody.mid(fileOffset), volumeHeaderSize + fileOffset, index);
|
||||||
pdata.offset = offset + volumeHeaderSize + fileOffset;
|
|
||||||
QByteArray padding = volumeBody.mid(fileOffset);
|
|
||||||
|
|
||||||
// Get info
|
|
||||||
QString info = tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size());
|
|
||||||
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
|
||||||
|
|
||||||
// Add padding tree item
|
|
||||||
QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index);
|
|
||||||
|
|
||||||
// Show message
|
|
||||||
msg(tr("parseVolumeBody: non-UEFI data found inside volume's file space"), dataIndex);
|
|
||||||
|
|
||||||
break; // Exit from parsing loop
|
break; // Exit from parsing loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1614,7 +1652,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseSections(QByteArray sections, const QModelIndex & index)
|
STATUS FfsParser::parseSections(const QByteArray & sections, const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
|
@ -70,7 +70,8 @@ private:
|
|||||||
STATUS parseEcRegion(const QByteArray & ec, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseEcRegion(const QByteArray & ec, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
|
|
||||||
STATUS parsePadFileBody(const QModelIndex & index);
|
STATUS parsePadFileBody(const QModelIndex & index);
|
||||||
STATUS parseSections(QByteArray sections, const QModelIndex & index);
|
STATUS parseVolumeNonUefiData(const QByteArray & data, const UINT32 parentOffset, const QModelIndex & index);
|
||||||
|
STATUS parseSections(const QByteArray & sections, const QModelIndex & index);
|
||||||
|
|
||||||
STATUS parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
STATUS parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
|
@ -74,9 +74,12 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
|
|||||||
UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4;
|
UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4;
|
||||||
if (fitHeader->Type & 0x80) {
|
if (fitHeader->Type & 0x80) {
|
||||||
// Calculate FIT entry checksum
|
// Calculate FIT entry checksum
|
||||||
UINT8 calculated = calculateChecksum8((const UINT8*)fitHeader, fitSize);
|
QByteArray tempFIT = model->body(fitIndex).mid(fitOffset, fitSize);
|
||||||
if (calculated) {
|
FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data();
|
||||||
msg(tr("Invalid FIT table checksum"), fitIndex);
|
tempFitHeader->Checksum = 0;
|
||||||
|
UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize);
|
||||||
|
if (calculated != fitHeader->Checksum) {
|
||||||
|
msg(tr("Invalid FIT table checksum %1h, should be %2h").hexarg2(fitHeader->Checksum, 2).hexarg2(calculated, 2), fitIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,9 +173,10 @@ STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & foun
|
|||||||
// Get parsing data for the current item
|
// Get parsing data for the current item
|
||||||
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
// Check for FIT signature in item's body
|
// Check for all FIT signatures in item's body
|
||||||
INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
|
for (INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
|
||||||
if (offset >= 0) {
|
offset >= 0;
|
||||||
|
offset = model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) {
|
||||||
// FIT candidate found, calculate it's physical address
|
// FIT candidate found, calculate it's physical address
|
||||||
UINT32 fitAddress = pdata.address + model->header(index).size() + (UINT32)offset;
|
UINT32 fitAddress = pdata.address + model->header(index).size() + (UINT32)offset;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user