Skip to content

Commit b83c55b

Browse files
committed
Add checks for FFS file and section alignment bytes
1 parent 19a4dab commit b83c55b

7 files changed

Lines changed: 108 additions & 14 deletions

File tree

UEFIExtract/uefidump.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
9999

100100
if (!nameFound) {
101101
printf("Cannot find unique name for \"%s\".\n", (const char*)orgName.toLocal8Bit());
102-
return U_INVALID_PARAMETER; //TODO: replace with proper errorCode
102+
return U_ITEM_NOT_FOUND;
103103
}
104104

105105
// Add header and body only for leaf sections

common/ffsbuilder.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,6 @@ USTATUS FfsBuilder::buildNonUefiData(const UModelIndex & index, UByteArray & dat
364364
return erase(index, data);
365365
}
366366

367-
// TODO: rebuild properly
368-
369367
msg(UString("buildNoUefiData: unexpected action " + actionTypeToUString(model->action(index))), index);
370368
return U_NOT_IMPLEMENTED;
371369
}

common/ffsparser.cpp

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,8 +1432,8 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
14321432
// Check for AppleCRC32 and UsedSpace in ZeroVector
14331433
bool hasAppleCrc32 = false;
14341434
UINT32 volumeSize = (UINT32)volume.size();
1435-
UINT32 appleCrc32 = *(UINT32*)(volume.constData() + 8);
1436-
UINT32 usedSpace = *(UINT32*)(volume.constData() + 12);
1435+
UINT32 appleCrc32 = readUnaligned((UINT32*)(volume.constData() + 8));
1436+
UINT32 usedSpace = readUnaligned((UINT32*)(volume.constData() + 12));
14371437
if (appleCrc32 != 0) {
14381438
// Calculate CRC32 of the volume body
14391439
UINT32 crc = (UINT32)crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
@@ -2031,7 +2031,37 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index, const bool probe)
20312031

20322032
// Move to next file
20332033
fileOffset += fileSize;
2034-
// TODO: check that alignment bytes are all of erase polarity bit, warn if not so
2034+
2035+
// Check for alignment bytes after the current file
2036+
// Files must be aligned to 8 bytes boundary inside the FFS volume
2037+
// The alignment byte should be equal to 0xFF (erasePolarity = 1) or 0x00 (erasePolarity = 0)
2038+
UINT32 numAlignmentBytes = ALIGN8(fileOffset) - fileOffset;
2039+
2040+
// We might be at the very end of the volume, need a check for it
2041+
if (volumeBodySize < fileOffset + fileSize + numAlignmentBytes) {
2042+
numAlignmentBytes = volumeBodySize - fileOffset - fileSize;
2043+
}
2044+
2045+
if (numAlignmentBytes > 0) {
2046+
UByteArray alignmentBytes = volumeBody.mid(fileOffset + fileSize, numAlignmentBytes);
2047+
// Check alignment bytes to be sane
2048+
if (!isUniformByte(alignmentBytes, emptyByte)) {
2049+
msg(usprintf("%s: unexpected bytes found in alignment area, should all be %s", __FUNCTION__, emptyByte ? "0xFF" : "0x00"), fileIndex);
2050+
2051+
// Add unexpected alignment bytes to tree item info
2052+
UString info;
2053+
for (UINT8 i = 0; i < numAlignmentBytes; i++) {
2054+
info += usprintf("%02X ", alignmentBytes[i]);
2055+
}
2056+
info = UString("Alignment bytes: ") + info + "\n";
2057+
model->addInfo(fileIndex, info);
2058+
}
2059+
2060+
// Store alignment bytes for upholding parsing pre/post-conditions (aka "every byte is accounted for")
2061+
model->setAlignmentBytes(fileIndex, alignmentBytes);
2062+
}
2063+
2064+
// Adjust fileOffset
20352065
fileOffset = ALIGN8(fileOffset);
20362066
}
20372067

@@ -2505,8 +2535,8 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
25052535
return U_INVALID_PARAMETER;
25062536

25072537
// Search for and parse all sections
2508-
UINT32 bodySize = (UINT32)sections.size();
2509-
UINT32 headerSize = model->headerSize(index);
2538+
UINT32 fileBodySize = (UINT32)sections.size();
2539+
UINT32 fileHeaderSize = model->headerSize(index);
25102540
UINT32 sectionOffset = 0;
25112541
USTATUS result = U_SUCCESS;
25122542

@@ -2521,20 +2551,20 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
25212551

25222552
// Iterate over sections
25232553
UINT32 sectionSize = 0;
2524-
while (sectionOffset < bodySize) {
2554+
while (sectionOffset < fileBodySize) {
25252555
// Get section size
25262556
sectionSize = getSectionSize(sections, sectionOffset, ffsVersion);
25272557

25282558
// Check section size to be sane
25292559
if (sectionSize < sizeof(EFI_COMMON_SECTION_HEADER)
2530-
|| sectionSize > (bodySize - sectionOffset)) {
2560+
|| sectionSize > (fileBodySize - sectionOffset)) {
25312561
// Final parsing
25322562
if (!probe) {
25332563
// Add padding to fill the rest of sections
25342564
UByteArray padding = sections.mid(sectionOffset);
25352565

25362566
// Add tree item
2537-
UModelIndex dataIndex = model->addItem(headerSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), UString(), UByteArray(), padding, UByteArray(), Fixed, index);
2567+
UModelIndex dataIndex = model->addItem(fileHeaderSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), UString(), UByteArray(), padding, UByteArray(), Fixed, index);
25382568

25392569
// Show message
25402570
msg(usprintf("%s: non-UEFI data found in sections area", __FUNCTION__), dataIndex);
@@ -2550,7 +2580,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
25502580

25512581
// Parse section header
25522582
UModelIndex sectionIndex;
2553-
result = parseSectionHeader(sections.mid(sectionOffset, sectionSize), headerSize + sectionOffset, index, sectionIndex, probe);
2583+
result = parseSectionHeader(sections.mid(sectionOffset, sectionSize), fileHeaderSize + sectionOffset, index, sectionIndex, probe);
25542584
if (result) {
25552585
if (!probe)
25562586
msg(usprintf("%s: section header parsing failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
@@ -2560,7 +2590,37 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
25602590

25612591
// Move to next section
25622592
sectionOffset += sectionSize;
2563-
// TODO: verify that alignment bytes are actually zero as per PI spec
2593+
2594+
// Check for alignment bytes after the current section
2595+
// Sections must be aligned to 4 bytes boundary inside the FFS file
2596+
// The alignment byte should be equal to 0x00 regardless of erasePolarity
2597+
UINT32 numAlignmentBytes = ALIGN4(sectionOffset) - sectionOffset;
2598+
2599+
// We might be at the very end of the file, need a check for it
2600+
if (fileBodySize < sectionOffset + sectionSize + numAlignmentBytes) {
2601+
numAlignmentBytes = fileBodySize - sectionOffset - sectionSize;
2602+
}
2603+
2604+
if (numAlignmentBytes > 0) {
2605+
UByteArray alignmentBytes = sections.mid(sectionOffset + sectionSize, numAlignmentBytes);
2606+
// Check alignment bytes to be sane
2607+
if (!isUniformByte(alignmentBytes, 0x00)) {
2608+
msg(usprintf("%s: unexpected bytes found in alignment area, should all be 0x00", __FUNCTION__), sectionIndex);
2609+
2610+
// Add unexpected alignment bytes to tree item info
2611+
UString info;
2612+
for (UINT8 i = 0; i < numAlignmentBytes; i++) {
2613+
info += usprintf("%02X ", alignmentBytes[i]);
2614+
}
2615+
info = UString("Alignment bytes: ") + info + "\n";
2616+
model->addInfo(sectionIndex, info);
2617+
}
2618+
2619+
// Store alignment bytes for upholding parsing pre/post-conditions (aka "every byte is accounted for")
2620+
model->setAlignmentBytes(sectionIndex, alignmentBytes);
2621+
}
2622+
2623+
// Adjust sectionOffset
25642624
sectionOffset = ALIGN4(sectionOffset);
25652625
}
25662626

common/treeitem.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ class TreeItem
9696
bool hasEmptyUncompressedData() const { return itemUncompressedData.isEmpty(); }
9797
void setUncompressedData(const UByteArray & ucdata) { itemUncompressedData = ucdata; }
9898

99+
UByteArray alignmentBytes() const { return itemAlignmentBytes; };
100+
bool hasEmptyAlignmentBytes() const { return itemAlignmentBytes.isEmpty(); }
101+
void setAlignmentBytes(const UByteArray & abytes) { itemAlignmentBytes = abytes; }
102+
99103
UINT8 marking() const { return itemMarking; }
100104
void setMarking(const UINT8 marking) { itemMarking = marking; }
101105

@@ -116,6 +120,7 @@ class TreeItem
116120
bool itemCompressed;
117121
UByteArray itemParsingData;
118122
UByteArray itemUncompressedData;
123+
UByteArray itemAlignmentBytes;
119124
TreeItem* parentItem;
120125
};
121126

common/treemodel.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,34 @@ void TreeModel::setParsingData(const UModelIndex &index, const UByteArray &data)
511511
emit dataChanged(this->index(0, 0), index);
512512
}
513513

514+
UByteArray TreeModel::alignmentBytes(const UModelIndex &index) const
515+
{
516+
if (!index.isValid())
517+
return UByteArray();
518+
519+
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
520+
return item->alignmentBytes();
521+
}
522+
523+
bool TreeModel::hasEmptyAlignmentBytes(const UModelIndex &index) const
524+
{
525+
if (!index.isValid())
526+
return true;
527+
528+
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
529+
return item->hasEmptyAlignmentBytes();
530+
}
531+
532+
void TreeModel::setAlignmentBytes(const UModelIndex &index, const UByteArray &data)
533+
{
534+
if (!index.isValid())
535+
return;
536+
537+
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
538+
item->setAlignmentBytes(data);
539+
emit dataChanged(this->index(0, 0), index);
540+
}
541+
514542
UByteArray TreeModel::uncompressedData(const UModelIndex &index) const
515543
{
516544
if (!index.isValid())

common/treemodel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ class TreeModel
208208
bool hasEmptyParsingData(const UModelIndex &index) const;
209209
void setParsingData(const UModelIndex &index, const UByteArray &pdata);
210210

211+
UByteArray alignmentBytes(const UModelIndex &index) const;
212+
bool hasEmptyAlignmentBytes(const UModelIndex &index) const;
213+
void setAlignmentBytes(const UModelIndex &index, const UByteArray &abytes);
214+
211215
UModelIndex addItem(const UINT32 offset, const UINT8 type, const UINT8 subtype,
212216
const UString & name, const UString & text, const UString & info,
213217
const UByteArray & header, const UByteArray & body, const UByteArray & tail,

common/utility.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ void fixFileName(UString &name, bool replaceSpaces)
147147
// Returns text representation of error code
148148
UString errorCodeToUString(USTATUS errorCode)
149149
{
150-
// TODO: improve
151150
switch (errorCode) {
152151
case U_SUCCESS: return UString("Success");
153152
case U_NOT_IMPLEMENTED: return UString("Not implemented");

0 commit comments

Comments
 (0)