mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
NE_alpha4
- second pass of parsing to add physical memory addresses to all uncompressed items in the tree - TE image revisions can be detected now - more builder routines, but still not ready for enabling - PE and TE header info is back
This commit is contained in:
parent
129819314d
commit
87bd80b72c
@ -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_alpha3"))
|
version(tr("0.30.0_alpha4"))
|
||||||
{
|
{
|
||||||
clipboard = QApplication::clipboard();
|
clipboard = QApplication::clipboard();
|
||||||
|
|
||||||
|
@ -37,9 +37,15 @@ void FfsBuilder::clearMessages()
|
|||||||
messagesVector.clear();
|
messagesVector.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image)
|
STATUS FfsBuilder::erase(const QModelIndex & index, QByteArray & erased)
|
||||||
{
|
{
|
||||||
return ERR_NOT_IMPLEMENTED;
|
// Sanity check
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
||||||
|
erased.fill(pdata.emptyByte);
|
||||||
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
|
STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
|
||||||
@ -63,20 +69,24 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
|
|||||||
// Clear the supplied QByteArray
|
// Clear the supplied QByteArray
|
||||||
capsule.clear();
|
capsule.clear();
|
||||||
|
|
||||||
// Reconstruct children
|
// Build children
|
||||||
for (int i = 0; i < model->rowCount(index); i++) {
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
QModelIndex currentChild = index.child(i, 0);
|
QModelIndex currentChild = index.child(i, 0);
|
||||||
QByteArray currentData;
|
QByteArray currentData;
|
||||||
// Check child type
|
// Check child type
|
||||||
if (model->type(currentChild) == Types::Image) {
|
if (model->type(currentChild) == Types::Image) {
|
||||||
result = buildImage(currentChild, currentData);
|
if (model->subtype(currentChild) == Subtypes::IntelImage)
|
||||||
if (!result) {
|
result = buildIntelImage(currentChild, currentData);
|
||||||
capsule.append(currentData);
|
else
|
||||||
}
|
result = buildRawArea(currentChild, currentData);
|
||||||
else {
|
|
||||||
|
// Check build result
|
||||||
|
if (result) {
|
||||||
msg(tr("buildCapsule: building of \"%1\" failed with error \"%2\", original item data used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
|
msg(tr("buildCapsule: building of \"%1\" failed with error \"%2\", original item data used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
|
||||||
capsule.append(model->header(currentChild)).append(model->body(currentChild));
|
capsule.append(model->header(currentChild)).append(model->body(currentChild));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
capsule.append(currentData);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg(tr("buildCapsule: unexpected child item of type \"%1\" can't be processed, original item data used").arg(itemTypeToQString(model->type(currentChild))), currentChild);
|
msg(tr("buildCapsule: unexpected child item of type \"%1\" can't be processed, original item data used").arg(itemTypeToQString(model->type(currentChild))), currentChild);
|
||||||
@ -85,18 +95,16 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check size of reconstructed capsule, it must remain the same
|
// Check size of reconstructed capsule, it must remain the same
|
||||||
if (capsule.size() > model->body(index).size()) {
|
UINT32 newSize = capsule.size();
|
||||||
|
UINT32 oldSize = model->body(index).size();
|
||||||
|
if (newSize > oldSize) {
|
||||||
msg(tr("buildCapsule: new capsule size %1h (%2) is bigger than the original %3h (%4)")
|
msg(tr("buildCapsule: new capsule size %1h (%2) is bigger than the original %3h (%4)")
|
||||||
.hexarg(capsule.size()).arg(capsule.size())
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize),index);
|
||||||
.hexarg(model->body(index).size()).arg(model->body(index).size()),
|
|
||||||
index);
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
else if (capsule.size() < model->body(index).size()) {
|
else if (newSize < oldSize) {
|
||||||
msg(tr("buildCapsule: new capsule size %1h (%2) is smaller than the original %3h (%4)")
|
msg(tr("buildCapsule: new capsule size %1h (%2) is smaller than the original %3h (%4)")
|
||||||
.hexarg(capsule.size()).arg(capsule.size())
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
.hexarg(model->body(index).size()).arg(model->body(index).size()),
|
|
||||||
index);
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,16 +115,197 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
|
|||||||
capsule = model->header(index).append(capsule);
|
capsule = model->header(index).append(capsule);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg(tr("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
|
msg(tr("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
|
||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsBuilder::buildImage(const QModelIndex & index, QByteArray & intelImage)
|
STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intelImage)
|
||||||
{
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
UINT8 result;
|
||||||
|
|
||||||
|
// No action
|
||||||
|
if (model->action(index) == Actions::NoAction) {
|
||||||
|
intelImage = model->header(index).append(model->body(index));
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other supported actions
|
||||||
|
else if (model->action(index) == Actions::Rebuild) {
|
||||||
|
intelImage.clear();
|
||||||
|
// First child will always be descriptor for this type of image
|
||||||
|
QByteArray descriptor;
|
||||||
|
result = buildRegion(index.child(0, 0), descriptor);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
intelImage.append(descriptor);
|
||||||
|
|
||||||
|
const FLASH_DESCRIPTOR_MAP* descriptorMap = (const FLASH_DESCRIPTOR_MAP*)(descriptor.constData() + sizeof(FLASH_DESCRIPTOR_HEADER));
|
||||||
|
const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->RegionBase);
|
||||||
|
QByteArray gbe;
|
||||||
|
UINT32 gbeBegin = calculateRegionOffset(regionSection->GbeBase);
|
||||||
|
UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit);
|
||||||
|
QByteArray me;
|
||||||
|
UINT32 meBegin = calculateRegionOffset(regionSection->MeBase);
|
||||||
|
UINT32 meEnd = meBegin + calculateRegionSize(regionSection->MeBase, regionSection->MeLimit);
|
||||||
|
QByteArray bios;
|
||||||
|
UINT32 biosBegin = calculateRegionOffset(regionSection->BiosBase);
|
||||||
|
UINT32 biosEnd = biosBegin + calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit);
|
||||||
|
QByteArray pdr;
|
||||||
|
UINT32 pdrBegin = calculateRegionOffset(regionSection->PdrBase);
|
||||||
|
UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit);
|
||||||
|
|
||||||
|
UINT32 offset = descriptor.size();
|
||||||
|
// Reconstruct other regions
|
||||||
|
char empty = '\xFF';
|
||||||
|
for (int i = 1; i < model->rowCount(index); i++) {
|
||||||
|
QByteArray region;
|
||||||
|
result = buildRegion(index.child(i, 0), region);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
UINT8 type = model->subtype(index.child(i, 0));
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Subtypes::GbeRegion:
|
||||||
|
gbe = region;
|
||||||
|
if (gbeBegin > offset)
|
||||||
|
intelImage.append(QByteArray(gbeBegin - offset, empty));
|
||||||
|
intelImage.append(gbe);
|
||||||
|
offset = gbeEnd;
|
||||||
|
break;
|
||||||
|
case Subtypes::MeRegion:
|
||||||
|
me = region;
|
||||||
|
if (meBegin > offset)
|
||||||
|
intelImage.append(QByteArray(meBegin - offset, empty));
|
||||||
|
intelImage.append(me);
|
||||||
|
offset = meEnd;
|
||||||
|
break;
|
||||||
|
case Subtypes::BiosRegion:
|
||||||
|
bios = region;
|
||||||
|
if (biosBegin > offset)
|
||||||
|
intelImage.append(QByteArray(biosBegin - offset, empty));
|
||||||
|
intelImage.append(bios);
|
||||||
|
offset = biosEnd;
|
||||||
|
break;
|
||||||
|
case Subtypes::PdrRegion:
|
||||||
|
pdr = region;
|
||||||
|
if (pdrBegin > offset)
|
||||||
|
intelImage.append(QByteArray(pdrBegin - offset, empty));
|
||||||
|
intelImage.append(pdr);
|
||||||
|
offset = pdrEnd;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg(tr("buildIntelImage: unknown region type found"), index);
|
||||||
|
return ERR_INVALID_REGION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((UINT32)model->body(index).size() > offset)
|
||||||
|
intelImage.append(QByteArray((UINT32)model->body(index).size() - offset, empty));
|
||||||
|
|
||||||
|
// Check size of new image, it must be same as old one
|
||||||
|
UINT32 newSize = intelImage.size();
|
||||||
|
UINT32 oldSize = model->body(index).size();
|
||||||
|
if (newSize > oldSize) {
|
||||||
|
msg(tr("buildIntelImage: new image size %1h (%2) is bigger than the original %3h (%4)")
|
||||||
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
else if (newSize < oldSize) {
|
||||||
|
msg(tr("buildIntelImage: new image size %1h (%2) is smaller than the original %3h (%4)")
|
||||||
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconstruction successful
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg(tr("buildIntelImage: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
|
||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea)
|
STATUS FfsBuilder::buildRegion(const QModelIndex & index, QByteArray & region)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
UINT8 result;
|
||||||
|
|
||||||
|
// No action required
|
||||||
|
if (model->action(index) == Actions::NoAction) {
|
||||||
|
region = model->header(index).append(model->body(index));
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erase
|
||||||
|
else if (model->action(index) == Actions::Erase) {
|
||||||
|
region = model->header(index).append(model->body(index));
|
||||||
|
if (erase(index, region))
|
||||||
|
msg(tr("buildRegion: erase failed, original item data used"), index);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebuild or replace
|
||||||
|
else if (model->action(index) == Actions::Rebuild ||
|
||||||
|
model->action(index) == Actions::Replace) {
|
||||||
|
if (model->rowCount(index)) {
|
||||||
|
region.clear();
|
||||||
|
// Build children
|
||||||
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
|
QModelIndex currentChild = index.child(i, 0);
|
||||||
|
QByteArray currentData;
|
||||||
|
// Check child type
|
||||||
|
if (model->type(currentChild) == Types::Volume) {
|
||||||
|
result = buildVolume(currentChild, currentData);
|
||||||
|
}
|
||||||
|
else if (model->type(currentChild) == Types::Padding) {
|
||||||
|
result = buildPadding(currentChild, currentData);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg(tr("buildRegion: unexpected child item of type \"%1\" can't be processed, original item data used").arg(itemTypeToQString(model->type(currentChild))), currentChild);
|
||||||
|
result = ERR_SUCCESS;
|
||||||
|
currentData = model->header(currentChild).append(model->body(currentChild));
|
||||||
|
}
|
||||||
|
// Check build result
|
||||||
|
if (result) {
|
||||||
|
msg(tr("buildRegion: building of \"%1\" failed with error \"%2\", original item data used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
|
||||||
|
currentData = model->header(currentChild).append(model->body(currentChild));
|
||||||
|
}
|
||||||
|
// Append current data
|
||||||
|
region.append(currentData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
region = model->body(index);
|
||||||
|
|
||||||
|
// Check size of new region, it must be same as original one
|
||||||
|
UINT32 newSize = region.size();
|
||||||
|
UINT32 oldSize = model->body(index).size();
|
||||||
|
if (newSize > oldSize) {
|
||||||
|
msg(tr("buildRegion: new region size %1h (%2) is bigger than the original %3h (%4)")
|
||||||
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
else if (newSize < oldSize) {
|
||||||
|
msg(tr("buildRegion: new region size %1h (%2) is smaller than the original %3h (%4)")
|
||||||
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build successful
|
||||||
|
region = model->header(index).append(region);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg(tr("buildRegion: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea, bool addHeader)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -137,7 +326,7 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea)
|
|||||||
// Clear the supplied QByteArray
|
// Clear the supplied QByteArray
|
||||||
rawArea.clear();
|
rawArea.clear();
|
||||||
|
|
||||||
// Reconstruct children
|
// Build children
|
||||||
for (int i = 0; i < model->rowCount(index); i++) {
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
QModelIndex currentChild = index.child(i, 0);
|
QModelIndex currentChild = index.child(i, 0);
|
||||||
QByteArray currentData;
|
QByteArray currentData;
|
||||||
@ -162,27 +351,26 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea)
|
|||||||
rawArea.append(currentData);
|
rawArea.append(currentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check size of reconstructed raw area, it must remain the same
|
// Check size of new raw area, it must be same as original one
|
||||||
if (rawArea.size() > model->body(index).size()) {
|
UINT32 newSize = rawArea.size();
|
||||||
msg(tr("buildRawArea: new raw area size %1h (%2) is bigger than the original %3h (%4)")
|
UINT32 oldSize = model->body(index).size();
|
||||||
.hexarg(rawArea.size()).arg(rawArea.size())
|
if (newSize > oldSize) {
|
||||||
.hexarg(model->body(index).size()).arg(model->body(index).size()),
|
msg(tr("buildRawArea: new area size %1h (%2) is bigger than the original %3h (%4)")
|
||||||
index);
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
else if (rawArea.size() < model->body(index).size()) {
|
else if (newSize < oldSize) {
|
||||||
msg(tr("buildRawArea: new raw area size %1h (%2) is smaller than the original %3h (%4)")
|
msg(tr("buildRawArea: new area size %1h (%2) is smaller than the original %3h (%4)")
|
||||||
.hexarg(rawArea.size()).arg(rawArea.size())
|
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
|
||||||
.hexarg(model->body(index).size()).arg(model->body(index).size()),
|
|
||||||
index);
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rawArea = model->body(index);
|
rawArea = model->body(index);
|
||||||
|
|
||||||
// Build successful, append header
|
// Build successful, add header if needed
|
||||||
rawArea = model->header(index).append(rawArea);
|
if (addHeader)
|
||||||
|
rawArea = model->header(index).append(rawArea);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +378,6 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea)
|
|||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsBuilder::buildVolume(const QModelIndex & index, QByteArray & volume)
|
|
||||||
{
|
|
||||||
return ERR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATUS FfsBuilder::buildPadding(const QModelIndex & index, QByteArray & padding)
|
STATUS FfsBuilder::buildPadding(const QModelIndex & index, QByteArray & padding)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
@ -209,7 +392,9 @@ STATUS FfsBuilder::buildPadding(const QModelIndex & index, QByteArray & padding)
|
|||||||
|
|
||||||
// Erase
|
// Erase
|
||||||
else if (model->action(index) == Actions::Erase) {
|
else if (model->action(index) == Actions::Erase) {
|
||||||
padding.fill('\xFF', model->header(index).size() + model->body(index).size());
|
padding = model->header(index).append(model->body(index));
|
||||||
|
if(erase(index, padding))
|
||||||
|
msg(tr("buildPadding: erase failed, original item data used"), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +416,9 @@ STATUS FfsBuilder::buildNonUefiData(const QModelIndex & index, QByteArray & data
|
|||||||
|
|
||||||
// Erase
|
// Erase
|
||||||
else if (model->action(index) == Actions::Erase) {
|
else if (model->action(index) == Actions::Erase) {
|
||||||
data.fill('\xFF', model->header(index).size() + model->body(index).size());
|
data = model->header(index).append(model->body(index));
|
||||||
|
if (erase(index, data))
|
||||||
|
msg(tr("buildNonUefiData: erase failed, original item data used"), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +442,11 @@ STATUS FfsBuilder::buildFreeSpace(const QModelIndex & index, QByteArray & freeSp
|
|||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATUS FfsBuilder::buildVolume(const QModelIndex & index, QByteArray & volume)
|
||||||
|
{
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
STATUS FfsBuilder::buildPadFile(const QModelIndex & index, QByteArray & padFile)
|
STATUS FfsBuilder::buildPadFile(const QModelIndex & index, QByteArray & padFile)
|
||||||
{
|
{
|
||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
@ -270,3 +462,7 @@ STATUS FfsBuilder::buildSection(const QModelIndex & index, QByteArray & section)
|
|||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image)
|
||||||
|
{
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
#include "../common/basetypes.h"
|
#include "../common/basetypes.h"
|
||||||
#include "../common/treemodel.h"
|
#include "../common/treemodel.h"
|
||||||
|
#include "../common/descriptor.h"
|
||||||
#include "../common/ffs.h"
|
#include "../common/ffs.h"
|
||||||
#include "../common/utility.h"
|
#include "../common/utility.h"
|
||||||
|
|
||||||
@ -44,17 +45,19 @@ private:
|
|||||||
|
|
||||||
// UEFI standard structures
|
// UEFI standard structures
|
||||||
STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule);
|
STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule);
|
||||||
STATUS buildImage(const QModelIndex & index, QByteArray & intelImage);
|
STATUS buildIntelImage(const QModelIndex & index, QByteArray & intelImage);
|
||||||
STATUS buildRegion(const QModelIndex & index, QByteArray & region);
|
STATUS buildRegion(const QModelIndex & index, QByteArray & region);
|
||||||
STATUS buildRawArea(const QModelIndex & index, QByteArray & rawArea);
|
STATUS buildRawArea(const QModelIndex & index, QByteArray & rawArea, bool addHeader = true);
|
||||||
STATUS buildVolume(const QModelIndex & index, QByteArray & volume);
|
|
||||||
STATUS buildPadding(const QModelIndex & index, QByteArray & padding);
|
STATUS buildPadding(const QModelIndex & index, QByteArray & padding);
|
||||||
|
STATUS buildVolume(const QModelIndex & index, QByteArray & volume);
|
||||||
STATUS buildNonUefiData(const QModelIndex & index, QByteArray & data);
|
STATUS buildNonUefiData(const QModelIndex & index, QByteArray & data);
|
||||||
STATUS buildFreeSpace(const QModelIndex & index, QByteArray & freeSpace);
|
STATUS buildFreeSpace(const QModelIndex & index, QByteArray & freeSpace);
|
||||||
STATUS buildPadFile(const QModelIndex & index, QByteArray & padFile);
|
STATUS buildPadFile(const QModelIndex & index, QByteArray & padFile);
|
||||||
STATUS buildFile(const QModelIndex & index, QByteArray & file);
|
STATUS buildFile(const QModelIndex & index, QByteArray & file);
|
||||||
STATUS buildSection(const QModelIndex & index, QByteArray & section);
|
STATUS buildSection(const QModelIndex & index, QByteArray & section);
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
STATUS erase(const QModelIndex & index, QByteArray & erased);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -153,7 +153,19 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
QModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, QString(), info, QByteArray(), flashImage, parsingDataToQByteArray(pdata), index);
|
QModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, QString(), info, QByteArray(), flashImage, parsingDataToQByteArray(pdata), index);
|
||||||
|
|
||||||
// Parse the image
|
// Parse the image
|
||||||
return parseRawArea(flashImage, biosIndex);
|
result = parseRawArea(flashImage, biosIndex);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Check if the last VTF is found
|
||||||
|
if (!lastVtf.isValid()) {
|
||||||
|
msg(tr("parseImageFile: not a single Volume Top File is found, physical memory addresses can't be calculated"), biosIndex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return addMemoryAddressesInfo(biosIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelIndex & parent, QModelIndex & index)
|
||||||
@ -397,6 +409,14 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelInd
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the last VTF is found
|
||||||
|
if (!lastVtf.isValid()) {
|
||||||
|
msg(tr("parseIntelImage: not a single Volume Top File is found, physical memory addresses can't be calculated"), index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return addMemoryAddressesInfo(index);
|
||||||
|
}
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,6 +615,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde
|
|||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
pdata.fixed = TRUE;
|
pdata.fixed = TRUE;
|
||||||
|
pdata.offset = offset + headerSize;
|
||||||
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
@ -731,7 +752,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
|
|
||||||
// Calculate volume header size
|
// Calculate volume header size
|
||||||
UINT32 headerSize;
|
UINT32 headerSize;
|
||||||
EFI_GUID extendedHeaderGuid = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
|
EFI_GUID extendedHeaderGuid = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
|
||||||
bool hasExtendedHeader = false;
|
bool hasExtendedHeader = false;
|
||||||
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
||||||
hasExtendedHeader = true;
|
hasExtendedHeader = true;
|
||||||
@ -1216,6 +1237,17 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf
|
|||||||
.hexarg(body.size()).arg(body.size())
|
.hexarg(body.size()).arg(body.size())
|
||||||
.hexarg2(fileHeader->State, 2);
|
.hexarg2(fileHeader->State, 2);
|
||||||
|
|
||||||
|
// Check if the file is a Volume Top File
|
||||||
|
QString text;
|
||||||
|
bool isVtf = false;
|
||||||
|
if (EFI_FFS_VOLUME_TOP_FILE_GUID == header.left(sizeof(EFI_GUID))) {
|
||||||
|
// Mark it as the last VTF
|
||||||
|
// This information will later be used to determine memory addresses of uncompressed image elements
|
||||||
|
// Because the last byte of the last VFT is mapped to 0xFFFFFFFF physical memory address
|
||||||
|
isVtf = true;
|
||||||
|
text = tr("Volume Top File");
|
||||||
|
}
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
pdata.fixed = fileHeader->Attributes & FFS_ATTRIB_FIXED;
|
pdata.fixed = fileHeader->Attributes & FFS_ATTRIB_FIXED;
|
||||||
pdata.offset += parentOffset;
|
pdata.offset += parentOffset;
|
||||||
@ -1224,7 +1256,12 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf
|
|||||||
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(Types::File, fileHeader->Type, name, "", info, header, body, parsingDataToQByteArray(pdata), parent);
|
index = model->addItem(Types::File, fileHeader->Type, name, text, info, header, body, parsingDataToQByteArray(pdata), parent);
|
||||||
|
|
||||||
|
// Overwrite lastVtf, if needed
|
||||||
|
if (isVtf) {
|
||||||
|
lastVtf = index;
|
||||||
|
}
|
||||||
|
|
||||||
// Show messages
|
// Show messages
|
||||||
if (msgUnalignedFile)
|
if (msgUnalignedFile)
|
||||||
@ -1435,9 +1472,9 @@ STATUS FfsParser::parseSectionHeader(const QByteArray & section, const UINT32 pa
|
|||||||
case EFI_SECTION_DXE_DEPEX:
|
case EFI_SECTION_DXE_DEPEX:
|
||||||
case EFI_SECTION_PEI_DEPEX:
|
case EFI_SECTION_PEI_DEPEX:
|
||||||
case EFI_SECTION_SMM_DEPEX:
|
case EFI_SECTION_SMM_DEPEX:
|
||||||
case EFI_SECTION_TE:
|
|
||||||
case EFI_SECTION_PE32:
|
case EFI_SECTION_PE32:
|
||||||
case EFI_SECTION_PIC:
|
case EFI_SECTION_PIC:
|
||||||
|
case EFI_SECTION_TE:
|
||||||
case EFI_SECTION_COMPATIBILITY16:
|
case EFI_SECTION_COMPATIBILITY16:
|
||||||
case EFI_SECTION_USER_INTERFACE:
|
case EFI_SECTION_USER_INTERFACE:
|
||||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
||||||
@ -1732,6 +1769,7 @@ STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const U
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STATUS FfsParser::parseSectionBody(const QModelIndex & index)
|
STATUS FfsParser::parseSectionBody(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
@ -1751,9 +1789,9 @@ STATUS FfsParser::parseSectionBody(const QModelIndex & index)
|
|||||||
case EFI_SECTION_DXE_DEPEX:
|
case EFI_SECTION_DXE_DEPEX:
|
||||||
case EFI_SECTION_PEI_DEPEX:
|
case EFI_SECTION_PEI_DEPEX:
|
||||||
case EFI_SECTION_SMM_DEPEX: return parseDepexSectionBody(index);
|
case EFI_SECTION_SMM_DEPEX: return parseDepexSectionBody(index);
|
||||||
case EFI_SECTION_TE: return ERR_SUCCESS;//return parseTeSectionBody(index);
|
case EFI_SECTION_TE: return parseTeImageSectionBody(index);
|
||||||
case EFI_SECTION_PE32:
|
case EFI_SECTION_PE32:
|
||||||
case EFI_SECTION_PIC: return ERR_SUCCESS;//return parsePeSectionBody(index);
|
case EFI_SECTION_PIC: return parsePeImageSectionBody(index);
|
||||||
case EFI_SECTION_USER_INTERFACE: return parseUiSectionBody(index);
|
case EFI_SECTION_USER_INTERFACE: return parseUiSectionBody(index);
|
||||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return parseRawArea(model->body(index), index);
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return parseRawArea(model->body(index), index);
|
||||||
case EFI_SECTION_RAW: return parseRawSectionBody(index);
|
case EFI_SECTION_RAW: return parseRawSectionBody(index);
|
||||||
@ -2109,37 +2147,29 @@ STATUS FfsParser::parseRawSectionBody(const QModelIndex & index)
|
|||||||
return parseRawArea(model->body(index), index);
|
return parseRawArea(model->body(index), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
STATUS FfsEngine::parsePeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
|
||||||
{
|
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
|
||||||
UINT32 headerSize = sizeOfSectionHeader(sectionHeader);
|
|
||||||
QByteArray header = section.left(headerSize);
|
|
||||||
QByteArray body = section.mid(headerSize);
|
|
||||||
|
|
||||||
// Get standard info
|
STATUS FfsParser::parsePeImageSectionBody(const QModelIndex & index)
|
||||||
QString name = sectionTypeToQString(sectionHeader->Type) + tr(" section");
|
{
|
||||||
QString info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)")
|
// Sanity check
|
||||||
.hexarg2(sectionHeader->Type, 2)
|
if (!index.isValid())
|
||||||
.hexarg(section.size()).arg(section.size())
|
return ERR_INVALID_PARAMETER;
|
||||||
.hexarg(header.size()).arg(header.size())
|
|
||||||
.hexarg(body.size()).arg(body.size());
|
// Get section body
|
||||||
|
QByteArray body = model->body(index);
|
||||||
|
|
||||||
// Get PE info
|
// Get PE info
|
||||||
bool msgInvalidDosSignature = false;
|
QByteArray info;
|
||||||
bool msgInvalidPeSignature = false;
|
|
||||||
bool msgUnknownOptionalHeaderSignature = false;
|
|
||||||
|
|
||||||
const EFI_IMAGE_DOS_HEADER* dosHeader = (const EFI_IMAGE_DOS_HEADER*)body.constData();
|
const EFI_IMAGE_DOS_HEADER* dosHeader = (const EFI_IMAGE_DOS_HEADER*)body.constData();
|
||||||
if (dosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
|
if (dosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
|
||||||
info += tr("\nDOS signature: %1h, invalid").hexarg2(dosHeader->e_magic, 4);
|
info += tr("\nDOS signature: %1h, invalid").hexarg2(dosHeader->e_magic, 4);
|
||||||
msgInvalidDosSignature = true;
|
msg(tr("parsePeImageSectionBody: PE32 image with invalid DOS signature"), index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const EFI_IMAGE_PE_HEADER* peHeader = (EFI_IMAGE_PE_HEADER*)(body.constData() + dosHeader->e_lfanew);
|
const EFI_IMAGE_PE_HEADER* peHeader = (EFI_IMAGE_PE_HEADER*)(body.constData() + dosHeader->e_lfanew);
|
||||||
if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) {
|
if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) {
|
||||||
info += tr("\nPE signature: %1h, invalid").hexarg2(peHeader->Signature, 8);
|
info += tr("\nPE signature: %1h, invalid").hexarg2(peHeader->Signature, 8);
|
||||||
msgInvalidPeSignature = true;
|
msg(tr("parsePeImageSectionBody: PE32 image with invalid PE signature"), index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const EFI_IMAGE_FILE_HEADER* imageFileHeader = (const EFI_IMAGE_FILE_HEADER*)(peHeader + 1);
|
const EFI_IMAGE_FILE_HEADER* imageFileHeader = (const EFI_IMAGE_FILE_HEADER*)(peHeader + 1);
|
||||||
@ -2153,82 +2183,53 @@ STATUS FfsEngine::parsePeSectionHeader(const QByteArray & section, const UINT32
|
|||||||
EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION optionalHeader;
|
EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION optionalHeader;
|
||||||
optionalHeader.H32 = (const EFI_IMAGE_OPTIONAL_HEADER32*)(imageFileHeader + 1);
|
optionalHeader.H32 = (const EFI_IMAGE_OPTIONAL_HEADER32*)(imageFileHeader + 1);
|
||||||
if (optionalHeader.H32->Magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) {
|
if (optionalHeader.H32->Magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) {
|
||||||
info += tr("\nOptional header signature: %1h\nSubsystem: %2h\nRelativeEntryPoint: %3h\nBaseOfCode: %4h\nImageBase: %5h\nEntryPoint: %6h")
|
info += tr("\nOptional header signature: %1h\nSubsystem: %2h\nAddress of entryPoint: %3h\nBase of code: %4h\nImage base: %5h")
|
||||||
.hexarg2(optionalHeader.H32->Magic, 4)
|
.hexarg2(optionalHeader.H32->Magic, 4)
|
||||||
.hexarg2(optionalHeader.H32->Subsystem, 4)
|
.hexarg2(optionalHeader.H32->Subsystem, 4)
|
||||||
.hexarg(optionalHeader.H32->AddressOfEntryPoint)
|
.hexarg(optionalHeader.H32->AddressOfEntryPoint)
|
||||||
.hexarg(optionalHeader.H32->BaseOfCode)
|
.hexarg(optionalHeader.H32->BaseOfCode)
|
||||||
.hexarg(optionalHeader.H32->ImageBase)
|
.hexarg(optionalHeader.H32->ImageBase);
|
||||||
.hexarg(optionalHeader.H32->ImageBase + optionalHeader.H32->AddressOfEntryPoint);
|
|
||||||
}
|
}
|
||||||
else if (optionalHeader.H32->Magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) {
|
else if (optionalHeader.H32->Magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) {
|
||||||
info += tr("\nOptional header signature: %1h\nSubsystem: %2h\nRelativeEntryPoint: %3h\nBaseOfCode: %4h\nImageBase: %5h\nEntryPoint: %6h")
|
info += tr("\nOptional header signature: %1h\nSubsystem: %2h\nAddress of entryPoint: %3h\nBase of code: %4h\nImage base: %5h")
|
||||||
.hexarg2(optionalHeader.H64->Magic, 4)
|
.hexarg2(optionalHeader.H64->Magic, 4)
|
||||||
.hexarg2(optionalHeader.H64->Subsystem, 4)
|
.hexarg2(optionalHeader.H64->Subsystem, 4)
|
||||||
.hexarg(optionalHeader.H64->AddressOfEntryPoint)
|
.hexarg(optionalHeader.H64->AddressOfEntryPoint)
|
||||||
.hexarg(optionalHeader.H64->BaseOfCode)
|
.hexarg(optionalHeader.H64->BaseOfCode)
|
||||||
.hexarg(optionalHeader.H64->ImageBase)
|
.hexarg(optionalHeader.H64->ImageBase);
|
||||||
.hexarg(optionalHeader.H64->ImageBase + optionalHeader.H64->AddressOfEntryPoint);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
info += tr("\nOptional header signature: %1h, unknown").hexarg2(optionalHeader.H64->Magic, 4);
|
info += tr("\nOptional header signature: %1h, unknown").hexarg2(optionalHeader.H64->Magic, 4);
|
||||||
msgUnknownOptionalHeaderSignature = true;
|
msg(tr("parsePeImageSectionBody: PE32 image with invalid optional PE header signature"), index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add tree item
|
// Add PE info
|
||||||
index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
model->addInfo(index, info);
|
||||||
|
|
||||||
// Show messages
|
|
||||||
if (msgInvalidDosSignature) {
|
|
||||||
msg("parseSection: PE32 image with invalid DOS signature", index);
|
|
||||||
}
|
|
||||||
if (msgInvalidPeSignature) {
|
|
||||||
msg("parseSection: PE32 image with invalid PE signature", index);
|
|
||||||
}
|
|
||||||
if (msgUnknownOptionalHeaderSignature) {
|
|
||||||
msg("parseSection: PE32 image with unknown optional header signature", index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special case of PEI Core
|
|
||||||
QModelIndex core = model->findParentOfType(index, Types::File);
|
|
||||||
if (core.isValid() && model->subtype(core) == EFI_FV_FILETYPE_PEI_CORE
|
|
||||||
&& oldPeiCoreEntryPoint == 0) {
|
|
||||||
result = getEntryPoint(model->body(index), oldPeiCoreEntryPoint);
|
|
||||||
if (result)
|
|
||||||
msg(tr("parseSection: can't get original PEI core entry point"), index);
|
|
||||||
}
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
STATUS FfsEngine::parseTeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseTeImageSectionBody(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
// Sanity check
|
||||||
UINT32 headerSize = sizeOfSectionHeader(sectionHeader);
|
if (!index.isValid())
|
||||||
QByteArray header = section.left(headerSize);
|
return ERR_INVALID_PARAMETER;
|
||||||
QByteArray body = section.mid(headerSize);
|
|
||||||
|
|
||||||
// Get standard info
|
// Get section body
|
||||||
QString name = sectionTypeToQString(sectionHeader->Type) + tr(" section");
|
QByteArray body = model->body(index);
|
||||||
QString info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)")
|
|
||||||
.hexarg2(sectionHeader->Type, 2)
|
|
||||||
.hexarg(section.size()).arg(section.size())
|
|
||||||
.hexarg(header.size()).arg(header.size())
|
|
||||||
.hexarg(body.size()).arg(body.size());
|
|
||||||
|
|
||||||
// Get TE info
|
// Get TE info
|
||||||
bool msgInvalidSignature = false;
|
QByteArray info;
|
||||||
const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)body.constData();
|
const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)body.constData();
|
||||||
UINT32 teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
|
|
||||||
if (teHeader->Signature != EFI_IMAGE_TE_SIGNATURE) {
|
if (teHeader->Signature != EFI_IMAGE_TE_SIGNATURE) {
|
||||||
info += tr("\nSignature: %1h, invalid").hexarg2(teHeader->Signature, 4);
|
info += tr("\nSignature: %1h, invalid").hexarg2(teHeader->Signature, 4);
|
||||||
msgInvalidSignature = true;
|
msg(tr("parseTeImageSectionBody: TE image with invalid TE signature"), index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
info += tr("\nSignature: %1h\nMachine type: %2\nNumber of sections: %3\nSubsystem: %4h\nStrippedSize: %5h (%6)\nBaseOfCode: %7h\nRelativeEntryPoint: %8h\nImageBase: %9h\nEntryPoint: %10h")
|
info += tr("\nSignature: %1h\nMachine type: %2\nNumber of sections: %3\nSubsystem: %4h\nStripped size: %5h (%6)\nBase of code: %7h\nAddress of entry point: %8h\nImage base: %9h\nAdjusted image base: %10h")
|
||||||
.hexarg2(teHeader->Signature, 4)
|
.hexarg2(teHeader->Signature, 4)
|
||||||
.arg(machineTypeToQString(teHeader->Machine))
|
.arg(machineTypeToQString(teHeader->Machine))
|
||||||
.arg(teHeader->NumberOfSections)
|
.arg(teHeader->NumberOfSections)
|
||||||
@ -2237,51 +2238,95 @@ STATUS FfsEngine::parseTeSectionHeader(const QByteArray & section, const UINT32
|
|||||||
.hexarg(teHeader->BaseOfCode)
|
.hexarg(teHeader->BaseOfCode)
|
||||||
.hexarg(teHeader->AddressOfEntryPoint)
|
.hexarg(teHeader->AddressOfEntryPoint)
|
||||||
.hexarg(teHeader->ImageBase)
|
.hexarg(teHeader->ImageBase)
|
||||||
.hexarg(teHeader->ImageBase + teHeader->AddressOfEntryPoint - teFixup);
|
.hexarg(teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER));
|
||||||
}
|
|
||||||
// Add tree item
|
|
||||||
index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
|
||||||
|
|
||||||
// Show messages
|
|
||||||
if (msgInvalidSignature) {
|
|
||||||
msg("parseSection: TE image with invalid TE signature", index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case of PEI Core
|
// Get data from parsing data
|
||||||
QModelIndex core = model->findParentOfType(index, Types::File);
|
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
||||||
if (core.isValid() && model->subtype(core) == EFI_FV_FILETYPE_PEI_CORE
|
pdata.section.teImage.imageBase = teHeader->ImageBase;
|
||||||
&& oldPeiCoreEntryPoint == 0) {
|
pdata.section.teImage.adjustedImageBase = teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
|
||||||
result = getEntryPoint(model->body(index), oldPeiCoreEntryPoint);
|
|
||||||
if (result)
|
// Update parsing data
|
||||||
msg(tr("parseSection: can't get original PEI core entry point"), index);
|
model->setParsingData(index, parsingDataToQByteArray(pdata));
|
||||||
}
|
|
||||||
|
// Add TE info
|
||||||
|
model->addInfo(index, info);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsEngine::parseFirmwareVolumeImageSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
|
||||||
|
STATUS FfsParser::addMemoryAddressesInfo(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
// Sanity check
|
||||||
QByteArray header = section.left(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
|
if (!index.isValid() || !lastVtf.isValid())
|
||||||
QByteArray body = section.mid(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get info
|
// Get parsing data for the last VTF
|
||||||
QString name = sectionTypeToQString(sectionHeader->Type) + tr(" section");
|
PARSING_DATA pdata = parsingDataFromQByteArray(lastVtf);
|
||||||
QString info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)")
|
if (!pdata.isOnFlash) {
|
||||||
.hexarg2(sectionHeader->Type, 2)
|
msg(tr("addPhysicalAddressInfo: the last VTF appears inside compressed item, the image may be damaged"), lastVtf);
|
||||||
.hexarg(section.size()).arg(section.size())
|
return ERR_SUCCESS;
|
||||||
.hexarg(header.size()).arg(header.size())
|
|
||||||
.hexarg(body.size()).arg(body.size());
|
|
||||||
|
|
||||||
// Add tree item
|
|
||||||
index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
|
||||||
|
|
||||||
// Parse section body as BIOS space
|
|
||||||
result = parseBios(body, index);
|
|
||||||
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) {
|
|
||||||
msg(tr("parseSection: parsing firmware volume image section as BIOS failed with error \"%1\"").arg(errorMessage(result)), index);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
return ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
// Calculate address difference
|
||||||
|
const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + (pdata.file.hasTail ? sizeof(UINT16) : 0);
|
||||||
|
const UINT32 diff = 0xFFFFFFFF - pdata.offset - vtfSize + 1;
|
||||||
|
|
||||||
|
// Apply address information to index and all it's child items
|
||||||
|
return addMemoryAddressesRecursive(index, diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS FfsParser::addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff)
|
||||||
|
{
|
||||||
|
// Sanity check
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
// Get parsing data for the current item
|
||||||
|
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
||||||
|
|
||||||
|
// Set address value for non-compressed data
|
||||||
|
if (pdata.isOnFlash) {
|
||||||
|
// Check address sanity
|
||||||
|
if ((const UINT64)diff + pdata.offset <= 0xFFFFFFFF) {
|
||||||
|
// Update info
|
||||||
|
pdata.address = diff + pdata.offset;
|
||||||
|
UINT32 headerSize = model->header(index).size();
|
||||||
|
if (headerSize) {
|
||||||
|
model->addInfo(index, tr("\nHeader memory address: %1h").hexarg2(pdata.address, 8));
|
||||||
|
model->addInfo(index, tr("\nData memory address: %1h").hexarg2(pdata.address + headerSize, 8));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
model->addInfo(index, tr("\nMemory address: %1h").hexarg2(pdata.address, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case of uncompressed TE image sections
|
||||||
|
if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_TE && pdata.isOnFlash) {
|
||||||
|
// Check data memory address to be equal to either ImageBase or AdjustedImageBase
|
||||||
|
if (pdata.section.teImage.imageBase == pdata.address + headerSize) {
|
||||||
|
pdata.section.teImage.revision = 1;
|
||||||
|
model->addInfo(index, tr("\nTE image format revision: %1").arg(pdata.section.teImage.revision));
|
||||||
|
}
|
||||||
|
else if (pdata.section.teImage.adjustedImageBase == pdata.address + headerSize) {
|
||||||
|
pdata.section.teImage.revision = 2;
|
||||||
|
model->addInfo(index, tr("\nTE image format revision: %1").arg(pdata.section.teImage.revision));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg(tr("addMemoryAddressesRecursive: image base is nether original nor adjusted, the image is either damaged or a part of backup PEI volume"), index);
|
||||||
|
pdata.section.teImage.revision = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set modified parsing data
|
||||||
|
model->setParsingData(index, parsingDataToQByteArray(pdata));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process child items
|
||||||
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
|
addMemoryAddressesRecursive(index.child(i, 0), diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
@ -53,13 +53,10 @@ public:
|
|||||||
STATUS parseSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
STATUS parseSectionBody(const QModelIndex & index);
|
STATUS parseSectionBody(const QModelIndex & index);
|
||||||
|
|
||||||
/*// Search routines TODO: move to another class
|
|
||||||
// Extract routine TODO: move to another class
|
|
||||||
STATUS extract(const QModelIndex & index, QString & name, QByteArray & extracted, const UINT8 mode);*/
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TreeModel *model;
|
TreeModel *model;
|
||||||
QVector<QPair<QString, QModelIndex> > messagesVector;
|
QVector<QPair<QString, QModelIndex> > messagesVector;
|
||||||
|
QModelIndex lastVtf;
|
||||||
|
|
||||||
STATUS parseIntelImage(const QByteArray & intelImage, const QModelIndex & parent, QModelIndex & root);
|
STATUS parseIntelImage(const QByteArray & intelImage, const QModelIndex & parent, QModelIndex & root);
|
||||||
STATUS parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
@ -83,6 +80,8 @@ private:
|
|||||||
STATUS parseDepexSectionBody(const QModelIndex & index);
|
STATUS parseDepexSectionBody(const QModelIndex & index);
|
||||||
STATUS parseUiSectionBody(const QModelIndex & index);
|
STATUS parseUiSectionBody(const QModelIndex & index);
|
||||||
STATUS parseRawSectionBody(const QModelIndex & index);
|
STATUS parseRawSectionBody(const QModelIndex & index);
|
||||||
|
STATUS parsePeImageSectionBody(const QModelIndex & index);
|
||||||
|
STATUS parseTeImageSectionBody(const QModelIndex & index);
|
||||||
|
|
||||||
UINT8 getPaddingType(const QByteArray & padding);
|
UINT8 getPaddingType(const QByteArray & padding);
|
||||||
STATUS parseAprioriRawSection(const QByteArray & body, QString & parsed);
|
STATUS parseAprioriRawSection(const QByteArray & body, QString & parsed);
|
||||||
@ -91,6 +90,9 @@ private:
|
|||||||
UINT32 getFileSize(const QByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
|
UINT32 getFileSize(const QByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
|
||||||
UINT32 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
|
UINT32 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
|
||||||
|
|
||||||
|
STATUS addMemoryAddressesInfo(const QModelIndex & index);
|
||||||
|
STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff);
|
||||||
|
|
||||||
// Internal operations
|
// Internal operations
|
||||||
BOOLEAN hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
BOOLEAN hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
||||||
|
|
||||||
|
@ -61,11 +61,18 @@ typedef struct _FREEFORM_GUIDED_SECTION_PARSING_DATA {
|
|||||||
EFI_GUID guid;
|
EFI_GUID guid;
|
||||||
} FREEFORM_GUIDED_SECTION_PARSING_DATA;
|
} FREEFORM_GUIDED_SECTION_PARSING_DATA;
|
||||||
|
|
||||||
|
typedef struct _TE_IMAGE_SECTION_PARSING_DATA {
|
||||||
|
UINT32 imageBase;
|
||||||
|
UINT32 adjustedImageBase;
|
||||||
|
UINT8 revision;
|
||||||
|
} TE_IMAGE_SECTION_PARSING_DATA;
|
||||||
|
|
||||||
typedef struct _SECTION_PARSING_DATA {
|
typedef struct _SECTION_PARSING_DATA {
|
||||||
union {
|
union {
|
||||||
COMPRESSED_SECTION_PARSING_DATA compressed;
|
COMPRESSED_SECTION_PARSING_DATA compressed;
|
||||||
GUIDED_SECTION_PARSING_DATA guidDefined;
|
GUIDED_SECTION_PARSING_DATA guidDefined;
|
||||||
FREEFORM_GUIDED_SECTION_PARSING_DATA freeformSubtypeGuid;
|
FREEFORM_GUIDED_SECTION_PARSING_DATA freeformSubtypeGuid;
|
||||||
|
TE_IMAGE_SECTION_PARSING_DATA teImage;
|
||||||
};
|
};
|
||||||
} SECTION_PARSING_DATA;
|
} SECTION_PARSING_DATA;
|
||||||
|
|
||||||
@ -75,7 +82,7 @@ typedef struct _PARSING_DATA {
|
|||||||
UINT8 emptyByte;
|
UINT8 emptyByte;
|
||||||
UINT8 ffsVersion;
|
UINT8 ffsVersion;
|
||||||
UINT32 offset;
|
UINT32 offset;
|
||||||
UINT64 address;
|
UINT32 address;
|
||||||
union {
|
union {
|
||||||
//CAPSULE_PARSING_DATA capsule;
|
//CAPSULE_PARSING_DATA capsule;
|
||||||
//IMAGE_PARSING_DATA image;
|
//IMAGE_PARSING_DATA image;
|
||||||
|
Loading…
Reference in New Issue
Block a user