modification support & other

+ Replace and rebuild functions
+ NVRAM volumes rebuild support (without changing the size of volume)
+ 'TXT' and 'Microcode' parsing tabs
+ 'Inspect with IDA' function
This commit is contained in:
Dmitry Frolov 2018-08-23 08:43:46 +03:00
parent b064495db8
commit 856ea2a3aa
18 changed files with 2439 additions and 301 deletions

View file

@ -19,54 +19,57 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <stddef.h>
typedef size_t USTATUS;
#define U_SUCCESS 0
#define U_INVALID_PARAMETER 1
#define U_BUFFER_TOO_SMALL 2
#define U_OUT_OF_RESOURCES 3
#define U_OUT_OF_MEMORY 4
#define U_FILE_OPEN 5
#define U_FILE_READ 6
#define U_FILE_WRITE 7
#define U_ITEM_NOT_FOUND 8
#define U_UNKNOWN_ITEM_TYPE 9
#define U_INVALID_FLASH_DESCRIPTOR 10
#define U_INVALID_REGION 11
#define U_EMPTY_REGION 12
#define U_BIOS_REGION_NOT_FOUND 13
#define U_VOLUMES_NOT_FOUND 14
#define U_INVALID_VOLUME 15
#define U_VOLUME_REVISION_NOT_SUPPORTED 16
#define U_COMPLEX_BLOCK_MAP 17
#define U_UNKNOWN_FFS 18
#define U_INVALID_FILE 19
#define U_INVALID_SECTION 20
#define U_UNKNOWN_SECTION 21
#define U_STANDARD_COMPRESSION_FAILED 22
#define U_CUSTOMIZED_COMPRESSION_FAILED 23
#define U_STANDARD_DECOMPRESSION_FAILED 24
#define U_CUSTOMIZED_DECOMPRESSION_FAILED 25
#define U_UNKNOWN_COMPRESSION_TYPE 26
#define U_DEPEX_PARSE_FAILED 27
#define U_UNKNOWN_EXTRACT_MODE 28
#define U_UNKNOWN_REPLACE_MODE 29
#define U_UNKNOWN_IMAGE_TYPE 30
#define U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE 31
#define U_UNKNOWN_RELOCATION_TYPE 32
#define U_DIR_ALREADY_EXIST 33
#define U_DIR_CREATE 34
#define U_DIR_CHANGE 35
#define U_TRUNCATED_IMAGE 36
#define U_INVALID_CAPSULE 37
#define U_STORES_NOT_FOUND 38
#define U_INVALID_IMAGE 39
#define U_INVALID_RAW_AREA 40
#define U_INVALID_FIT 41
#define U_INVALID_MICROCODE 42
#define U_INVALID_ACM 43
#define U_INVALID_BG_KEY_MANIFEST 44
#define U_INVALID_BG_BOOT_POLICY 45
#define U_ELEMENTS_NOT_FOUND 46
#define U_NOT_IMPLEMENTED 0xFF
#define U_SUCCESS 0
#define U_INVALID_PARAMETER 1
#define U_BUFFER_TOO_SMALL 2
#define U_OUT_OF_RESOURCES 3
#define U_OUT_OF_MEMORY 4
#define U_FILE_OPEN 5
#define U_FILE_READ 6
#define U_FILE_WRITE 7
#define U_ITEM_NOT_FOUND 8
#define U_UNKNOWN_ITEM_TYPE 9
#define U_INVALID_FLASH_DESCRIPTOR 10
#define U_INVALID_REGION 11
#define U_EMPTY_REGION 12
#define U_BIOS_REGION_NOT_FOUND 13
#define U_VOLUMES_NOT_FOUND 14
#define U_INVALID_VOLUME 15
#define U_VOLUME_REVISION_NOT_SUPPORTED 16
#define U_COMPLEX_BLOCK_MAP 17
#define U_UNKNOWN_FFS 18
#define U_INVALID_FILE 19
#define U_INVALID_SECTION 20
#define U_UNKNOWN_SECTION 21
#define U_STANDARD_COMPRESSION_FAILED 22
#define U_CUSTOMIZED_COMPRESSION_FAILED 23
#define U_STANDARD_DECOMPRESSION_FAILED 24
#define U_CUSTOMIZED_DECOMPRESSION_FAILED 25
#define U_UNKNOWN_COMPRESSION_TYPE 26
#define U_DEPEX_PARSE_FAILED 27
#define U_UNKNOWN_EXTRACT_MODE 28
#define U_UNKNOWN_REPLACE_MODE 29
#define U_UNKNOWN_IMAGE_TYPE 30
#define U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE 31
#define U_UNKNOWN_RELOCATION_TYPE 32
#define U_DIR_ALREADY_EXIST 33
#define U_DIR_CREATE 34
#define U_DIR_CHANGE 35
#define U_TRUNCATED_IMAGE 36
#define U_INVALID_CAPSULE 37
#define U_STORES_NOT_FOUND 38
#define U_INVALID_IMAGE 39
#define U_INVALID_RAW_AREA 40
#define U_INVALID_FIT 41
#define U_INVALID_MICROCODE 42
#define U_INVALID_ACM 43
#define U_INVALID_BG_KEY_MANIFEST 44
#define U_INVALID_BG_BOOT_POLICY 45
#define U_INVALID_TXT_CONF 46
#define U_ELEMENTS_NOT_FOUND 47
#define U_PEI_CORE_ENTRY_POINT_NOT_FOUND 48
#define U_INVALID_STORE_SIZE 49
#define U_NOT_IMPLEMENTED 0xFF
// UDK porting definitions
typedef uint8_t BOOLEAN;
@ -87,6 +90,10 @@ typedef ptrdiff_t INTN;
#define VOID void
#define STATIC static
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif
#ifndef TRUE
#define TRUE ((BOOLEAN)(1==1))
#endif
@ -125,6 +132,10 @@ typedef ptrdiff_t INTN;
#define EXTRACT_MODE_BODY 1
#define EXTRACT_MODE_BODY_UNCOMPRESSED 2
// Item inspect modes
#define INSPECT_MODE_IDA32 0
#define INSPECT_MODE_IDA64 1
// Item replace modes
#define REPLACE_MODE_AS_IS 0
#define REPLACE_MODE_BODY 1

View file

@ -72,11 +72,14 @@ typedef struct BG_MICROSOFT_PMDA_ENTRY_
// Intel ACM
//
#define INTEL_ACM_MODULE_TYPE 0x00030002
#define INTEL_ACM_MODULE_VENDOR 0x8086
#define INTEL_ACM_MODULE_TYPE 0x2
#define INTEL_ACM_MODULE_SUBTYPE_TXT_ACM 0x0
#define INTEL_ACM_MODULE_SUBTYPE_S_ACM 0x1
#define INTEL_ACM_MODULE_VENDOR 0x8086
typedef struct INTEL_ACM_HEADER_ {
UINT32 ModuleType;
UINT16 ModuleType;
UINT16 ModuleSubtype;
UINT32 HeaderType;
UINT32 HeaderVersion;
UINT16 ChipsetId;
@ -203,4 +206,4 @@ typedef struct BG_KEY_MANIFEST_ {
#pragma pack(pop)
#endif // BOOTGUARD_H
#endif // BOOTGUARD_H

View file

@ -118,3 +118,52 @@ UString sectionTypeToUString(const UINT8 type)
}
}
UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header)
{
if (!header)
return 0;
bool extended = false;
if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) {
extended = true;
}
switch (header->Type)
{
case EFI_SECTION_GUID_DEFINED: {
if (!extended) {
const EFI_GUID_DEFINED_SECTION* gdsHeader = (const EFI_GUID_DEFINED_SECTION*)header;
if (QByteArray((const char*)&gdsHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) {
const WIN_CERTIFICATE* certificateHeader = (const WIN_CERTIFICATE*)(gdsHeader + 1);
return gdsHeader->DataOffset + certificateHeader->Length;
}
return gdsHeader->DataOffset;
}
else {
const EFI_GUID_DEFINED_SECTION2* gdsHeader = (const EFI_GUID_DEFINED_SECTION2*)header;
if (QByteArray((const char*)&gdsHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) {
const WIN_CERTIFICATE* certificateHeader = (const WIN_CERTIFICATE*)(gdsHeader + 1);
return gdsHeader->DataOffset + certificateHeader->Length;
}
return gdsHeader->DataOffset;
}
}
case EFI_SECTION_COMPRESSION: return extended ? sizeof(EFI_COMPRESSION_SECTION2) : sizeof(EFI_COMPRESSION_SECTION);
case EFI_SECTION_DISPOSABLE: return extended ? sizeof(EFI_DISPOSABLE_SECTION2) : sizeof(EFI_DISPOSABLE_SECTION);
case EFI_SECTION_PE32: return extended ? sizeof(EFI_PE32_SECTION2) : sizeof(EFI_PE32_SECTION);
case EFI_SECTION_PIC: return extended ? sizeof(EFI_PIC_SECTION2) : sizeof(EFI_PIC_SECTION);
case EFI_SECTION_TE: return extended ? sizeof(EFI_TE_SECTION2) : sizeof(EFI_TE_SECTION);
case EFI_SECTION_DXE_DEPEX: return extended ? sizeof(EFI_DXE_DEPEX_SECTION2) : sizeof(EFI_DXE_DEPEX_SECTION);
case EFI_SECTION_VERSION: return extended ? sizeof(EFI_VERSION_SECTION2) : sizeof(EFI_VERSION_SECTION);
case EFI_SECTION_USER_INTERFACE: return extended ? sizeof(EFI_USER_INTERFACE_SECTION2) : sizeof(EFI_USER_INTERFACE_SECTION);
case EFI_SECTION_COMPATIBILITY16: return extended ? sizeof(EFI_COMPATIBILITY16_SECTION2) : sizeof(EFI_COMPATIBILITY16_SECTION);
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return extended ? sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION2) : sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION);
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return extended ? sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION2) : sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION);
case EFI_SECTION_RAW: return extended ? sizeof(EFI_RAW_SECTION2) : sizeof(EFI_RAW_SECTION);
case EFI_SECTION_PEI_DEPEX: return extended ? sizeof(EFI_PEI_DEPEX_SECTION2) : sizeof(EFI_PEI_DEPEX_SECTION);
case EFI_SECTION_MM_DEPEX: return extended ? sizeof(EFI_SMM_DEPEX_SECTION2) : sizeof(EFI_SMM_DEPEX_SECTION);
case INSYDE_SECTION_POSTCODE: return extended ? sizeof(POSTCODE_SECTION2) : sizeof(POSTCODE_SECTION);
case PHOENIX_SECTION_POSTCODE: return extended ? sizeof(POSTCODE_SECTION2) : sizeof(POSTCODE_SECTION);
default: return extended ? sizeof(EFI_COMMON_SECTION_HEADER2) : sizeof(EFI_COMMON_SECTION_HEADER);
}
}

View file

@ -26,6 +26,7 @@ extern UString guidToUString(const EFI_GUID& guid, bool convertToString = true);
extern UString fileTypeToUString(const UINT8 type);
extern UString sectionTypeToUString(const UINT8 type);
//*****************************************************************************
// EFI Capsule
//*****************************************************************************
@ -369,6 +370,10 @@ const UByteArray AMI_CORE_DXE_GUID // 5AE3F37E-4EAE-41AE-8240-35465B5E81EB
const UByteArray EFI_DXE_CORE_GUID // D6A2CB7F-6A18-4E2F-B43B-9920A733700A
("\x7F\xCB\xA2\xD6\x18\x6A\x2F\x4E\xB4\x3B\x99\x20\xA7\x33\x70\x0A", 16);
// TXT ACM
const UByteArray EFI_TXT_ACM_GUID // 2D27C618-7DCD-41F5-BB10-21166BE7E143
("\x18\xC6\x27\x2D\xCD\x7D\xF5\x41\xBB\x10\x21\x16\x6B\xE7\xE1\x43", 16);
// FFS size conversion routines
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
@ -432,6 +437,14 @@ typedef struct EFI_COMPRESSION_SECTION_ {
UINT8 CompressionType;
} EFI_COMPRESSION_SECTION;
typedef struct _EFI_COMPRESSION_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
UINT32 UncompressedLength;
UINT8 CompressionType;
} EFI_COMPRESSION_SECTION2;
typedef struct EFI_COMPRESSION_SECTION_APPLE_ {
UINT32 UncompressedLength;
UINT32 CompressionType;
@ -456,6 +469,16 @@ typedef struct EFI_GUID_DEFINED_SECTION_APPLE_ {
UINT32 Reserved;
} EFI_GUID_DEFINED_SECTION_APPLE;
typedef struct _EFI_GUID_DEFINED_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
EFI_GUID SectionDefinitionGuid;
UINT16 DataOffset;
UINT16 Attributes;
} EFI_GUID_DEFINED_SECTION2;
// Attributes for GUID defined section
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
@ -511,16 +534,64 @@ typedef struct EFI_VERSION_SECTION_ {
UINT16 BuildNumber;
} EFI_VERSION_SECTION;
typedef struct _EFI_VERSION_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
UINT16 BuildNumber;
} EFI_VERSION_SECTION2;
// Freeform subtype GUID section
typedef struct EFI_FREEFORM_SUBTYPE_GUID_SECTION_ {
EFI_GUID SubTypeGuid;
} EFI_FREEFORM_SUBTYPE_GUID_SECTION;
typedef struct _EFI_FREEFORM_SUBTYPE_GUID_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
EFI_GUID SubTypeGuid;
} EFI_FREEFORM_SUBTYPE_GUID_SECTION2;
// Phoenix SCT and Insyde postcode section
typedef struct POSTCODE_SECTION_ {
UINT32 Postcode;
} POSTCODE_SECTION;
typedef struct _POSTCODE_SECTION2 {
UINT8 Size[3];
UINT8 Type;
UINT32 ExtendedSize;
UINT32 Postcode;
} POSTCODE_SECTION2;
// Other sections
typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_DISPOSABLE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_SMM_DEPEX_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_USER_INTERFACE_SECTION2;
// Section routines
UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header);
//*****************************************************************************
// EFI Dependency Expression
//*****************************************************************************

File diff suppressed because it is too large Load diff

View file

@ -20,11 +20,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ubytearray.h"
#include "ustring.h"
#include "treemodel.h"
#include "ffsparser.h"
class FfsBuilder
{
public:
FfsBuilder(const TreeModel * treeModel) : model(treeModel) {}
FfsBuilder(const TreeModel * treeModel, FfsParser * ffsParser) : model(treeModel), parser(ffsParser) {}
~FfsBuilder() {}
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
@ -33,7 +36,9 @@ public:
USTATUS build(const UModelIndex & root, UByteArray & image);
private:
const TreeModel* model;
const TreeModel * model;
FfsParser * parser;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
@ -41,17 +46,23 @@ private:
USTATUS buildCapsule(const UModelIndex & index, UByteArray & capsule);
USTATUS buildIntelImage(const UModelIndex & index, UByteArray & intelImage);
USTATUS buildRawArea(const UModelIndex & index, UByteArray & rawArea);
USTATUS buildRawArea(const UModelIndex & index, UByteArray & rawArea, bool includeHeader = true);
USTATUS buildPadding(const UModelIndex & index, UByteArray & padding);
USTATUS buildVolume(const UModelIndex & index, UByteArray & volume);
USTATUS buildNvramVolume(const UModelIndex & index, UByteArray & volume);
USTATUS buildNvramStore(const UModelIndex & index, UByteArray & store);
USTATUS buildNvarStore(const UModelIndex & index, UByteArray & store);
USTATUS buildNonUefiData(const UModelIndex & index, UByteArray & data);
USTATUS buildFreeSpace(const UModelIndex & index, UByteArray & freeSpace);
USTATUS buildPadFile(const UModelIndex & index, UByteArray & padFile);
USTATUS buildFile(const UModelIndex & index, UByteArray & file);
USTATUS buildSection(const UModelIndex & index, UByteArray & section);
USTATUS buildPadFile(const UByteArray &guid, const UINT32 size, const UINT8 revision, const UINT8 erasePolarity, UByteArray & pad);
USTATUS buildFile(const UModelIndex & index, const UINT8 revision, const UINT8 erasePolarity, const UINT32 base, UByteArray & reconstructed);
USTATUS buildSection(const UModelIndex & index, const UINT32 base, UByteArray & reconstructed);
USTATUS buildRegion(const UModelIndex& index, UByteArray & reconstructed, bool includeHeader = true);
// Utility functions
USTATUS erase(const UModelIndex & index, UByteArray & erased);
};
#endif // FFSBUILDER_H

View file

@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsops.h"
#include "ffs.h"
#include "utility.h"
#include "nvramparser.h"
USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteArray & extracted, const UINT8 mode)
{
@ -59,22 +60,114 @@ USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteA
return U_SUCCESS;
}
USTATUS FfsOperations::replace(const UModelIndex & index, const UString & data, const UINT8 mode)
USTATUS FfsOperations::replace(const UModelIndex & index, UByteArray & data, const UINT8 mode)
{
U_UNUSED_PARAMETER(data);
// Sanity check
if (!index.isValid())
if (!index.isValid() || !index.parent().isValid())
return U_INVALID_PARAMETER;
if (mode == REPLACE_MODE_AS_IS) {
return U_NOT_IMPLEMENTED;
USTATUS result;
UByteArray empty = "";
FfsParser parser(model);
UINT32 localOffset = model->offset(index) + model->header(index).size();
UModelIndex index_out;
if(mode == REPLACE_MODE_BODY)
data = model->header(index) + data;
if (model->type(index) == Types::Region) {
UINT8 type = model->subtype(index);
switch (type) {
case Subtypes::BiosRegion:
result = parser.parseBiosRegion(data, localOffset, index, index_out, CREATE_MODE_AFTER);
break;
case Subtypes::MeRegion:
result = parser.parseMeRegion(data, localOffset, index, index_out, CREATE_MODE_AFTER);
break;
case Subtypes::GbeRegion:
result = parser.parseGbeRegion(data, localOffset, index, index_out, CREATE_MODE_AFTER);
break;
case Subtypes::PdrRegion:
result = parser.parsePdrRegion(data, localOffset, index, index_out, CREATE_MODE_AFTER);
break;
default:
return U_NOT_IMPLEMENTED;
}
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
return result;
}
else if (mode == REPLACE_MODE_BODY) {
return U_NOT_IMPLEMENTED;
else if (model->type(index) == Types::Padding) {
// Get info
QString name = usprintf("Padding");
QString info = usprintf("Full size: %Xh (%u)", data.size(), data.size());
// Add tree item
//!TODO UModelIndex fileIndex = model->addItem(Types::Padding, getPaddingType(body), COMPRESSION_ALGORITHM_NONE, name, "", info, UByteArray(), body, index, mode);
}
return U_UNKNOWN_REPLACE_MODE;
else if (model->type(index) == Types::Volume) {
result = parser.parseVolumeHeader(data, localOffset, index, index_out, CREATE_MODE_AFTER);
if (result)
return result;
result = parser.parseVolumeBody(index_out);
if (result)
return result;
}
else if (model->type(index) == Types::File) {
result = parser.parseFileHeader(data, localOffset, index, index_out, CREATE_MODE_AFTER);
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
return result;
result = parser.parseFileBody(index_out);
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
return result;
}
else if (model->type(index) == Types::Section) {
result = parser.parseSectionHeader(data, localOffset, index, index_out, true, CREATE_MODE_AFTER);
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
return result;
result = parser.parseSectionBody(index_out);
if(result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
return result;
}
else if(model->type(index) == Types::EvsaStore || model->type(index) == Types::CmdbStore ||
model->type(index) == Types::FdcStore || model->type(index) == Types::FlashMapStore ||
model->type(index) == Types::FsysStore || model->type(index) == Types::FtwStore ||
model->type(index) == Types::Vss2Store || model->type(index) == Types::VssStore) {
if(data.size() != model->header(index).size() + model->body(index).size())
return U_INVALID_STORE_SIZE;
NvramParser nvramParser(model, &parser);
result = nvramParser.parseStoreHeader(data, localOffset, index, index_out, CREATE_MODE_AFTER);
if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME)
return result;
UINT8 type = model->type(index);
switch (type) {
case Types::FdcStore: nvramParser.parseFdcStoreBody(index_out); break;
case Types::VssStore: nvramParser.parseVssStoreBody(index_out, 0); break;
case Types::Vss2Store: nvramParser.parseVssStoreBody(index_out, 4); break;
case Types::FsysStore: nvramParser.parseFsysStoreBody(index_out); break;
case Types::EvsaStore: nvramParser.parseEvsaStoreBody(index_out); break;
case Types::FlashMapStore: nvramParser.parseFlashMapBody(index_out); break;
}
}
else
return U_NOT_IMPLEMENTED;
// Set remove action to replaced item
model->setAction(index, Actions::Remove);
model->setAction(index_out, Actions::Replace);
// Rebuild parent, if it has no action now
UModelIndex parent = index.parent();
if (parent.isValid() && model->type(parent) != Types::Root
&& model->action(parent) == Actions::NoAction)
rebuild(parent);
return U_SUCCESS;
}
USTATUS FfsOperations::remove(const UModelIndex & index)

View file

@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ubytearray.h"
#include "ustring.h"
#include "treemodel.h"
#include "ffsparser.h"
class FfsOperations
{
@ -32,13 +33,14 @@ public:
void clearMessages() { messagesVector.clear(); }
USTATUS extract(const UModelIndex & index, UString & name, UByteArray & extracted, const UINT8 mode);
USTATUS replace(const UModelIndex & index, const UString & data, const UINT8 mode);
USTATUS replace(const UModelIndex & index, UByteArray & data, const UINT8 mode);
USTATUS remove(const UModelIndex & index);
USTATUS rebuild(const UModelIndex & index);
private:
TreeModel* model;
TreeModel * model;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {

View file

@ -55,7 +55,7 @@ struct REGION_INFO {
// Constructor
FfsParser::FfsParser(TreeModel* treeModel) : model(treeModel),
imageBase(0), addressDiff(0x100000000ULL),
imageBase(0), addressDiff(0x100000000ULL), peiCoreEntryPoint(0), newPeiCoreEntryPoint(0),
bgAcmFound(false), bgKeyManifestFound(false), bgBootPolicyFound(false), bgFirstVolumeOffset(0x100000000ULL) {
nvramParser = new NvramParser(treeModel, this);
meParser = new MeParser(treeModel);
@ -101,6 +101,9 @@ USTATUS FfsParser::parse(const UByteArray & buffer)
USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & index)
{
peiCoreEntryPoint = 0;
newPeiCoreEntryPoint = 0;
// Sanity check
if (buffer.isEmpty()) {
return EFI_INVALID_PARAMETER;
@ -630,7 +633,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
return parseResult;
}
USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Check sanity
if (gbe.isEmpty())
@ -650,12 +653,12 @@ USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 localOffs
version->minor);
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::GbeRegion, name, UString(), info, UByteArray(), gbe, UByteArray(), Fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::GbeRegion, name, UString(), info, UByteArray(), gbe, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Check sanity
if (me.isEmpty())
@ -702,7 +705,7 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset
}
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::MeRegion, name, UString(), info, UByteArray(), me, UByteArray(), Fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::MeRegion, name, UString(), info, UByteArray(), me, UByteArray(), Fixed, parent, mode);
// Show messages
if (emptyRegion) {
@ -718,7 +721,7 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset
return U_SUCCESS;
}
USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Check sanity
if (pdr.isEmpty())
@ -729,7 +732,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
UString info = usprintf("Full size: %Xh (%u)", pdr.size(), pdr.size());
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent, mode);
// Parse PDR region as BIOS space
USTATUS result = parseRawArea(index);
@ -739,7 +742,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
return U_SUCCESS;
}
USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Check sanity
if (region.isEmpty())
@ -750,12 +753,12 @@ USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & re
UString info = usprintf("Full size: %Xh (%u)", region.size(), region.size());
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Sanity check
if (bios.isEmpty())
@ -766,7 +769,7 @@ USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 localOf
UString info = usprintf("Full size: %Xh (%u)", bios.size(), bios.size());
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent, mode);
return parseRawArea(index);
}
@ -907,7 +910,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
return U_SUCCESS;
}
USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Sanity check
if (volume.isEmpty())
@ -1069,7 +1072,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
else if (isNvramVolume)
subtype = Subtypes::NvramVolume;
}
index = model->addItem(model->offset(parent) + localOffset, Types::Volume, subtype, name, text, info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Volume, subtype, name, text, info, header, body, UByteArray(), Fixed, parent, mode);
// Set parsing data for created volume
VOLUME_PARSING_DATA pdata;
@ -1376,7 +1379,7 @@ UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset
return 0;
}
USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
// Sanity check
if (file.isEmpty()) {
@ -1496,6 +1499,7 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
usprintf("\nHeader checksum: %02Xh", fileHeader->IntegrityCheck.Checksum.Header) + (msgInvalidHeaderChecksum ? usprintf(", invalid, should be %02Xh", calculatedHeader) : UString(", valid")) +
usprintf("\nData checksum: %02Xh", fileHeader->IntegrityCheck.Checksum.File) + (msgInvalidDataChecksum ? usprintf(", invalid, should be %02Xh", calculatedData) : UString(", valid"));
UString text;
bool isVtf = false;
bool isDxeCore = false;
@ -1514,12 +1518,62 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
// This information may be used to determine DXE volume offset for old AMI or post-IBB protected ranges
isDxeCore = true;
}
else if (fileGuid == EFI_TXT_ACM_GUID) {
// Detect TXT ACM and update TXT tab
const INTEL_ACM_HEADER* acmHeader = (const INTEL_ACM_HEADER*)body.constData();
// Add ACM header info
txtInfo += usprintf(
"TXT ACM found at offset %Xh\n"
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n"
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n"
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh",
model->offset(parent) + localOffset,
acmHeader->ModuleType,
acmHeader->ModuleSubtype,
acmHeader->ModuleSize * sizeof(UINT32),
acmHeader->HeaderVersion,
acmHeader->ChipsetId,
acmHeader->Flags,
acmHeader->ModuleVendor,
acmHeader->DateDay, acmHeader->DateMonth, acmHeader->DateYear,
acmHeader->ModuleSize * sizeof(UINT32),
acmHeader->EntryPoint,
acmHeader->AcmSvn,
acmHeader->Unknown1,
acmHeader->Unknown2,
acmHeader->GdtBase,
acmHeader->GdtMax,
acmHeader->SegmentSel,
acmHeader->KeySize * sizeof(UINT32),
acmHeader->Unknown4 * sizeof(UINT32)
);
// Add PubKey
txtInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", acmHeader->RsaPubExp);
for (UINT16 i = 0; i < sizeof(acmHeader->RsaPubKey); i++) {
if (i % 32 == 0)
txtInfo += UString("\n");
txtInfo += usprintf("%02X", acmHeader->RsaPubKey[i]);
}
// Add RsaSig
txtInfo += UString("\n\nACM RSA Signature:");
for (UINT16 i = 0; i < sizeof(acmHeader->RsaSig); i++) {
if (i % 32 == 0)
txtInfo += UString("\n");
txtInfo += usprintf("%02X", acmHeader->RsaSig[i]);
}
txtInfo += UString("\n------------------------------------------------------------------------\n\n");
}
// Construct fixed state
ItemFixedState fixed = (ItemFixedState)((fileHeader->Attributes & FFS_ATTRIB_FIXED) != 0);
// Add tree item
index = model->addItem(model->offset(parent) + localOffset, Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parent, mode);
// Set parsing data for created file
FILE_PARSING_DATA pdata;
@ -1763,7 +1817,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
return U_SUCCESS;
}
USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) {
@ -1773,12 +1827,12 @@ USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 l
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
switch (sectionHeader->Type) {
// Special
case EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, localOffset, parent, index, insertIntoTree);
case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, localOffset, parent, index, insertIntoTree);
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, localOffset, parent, index, insertIntoTree);
case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, localOffset, parent, index, insertIntoTree);
case EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
case PHOENIX_SECTION_POSTCODE:
case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, localOffset, parent, index, insertIntoTree);
case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
// Common
case EFI_SECTION_DISPOSABLE:
case EFI_SECTION_DXE_DEPEX:
@ -1790,16 +1844,16 @@ USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 l
case EFI_SECTION_COMPATIBILITY16:
case EFI_SECTION_USER_INTERFACE:
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
case EFI_SECTION_RAW: return parseCommonSectionHeader(section, localOffset, parent, index, insertIntoTree);
case EFI_SECTION_RAW: return parseCommonSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
// Unknown
default:
USTATUS result = parseCommonSectionHeader(section, localOffset, parent, index, insertIntoTree);
USTATUS result = parseCommonSectionHeader(section, localOffset, parent, index, insertIntoTree, mode);
msg(usprintf("%s: section with unknown type %02Xh", __FUNCTION__, sectionHeader->Type), index);
return result;
}
}
USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) {
@ -1847,15 +1901,23 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI
headerSize, headerSize,
body.size(), body.size());
// Special case of PEI Core
if (model->subtype(parent) == EFI_FV_FILETYPE_PEI_CORE
&& peiCoreEntryPoint == 0) {
USTATUS result = getEntryPoint(body, peiCoreEntryPoint);
if (result)
msg("parseCommonSectionHeader: can't get original PEI core entry point", index);
}
// Add tree item
if (insertIntoTree) {
index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent, mode);
}
return U_SUCCESS;
}
USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -1919,7 +1981,7 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons
// Add tree item
if (insertIntoTree) {
index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent, mode);
// Set section parsing data
COMPRESSED_SECTION_PARSING_DATA pdata;
@ -1931,7 +1993,7 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons
return U_SUCCESS;
}
USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2097,7 +2159,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
// Add tree item
if (insertIntoTree) {
index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent, mode);
// Set parsing data
GUIDED_SECTION_PARSING_DATA pdata;
@ -2124,7 +2186,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
return U_SUCCESS;
}
USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2186,7 +2248,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section,
// Add tree item
if (insertIntoTree) {
index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent, mode);
// Set parsing data
FREEFORM_GUIDED_SECTION_PARSING_DATA pdata;
@ -2200,7 +2262,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section,
return U_SUCCESS;
}
USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2260,13 +2322,13 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U
// Add tree item
if (insertIntoTree) {
index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent, mode);
}
return U_SUCCESS;
}
USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree)
USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode)
{
// Check sanity
if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER))
@ -2326,7 +2388,7 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const
// Add tree item
if (insertIntoTree) {
index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent);
index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent, mode);
}
return U_SUCCESS;
@ -3407,6 +3469,9 @@ USTATUS FfsParser::parseFit(const UModelIndex & index)
return U_INVALID_FIT;
}
if (currentEntry->Type == FIT_TYPE_TXT_CONF_POLICY)
parseTxtConfigurationPolicy(currentEntry, info);
// Set item index
if (currentEntry->Address > addressDiff && currentEntry->Address < 0xFFFFFFFFUL) { // Only elements in the image need to be parsed
currentEntryOffset = (UINT32)(currentEntry->Address - addressDiff);
@ -3554,6 +3619,64 @@ 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)
{
U_UNUSED_PARAMETER(info);
const TXT_CONFIG_POLICY* txtCfg = (const TXT_CONFIG_POLICY*)entry;
if(entry->Version == 0) {
txtInfo += usprintf(
"TXT Configuration Policy found (Version = 0)\n"
"Index: %04Xh Bit Position: %02Xh\n"
"Access width in bytes: %02Xh\n"
"Data Register Address: %04Xh\n"
"Index Register Address: %04Xh",
txtCfg->IndexedIOPtrInfo.Index,
txtCfg->IndexedIOPtrInfo.BitPosition,
txtCfg->IndexedIOPtrInfo.AccessWidth,
txtCfg->IndexedIOPtrInfo.DataRegisterAddress,
txtCfg->IndexedIOPtrInfo.IndexRegisterAddress
);
}
else if(entry->Version == 1) {
txtInfo += usprintf(
"TXT Configuration Policy found (Version = 1)\n"
"Physical Address: %16Xh ",
txtCfg->FlatMemoryPtrInfo.FlatMemoryPhysicalAddress
);
txtInfo += txtCfg->FlatMemoryPtrInfo.TxtEnabled ?
"(Bit 0 is zero - Intel TXT disabled)" : "(Bit 0 is 1 - Intel TXT enabled)";
}
else
txtInfo += "\nUnknown version of TXT Configuration Policy";
txtInfo += "\n------------------------------------------------------------------------\n\n";
return U_SUCCESS;
}
@ -3585,16 +3708,18 @@ USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffse
realSize = acmSize;
// Add ACM header info
bootGuardInfo += usprintf(
"Intel ACM found at offset %Xh\n"
"ModuleType: %08Xh HeaderLength: %08Xh HeaderVersion: %08Xh\n"
"ChipsetId: %04Xh Flags: %04Xh ModuleVendor: %04Xh\n"
"Date: %02X.%02X.%04X ModuleSize: %08Xh EntryPoint: %08Xh\n"
"AcmSvn: %04Xh Unknown1: %08Xh Unknown2: %08Xh\n"
"GdtBase: %08Xh GdtMax: %08Xh SegSel: %08Xh\n"
"KeySize: %08Xh Unknown3: %08Xh",
UString acmInfo;
acmInfo += usprintf(
" found at offset %Xh\n"
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n"
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n"
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh",
model->offset(parent) + localOffset,
header->ModuleType,
header->ModuleSubtype,
header->ModuleSize * sizeof(UINT32),
header->HeaderVersion,
header->ChipsetId,
@ -3613,20 +3738,28 @@ USTATUS FfsParser::parseIntelAcm(const UByteArray & acm, const UINT32 localOffse
header->Unknown4 * sizeof(UINT32)
);
// Add PubKey
bootGuardInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", header->RsaPubExp);
acmInfo += usprintf("\n\nACM RSA Public Key (Exponent: %Xh):", header->RsaPubExp);
for (UINT16 i = 0; i < sizeof(header->RsaPubKey); i++) {
if (i % 32 == 0)
bootGuardInfo += UString("\n");
bootGuardInfo += usprintf("%02X", header->RsaPubKey[i]);
acmInfo += UString("\n");
acmInfo += usprintf("%02X", header->RsaPubKey[i]);
}
// Add RsaSig
bootGuardInfo += UString("\n\nACM RSA Signature:");
acmInfo += UString("\n\nACM RSA Signature:");
for (UINT16 i = 0; i < sizeof(header->RsaSig); i++) {
if (i % 32 == 0)
bootGuardInfo += UString("\n");
bootGuardInfo += usprintf("%02X", header->RsaSig[i]);
acmInfo += UString("\n");
acmInfo += usprintf("%02X", header->RsaSig[i]);
}
bootGuardInfo += UString("\n------------------------------------------------------------------------\n\n");
acmInfo += UString("\n------------------------------------------------------------------------\n\n");
if(header->ModuleSubtype == INTEL_ACM_MODULE_SUBTYPE_TXT_ACM)
txtInfo += "TXT ACM (From FIT)" + acmInfo;
else if(header->ModuleSubtype == INTEL_ACM_MODULE_SUBTYPE_S_ACM)
txtInfo += "S-ACM (From FIT)" + acmInfo;
else
bootGuardInfo += "Intel ACM" + acmInfo;
bgAcmFound = true;
return U_SUCCESS;
}

View file

@ -20,6 +20,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ubytearray.h"
#include "treemodel.h"
#include "bootguard.h"
#include "fit.h"
typedef struct BG_PROTECTED_RANGE_
{
@ -60,9 +61,17 @@ public:
// Obtain BootGuardInfo
UString getBootGuardInfo() const { return bootGuardInfo; }
// 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; }
void setNewPeiCoreEntryPoint(UINT32 entry) { newPeiCoreEntryPoint = entry; }
private:
TreeModel *model;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
@ -77,6 +86,8 @@ private:
UModelIndex lastVtf;
UINT32 imageBase;
UINT64 addressDiff;
UINT32 peiCoreEntryPoint;
UINT32 newPeiCoreEntryPoint;
std::vector<std::pair<std::vector<UString>, UModelIndex> > fitTable;
UString bootGuardInfo;
@ -90,6 +101,9 @@ private:
UINT64 bgFirstVolumeOffset;
UModelIndex bgDxeCoreIndex;
UString txtInfo;
UString microcodeInfo;
// First pass
USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index);
@ -98,29 +112,29 @@ private:
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);
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 parseFileHeader(const UByteArray & file, const UINT32 localOffset, const UModelIndex & parent, 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);
USTATUS parseSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseSectionBody(const UModelIndex & index);
USTATUS parseGbeRegion(const UByteArray & gbe, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseGbeRegion(const UByteArray & gbe, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseGenericRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parsePadFileBody(const UModelIndex & index);
USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 localOffset, const UModelIndex & index);
USTATUS parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree);
USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree);
USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseCompressedSectionBody(const UModelIndex & index);
USTATUS parseGuidedSectionBody(const UModelIndex & index);
@ -156,12 +170,15 @@ private:
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);
#endif
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
friend class NvramParser; // Make FFS parsing routines accessible to NvramParser
#endif
friend class FfsOperations;
friend class FfsBuilder;
};
#endif // FFSPARSER_H

View file

@ -65,6 +65,20 @@ typedef struct INTEL_MICROCODE_HEADER_ {
UINT8 Reserved[12];
} INTEL_MICROCODE_HEADER;
typedef union {
struct {
UINT16 IndexRegisterAddress;
UINT16 DataRegisterAddress;
UINT8 AccessWidth;
UINT8 BitPosition;
UINT16 Index;
} IndexedIOPtrInfo;
struct {
UINT64 FlatMemoryPhysicalAddress : 63;
UINT64 TxtEnabled : 1; // bit 0 - configuration policy (0 = TXT Disabled, 1 = TXT Enabled)
} FlatMemoryPtrInfo;
} TXT_CONFIG_POLICY;
#define INTEL_MICROCODE_HEADER_VERSION 0x00000001
#define INTEL_MICROCODE_HEADER_RESERVED_BYTE 0x00
#define INTEL_MICROCODE_HEADER_SIZES_VALID(ptr) (((INTEL_MICROCODE_HEADER*)ptr)->TotalSize - ((INTEL_MICROCODE_HEADER*)ptr)->DataSize == sizeof(INTEL_MICROCODE_HEADER))

View file

@ -764,7 +764,7 @@ USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOff
return U_SUCCESS;
}
USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -808,12 +808,12 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
vssStoreHeader->Unknown);
// Add tree item
index = model->addItem(localOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseVss2StoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseVss2StoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -856,12 +856,12 @@ USTATUS NvramParser::parseVss2StoreHeader(const UByteArray & store, const UINT32
vssStoreHeader->Unknown);
// Add tree item
index = model->addItem(localOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -926,12 +926,12 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32
(ftw32BlockHeader->Crc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
// Add tree item
index = model->addItem(localOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -964,12 +964,12 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32
body.size(), body.size());
// Add tree item
index = model->addItem(localOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1011,12 +1011,12 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32
+ (storedCrc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
// Add tree item
index = model->addItem(localOffset, Types::FsysStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::FsysStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1056,12 +1056,12 @@ USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32
(evsaStoreHeader->Header.Checksum != calculated ? usprintf("%, invalid, should be %02Xh", calculated) : UString(", valid"));
// Add tree item
index = model->addItem(localOffset, Types::EvsaStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::EvsaStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1096,12 +1096,12 @@ USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UI
flashMapHeader->NumEntries);
// Add tree item
index = model->addItem(localOffset, Types::FlashMapStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::FlashMapStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1134,12 +1134,12 @@ USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32
body.size(), body.size());
// Add tree item
index = model->addItem(localOffset, Types::CmdbStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::CmdbStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1176,12 +1176,12 @@ USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT3
pubkeyHeader->Exponent);
// Add tree item
index = model->addItem(localOffset, Types::SlicData, Subtypes::PubkeySlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::SlicData, Subtypes::PubkeySlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1218,12 +1218,12 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3
// Add tree item
index = model->addItem(localOffset, Types::SlicData, Subtypes::MarkerSlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, parent);
index = model->addItem(localOffset, Types::SlicData, Subtypes::MarkerSlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, parent, mode);
return U_SUCCESS;
}
USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index)
USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
@ -1267,12 +1267,12 @@ USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const U
ucodeHeader->CpuFlags);
// Add tree item
index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent);
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)
USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode)
{
const UINT32 dataSize = (const UINT32)store.size();
const UINT32* signature = (const UINT32*)store.constData();
@ -1285,38 +1285,38 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 loc
// Check signature and run parser function needed
// VSS/SVS store
if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE)
return parseVssStoreHeader(store, localOffset, false, parent, index);
return parseVssStoreHeader(store, localOffset, false, parent, index, mode);
// VSS2 store
if (*signature == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 || *signature == NVRAM_VSS2_STORE_GUID_PART1)
return parseVss2StoreHeader(store, localOffset, false, parent, index);
return parseVss2StoreHeader(store, localOffset, false, parent, index, mode);
// FTW store
else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *signature == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1)
return parseFtwStoreHeader(store, localOffset, parent, index);
return parseFtwStoreHeader(store, localOffset, parent, index, mode);
// FDC store
else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE)
return parseFdcStoreHeader(store, localOffset, parent, index);
return parseFdcStoreHeader(store, localOffset, parent, index, mode);
// Apple Fsys/Gaid store
else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *signature == NVRAM_APPLE_GAID_STORE_SIGNATURE)
return parseFsysStoreHeader(store, localOffset, parent, index);
return parseFsysStoreHeader(store, localOffset, parent, index, mode);
// EVSA store
else if (dataSize >= 2 * sizeof(UINT32) && *(signature + 1) == NVRAM_EVSA_STORE_SIGNATURE)
return parseEvsaStoreHeader(store, localOffset, parent, index);
return parseEvsaStoreHeader(store, localOffset, parent, index, mode);
// Phoenix SCT flash map
else if (*signature == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1)
return parseFlashMapStoreHeader(store, localOffset, parent, index);
return parseFlashMapStoreHeader(store, localOffset, parent, index, mode);
// Phoenix CMDB store
else if (*signature == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE)
return parseCmdbStoreHeader(store, localOffset, parent, index);
return parseCmdbStoreHeader(store, localOffset, parent, index, mode);
// SLIC pubkey
else if (dataSize >= 5 * sizeof(UINT32) && *(signature + 4) == OEM_ACTIVATION_PUBKEY_MAGIC)
return parseSlicPubkeyHeader(store, localOffset, parent, index);
return parseSlicPubkeyHeader(store, localOffset, parent, index, mode);
// SLIC marker
else if (dataSize >= 34 && *(const UINT64*)(store.constData() + 26) == OEM_ACTIVATION_MARKER_WINDOWS_FLAG)
return parseSlicMarkerHeader(store, localOffset, parent, index);
return parseSlicMarkerHeader(store, localOffset, parent, index, mode);
// 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);
return 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

@ -39,7 +39,7 @@ public:
// NVRAM parsing
USTATUS parseNvramVolumeBody(const UModelIndex & index);
USTATUS parseNvarStore(const UModelIndex & index);
private:
TreeModel *model;
FfsParser *ffsParser;
@ -50,25 +50,27 @@ private:
USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 localOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset);
USTATUS getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
USTATUS parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index);
USTATUS parseVss2StoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseEvsaStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFlashMapStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseSlicPubkeyHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseVss2StoreHeader(const UByteArray & store, const UINT32 localOffset, const bool sizeOverride, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseEvsaStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
USTATUS parseFlashMapStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const UINT8 mode = CREATE_MODE_APPEND);
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);
USTATUS parseFsysStoreBody(const UModelIndex & index);
USTATUS parseEvsaStoreBody(const UModelIndex & index);
USTATUS parseFlashMapBody(const UModelIndex & index);
friend class FfsOperations;
};
#else
class NvramParser

View file

@ -17,7 +17,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "treemodel.h"
#include "utility.h"
#include "peimage.h"
#include "ffs.h"
#include "basetypes.h"
#include "Tiano/EfiTianoCompress.h"
#include "Tiano/EfiTianoDecompress.h"
#include "LZMA/LzmaCompress.h"
@ -131,6 +133,7 @@ UString errorCodeToUString(USTATUS errorCode)
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
case U_INVALID_CAPSULE: return UString("Invalid capsule");
case U_STORES_NOT_FOUND: return UString("Stores not found");
case U_INVALID_STORE_SIZE: return UString("Invalid store size");
default: return usprintf("Unknown error %02X", errorCode);
}
}
@ -329,6 +332,139 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp
}
}
UINT8 compress(const UByteArray & data, const UINT8 algorithm, UByteArray & compressedData)
{
UINT8* compressed;
switch (algorithm) {
case COMPRESSION_ALGORITHM_NONE:
{
compressedData = data;
return U_SUCCESS;
}
break;
case COMPRESSION_ALGORITHM_EFI11:
{
// Try legacy function first
UINT32 compressedSize = 0;
if (EfiCompressLegacy(data.constData(), data.size(), NULL, &compressedSize) != U_BUFFER_TOO_SMALL)
return U_STANDARD_COMPRESSION_FAILED;
compressed = new UINT8[compressedSize];
if (EfiCompressLegacy(data.constData(), data.size(), compressed, &compressedSize) != U_SUCCESS) {
delete[] compressed;
return U_STANDARD_COMPRESSION_FAILED;
}
compressedData = UByteArray((const char*)compressed, compressedSize);
// Check that compressed data can be decompressed normally
UByteArray decompressed;
UByteArray efiDecompressed;
UINT8 alg = 0; // TODO !!
if (decompress(compressedData, EFI_STANDARD_COMPRESSION, alg, decompressed, efiDecompressed) == U_SUCCESS
&& decompressed == data) {
delete[] compressed;
return U_SUCCESS;
}
delete[] compressed;
// Legacy function failed, use current one
compressedSize = 0;
if (EfiCompress(data.constData(), data.size(), NULL, &compressedSize) != U_BUFFER_TOO_SMALL)
return U_STANDARD_COMPRESSION_FAILED;
compressed = new UINT8[compressedSize];
if (EfiCompress(data.constData(), data.size(), compressed, &compressedSize) != U_SUCCESS) {
delete[] compressed;
return U_STANDARD_COMPRESSION_FAILED;
}
compressedData = UByteArray((const char*)compressed, compressedSize);
// New functions will be trusted here, because another check will reduce performance
delete[] compressed;
return U_SUCCESS;
}
break;
case COMPRESSION_ALGORITHM_TIANO:
{
// Try legacy function first
UINT32 compressedSize = 0;
if (TianoCompressLegacy(data.constData(), data.size(), NULL, &compressedSize) != U_BUFFER_TOO_SMALL)
return U_STANDARD_COMPRESSION_FAILED;
compressed = new UINT8[compressedSize];
if (TianoCompressLegacy(data.constData(), data.size(), compressed, &compressedSize) != U_SUCCESS) {
delete[] compressed;
return U_STANDARD_COMPRESSION_FAILED;
}
compressedData = UByteArray((const char*)compressed, compressedSize);
// Check that compressed data can be decompressed normally
UByteArray decompressed;
UByteArray efiDecompressed;
UINT8 alg = 0; // TODO !!
if (decompress(compressedData, EFI_STANDARD_COMPRESSION, alg, decompressed, efiDecompressed) == U_SUCCESS
&& decompressed == data) {
delete[] compressed;
return U_SUCCESS;
}
delete[] compressed;
// Legacy function failed, use current one
compressedSize = 0;
if (TianoCompress(data.constData(), data.size(), NULL, &compressedSize) != U_BUFFER_TOO_SMALL)
return U_STANDARD_COMPRESSION_FAILED;
compressed = new UINT8[compressedSize];
if (TianoCompress(data.constData(), data.size(), compressed, &compressedSize) != U_SUCCESS) {
delete[] compressed;
return U_STANDARD_COMPRESSION_FAILED;
}
compressedData = UByteArray((const char*)compressed, compressedSize);
// New functions will be trusted here, because another check will reduce performance
delete[] compressed;
return U_SUCCESS;
}
break;
case COMPRESSION_ALGORITHM_LZMA:
{
UINT32 compressedSize = 0;
if (LzmaCompress((const UINT8*)data.constData(), data.size(), NULL, &compressedSize) != U_BUFFER_TOO_SMALL)
return U_CUSTOMIZED_COMPRESSION_FAILED;
compressed = new UINT8[compressedSize];
if (LzmaCompress((const UINT8*)data.constData(), data.size(), compressed, &compressedSize) != U_SUCCESS) {
delete[] compressed;
return U_CUSTOMIZED_COMPRESSION_FAILED;
}
compressedData = UByteArray((const char*)compressed, compressedSize);
delete[] compressed;
return U_SUCCESS;
}
break;
case COMPRESSION_ALGORITHM_IMLZMA:
{
UINT32 compressedSize = 0;
UByteArray header = data.left(sizeof(EFI_COMMON_SECTION_HEADER));
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)header.constData();
UINT32 headerSize = sizeOfSectionHeader(sectionHeader);
header = data.left(headerSize);
UByteArray newData = data.mid(headerSize);
if (LzmaCompress((const UINT8*)newData.constData(), newData.size(), NULL, &compressedSize) != U_BUFFER_TOO_SMALL)
return U_CUSTOMIZED_COMPRESSION_FAILED;
compressed = new UINT8[compressedSize];
if (LzmaCompress((const UINT8*)newData.constData(), newData.size(), compressed, &compressedSize) != U_SUCCESS) {
delete[] compressed;
return U_CUSTOMIZED_COMPRESSION_FAILED;
}
compressedData = header.append(UByteArray((const char*)compressed, compressedSize));
delete[] compressed;
return U_SUCCESS;
}
break;
default:
//msg(usprintf("compress: unknown compression algorithm %1").arg(algorithm));
//return U_UNKNOWN_COMPRESSION_ALGORITHM;
return -1;
}
}
// 8bit sum calculation routine
UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize)
{
@ -414,7 +550,7 @@ INTN findPattern(const UINT8 *pattern, const UINT8 *patternMask, UINTN patternSi
}
BOOLEAN makePattern(const CHAR8 *textPattern, std::vector<UINT8> &pattern, std::vector<UINT8> &patternMask) {
UINTN len = std::strlen(textPattern);
UINTN len = strlen(textPattern);
if (len == 0 || len % 2 != 0)
return FALSE;
@ -441,6 +577,316 @@ BOOLEAN makePattern(const CHAR8 *textPattern, std::vector<UINT8> &pattern, std::
pattern[i] |= static_cast<UINT8>(v2);
}
}
return TRUE;
}
USTATUS getEntryPoint(const UByteArray &file, UINT32& entryPoint)
{
if (file.isEmpty())
return U_INVALID_FILE;
// Populate DOS header
if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER))
return U_INVALID_FILE;
const EFI_IMAGE_DOS_HEADER* dosHeader = (const EFI_IMAGE_DOS_HEADER*)file.constData();
// Check signature
if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){
UINT32 offset = dosHeader->e_lfanew;
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER))
return U_UNKNOWN_IMAGE_TYPE;
const EFI_IMAGE_PE_HEADER* peHeader = (const EFI_IMAGE_PE_HEADER*)(file.constData() + offset);
if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE)
return U_UNKNOWN_IMAGE_TYPE;
offset += sizeof(EFI_IMAGE_PE_HEADER);
// Skip file header
offset += sizeof(EFI_IMAGE_FILE_HEADER);
// Check optional header magic
const UINT16 magic = *(const UINT16*)(file.constData() + offset);
if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) {
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32))
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
const EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER32*)(file.constData() + offset);
entryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint;
}
else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) {
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64))
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
const EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER64*)(file.constData() + offset);
entryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint;
}
else
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
}
else if (dosHeader->e_magic == EFI_IMAGE_TE_SIGNATURE){
// Populate TE header
if ((UINT32)file.size() < sizeof(EFI_IMAGE_TE_HEADER))
return U_INVALID_FILE;
const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)file.constData();
UINT32 teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
entryPoint = teHeader->ImageBase + teHeader->AddressOfEntryPoint - teFixup;
}
return U_SUCCESS;
}
USTATUS getBase(const UByteArray& file, UINT32& base)
{
if (file.isEmpty())
return U_INVALID_FILE;
// Populate DOS header
if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER))
return U_INVALID_FILE;
const EFI_IMAGE_DOS_HEADER* dosHeader = (const EFI_IMAGE_DOS_HEADER*)file.constData();
// Check signature
if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){
UINT32 offset = dosHeader->e_lfanew;
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER))
return U_UNKNOWN_IMAGE_TYPE;
const EFI_IMAGE_PE_HEADER* peHeader = (const EFI_IMAGE_PE_HEADER*)(file.constData() + offset);
if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE)
return U_UNKNOWN_IMAGE_TYPE;
offset += sizeof(EFI_IMAGE_PE_HEADER);
// Skip file header
offset += sizeof(EFI_IMAGE_FILE_HEADER);
// Check optional header magic
const UINT16 magic = *(const UINT16*)(file.constData() + offset);
if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) {
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32))
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
const EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER32*)(file.constData() + offset);
base = optHeader->ImageBase;
}
else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) {
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64))
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
const EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER64*)(file.constData() + offset);
base = optHeader->ImageBase;
}
else
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
}
else if (dosHeader->e_magic == EFI_IMAGE_TE_SIGNATURE){
// Populate TE header
if ((UINT32)file.size() < sizeof(EFI_IMAGE_TE_HEADER))
return U_INVALID_FILE;
const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)file.constData();
//!TODO: add handling
base = teHeader->ImageBase;
}
return U_SUCCESS;
}
USTATUS growVolume(UByteArray & header, const UINT32 size, UINT32 & newSize)
{
// Check sanity
if ((UINT32)header.size() < sizeof(EFI_FIRMWARE_VOLUME_HEADER))
return U_INVALID_VOLUME;
// Adjust new size to be representable by current FvBlockMap
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)header.data();
EFI_FV_BLOCK_MAP_ENTRY* blockMap = (EFI_FV_BLOCK_MAP_ENTRY*)(header.data() + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
// Get block map size
UINT32 blockMapSize = volumeHeader->HeaderLength - sizeof(EFI_FIRMWARE_VOLUME_HEADER);
if (blockMapSize % sizeof(EFI_FV_BLOCK_MAP_ENTRY))
return U_INVALID_VOLUME;
UINT32 blockMapCount = blockMapSize / sizeof(EFI_FV_BLOCK_MAP_ENTRY);
// Check blockMap validity
if (blockMap[blockMapCount - 1].NumBlocks != 0 || blockMap[blockMapCount - 1].Length != 0)
return U_INVALID_VOLUME;
// Case of complex blockMap
if (blockMapCount > 2)
return U_COMPLEX_BLOCK_MAP;
// Calculate new size
if (newSize <= size)
return U_INVALID_PARAMETER;
newSize += blockMap[0].Length - newSize % blockMap[0].Length;
// Recalculate number of blocks
blockMap[0].NumBlocks = newSize / blockMap[0].Length;
// Set new volume size
volumeHeader->FvLength = 0;
for (UINT8 i = 0; i < blockMapCount; i++) {
volumeHeader->FvLength += blockMap[i].NumBlocks * blockMap[i].Length;
}
// Recalculate volume header checksum
volumeHeader->Checksum = 0;
volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength);
return U_SUCCESS;
}
USTATUS rebase(UByteArray &executable, const UINT32 base)
{
UINT32 delta; // Difference between old and new base addresses
UINT32 relocOffset; // Offset of relocation region
UINT32 relocSize; // Size of relocation region
UINT32 teFixup = 0; // Bytes removed form PE header for TE images
// Copy input data to local storage
UByteArray file = executable;
// Populate DOS header
if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER))
return U_INVALID_FILE;
EFI_IMAGE_DOS_HEADER* dosHeader = (EFI_IMAGE_DOS_HEADER*)file.data();
// Check signature
if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){
UINT32 offset = dosHeader->e_lfanew;
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER))
return U_UNKNOWN_IMAGE_TYPE;
EFI_IMAGE_PE_HEADER* peHeader = (EFI_IMAGE_PE_HEADER*)(file.data() + offset);
if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE)
return U_UNKNOWN_IMAGE_TYPE;
offset += sizeof(EFI_IMAGE_PE_HEADER);
// Skip file header
offset += sizeof(EFI_IMAGE_FILE_HEADER);
// Check optional header magic
if ((UINT32)file.size() < offset + sizeof(UINT16))
return U_UNKNOWN_IMAGE_TYPE;
UINT16 magic = *(UINT16*)(file.data() + offset);
if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) {
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32))
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (EFI_IMAGE_OPTIONAL_HEADER32*)(file.data() + offset);
delta = base - optHeader->ImageBase;
if (!delta)
// No need to rebase
return U_SUCCESS;
relocOffset = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
relocSize = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
// Set new base
optHeader->ImageBase = base;
}
else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) {
if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64))
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (EFI_IMAGE_OPTIONAL_HEADER64*)(file.data() + offset);
delta = base - optHeader->ImageBase;
if (!delta)
// No need to rebase
return U_SUCCESS;
relocOffset = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
relocSize = optHeader->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
// Set new base
optHeader->ImageBase = base;
}
else
return U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE;
}
else if (dosHeader->e_magic == EFI_IMAGE_TE_SIGNATURE){
// Populate TE header
if ((UINT32)file.size() < sizeof(EFI_IMAGE_TE_HEADER))
return U_INVALID_FILE;
EFI_IMAGE_TE_HEADER* teHeader = (EFI_IMAGE_TE_HEADER*)file.data();
delta = base - teHeader->ImageBase;
if (!delta)
// No need to rebase
return U_SUCCESS;
relocOffset = teHeader->DataDirectory[EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
relocSize = teHeader->DataDirectory[EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC].Size;
// Set new base
teHeader->ImageBase = base;
// Warn the user about possible outcome of incorrect rebase of TE image
//msg(tr("rebase: can't determine if TE image base is adjusted or not, rebased TE image may stop working"), index);
}
else
return U_UNKNOWN_IMAGE_TYPE;
// No relocations
if (relocOffset == 0) {
// No need to fix relocations
executable = file;
return U_SUCCESS;
}
EFI_IMAGE_BASE_RELOCATION *RelocBase;
EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
UINT16 *Reloc;
UINT16 *RelocEnd;
UINT16 *F16;
UINT32 *F32;
UINT64 *F64;
// Run the whole relocation block
RelocBase = (EFI_IMAGE_BASE_RELOCATION*)(file.data() + relocOffset - teFixup);
RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION*)(file.data() + relocOffset - teFixup + relocSize);
while (RelocBase < RelocBaseEnd) {
Reloc = (UINT16*)((UINT8*)RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION));
RelocEnd = (UINT16*)((UINT8*)RelocBase + RelocBase->SizeOfBlock);
// Run this relocation record
while (Reloc < RelocEnd) {
if (*Reloc == 0x0000) {
// Skip last emtpy reloc entry
Reloc += 1;
continue;
}
UINT32 RelocLocation = RelocBase->VirtualAddress - teFixup + (*Reloc & 0x0FFF);
if ((UINT32)file.size() < RelocLocation)
//return U_BAD_RELOCATION_ENTRY;
return U_UNKNOWN_RELOCATION_TYPE;
UINT8* data = (UINT8*)(file.data() + RelocLocation);
switch ((*Reloc) >> 12) {
case EFI_IMAGE_REL_BASED_ABSOLUTE:
// Do nothing
break;
case EFI_IMAGE_REL_BASED_HIGH:
// Add second 16 bits of delta
F16 = (UINT16*)data;
*F16 = (UINT16)(*F16 + (UINT16)(((UINT32)delta) >> 16));
break;
case EFI_IMAGE_REL_BASED_LOW:
// Add first 16 bits of delta
F16 = (UINT16*)data;
*F16 = (UINT16)(*F16 + (UINT16)delta);
break;
case EFI_IMAGE_REL_BASED_HIGHLOW:
// Add first 32 bits of delta
F32 = (UINT32*)data;
*F32 = *F32 + (UINT32)delta;
break;
case EFI_IMAGE_REL_BASED_DIR64:
// Add all 64 bits of delta
F64 = (UINT64*)data;
*F64 = *F64 + (UINT64)delta;
break;
default:
return U_UNKNOWN_RELOCATION_TYPE;
}
// Next relocation record
Reloc += 1;
}
// Next relocation block
RelocBase = (EFI_IMAGE_BASE_RELOCATION*)RelocEnd;
}
executable = file;
return U_SUCCESS;
}

View file

@ -31,6 +31,7 @@ UString errorCodeToUString(USTATUS errorCode);
USTATUS decompress(const UByteArray & compressed, const UINT8 compressionType, UINT8 & algorithm, UByteArray & decompressed, UByteArray & efiDecompressed);
// Compression routine
UINT8 compress(const UByteArray & data, const UINT8 algorithm, UByteArray & compressedData);
//USTATUS compress(const UByteArray & decompressed, UByteArray & compressed, const UINT8 & algorithm);
// CRC32 calculation routine
@ -55,4 +56,13 @@ BOOLEAN makePattern(const CHAR8 *textPattern, std::vector<UINT8> &pattern, std::
INTN findPattern(const UINT8 *pattern, const UINT8 *patternMask, UINTN patternSize,
const UINT8 *data, UINTN dataSize, UINTN dataOff);
// Image base adress
USTATUS getBase(const UByteArray& file, UINT32& base);
// Entry point
USTATUS getEntryPoint(const UByteArray& file, UINT32 &entryPoint);
USTATUS growVolume(UByteArray & header, const UINT32 size, UINT32 & newSize);
USTATUS rebase(UByteArray &executable, const UINT32 base);
#endif // UTILITY_H