1
0
Fork 0
mirror of https://github.com/LongSoft/UEFITool.git synced 2025-05-19 17:55:20 -04:00

Version 0.18.9

- padding types changed to Empty and NonEmpty
- added apriori files detection and parsing
- added depex sections parsing
This commit is contained in:
Nikolaj Schlej 2014-11-02 11:27:54 +01:00
parent db2ef69901
commit 28b985b1f1
6 changed files with 235 additions and 22 deletions

View file

@ -162,6 +162,9 @@ QString errorMessage(UINT8 errorCode)
case ERR_NOTHING_TO_PATCH:
msg = QObject::tr("Nothing to patch");
break;
case ERR_DEPEX_PARSE_FAILED:
msg = QObject::tr("Dependency expression parsing failed");
break;
default:
msg = QObject::tr("Unknown error %1").arg(errorCode);
break;
@ -621,7 +624,7 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, con
// Parse PDR region as BIOS space
UINT8 result = parseBios(pdr, index);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
return result;
return ERR_SUCCESS;
@ -969,7 +972,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
// Parse file
QModelIndex fileIndex;
result = parseFile(file, fileIndex, empty == '\xFF' ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
msg(tr("parseVolume: FFS file parsing failed with error \"%1\"").arg(errorMessage(result)), index);
// Show messages
@ -1144,7 +1147,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U
UINT8 result;
if (parseAsBios) {
result = parseBios(body, index);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
msg(tr("parseFile: Parsing file as BIOS failed with error \"%1\"").arg(errorMessage(result)), index);
return result;
}
@ -1196,6 +1199,112 @@ UINT8 FfsEngine::parseSections(const QByteArray & body, const QModelIndex & pare
return ERR_SUCCESS;
}
void FfsEngine::parseAprioriRawSection(const QByteArray & body, QString & parsed)
{
parsed.clear();
UINT32 count = body.size() / sizeof(EFI_GUID);
if (count > 0) {
for (UINT32 i = 0; i < count; i++) {
EFI_GUID* guid = (EFI_GUID*)body.data() + i;
parsed += tr("\n%1").arg(guidToQString(*guid));
}
}
}
UINT8 FfsEngine::parseDepexSection(const QByteArray & body, QString & parsed)
{
parsed.clear();
// Check data to be present
if (!body.size())
return ERR_INVALID_PARAMETER;
EFI_GUID * guid;
UINT8* current = (UINT8*)body.data();
// Special cases of first opcode
switch (*current) {
case EFI_DEP_BEFORE:
if (body.size() != 2*EFI_DEP_OPCODE_SIZE + sizeof(EFI_GUID))
return ERR_DEPEX_PARSE_FAILED;
guid = (EFI_GUID*)(current + EFI_DEP_OPCODE_SIZE);
parsed += tr("\nBEFORE %1").arg(guidToQString(*guid));
current += EFI_DEP_OPCODE_SIZE + sizeof(EFI_GUID);
if (*current != EFI_DEP_END)
return ERR_DEPEX_PARSE_FAILED;
return ERR_SUCCESS;
case EFI_DEP_AFTER:
if (body.size() != 2 * EFI_DEP_OPCODE_SIZE + sizeof(EFI_GUID))
return ERR_DEPEX_PARSE_FAILED;
guid = (EFI_GUID*)(current + EFI_DEP_OPCODE_SIZE);
parsed += tr("\nAFTER %1").arg(guidToQString(*guid));
current += EFI_DEP_OPCODE_SIZE + sizeof(EFI_GUID);
if (*current != EFI_DEP_END)
return ERR_DEPEX_PARSE_FAILED;
return ERR_SUCCESS;
case EFI_DEP_SOR:
if (body.size() <= 2 * EFI_DEP_OPCODE_SIZE) {
return ERR_DEPEX_PARSE_FAILED;
}
parsed += tr("\nSOR");
current += EFI_DEP_OPCODE_SIZE;
break;
default:
break;
}
// Parse the rest of depex
while (current - (UINT8*)body.data() < body.size()) {
switch (*current) {
case EFI_DEP_BEFORE:
case EFI_DEP_AFTER:
case EFI_DEP_SOR:
return ERR_DEPEX_PARSE_FAILED;
case EFI_DEP_PUSH:
// Check that the rest of depex has correct size
if (body.size() - (current - (UINT8*)body.data()) <= EFI_DEP_OPCODE_SIZE + sizeof(EFI_GUID)) {
parsed.clear();
return ERR_DEPEX_PARSE_FAILED;
}
guid = (EFI_GUID*)(current + EFI_DEP_OPCODE_SIZE);
parsed += tr("\nPUSH %1").arg(guidToQString(*guid));
current += EFI_DEP_OPCODE_SIZE + sizeof(EFI_GUID);
break;
case EFI_DEP_AND:
parsed += tr("\nAND");
current += EFI_DEP_OPCODE_SIZE;
break;
case EFI_DEP_OR:
parsed += tr("\nOR");
current += EFI_DEP_OPCODE_SIZE;
break;
case EFI_DEP_NOT:
parsed += tr("\nNOT");
current += EFI_DEP_OPCODE_SIZE;
break;
case EFI_DEP_TRUE:
parsed += tr("\nTRUE");
current += EFI_DEP_OPCODE_SIZE;
break;
case EFI_DEP_FALSE:
parsed += tr("\nFALSE");
current += EFI_DEP_OPCODE_SIZE;
break;
case EFI_DEP_END:
parsed += tr("\nEND");
current += EFI_DEP_OPCODE_SIZE;
// Check that END is the last opcode
if (current - (UINT8*)body.data() < body.size()) {
parsed.clear();
return ERR_DEPEX_PARSE_FAILED;
}
break;
}
}
return ERR_SUCCESS;
}
UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
{
EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*)(section.constData());
@ -1372,13 +1481,40 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
return result;
}
break;
// Leaf sections
// Leaf sections
case EFI_SECTION_DXE_DEPEX:
case EFI_SECTION_PEI_DEPEX:
case EFI_SECTION_SMM_DEPEX: {
bool msgDepexParseFailed = false;
headerSize = sizeOfSectionHeader(sectionHeader);
header = section.left(headerSize);
body = section.mid(headerSize, sectionSize - headerSize);
// Get info
info = tr("Type: 0x%1\nSize: 0x%2")
.arg(sectionHeader->Type, 2, 16, QChar('0'))
.arg(body.size(), 6, 16, QChar('0'));
// Parse dependency expression
QString str;
result = parseDepexSection(body, str);
if (result)
msgDepexParseFailed = true;
else if (str.count())
info += tr("\nParsed expression:%1").arg(str);
// Add tree item
index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
// Show messages
if (msgDepexParseFailed)
msg(tr("parseSection: dependency expression parsing failed"), index);
}
break;
case EFI_SECTION_PE32:
case EFI_SECTION_TE:
case EFI_SECTION_PIC:
case EFI_SECTION_DXE_DEPEX:
case EFI_SECTION_PEI_DEPEX:
case EFI_SECTION_SMM_DEPEX:
case EFI_SECTION_COMPATIBILITY16: {
headerSize = sizeOfSectionHeader(sectionHeader);
header = section.left(headerSize);
@ -1466,13 +1602,14 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
// Parse section body as BIOS space
result = parseBios(body, index);
if (result && result != ERR_VOLUMES_NOT_FOUND) {
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) {
msg(tr("parseSection: Parsing firmware volume image section as BIOS failed with error \"%1\"").arg(errorMessage(result)), index);
return result;
}
}
break;
case EFI_SECTION_RAW: {
bool parsed = false;
header = section.left(sizeof(EFI_RAW_SECTION));
body = section.mid(sizeof(EFI_RAW_SECTION), sectionSize - sizeof(EFI_RAW_SECTION));
@ -1481,14 +1618,46 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
.arg(sectionHeader->Type, 2, 16, QChar('0'))
.arg(body.size(), 6, 16, QChar('0'));
// Check for apriori file
QModelIndex parentFile = model->findParentOfType(parent, Types::File);
QByteArray parentFileGuid = model->header(parentFile).left(sizeof(EFI_GUID));
if (parentFileGuid == EFI_PEI_APRIORI_FILE_GUID) {
// Mark file as parsed
parsed = true;
// Parse apriori file list
QString str;
parseAprioriRawSection(body, str);
if (str.count())
info += tr("\nFile list:%1").arg(str);
// Rename parent file
model->setTextString(parentFile, tr("PEI apriori file"));
}
else if (parentFileGuid == EFI_DXE_APRIORI_FILE_GUID) {
// Mark file as parsed
parsed = true;
// Parse apriori file list
QString str;
parseAprioriRawSection(body, str);
if (str.count())
info += tr("\nFile list:%1").arg(str);
// Rename parent file
model->setTextString(parentFile, tr("DXE apriori file"));
}
// Add tree item
index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
// Parse section body as BIOS space
result = parseBios(body, index);
if (result && result != ERR_VOLUMES_NOT_FOUND) {
msg(tr("parseSection: Parsing raw section as BIOS failed with error \"%1\"").arg(errorMessage(result)), index);
return result;
if (!parsed) {
result = parseBios(body, index);
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) {
msg(tr("parseSection: Parsing raw section as BIOS failed with error \"%1\"").arg(errorMessage(result)), index);
return result;
}
}
}
break;
@ -1543,7 +1712,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
return ERR_NOT_IMPLEMENTED;
}
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
return result;
// Set action
@ -1601,7 +1770,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Parse file
result = parseFile(created, fileIndex, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
return result;
// Set action
@ -1652,7 +1821,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Parse section
QModelIndex sectionIndex;
result = parseSection(created, sectionIndex, index, mode);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
return result;
// Set create action
@ -1678,7 +1847,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Parse section
QModelIndex sectionIndex;
result = parseSection(created, sectionIndex, index, mode);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
return result;
// Set create action
@ -1698,7 +1867,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
// Parse section
QModelIndex sectionIndex;
result = parseSection(created, sectionIndex, index, mode);
if (result && result != ERR_VOLUMES_NOT_FOUND)
if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME)
return result;
// Set create action