UT NE A25

- support for Phoenix SCT FlashMap
- support for Apple Gaid stores
- UI for EVSA and FlashMap store and entries
- small fixes
This commit is contained in:
Nikolaj Schlej 2016-04-13 01:35:18 +02:00
parent d6909fe9b6
commit 1100cead24
7 changed files with 261 additions and 78 deletions

View File

@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr("0.30.0_alpha24"))
version(tr("0.30.0_alpha25"))
{
clipboard = QApplication::clipboard();
@ -172,8 +172,10 @@ void UEFITool::populateUi(const QModelIndex &current)
ui->menuVolumeActions->setEnabled(type == Types::Volume);
ui->menuFileActions->setEnabled(type == Types::File);
ui->menuSectionActions->setEnabled(type == Types::Section);
ui->menuVariableActions->setEnabled(type == Types::NvramVariableNvar || type == Types::NvramVariableVss || type == Types::NvramVariableFsys);
ui->menuStoreActions->setEnabled(type == Types::NvramStoreVss || type == Types::NvramStoreFdc || type == Types::NvramStoreFsys || type == Types::NvramStoreEvsa || type == Types::NvramFtwBlock);
ui->menuVariableActions->setEnabled(type == Types::NvramVariableNvar || type == Types::NvramVariableVss || type == Types::NvramEntryFsys
|| type == Types::NvramEntryEvsa || type == Types::NvramEntryFlashMap);
ui->menuStoreActions->setEnabled(type == Types::NvramStoreVss || type == Types::NvramStoreFdc || type == Types::NvramStoreFsys
|| type == Types::NvramStoreEvsa || type == Types::NvramStoreFtw || type == Types::NvramStoreFlashMap);
// Enable actions
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
@ -537,12 +539,25 @@ void UEFITool::extract(const UINT8 mode)
path = QFileDialog::getSaveFileName(this, tr("Save section to file"), name + ".sct", "Section files (*.sct *.bin);;All files (*)");
break;
case Types::NvramVariableNvar:
path = QFileDialog::getSaveFileName(this, tr("Save NVAR variable to file"), name + ".nvar", "NVAR variable files (*.nvar *.bin);;All files (*)");
break;
case Types::NvramVariableVss:
path = QFileDialog::getSaveFileName(this, tr("Save variable to file"), name + ".var", "Variable files (*.var *.bin);;All files (*)");
path = QFileDialog::getSaveFileName(this, tr("Save VSS variable to file"), name + ".var", "VSS variable files (*.var *.bin);;All files (*)");
break;
case Types::NvramEntryFsys:
path = QFileDialog::getSaveFileName(this, tr("Save Fsys entry to file"), name + ".fse", "Fsys entry files (*.fse *.bin);;All files (*)");
break;
case Types::NvramEntryEvsa:
path = QFileDialog::getSaveFileName(this, tr("Save EVSA entry to file"), name + ".evse", "EVSA entry files (*.evse *.bin);;All files (*)");
break;
case Types::NvramEntryFlashMap:
path = QFileDialog::getSaveFileName(this, tr("Save FlashMap entry to file"), name + ".fme", "FlashMap entry files (*.fme *.bin);;All files (*)");
break;
case Types::NvramStoreVss:
path = QFileDialog::getSaveFileName(this, tr("Save VSS store to file"), name + ".vss", "VSS store files (*.vss *.bin);;All files (*)");
break;
case Types::NvramStoreFdc:
path = QFileDialog::getSaveFileName(this, tr("Save variable store to file"), name + ".vss", "Variable store files (*.vss *.bin);;All files (*)");
path = QFileDialog::getSaveFileName(this, tr("Save FDC store to file"), name + ".fdc", "FDC store files (*.fdc *.bin);;All files (*)");
break;
case Types::NvramStoreFsys:
path = QFileDialog::getSaveFileName(this, tr("Save Fsys store to file"), name + ".fsys", "Fsys store files (*.fsys *.bin);;All files (*)");
@ -550,8 +565,11 @@ void UEFITool::extract(const UINT8 mode)
case Types::NvramStoreEvsa:
path = QFileDialog::getSaveFileName(this, tr("Save EVSA store to file"), name + ".evsa", "EVSA store files (*.evsa *.bin);;All files (*)");
break;
case Types::NvramFtwBlock:
path = QFileDialog::getSaveFileName(this, tr("Save FTW block to file"), name + ".ftw", "FTW block files (*.ftw *.bin);;All files (*)");
case Types::NvramStoreFtw:
path = QFileDialog::getSaveFileName(this, tr("Save FTW store to file"), name + ".ftw", "FTW store files (*.ftw *.bin);;All files (*)");
break;
case Types::NvramStoreFlashMap:
path = QFileDialog::getSaveFileName(this, tr("Save FlashMap store to file"), name + ".fmap", "FlashMap store files (*.fmap *.bin);;All files (*)");
break;
default:
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
@ -587,11 +605,12 @@ void UEFITool::extract(const UINT8 mode)
break;
case Types::NvramVariableNvar:
case Types::NvramVariableVss:
case Types::NvramEntryEvsa:
path = QFileDialog::getSaveFileName(this, tr("Save variable body to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
break;
case Types::NvramStoreVss:
case Types::NvramStoreFdc:
path = QFileDialog::getSaveFileName(this, tr("Save variable store body to file"), name + ".vsb", "Variable store body files (*.vsb *.bin);;All files (*)");
path = QFileDialog::getSaveFileName(this, tr("Save VSS variable store body to file"), name + ".vsb", "VSS variable store body files (*.vsb *.bin);;All files (*)");
break;
case Types::NvramStoreFsys:
path = QFileDialog::getSaveFileName(this, tr("Save Fsys store body to file"), name + ".fsb", "Fsys store body files (*.fsb *.bin);;All files (*)");
@ -599,8 +618,11 @@ void UEFITool::extract(const UINT8 mode)
case Types::NvramStoreEvsa:
path = QFileDialog::getSaveFileName(this, tr("Save EVSA store body to file"), name + ".esb", "EVSA store body files (*.esb *.bin);;All files (*)");
break;
case Types::NvramFtwBlock:
path = QFileDialog::getSaveFileName(this, tr("Save FTW block body to file"), name + ".ftb", "FTW block body files (*.ftb *.bin);;All files (*)");
case Types::NvramStoreFtw:
path = QFileDialog::getSaveFileName(this, tr("Save FTW store body to file"), name + ".ftb", "FTW store body files (*.ftb *.bin);;All files (*)");
break;
case Types::NvramStoreFlashMap:
path = QFileDialog::getSaveFileName(this, tr("Save FlashMap store body to file"), name + ".fmb", "FlashMap store body files (*.fmb *.bin);;All files (*)");
break;
default:
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
@ -962,14 +984,17 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
break;
case Types::NvramVariableNvar:
case Types::NvramVariableVss:
case Types::NvramVariableFsys:
case Types::NvramEntryFsys:
case Types::NvramEntryEvsa:
case Types::NvramEntryFlashMap:
ui->menuVariableActions->exec(event->globalPos());
break;
case Types::NvramStoreVss:
case Types::NvramStoreFdc:
case Types::NvramStoreFsys:
case Types::NvramStoreEvsa:
case Types::NvramFtwBlock:
case Types::NvramStoreFtw:
case Types::NvramStoreFlashMap:
ui->menuStoreActions->exec(event->globalPos());
break;
}

View File

@ -59,27 +59,18 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
case Types::NvramVariableNvar:
case Types::NvramVariableVss:
case Types::File: {
name = itemText.isEmpty() ? itemName : itemText.replace(' ', '_');
name = itemText.isEmpty() ? itemName : itemText.replace(' ', '_').replace('-', '_');
} break;
case Types::Section: {
// Get parent file name
QModelIndex fileIndex = model->findParentOfType(index, Types::File);
QString fileText = model->text(fileIndex);
name = fileText.isEmpty() ? model->name(fileIndex) : fileText.replace(' ', '_');
name = fileText.isEmpty() ? model->name(fileIndex) : fileText.replace(' ', '_').replace('-', '_');
// Append section subtype name
name += QChar('_') + itemName.replace(' ', '_');
} break;
case Types::Capsule:
case Types::Image:
case Types::Region:
case Types::Padding:
case Types::NvramStoreVss:
case Types::NvramStoreFdc:
case Types::NvramStoreFsys:
case Types::NvramStoreEvsa:
case Types::NvramFtwBlock:
default:
name = itemName.replace(' ', '_').replace('/', '_');
name = itemName.replace(' ', '_').replace('/', '_').replace('-', '_');
}
// Get extracted data

View File

@ -3366,7 +3366,10 @@ STATUS FfsParser::parseStoreArea(const QByteArray & data, const QModelIndex & in
case Types::NvramStoreEvsa:
parseEvsaStoreBody(current);
break;
case Types::NvramFtwBlock:
case Types::NvramStoreFlashMap:
parseFlashMapBody(current);
break;
case Types::NvramStoreFtw:
case Types::Padding:
// No parsing required
break;
@ -3410,7 +3413,7 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da
// All checks passed, store found
break;
}
else if (*currentPos == NVRAM_APPLE_FSYS_STORE_SIGNATURE) { //Fsys signature found
else if (*currentPos == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_GAID_STORE_SIGNATURE) { //Fsys or Gaid signature found
const APPLE_FSYS_STORE_HEADER* fsysHeader = (const APPLE_FSYS_STORE_HEADER*)currentPos;
if (fsysHeader->Size == 0 || fsysHeader->Size == 0xFFFF) {
msg(QObject::tr("findNextStore: Fsys store candidate at offset %1h skipped, has invalid size %2h").hexarg(parentOffset + offset).hexarg2(fsysHeader->Size, 4), index);
@ -3435,8 +3438,9 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da
offset -= 4;
break;
}
else if (*currentPos == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1) { //Possible FTW block signature found
if (QByteArray(data.constData() + offset, sizeof(EFI_GUID)) != NVRAM_MAIN_STORE_VOLUME_GUID) // Check the whole signature
else if (*currentPos == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *currentPos == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1) { //Possible FTW block signature found
QByteArray guid = QByteArray(data.constData() + offset, sizeof(EFI_GUID));
if (guid != NVRAM_MAIN_STORE_VOLUME_GUID && guid != EDKII_WORKING_BLOCK_SIGNATURE_GUID) // Check the whole signature
continue;
// Detect header variant based on WriteQueueSize
@ -3460,6 +3464,14 @@ STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & da
// All checks passed, store found
break;
}
else if (*currentPos == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1) {// Phoenix SCT flash map
QByteArray signature = QByteArray(data.constData() + offset, NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH);
if (signature != NVRAM_PHOENIX_FLASH_MAP_SIGNATURE) // Check the whole signature
continue;
// All checks passed, store found
break;
}
}
// No more stores found
if (offset >= dataSize - sizeof(UINT32))
@ -3481,7 +3493,7 @@ STATUS FfsParser::getStoreSize(const QByteArray & data, const UINT32 storeOffset
const FDC_VOLUME_HEADER* fdcHeader = (const FDC_VOLUME_HEADER*)signature;
storeSize = fdcHeader->Size;
}
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE) {
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *signature == NVRAM_APPLE_GAID_STORE_SIGNATURE) {
const APPLE_FSYS_STORE_HEADER* fsysHeader = (const APPLE_FSYS_STORE_HEADER*)signature;
storeSize = fsysHeader->Size;
}
@ -3489,7 +3501,7 @@ STATUS FfsParser::getStoreSize(const QByteArray & data, const UINT32 storeOffset
const EVSA_STORE_ENTRY* evsaHeader = (const EVSA_STORE_ENTRY*)signature;
storeSize = evsaHeader->StoreSize;
}
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1) {
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *signature == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1) {
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* ftwHeader = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)signature;
if (ftwHeader->WriteQueueSize % 0x10 == 0x04) { // Header with 32 bit WriteQueueSize
storeSize = sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32) + ftwHeader->WriteQueueSize;
@ -3499,6 +3511,10 @@ STATUS FfsParser::getStoreSize(const QByteArray & data, const UINT32 storeOffset
storeSize = sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64) + ftw64Header->WriteQueueSize;
}
}
else if (*signature == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1) { // Phoenix SCT flash map
const PHOENIX_FLASH_MAP_HEADER* flashMapHeader = (const PHOENIX_FLASH_MAP_HEADER*)signature;
storeSize = sizeof(PHOENIX_FLASH_MAP_HEADER) + sizeof(PHOENIX_FLASH_MAP_ENTRY) * flashMapHeader->NumEntries;
}
return ERR_SUCCESS;
}
@ -3516,7 +3532,7 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// VSS variable stores
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
// The volume must begin with a store to be valid, but after the first one, there can be many variants
// Check dataSize
if (dataSize < sizeof(VSS_VARIABLE_STORE_HEADER)) {
msg(QObject::tr("parseStoreHeader: volume body is too small even for VSS store header"), parent);
return ERR_SUCCESS;
@ -3528,8 +3544,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// Check store size
if (dataSize < vssStoreHeader->Size) {
msg(QObject::tr("parseStoreHeader: VSS store size %1h (%2) is greater than volume body size %3h (%4)")
.hexarg2(vssStoreHeader->Size, 8).arg(vssStoreHeader->Size)
.hexarg2(dataSize, 8).arg(dataSize), parent);
.hexarg(vssStoreHeader->Size).arg(vssStoreHeader->Size)
.hexarg(dataSize).arg(dataSize), parent);
return ERR_SUCCESS;
}
@ -3541,18 +3557,15 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
QByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), vssStoreHeader->Size - sizeof(VSS_VARIABLE_STORE_HEADER));
// Add info
QString name = QObject::tr("VSS store");
QString info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nFormat: %8h\nState: %9h")
QString name = (*signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) ? QObject::tr("SVS store") : QObject::tr("VSS store");
QString info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nFormat: %8h\nState: %9h\nUnknown: %10h")
.hexarg2(vssStoreHeader->Signature, 8)
.hexarg(vssStoreHeader->Size).arg(vssStoreHeader->Size)
.hexarg(header.size()).arg(header.size())
.hexarg(body.size()).arg(body.size())
.hexarg2(vssStoreHeader->Format, 2)
.hexarg2(vssStoreHeader->State, 2);
// Add unknown field for $SVS stores
if (*signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
info += QObject::tr("\nUnknown: %1h").hexarg2(vssStoreHeader->Unknown, 4);
.hexarg2(vssStoreHeader->State, 2)
.hexarg2(vssStoreHeader->Unknown, 4);
// Add correct offset
pdata.offset = parentOffset;
@ -3561,7 +3574,7 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
index = model->addItem(Types::NvramStoreVss, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
}
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
// The volume must begin with a store to be valid, but after the first one, there can be many variants
// Check dataSize
if (dataSize < sizeof(FDC_VOLUME_HEADER)) {
msg(QObject::tr("parseStoreHeader: volume body is too small even for FDC store header"), parent);
return ERR_SUCCESS;
@ -3573,8 +3586,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// Check store size
if (dataSize < fdcStoreHeader->Size) {
msg(QObject::tr("parseStoreHeader: FDC store size %1h (%2) is greater than volume body size %3h (%4)")
.hexarg2(fdcStoreHeader->Size, 8).arg(fdcStoreHeader->Size)
.hexarg2(dataSize, 8).arg(dataSize), parent);
.hexarg(fdcStoreHeader->Size).arg(fdcStoreHeader->Size)
.hexarg(dataSize).arg(dataSize), parent);
return ERR_SUCCESS;
}
@ -3628,8 +3641,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// Add tree item
index = model->addItem(Types::NvramStoreFdc, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
}
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE) {
// The volume must begin with a store to be valid, but after the first one, there can be many variants
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *signature == NVRAM_APPLE_GAID_STORE_SIGNATURE) {
// Check dataSize
if (dataSize < sizeof(APPLE_FSYS_STORE_HEADER)) {
msg(QObject::tr("parseStoreHeader: volume body is too small even for Fsys store header"), parent);
return ERR_SUCCESS;
@ -3641,8 +3654,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// Check store size
if (dataSize < fsysStoreHeader->Size) {
msg(QObject::tr("parseStoreHeader: Fsys store size %1h (%2) is greater than volume body size %3h (%4)")
.hexarg2(fsysStoreHeader->Size, 4).arg(fsysStoreHeader->Size)
.hexarg2(dataSize, 8).arg(dataSize), parent);
.hexarg(fsysStoreHeader->Size).arg(fsysStoreHeader->Size)
.hexarg(dataSize).arg(dataSize), parent);
return ERR_SUCCESS;
}
@ -3658,7 +3671,7 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
UINT32 calculatedCrc = calculatedCrc = crc32(0, (const UINT8*)store.constData(), (const UINT32)store.size() - sizeof(UINT32));
// Add info
QString name = QObject::tr("Fsys store");
QString name = (*signature == NVRAM_APPLE_GAID_STORE_SIGNATURE) ? QObject::tr("Gaid store") : QObject::tr("Fsys store");
QString info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nUnknown: %9 %10 %11 %12 %13\nCRC32: %14")
.hexarg2(fsysStoreHeader->Signature, 8)
.hexarg(fsysStoreHeader->Size).arg(fsysStoreHeader->Size)
@ -3678,7 +3691,7 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
index = model->addItem(Types::NvramStoreFsys, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
}
else if (*(signature + 1) == NVRAM_EVSA_STORE_SIGNATURE) {
// The volume must begin with a store to be valid, but after the first one, there can be many variants
// Check dataSize
if (dataSize < sizeof(EVSA_STORE_ENTRY)) {
msg(QObject::tr("parseStoreHeader: volume body is too small even for EVSA store header"), parent);
return ERR_SUCCESS;
@ -3690,8 +3703,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// Check store size
if (dataSize < evsaStoreHeader->StoreSize) {
msg(QObject::tr("parseStoreHeader: EVSA store size %1h (%2) is greater than volume body size %3h (%4)")
.hexarg2(evsaStoreHeader->StoreSize, 4).arg(evsaStoreHeader->StoreSize)
.hexarg2(dataSize, 8).arg(dataSize), parent);
.hexarg(evsaStoreHeader->StoreSize).arg(evsaStoreHeader->StoreSize)
.hexarg(dataSize).arg(dataSize), parent);
return ERR_SUCCESS;
}
@ -3724,8 +3737,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
// Add tree item
index = model->addItem(Types::NvramStoreEvsa, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
}
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1) {
// The volume must begin with a store to be valid, but after the first one, there can be many variants
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *signature == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1) {
// Check dataSize
if (dataSize < sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64)) {
msg(QObject::tr("parseStoreHeader: volume body is too small even for FTW block header"), parent);
return ERR_SUCCESS;
@ -3748,8 +3761,8 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
}
if (dataSize < ftwBlockSize) {
msg(QObject::tr("parseStoreHeader: FTW block size %1h (%2) is greater than volume body size %3h (%4)")
.hexarg2(ftwBlockSize, 4).arg(ftwBlockSize)
.hexarg2(dataSize, 8).arg(dataSize), parent);
.hexarg(ftwBlockSize).arg(ftwBlockSize)
.hexarg(dataSize).arg(dataSize), parent);
return ERR_SUCCESS;
}
@ -3784,7 +3797,46 @@ STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parent
pdata.offset = parentOffset;
// Add tree item
index = model->addItem(Types::NvramFtwBlock, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
index = model->addItem(Types::NvramStoreFtw, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
}
else if (*signature == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1) { // Phoenix SCT flash map
if (dataSize < sizeof(PHOENIX_FLASH_MAP_HEADER)) {
msg(QObject::tr("parseStoreHeader: volume body is too small even for FlashMap block header"), parent);
return ERR_SUCCESS;
}
// Get FlashMap block header
const PHOENIX_FLASH_MAP_HEADER* flashMapHeader = (const PHOENIX_FLASH_MAP_HEADER*)signature;
// Check store size
UINT32 flashMapSize = sizeof(PHOENIX_FLASH_MAP_HEADER) + flashMapHeader->NumEntries * sizeof(PHOENIX_FLASH_MAP_ENTRY);
if (dataSize < flashMapSize) {
msg(QObject::tr("parseStoreHeader: FlashMap block size %1h (%2) is greater than volume body size %3h (%4)")
.hexarg(flashMapSize).arg(flashMapSize)
.hexarg(dataSize).arg(dataSize), parent);
return ERR_SUCCESS;
}
// Get parsing data
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
// Construct header and body
QByteArray header = store.left(sizeof(PHOENIX_FLASH_MAP_HEADER));
QByteArray body = store.mid(sizeof(PHOENIX_FLASH_MAP_HEADER), flashMapSize - sizeof(PHOENIX_FLASH_MAP_HEADER));
// Add info
QString name = QObject::tr("Phoenix SCT FlashMap");
QString info = QObject::tr("Signature: _FLASH_MAP\nFull size: %1h (%2)\nHeader size: %3h (%4)\nBody size: %5h (%6)\nNumber of entries: %7")
.hexarg(flashMapSize).arg(flashMapSize)
.hexarg(header.size()).arg(header.size())
.hexarg(body.size()).arg(body.size())
.arg(flashMapHeader->NumEntries);
// Add correct offset
pdata.offset = parentOffset;
// Add tree item
index = model->addItem(Types::NvramStoreFlashMap, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
}
return ERR_SUCCESS;
@ -4036,7 +4088,7 @@ STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset;
// Add EOF tree item
model->addItem(Types::NvramVariableFsys, 0, name, QString(), info, header, QByteArray(), FALSE, parsingDataToQByteArray(pdata), index);
model->addItem(Types::NvramEntryFsys, 0, name, QString(), info, header, QByteArray(), FALSE, parsingDataToQByteArray(pdata), index);
// Add free space
offset += header.size();
@ -4092,7 +4144,7 @@ STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
pdata.offset = parentOffset + offset;
// Add tree item
model->addItem(Types::NvramVariableFsys, 0, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), index);
model->addItem(Types::NvramEntryFsys, 0, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), index);
// Move to next variable
offset += variableSize;
@ -4162,7 +4214,9 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index)
entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_GUID2) {
const EVSA_GUID_ENTRY* guidHeader = (const EVSA_GUID_ENTRY*)entryHeader;
header = data.mid(offset, sizeof(EVSA_GUID_ENTRY));
name = guidToQString(guidHeader->Guid);
body = data.mid(offset + sizeof(EVSA_GUID_ENTRY), guidHeader->Header.Size - sizeof(EVSA_GUID_ENTRY));
EFI_GUID guid = *(EFI_GUID*)body.constData();
name = guidToQString(guid);
info = QObject::tr("Full size: %1h (%2)\nHeader size %3h (%4)\nBody size: %5h (%6)\nType: %7h\nChecksum: %8\nGuidId: %9h")
.hexarg(variableSize).arg(variableSize)
.hexarg(header.size()).arg(header.size())
@ -4173,7 +4227,7 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index)
QObject::tr("%1h, invalid, should be %2h").hexarg2(guidHeader->Header.Checksum, 2).hexarg2(calculated, 2))
.hexarg2(guidHeader->GuidId, 4);
subtype = Subtypes::GuidEvsaEntry;
guidMap.insert(std::pair<UINT16, EFI_GUID>(guidHeader->GuidId, guidHeader->Guid));
guidMap.insert(std::pair<UINT16, EFI_GUID>(guidHeader->GuidId, guid));
}
// Name entry
else if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_NAME1 ||
@ -4282,3 +4336,69 @@ STATUS FfsParser::parseEvsaStoreBody(const QModelIndex & index)
}
STATUS FfsParser::parseFlashMapBody(const QModelIndex & index)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
// Get parsing data for the current item
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
UINT32 parentOffset = pdata.offset + model->header(index).size();
const QByteArray data = model->body(index);
const UINT32 dataSize = (UINT32)data.size();
UINT32 offset = 0;
UINT32 unparsedSize = dataSize;
// Parse all entries
while (unparsedSize) {
const PHOENIX_FLASH_MAP_ENTRY* entryHeader = (const PHOENIX_FLASH_MAP_ENTRY*)(data.constData() + offset);
// Check entry size
if (unparsedSize < sizeof(PHOENIX_FLASH_MAP_ENTRY)) {
// Last variable is bad, add the rest as padding and return
QByteArray body = data.mid(offset);
QString info = QObject::tr("Full size: %1h (%2)")
.hexarg(body.size()).arg(body.size());
// Add correct offset to parsing data
pdata.offset = parentOffset + offset;
// Add free space tree item
model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index);
// Show message
if (unparsedSize < entryHeader->Size)
msg(QObject::tr("parseFlashMapBody: next entry appears too big, added as padding"), index);
break;
}
QString name = guidToQString(entryHeader->Guid);
// Construct header
QByteArray header = data.mid(offset, sizeof(PHOENIX_FLASH_MAP_ENTRY));
// Add info
QString info = QObject::tr("Entry GUID: %1\nFull size: 24h (36)\nHeader size %2h (%3)\nBody size: 0h (0)\nType %4h\nMemory address: %5h\nSize: %6h\nOffset: %7h")
.arg(name)
.hexarg(header.size()).arg(header.size())
.hexarg2(entryHeader->Type, 8)
.hexarg2(entryHeader->PhysicalAddress, 8)
.hexarg2(entryHeader->Size, 8)
.hexarg2(entryHeader->Offset, 8);
// Add correct offset to parsing data
pdata.offset = parentOffset + offset;
// Add tree item
model->addItem(Types::NvramEntryFlashMap, 0, name, QString(), info, header, QByteArray(), TRUE, parsingDataToQByteArray(pdata), index);
// Move to next variable
offset += sizeof(PHOENIX_FLASH_MAP_ENTRY);
unparsedSize = dataSize - offset;
}
return ERR_SUCCESS;
}

View File

@ -116,6 +116,7 @@ private:
STATUS parseVssStoreBody(const QModelIndex & index);
STATUS parseFsysStoreBody(const QModelIndex & index);
STATUS parseEvsaStoreBody(const QModelIndex & index);
STATUS parseFlashMapBody(const QModelIndex & index);
// Message helper
void msg(const QString & message, const QModelIndex &index = QModelIndex());

View File

@ -73,7 +73,6 @@ typedef struct NVAR_VARIABLE_HEADER_ {
// FFF12B8D-7696-4C8B-A985-2747075B4F50
const QByteArray NVRAM_MAIN_STORE_VOLUME_GUID
("\x8D\x2B\xF1\xFF\x96\x76\x8B\x4C\xA9\x85\x27\x47\x07\x5B\x4F\x50", 16);
#define NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 0xFFF12B8D
// 00504624-8A59-4EEB-BD0F-6B36E96128E0
const QByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
@ -82,6 +81,7 @@ const QByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
#define NVRAM_APPLE_FSYS_STORE_SIGNATURE 0x73797346 // Fsys
#define NVRAM_APPLE_GAID_STORE_SIGNATURE 0x64696147 // Gaid
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA
// Variable store header flags
@ -158,14 +158,14 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ {
#define NVRAM_VSS_VARIABLE_APPEND_WRITE 0x00000040
#define NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM 0x80000000
// FDC region can be found in some VSS volumes
// FDC region can be found in Insyde VSS volumes
// It has another VSS volume inside
// _FDC header structure
#define NVRAM_FDC_VOLUME_SIGNATURE 0x4344465F
typedef struct FDC_VOLUME_HEADER_ {
UINT32 Signature; //_FDC
UINT32 Size;
UINT32 Size; // Size of the whole region
//EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2];
//VSS_VARIABLE_STORE_HEADER VssHeader;
@ -175,20 +175,28 @@ typedef struct FDC_VOLUME_HEADER_ {
// EFI Fault tolerant working block header
#define EFI_FAULT_TOLERANT_WORKING_BLOCK_VALID 0x1
#define EFI_FAULT_TOLERANT_WORKING_BLOCK_INVALID 0x2
typedef struct {
// 9E58292B-7C68-497D-0ACE6500FD9F1B95
const QByteArray EDKII_WORKING_BLOCK_SIGNATURE_GUID
("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\x0A\xCE\x65\x00\xFD\x9F\x1B\x95", 16);
#define NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 0xFFF12B8D
#define EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 0x9E58292B
typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32_ {
EFI_GUID Signature; // NVRAM_MAIN_STORE_VOLUME_GUID
UINT32 Crc; // Crc32 of the header with empty Crc and State fields
UINT8 State;
UINT8 Reserved3[3];
UINT8 Reserved[3];
UINT32 WriteQueueSize; // Size of the FTW block without the header
//UINT8 WriteQueue[WriteQueueSize];
} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32;
typedef struct {
typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64_ {
EFI_GUID Signature; // NVRAM_MAIN_STORE_VOLUME_GUID
UINT32 Crc; // Crc32 of the header with empty Crc and State fields
UINT8 State;
UINT8 Reserved3[3];
UINT8 Reserved[3];
UINT64 WriteQueueSize; // Size of the FTW block without the header
//UINT8 WriteQueue[WriteQueueSize];
} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64;
@ -203,7 +211,7 @@ typedef struct APPLE_FSYS_STORE_HEADER_ {
UINT16 Size; // Size of variable store
} APPLE_FSYS_STORE_HEADER;
// Apple Fsys variable format
// Apple Fsys entry format
// UINT8 NameLength;
// CHAR8 Name[];
// UINT16 DataLength;
@ -244,7 +252,7 @@ typedef struct EVSA_STORE_ENTRY_ {
typedef struct EVSA_GUID_ENTRY_ {
EVSA_ENTRY_HEADER Header;
UINT16 GuidId;
EFI_GUID Guid;
//EFI_GUID Guid;
} EVSA_GUID_ENTRY;
typedef struct EVSA_NAME_ENTRY_ {
@ -261,6 +269,36 @@ typedef struct EVSA_DATA_ENTRY_ {
//UINT8 Data[];
} EVSA_DATA_ENTRY;
//
// Phoenix SCT Flash Map
//
#define NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 0x414C465F
#define NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH 10
// _FLASH_MAP
const QByteArray NVRAM_PHOENIX_FLASH_MAP_SIGNATURE
("\x5F\x46\x4C\x41\x53\x48\x5F\x4D\x41\x50", 10);
typedef struct PHOENIX_FLASH_MAP_HEADER_ {
UINT8 Signature[10]; // _FLASH_MAP signature
UINT16 NumEntries; // Number of entries in the map
UINT32 : 32; // Reserved field
} PHOENIX_FLASH_MAP_HEADER;
typedef struct PHOENIX_FLASH_MAP_ENTRY_ {
EFI_GUID Guid;
UINT32 Type;
UINT64 PhysicalAddress;
UINT32 Size;
UINT32 Offset;
} PHOENIX_FLASH_MAP_ENTRY;
// Restore previous packing rules
#pragma pack(pop)

View File

@ -73,16 +73,20 @@ QString itemTypeToQString(const UINT8 type)
return QObject::tr("Fsys store");
case Types::NvramStoreEvsa:
return QObject::tr("EVSA store");
case Types::NvramFtwBlock:
return QObject::tr("FTW block");
case Types::NvramStoreFtw:
return QObject::tr("FTW store");
case Types::NvramStoreFlashMap:
return QObject::tr("FlashMap store");
case Types::NvramVariableNvar:
return QObject::tr("NVAR variable");
case Types::NvramVariableVss:
return QObject::tr("VSS variable");
case Types::NvramVariableFsys:
return QObject::tr("Fsys variable");
case Types::NvramEntryFsys:
return QObject::tr("Fsys entry");
case Types::NvramEntryEvsa:
return QObject::tr("EVSA entry");
case Types::NvramEntryFlashMap:
return QObject::tr("FlashMap entry");
default:
return QObject::tr("Unknown");
}
@ -142,8 +146,10 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
case Types::NvramStoreFdc:
case Types::NvramStoreFsys:
case Types::NvramStoreEvsa:
case Types::NvramFtwBlock:
case Types::NvramVariableFsys:
case Types::NvramStoreFtw:
case Types::NvramStoreFlashMap:
case Types::NvramEntryFsys:
case Types::NvramEntryFlashMap:
return QString();
case Types::NvramVariableNvar:
if (subtype == Subtypes::InvalidNvarVariable)

View File

@ -47,11 +47,13 @@ namespace Types {
NvramStoreFdc,
NvramStoreFsys,
NvramStoreEvsa,
NvramFtwBlock,
NvramStoreFlashMap,
NvramStoreFtw,
NvramVariableNvar,
NvramVariableVss,
NvramVariableFsys,
NvramEntryEvsa
NvramEntryFsys,
NvramEntryEvsa,
NvramEntryFlashMap,
};
}