Version 0.17.4

- solved a bug in wrong volume size calculation in rare cases
- added diagnostic message if FvLength and size calculated using BlockMap are different
- solved a bug that lead to unneeded PEI files relocation
- rebuild action on volume will now relocate PEI files in it
This commit is contained in:
Nikolaj Schlej 2014-02-26 09:33:38 +01:00
parent 9fb1c7eb09
commit e5d94b6479
3 changed files with 47 additions and 27 deletions

View File

@ -627,7 +627,7 @@ UINT8 FfsEngine::findNextVolume(const QByteArray & bios, UINT32 volumeOffset, UI
return ERR_SUCCESS; return ERR_SUCCESS;
} }
UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UINT32 & volumeSize, bool fromHeader) UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UINT32 & volumeSize)
{ {
// Populate volume header // Populate volume header
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) (bios.constData() + volumeOffset); EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) (bios.constData() + volumeOffset);
@ -636,22 +636,29 @@ UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UIN
if (QByteArray((const char*) &volumeHeader->Signature, sizeof(volumeHeader->Signature)) != EFI_FV_SIGNATURE) if (QByteArray((const char*) &volumeHeader->Signature, sizeof(volumeHeader->Signature)) != EFI_FV_SIGNATURE)
return ERR_INVALID_VOLUME; return ERR_INVALID_VOLUME;
if (fromHeader) { // Calculate volume size using BlockMap
// Use header field
volumeSize = volumeHeader->FvLength;
}
else {
// Use BlockMap
EFI_FV_BLOCK_MAP_ENTRY* entry = (EFI_FV_BLOCK_MAP_ENTRY*)(bios.constData() + volumeOffset + sizeof(EFI_FIRMWARE_VOLUME_HEADER)); EFI_FV_BLOCK_MAP_ENTRY* entry = (EFI_FV_BLOCK_MAP_ENTRY*)(bios.constData() + volumeOffset + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
volumeSize = 0; UINT32 bmVolumeSize = 0;
while (entry->NumBlocks != 0 && entry->Length != 0) { while (entry->NumBlocks != 0 && entry->Length != 0) {
if ((void*)entry > bios.constData() + bios.size()) if ((void*)entry > bios.constData() + bios.size())
return ERR_INVALID_VOLUME; return ERR_INVALID_VOLUME;
volumeSize += entry->NumBlocks * entry->Length; bmVolumeSize += entry->NumBlocks * entry->Length;
entry += 1; entry += 1;
} }
// Check calculated and stored volume sizes to be the same
if (volumeHeader->FvLength != bmVolumeSize) {
msg(tr("getVolumeSize: %1, volume size in header (%2) differs from calculated using BlockMap (%3). Smaller value is used.")
.arg(guidToQString(volumeHeader->FileSystemGuid))
.arg(volumeHeader->FvLength, 8, 16, QChar('0'))
.arg(bmVolumeSize, 8, 16, QChar('0')));
// Use smaller value as volume size
volumeSize = volumeHeader->FvLength < bmVolumeSize ? volumeHeader->FvLength : bmVolumeSize;
} }
else
volumeSize = bmVolumeSize;
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -704,7 +711,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
UINT8 result; UINT8 result;
UINT32 volumeSize; UINT32 volumeSize;
result = getVolumeSize(volume, 0, volumeSize, false); result = getVolumeSize(volume, 0, volumeSize);
if (result) if (result)
return result; return result;
@ -1601,7 +1608,9 @@ UINT8 FfsEngine::remove(const QModelIndex & index)
QModelIndex fileIndex; QModelIndex fileIndex;
if (model->type(index) == File) if (model->type(index) == Volume && model->rowCount(index) > 0)
fileIndex = index.child(0, 0);
else if(model->type(index) == File)
fileIndex = index; fileIndex = index;
else if (model->type(index) == Section) else if (model->type(index) == Section)
fileIndex = model->findParentOfType(index, File); fileIndex = model->findParentOfType(index, File);
@ -1624,7 +1633,9 @@ UINT8 FfsEngine::rebuild(const QModelIndex & index)
QModelIndex fileIndex; QModelIndex fileIndex;
if (model->type(index) == File) if (model->type(index) == Volume && model->rowCount(index) > 0)
fileIndex = index.child(0, 0);
else if (model->type(index) == File)
fileIndex = index; fileIndex = index;
else if (model->type(index) == Section) else if (model->type(index) == Section)
fileIndex = model->findParentOfType(index, File); fileIndex = model->findParentOfType(index, File);
@ -2019,7 +2030,7 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst
return ERR_NOT_IMPLEMENTED; return ERR_NOT_IMPLEMENTED;
} }
UINT8 FfsEngine::reconstructVolume(const QModelIndex& index, QByteArray& reconstructed) UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & reconstructed)
{ {
if (!index.isValid()) if (!index.isValid())
return ERR_SUCCESS; return ERR_SUCCESS;
@ -2076,7 +2087,19 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex& index, QByteArray& reconst
} }
} }
// VTF not found // Determine if volume is inside compressed item
if (!baseFound) {
// Iterate up to the root, checking for compression type to be other then none
for (QModelIndex parentIndex = index.parent(); model->type(parentIndex) != Root; parentIndex = parentIndex.parent())
if (model->compression(parentIndex) != COMPRESSION_ALGORITHM_NONE) {
// No rebase needed for compressed PEI files
baseFound = true;
volumeBase = 0;
break;
}
}
// Find volume base address using first PEI file in it
if (!baseFound) { if (!baseFound) {
// Search for first PEI-file and use it as base source // Search for first PEI-file and use it as base source
UINT32 fileOffset = header.size(); UINT32 fileOffset = header.size();
@ -2103,13 +2126,12 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex& index, QByteArray& reconst
// Calculate volume base // Calculate volume base
volumeBase = imagebase - relbase; volumeBase = imagebase - relbase;
baseFound = true; baseFound = true;
}
goto out; goto out;
} }
}
sectionOffset += model->header(peiFile.child(j,0)).size() + model->body(peiFile.child(j,0)).size(); sectionOffset += model->header(peiFile.child(j,0)).size() + model->body(peiFile.child(j,0)).size();
sectionOffset = ALIGN4(sectionOffset); sectionOffset = ALIGN4(sectionOffset);
} }
} }
fileOffset += model->header(index.child(i, 0)).size() + model->body(index.child(i, 0)).size() + model->tail(index.child(i, 0)).size(); fileOffset += model->header(index.child(i, 0)).size() + model->body(index.child(i, 0)).size() + model->tail(index.child(i, 0)).size();
fileOffset = ALIGN8(fileOffset); fileOffset = ALIGN8(fileOffset);
@ -2572,8 +2594,6 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
msg(tr("reconstructSection: can't get entry point of PEI core"), index); msg(tr("reconstructSection: can't get entry point of PEI core"), index);
} }
} }
else
msg(tr("reconstructSection: volume base is unknown, section can't be rebased"), index);
} }
// Reconstruction successful // Reconstruction successful

View File

@ -93,7 +93,7 @@ private:
// Parsing helpers // Parsing helpers
UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, bool fromHeader = true); UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize);
UINT8 getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize); UINT8 getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize);
UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize); UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize);

View File

@ -20,7 +20,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>UEFITool 0.17.3</string> <string>UEFITool 0.17.4</string>
</property> </property>
<widget class="QWidget" name="centralWidget"> <widget class="QWidget" name="centralWidget">
<property name="sizePolicy"> <property name="sizePolicy">