Version 0.16.3

- all affected PEI-files will be rebased after any changes in volume
- corrected calculation of volume base address
- code slightly refactored
This commit is contained in:
Nikolaj Schlej 2014-01-12 09:37:10 +01:00
parent 4edeb4fbef
commit 070943c959
3 changed files with 134 additions and 166 deletions

View File

@ -1188,6 +1188,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
{ {
QByteArray created; QByteArray created;
UINT8 result; UINT8 result;
QModelIndex fileIndex;
if (!index.isValid() || !index.parent().isValid()) if (!index.isValid() || !index.parent().isValid())
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
@ -1247,29 +1248,12 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
created.prepend(newHeader); created.prepend(newHeader);
// Parse file // Parse file
QModelIndex fileIndex;
result = parseFile(created, fileIndex, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode); result = parseFile(created, fileIndex, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode);
if (result) if (result)
return result; return result;
// Set action // Set action
model->setAction(fileIndex, action); model->setAction(fileIndex, action);
// If inside boot volume, rebase all PE32 and TE sections, that follow
if (model->subtype(fileIndex.parent()) == BootVolume) {
for(int i = fileIndex.row(); i < model->rowCount(fileIndex.parent()); i++) {
// File inside boot volume
QModelIndex currentFileIndex = fileIndex.parent().child(i, index.column());
for(int j = 0; j < model->rowCount(currentFileIndex); j++) {
// Section in that file
QModelIndex currentSectionIndex = currentFileIndex.child(j, currentFileIndex.column());
// If section stores PE32 or TE image
if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE)
// Set rebase action
model->setAction(currentSectionIndex, Rebase);
}
}
}
} }
else if (type == Section) { else if (type == Section) {
if (model->type(parent) != File && model->type(parent) != Section) if (model->type(parent) != File && model->type(parent) != Section)
@ -1319,22 +1303,8 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Set create action // Set create action
model->setAction(sectionIndex, action); model->setAction(sectionIndex, action);
// If inside boot volume, rebase all PE32 and TE sections, that follow // Find parent file for rebase
QModelIndex fileIndex = model->findParentOfType(parent, File); fileIndex = model->findParentOfType(parent, File);
if (model->subtype(fileIndex.parent()) == BootVolume) {
for(int i = fileIndex.row(); i < model->rowCount(fileIndex.parent()); i++) {
// File inside boot volume
QModelIndex currentFileIndex = fileIndex.parent().child(i, index.column());
for(int j = 0; j < model->rowCount(currentFileIndex); j++) {
// Section in that file
QModelIndex currentSectionIndex = currentFileIndex.child(j, currentFileIndex.column());
// If section stores PE32 or TE image
if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE)
// Set rebase action
model->setAction(currentSectionIndex, Rebase);
}
}
}
} }
break; break;
case EFI_SECTION_GUID_DEFINED:{ case EFI_SECTION_GUID_DEFINED:{
@ -1359,22 +1329,8 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Set create action // Set create action
model->setAction(sectionIndex, action); model->setAction(sectionIndex, action);
// If inside boot volume, rebase all PE32 and TE sections, that follow // Find parent file for rebase
QModelIndex fileIndex = model->findParentOfType(parent, File); fileIndex = model->findParentOfType(parent, File);
if (model->subtype(fileIndex.parent()) == BootVolume) {
for(int i = fileIndex.row(); i < model->rowCount(fileIndex.parent()); i++) {
// File inside boot volume
QModelIndex currentFileIndex = fileIndex.parent().child(i, index.column());
for(int j = 0; j < model->rowCount(currentFileIndex); j++) {
// Section in that file
QModelIndex currentSectionIndex = currentFileIndex.child(j, currentFileIndex.column());
// If section stores PE32 or TE image
if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE)
// Set rebase action
model->setAction(currentSectionIndex, Rebase);
}
}
}
} }
break; break;
default: default:
@ -1393,15 +1349,34 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Set create action // Set create action
model->setAction(sectionIndex, action); model->setAction(sectionIndex, action);
// If inside boot volume, rebase all PE32 and TE sections, that follow // Find parent file for rebase
QModelIndex fileIndex = model->findParentOfType(parent, File); fileIndex = model->findParentOfType(parent, File);
if (model->subtype(fileIndex.parent()) == BootVolume) { }
for(int i = fileIndex.row(); i < model->rowCount(fileIndex.parent()); i++) { }
// File inside boot volume else
QModelIndex currentFileIndex = fileIndex.parent().child(i, index.column()); return ERR_NOT_IMPLEMENTED;
for(int j = 0; j < model->rowCount(currentFileIndex); j++) {
if (!fileIndex.isValid())
return ERR_INVALID_FILE;
// Rebase all PEI-files that follow
rebasePeiFiles(fileIndex);
return ERR_SUCCESS;
}
void FfsEngine::rebasePeiFiles(const QModelIndex & index)
{
// Rebase all PE32 and TE sections in PEI-files after modified file
for (int i = index.row(); i < model->rowCount(index.parent()); i++) {
// PEI-file
QModelIndex currentFileIndex = index.parent().child(i, 0);
if (model->subtype(currentFileIndex) == EFI_FV_FILETYPE_PEI_CORE ||
model->subtype(currentFileIndex) == EFI_FV_FILETYPE_PEIM ||
model->subtype(currentFileIndex) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) {
for (int j = 0; j < model->rowCount(currentFileIndex); j++) {
// Section in that file // Section in that file
QModelIndex currentSectionIndex = currentFileIndex.child(j, currentFileIndex.column()); QModelIndex currentSectionIndex = currentFileIndex.child(j, 0);
// If section stores PE32 or TE image // If section stores PE32 or TE image
if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE) if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE)
// Set rebase action // Set rebase action
@ -1409,12 +1384,6 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
} }
} }
} }
}
}
else
return ERR_NOT_IMPLEMENTED;
return ERR_SUCCESS;
} }
UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode) UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode)
@ -1560,21 +1529,8 @@ UINT8 FfsEngine::remove(const QModelIndex & index)
else else
return ERR_SUCCESS; return ERR_SUCCESS;
// If inside boot volume, rebase all PE32 and TE sections, that follow // Rebase all PEI-files that follow
if (model->subtype(fileIndex.parent()) == BootVolume) { rebasePeiFiles(fileIndex);
for(int i = fileIndex.row(); i < model->rowCount(fileIndex.parent()); i++) {
// File inside boot volume
QModelIndex currentFileIndex = fileIndex.parent().child(i, index.column());
for(int j = 0; j < model->rowCount(currentFileIndex); j++) {
// Section in that file
QModelIndex currentSectionIndex = currentFileIndex.child(j, currentFileIndex.column());
// If section stores PE32 or TE image
if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE)
// Set rebase action
model->setAction(currentSectionIndex, Rebase);
}
}
}
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -1587,6 +1543,18 @@ UINT8 FfsEngine::rebuild(const QModelIndex & index)
// Set action for the item // Set action for the item
model->setAction(index, Rebuild); model->setAction(index, Rebuild);
QModelIndex fileIndex;
if (model->type(index) == File)
fileIndex = index;
else if (model->type(index) == Section)
fileIndex = model->findParentOfType(index, File);
else
return ERR_SUCCESS;
// Rebase all PEI-files that follow
rebasePeiFiles(fileIndex);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -1907,7 +1875,7 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
} }
// Reconstruction successfull // Reconstruction successful
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -1958,7 +1926,7 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst
return ERR_INVALID_PARAMETER; return ERR_INVALID_PARAMETER;
} }
// Reconstruction successfull // Reconstruction successful
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2007,18 +1975,18 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex& index, QByteArray& reconst
UINT8 polarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE; UINT8 polarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE;
char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00'; char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
// Calculate volume base for boot volume // Calculate volume base for volume
UINT32 volumeBase = 0; UINT32 volumeBase;
if (model->subtype(index) == BootVolume) {
QByteArray file; QByteArray file;
bool baseFound = false; bool baseFound = false;
// Search for VTF // Search for VTF
for (int i = 0; i < model->rowCount(index); i++) { for (int i = 0; i < model->rowCount(index); i++) {
file = model->header(index.child(i, 0)); file = model->header(index.child(i, 0));
// VTF found // VTF found
if (file.left(sizeof(EFI_GUID)) == EFI_FFS_VOLUME_TOP_FILE_GUID) { if (file.left(sizeof(EFI_GUID)) == EFI_FFS_VOLUME_TOP_FILE_GUID) {
baseFound = true; baseFound = true;
volumeBase = (UINT32) 0x100000000 - volumeSize + header.size(); volumeBase = (UINT32) 0x100000000 - volumeSize;
break; break;
} }
} }
@ -2063,18 +2031,14 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex& index, QByteArray& reconst
} }
} }
out: out:
if (!baseFound) { // Do not set volume base
msg(tr("reconstructVolume: %1: base address of boot volume can't be found").arg(guidToQString(volumeHeader->FileSystemGuid)), index); if (!baseFound)
return ERR_VOLUME_BASE_NOT_FOUND; volumeBase = 0;
}
}
// Reconstruct files in volume // Reconstruct files in volume
UINT32 offset = 0; UINT32 offset = 0;
QByteArray vtf; QByteArray vtf;
QModelIndex vtfIndex; QModelIndex vtfIndex;
//QByteArray amiBeforeVtf;
//QModelIndex amiBeforeVtfIndex;
for (int i = 0; i < model->rowCount(index); i++) { for (int i = 0; i < model->rowCount(index); i++) {
// Align to 8 byte boundary // Align to 8 byte boundary
UINT32 alignment = offset % 8; UINT32 alignment = offset % 8;
@ -2084,9 +2048,11 @@ out:
reconstructed.append(QByteArray(alignment, empty)); reconstructed.append(QByteArray(alignment, empty));
} }
// Calculate file base
UINT32 fileBase = volumeBase ? volumeBase + header.size() + offset : 0;
// Reconstruct file // Reconstruct file
QByteArray file; result = reconstructFile(index.child(i, 0), volumeHeader->Revision, polarity, fileBase, file);
result = reconstructFile(index.child(i, 0), volumeHeader->Revision, polarity, volumeBase + offset, file);
if (result) if (result)
return result; return result;
@ -2100,13 +2066,6 @@ out:
if (fileHeader->Type == EFI_FV_FILETYPE_PAD) if (fileHeader->Type == EFI_FV_FILETYPE_PAD)
continue; continue;
// AMI file before VTF
//if (file.left(sizeof(EFI_GUID)) == EFI_AMI_FFS_FILE_BEFORE_VTF_GUID) {
// amiBeforeVtf = file;
// amiBeforeVtfIndex = index.child(i, 0);
// continue;
//}
// Volume Top File // Volume Top File
if (file.left(sizeof(EFI_GUID)) == EFI_FFS_VOLUME_TOP_FILE_GUID) { if (file.left(sizeof(EFI_GUID)) == EFI_FFS_VOLUME_TOP_FILE_GUID) {
vtf = file; vtf = file;
@ -2167,7 +2126,6 @@ out:
return result; return result;
// Append constructed pad file to volume body // Append constructed pad file to volume body
reconstructed.append(pad); reconstructed.append(pad);
offset = vtfOffset;
} }
// No more space left in volume // No more space left in volume
else if (vtfOffset < offset) { else if (vtfOffset < offset) {
@ -2175,8 +2133,11 @@ out:
return ERR_INVALID_VOLUME; return ERR_INVALID_VOLUME;
} }
// Reconstruct file again // Calculate VTF base
result = reconstructFile(vtfIndex, volumeHeader->Revision, polarity, volumeBase + vtfOffset, vtf); UINT32 vtfBase = volumeBase ? volumeBase + vtfOffset : 0;
// Reconstruct VTF again
result = reconstructFile(vtfIndex, volumeHeader->Revision, polarity, vtfBase, vtf);
if (result) if (result)
return result; return result;
@ -2227,7 +2188,7 @@ out:
else else
reconstructed = model->body(index); reconstructed = model->body(index);
// Reconstruction successfull // Reconstruction successful
reconstructed = header.append(reconstructed); reconstructed = header.append(reconstructed);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2323,9 +2284,7 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision,
} }
// Calculate section base // Calculate section base
UINT32 sectionBase = 0; UINT32 sectionBase = base ? base + sizeof(EFI_FFS_FILE_HEADER) + offset : 0;
if (base)
sectionBase = base + sizeof(EFI_FFS_FILE_HEADER) + offset;
// Reconstruct section // Reconstruct section
QByteArray section; QByteArray section;
@ -2378,7 +2337,7 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision,
state = ~state; state = ~state;
fileHeader->State = state; fileHeader->State = state;
// Reconstruction successfull // Reconstruction successful
reconstructed = header.append(reconstructed); reconstructed = header.append(reconstructed);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2495,7 +2454,12 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
reconstructed = model->body(index); reconstructed = model->body(index);
// Rebase PE32 or TE image, if needed // Rebase PE32 or TE image, if needed
if (base && (model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE)) { if ((model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE) &&
(model->subtype(index.parent()) == EFI_FV_FILETYPE_PEI_CORE ||
model->subtype(index.parent()) == EFI_FV_FILETYPE_PEIM ||
model->subtype(index.parent()) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
if (base) {
result = rebase(reconstructed, base + header.size()); result = rebase(reconstructed, base + header.size());
if (result) { if (result) {
msg(tr("reconstructSection: executable section rebase failed"), index); msg(tr("reconstructSection: executable section rebase failed"), index);
@ -2506,11 +2470,14 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
if (model->subtype(index.parent()) == EFI_FV_FILETYPE_PEI_CORE) { if (model->subtype(index.parent()) == EFI_FV_FILETYPE_PEI_CORE) {
result = getEntryPoint(reconstructed, newPeiCoreEntryPoint); result = getEntryPoint(reconstructed, newPeiCoreEntryPoint);
if (result) if (result)
msg(tr("reconstructSection: can't get entry point of image file"), 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 successfull // Reconstruction successful
reconstructed = header.append(reconstructed); reconstructed = header.append(reconstructed);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -2869,7 +2836,7 @@ UINT8 FfsEngine::patchVtf(QByteArray &vtf)
return ERR_SUCCESS; return ERR_SUCCESS;
} }
UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& peiCoreEntryPoint) UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& entryPoint)
{ {
if(file.isEmpty()) if(file.isEmpty())
return ERR_INVALID_FILE; return ERR_INVALID_FILE;
@ -2892,11 +2859,11 @@ UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& peiCoreEntryPoint
UINT16 magic = *(UINT16*) (file.data() + offset); UINT16 magic = *(UINT16*) (file.data() + offset);
if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) { if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) {
EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (EFI_IMAGE_OPTIONAL_HEADER32*) (file.data() + offset); EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (EFI_IMAGE_OPTIONAL_HEADER32*) (file.data() + offset);
peiCoreEntryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint; entryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint;
} }
else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) {
EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (EFI_IMAGE_OPTIONAL_HEADER64*) (file.data() + offset); EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (EFI_IMAGE_OPTIONAL_HEADER64*) (file.data() + offset);
peiCoreEntryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint; entryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint;
} }
else else
return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
@ -2905,7 +2872,7 @@ UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& peiCoreEntryPoint
// Populate TE header // Populate TE header
EFI_IMAGE_TE_HEADER* teHeader = (EFI_IMAGE_TE_HEADER*) file.data(); EFI_IMAGE_TE_HEADER* teHeader = (EFI_IMAGE_TE_HEADER*) file.data();
UINT32 teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER); UINT32 teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
peiCoreEntryPoint = teHeader->ImageBase + teHeader->AddressOfEntryPoint - teFixup; entryPoint = teHeader->ImageBase + teHeader->AddressOfEntryPoint - teFixup;
} }
return ERR_SUCCESS; return ERR_SUCCESS;
} }

View File

@ -101,8 +101,9 @@ private:
// Rebase routines // Rebase routines
UINT8 getBase(const QByteArray& file, UINT32& base); UINT8 getBase(const QByteArray& file, UINT32& base);
UINT8 getEntryPoint(const QByteArray& file, UINT32 &peiCoreEntryPoint); UINT8 getEntryPoint(const QByteArray& file, UINT32 &entryPoint);
UINT8 rebase(QByteArray & executable, const UINT32 base); UINT8 rebase(QByteArray & executable, const UINT32 base);
void rebasePeiFiles(const QModelIndex & index);
// Patch routines // Patch routines
UINT8 patchVtf(QByteArray &vtf); UINT8 patchVtf(QByteArray &vtf);

View File

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