mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-25 17:38:22 +08:00
Initial EVSA format support
- better UI and parsing upcoming - "storage" replaced with "store" everywhere
This commit is contained in:
parent
40200bca12
commit
57e24c7465
@ -176,11 +176,11 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
ui->menuFileActions->setEnabled(type == Types::File);
|
ui->menuFileActions->setEnabled(type == Types::File);
|
||||||
ui->menuSectionActions->setEnabled(type == Types::Section);
|
ui->menuSectionActions->setEnabled(type == Types::Section);
|
||||||
ui->menuVariableActions->setEnabled(type == Types::NvramVariableNvar || type == Types::NvramVariableVss || type == Types::NvramVariableFsys);
|
ui->menuVariableActions->setEnabled(type == Types::NvramVariableNvar || type == Types::NvramVariableVss || type == Types::NvramVariableFsys);
|
||||||
ui->menuStorageActions->setEnabled(type == Types::NvramStorageVss || type == Types::NvramStorageFdc || type == Types::NvramStorageFsys);
|
ui->menuStoreActions->setEnabled(type == Types::NvramStoreVss || type == Types::NvramStoreFdc || type == Types::NvramStoreFsys || type == Types::NvramStoreEvsa);
|
||||||
|
|
||||||
// Enable actions
|
// Enable actions
|
||||||
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
|
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
|
||||||
ui->actionGoToData->setEnabled(type == Types::NvramVariableNvar && subtype == Subtypes::LinkNvar);
|
ui->actionGoToData->setEnabled(type == Types::NvramVariableNvar && subtype == Subtypes::LinkNvarVariable);
|
||||||
|
|
||||||
// Disable rebuild for now
|
// Disable rebuild for now
|
||||||
//ui->actionRebuild->setDisabled(type == Types::Region && subtype == Subtypes::DescriptorRegion);
|
//ui->actionRebuild->setDisabled(type == Types::Region && subtype == Subtypes::DescriptorRegion);
|
||||||
@ -284,7 +284,7 @@ void UEFITool::search()
|
|||||||
void UEFITool::goToData()
|
void UEFITool::goToData()
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
if (!index.isValid() || model->type(index) != Types::NvramVariableNvar || model->subtype(index) != Subtypes::LinkNvar)
|
if (!index.isValid() || model->type(index) != Types::NvramVariableNvar || model->subtype(index) != Subtypes::LinkNvarVariable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get parent
|
// Get parent
|
||||||
@ -543,12 +543,15 @@ void UEFITool::extract(const UINT8 mode)
|
|||||||
case Types::NvramVariableVss:
|
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 variable to file"), name + ".var", "Variable files (*.var *.bin);;All files (*)");
|
||||||
break;
|
break;
|
||||||
case Types::NvramStorageVss:
|
case Types::NvramStoreVss:
|
||||||
case Types::NvramStorageFdc:
|
case Types::NvramStoreFdc:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save variable storage to file"), name + ".vss", "Variable storage files (*.vss *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save variable store to file"), name + ".vss", "Variable store files (*.vss *.bin);;All files (*)");
|
||||||
break;
|
break;
|
||||||
case Types::NvramStorageFsys:
|
case Types::NvramStoreFsys:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save Fsys storage to file"), name + ".fsys", "Fsys storage files (*.fsys *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save Fsys store to file"), name + ".fsys", "Fsys store files (*.fsys *.bin);;All files (*)");
|
||||||
|
break;
|
||||||
|
case Types::NvramStoreEvsa:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save EVSA store to file"), name + ".evsa", "EVSA store files (*.evsa *.bin);;All files (*)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
||||||
@ -586,12 +589,15 @@ void UEFITool::extract(const UINT8 mode)
|
|||||||
case Types::NvramVariableVss:
|
case Types::NvramVariableVss:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save variable body to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save variable body to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
||||||
break;
|
break;
|
||||||
case Types::NvramStorageVss:
|
case Types::NvramStoreVss:
|
||||||
case Types::NvramStorageFdc:
|
case Types::NvramStoreFdc:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save variable storage body to file"), name + ".vsb", "Variable storage body files (*.vsb *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save variable store body to file"), name + ".vsb", "Variable store body files (*.vsb *.bin);;All files (*)");
|
||||||
break;
|
break;
|
||||||
case Types::NvramStorageFsys:
|
case Types::NvramStoreFsys:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save Fsys storage body to file"), name + ".fsb", "Fsys storage body files (*.fsb *.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save Fsys store body to file"), name + ".fsb", "Fsys store body files (*.fsb *.bin);;All files (*)");
|
||||||
|
break;
|
||||||
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
path = QFileDialog::getSaveFileName(this, tr("Save object to file"), name + ".bin", "Binary files (*.bin);;All files (*)");
|
||||||
@ -959,10 +965,11 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
case Types::NvramVariableFsys:
|
case Types::NvramVariableFsys:
|
||||||
ui->menuVariableActions->exec(event->globalPos());
|
ui->menuVariableActions->exec(event->globalPos());
|
||||||
break;
|
break;
|
||||||
case Types::NvramStorageVss:
|
case Types::NvramStoreVss:
|
||||||
case Types::NvramStorageFdc:
|
case Types::NvramStoreFdc:
|
||||||
case Types::NvramStorageFsys:
|
case Types::NvramStoreFsys:
|
||||||
ui->menuStorageActions->exec(event->globalPos());
|
case Types::NvramStoreEvsa:
|
||||||
|
ui->menuStoreActions->exec(event->globalPos());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,9 +413,9 @@
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionRemove"/>
|
<addaction name="actionRemove"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuStorageActions">
|
<widget class="QMenu" name="menuStoreActions">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>S&torage</string>
|
<string>S&tore</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionExtract"/>
|
<addaction name="actionExtract"/>
|
||||||
<addaction name="actionExtractBody"/>
|
<addaction name="actionExtractBody"/>
|
||||||
@ -436,7 +436,7 @@
|
|||||||
<addaction name="menuVolumeActions"/>
|
<addaction name="menuVolumeActions"/>
|
||||||
<addaction name="menuFileActions"/>
|
<addaction name="menuFileActions"/>
|
||||||
<addaction name="menuSectionActions"/>
|
<addaction name="menuSectionActions"/>
|
||||||
<addaction name="menuStorageActions"/>
|
<addaction name="menuStoreActions"/>
|
||||||
<addaction name="menuVariableActions"/>
|
<addaction name="menuVariableActions"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="menuMessages"/>
|
<addaction name="menuMessages"/>
|
||||||
|
@ -80,7 +80,7 @@ typedef UINT8 STATUS;
|
|||||||
#define ERR_DIR_CREATE 34
|
#define ERR_DIR_CREATE 34
|
||||||
#define ERR_TRUNCATED_IMAGE 35
|
#define ERR_TRUNCATED_IMAGE 35
|
||||||
#define ERR_INVALID_CAPSULE 36
|
#define ERR_INVALID_CAPSULE 36
|
||||||
#define ERR_STORAGES_NOT_FOUND 37
|
#define ERR_STORES_NOT_FOUND 37
|
||||||
#define ERR_NOT_IMPLEMENTED 0xFF
|
#define ERR_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
// UDK porting definitions
|
// UDK porting definitions
|
||||||
|
@ -73,9 +73,9 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
|
|||||||
case Types::Image:
|
case Types::Image:
|
||||||
case Types::Region:
|
case Types::Region:
|
||||||
case Types::Padding:
|
case Types::Padding:
|
||||||
case Types::NvramStorageVss:
|
case Types::NvramStoreVss:
|
||||||
case Types::NvramStorageFdc:
|
case Types::NvramStoreFdc:
|
||||||
case Types::NvramStorageFsys:
|
case Types::NvramStoreFsys:
|
||||||
default:
|
default:
|
||||||
name = itemName.replace(' ', '_').replace('/', '_');
|
name = itemName.replace(' ', '_').replace('/', '_');
|
||||||
}
|
}
|
||||||
|
@ -1029,7 +1029,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
|
|
||||||
// Check for volume structure to be known
|
// Check for volume structure to be known
|
||||||
bool isUnknown = true;
|
bool isUnknown = true;
|
||||||
bool isVssNvramVolume = false;
|
bool isNvramVolume = false;
|
||||||
UINT8 ffsVersion = 0;
|
UINT8 ffsVersion = 0;
|
||||||
|
|
||||||
// Check for FFS v2 volume
|
// Check for FFS v2 volume
|
||||||
@ -1046,9 +1046,9 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for VSS NVRAM volume
|
// Check for VSS NVRAM volume
|
||||||
if (guid == NVRAM_VSS_STORAGE_VOLUME_GUID) {
|
if (guid == NVRAM_VSS_STORE_VOLUME_GUID || guid == NVRAM_ADDITIONAL_STORE_VOLUME_GUID) {
|
||||||
isUnknown = false;
|
isUnknown = false;
|
||||||
isVssNvramVolume = true;
|
isNvramVolume = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check volume revision and alignment
|
// Check volume revision and alignment
|
||||||
@ -1179,8 +1179,8 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
subtype = Subtypes::Ffs2Volume;
|
subtype = Subtypes::Ffs2Volume;
|
||||||
else if (ffsVersion == 3)
|
else if (ffsVersion == 3)
|
||||||
subtype = Subtypes::Ffs3Volume;
|
subtype = Subtypes::Ffs3Volume;
|
||||||
else if (isVssNvramVolume)
|
else if (isNvramVolume)
|
||||||
subtype = Subtypes::VssNvramVolume;
|
subtype = Subtypes::NvramVolume;
|
||||||
}
|
}
|
||||||
index = model->addItem(Types::Volume, subtype, name, text, info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
index = model->addItem(Types::Volume, subtype, name, text, info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
||||||
|
|
||||||
@ -1345,8 +1345,8 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
|||||||
UINT32 offset = pdata.offset;
|
UINT32 offset = pdata.offset;
|
||||||
|
|
||||||
// Parse VSS NVRAM volumes with a dedicated function
|
// Parse VSS NVRAM volumes with a dedicated function
|
||||||
if (model->subtype(index) == Subtypes::VssNvramVolume)
|
if (model->subtype(index) == Subtypes::NvramVolume)
|
||||||
return parseStorageArea(volumeBody, index);
|
return parseStoreArea(volumeBody, index);
|
||||||
|
|
||||||
if (pdata.ffsVersion != 2 && pdata.ffsVersion != 3) // Don't parse unknown volumes
|
if (pdata.ffsVersion != 2 && pdata.ffsVersion != 3) // Don't parse unknown volumes
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
@ -1622,10 +1622,10 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf
|
|||||||
isVtf = true;
|
isVtf = true;
|
||||||
text = QObject::tr("Volume Top File");
|
text = QObject::tr("Volume Top File");
|
||||||
}
|
}
|
||||||
// Check if the file is NVRAM storage with NVAR format
|
// Check if the file is NVRAM store with NVAR format
|
||||||
else if (guid == NVRAM_NVAR_STORAGE_FILE_GUID || guid == NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID) {
|
else if (guid == NVRAM_NVAR_STORE_FILE_GUID || guid == NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID) {
|
||||||
// Mark the file as NVAR storage
|
// Mark the file as NVAR store
|
||||||
pdata.file.format = RAW_FILE_FORMAT_NVAR_STORAGE;
|
pdata.file.format = RAW_FILE_FORMAT_NVAR_STORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
@ -1700,9 +1700,9 @@ STATUS FfsParser::parseFileBody(const QModelIndex & index)
|
|||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
// Parse NVAR storage
|
// Parse NVAR store
|
||||||
if (pdata.file.format == RAW_FILE_FORMAT_NVAR_STORAGE)
|
if (pdata.file.format == RAW_FILE_FORMAT_NVAR_STORE)
|
||||||
return parseNvarStorage(model->body(index), index);
|
return parseNvarStore(model->body(index), index);
|
||||||
|
|
||||||
return parseRawArea(model->body(index), index);
|
return parseRawArea(model->body(index), index);
|
||||||
}
|
}
|
||||||
@ -2440,7 +2440,7 @@ STATUS FfsParser::parseVersionSectionBody(const QModelIndex & index)
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
model->addInfo(index, QObject::tr("\nVersion string: %1").arg(QString::fromUtf16((const ushort*)model->body(index).constData())));
|
model->addInfo(index, QObject::tr("\nVersion string: %1").arg(QString::fromUtf16((const CHAR16*)model->body(index).constData())));
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -2575,7 +2575,7 @@ STATUS FfsParser::parseUiSectionBody(const QModelIndex & index)
|
|||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
QString text = QString::fromUtf16((const ushort*)model->body(index).constData());
|
QString text = QString::fromUtf16((const CHAR16*)model->body(index).constData());
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
model->addInfo(index, QObject::tr("\nText: %1").arg(text));
|
model->addInfo(index, QObject::tr("\nText: %1").arg(text));
|
||||||
@ -2881,7 +2881,7 @@ STATUS FfsParser::addOffsetsRecursive(const QModelIndex & index)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex & index)
|
STATUS FfsParser::parseNvarStore(const QByteArray & data, const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -2892,10 +2892,10 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
UINT32 parentOffset = pdata.offset + model->header(index).size();
|
UINT32 parentOffset = pdata.offset + model->header(index).size();
|
||||||
|
|
||||||
// Rename parent file
|
// Rename parent file
|
||||||
model->setText(model->findParentOfType(index, Types::File), QObject::tr("NVAR storage"));
|
model->setText(model->findParentOfType(index, Types::File), QObject::tr("NVAR store"));
|
||||||
|
|
||||||
UINT32 offset = 0;
|
UINT32 offset = 0;
|
||||||
UINT32 guidsInStorage = 0;
|
UINT32 guidsInStore = 0;
|
||||||
|
|
||||||
// Parse all variables
|
// Parse all variables
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -2918,14 +2918,14 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
UINT64 timestamp = 0;
|
UINT64 timestamp = 0;
|
||||||
QByteArray hash;
|
QByteArray hash;
|
||||||
|
|
||||||
UINT8 subtype = Subtypes::FullNvar;
|
UINT8 subtype = Subtypes::FullNvarVariable;
|
||||||
QString name;
|
QString name;
|
||||||
QString text;
|
QString text;
|
||||||
QByteArray header;
|
QByteArray header;
|
||||||
QByteArray body;
|
QByteArray body;
|
||||||
QByteArray extendedData;
|
QByteArray extendedData;
|
||||||
|
|
||||||
UINT32 guidAreaSize = guidsInStorage * sizeof(EFI_GUID);
|
UINT32 guidAreaSize = guidsInStore * sizeof(EFI_GUID);
|
||||||
UINT32 unparsedSize = (UINT32)data.size() - offset - guidAreaSize;
|
UINT32 unparsedSize = (UINT32)data.size() - offset - guidAreaSize;
|
||||||
|
|
||||||
// Get variable header
|
// Get variable header
|
||||||
@ -2949,7 +2949,7 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
else {
|
else {
|
||||||
// Nothing is parsed yet, but the file is not empty
|
// Nothing is parsed yet, but the file is not empty
|
||||||
if (!offset) {
|
if (!offset) {
|
||||||
msg(QObject::tr("parseNvarStorage: file can't be parsed as NVAR variables storage"), index);
|
msg(QObject::tr("parseNvarStore: file can't be parsed as NVAR variables store"), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2966,13 +2966,13 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
// Add tree item
|
// Add tree item
|
||||||
model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, FALSE, parsingDataToQByteArray(pdata), index);
|
model->addItem(type, subtype, name, QString(), info, QByteArray(), padding, FALSE, parsingDataToQByteArray(pdata), index);
|
||||||
|
|
||||||
// Add GUID storage area
|
// Add GUID store area
|
||||||
QByteArray guidArea = data.right(guidAreaSize);
|
QByteArray guidArea = data.right(guidAreaSize);
|
||||||
// Get info
|
// Get info
|
||||||
name = QObject::tr("GUID storage area");
|
name = QObject::tr("GUID store area");
|
||||||
info = QObject::tr("Full size: %1h (%2)\nGUIDs in storage: %3")
|
info = QObject::tr("Full size: %1h (%2)\nGUIDs in store: %3")
|
||||||
.hexarg(guidArea.size()).arg(guidArea.size())
|
.hexarg(guidArea.size()).arg(guidArea.size())
|
||||||
.arg(guidsInStorage);
|
.arg(guidsInStore);
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
pdata.offset = parentOffset + offset + padding.size();
|
pdata.offset = parentOffset + offset + padding.size();
|
||||||
// Add tree item
|
// Add tree item
|
||||||
@ -2999,7 +2999,7 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
|
|
||||||
// Add next node information to parsing data
|
// Add next node information to parsing data
|
||||||
if (variableHeader->Next != lastVariableFlag) {
|
if (variableHeader->Next != lastVariableFlag) {
|
||||||
subtype = Subtypes::LinkNvar;
|
subtype = Subtypes::LinkNvarVariable;
|
||||||
pdata.nvram.nvar.next = variableHeader->Next;
|
pdata.nvram.nvar.next = variableHeader->Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3081,7 +3081,7 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
text = model->text(nvarIndex);
|
text = model->text(nvarIndex);
|
||||||
|
|
||||||
if (variableHeader->Next == lastVariableFlag)
|
if (variableHeader->Next == lastVariableFlag)
|
||||||
subtype = Subtypes::DataNvar;
|
subtype = Subtypes::DataNvarVariable;
|
||||||
}
|
}
|
||||||
|
|
||||||
isDataOnly = true;
|
isDataOnly = true;
|
||||||
@ -3091,7 +3091,7 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
|
|
||||||
// Get variable name
|
// Get variable name
|
||||||
{
|
{
|
||||||
UINT32 nameOffset = (variableHeader->Attributes & NVRAM_NVAR_VARIABLE_ATTRIB_GUID) ? sizeof(EFI_GUID) : 1; // GUID can be stored with the variable or in a separate storage, so there will only be an index of it
|
UINT32 nameOffset = (variableHeader->Attributes & NVRAM_NVAR_VARIABLE_ATTRIB_GUID) ? sizeof(EFI_GUID) : 1; // GUID can be stored with the variable or in a separate store, so there will only be an index of it
|
||||||
CHAR8* namePtr = (CHAR8*)(variableHeader + 1) + nameOffset;
|
CHAR8* namePtr = (CHAR8*)(variableHeader + 1) + nameOffset;
|
||||||
UINT32 nameSize = 0;
|
UINT32 nameSize = 0;
|
||||||
if (variableHeader->Attributes & NVRAM_NVAR_VARIABLE_ATTRIB_ASCII_NAME) { // Name is stored as ASCII string of CHAR8s
|
if (variableHeader->Attributes & NVRAM_NVAR_VARIABLE_ATTRIB_ASCII_NAME) { // Name is stored as ASCII string of CHAR8s
|
||||||
@ -3107,13 +3107,13 @@ STATUS FfsParser::parseNvarStorage(const QByteArray & data, const QModelIndex &
|
|||||||
if (variableHeader->Attributes & NVRAM_NVAR_VARIABLE_ATTRIB_GUID) { // GUID is strored in the variable itself
|
if (variableHeader->Attributes & NVRAM_NVAR_VARIABLE_ATTRIB_GUID) { // GUID is strored in the variable itself
|
||||||
name = guidToQString(*(EFI_GUID*)(variableHeader + 1));
|
name = guidToQString(*(EFI_GUID*)(variableHeader + 1));
|
||||||
}
|
}
|
||||||
// GUID is stored in GUID list at the end of the storage
|
// GUID is stored in GUID list at the end of the store
|
||||||
else {
|
else {
|
||||||
guidIndex = *(UINT8*)(variableHeader + 1);
|
guidIndex = *(UINT8*)(variableHeader + 1);
|
||||||
if (guidsInStorage < guidIndex + 1)
|
if (guidsInStore < guidIndex + 1)
|
||||||
guidsInStorage = guidIndex + 1;
|
guidsInStore = guidIndex + 1;
|
||||||
|
|
||||||
// The list begins at the end of the storage and goes backwards
|
// The list begins at the end of the store and goes backwards
|
||||||
const EFI_GUID* guidPtr = (const EFI_GUID*)(data.constData() + data.size()) - 1 - guidIndex;
|
const EFI_GUID* guidPtr = (const EFI_GUID*)(data.constData() + data.size()) - 1 - guidIndex;
|
||||||
name = guidToQString(*guidPtr);
|
name = guidToQString(*guidPtr);
|
||||||
hasGuidIndex = true;
|
hasGuidIndex = true;
|
||||||
@ -3129,11 +3129,11 @@ parsing_done:
|
|||||||
if (isInvalid) {
|
if (isInvalid) {
|
||||||
if (variableHeader->Next != lastVariableFlag) {
|
if (variableHeader->Next != lastVariableFlag) {
|
||||||
name = QObject::tr("Invalid link");
|
name = QObject::tr("Invalid link");
|
||||||
subtype = Subtypes::InvalidLinkNvar;
|
subtype = Subtypes::InvalidLinkNvarVariable;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
name = QObject::tr("Invalid");
|
name = QObject::tr("Invalid");
|
||||||
subtype = Subtypes::InvalidNvar;
|
subtype = Subtypes::InvalidNvarVariable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Add GUID info for valid variables
|
else // Add GUID info for valid variables
|
||||||
@ -3192,19 +3192,19 @@ parsing_done:
|
|||||||
|
|
||||||
// Show messages
|
// Show messages
|
||||||
if (msgUnknownExtDataFormat)
|
if (msgUnknownExtDataFormat)
|
||||||
msg(QObject::tr("parseNvarStorage: unknown extended data format"), varIndex);
|
msg(QObject::tr("parseNvarStore: unknown extended data format"), varIndex);
|
||||||
if (msgExtHeaderTooLong)
|
if (msgExtHeaderTooLong)
|
||||||
msg(QObject::tr("parseNvarStorage: extended header size (%1h) is greater than body size (%2h)")
|
msg(QObject::tr("parseNvarStore: extended header size (%1h) is greater than body size (%2h)")
|
||||||
.hexarg(extendedHeaderSize).hexarg(body.size()), varIndex);
|
.hexarg(extendedHeaderSize).hexarg(body.size()), varIndex);
|
||||||
if (msgExtDataTooShort)
|
if (msgExtDataTooShort)
|
||||||
msg(QObject::tr("parseNvarStorage: extended data size (%1h) is smaller than required for timestamp and hash (0x28)")
|
msg(QObject::tr("parseNvarStore: extended data size (%1h) is smaller than required for timestamp and hash (0x28)")
|
||||||
.hexarg(extendedData.size()), varIndex);
|
.hexarg(extendedData.size()), varIndex);
|
||||||
|
|
||||||
// Check variable name to be in the list of nesting variables
|
// Check variable name to be in the list of nesting variables
|
||||||
if (text == QString("StdDefaults") || text == QString("MfgDefaults")) {
|
if (text == QString("StdDefaults") || text == QString("MfgDefaults")) {
|
||||||
STATUS result = parseNvarStorage(body, varIndex);
|
STATUS result = parseNvarStore(body, varIndex);
|
||||||
if (result)
|
if (result)
|
||||||
msg(QObject::tr("parseNvarStorage: parsing of nested NVAR storage failed with error \"%1\"").arg(errorCodeToQString(result)), varIndex);
|
msg(QObject::tr("parseNvarStore: parsing of nested NVAR store failed with error \"%1\"").arg(errorCodeToQString(result)), varIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to next variable
|
// Move to next variable
|
||||||
@ -3214,7 +3214,7 @@ parsing_done:
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex & index)
|
STATUS FfsParser::parseStoreArea(const QByteArray & data, const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -3226,18 +3226,18 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
|
|
||||||
// Search for first volume
|
// Search for first volume
|
||||||
STATUS result;
|
STATUS result;
|
||||||
UINT32 prevStorageOffset;
|
UINT32 prevStoreOffset;
|
||||||
|
|
||||||
result = findNextStorage(index, data, parentOffset, 0, prevStorageOffset);
|
result = findNextStore(index, data, parentOffset, 0, prevStoreOffset);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// First storage is not at the beginning of volume body
|
// First store is not at the beginning of volume body
|
||||||
QString name;
|
QString name;
|
||||||
QString info;
|
QString info;
|
||||||
if (prevStorageOffset > 0) {
|
if (prevStoreOffset > 0) {
|
||||||
// Get info
|
// Get info
|
||||||
QByteArray padding = data.left(prevStorageOffset);
|
QByteArray padding = data.left(prevStoreOffset);
|
||||||
name = QObject::tr("Padding");
|
name = QObject::tr("Padding");
|
||||||
info = QObject::tr("Full size: %1h (%2)")
|
info = QObject::tr("Full size: %1h (%2)")
|
||||||
.hexarg(padding.size()).arg(padding.size());
|
.hexarg(padding.size()).arg(padding.size());
|
||||||
@ -3249,16 +3249,16 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for and parse all storages
|
// Search for and parse all stores
|
||||||
UINT32 storageOffset = prevStorageOffset;
|
UINT32 storeOffset = prevStoreOffset;
|
||||||
UINT32 prevStorageSize = 0;
|
UINT32 prevStoreSize = 0;
|
||||||
|
|
||||||
while (!result)
|
while (!result)
|
||||||
{
|
{
|
||||||
// Padding between storages
|
// Padding between stores
|
||||||
if (storageOffset > prevStorageOffset + prevStorageSize) {
|
if (storeOffset > prevStoreOffset + prevStoreSize) {
|
||||||
UINT32 paddingOffset = prevStorageOffset + prevStorageSize;
|
UINT32 paddingOffset = prevStoreOffset + prevStoreSize;
|
||||||
UINT32 paddingSize = storageOffset - paddingOffset;
|
UINT32 paddingSize = storeOffset - paddingOffset;
|
||||||
QByteArray padding = data.mid(paddingOffset, paddingSize);
|
QByteArray padding = data.mid(paddingOffset, paddingSize);
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
@ -3273,24 +3273,24 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get storage size
|
// Get store size
|
||||||
UINT32 storageSize = 0;
|
UINT32 storeSize = 0;
|
||||||
result = getStorageSize(data, storageOffset, storageSize);
|
result = getStoreSize(data, storeOffset, storeSize);
|
||||||
if (result) {
|
if (result) {
|
||||||
msg(QObject::tr("parseStorageArea: getVssStorageSize failed with error \"%1\"").arg(errorCodeToQString(result)), index);
|
msg(QObject::tr("parseStoreArea: getVssStoreSize failed with error \"%1\"").arg(errorCodeToQString(result)), index);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that storage is fully present in input
|
// Check that store is fully present in input
|
||||||
if (storageSize > (UINT32)data.size() || storageOffset + storageSize > (UINT32)data.size()) {
|
if (storeSize > (UINT32)data.size() || storeOffset + storeSize > (UINT32)data.size()) {
|
||||||
msg(QObject::tr("parseVssStorageArea: one of storages inside overlaps the end of data"), index);
|
msg(QObject::tr("parseVssStoreArea: one of stores inside overlaps the end of data"), index);
|
||||||
return ERR_INVALID_VOLUME;
|
return ERR_INVALID_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray storage = data.mid(storageOffset, storageSize);
|
QByteArray store = data.mid(storeOffset, storeSize);
|
||||||
if (storageSize > (UINT32)storage.size()) {
|
if (storeSize > (UINT32)store.size()) {
|
||||||
// Mark the rest as padding and finish the parsing
|
// Mark the rest as padding and finish the parsing
|
||||||
QByteArray padding = data.right(storage.size());
|
QByteArray padding = data.right(store.size());
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
name = QObject::tr("Padding");
|
name = QObject::tr("Padding");
|
||||||
@ -3298,35 +3298,35 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
.hexarg(padding.size()).arg(padding.size());
|
.hexarg(padding.size()).arg(padding.size());
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
pdata.offset = parentOffset + storageOffset;
|
pdata.offset = parentOffset + storeOffset;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
||||||
msg(QObject::tr("parseStorageArea: one of storages inside overlaps the end of data"), paddingIndex);
|
msg(QObject::tr("parseStoreArea: one of stores inside overlaps the end of data"), paddingIndex);
|
||||||
|
|
||||||
// Update variables
|
// Update variables
|
||||||
prevStorageOffset = storageOffset;
|
prevStoreOffset = storeOffset;
|
||||||
prevStorageSize = padding.size();
|
prevStoreSize = padding.size();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse current volume's header
|
// Parse current volume's header
|
||||||
QModelIndex storageIndex;
|
QModelIndex storeIndex;
|
||||||
result = parseStorageHeader(storage, parentOffset + storageOffset, index, storageIndex);
|
result = parseStoreHeader(store, parentOffset + storeOffset, index, storeIndex);
|
||||||
if (result) {
|
if (result) {
|
||||||
msg(QObject::tr("parseStorageArea: storage header parsing failed with error \"%1\"").arg(errorCodeToQString(result)), index);
|
msg(QObject::tr("parseStoreArea: store header parsing failed with error \"%1\"").arg(errorCodeToQString(result)), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to next volume
|
// Go to next volume
|
||||||
prevStorageOffset = storageOffset;
|
prevStoreOffset = storeOffset;
|
||||||
prevStorageSize = storageSize;
|
prevStoreSize = storeSize;
|
||||||
result = findNextStorage(index, data, parentOffset, storageOffset + prevStorageSize, storageOffset);
|
result = findNextStore(index, data, parentOffset, storeOffset + prevStoreSize, storeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Padding/free space at the end of volume
|
// Padding/free space at the end of volume
|
||||||
storageOffset = prevStorageOffset + prevStorageSize;
|
storeOffset = prevStoreOffset + prevStoreSize;
|
||||||
if ((UINT32)data.size() > storageOffset) {
|
if ((UINT32)data.size() > storeOffset) {
|
||||||
QByteArray padding = data.mid(storageOffset);
|
QByteArray padding = data.mid(storeOffset);
|
||||||
UINT8 type;
|
UINT8 type;
|
||||||
UINT8 subtype;
|
UINT8 subtype;
|
||||||
if (padding.count(pdata.emptyByte) == padding.size()) {
|
if (padding.count(pdata.emptyByte) == padding.size()) {
|
||||||
@ -3337,8 +3337,8 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Nothing is parsed yet, but the file is not empty
|
// Nothing is parsed yet, but the file is not empty
|
||||||
if (!storageOffset) {
|
if (!storeOffset) {
|
||||||
msg(QObject::tr("parseStorageArea: area can't be parsed as storage"), index);
|
msg(QObject::tr("parseStoreArea: area can't be parsed as variable store"), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3353,7 +3353,7 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
.hexarg(padding.size()).arg(padding.size());
|
.hexarg(padding.size()).arg(padding.size());
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
pdata.offset = parentOffset + storageOffset;
|
pdata.offset = parentOffset + storeOffset;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, TRUE, parsingDataToQByteArray(pdata), index);
|
||||||
@ -3363,12 +3363,15 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
for (int i = 0; i < model->rowCount(index); i++) {
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
QModelIndex current = index.child(i, 0);
|
QModelIndex current = index.child(i, 0);
|
||||||
switch (model->type(current)) {
|
switch (model->type(current)) {
|
||||||
case Types::NvramStorageVss:
|
case Types::NvramStoreVss:
|
||||||
case Types::NvramStorageFdc:
|
case Types::NvramStoreFdc:
|
||||||
parseVssStorageBody(current);
|
parseVssStoreBody(current);
|
||||||
break;
|
break;
|
||||||
case Types::NvramStorageFsys:
|
case Types::NvramStoreFsys:
|
||||||
parseFsysStorageBody(current);
|
parseFsysStoreBody(current);
|
||||||
|
break;
|
||||||
|
case Types::NvramStoreEvsa:
|
||||||
|
parseEvsaStoreBody(current);
|
||||||
break;
|
break;
|
||||||
case Types::Padding:
|
case Types::Padding:
|
||||||
// No parsing required
|
// No parsing required
|
||||||
@ -3381,33 +3384,28 @@ STATUS FfsParser::parseStorageArea(const QByteArray & data, const QModelIndex &
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::findNextStorage(const QModelIndex & index, const QByteArray & data, const UINT32 parentOffset, const UINT32 storageOffset, UINT32 & nextStorageOffset)
|
STATUS FfsParser::findNextStore(const QModelIndex & index, const QByteArray & data, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset)
|
||||||
{
|
{
|
||||||
UINT32 dataSize = data.size();
|
UINT32 dataSize = data.size();
|
||||||
|
|
||||||
if (dataSize < sizeof(UINT32))
|
if (dataSize < sizeof(UINT32))
|
||||||
return ERR_STORAGES_NOT_FOUND;
|
return ERR_STORES_NOT_FOUND;
|
||||||
|
|
||||||
UINT32 offset = storageOffset;
|
UINT32 offset = storeOffset;
|
||||||
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
for (; offset < dataSize - sizeof(UINT32); offset++) {
|
||||||
const UINT32* currentPos = (const UINT32*)(data.constData() + offset);
|
const UINT32* currentPos = (const UINT32*)(data.constData() + offset);
|
||||||
if (*currentPos == NVRAM_VSS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_SVS_STORE_SIGNATURE) { //$VSS or $SVS signatures found, perform checks
|
if (*currentPos == NVRAM_VSS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_SVS_STORE_SIGNATURE) { //$VSS or $SVS signatures found, perform checks
|
||||||
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)currentPos;
|
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)currentPos;
|
||||||
if (vssHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) {
|
if (vssHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) {
|
||||||
msg(QObject::tr("findNextStorage: VSS storage candidate at offset %1h skipped, has invalid format %2h").hexarg(parentOffset + offset).hexarg2(vssHeader->Format, 2), index);
|
msg(QObject::tr("findNextStore: VSS store candidate at offset %1h skipped, has invalid format %2h").hexarg(parentOffset + offset).hexarg2(vssHeader->Format, 2), index);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (vssHeader->Size == 0 || vssHeader->Size == 0xFFFFFFFF) {
|
if (vssHeader->Size == 0 || vssHeader->Size == 0xFFFFFFFF) {
|
||||||
msg(QObject::tr("findNextStorage: VSS storage candidate at offset %1h skipped, has invalid size %2h").hexarg(parentOffset + offset).hexarg2(vssHeader->Size, 8), index);
|
msg(QObject::tr("findNextStore: VSS store candidate at offset %1h skipped, has invalid size %2h").hexarg(parentOffset + offset).hexarg2(vssHeader->Size, 8), index);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (vssHeader->State != NVRAM_VSS_VARIABLE_STORE_HEALTHY) {
|
// All checks passed, store found
|
||||||
// msg(QObject::tr("findNextStorage: VSS storage candidate at offset %1h skipped, has invalid state %2h").hexarg(parentOffset + offset).hexarg2(vssHeader->State, 2), index);
|
|
||||||
// continue;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// All checks passed, storage found
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (*currentPos == NVRAM_FDC_VOLUME_SIGNATURE) { //FDC signature found
|
else if (*currentPos == NVRAM_FDC_VOLUME_SIGNATURE) { //FDC signature found
|
||||||
@ -3418,62 +3416,80 @@ STATUS FfsParser::findNextStorage(const QModelIndex & index, const QByteArray &
|
|||||||
// No checks needed
|
// No checks needed
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
else if (*currentPos == NVRAM_EVSA_STORE_SIGNATURE) { //EVSA signature found
|
||||||
// No more storages found
|
if (offset < 4)
|
||||||
if (offset >= dataSize - sizeof(UINT32))
|
continue;
|
||||||
return ERR_STORAGES_NOT_FOUND;
|
|
||||||
|
|
||||||
nextStorageOffset = offset;
|
const EVSA_STORE_ENTRY* evsaHeader = (const EVSA_STORE_ENTRY*)(currentPos - 1);
|
||||||
|
if (evsaHeader->Header.Type != NVRAM_EVSA_ENTRY_TYPE_STORE) {
|
||||||
|
msg(QObject::tr("findNextStore: EVSA store candidate at offset %1h skipped, has invalid type %2h").hexarg(parentOffset + offset - 4).hexarg2(evsaHeader->Header.Type, 2), index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All checks passed, store found
|
||||||
|
offset -= 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No more storas found
|
||||||
|
if (offset >= dataSize - sizeof(UINT32))
|
||||||
|
return ERR_STORES_NOT_FOUND;
|
||||||
|
|
||||||
|
nextStoreOffset = offset;
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::getStorageSize(const QByteArray & data, const UINT32 storageOffset, UINT32 & storageSize)
|
STATUS FfsParser::getStoreSize(const QByteArray & data, const UINT32 storeOffset, UINT32 & storeSize)
|
||||||
{
|
{
|
||||||
//TODO: add GUID support
|
//TODO: add GUID support
|
||||||
const UINT32* signature = (const UINT32*)(data.constData() + storageOffset);
|
const UINT32* signature = (const UINT32*)(data.constData() + storeOffset);
|
||||||
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
|
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
|
||||||
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
||||||
storageSize = vssHeader->Size;
|
storeSize = vssHeader->Size;
|
||||||
}
|
}
|
||||||
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
||||||
const FDC_VOLUME_HEADER* fdcHeader = (const FDC_VOLUME_HEADER*)signature;
|
const FDC_VOLUME_HEADER* fdcHeader = (const FDC_VOLUME_HEADER*)signature;
|
||||||
storageSize = fdcHeader->Size;
|
storeSize = fdcHeader->Size;
|
||||||
}
|
}
|
||||||
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE) {
|
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE) {
|
||||||
const APPLE_FSYS_STORE_HEADER* fsysHeader = (const APPLE_FSYS_STORE_HEADER*)signature;
|
const APPLE_FSYS_STORE_HEADER* fsysHeader = (const APPLE_FSYS_STORE_HEADER*)signature;
|
||||||
storageSize = fsysHeader->Size;
|
storeSize = fsysHeader->Size;
|
||||||
|
}
|
||||||
|
else if (*(signature + 1) == NVRAM_EVSA_STORE_SIGNATURE) {
|
||||||
|
const EVSA_STORE_ENTRY* evsaHeader = (const EVSA_STORE_ENTRY*)signature;
|
||||||
|
storeSize = evsaHeader->StoreSize;
|
||||||
}
|
}
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Parse VSS volume like raw area
|
// Parse VSS volume like raw area
|
||||||
//TODO: seen for now - $VSS, $SVS, Fsys, full volume GUID, _FDC and paddings
|
//TODO: seen for now - $VSS, $SVS, Fsys, full volume GUID, _FDC, EVSA and paddings
|
||||||
|
|
||||||
const UINT32 dataSize = (UINT32)storage.size();
|
const UINT32 dataSize = (UINT32)store.size();
|
||||||
const UINT32* signature = (const UINT32*)storage.constData();
|
const UINT32* signature = (const UINT32*)store.constData();
|
||||||
if (dataSize < sizeof(UINT32)) {
|
if (dataSize < sizeof(UINT32)) {
|
||||||
msg(QObject::tr("parseStorageHeader: volume body is too small even for storage signature"), parent);
|
msg(QObject::tr("parseStoreHeader: volume body is too small even for store signature"), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VSS variable storages
|
// VSS variable stores
|
||||||
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
|
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
|
||||||
// The volume must begin with a storage to be valid, but after the first one, there can be many variants
|
// The volume must begin with a store to be valid, but after the first one, there can be many variants
|
||||||
if (dataSize < sizeof(VSS_VARIABLE_STORE_HEADER)) {
|
if (dataSize < sizeof(VSS_VARIABLE_STORE_HEADER)) {
|
||||||
msg(QObject::tr("parseStorageHeader: volume body is too small even for VSS storage header"), parent);
|
msg(QObject::tr("parseStoreHeader: volume body is too small even for VSS store header"), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get VSS storage header
|
// Get VSS store header
|
||||||
const VSS_VARIABLE_STORE_HEADER* vssStorageHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
const VSS_VARIABLE_STORE_HEADER* vssStoreHeader = (const VSS_VARIABLE_STORE_HEADER*)signature;
|
||||||
|
|
||||||
// Check storage size
|
// Check store size
|
||||||
if (dataSize < vssStorageHeader->Size) {
|
if (dataSize < vssStoreHeader->Size) {
|
||||||
msg(QObject::tr("parseStorageHeader: VSS storage size %1h (%2) is greater than volume body size %3h (%4)")
|
msg(QObject::tr("parseStoreHeader: VSS store size %1h (%2) is greater than volume body size %3h (%4)")
|
||||||
.hexarg2(vssStorageHeader->Size, 8).arg(vssStorageHeader->Size)
|
.hexarg2(vssStoreHeader->Size, 8).arg(vssStoreHeader->Size)
|
||||||
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -3482,49 +3498,49 @@ STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 pa
|
|||||||
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Construct header and body
|
// Construct header and body
|
||||||
QByteArray header = storage.left(sizeof(VSS_VARIABLE_STORE_HEADER));
|
QByteArray header = store.left(sizeof(VSS_VARIABLE_STORE_HEADER));
|
||||||
QByteArray body = storage.mid(sizeof(VSS_VARIABLE_STORE_HEADER), vssStorageHeader->Size - sizeof(VSS_VARIABLE_STORE_HEADER));
|
QByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), vssStoreHeader->Size - sizeof(VSS_VARIABLE_STORE_HEADER));
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
QString name = QObject::tr("VSS storage");
|
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 info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nFormat: %8h\nState: %9h")
|
||||||
.hexarg2(vssStorageHeader->Signature, 8)
|
.hexarg2(vssStoreHeader->Signature, 8)
|
||||||
.hexarg(vssStorageHeader->Size).arg(vssStorageHeader->Size)
|
.hexarg(vssStoreHeader->Size).arg(vssStoreHeader->Size)
|
||||||
.hexarg(header.size()).arg(header.size())
|
.hexarg(header.size()).arg(header.size())
|
||||||
.hexarg(body.size()).arg(body.size())
|
.hexarg(body.size()).arg(body.size())
|
||||||
.hexarg2(vssStorageHeader->Format, 2)
|
.hexarg2(vssStoreHeader->Format, 2)
|
||||||
.hexarg2(vssStorageHeader->State, 2);
|
.hexarg2(vssStoreHeader->State, 2);
|
||||||
|
|
||||||
// Add unknown field for $SVS storages
|
// Add unknown field for $SVS stores
|
||||||
if (*signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
|
if (*signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
|
||||||
info += QObject::tr("\nUnknown: %1h").hexarg2(vssStorageHeader->Unknown, 4);
|
info += QObject::tr("\nUnknown: %1h").hexarg2(vssStoreHeader->Unknown, 4);
|
||||||
|
|
||||||
// Add correct offset
|
// Add correct offset
|
||||||
pdata.offset = parentOffset;
|
pdata.offset = parentOffset;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(Types::NvramStorageVss, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
index = model->addItem(Types::NvramStoreVss, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
||||||
}
|
}
|
||||||
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) {
|
||||||
// The volume must begin with a storage to be valid, but after the first one, there can be many variants
|
// The volume must begin with a store to be valid, but after the first one, there can be many variants
|
||||||
if (dataSize < sizeof(FDC_VOLUME_HEADER)) {
|
if (dataSize < sizeof(FDC_VOLUME_HEADER)) {
|
||||||
msg(QObject::tr("parseStorageHeader: volume body is too small even for FDC storage header"), parent);
|
msg(QObject::tr("parseStoreHeader: volume body is too small even for FDC store header"), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get VSS storage header
|
// Get VSS store header
|
||||||
const FDC_VOLUME_HEADER* fdcStorageHeader = (const FDC_VOLUME_HEADER*)signature;
|
const FDC_VOLUME_HEADER* fdcStoreHeader = (const FDC_VOLUME_HEADER*)signature;
|
||||||
|
|
||||||
// Check storage size
|
// Check store size
|
||||||
if (dataSize < fdcStorageHeader->Size) {
|
if (dataSize < fdcStoreHeader->Size) {
|
||||||
msg(QObject::tr("parseStorageHeader: FDC storage size %1h (%2) is greater than volume body size %3h (%4)")
|
msg(QObject::tr("parseStoreHeader: FDC store size %1h (%2) is greater than volume body size %3h (%4)")
|
||||||
.hexarg2(fdcStorageHeader->Size, 8).arg(fdcStorageHeader->Size)
|
.hexarg2(fdcStoreHeader->Size, 8).arg(fdcStoreHeader->Size)
|
||||||
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine internal volume header size
|
// Determine internal volume header size
|
||||||
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(fdcStorageHeader + 1);
|
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(fdcStoreHeader + 1);
|
||||||
UINT32 headerSize;
|
UINT32 headerSize;
|
||||||
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
||||||
const EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (const EFI_FIRMWARE_VOLUME_EXT_HEADER*)((const UINT8*)volumeHeader + volumeHeader->ExtHeaderOffset);
|
const EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (const EFI_FIRMWARE_VOLUME_EXT_HEADER*)((const UINT8*)volumeHeader + volumeHeader->ExtHeaderOffset);
|
||||||
@ -3536,7 +3552,7 @@ STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 pa
|
|||||||
// Extended header end can be unaligned
|
// Extended header end can be unaligned
|
||||||
headerSize = ALIGN8(headerSize);
|
headerSize = ALIGN8(headerSize);
|
||||||
|
|
||||||
// Add VSS storage header
|
// Add VSS store header
|
||||||
headerSize += sizeof(VSS_VARIABLE_STORE_HEADER);
|
headerSize += sizeof(VSS_VARIABLE_STORE_HEADER);
|
||||||
|
|
||||||
// Add FDC header
|
// Add FDC header
|
||||||
@ -3544,8 +3560,8 @@ STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 pa
|
|||||||
|
|
||||||
// Check sanity of combined header size
|
// Check sanity of combined header size
|
||||||
if (dataSize < headerSize) {
|
if (dataSize < headerSize) {
|
||||||
msg(QObject::tr("parseStorageHeader: FDC storage header size %1h (%2) is greater than volume body size %3h (%4)")
|
msg(QObject::tr("parseStoreHeader: FDC store header size %1h (%2) is greater than volume body size %3h (%4)")
|
||||||
.hexarg2(fdcStorageHeader->Size, 8).arg(fdcStorageHeader->Size)
|
.hexarg2(fdcStoreHeader->Size, 8).arg(fdcStoreHeader->Size)
|
||||||
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -3554,14 +3570,14 @@ STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 pa
|
|||||||
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Construct header and body
|
// Construct header and body
|
||||||
QByteArray header = storage.left(headerSize);
|
QByteArray header = store.left(headerSize);
|
||||||
QByteArray body = storage.mid(headerSize, fdcStorageHeader->Size - headerSize);
|
QByteArray body = store.mid(headerSize, fdcStoreHeader->Size - headerSize);
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
QString name = QObject::tr("FDC storage");
|
QString name = QObject::tr("FDC store");
|
||||||
QString info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)")
|
QString info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)")
|
||||||
.hexarg2(fdcStorageHeader->Signature, 8)
|
.hexarg2(fdcStoreHeader->Signature, 8)
|
||||||
.hexarg(fdcStorageHeader->Size).arg(fdcStorageHeader->Size)
|
.hexarg(fdcStoreHeader->Size).arg(fdcStoreHeader->Size)
|
||||||
.hexarg(header.size()).arg(header.size())
|
.hexarg(header.size()).arg(header.size())
|
||||||
.hexarg(body.size()).arg(body.size());
|
.hexarg(body.size()).arg(body.size());
|
||||||
|
|
||||||
@ -3571,22 +3587,22 @@ STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 pa
|
|||||||
pdata.offset = parentOffset;
|
pdata.offset = parentOffset;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(Types::NvramStorageFdc, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
index = model->addItem(Types::NvramStoreFdc, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
||||||
}
|
}
|
||||||
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE) {
|
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE) {
|
||||||
// The volume must begin with a storage to be valid, but after the first one, there can be many variants
|
// The volume must begin with a store to be valid, but after the first one, there can be many variants
|
||||||
if (dataSize < sizeof(APPLE_FSYS_STORE_HEADER)) {
|
if (dataSize < sizeof(APPLE_FSYS_STORE_HEADER)) {
|
||||||
msg(QObject::tr("parseStorageHeader: volume body is too small even for Fsys storage header"), parent);
|
msg(QObject::tr("parseStoreHeader: volume body is too small even for Fsys store header"), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Fsys storage header
|
// Get Fsys store header
|
||||||
const APPLE_FSYS_STORE_HEADER* fsysStorageHeader = (const APPLE_FSYS_STORE_HEADER*)signature;
|
const APPLE_FSYS_STORE_HEADER* fsysStoreHeader = (const APPLE_FSYS_STORE_HEADER*)signature;
|
||||||
|
|
||||||
// Check storage size
|
// Check store size
|
||||||
if (dataSize < fsysStorageHeader->Size) {
|
if (dataSize < fsysStoreHeader->Size) {
|
||||||
msg(QObject::tr("parseStorageHeader: Fsys storage size %1h (%2) is greater than volume body size %3h (%4)")
|
msg(QObject::tr("parseStoreHeader: Fsys store size %1h (%2) is greater than volume body size %3h (%4)")
|
||||||
.hexarg2(fsysStorageHeader->Size, 4).arg(fsysStorageHeader->Size)
|
.hexarg2(fsysStoreHeader->Size, 4).arg(fsysStoreHeader->Size)
|
||||||
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
.hexarg2(dataSize, 8).arg(dataSize), parent);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -3595,38 +3611,85 @@ STATUS FfsParser::parseStorageHeader(const QByteArray & storage, const UINT32 pa
|
|||||||
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Construct header and body
|
// Construct header and body
|
||||||
QByteArray header = storage.left(sizeof(APPLE_FSYS_STORE_HEADER));
|
QByteArray header = store.left(sizeof(APPLE_FSYS_STORE_HEADER));
|
||||||
QByteArray body = storage.mid(sizeof(APPLE_FSYS_STORE_HEADER), fsysStorageHeader->Size - sizeof(APPLE_FSYS_STORE_HEADER) - sizeof(UINT32));
|
QByteArray body = store.mid(sizeof(APPLE_FSYS_STORE_HEADER), fsysStoreHeader->Size - sizeof(APPLE_FSYS_STORE_HEADER) - sizeof(UINT32));
|
||||||
|
|
||||||
// Check storage checksum
|
// Check store checksum
|
||||||
UINT32 storedCrc = *(UINT32*)storage.right(sizeof(UINT32)).constBegin();
|
UINT32 storedCrc = *(UINT32*)store.right(sizeof(UINT32)).constBegin();
|
||||||
UINT32 calculatedCrc = calculatedCrc = crc32(0, (const UINT8*)storage.constData(), (const UINT32)storage.size() - sizeof(UINT32));
|
UINT32 calculatedCrc = calculatedCrc = crc32(0, (const UINT8*)store.constData(), (const UINT32)store.size() - sizeof(UINT32));
|
||||||
|
|
||||||
// Add info
|
// Add info
|
||||||
QString name = QObject::tr("Fsys storage");
|
QString name = 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")
|
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(fsysStorageHeader->Signature, 8)
|
.hexarg2(fsysStoreHeader->Signature, 8)
|
||||||
.hexarg(fsysStorageHeader->Size).arg(fsysStorageHeader->Size)
|
.hexarg(fsysStoreHeader->Size).arg(fsysStoreHeader->Size)
|
||||||
.hexarg(header.size()).arg(header.size())
|
.hexarg(header.size()).arg(header.size())
|
||||||
.hexarg(body.size()).arg(body.size())
|
.hexarg(body.size()).arg(body.size())
|
||||||
.hexarg2(fsysStorageHeader->Unknown[0], 2)
|
.hexarg2(fsysStoreHeader->Unknown[0], 2)
|
||||||
.hexarg2(fsysStorageHeader->Unknown[1], 2)
|
.hexarg2(fsysStoreHeader->Unknown[1], 2)
|
||||||
.hexarg2(fsysStorageHeader->Unknown[2], 2)
|
.hexarg2(fsysStoreHeader->Unknown[2], 2)
|
||||||
.hexarg2(fsysStorageHeader->Unknown[3], 2)
|
.hexarg2(fsysStoreHeader->Unknown[3], 2)
|
||||||
.hexarg2(fsysStorageHeader->Unknown[4], 2)
|
.hexarg2(fsysStoreHeader->Unknown[4], 2)
|
||||||
.arg(storedCrc == calculatedCrc ? QObject::tr("%1h, valid").hexarg2(storedCrc, 8) : QObject::tr("%1h, invalid, should be %2h").hexarg2(storedCrc, 8).hexarg2(calculatedCrc, 8));
|
.arg(storedCrc == calculatedCrc ? QObject::tr("%1h, valid").hexarg2(storedCrc, 8) : QObject::tr("%1h, invalid, should be %2h").hexarg2(storedCrc, 8).hexarg2(calculatedCrc, 8));
|
||||||
|
|
||||||
// Add correct offset
|
// Add correct offset
|
||||||
pdata.offset = parentOffset;
|
pdata.offset = parentOffset;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = model->addItem(Types::NvramStorageFsys, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), 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
|
||||||
|
if (dataSize < sizeof(EVSA_STORE_ENTRY)) {
|
||||||
|
msg(QObject::tr("parseStoreHeader: volume body is too small even for EVSA store header"), parent);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get EVSA store header
|
||||||
|
const EVSA_STORE_ENTRY* evsaStoreHeader = (const EVSA_STORE_ENTRY*)signature;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get parsing data
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
|
// Construct header and body
|
||||||
|
QByteArray header = store.left(evsaStoreHeader->Header.Size);
|
||||||
|
QByteArray body = store.mid(evsaStoreHeader->Header.Size, evsaStoreHeader->StoreSize - evsaStoreHeader->Header.Size);
|
||||||
|
|
||||||
|
// Recalculate checksum
|
||||||
|
UINT8 calculated = calculateChecksum8(((const UINT8*)evsaStoreHeader) + 2, evsaStoreHeader->Header.Size - 2);
|
||||||
|
|
||||||
|
// Add info
|
||||||
|
QString name = QObject::tr("EVSA store");
|
||||||
|
QString info = QObject::tr("Signature: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nType: %9h\nChecksum: %10\nAttributes: %11h")
|
||||||
|
.hexarg2(evsaStoreHeader->Signature, 8)
|
||||||
|
.hexarg(evsaStoreHeader->StoreSize).arg(evsaStoreHeader->StoreSize)
|
||||||
|
.hexarg(header.size()).arg(header.size())
|
||||||
|
.hexarg(body.size()).arg(body.size())
|
||||||
|
.hexarg2(evsaStoreHeader->Header.Type, 2)
|
||||||
|
.arg(evsaStoreHeader->Header.Checksum == calculated ?
|
||||||
|
QObject::tr("%1h, valid").hexarg2(calculated,2) :
|
||||||
|
QObject::tr("%1h, invalid, should be %2h").hexarg2(evsaStoreHeader->Header.Checksum, 2).hexarg2(calculated,2))
|
||||||
|
.hexarg2(evsaStoreHeader->Attributes, 8);
|
||||||
|
|
||||||
|
// Add correct offset
|
||||||
|
pdata.offset = parentOffset;
|
||||||
|
|
||||||
|
// Add tree item
|
||||||
|
index = model->addItem(Types::NvramStoreEvsa, 0, name, QString(), info, header, body, TRUE, parsingDataToQByteArray(pdata), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseVssStorageBody(const QModelIndex & index)
|
STATUS FfsParser::parseVssStoreBody(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -3640,7 +3703,7 @@ STATUS FfsParser::parseVssStorageBody(const QModelIndex & index)
|
|||||||
// Check that the is enough space for variable header
|
// Check that the is enough space for variable header
|
||||||
const UINT32 dataSize = (UINT32)data.size();
|
const UINT32 dataSize = (UINT32)data.size();
|
||||||
if (dataSize < sizeof(VSS_VARIABLE_HEADER)) {
|
if (dataSize < sizeof(VSS_VARIABLE_HEADER)) {
|
||||||
msg(QObject::tr("parseVssStorageBody: storage body is too small even for VSS variable header"), index);
|
msg(QObject::tr("parseVssStoreBody: store body is too small even for VSS variable header"), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3752,9 +3815,9 @@ STATUS FfsParser::parseVssStorageBody(const QModelIndex & index)
|
|||||||
subtype = 0;
|
subtype = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Nothing is parsed yet, but the storage is not empty
|
// Nothing is parsed yet, but the store is not empty
|
||||||
if (!offset) {
|
if (!offset) {
|
||||||
msg(QObject::tr("parseVssStorageBody: storage can't be parsed as VSS storage"), index);
|
msg(QObject::tr("parseVssStoreBody: store can't be parsed as VSS store"), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3803,20 +3866,20 @@ STATUS FfsParser::parseVssStorageBody(const QModelIndex & index)
|
|||||||
|
|
||||||
// Set subtype and add related info
|
// Set subtype and add related info
|
||||||
if (isInvalid)
|
if (isInvalid)
|
||||||
subtype = Subtypes::InvalidVss;
|
subtype = Subtypes::InvalidVssVariable;
|
||||||
else if (isAuthenticated) {
|
else if (isAuthenticated) {
|
||||||
subtype = Subtypes::AuthVss;
|
subtype = Subtypes::AuthVssVariable;
|
||||||
info += QObject::tr("\nMonotonic counter: %1h\nTimestamp: %2\nPubKey index: %3")
|
info += QObject::tr("\nMonotonic counter: %1h\nTimestamp: %2\nPubKey index: %3")
|
||||||
.hexarg(monotonicCounter).arg(efiTimeToQString(timestamp)).arg(pubKeyIndex);
|
.hexarg(monotonicCounter).arg(efiTimeToQString(timestamp)).arg(pubKeyIndex);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (isAppleCrc32) {
|
else if (isAppleCrc32) {
|
||||||
subtype = Subtypes::AppleCrc32Vss;
|
subtype = Subtypes::Crc32VssVariable;
|
||||||
info += QObject::tr("\nCRC32: %1h%2").hexarg2(storedCrc32, 8)
|
info += QObject::tr("\nCRC32: %1h%2").hexarg2(storedCrc32, 8)
|
||||||
.arg(storedCrc32 == calculatedCrc32 ? QObject::tr(", valid") : QObject::tr(", invalid, should be %1h").hexarg2(calculatedCrc32,8));
|
.arg(storedCrc32 == calculatedCrc32 ? QObject::tr(", valid") : QObject::tr(", invalid, should be %1h").hexarg2(calculatedCrc32,8));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
subtype = Subtypes::StandardVss;
|
subtype = Subtypes::StandardVssVariable;
|
||||||
|
|
||||||
// Add correct offset to parsing data
|
// Add correct offset to parsing data
|
||||||
pdata.offset = parentOffset + offset;
|
pdata.offset = parentOffset + offset;
|
||||||
@ -3831,7 +3894,7 @@ STATUS FfsParser::parseVssStorageBody(const QModelIndex & index)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseFsysStorageBody(const QModelIndex & index)
|
STATUS FfsParser::parseFsysStoreBody(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -3909,7 +3972,7 @@ STATUS FfsParser::parseFsysStorageBody(const QModelIndex & index)
|
|||||||
model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index);
|
model->addItem(Types::Padding, getPaddingType(body), QObject::tr("Padding"), QString(), info, QByteArray(), body, FALSE, parsingDataToQByteArray(pdata), index);
|
||||||
|
|
||||||
// Show message
|
// Show message
|
||||||
msg(QObject::tr("parseFsysStorageBody: variable appears too big, added as padding"), index);
|
msg(QObject::tr("parseFsysStoreBody: variable appears too big, added as padding"), index);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -3937,4 +4000,120 @@ STATUS FfsParser::parseFsysStorageBody(const QModelIndex & index)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATUS FfsParser::parseEvsaStoreBody(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);
|
||||||
|
|
||||||
|
// Check that the is enough space for variable header
|
||||||
|
const UINT32 dataSize = (UINT32)data.size();
|
||||||
|
UINT32 offset = 0;
|
||||||
|
|
||||||
|
// Parse all variables
|
||||||
|
while (1) {
|
||||||
|
UINT32 unparsedSize = dataSize - offset;
|
||||||
|
UINT32 variableSize = 0;
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
QString info;
|
||||||
|
QByteArray header;
|
||||||
|
QByteArray body;
|
||||||
|
UINT8 subtype;
|
||||||
|
UINT8 calculated;
|
||||||
|
|
||||||
|
const EVSA_ENTRY_HEADER* entryHeader = (const EVSA_ENTRY_HEADER*)(data.constData() + offset);
|
||||||
|
|
||||||
|
// Check variable size
|
||||||
|
variableSize = sizeof(EVSA_ENTRY_HEADER);
|
||||||
|
if (unparsedSize < variableSize || unparsedSize < entryHeader->Size) {
|
||||||
|
//Add the rest as padding and break from cycle
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
variableSize = entryHeader->Size;
|
||||||
|
|
||||||
|
// Recalculate entry checksum
|
||||||
|
calculated = calculateChecksum8(((const UINT8*)entryHeader) + 2, entryHeader->Size - 2);
|
||||||
|
|
||||||
|
// GUID entry
|
||||||
|
if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_GUID1 ||
|
||||||
|
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);
|
||||||
|
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())
|
||||||
|
.hexarg(body.size()).arg(body.size())
|
||||||
|
.hexarg2(guidHeader->Header.Type, 2)
|
||||||
|
.arg(guidHeader->Header.Checksum == calculated ?
|
||||||
|
QObject::tr("%1h, valid").hexarg2(calculated, 2) :
|
||||||
|
QObject::tr("%1h, invalid, should be %2h").hexarg2(guidHeader->Header.Checksum, 2).hexarg2(calculated, 2))
|
||||||
|
.hexarg2(guidHeader->GuidId, 4);
|
||||||
|
subtype = Subtypes::GuidEvsaEntry;
|
||||||
|
}
|
||||||
|
// Name entry
|
||||||
|
else if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_NAME1 ||
|
||||||
|
entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_NAME2) {
|
||||||
|
const EVSA_NAME_ENTRY* nameHeader = (const EVSA_NAME_ENTRY*)entryHeader;
|
||||||
|
header = data.mid(offset, sizeof(EVSA_NAME_ENTRY));
|
||||||
|
body = data.mid(offset + sizeof(EVSA_NAME_ENTRY), nameHeader->Header.Size - sizeof(EVSA_NAME_ENTRY));
|
||||||
|
name = QString::fromUtf16((const CHAR16*)body.constData());
|
||||||
|
info = QObject::tr("Full size: %1h (%2)\nHeader size %3h (%4)\nBody size: %5h (%6)\nType: %7h\nChecksum: %8\nVarId: %9h")
|
||||||
|
.hexarg(variableSize).arg(variableSize)
|
||||||
|
.hexarg(header.size()).arg(header.size())
|
||||||
|
.hexarg(body.size()).arg(body.size())
|
||||||
|
.hexarg2(nameHeader->Header.Type, 2)
|
||||||
|
.arg(nameHeader->Header.Checksum == calculated ?
|
||||||
|
QObject::tr("%1h, valid").hexarg2(calculated, 2) :
|
||||||
|
QObject::tr("%1h, invalid, should be %2h").hexarg2(nameHeader->Header.Checksum, 2).hexarg2(calculated, 2))
|
||||||
|
.hexarg2(nameHeader->VarId, 4);
|
||||||
|
subtype = Subtypes::NameEvsaEntry;
|
||||||
|
}
|
||||||
|
// Data entry
|
||||||
|
else if (entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA1 ||
|
||||||
|
entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA2 ||
|
||||||
|
entryHeader->Type == NVRAM_EVSA_ENTRY_TYPE_DATA3) {
|
||||||
|
const EVSA_DATA_ENTRY* dataHeader = (const EVSA_DATA_ENTRY*)entryHeader;
|
||||||
|
header = data.mid(offset, sizeof(EVSA_DATA_ENTRY));
|
||||||
|
body = data.mid(offset + sizeof(EVSA_DATA_ENTRY), dataHeader->Header.Size - sizeof(EVSA_DATA_ENTRY));
|
||||||
|
name = QObject::tr("Data");
|
||||||
|
info = QObject::tr("Full size: %1h (%2)\nHeader size %3h (%4)\nBody size: %5h (%6)\nType: %7h\nChecksum: %8\nVarId: %9h\nGuidId: %10h\nAttributes: %11h")
|
||||||
|
.hexarg(variableSize).arg(variableSize)
|
||||||
|
.hexarg(header.size()).arg(header.size())
|
||||||
|
.hexarg(body.size()).arg(body.size())
|
||||||
|
.hexarg2(dataHeader->Header.Type, 2)
|
||||||
|
.arg(dataHeader->Header.Checksum == calculated ?
|
||||||
|
QObject::tr("%1h, valid").hexarg2(calculated, 2) :
|
||||||
|
QObject::tr("%1h, invalid, should be %2h").hexarg2(dataHeader->Header.Checksum, 2).hexarg2(calculated, 2))
|
||||||
|
.hexarg2(dataHeader->VarId, 4)
|
||||||
|
.hexarg2(dataHeader->GuidId, 4)
|
||||||
|
.hexarg2(dataHeader->Attributes, 8);
|
||||||
|
subtype = Subtypes::DataEvsaEntry;
|
||||||
|
}
|
||||||
|
// Unknown entry
|
||||||
|
else {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add correct offset to parsing data
|
||||||
|
pdata.offset = parentOffset + offset;
|
||||||
|
|
||||||
|
// Add tree item
|
||||||
|
model->addItem(Types::NvramEntryEvsa, subtype, name, QString(), info, header, body, FALSE, parsingDataToQByteArray(pdata), index);
|
||||||
|
|
||||||
|
// Move to next variable
|
||||||
|
offset += variableSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,14 +107,15 @@ private:
|
|||||||
STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff);
|
STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff);
|
||||||
|
|
||||||
// NVRAM parsing
|
// NVRAM parsing
|
||||||
STATUS parseNvarStorage(const QByteArray & data, const QModelIndex & index);
|
STATUS parseNvarStore(const QByteArray & data, const QModelIndex & index);
|
||||||
|
|
||||||
STATUS parseStorageArea(const QByteArray & data, const QModelIndex & index);
|
STATUS parseStoreArea(const QByteArray & data, const QModelIndex & index);
|
||||||
STATUS findNextStorage(const QModelIndex & index, const QByteArray & data, const UINT32 parentOffset, const UINT32 storageOffset, UINT32 & nextStorageOffset);
|
STATUS findNextStore(const QModelIndex & index, const QByteArray & data, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset);
|
||||||
STATUS getStorageSize(const QByteArray & data, const UINT32 storageOffset, UINT32 & storageSize);
|
STATUS getStoreSize(const QByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
|
||||||
STATUS parseStorageHeader(const QByteArray & storage, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
STATUS parseVssStorageBody(const QModelIndex & index);
|
STATUS parseVssStoreBody(const QModelIndex & index);
|
||||||
STATUS parseFsysStorageBody(const QModelIndex & index);
|
STATUS parseFsysStoreBody(const QModelIndex & index);
|
||||||
|
STATUS parseEvsaStoreBody(const QModelIndex & index);
|
||||||
|
|
||||||
// Message helper
|
// Message helper
|
||||||
void msg(const QString & message, const QModelIndex &index = QModelIndex());
|
void msg(const QString & message, const QModelIndex &index = QModelIndex());
|
||||||
|
@ -153,13 +153,13 @@ STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & foun
|
|||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return EFI_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
// Process child items
|
// Process child items
|
||||||
for (int i = 0; i < model->rowCount(index); i++) {
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
findFitRecursive(index.child(i, 0), found, fitOffset);
|
findFitRecursive(index.child(i, 0), found, fitOffset);
|
||||||
if (found.isValid())
|
if (found.isValid())
|
||||||
return EFI_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get parsing data for the current item
|
// Get parsing data for the current item
|
||||||
|
107
common/nvram.h
107
common/nvram.h
@ -20,11 +20,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "basetypes.h"
|
#include "basetypes.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Let's start with NVAR storage, as the most difficult one
|
// NVAR store
|
||||||
//
|
//
|
||||||
|
|
||||||
// CEF5B9A3-476D-497F-9FDC-E98143E0422C
|
// CEF5B9A3-476D-497F-9FDC-E98143E0422C
|
||||||
const QByteArray NVRAM_NVAR_STORAGE_FILE_GUID
|
const QByteArray NVRAM_NVAR_STORE_FILE_GUID
|
||||||
("\xA3\xB9\xF5\xCE\x6D\x47\x7F\x49\x9F\xDC\xE9\x81\x43\xE0\x42\x2C", 16);
|
("\xA3\xB9\xF5\xCE\x6D\x47\x7F\x49\x9F\xDC\xE9\x81\x43\xE0\x42\x2C", 16);
|
||||||
|
|
||||||
// 9221315B-30BB-46B5-813E-1B1BF4712BD3
|
// 9221315B-30BB-46B5-813E-1B1BF4712BD3
|
||||||
@ -65,13 +65,17 @@ typedef struct _NVAR_VARIABLE_HEADER {
|
|||||||
#define NVRAM_NVAR_VARIABLE_EXT_ATTRIB_TIME_BASED 0x20
|
#define NVRAM_NVAR_VARIABLE_EXT_ATTRIB_TIME_BASED 0x20
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next format is TianoCore VSS and it's variations
|
// TianoCore VSS and it's variations
|
||||||
//
|
//
|
||||||
|
|
||||||
// FFF12B8D-7696-4C8B-A985-2747075B4F50
|
// FFF12B8D-7696-4C8B-A985-2747075B4F50
|
||||||
const QByteArray NVRAM_VSS_STORAGE_VOLUME_GUID
|
const QByteArray NVRAM_VSS_STORE_VOLUME_GUID
|
||||||
("\x8D\x2B\xF1\xFF\x96\x76\x8B\x4C\xA9\x85\x27\x47\x07\x5B\x4F\x50", 16);
|
("\x8D\x2B\xF1\xFF\x96\x76\x8B\x4C\xA9\x85\x27\x47\x07\x5B\x4F\x50", 16);
|
||||||
|
|
||||||
|
// 00504624-8A59-4EEB-BD0F-6B36E96128E0
|
||||||
|
const QByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
|
||||||
|
("\x24\x46\x50\x00\x59\x8A\xEB\x4E\xBD\x0F\x6B\x36\xE9\x61\x28\xE0", 16);
|
||||||
|
|
||||||
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
|
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
|
||||||
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
|
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
|
||||||
#define NVRAM_APPLE_FSYS_STORE_SIGNATURE 0x73797346 // Fsys
|
#define NVRAM_APPLE_FSYS_STORE_SIGNATURE 0x73797346 // Fsys
|
||||||
@ -90,29 +94,13 @@ const QByteArray NVRAM_VSS_STORAGE_VOLUME_GUID
|
|||||||
// Variable store header
|
// Variable store header
|
||||||
typedef struct _VSS_VARIABLE_STORE_HEADER {
|
typedef struct _VSS_VARIABLE_STORE_HEADER {
|
||||||
UINT32 Signature; // $VSS signature
|
UINT32 Signature; // $VSS signature
|
||||||
UINT32 Size; // Size of variable storage, including storage header
|
UINT32 Size; // Size of variable store, including store header
|
||||||
UINT8 Format; // Storage format state
|
UINT8 Format; // Store format state
|
||||||
UINT8 State; // Storage health state
|
UINT8 State; // Store health state
|
||||||
UINT16 Unknown; // Used in Apple $SVS varstores
|
UINT16 Unknown; // Used in Apple $SVS varstores
|
||||||
UINT32 : 32;
|
UINT32 : 32;
|
||||||
} VSS_VARIABLE_STORE_HEADER;
|
} VSS_VARIABLE_STORE_HEADER;
|
||||||
|
|
||||||
// Apple Fsys store header
|
|
||||||
typedef struct _APPLE_FSYS_STORE_HEADER {
|
|
||||||
UINT32 Signature; // Fsys signature
|
|
||||||
UINT8 Unknown[5]; // Still unknown
|
|
||||||
UINT16 Size; // Size of variable storage
|
|
||||||
} APPLE_FSYS_STORE_HEADER;
|
|
||||||
|
|
||||||
// Apple Fsys variable format
|
|
||||||
// UINT8 NameLength;
|
|
||||||
// CHAR8 Name[];
|
|
||||||
// UINT16 DataLength;
|
|
||||||
// UINT8 Data[]
|
|
||||||
// Storage ends with a chunk named "EOF" without data
|
|
||||||
// All free bytes in storage are zeroed
|
|
||||||
// Has CRC32 of the whole store without checksum field at the end
|
|
||||||
|
|
||||||
// Normal variable header
|
// Normal variable header
|
||||||
typedef struct _VSS_VARIABLE_HEADER {
|
typedef struct _VSS_VARIABLE_HEADER {
|
||||||
UINT16 StartId; // Variable start marker AA55
|
UINT16 StartId; // Variable start marker AA55
|
||||||
@ -170,17 +158,84 @@ typedef struct _VSS_AUTH_VARIABLE_HEADER {
|
|||||||
// FDC region can be found in some VSS volumes
|
// FDC region can be found in some VSS volumes
|
||||||
// It has another VSS volume inside
|
// It has another VSS volume inside
|
||||||
// _FDC header structure
|
// _FDC header structure
|
||||||
|
#define NVRAM_FDC_VOLUME_SIGNATURE 0x4344465F
|
||||||
|
|
||||||
typedef struct _FDC_VOLUME_HEADER {
|
typedef struct _FDC_VOLUME_HEADER {
|
||||||
UINT32 Signature;
|
UINT32 Signature; //_FDC
|
||||||
UINT32 Size;
|
UINT32 Size;
|
||||||
//EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
|
//EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
|
||||||
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2];
|
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2];
|
||||||
//VSS_VARIABLE_STORE_HEADER VssHeader;
|
//VSS_VARIABLE_STORE_HEADER VssHeader;
|
||||||
} FDC_VOLUME_HEADER;
|
} FDC_VOLUME_HEADER;
|
||||||
|
|
||||||
#define NVRAM_FDC_VOLUME_SIGNATURE 0x4344465F
|
//
|
||||||
|
// Apple Fsys
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _APPLE_FSYS_STORE_HEADER {
|
||||||
|
UINT32 Signature; // Fsys signature
|
||||||
|
UINT8 Unknown[5]; // Still unknown
|
||||||
|
UINT16 Size; // Size of variable store
|
||||||
|
} APPLE_FSYS_STORE_HEADER;
|
||||||
|
|
||||||
|
// Apple Fsys variable format
|
||||||
|
// UINT8 NameLength;
|
||||||
|
// CHAR8 Name[];
|
||||||
|
// UINT16 DataLength;
|
||||||
|
// UINT8 Data[]
|
||||||
|
// Store ends with a chunk named "EOF" without data
|
||||||
|
// All free bytes in store are zeroed
|
||||||
|
// Has CRC32 of the whole store without checksum field at the end
|
||||||
|
|
||||||
|
//
|
||||||
|
// EVSA
|
||||||
|
//
|
||||||
|
|
||||||
|
#define NVRAM_EVSA_STORE_SIGNATURE 0x41535645
|
||||||
|
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_STORE 0xEC
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_GUID1 0xED
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_GUID2 0xE1
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_NAME1 0xEE
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_NAME2 0xE2
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_DATA1 0xEF
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_DATA2 0xE3
|
||||||
|
#define NVRAM_EVSA_ENTRY_TYPE_DATA3 0x83
|
||||||
|
|
||||||
|
typedef struct _EVSA_ENTRY_HEADER {
|
||||||
|
UINT8 Type;
|
||||||
|
UINT8 Checksum;
|
||||||
|
UINT16 Size;
|
||||||
|
} EVSA_ENTRY_HEADER;
|
||||||
|
|
||||||
|
typedef struct _EVSA_STORE_ENTRY {
|
||||||
|
EVSA_ENTRY_HEADER Header;
|
||||||
|
UINT32 Signature; // EVSA
|
||||||
|
UINT32 Attributes;
|
||||||
|
UINT32 StoreSize;
|
||||||
|
UINT32 : 32;
|
||||||
|
} EVSA_STORE_ENTRY;
|
||||||
|
|
||||||
|
typedef struct _EVSA_GUID_ENTRY {
|
||||||
|
EVSA_ENTRY_HEADER Header;
|
||||||
|
UINT16 GuidId;
|
||||||
|
EFI_GUID Guid;
|
||||||
|
} EVSA_GUID_ENTRY;
|
||||||
|
|
||||||
|
typedef struct _EVSA_NAME_ENTRY {
|
||||||
|
EVSA_ENTRY_HEADER Header;
|
||||||
|
UINT16 VarId;
|
||||||
|
//CHAR16 Name[];
|
||||||
|
} EVSA_NAME_ENTRY;
|
||||||
|
|
||||||
|
typedef struct _EVSA_DATA_ENTRY {
|
||||||
|
EVSA_ENTRY_HEADER Header;
|
||||||
|
UINT16 GuidId;
|
||||||
|
UINT16 VarId;
|
||||||
|
UINT32 Attributes;
|
||||||
|
//UINT8 Data[];
|
||||||
|
} EVSA_DATA_ENTRY;
|
||||||
|
|
||||||
// Restore previous packing rules
|
// Restore previous packing rules
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,7 +51,7 @@ typedef struct _FILE_PARSING_DATA {
|
|||||||
} FILE_PARSING_DATA;
|
} FILE_PARSING_DATA;
|
||||||
|
|
||||||
#define RAW_FILE_FORMAT_UNKNOWN 0
|
#define RAW_FILE_FORMAT_UNKNOWN 0
|
||||||
#define RAW_FILE_FORMAT_NVAR_STORAGE 1
|
#define RAW_FILE_FORMAT_NVAR_STORE 1
|
||||||
|
|
||||||
typedef struct _COMPRESSED_SECTION_PARSING_DATA {
|
typedef struct _COMPRESSED_SECTION_PARSING_DATA {
|
||||||
UINT32 uncompressedSize;
|
UINT32 uncompressedSize;
|
||||||
|
@ -65,18 +65,22 @@ QString itemTypeToQString(const UINT8 type)
|
|||||||
return QObject::tr("Section");
|
return QObject::tr("Section");
|
||||||
case Types::FreeSpace:
|
case Types::FreeSpace:
|
||||||
return QObject::tr("Free space");
|
return QObject::tr("Free space");
|
||||||
|
case Types::NvramStoreVss:
|
||||||
|
return QObject::tr("VSS store");
|
||||||
|
case Types::NvramStoreFdc:
|
||||||
|
return QObject::tr("FDC store");
|
||||||
|
case Types::NvramStoreFsys:
|
||||||
|
return QObject::tr("Fsys store");
|
||||||
|
case Types::NvramStoreEvsa:
|
||||||
|
return QObject::tr("EVSA store");
|
||||||
case Types::NvramVariableNvar:
|
case Types::NvramVariableNvar:
|
||||||
return QObject::tr("NVAR variable");
|
return QObject::tr("NVAR variable");
|
||||||
case Types::NvramStorageVss:
|
|
||||||
return QObject::tr("VSS storage");
|
|
||||||
case Types::NvramStorageFdc:
|
|
||||||
return QObject::tr("FDC storage");
|
|
||||||
case Types::NvramStorageFsys:
|
|
||||||
return QObject::tr("Fsys storage");
|
|
||||||
case Types::NvramVariableVss:
|
case Types::NvramVariableVss:
|
||||||
return QObject::tr("VSS variable");
|
return QObject::tr("VSS variable");
|
||||||
case Types::NvramVariableFsys:
|
case Types::NvramVariableFsys:
|
||||||
return QObject::tr("Fsys variable");
|
return QObject::tr("Fsys variable");
|
||||||
|
case Types::NvramEntryEvsa:
|
||||||
|
return QObject::tr("EVSA entry");
|
||||||
default:
|
default:
|
||||||
return QObject::tr("Unknown");
|
return QObject::tr("Unknown");
|
||||||
}
|
}
|
||||||
@ -109,8 +113,8 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
|||||||
return QObject::tr("FFSv2");
|
return QObject::tr("FFSv2");
|
||||||
else if (subtype == Subtypes::Ffs3Volume)
|
else if (subtype == Subtypes::Ffs3Volume)
|
||||||
return QObject::tr("FFSv3");
|
return QObject::tr("FFSv3");
|
||||||
else if (subtype == Subtypes::VssNvramVolume)
|
else if (subtype == Subtypes::NvramVolume)
|
||||||
return QObject::tr("VSS NVRAM");
|
return QObject::tr("NVRAM");
|
||||||
else
|
else
|
||||||
return QObject::tr("Unknown subtype");
|
return QObject::tr("Unknown subtype");
|
||||||
case Types::Capsule:
|
case Types::Capsule:
|
||||||
@ -132,35 +136,49 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
|||||||
return sectionTypeToQString(subtype);
|
return sectionTypeToQString(subtype);
|
||||||
case Types::FreeSpace:
|
case Types::FreeSpace:
|
||||||
return QString();
|
return QString();
|
||||||
|
case Types::NvramStoreVss:
|
||||||
|
case Types::NvramStoreFdc:
|
||||||
|
case Types::NvramStoreFsys:
|
||||||
|
case Types::NvramStoreEvsa:
|
||||||
|
case Types::NvramVariableFsys:
|
||||||
|
return QString();
|
||||||
case Types::NvramVariableNvar:
|
case Types::NvramVariableNvar:
|
||||||
if (subtype == Subtypes::InvalidNvar)
|
if (subtype == Subtypes::InvalidNvarVariable)
|
||||||
return QObject::tr("Invalid");
|
return QObject::tr("Invalid");
|
||||||
if (subtype == Subtypes::InvalidLinkNvar)
|
if (subtype == Subtypes::InvalidLinkNvarVariable)
|
||||||
return QObject::tr("Invalid link");
|
return QObject::tr("Invalid link");
|
||||||
if (subtype == Subtypes::LinkNvar)
|
if (subtype == Subtypes::LinkNvarVariable)
|
||||||
return QObject::tr("Link");
|
return QObject::tr("Link");
|
||||||
if (subtype == Subtypes::DataNvar)
|
if (subtype == Subtypes::DataNvarVariable)
|
||||||
return QObject::tr("Data");
|
return QObject::tr("Data");
|
||||||
if (subtype == Subtypes::FullNvar)
|
if (subtype == Subtypes::FullNvarVariable)
|
||||||
return QObject::tr("Full");
|
return QObject::tr("Full");
|
||||||
else
|
else
|
||||||
return QObject::tr("Unknown subtype");
|
return QObject::tr("Unknown subtype");
|
||||||
case Types::NvramStorageVss:
|
|
||||||
case Types::NvramStorageFdc:
|
|
||||||
case Types::NvramStorageFsys:
|
|
||||||
case Types::NvramVariableFsys:
|
|
||||||
return QString();
|
|
||||||
case Types::NvramVariableVss:
|
case Types::NvramVariableVss:
|
||||||
if (subtype == Subtypes::InvalidVss)
|
if (subtype == Subtypes::InvalidVssVariable)
|
||||||
return QObject::tr("Invalid");
|
return QObject::tr("Invalid");
|
||||||
if (subtype == Subtypes::StandardVss)
|
if (subtype == Subtypes::StandardVssVariable)
|
||||||
return QObject::tr("Standard");
|
return QObject::tr("Standard");
|
||||||
if (subtype == Subtypes::AppleCrc32Vss)
|
if (subtype == Subtypes::Crc32VssVariable)
|
||||||
return QObject::tr("Apple CRC32");
|
return QObject::tr("Apple CRC32");
|
||||||
if (subtype == Subtypes::AuthVss)
|
if (subtype == Subtypes::AuthVssVariable)
|
||||||
return QObject::tr("Auth");
|
return QObject::tr("Auth");
|
||||||
else
|
else
|
||||||
return QObject::tr("Unknown subtype");
|
return QObject::tr("Unknown subtype");
|
||||||
|
case Types::NvramEntryEvsa:
|
||||||
|
if (subtype == Subtypes::InvalidEvsaEntry)
|
||||||
|
return QObject::tr("Invalid");
|
||||||
|
if (subtype == Subtypes::UnknownEvsaEntry)
|
||||||
|
return QObject::tr("Unknown");
|
||||||
|
if (subtype == Subtypes::GuidEvsaEntry)
|
||||||
|
return QObject::tr("GUID");
|
||||||
|
if (subtype == Subtypes::NameEvsaEntry)
|
||||||
|
return QObject::tr("Name");
|
||||||
|
if (subtype == Subtypes::DataEvsaEntry)
|
||||||
|
return QObject::tr("Data");
|
||||||
|
else
|
||||||
|
return QObject::tr("Unknown subtype");
|
||||||
default:
|
default:
|
||||||
return QObject::tr("Unknown subtype");
|
return QObject::tr("Unknown subtype");
|
||||||
}
|
}
|
||||||
|
@ -43,33 +43,35 @@ namespace Types {
|
|||||||
File,
|
File,
|
||||||
Section,
|
Section,
|
||||||
FreeSpace,
|
FreeSpace,
|
||||||
|
NvramStoreVss,
|
||||||
|
NvramStoreFdc,
|
||||||
|
NvramStoreFsys,
|
||||||
|
NvramStoreEvsa,
|
||||||
NvramVariableNvar,
|
NvramVariableNvar,
|
||||||
NvramStorageVss,
|
|
||||||
NvramStorageFdc,
|
|
||||||
NvramStorageFsys,
|
|
||||||
NvramVariableVss,
|
NvramVariableVss,
|
||||||
NvramVariableFsys
|
NvramVariableFsys,
|
||||||
|
NvramEntryEvsa
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Subtypes {
|
namespace Subtypes {
|
||||||
enum ImageSubtypes{
|
enum ImageSubtypes{
|
||||||
IntelImage = 70,
|
IntelImage = 90,
|
||||||
UefiImage
|
UefiImage
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CapsuleSubtypes {
|
enum CapsuleSubtypes {
|
||||||
AptioSignedCapsule = 80,
|
AptioSignedCapsule = 100,
|
||||||
AptioUnsignedCapsule,
|
AptioUnsignedCapsule,
|
||||||
UefiCapsule,
|
UefiCapsule,
|
||||||
ToshibaCapsule
|
ToshibaCapsule
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VolumeSubtypes {
|
enum VolumeSubtypes {
|
||||||
UnknownVolume = 90,
|
UnknownVolume = 110,
|
||||||
Ffs2Volume,
|
Ffs2Volume,
|
||||||
Ffs3Volume,
|
Ffs3Volume,
|
||||||
VssNvramVolume
|
NvramVolume
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RegionSubtypes {
|
enum RegionSubtypes {
|
||||||
@ -86,24 +88,32 @@ namespace Subtypes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum PaddingSubtypes {
|
enum PaddingSubtypes {
|
||||||
ZeroPadding = 110,
|
ZeroPadding = 120,
|
||||||
OnePadding,
|
OnePadding,
|
||||||
DataPadding
|
DataPadding
|
||||||
};
|
};
|
||||||
|
|
||||||
enum NvarVariableSubtypes {
|
enum NvarVariableSubtypes {
|
||||||
InvalidNvar = 120,
|
InvalidNvarVariable = 130,
|
||||||
InvalidLinkNvar,
|
InvalidLinkNvarVariable,
|
||||||
LinkNvar,
|
LinkNvarVariable,
|
||||||
DataNvar,
|
DataNvarVariable,
|
||||||
FullNvar
|
FullNvarVariable
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VssVariableSubtypes {
|
enum VssVariableSubtypes {
|
||||||
InvalidVss = 130,
|
InvalidVssVariable = 140,
|
||||||
StandardVss,
|
StandardVssVariable,
|
||||||
AppleCrc32Vss,
|
Crc32VssVariable,
|
||||||
AuthVss
|
AuthVssVariable
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EvsaVariableSubtypes {
|
||||||
|
InvalidEvsaEntry = 150,
|
||||||
|
UnknownEvsaEntry,
|
||||||
|
GuidEvsaEntry,
|
||||||
|
NameEvsaEntry,
|
||||||
|
DataEvsaEntry,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ QString errorCodeToQString(UINT8 errorCode)
|
|||||||
case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed");
|
case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed");
|
||||||
case ERR_TRUNCATED_IMAGE: return QObject::tr("Image is truncated");
|
case ERR_TRUNCATED_IMAGE: return QObject::tr("Image is truncated");
|
||||||
case ERR_INVALID_CAPSULE: return QObject::tr("Invalid capsule");
|
case ERR_INVALID_CAPSULE: return QObject::tr("Invalid capsule");
|
||||||
case ERR_STORAGES_NOT_FOUND: return QObject::tr("Storages not found");
|
case ERR_STORES_NOT_FOUND: return QObject::tr("Stores not found");
|
||||||
default: return QObject::tr("Unknown error %1").arg(errorCode);
|
default: return QObject::tr("Unknown error %1").arg(errorCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user