Add support for x86 recovery startup AP data entries in special padding files

This commit is contained in:
Nikolaj Schlej 2022-09-10 09:56:14 +02:00 committed by Nikolaj Schlej
parent 06653d024b
commit a4a455d0ff
7 changed files with 485 additions and 439 deletions

View file

@ -72,7 +72,7 @@ extern const UByteArray EFI_DXE_APRIORI_FILE_GUID // FC510EE7-FFDC-11D4-BD41-008
// Volume top file
extern const UByteArray EFI_FFS_VOLUME_TOP_FILE_GUID // 1BA0062E-C779-4582-8566-336AE8F78F09
("\x2E\x06\xA0\x1B\x79\xC7\x82\x45\x85\x66\x33\x6A\xE8\xF7\x8F\x09", 16);
// Pad file GUID
// Padding file GUID
extern const UByteArray EFI_FFS_PAD_FILE_GUID // E4536585-7909-4A60-B5C6-ECDEA6EBFB5
("\x85\x65\x53\xE4\x09\x79\x60\x4A\xB5\xC6\xEC\xDE\xA6\xEB\xFB\x54", 16);
// AMI DXE core file
@ -125,6 +125,9 @@ const UINT8 ffsAlignmentTable[] =
const UINT8 ffsAlignment2Table[] =
{ 17, 18, 19, 20, 21, 22, 23, 24 };
extern const UByteArray RECOVERY_STARTUP_AP_DATA_X86_128K // jmp far F000:FFD0, EAD0FF00F0
("\xEA\xD0\xFF\x00\xF0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x2D", RECOVERY_STARTUP_AP_DATA_X86_SIZE);
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
{
ffsSize[2] = (UINT8)((size) >> 16U);

View file

@ -348,7 +348,7 @@ extern const UByteArray EFI_DXE_APRIORI_FILE_GUID; // FC510EE7-FFDC-11D4-BD41-00
// Volume top file
extern const UByteArray EFI_FFS_VOLUME_TOP_FILE_GUID; // 1BA0062E-C779-4582-8566-336AE8F78F09
// AMI pad file GUID
// AMI padding file GUID
extern const UByteArray EFI_FFS_PAD_FILE_GUID; // E4536585-7909-4A60-B5C6-ECDEA6EBFB5
// AMI DXE core file
@ -530,6 +530,13 @@ typedef struct POSTCODE_SECTION_ {
///
#define EFI_DEP_SOR 0x09
//*****************************************************************************
// X86 Startup AP Data
//*****************************************************************************
#define RECOVERY_STARTUP_AP_DATA_X86_SIZE 0x10
extern const UByteArray RECOVERY_STARTUP_AP_DATA_X86_64K;
extern const UByteArray RECOVERY_STARTUP_AP_DATA_X86_128K;
//*****************************************************************************
// X86 Reset Vector Data
//*****************************************************************************

View file

@ -1368,7 +1368,8 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
nextItemOffset = offset - EFI_FV_SIGNATURE_OFFSET;
break;
}
else if (readUnaligned(currentPos) == BPDT_GREEN_SIGNATURE || readUnaligned(currentPos) == BPDT_YELLOW_SIGNATURE) {
else if (readUnaligned(currentPos) == BPDT_GREEN_SIGNATURE
|| readUnaligned(currentPos) == BPDT_YELLOW_SIGNATURE) {
// Check data size
if (restSize < sizeof(BPDT_HEADER))
continue;
@ -1548,8 +1549,8 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
// We aren't at the end of empty space
// Check that the remaining space can still have a file in it
if (volumeBodySize - fileOffset < sizeof(EFI_FFS_FILE_HEADER) || // Remaining space is smaller than the smallest possible file
volumeBodySize - fileOffset < fileSize) { // Remaining space is smaller than non-empty file size
if (volumeBodySize - fileOffset < sizeof(EFI_FFS_FILE_HEADER) // Remaining space is smaller than the smallest possible file
|| volumeBodySize - fileOffset < fileSize) { // Remaining space is smaller than non-empty file size
// Parse non-UEFI data
parseVolumeNonUefiData(volumeBody.mid(fileOffset), volumeHeaderSize + fileOffset, index);
@ -1573,8 +1574,9 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
for (int i = 0; i < model->rowCount(index); i++) {
UModelIndex current = index.model()->index(i, 0, index);
// Skip non-file entries and pad files
if (model->type(current) != Types::File || model->subtype(current) == EFI_FV_FILETYPE_PAD) {
// Skip non-file entries and padding files
if (model->type(current) != Types::File
|| model->subtype(current) == EFI_FV_FILETYPE_PAD) {
continue;
}
@ -1755,7 +1757,7 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
if (fileHeader->Type != EFI_FV_FILETYPE_PAD) {
name = guidToUString(fileHeader->Name);
} else {
name = UString("Pad-file");
name = UString("Padding file");
}
info = UString("File GUID: ") + guidToUString(fileHeader->Name, false) +
@ -1864,7 +1866,7 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index)
if (model->type(index) != Types::File)
return U_SUCCESS;
// Parse pad-file body
// Parse padding file body
if (model->subtype(index) == EFI_FV_FILETYPE_PAD)
return parsePadFileBody(index);
@ -1915,7 +1917,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
emptyByte = pdata->emptyByte;
}
// Check if the while PAD file is empty
// Check if the while padding file is empty
if (body.size() == body.count(emptyByte))
return U_SUCCESS;
@ -1950,20 +1952,39 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
// ... and all bytes after as a padding
UByteArray padding = body.mid(nonEmptyByteOffset);
// Get info
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
// Check for that data to be recovery startup AP data for x86
// https://github.com/tianocore/edk2/blob/stable/202011/BaseTools/Source/C/GenFv/GenFvInternalLib.c#L106
if (padding.left(RECOVERY_STARTUP_AP_DATA_X86_SIZE) == RECOVERY_STARTUP_AP_DATA_X86_128K) {
// Get info
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
// Add tree item
(void)model->addItem(headerSize + nonEmptyByteOffset, Types::StartupApDataEntry, Subtypes::x86128kStartupApDataEntry, UString("Startup AP data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
// Rename the file
model->setName(index, UString("Startup AP data padding file"));
// Do not parse contents
return U_SUCCESS;
}
else { // Not a data array
// Get info
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
// Add tree item
UModelIndex dataIndex = model->addItem(headerSize + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
// Show message
msg(usprintf("%s: non-UEFI data found in padding file", __FUNCTION__), dataIndex);
// Rename the file
model->setName(index, UString("Non-empty padding file"));
// Do not parse contents
return U_SUCCESS;
}
// Add tree item
UModelIndex dataIndex = model->addItem(headerSize + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
// Show message
msg(usprintf("%s: non-UEFI data found in pad-file", __FUNCTION__), dataIndex);
// Rename the file
model->setName(index, UString("Non-empty pad-file"));
// Parse contents as RAW area
return parseRawArea(dataIndex);
return U_SUCCESS;
}
USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree)

View file

@ -42,44 +42,44 @@ UString regionTypeToUString(const UINT8 type)
UString itemTypeToUString(const UINT8 type)
{
switch (type) {
case Types::Root: return UString("Root");
case Types::Image: return UString("Image");
case Types::Capsule: return UString("Capsule");
case Types::Region: return UString("Region");
case Types::Volume: return UString("Volume");
case Types::Padding: return UString("Padding");
case Types::File: return UString("File");
case Types::Section: return UString("Section");
case Types::FreeSpace: return UString("Free space");
case Types::VssStore: return UString("VSS store");
case Types::Vss2Store: return UString("VSS2 store");
case Types::FtwStore: return UString("FTW store");
case Types::FdcStore: return UString("FDC store");
case Types::FsysStore: return UString("Fsys store");
case Types::EvsaStore: return UString("EVSA store");
case Types::CmdbStore: return UString("CMDB store");
case Types::FlashMapStore: return UString("FlashMap store");
case Types::NvarEntry: return UString("NVAR entry");
case Types::VssEntry: return UString("VSS entry");
case Types::FsysEntry: return UString("Fsys entry");
case Types::EvsaEntry: return UString("EVSA entry");
case Types::FlashMapEntry: return UString("FlashMap entry");
case Types::Microcode: return UString("Microcode");
case Types::SlicData: return UString("SLIC data");
// ME-specific
case Types::FptStore: return UString("FPT store");
case Types::FptEntry: return UString("FPT entry");
case Types::IfwiHeader: return UString("IFWI header");
case Types::IfwiPartition: return UString("IFWI partition");
case Types::FptPartition: return UString("FPT partition");
case Types::BpdtStore: return UString("BPDT store");
case Types::BpdtEntry: return UString("BPDT entry");
case Types::BpdtPartition: return UString("BPDT partition");
case Types::CpdStore: return UString("CPD store");
case Types::CpdEntry: return UString("CPD entry");
case Types::CpdPartition: return UString("CPD partition");
case Types::CpdExtension: return UString("CPD extension");
case Types::CpdSpiEntry: return UString("CPD SPI entry");
case Types::Root: return UString("Root");
case Types::Image: return UString("Image");
case Types::Capsule: return UString("Capsule");
case Types::Region: return UString("Region");
case Types::Volume: return UString("Volume");
case Types::Padding: return UString("Padding");
case Types::File: return UString("File");
case Types::Section: return UString("Section");
case Types::FreeSpace: return UString("Free space");
case Types::VssStore: return UString("VSS store");
case Types::Vss2Store: return UString("VSS2 store");
case Types::FtwStore: return UString("FTW store");
case Types::FdcStore: return UString("FDC store");
case Types::FsysStore: return UString("Fsys store");
case Types::EvsaStore: return UString("EVSA store");
case Types::CmdbStore: return UString("CMDB store");
case Types::FlashMapStore: return UString("FlashMap store");
case Types::NvarEntry: return UString("NVAR entry");
case Types::VssEntry: return UString("VSS entry");
case Types::FsysEntry: return UString("Fsys entry");
case Types::EvsaEntry: return UString("EVSA entry");
case Types::FlashMapEntry: return UString("FlashMap entry");
case Types::Microcode: return UString("Microcode");
case Types::SlicData: return UString("SLIC data");
case Types::FptStore: return UString("FPT store");
case Types::FptEntry: return UString("FPT entry");
case Types::IfwiHeader: return UString("IFWI header");
case Types::IfwiPartition: return UString("IFWI partition");
case Types::FptPartition: return UString("FPT partition");
case Types::BpdtStore: return UString("BPDT store");
case Types::BpdtEntry: return UString("BPDT entry");
case Types::BpdtPartition: return UString("BPDT partition");
case Types::CpdStore: return UString("CPD store");
case Types::CpdEntry: return UString("CPD entry");
case Types::CpdPartition: return UString("CPD partition");
case Types::CpdExtension: return UString("CPD extension");
case Types::CpdSpiEntry: return UString("CPD SPI entry");
case Types::StartupApDataEntry: return UString("Startup AP data");
}
return usprintf("Unknown %02Xh", type);
@ -89,82 +89,83 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
{
switch (type) {
case Types::Image:
if (subtype == Subtypes::IntelImage) return UString("Intel");
if (subtype == Subtypes::UefiImage) return UString("UEFI");
if (subtype == Subtypes::IntelImage) return UString("Intel");
else if (subtype == Subtypes::UefiImage) return UString("UEFI");
break;
case Types::Padding:
if (subtype == Subtypes::ZeroPadding) return UString("Empty (0x00)");
if (subtype == Subtypes::OnePadding) return UString("Empty (0xFF)");
if (subtype == Subtypes::DataPadding) return UString("Non-empty");
if (subtype == Subtypes::ZeroPadding) return UString("Empty (0x00)");
else if (subtype == Subtypes::OnePadding) return UString("Empty (0xFF)");
else if (subtype == Subtypes::DataPadding) return UString("Non-empty");
break;
case Types::Volume:
if (subtype == Subtypes::UnknownVolume) return UString("Unknown");
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");
if (subtype == Subtypes::UnknownVolume) return UString("Unknown");
else if (subtype == Subtypes::Ffs2Volume) return UString("FFSv2");
else if (subtype == Subtypes::Ffs3Volume) return UString("FFSv3");
else if (subtype == Subtypes::NvramVolume) return UString("NVRAM");
else if (subtype == Subtypes::MicrocodeVolume) return UString("Microcode");
break;
case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed");
if (subtype == Subtypes::AptioUnsignedCapsule) return UString("Aptio unsigned");
if (subtype == Subtypes::UefiCapsule) return UString("UEFI 2.0");
if (subtype == Subtypes::ToshibaCapsule) return UString("Toshiba");
if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed");
else if (subtype == Subtypes::AptioUnsignedCapsule) return UString("Aptio unsigned");
else if (subtype == Subtypes::UefiCapsule) return UString("UEFI 2.0");
else if (subtype == Subtypes::ToshibaCapsule) return UString("Toshiba");
break;
case Types::Region: return regionTypeToUString(subtype);
case Types::File: return fileTypeToUString(subtype);
case Types::Section: return sectionTypeToUString(subtype);
case Types::Region: return regionTypeToUString(subtype);
case Types::File: return fileTypeToUString(subtype);
case Types::Section: return sectionTypeToUString(subtype);
case Types::NvarEntry:
if (subtype == Subtypes::InvalidNvarEntry) return UString("Invalid");
if (subtype == Subtypes::InvalidLinkNvarEntry) return UString("Invalid link");
if (subtype == Subtypes::LinkNvarEntry) return UString("Link");
if (subtype == Subtypes::DataNvarEntry) return UString("Data");
if (subtype == Subtypes::FullNvarEntry) return UString("Full");
if (subtype == Subtypes::InvalidNvarEntry) return UString("Invalid");
else if (subtype == Subtypes::InvalidLinkNvarEntry) return UString("Invalid link");
else if (subtype == Subtypes::LinkNvarEntry) return UString("Link");
else if (subtype == Subtypes::DataNvarEntry) return UString("Data");
else if (subtype == Subtypes::FullNvarEntry) return UString("Full");
break;
case Types::VssEntry:
if (subtype == Subtypes::InvalidVssEntry) return UString("Invalid");
if (subtype == Subtypes::StandardVssEntry) return UString("Standard");
if (subtype == Subtypes::AppleVssEntry) return UString("Apple");
if (subtype == Subtypes::AuthVssEntry) return UString("Auth");
if (subtype == Subtypes::IntelVssEntry) return UString("Intel");
if (subtype == Subtypes::InvalidVssEntry) return UString("Invalid");
else if (subtype == Subtypes::StandardVssEntry) return UString("Standard");
else if (subtype == Subtypes::AppleVssEntry) return UString("Apple");
else if (subtype == Subtypes::AuthVssEntry) return UString("Auth");
else if (subtype == Subtypes::IntelVssEntry) return UString("Intel");
break;
case Types::FsysEntry:
if (subtype == Subtypes::InvalidFsysEntry) return UString("Invalid");
if (subtype == Subtypes::NormalFsysEntry) return UString("Normal");
if (subtype == Subtypes::InvalidFsysEntry) return UString("Invalid");
else if (subtype == Subtypes::NormalFsysEntry) return UString("Normal");
break;
case Types::EvsaEntry:
if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid");
if (subtype == Subtypes::UnknownEvsaEntry) return UString("Unknown");
if (subtype == Subtypes::GuidEvsaEntry) return UString("GUID");
if (subtype == Subtypes::NameEvsaEntry) return UString("Name");
if (subtype == Subtypes::DataEvsaEntry) return UString("Data");
if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid");
else if (subtype == Subtypes::UnknownEvsaEntry) return UString("Unknown");
else if (subtype == Subtypes::GuidEvsaEntry) return UString("GUID");
else if (subtype == Subtypes::NameEvsaEntry) return UString("Name");
else if (subtype == Subtypes::DataEvsaEntry) return UString("Data");
break;
case Types::FlashMapEntry:
if (subtype == Subtypes::VolumeFlashMapEntry) return UString("Volume");
if (subtype == Subtypes::DataFlashMapEntry) return UString("Data");
if (subtype == Subtypes::VolumeFlashMapEntry) return UString("Volume");
else if (subtype == Subtypes::DataFlashMapEntry) return UString("Data");
break;
case Types::Microcode:
if (subtype == Subtypes::IntelMicrocode) return UString("Intel");
if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
if (subtype == Subtypes::IntelMicrocode) return UString("Intel");
else if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
break;
// ME-specific
case Types::FptEntry:
if (subtype == Subtypes::ValidFptEntry) return UString("Valid");
if (subtype == Subtypes::InvalidFptEntry) return UString("Invalid");
if (subtype == Subtypes::ValidFptEntry) return UString("Valid");
else if (subtype == Subtypes::InvalidFptEntry) return UString("Invalid");
break;
case Types::FptPartition:
if (subtype == Subtypes::CodeFptPartition) return UString("Code");
if (subtype == Subtypes::DataFptPartition) return UString("Data");
if (subtype == Subtypes::GlutFptPartition) return UString("GLUT");
if (subtype == Subtypes::CodeFptPartition) return UString("Code");
else if (subtype == Subtypes::DataFptPartition) return UString("Data");
else if (subtype == Subtypes::GlutFptPartition) return UString("GLUT");
break;
case Types::IfwiPartition:
if (subtype == Subtypes::BootIfwiPartition) return UString("Boot");
if (subtype == Subtypes::DataIfwiPartition) return UString("Data");
if (subtype == Subtypes::BootIfwiPartition) return UString("Boot");
else if (subtype == Subtypes::DataIfwiPartition) return UString("Data");
break;
case Types::CpdPartition:
if (subtype == Subtypes::ManifestCpdPartition) return UString("Manifest");
if (subtype == Subtypes::MetadataCpdPartition) return UString("Metadata");
if (subtype == Subtypes::KeyCpdPartition) return UString("Key");
if (subtype == Subtypes::CodeCpdPartition) return UString("Code");
if (subtype == Subtypes::ManifestCpdPartition) return UString("Manifest");
else if (subtype == Subtypes::MetadataCpdPartition) return UString("Metadata");
else if (subtype == Subtypes::KeyCpdPartition) return UString("Key");
else if (subtype == Subtypes::CodeCpdPartition) return UString("Code");
case Types::StartupApDataEntry:
if (subtype == Subtypes::x86128kStartupApDataEntry) return UString("X86 128K");
break;
}

View file

@ -27,7 +27,7 @@ namespace Actions
Replace,
Remove,
Rebuild,
Rebase
Rebase,
};
}
@ -58,7 +58,6 @@ namespace Types {
FlashMapEntry,
Microcode,
SlicData,
// ME-specific
IfwiHeader,
IfwiPartition,
FptStore,
@ -71,21 +70,22 @@ namespace Types {
CpdEntry,
CpdPartition,
CpdExtension,
CpdSpiEntry
CpdSpiEntry,
StartupApDataEntry,
};
}
namespace Subtypes {
enum ImageSubtypes{
IntelImage = 90,
UefiImage
UefiImage,
};
enum CapsuleSubtypes {
AptioSignedCapsule = 100,
AptioUnsignedCapsule,
UefiCapsule,
ToshibaCapsule
ToshibaCapsule,
};
enum VolumeSubtypes {
@ -93,7 +93,7 @@ namespace Subtypes {
Ffs2Volume,
Ffs3Volume,
NvramVolume,
MicrocodeVolume
MicrocodeVolume,
};
enum RegionSubtypes {
@ -112,13 +112,13 @@ namespace Subtypes {
Tgbe2Region,
Reserved1Region,
Reserved2Region,
PttRegion
PttRegion,
};
enum PaddingSubtypes {
ZeroPadding = 120,
OnePadding,
DataPadding
DataPadding,
};
enum NvarEntrySubtypes {
@ -126,7 +126,7 @@ namespace Subtypes {
InvalidLinkNvarEntry,
LinkNvarEntry,
DataNvarEntry,
FullNvarEntry
FullNvarEntry,
};
enum VssEntrySubtypes {
@ -134,12 +134,12 @@ namespace Subtypes {
StandardVssEntry,
AppleVssEntry,
AuthVssEntry,
IntelVssEntry
IntelVssEntry,
};
enum FsysEntrySubtypes {
InvalidFsysEntry = 150,
NormalFsysEntry
NormalFsysEntry,
};
enum EvsaEntrySubtypes {
@ -152,41 +152,45 @@ namespace Subtypes {
enum FlashMapEntrySubtypes {
VolumeFlashMapEntry = 170,
DataFlashMapEntry
DataFlashMapEntry,
};
enum MicrocodeSubtypes {
IntelMicrocode = 180,
AmdMicrocode
AmdMicrocode,
};
enum SlicDataSubtypes {
PubkeySlicData = 190,
MarkerSlicData
MarkerSlicData,
};
// ME-specific
enum IfwiPartitionSubtypes {
DataIfwiPartition = 200,
BootIfwiPartition
BootIfwiPartition,
};
enum FptEntrySubtypes {
ValidFptEntry = 210,
InvalidFptEntry
InvalidFptEntry,
};
enum FptPartitionSubtypes {
CodeFptPartition = 220,
DataFptPartition,
GlutFptPartition
GlutFptPartition,
};
enum CpdPartitionSubtypes {
ManifestCpdPartition = 230,
MetadataCpdPartition,
KeyCpdPartition,
CodeCpdPartition
CodeCpdPartition,
};
enum StartupApDataEntrySubtypes {
x86128kStartupApDataEntry = 240,
};
}

View file

@ -67,7 +67,7 @@ UString uniqueItemName(const UModelIndex & index)
{
// Sanity check
if (!index.isValid())
return UString("Invalid_index");
return UString("InvalidIndex");
// Get model from index
const TreeModel* model = (const TreeModel*)index.model();