mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-21 23:48:22 +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) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::UEFITool),
|
||||
version(tr("0.30.0_alpha11"))
|
||||
version(tr("0.30.0_alpha12"))
|
||||
{
|
||||
clipboard = QApplication::clipboard();
|
||||
|
||||
@ -619,13 +619,13 @@ void UEFITool::saveImageFile()
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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())
|
||||
return;
|
||||
QProcess::startDetached(currentProgramPath, QStringList(path));
|
||||
@ -695,7 +695,7 @@ 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
|
||||
else if (ui->messagesTabWidget->currentIndex() == 2) // FIT tab
|
||||
clipboard->setText(ui->fitMessagesListWidget->currentItem()->text());
|
||||
}
|
||||
|
||||
@ -898,7 +898,6 @@ void UEFITool::showFitTable()
|
||||
ui->fitTableWidget->clear();
|
||||
ui->fitTableWidget->setRowCount(fitTable.length());
|
||||
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->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
|
@ -85,7 +85,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
||||
.arg(guidToQString(capsuleHeader->CapsuleGuid))
|
||||
.hexarg(buffer.size()).arg(buffer.size())
|
||||
.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);
|
||||
|
||||
// Construct parsing data
|
||||
@ -1178,6 +1178,66 @@ STATUS FfsParser::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UI
|
||||
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)
|
||||
{
|
||||
// Sanity check
|
||||
@ -1227,7 +1287,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
||||
pdata.fixed = FALSE; // Free space is not fixed
|
||||
pdata.offset = offset + volumeHeaderSize + fileOffset;
|
||||
|
||||
// Add all bytes before as free space...
|
||||
// Add all bytes before as free space
|
||||
if (i > 0) {
|
||||
QByteArray free = freeSpace.left(i);
|
||||
|
||||
@ -1238,18 +1298,9 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
||||
// Add free space item
|
||||
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
|
||||
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);
|
||||
msg(tr("parseVolumeBody: non-UEFI data found in volume's free space"), dataIndex);
|
||||
// Parse non-UEFI data
|
||||
parseVolumeNonUefiData(freeSpace.mid(i), volumeHeaderSize + fileOffset + i, index);
|
||||
}
|
||||
else {
|
||||
// Construct parsing data
|
||||
@ -1266,21 +1317,8 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
||||
break; // Exit from parsing loop
|
||||
}
|
||||
else { //File space
|
||||
// Add padding to the end of the volume
|
||||
pdata.fixed = TRUE; // Non-UEFI data is fixed
|
||||
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);
|
||||
|
||||
// Parse non-UEFI data
|
||||
parseVolumeNonUefiData(volumeBody.mid(fileOffset), volumeHeaderSize + fileOffset, index);
|
||||
break; // Exit from parsing loop
|
||||
}
|
||||
}
|
||||
@ -1614,7 +1652,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index)
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
STATUS FfsParser::parseSections(QByteArray sections, const QModelIndex & index)
|
||||
STATUS FfsParser::parseSections(const QByteArray & sections, const QModelIndex & index)
|
||||
{
|
||||
// Sanity check
|
||||
if (!index.isValid())
|
||||
|
@ -70,7 +70,8 @@ private:
|
||||
STATUS parseEcRegion(const QByteArray & ec, const UINT32 parentOffset, const QModelIndex & parent, 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 parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||
|
@ -69,14 +69,17 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
|
||||
|
||||
// Special case of FIT header
|
||||
const FIT_ENTRY* fitHeader = (const FIT_ENTRY*)(model->body(fitIndex).constData() + fitOffset);
|
||||
|
||||
|
||||
// Check FIT checksum, if present
|
||||
UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4;
|
||||
if (fitHeader->Type & 0x80) {
|
||||
// Calculate FIT entry checksum
|
||||
UINT8 calculated = calculateChecksum8((const UINT8*)fitHeader, fitSize);
|
||||
if (calculated) {
|
||||
msg(tr("Invalid FIT table checksum"), fitIndex);
|
||||
QByteArray tempFIT = model->body(fitIndex).mid(fitOffset, fitSize);
|
||||
FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data();
|
||||
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
|
||||
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||
|
||||
// Check for FIT signature in item's body
|
||||
INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
|
||||
if (offset >= 0) {
|
||||
// Check for all FIT signatures in item's body
|
||||
for (INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
|
||||
offset >= 0;
|
||||
offset = model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) {
|
||||
// FIT candidate found, calculate it's physical address
|
||||
UINT32 fitAddress = pdata.address + model->header(index).size() + (UINT32)offset;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user