Display microcode in the tree

This commit is contained in:
vit9696 2018-09-01 08:17:17 +03:00
parent 717821de2b
commit 2d02eeab6d
21 changed files with 369 additions and 8270 deletions

3
.gitignore vendored
View File

@ -3,6 +3,7 @@
#################
moc_*.*
ui_*.*
qrc_*.*
#################
## Qt Creator
@ -234,6 +235,8 @@ Makefile
uefitool_plugin_import.cpp
UEFITool.app/
UEFITool/Info.plist
UEFITool/XCBuildData
UEFIDump/UEFIDump
UEFIExtract/UEFIExtract
UEFIFind/UEFIFind

View File

@ -1,6 +1,6 @@
/* ffsdumper.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at

View File

@ -1,6 +1,6 @@
/* uefidump.h
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at

0
UEFITool/ffsfinder.cpp Normal file → Executable file
View File

0
UEFITool/ffsfinder.h Normal file → Executable file
View File

View File

@ -112,7 +112,7 @@ int QHexEdit::addressWidth()
if (size > Q_INT64_C(0x100000000)){ n += 8; size /= Q_INT64_C(0x100000000);}
if (size > 0x10000){ n += 4; size /= 0x10000;}
if (size > 0x100){ n += 2; size /= 0x100;}
if (size > 0x10){ n += 1; size /= 0x10;}
if (size > 0x10){ n += 1; }
if (n > _addressWidth)
return n;

File diff suppressed because it is too large Load Diff

View File

@ -114,7 +114,6 @@ void UEFITool::init()
ui->infoEdit->clear();
ui->bootGuardEdit->clear();
ui->txtEdit->clear();
ui->microcodeEdit->clear();
ui->messagesTabWidget->setTabEnabled(1, false);
ui->messagesTabWidget->setTabEnabled(2, false);
ui->messagesTabWidget->setTabEnabled(3, false);
@ -201,7 +200,8 @@ void UEFITool::populateUi(const UModelIndex &current)
ui->menuVolumeActions->setEnabled(type == Types::Volume);
ui->menuFileActions->setEnabled(type == Types::File);
ui->menuSectionActions->setEnabled(type == Types::Section);
ui->menuEntryActions->setEnabled(type == Types::NvarEntry
ui->menuEntryActions->setEnabled(type == Types::Microcode
|| type == Types::NvarEntry
|| type == Types::VssEntry
|| type == Types::FsysEntry
|| type == Types::EvsaEntry
@ -214,8 +214,8 @@ void UEFITool::populateUi(const UModelIndex &current)
|| type == Types::FtwStore
|| type == Types::FlashMapStore
|| type == Types::CmdbStore
|| type == Types::Microcode
|| type == Types::SlicData);
|| type == Types::SlicData
);
// Enable actions
ui->actionHexView->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
@ -700,18 +700,6 @@ void UEFITool::extract(const UINT8 mode, UString* pathOut)
|| subtype == EFI_SECTION_PIC) path = QFileDialog::getSaveFileName(this, tr("Save section body to EFI executable file"), name + ".efi", tr("EFI executable files (*.efi *.bin);;All files (*)"));
else path = QFileDialog::getSaveFileName(this, tr("Save section body to file"), name + ".bin", tr("Binary files (*.bin);;All files (*)"));
break;
case Types::NvarEntry:
case Types::VssEntry:
case Types::EvsaEntry:
case Types::FlashMapEntry:
case Types::FsysEntry: path = QFileDialog::getSaveFileName(this, tr("Save entry body to file"), name + ".bin", tr("Binary files (*.bin);;All files (*)")); break;
case Types::VssStore:
case Types::Vss2Store:
case Types::FtwStore:
case Types::FdcStore:
case Types::FsysStore:
case Types::FlashMapStore:
case Types::CmdbStore: path = QFileDialog::getSaveFileName(this, tr("Save store body to file"), name + ".bin", tr("Binary files (*.bin);;All files (*)")); break;
case Types::Microcode: path = QFileDialog::getSaveFileName(this, tr("Save microcode body to file"), name + ".ucb", tr("Microcode body files (*.ucb *.bin);;All files (*)")); break;
case Types::SlicData:
if (subtype == Subtypes::PubkeySlicData) path = QFileDialog::getSaveFileName(this, tr("Save SLIC pubkey body to file"), name + ".spb", tr("SLIC pubkey body files (*.spb *.bin);;All files (*)"));
@ -1144,18 +1132,13 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
switch (model->type(index))
{
case Types::Capsule: ui->menuCapsuleActions->exec(event->globalPos()); break;
case Types::Capsule: ui->menuCapsuleActions->exec(event->globalPos()); break;
case Types::Image: ui->menuImageActions->exec(event->globalPos()); break;
case Types::Region: ui->menuRegionActions->exec(event->globalPos()); break;
case Types::Padding: ui->menuPaddingActions->exec(event->globalPos()); break;
case Types::Volume: ui->menuVolumeActions->exec(event->globalPos()); break;
case Types::File: ui->menuFileActions->exec(event->globalPos()); break;
case Types::Section: ui->menuSectionActions->exec(event->globalPos()); break;
case Types::NvarEntry:
case Types::VssEntry:
case Types::FsysEntry:
case Types::EvsaEntry:
case Types::FlashMapEntry: ui->menuEntryActions->exec(event->globalPos()); break;
case Types::Region: ui->menuRegionActions->exec(event->globalPos()); break;
case Types::Padding: ui->menuPaddingActions->exec(event->globalPos()); break;
case Types::Volume: ui->menuVolumeActions->exec(event->globalPos()); break;
case Types::File: ui->menuFileActions->exec(event->globalPos()); break;
case Types::Section: ui->menuSectionActions->exec(event->globalPos()); break;
case Types::VssStore:
case Types::Vss2Store:
case Types::FdcStore:
@ -1163,9 +1146,8 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
case Types::EvsaStore:
case Types::FtwStore:
case Types::FlashMapStore:
case Types::CmdbStore:
case Types::Microcode:
case Types::SlicData: ui->menuStoreActions->exec(event->globalPos()); break;
case Types::CmdbStore: ui->menuStoreActions->exec(event->globalPos()); break;
default: ui->menuEntryActions->exec(event->globalPos()); break;
}
}
@ -1213,7 +1195,6 @@ void UEFITool::readSettings()
ui->fitTableWidget->setFont(currentFont);
ui->bootGuardEdit->setFont(currentFont);
ui->txtEdit->setFont(currentFont);
ui->microcodeEdit->setFont(currentFont);
ui->structureTreeView->setFont(currentFont);
searchDialog->ui->guidEdit->setFont(currentFont);
searchDialog->ui->hexEdit->setFont(currentFont);
@ -1287,14 +1268,6 @@ void UEFITool::showFitTable()
ui->messagesTabWidget->setCurrentIndex(2);
}
// Get Microcode info
UString microcodeInfo = ffsParser->getMicrocodeInfo();
if (!microcodeInfo.isEmpty()) {
ui->messagesTabWidget->setTabEnabled(4, true);
ui->microcodeEdit->setPlainText(microcodeInfo);
ui->messagesTabWidget->setCurrentIndex(4);
}
// Get TXT ACM info
UString txtInfo = ffsParser->getTxtInfo();
if (!txtInfo.isEmpty()) {

View File

@ -279,44 +279,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="microcodeTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>Microcode</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPlainTextEdit" name="microcodeEdit">
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="finderTab">
<attribute name="title">
<string>Search</string>

View File

@ -17,8 +17,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
const UByteArray FFSv2VolumesInt[] = {
EFI_FIRMWARE_FILE_SYSTEM_GUID,
EFI_FIRMWARE_FILE_SYSTEM2_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID,
EFI_APPLE_AUTHENTICATION_FV_GUID,
EFI_APPLE_IMMUTABLE_FV_GUID,
EFI_INTEL_FILE_SYSTEM_GUID,
EFI_INTEL_FILE_SYSTEM2_GUID,
EFI_SONY_FILE_SYSTEM_GUID

View File

@ -114,38 +114,43 @@ typedef struct EFI_FIRMWARE_VOLUME_HEADER_ {
} EFI_FIRMWARE_VOLUME_HEADER;
// Standard file system GUIDs
const UByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID
const UByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID // 7A9354D9-0468-444A-81CE-0BF617D890DF
("\xD9\x54\x93\x7A\x68\x04\x4A\x44\x81\xCE\x0B\xF6\x17\xD8\x90\xDF", 16);
const UByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID
const UByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID // 8C8CE578-8A3D-4F1C-9935-896185C32DD3
("\x78\xE5\x8C\x8C\x3D\x8A\x1C\x4F\x99\x35\x89\x61\x85\xC3\x2D\xD3", 16);
// Vendor-specific file system GUIDs
const UByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID
("\xAD\xEE\xAD\x04\xFF\x61\x31\x4D\xB6\xBA\x64\xF8\xBF\x90\x1F\x5A", 16);
const UByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16);
// AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0 // Intel 1
const UByteArray EFI_INTEL_FILE_SYSTEM_GUID
("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16);
// D6A1CD70-4B33-4994-A6EA-375F2CCC5437 // Intel 2
const UByteArray EFI_INTEL_FILE_SYSTEM2_GUID
("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16);
// 4F494156-AED6-4D64-A537-B8A5557BCEEC // Sony 1
const UByteArray EFI_SONY_FILE_SYSTEM_GUID
("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16);
// Vector of volume GUIDs with FFSv2-compatible files
extern const std::vector<UByteArray> FFSv2Volumes;
const UByteArray EFI_FIRMWARE_FILE_SYSTEM3_GUID // 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
("\x7A\xC0\x73\x54\xCB\x3D\xCA\x4D\xBD\x6F\x1E\x96\x89\xE7\x34\x9A", 16);
// Vendor-specific file system GUIDs
const UByteArray EFI_APPLE_IMMUTABLE_FV_GUID // 04ADEEAD-61FF-4D31-B6BA-64F8BF901F5A
("\xAD\xEE\xAD\x04\xFF\x61\x31\x4D\xB6\xBA\x64\xF8\xBF\x90\x1F\x5A", 16);
const UByteArray EFI_APPLE_AUTHENTICATION_FV_GUID // BD001B8C-6A71-487B-A14F-0C2A2DCF7A5D
("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16);
const UByteArray EFI_APPLE_MICROCODE_VOLUME_GUID // 153D2197-29BD-44DC-AC59-887F70E41A6B
("\x97\x21\x3D\x15\xBD\x29\xDC\x44\xAC\x59\x88\x7F\x70\xE4\x1A\x6B", 16);
#define EFI_APPLE_MICROCODE_VOLUME_HEADER_SIZE 0x100
const UByteArray EFI_INTEL_FILE_SYSTEM_GUID // AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0
("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16);
const UByteArray EFI_INTEL_FILE_SYSTEM2_GUID // D6A1CD70-4B33-4994-A6EA-375F2CCC5437
("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16);
const UByteArray EFI_SONY_FILE_SYSTEM_GUID // 4F494156-AED6-4D64-A537-B8A5557BCEEC
("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16);
// Vector of volume GUIDs with FFSv2-compatible files
extern const std::vector<UByteArray> FFSv2Volumes;
// Vector of volume GUIDs with FFSv3-compatible files
extern const std::vector<UByteArray> FFSv3Volumes;
// Firmware volume signature
const UByteArray EFI_FV_SIGNATURE("_FVH", 4);
#define EFI_FV_SIGNATURE 0x4856465F // _FVH
#define EFI_FV_SIGNATURE_OFFSET 0x28
// Firmware volume attributes

View File

@ -104,13 +104,15 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind
peiCoreEntryPoint = 0;
newPeiCoreEntryPoint = 0;
// Sanity check
// Sanity check
if (buffer.isEmpty()) {
return EFI_INVALID_PARAMETER;
}
USTATUS result;
// Try parsing as UEFI Capsule
USTATUS result = parseCapsule(buffer, index);
result = parseCapsule(buffer, 0, UModelIndex(), index);;
if (result != U_ITEM_NOT_FOUND) {
return result;
}
@ -122,6 +124,7 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind
}
// Parse as generic image
imageBase = 0;
return parseGenericImage(buffer, 0, UModelIndex(), index);
}
@ -138,7 +141,7 @@ USTATUS FfsParser::parseGenericImage(const UByteArray & buffer, const UINT32 loc
return parseRawArea(index);
}
USTATUS FfsParser::parseCapsule(const UByteArray & capsule, UModelIndex & index)
USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
{
// Check buffer size to be more than or equal to size of EFI_CAPSULE_HEADER
if ((UINT32)capsule.size() < sizeof(EFI_CAPSULE_HEADER)) {
@ -181,7 +184,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, UModelIndex & index)
capsuleHeader->Flags);
// Add tree item
index = model->addItem(0, Types::Capsule, Subtypes::UefiCapsule, name, UString(), info, header, body, UByteArray(), Fixed);
index = model->addItem(model->offset(parent) + localOffset, Types::Capsule, Subtypes::UefiCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent);
}
// Check buffer for being Toshiba capsule header
else if (capsule.startsWith(TOSHIBA_CAPSULE_GUID)) {
@ -213,7 +216,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, UModelIndex & index)
capsuleHeader->Flags);
// Add tree item
index = model->addItem(0, Types::Capsule, Subtypes::ToshibaCapsule, name, UString(), info, header, body, UByteArray(), Fixed);
index = model->addItem(model->offset(parent) + localOffset, Types::Capsule, Subtypes::ToshibaCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent);
}
// Check buffer for being extended Aptio capsule header
else if (capsule.startsWith(APTIO_SIGNED_CAPSULE_GUID)
@ -255,7 +258,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, UModelIndex & index)
capsuleHeader->CapsuleHeader.Flags);
// Add tree item
index = model->addItem(0, Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, UString(), info, header, body, UByteArray(), Fixed);
index = model->addItem(model->offset(parent) + localOffset, Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent);
// Show message about possible Aptio signature break
if (signedCapsule) {
@ -265,9 +268,6 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, UModelIndex & index)
// Capsule present
if (capsuleHeaderSize > 0) {
// Set imageBase for proper alignment calculation
imageBase = capsuleHeaderSize;
UByteArray image = capsule.mid(capsuleHeaderSize);
UModelIndex imageIndex;
@ -574,6 +574,9 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
// Add descriptor tree item
UModelIndex regionIndex = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
// Set image base
imageBase = model->offset(parent) + localOffset;
// Parse regions
USTATUS result = U_SUCCESS;
USTATUS parseResult = U_SUCCESS;
@ -697,10 +700,10 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset
if (versionFound) {
const ME_VERSION* version = (const ME_VERSION*)(me.constData() + versionOffset);
info += usprintf("\nVersion: %u.%u.%u.%u",
version->major,
version->minor,
version->bugfix,
version->build);
version->Major,
version->Minor,
version->Bugfix,
version->Build);
}
}
@ -780,30 +783,32 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
if (!index.isValid())
return U_INVALID_PARAMETER;
// Get parsing data
// Get item data
UByteArray data = model->body(index);
UINT32 headerSize = model->header(index).size();
UINT32 offset = model->offset(index) + headerSize;
// Get item data
UByteArray data = model->body(index);
// Search for first volume
USTATUS result;
UINT32 prevVolumeOffset;
UString name;
UString info;
result = findNextVolume(index, data, offset, 0, prevVolumeOffset);
// Search for the first item
UINT8 prevItemType;
UINT32 prevItemOffset;
UINT32 prevItemSize;
UINT32 prevItemAltSize;
result = findNextRawAreaItem(index, 0, prevItemType, prevItemOffset, prevItemSize, prevItemAltSize);
if (result)
return result;
if (bgFirstVolumeOffset == 0x100000000ULL)
bgFirstVolumeOffset = model->offset(index) + prevVolumeOffset;
bgFirstVolumeOffset = model->offset(index) + prevItemOffset;
// First volume is not at the beginning of RAW area
UString name;
UString info;
if (prevVolumeOffset > 0) {
// First item is not at the beginning of this raw area
if (prevItemOffset > 0) {
// Get info
UByteArray padding = data.left(prevVolumeOffset);
UByteArray padding = data.left(prevItemOffset);
name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size());
@ -811,16 +816,17 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
model->addItem(offset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
}
// Search for and parse all volumes
UINT32 volumeOffset = prevVolumeOffset;
UINT32 prevVolumeSize = 0;
// Search for and parse all items
UINT8 itemType = prevItemType;
UINT32 itemOffset = prevItemOffset;
UINT32 itemSize = prevItemSize;
UINT32 itemAltSize = prevItemAltSize;
while (!result)
{
// Padding between volumes
if (volumeOffset > prevVolumeOffset + prevVolumeSize) {
UINT32 paddingOffset = prevVolumeOffset + prevVolumeSize;
UINT32 paddingSize = volumeOffset - paddingOffset;
while (!result) {
// Padding between items
if (itemOffset > prevItemOffset + prevItemSize) {
UINT32 paddingOffset = prevItemOffset + prevItemSize;
UINT32 paddingSize = itemOffset - paddingOffset;
UByteArray padding = data.mid(paddingOffset, paddingSize);
// Get info
@ -830,66 +836,74 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
// Add tree item
model->addItem(offset + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
}
// Get volume size
UINT32 volumeSize = 0;
UINT32 bmVolumeSize = 0;
result = getVolumeSize(data, volumeOffset, volumeSize, bmVolumeSize);
if (result) {
msg(usprintf("%s: getVolumeSize failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
return result;
}
// Check that volume is fully present in input
if (volumeSize > (UINT32)data.size() || volumeOffset + volumeSize > (UINT32)data.size()) {
// Mark the rest as padding and finish the parsing
UByteArray padding = data.mid(volumeOffset);
// Check that item is fully present in input
if (itemSize > (UINT32)data.size() || itemOffset + itemSize > (UINT32)data.size()) {
// Mark the rest as padding and finish parsing
UByteArray padding = data.mid(itemOffset);
// Get info
name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size());
// Add tree item
UModelIndex paddingIndex = model->addItem(offset + volumeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
UModelIndex paddingIndex = model->addItem(offset + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
msg(usprintf("%s: one of volumes inside overlaps the end of data", __FUNCTION__), paddingIndex);
// Update variables
prevVolumeOffset = volumeOffset;
prevVolumeSize = padding.size();
prevItemOffset = itemOffset;
prevItemSize = padding.size();
break;
}
// Parse current volume's header
UModelIndex volumeIndex;
UByteArray volume = data.mid(volumeOffset, volumeSize);
result = parseVolumeHeader(volume, headerSize + volumeOffset, index, volumeIndex);
if (result) {
msg(usprintf("%s: volume header parsing failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
} else {
// Show messages
if (volumeSize != bmVolumeSize)
msg(usprintf("%s: volume size stored in header %Xh differs from calculated using block map %Xh", __FUNCTION__,
volumeSize, bmVolumeSize),
volumeIndex);
if (itemType == Types::Volume) {
UModelIndex volumeIndex;
UByteArray volume = data.mid(itemOffset, itemSize);
result = parseVolumeHeader(volume, headerSize + itemOffset, index, volumeIndex);
if (result) {
msg(usprintf("%s: volume header parsing failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
} else {
// Show messages
if (itemSize != itemAltSize)
msg(usprintf("%s: volume size stored in header %Xh differs from calculated using block map %Xh", __FUNCTION__,
itemSize, itemAltSize),
volumeIndex);
}
}
else if (itemType == Types::Microcode) {
UModelIndex microcodeIndex;
UByteArray microcode = data.mid(itemOffset, itemSize);
result = parseIntelMicrocodeHeader(microcode, headerSize + itemOffset, index, microcodeIndex);
if (result) {
msg(usprintf("%s: microcode header parsing failed with error ", __FUNCTION__) + errorCodeToUString(result), index);
}
}
else {
return U_UNKNOWN_ITEM_TYPE;
}
// Go to next volume
prevVolumeOffset = volumeOffset;
prevVolumeSize = volumeSize;
result = findNextVolume(index, data, offset, volumeOffset + prevVolumeSize, volumeOffset);
// Go to next item
prevItemOffset = itemOffset;
prevItemSize = itemSize;
prevItemType = itemType;
result = findNextRawAreaItem(index, itemOffset + prevItemSize, itemType, itemOffset, itemSize, itemAltSize);
}
// Fixes clang analyzer warning
(void)prevItemType;
// Padding at the end of RAW area
volumeOffset = prevVolumeOffset + prevVolumeSize;
if ((UINT32)data.size() > volumeOffset) {
UByteArray padding = data.mid(volumeOffset);
itemOffset = prevItemOffset + prevItemSize;
if ((UINT32)data.size() > itemOffset) {
UByteArray padding = data.mid(itemOffset);
// Get info
name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size());
// Add tree item
model->addItem(offset + volumeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
model->addItem(offset + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
}
// Parse bodies
@ -899,6 +913,9 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
case Types::Volume:
parseVolumeBody(current);
break;
case Types::Microcode:
// Parsing already done
break;
case Types::Padding:
// No parsing required
break;
@ -947,8 +964,9 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
headerSize = volumeHeader->ExtHeaderOffset + extendedHeader->ExtHeaderSize;
extendedHeaderGuid = extendedHeader->FvName;
}
else
else {
headerSize = volumeHeader->HeaderLength;
}
// Extended header end can be unaligned
headerSize = ALIGN8(headerSize);
@ -956,6 +974,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
// Check for volume structure to be known
bool isUnknown = true;
bool isNvramVolume = false;
bool isMicrocodeVolume = false;
UINT8 ffsVersion = 0;
// Check for FFS v2 volume
@ -977,6 +996,13 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
isNvramVolume = true;
}
// Check for Microcode volume
if (guid == EFI_APPLE_MICROCODE_VOLUME_GUID) {
isUnknown = false;
isMicrocodeVolume = true;
headerSize = EFI_APPLE_MICROCODE_VOLUME_HEADER_SIZE;
}
// Check volume revision and alignment
bool msgAlignmentBitsSet = false;
bool msgUnaligned = false;
@ -1071,6 +1097,8 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
subtype = Subtypes::Ffs3Volume;
else if (isNvramVolume)
subtype = Subtypes::NvramVolume;
else if (isMicrocodeVolume)
subtype = Subtypes::MicrocodeVolume;
}
index = model->addItem(model->offset(parent) + localOffset, Types::Volume, subtype, name, text, info, header, body, UByteArray(), Fixed, parent, mode);
@ -1103,67 +1131,82 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
return U_SUCCESS;
}
USTATUS FfsParser::findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 globalOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset)
USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 localOffset, UINT8 & nextItemType, UINT32 & nextItemOffset, UINT32 & nextItemSize, UINT32 & nextItemAlternativeSize)
{
int nextIndex = bios.indexOf(EFI_FV_SIGNATURE, volumeOffset);
if (nextIndex < EFI_FV_SIGNATURE_OFFSET)
return U_VOLUMES_NOT_FOUND;
UByteArray data = model->body(index);
UINT32 dataSize = data.size();
// Check volume header to be sane
for (; nextIndex > 0; nextIndex = bios.indexOf(EFI_FV_SIGNATURE, nextIndex + 1)) {
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(bios.constData() + nextIndex - EFI_FV_SIGNATURE_OFFSET);
if (volumeHeader->FvLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER) + 2 * sizeof(EFI_FV_BLOCK_MAP_ENTRY) || volumeHeader->FvLength >= 0xFFFFFFFFUL) {
msg(usprintf("%s: volume candidate at offset %Xh skipped, has invalid FvLength %" PRIX64 "h", __FUNCTION__,
globalOffset + (nextIndex - EFI_FV_SIGNATURE_OFFSET),
volumeHeader->FvLength), index);
continue;
if (dataSize < sizeof(UINT32))
return U_STORES_NOT_FOUND;
UINT32 offset = localOffset;
for (; offset < dataSize - sizeof(UINT32); offset++) {
const UINT32* currentPos = (const UINT32*)(data.constData() + offset);
const UINT32 restSize = dataSize - offset;
UINT32 magic;
memcpy(&magic, currentPos, sizeof(UINT32));
if (magic == INTEL_MICROCODE_HEADER_VERSION) {// Intel microcode
// Check data size
if (restSize < sizeof(INTEL_MICROCODE_HEADER))
continue;
// Check microcode size
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)currentPos;
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(currentPos) || restSize < ucodeHeader->TotalSize) //TODO: needs a separate checking function
continue;
// Check reserved bytes
bool reservedBytesValid = true;
for (UINT32 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
if (ucodeHeader->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
reservedBytesValid = false;
break;
}
if (!reservedBytesValid)
continue;
// All checks passed, microcode found
nextItemType = Types::Microcode;
nextItemSize = ucodeHeader->TotalSize;
nextItemAlternativeSize = ucodeHeader->TotalSize;
nextItemOffset = offset;
break;
}
if (volumeHeader->Revision != 1 && volumeHeader->Revision != 2) {
msg(usprintf("%s: volume candidate at offset %Xh skipped, has invalid Revision byte value %02Xh", __FUNCTION__,
globalOffset + (nextIndex - EFI_FV_SIGNATURE_OFFSET),
volumeHeader->Revision), index);
continue;
else if (magic == EFI_FV_SIGNATURE) {
if (offset < EFI_FV_SIGNATURE_OFFSET)
continue;
offset -= EFI_FV_SIGNATURE_OFFSET;
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(data.constData() + offset);
if (volumeHeader->FvLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER) + 2 * sizeof(EFI_FV_BLOCK_MAP_ENTRY) || volumeHeader->FvLength >= 0xFFFFFFFFUL) {
continue;
}
if (volumeHeader->Revision != 1 && volumeHeader->Revision != 2) {
continue;
}
// Calculate alternative volume size using it's BlockMap
nextItemAlternativeSize = 0;
const EFI_FV_BLOCK_MAP_ENTRY* entry = (const EFI_FV_BLOCK_MAP_ENTRY*)(data.constData() + offset + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
while (entry->NumBlocks != 0 && entry->Length != 0) {
if ((void*)entry >= data.constData() + data.size()) {
continue;
}
nextItemAlternativeSize += entry->NumBlocks * entry->Length;
entry += 1;
}
// All checks passed, volume found
nextItemType = Types::Volume;
nextItemSize = volumeHeader->FvLength;
nextItemOffset = offset;
break;
}
// All checks passed, volume found
break;
}
// No more volumes found
if (nextIndex < EFI_FV_SIGNATURE_OFFSET)
return U_VOLUMES_NOT_FOUND;
nextVolumeOffset = nextIndex - EFI_FV_SIGNATURE_OFFSET;
return U_SUCCESS;
}
USTATUS FfsParser::getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize)
{
// Check that there is space for the volume header and at least two block map entries.
if ((UINT32)bios.size() < volumeOffset + sizeof(EFI_FIRMWARE_VOLUME_HEADER) + 2 * sizeof(EFI_FV_BLOCK_MAP_ENTRY))
return U_INVALID_VOLUME;
// Populate volume header
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(bios.constData() + volumeOffset);
// Check volume signature
if (UByteArray((const char*)&volumeHeader->Signature, sizeof(volumeHeader->Signature)) != EFI_FV_SIGNATURE)
return U_INVALID_VOLUME;
// Calculate volume size using BlockMap
const EFI_FV_BLOCK_MAP_ENTRY* entry = (const EFI_FV_BLOCK_MAP_ENTRY*)(bios.constData() + volumeOffset + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
UINT32 calcVolumeSize = 0;
while (entry->NumBlocks != 0 && entry->Length != 0) {
if ((void*)entry > bios.constData() + bios.size())
return U_INVALID_VOLUME;
calcVolumeSize += entry->NumBlocks * entry->Length;
entry += 1;
}
volumeSize = (UINT32)volumeHeader->FvLength;
bmVolumeSize = calcVolumeSize;
if (volumeSize == 0)
return U_INVALID_VOLUME;
// No more stores found
if (offset >= dataSize - sizeof(UINT32))
return U_STORES_NOT_FOUND;
return U_SUCCESS;
}
@ -1199,6 +1242,10 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
if (model->subtype(index) == Subtypes::NvramVolume)
return nvramParser->parseNvramVolumeBody(index);
// Parse Microcode volume with a dedicated function
if (model->subtype(index) == Subtypes::MicrocodeVolume)
return parseMicrocodeVolumeBody(index);
// Get required values from parsing data
UINT8 emptyByte = 0xFF;
UINT8 ffsVersion = 2;
@ -1732,7 +1779,8 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
// Rename the file
model->setName(index, UString("Non-empty pad-file"));
return U_SUCCESS;
// Parse contents as RAW area
return parseRawArea(dataIndex);
}
USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree)
@ -3484,7 +3532,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index)
}
if (currentEntry->Type == FIT_TYPE_TXT_CONF_POLICY)
parseTxtConfigurationPolicy(currentEntry, info);
parseFitEntryTxtConfigurationPolicy(currentEntry, info);
// Set item index
if (currentEntry->Address > addressDiff && currentEntry->Address < 0xFFFFFFFFUL) { // Only elements in the image need to be parsed
@ -3497,21 +3545,21 @@ USTATUS FfsParser::parseFit(const UModelIndex & index)
switch (currentEntry->Type) {
case FIT_TYPE_MICROCODE:
status = parseIntelMicrocode(item, localOffset, itemIndex, info, currentEntrySize);
status = parseFitEntryMicrocode(item, localOffset, itemIndex, info, currentEntrySize);
break;
case FIT_TYPE_BIOS_AC_MODULE:
status = parseIntelAcm(item, localOffset, itemIndex, info, currentEntrySize);
status = parseFitEntryAcm(item, localOffset, itemIndex, info, currentEntrySize);
acmIndex = itemIndex;
break;
case FIT_TYPE_AC_KEY_MANIFEST:
status = parseIntelBootGuardKeyManifest(item, localOffset, itemIndex, info, currentEntrySize);
status = parseFitEntryBootGuardKeyManifest(item, localOffset, itemIndex, info, currentEntrySize);
kmIndex = itemIndex;
break;
case FIT_TYPE_AC_BOOT_POLICY:
status = parseIntelBootGuardBootPolicy(item, localOffset, itemIndex, info, currentEntrySize);
status = parseFitEntryBootGuardBootPolicy(item, localOffset, itemIndex, info, currentEntrySize);
bpIndex = itemIndex;
break;
@ -3596,7 +3644,7 @@ USTATUS FfsParser::findFitRecursive(const UModelIndex & index, UModelIndex & fou
return U_SUCCESS;
}
USTATUS FfsParser::parseIntelMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
USTATUS FfsParser::parseFitEntryMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
{
U_UNUSED_PARAMETER(parent);
if ((UINT32)microcode.size() < localOffset + sizeof(INTEL_MICROCODE_HEADER)) {
@ -3633,33 +3681,10 @@ USTATUS FfsParser::parseIntelMicrocode(const UByteArray & microcode, const UINT3
header->DateYear
);
realSize = mcSize;
// Add Microcode header info
microcodeInfo += usprintf(
"Microcode Update Capsule found at offset %Xh\n"
"Checksum: %08Xh CPU Flags: %08Xh CPU Signature: %08Xh\n"
"Data Size: %08Xh Date: %02X.%02X.%04X Loader Revision: %08Xh\n"
"Date: %02X.%02X.%04X ModuleSize: %08Xh EntryPoint: %08Xh\n"
"Reserved: %02Xh Revision: %08Xh TotalSize: %08Xh\n"
"Version: %08Xh"
"\n------------------------------------------------------------------------\n\n",
model->offset(parent) + localOffset,
header->Checksum,
header->CpuFlags,
header->CpuSignature,
header->DataSize,
header->DateDay, header->DateMonth, header->DateYear,
header->LoaderRevision,
header->Reserved,
header->Revision,
header->TotalSize,
header->Version
);
return U_SUCCESS;
}
USTATUS FfsParser::parseTxtConfigurationPolicy(const FIT_ENTRY* entry, UString & info)
USTATUS FfsParser::parseFitEntryTxtConfigurationPolicy(const FIT_ENTRY* entry, UString & info)
{
U_UNUSED_PARAMETER(info);
const TXT_CONFIG_POLICY* txtCfg = (const TXT_CONFIG_POLICY*)entry;
@ -3694,7 +3719,7 @@ USTATUS FfsParser::parseTxtConfigurationPolicy(const FIT_ENTRY* entry, UString &
return U_SUCCESS;
}
USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
USTATUS FfsParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
{
if ((UINT32)acm.size() < localOffset + sizeof(INTEL_ACM_HEADER)) {
return U_INVALID_ACM;
@ -3778,7 +3803,7 @@ USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffse
return U_SUCCESS;
}
USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
USTATUS FfsParser::parseFitEntryBootGuardKeyManifest(const UByteArray & keyManifest, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
{
U_UNUSED_PARAMETER(realSize);
if ((UINT32)keyManifest.size() < localOffset + sizeof(BG_KEY_MANIFEST)) {
@ -3844,7 +3869,7 @@ USTATUS FfsParser::parseIntelBootGuardKeyManifest(const UByteArray & keyManifest
return U_SUCCESS;
}
USTATUS FfsParser::findNextElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize)
USTATUS FfsParser::findNextBootGuardBootPolicyElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize)
{
UINT32 dataSize = bootPolicy.size();
if (dataSize < sizeof(UINT64)) {
@ -3882,7 +3907,7 @@ USTATUS FfsParser::findNextElement(const UByteArray & bootPolicy, const UINT32 e
return U_ELEMENTS_NOT_FOUND;
}
USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
USTATUS FfsParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
{
U_UNUSED_PARAMETER(realSize);
if ((UINT32)bootPolicy.size() < localOffset + sizeof(BG_BOOT_POLICY_MANIFEST_HEADER)) {
@ -3923,7 +3948,7 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy,
// Iterate over elements to get them all
UINT32 elementOffset = 0;
UINT32 elementSize = 0;
USTATUS status = findNextElement(bootPolicy, localOffset + sizeof(BG_BOOT_POLICY_MANIFEST_HEADER), elementOffset, elementSize);
USTATUS status = findNextBootGuardBootPolicyElement(bootPolicy, localOffset + sizeof(BG_BOOT_POLICY_MANIFEST_HEADER), elementOffset, elementSize);
while (status == U_SUCCESS) {
const UINT64* currentPos = (const UINT64*)(bootPolicy.constData() + elementOffset);
if (*currentPos == BG_BOOT_POLICY_MANIFEST_IBB_ELEMENT_TAG) {
@ -4062,13 +4087,119 @@ USTATUS FfsParser::parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy,
bootGuardInfo += usprintf("%02X", elementHeader->KeySignature.Signature.Signature[i]);
}
}
status = findNextElement(bootPolicy, elementOffset + elementSize, elementOffset, elementSize);
status = findNextBootGuardBootPolicyElement(bootPolicy, elementOffset + elementSize, elementOffset, elementSize);
}
bootGuardInfo += UString("\n------------------------------------------------------------------------\n\n");
bgBootPolicyFound = true;
return U_SUCCESS;
}
#endif
USTATUS FfsParser::parseMicrocodeVolumeBody(const UModelIndex & index)
{
const UINT32 headerSize = (UINT32)model->header(index).size();
const UINT32 bodySize = (UINT32)model->body(index).size();
UINT32 offset = 0;
USTATUS result = U_SUCCESS;
while(true) {
// Parse current microcode
UModelIndex currentMicrocode;
UByteArray ucode = model->body(index).mid(offset);
// Check for empty area
if (ucode.size() == ucode.count('\xFF') || ucode.size() == ucode.count('\x00')) {
result = U_INVALID_MICROCODE;
}
else {
result = parseIntelMicrocodeHeader(ucode, headerSize + offset, index, currentMicrocode);
}
// Add the rest as padding
if (result) {
if (offset < bodySize) {
// Get info
UString name = UString("Padding");
UString info = usprintf("Full size: %Xh (%u)", ucode.size(), ucode.size());
// Add tree item
model->addItem(model->offset(index) + headerSize + offset, Types::Padding, getPaddingType(ucode), name, UString(), info, UByteArray(), ucode, UByteArray(), Fixed, index);
}
return U_SUCCESS;
}
// Get to next candidate
offset += model->header(currentMicrocode).size() + model->body(currentMicrocode).size() + model->tail(currentMicrocode).size();
if (offset >= bodySize)
break;
}
return U_SUCCESS;
}
USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, UINT8 mode)
{
const UINT32 dataSize = (const UINT32)microcode.size();
if (dataSize < sizeof(INTEL_MICROCODE_HEADER)) {
//msg(usprintf("%s: input is too small even for Intel microcode header", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)microcode.constData();
if (ucodeHeader->Version != INTEL_MICROCODE_HEADER_VERSION) {
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
if (!INTEL_MICROCODE_HEADER_SIZES_VALID(ucodeHeader)) {
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
bool reservedBytesValid = true;
for (UINT8 i = 0; i < sizeof(ucodeHeader->Reserved); i++)
if (ucodeHeader->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) {
reservedBytesValid = false;
break;
}
if (!reservedBytesValid) {
//msg(usprintf("%s: input has invalid Intel microcode header", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
if (dataSize < ucodeHeader->TotalSize) {
//msg(usprintf("%s: input is too small for the whole Intel microcode", __FUNCTION__), parent);
return U_INVALID_MICROCODE;
}
// Valid microcode found
// Construct header and body
UByteArray header = microcode.left(sizeof(INTEL_MICROCODE_HEADER));
UByteArray body = microcode.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize);
//TODO: recalculate microcode checksum
// Add info
UString name("Intel microcode");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n"
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh",
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
header.size(), header.size(),
body.size(), body.size(),
ucodeHeader->DateDay,
ucodeHeader->DateMonth,
ucodeHeader->DateYear,
ucodeHeader->CpuSignature,
ucodeHeader->Revision,
ucodeHeader->Checksum,
ucodeHeader->LoaderRevision,
ucodeHeader->CpuFlags);
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
// No need to parse body further for now
return U_SUCCESS;
}

View File

@ -64,9 +64,6 @@ public:
// Obtain TXT ACM Info
UString getTxtInfo() const { return txtInfo; }
// Obtain Microcode Info
UString getMicrocodeInfo() const { return microcodeInfo; }
// Obtain offset/address difference
UINT64 getAddressDiff() { return addressDiff; }
@ -102,18 +99,18 @@ private:
UModelIndex bgDxeCoreIndex;
UString txtInfo;
UString microcodeInfo;
// First pass
USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index);
USTATUS parseCapsule(const UByteArray & capsule, UModelIndex & index);
USTATUS parseCapsule(const UByteArray & capsule, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseGenericImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseRawArea(const UModelIndex & index);
USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseVolumeBody(const UModelIndex & index);
USTATUS parseMicrocodeVolumeBody(const UModelIndex & index);
USTATUS parseFileHeader(const UByteArray & file, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFileBody(const UModelIndex & index);
USTATUS parseSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
@ -146,8 +143,8 @@ private:
USTATUS parseTeImageSectionBody(const UModelIndex & index);
USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed);
USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 globalOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
USTATUS getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize);
USTATUS findNextRawAreaItem(const UModelIndex & index, const UINT32 localOffset,
UINT8 & nextItemType, UINT32 & nextItemOffset, UINT32 & nextItemSize, UINT32 & nextItemAlternativeSize);
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
@ -161,17 +158,18 @@ private:
USTATUS parseFit(const UModelIndex & index);
USTATUS parseVendorHashFile(const UByteArray & fileGuid, const UModelIndex & index);
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, UINT8 mode = CREATE_MODE_APPEND);
#ifdef U_ENABLE_FIT_PARSING_SUPPORT
USTATUS findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset);
// FIT entries
USTATUS parseIntelMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseIntelAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseIntelBootGuardKeyManifest(const UByteArray & keyManifest, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseIntelBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseTxtConfigurationPolicy(const FIT_ENTRY* entry, UString & info);
USTATUS findNextElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize);
USTATUS parseFitEntryMicrocode(const UByteArray & microcode, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryBootGuardKeyManifest(const UByteArray & keyManifest, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolicy, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize);
USTATUS parseFitEntryTxtConfigurationPolicy(const FIT_ENTRY* entry, UString & info);
USTATUS findNextBootGuardBootPolicyElement(const UByteArray & bootPolicy, const UINT32 elementOffset, UINT32 & nextElementOffset, UINT32 & nextElementSize);
#endif
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT

View File

@ -18,8 +18,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <fstream>
#include <sstream>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdio>
struct OperatorLessForGuids : public std::binary_function<EFI_GUID, EFI_GUID, bool>
{

View File

@ -22,12 +22,12 @@ const UByteArray ME_VERSION_SIGNATURE("\x24\x4D\x41\x4E", 4); //$MAN
const UByteArray ME_VERSION_SIGNATURE2("\x24\x4D\x4E\x32", 4); //$MN2
typedef struct ME_VERSION_ {
UINT32 signature;
UINT32 reserved;
UINT16 major;
UINT16 minor;
UINT16 bugfix;
UINT16 build;
UINT32 Signature;
UINT32 Reserved;
UINT16 Major;
UINT16 Minor;
UINT16 Bugfix;
UINT16 Build;
} ME_VERSION;
// Restore previous packing rules

View File

@ -108,6 +108,6 @@ UString flashMapGuidToUString(const EFI_GUID & guid)
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID) return UString("EVSA store");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_SELF_GUID) return UString("Flash map");
return UString();
return UString("Unknown");
}

View File

@ -1225,55 +1225,6 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3
return U_SUCCESS;
}
USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
// Check data size
if (dataSize < sizeof(INTEL_MICROCODE_HEADER)) {
msg(usprintf("%s: volume body is too small even for Intel microcode header", __FUNCTION__), parent);
return U_SUCCESS;
}
// Get Intel microcode header
const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)store.constData();
// Check store size
if (dataSize < ucodeHeader->TotalSize) {
msg(usprintf("%s: Intel microcode size %Xh (%u) is greater than volume body size %Xh (%u)", __FUNCTION__,
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
dataSize, dataSize), parent);
return U_SUCCESS;
}
// Construct header and body
UByteArray header = store.left(sizeof(INTEL_MICROCODE_HEADER));
UByteArray body = store.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize);
//TODO: recalculate microcode checksum
// Add info
UString name("Intel microcode");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n"
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh",
ucodeHeader->TotalSize, ucodeHeader->TotalSize,
header.size(), header.size(),
body.size(), body.size(),
ucodeHeader->DateDay,
ucodeHeader->DateMonth,
ucodeHeader->DateYear,
ucodeHeader->CpuSignature,
ucodeHeader->Revision,
ucodeHeader->Checksum,
ucodeHeader->LoaderRevision,
ucodeHeader->CpuFlags);
// Add tree item
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1318,7 +1269,7 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
// Intel microcode
// Must be checked after SLIC marker because of the same *signature values
else if (*signature == INTEL_MICROCODE_HEADER_VERSION)
return parseIntelMicrocodeHeader(store, localOffset, parent, index, mode);
return ffsParser->parseIntelMicrocodeHeader(store, localOffset, parent, index, mode);
msg(usprintf("parseStoreHeader: don't know how to parse a header with signature %08Xh", *signature), parent);
return U_SUCCESS;

View File

@ -62,7 +62,6 @@ private:
USTATUS parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseSlicPubkeyHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFdcStoreBody(const UModelIndex & index);
USTATUS parseVssStoreBody(const UModelIndex & index, const UINT8 alignment);

View File

@ -74,17 +74,6 @@ UString itemTypeToUString(const UINT8 type)
UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
{
switch (type) {
case Types::Root:
case Types::FreeSpace:
case Types::VssStore:
case Types::Vss2Store:
case Types::FdcStore:
case Types::FsysStore:
case Types::EvsaStore:
case Types::FtwStore:
case Types::FlashMapStore:
case Types::CmdbStore:
case Types::SlicData: return UString();
case Types::Image:
if (subtype == Subtypes::IntelImage) return UString("Intel");
if (subtype == Subtypes::UefiImage) return UString("UEFI");
@ -99,6 +88,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
if (subtype == Subtypes::Ffs2Volume) return UString("FFSv2");
if (subtype == Subtypes::Ffs3Volume) return UString("FFSv3");
if (subtype == Subtypes::NvramVolume) return UString("NVRAM");
if (subtype == Subtypes::MicrocodeVolume) return UString("Microcode");
break;
case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed");
@ -144,7 +134,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
break;
}
return UString("Unknown");
return UString();
}
UString compressionTypeToUString(const UINT8 algorithm)

View File

@ -78,7 +78,8 @@ namespace Subtypes {
UnknownVolume = 110,
Ffs2Volume,
Ffs3Volume,
NvramVolume
NvramVolume,
MicrocodeVolume
};
enum RegionSubtypes {

View File

@ -1,6 +1,6 @@
/* types.h
/* version.h
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -14,6 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __VERSION_H__
#define __VERSION_H__
#define PROGRAM_VERSION "NE alpha 51"
#define PROGRAM_VERSION "NE alpha 52"
#endif