Add Apple SysF/Diag parser

This commit is contained in:
Nikolaj Schlej 2025-02-24 18:12:02 +07:00
parent 2d6eaa917f
commit 4e600eb986
17 changed files with 597 additions and 154 deletions

View file

@ -35,6 +35,7 @@ SET(PROJECT_SOURCES
../common/bstrlib/bstrlib.c ../common/bstrlib/bstrlib.c
../common/bstrlib/bstrwrap.cpp ../common/bstrlib/bstrwrap.cpp
../common/generated/ami_nvar.cpp ../common/generated/ami_nvar.cpp
../common/generated/apple_sysf.cpp
../common/generated/edk2_vss.cpp ../common/generated/edk2_vss.cpp
../common/generated/edk2_vss2.cpp ../common/generated/edk2_vss2.cpp
../common/generated/edk2_ftw.cpp ../common/generated/edk2_ftw.cpp

View file

@ -32,6 +32,7 @@ SET(PROJECT_SOURCES
../common/bstrlib/bstrlib.c ../common/bstrlib/bstrlib.c
../common/bstrlib/bstrwrap.cpp ../common/bstrlib/bstrwrap.cpp
../common/generated/ami_nvar.cpp ../common/generated/ami_nvar.cpp
../common/generated/apple_sysf.cpp
../common/generated/edk2_vss.cpp ../common/generated/edk2_vss.cpp
../common/generated/edk2_vss2.cpp ../common/generated/edk2_vss2.cpp
../common/generated/edk2_ftw.cpp ../common/generated/edk2_ftw.cpp

View file

@ -68,6 +68,7 @@ SET(PROJECT_SOURCES
../common/digest/sha512.c ../common/digest/sha512.c
../common/digest/sm3.c ../common/digest/sm3.c
../common/generated/ami_nvar.cpp ../common/generated/ami_nvar.cpp
../common/generated/apple_sysf.cpp
../common/generated/edk2_vss.cpp ../common/generated/edk2_vss.cpp
../common/generated/edk2_vss2.cpp ../common/generated/edk2_vss2.cpp
../common/generated/edk2_ftw.cpp ../common/generated/edk2_ftw.cpp

View file

@ -466,7 +466,7 @@ void QHexView::checkState() {
int doclines = static_cast<int>(this->lines()), int doclines = static_cast<int>(this->lines()),
vislines = this->visibleLines(true); vislines = this->visibleLines(true);
qint64 vscrollmax = doclines - vislines; qint64 vscrollmax = doclines - vislines + 1; // UEFITool: ensure the very last line is visible on macOS
if(doclines >= vislines) if(doclines >= vislines)
vscrollmax++; vscrollmax++;

View file

@ -245,7 +245,7 @@ void UEFITool::populateUi(const QModelIndex &current)
|| type == Types::SlicData || type == Types::SlicData
|| type == Types::NvarEntry || type == Types::NvarEntry
|| type == Types::VssEntry || type == Types::VssEntry
|| type == Types::FsysEntry || type == Types::SysFEntry
|| type == Types::EvsaEntry || type == Types::EvsaEntry
|| type == Types::FlashMapEntry || type == Types::FlashMapEntry
|| type == Types::IfwiHeader || type == Types::IfwiHeader
@ -263,7 +263,7 @@ void UEFITool::populateUi(const QModelIndex &current)
ui->menuStoreActions->setEnabled(type == Types::VssStore ui->menuStoreActions->setEnabled(type == Types::VssStore
|| type == Types::Vss2Store || type == Types::Vss2Store
|| type == Types::FdcStore || type == Types::FdcStore
|| type == Types::FsysStore || type == Types::SysFStore
|| type == Types::EvsaStore || type == Types::EvsaStore
|| type == Types::FtwStore || type == Types::FtwStore
|| type == Types::FlashMapStore || type == Types::FlashMapStore
@ -907,7 +907,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
case Types::VssStore: case Types::VssStore:
case Types::Vss2Store: case Types::Vss2Store:
case Types::FdcStore: case Types::FdcStore:
case Types::FsysStore: case Types::SysFStore:
case Types::EvsaStore: case Types::EvsaStore:
case Types::FtwStore: case Types::FtwStore:
case Types::FlashMapStore: case Types::FlashMapStore:

View file

@ -51,6 +51,11 @@ HEADERS += uefitool.h \
../common/digest/sha2.h \ ../common/digest/sha2.h \
../common/digest/sm3.h \ ../common/digest/sm3.h \
../common/generated/ami_nvar.h \ ../common/generated/ami_nvar.h \
../common/generated/apple_sysf.h \
../common/generated/edk2_vss.h \
../common/generated/edk2_vss2.h \
../common/generated/edk2_ftw.h \
../common/generated/insyde_fdc.h \
../common/generated/intel_acbp_v1.h \ ../common/generated/intel_acbp_v1.h \
../common/generated/intel_acbp_v2.h \ ../common/generated/intel_acbp_v2.h \
../common/generated/intel_keym_v1.h \ ../common/generated/intel_keym_v1.h \
@ -118,6 +123,11 @@ SOURCES += uefitool_main.cpp \
../common/digest/sha512.c \ ../common/digest/sha512.c \
../common/digest/sm3.c \ ../common/digest/sm3.c \
../common/generated/ami_nvar.cpp \ ../common/generated/ami_nvar.cpp \
../common/generated/apple_sysf.cpp \
../common/generated/edk2_vss.cpp \
../common/generated/edk2_vss2.cpp \
../common/generated/edk2_ftw.cpp \
../common/generated/insyde_fdc.cpp \
../common/generated/intel_acbp_v1.cpp \ ../common/generated/intel_acbp_v1.cpp \
../common/generated/intel_acbp_v2.cpp \ ../common/generated/intel_acbp_v2.cpp \
../common/generated/intel_keym_v1.cpp \ ../common/generated/intel_keym_v1.cpp \

View file

@ -0,0 +1,115 @@
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "apple_sysf.h"
#include "../kaitai/exceptions.h"
apple_sysf_t::apple_sysf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, apple_sysf_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this; (void)p__root;
m_body = nullptr;
m__io__raw_body = nullptr;
f_len_sysf_store_header = false;
_read();
}
void apple_sysf_t::_read() {
m_signature = m__io->read_u4le();
{
uint32_t _ = signature();
if (!( ((_ == 1937339206) || (_ == 1684627783)) )) {
throw kaitai::validation_expr_error<uint32_t>(signature(), _io(), std::string("/seq/0"));
}
}
m_unknown = m__io->read_u1();
m_unknown1 = m__io->read_u4le();
m_sysf_size = m__io->read_u2le();
m__raw_body = m__io->read_bytes(((sysf_size() - len_sysf_store_header()) - 4));
m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
m_body = std::unique_ptr<sysf_store_body_t>(new sysf_store_body_t(m__io__raw_body.get(), this, m__root));
m_crc = m__io->read_u4le();
}
apple_sysf_t::~apple_sysf_t() {
_clean_up();
}
void apple_sysf_t::_clean_up() {
}
apple_sysf_t::sysf_store_body_t::sysf_store_body_t(kaitai::kstream* p__io, apple_sysf_t* p__parent, apple_sysf_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_variables = nullptr;
m_zeroes = nullptr;
_read();
}
void apple_sysf_t::sysf_store_body_t::_read() {
m_variables = std::unique_ptr<std::vector<std::unique_ptr<sysf_variable_t>>>(new std::vector<std::unique_ptr<sysf_variable_t>>());
{
int i = 0;
sysf_variable_t* _;
do {
_ = new sysf_variable_t(m__io, this, m__root);
m_variables->push_back(std::move(std::unique_ptr<sysf_variable_t>(_)));
i++;
} while (!( (( ((_->len_name() == 3) && (_->name() == (std::string("EOF")))) ) || (_io()->is_eof())) ));
}
m_zeroes = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
{
int i = 0;
while (!m__io->is_eof()) {
m_zeroes->push_back(std::move(m__io->read_u1()));
i++;
}
}
}
apple_sysf_t::sysf_store_body_t::~sysf_store_body_t() {
_clean_up();
}
void apple_sysf_t::sysf_store_body_t::_clean_up() {
}
apple_sysf_t::sysf_variable_t::sysf_variable_t(kaitai::kstream* p__io, apple_sysf_t::sysf_store_body_t* p__parent, apple_sysf_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
_read();
}
void apple_sysf_t::sysf_variable_t::_read() {
m_len_name = m__io->read_bits_int_le(7);
m_invalid_flag = m__io->read_bits_int_le(1);
m__io->align_to_byte();
m_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(m__io->read_bytes(len_name()), 0, false), std::string("ascii"));
n_len_data = true;
if (name() != std::string("EOF")) {
n_len_data = false;
m_len_data = m__io->read_u2le();
}
n_data = true;
if (name() != std::string("EOF")) {
n_data = false;
m_data = m__io->read_bytes(len_data());
}
}
apple_sysf_t::sysf_variable_t::~sysf_variable_t() {
_clean_up();
}
void apple_sysf_t::sysf_variable_t::_clean_up() {
if (!n_len_data) {
}
if (!n_data) {
}
}
int8_t apple_sysf_t::len_sysf_store_header() {
if (f_len_sysf_store_header)
return m_len_sysf_store_header;
m_len_sysf_store_header = 11;
f_len_sysf_store_header = true;
return m_len_sysf_store_header;
}

View file

@ -0,0 +1,129 @@
#pragma once
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "../kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <vector>
#if KAITAI_STRUCT_VERSION < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif
class apple_sysf_t : public kaitai::kstruct {
public:
class sysf_store_body_t;
class sysf_variable_t;
apple_sysf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, apple_sysf_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~apple_sysf_t();
class sysf_store_body_t : public kaitai::kstruct {
public:
sysf_store_body_t(kaitai::kstream* p__io, apple_sysf_t* p__parent = nullptr, apple_sysf_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~sysf_store_body_t();
private:
std::unique_ptr<std::vector<std::unique_ptr<sysf_variable_t>>> m_variables;
std::unique_ptr<std::vector<uint8_t>> m_zeroes;
apple_sysf_t* m__root;
apple_sysf_t* m__parent;
public:
std::vector<std::unique_ptr<sysf_variable_t>>* variables() const { return m_variables.get(); }
std::vector<uint8_t>* zeroes() const { return m_zeroes.get(); }
apple_sysf_t* _root() const { return m__root; }
apple_sysf_t* _parent() const { return m__parent; }
};
class sysf_variable_t : public kaitai::kstruct {
public:
sysf_variable_t(kaitai::kstream* p__io, apple_sysf_t::sysf_store_body_t* p__parent = nullptr, apple_sysf_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~sysf_variable_t();
private:
uint64_t m_len_name;
bool m_invalid_flag;
std::string m_name;
uint16_t m_len_data;
bool n_len_data;
public:
bool _is_null_len_data() { len_data(); return n_len_data; };
private:
std::string m_data;
bool n_data;
public:
bool _is_null_data() { data(); return n_data; };
private:
apple_sysf_t* m__root;
apple_sysf_t::sysf_store_body_t* m__parent;
public:
uint64_t len_name() const { return m_len_name; }
bool invalid_flag() const { return m_invalid_flag; }
std::string name() const { return m_name; }
uint16_t len_data() const { return m_len_data; }
std::string data() const { return m_data; }
apple_sysf_t* _root() const { return m__root; }
apple_sysf_t::sysf_store_body_t* _parent() const { return m__parent; }
};
private:
bool f_len_sysf_store_header;
int8_t m_len_sysf_store_header;
public:
int8_t len_sysf_store_header();
private:
uint32_t m_signature;
uint8_t m_unknown;
uint32_t m_unknown1;
uint16_t m_sysf_size;
std::unique_ptr<sysf_store_body_t> m_body;
uint32_t m_crc;
apple_sysf_t* m__root;
kaitai::kstruct* m__parent;
std::string m__raw_body;
std::unique_ptr<kaitai::kstream> m__io__raw_body;
public:
uint32_t signature() const { return m_signature; }
uint8_t unknown() const { return m_unknown; }
uint32_t unknown1() const { return m_unknown1; }
uint16_t sysf_size() const { return m_sysf_size; }
sysf_store_body_t* body() const { return m_body.get(); }
uint32_t crc() const { return m_crc; }
apple_sysf_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
std::string _raw_body() const { return m__raw_body; }
kaitai::kstream* _io__raw_body() const { return m__io__raw_body.get(); }
};

60
common/ksy/apple_fsys.ksy Normal file
View file

@ -0,0 +1,60 @@
meta:
id: apple_sysf
title: Apple system variable store
application: Apple MacEFI-based UEFI firmware
file-extension: sysf
tags:
- firmware
license: CC0-1.0
ks-version: 0.9
endian: le
seq:
- id: signature
type: u4
valid:
expr: _ == 0x73797346 or _ == 0x64696147 # Fsys/Gaid
- id: unknown
type: u1
- id: unknown1
type: u4
- id: sysf_size
type: u2
- id: body
type: sysf_store_body
size: sysf_size - len_sysf_store_header - sizeof<u4>
- id: crc
type: u4
instances:
len_sysf_store_header:
value: 11
types:
sysf_store_body:
seq:
- id: variables
type: sysf_variable
repeat: until
repeat-until: (_.len_name == 3 and _.name == "EOF") or _io.eof
- id: zeroes
type: u1
repeat: eos
sysf_variable:
seq:
- id: len_name
type: b7le
- id: invalid_flag
type: b1le
- id: name
type: strz
encoding: ascii
size: len_name
- id: len_data
type: u2
if: name != "EOF"
- id: data
size: len_data
if: name != "EOF"

View file

@ -33,6 +33,11 @@ uefitoolcommon = static_library('uefitoolcommon',
'utility.cpp', 'utility.cpp',
'ustring.cpp', 'ustring.cpp',
'generated/ami_nvar.cpp', 'generated/ami_nvar.cpp',
'generated/apple_sysf.cpp',
'generated/edk2_vss.cpp',
'generated/edk2_vss2.cpp',
'generated/edk2_ftw.cpp',
'generated/insyde_fdc.cpp',
'generated/intel_acbp_v1.cpp', 'generated/intel_acbp_v1.cpp',
'generated/intel_acbp_v2.cpp', 'generated/intel_acbp_v2.cpp',
'generated/intel_keym_v1.cpp', 'generated/intel_keym_v1.cpp',

View file

@ -70,8 +70,8 @@ extern const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID; // 00504624-8A59-4EE
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS #define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS #define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
#define NVRAM_APPLE_NSS_STORE_SIGNATURE 0x53534E24 // $NSS #define NVRAM_APPLE_NSS_STORE_SIGNATURE 0x53534E24 // $NSS
#define NVRAM_APPLE_FSYS_STORE_SIGNATURE 0x73797346 // Fsys #define NVRAM_APPLE_SYSF_STORE_SIGNATURE 0x73797346 // Fsys
#define NVRAM_APPLE_GAID_STORE_SIGNATURE 0x64696147 // Gaid #define NVRAM_APPLE_DIAG_STORE_SIGNATURE 0x64696147 // Gaid
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA #define NVRAM_VSS_VARIABLE_START_ID 0x55AA
// Variable store header flags // Variable store header flags
@ -229,15 +229,15 @@ typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64_ {
} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64; } EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64;
// //
// Apple Fsys store // Apple System Flags store
// //
typedef struct APPLE_FSYS_STORE_HEADER_ { typedef struct APPLE_SYSF_STORE_HEADER_ {
UINT32 Signature; // Fsys or Gaid signature UINT32 Signature; // Fsys or Gaid signature
UINT8 Unknown0; // Still unknown UINT8 Unknown0; // Still unknown
UINT32 Unknown1; // Still unknown UINT32 Unknown1; // Still unknown
UINT16 Size; // Size of variable store UINT16 Size; // Size of variable store
} APPLE_FSYS_STORE_HEADER; } APPLE_SYSF_STORE_HEADER;
// Apple Fsys entry format // Apple Fsys entry format
// UINT8 NameLength; // UINT8 NameLength;

View file

@ -26,6 +26,7 @@
#include "umemstream.h" #include "umemstream.h"
#include "kaitai/kaitaistream.h" #include "kaitai/kaitaistream.h"
#include "generated/ami_nvar.h" #include "generated/ami_nvar.h"
#include "generated/apple_sysf.h"
#include "generated/edk2_vss.h" #include "generated/edk2_vss.h"
#include "generated/edk2_vss2.h" #include "generated/edk2_vss2.h"
#include "generated/edk2_ftw.h" #include "generated/edk2_ftw.h"
@ -72,7 +73,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size()); UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
if ((UINT32)padding.count(0xFF) == unparsedSize) { // Free space if ((UINT32)padding.count('\'xFF') == unparsedSize) { // Free space
// Add tree item // Add tree item
model->addItem(localOffset + entry->offset(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(localOffset + entry->offset(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
} }
@ -312,7 +313,6 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
for (UINT32 storeOffset = 0; for (UINT32 storeOffset = 0;
storeOffset < volumeBodySize; storeOffset < volumeBodySize;
storeOffset++) { storeOffset++) {
bool storeFound = false;
// VSS // VSS
try { try {
if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) { if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) {
@ -375,18 +375,18 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
// Add header tree item // Add header tree item
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
// Add variables
UINT32 vssVariableOffset = storeOffset + parsed.len_vss_store_header(); UINT32 vssVariableOffset = storeOffset + parsed.len_vss_store_header();
for (const auto & variable : *parsed.body()->variables()) { for (const auto & variable : *parsed.body()->variables()) {
UINT8 subtype; UINT8 subtype;
UString text; UString text;
info.clear();
name.clear();
// This is thew terminating entry, needs special processing // This is the terminating entry, needs special processing
if (variable->_is_null_signature_last()) { if (variable->_is_null_signature_last()) {
// Add free space or padding after all variables, if needed // Add free space or padding after all variables, if needed
if (vssVariableOffset < storeSize) { UINT32 freeSpaceOffset = vssVariableOffset - storeOffset;
UByteArray freeSpace = vss.mid(vssVariableOffset, storeSize - vssVariableOffset); if (freeSpaceOffset < storeSize) {
UByteArray freeSpace = vss.mid(freeSpaceOffset, storeSize - freeSpaceOffset);
// Add info // Add info
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
@ -493,9 +493,9 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
vssVariableOffset += variableSize; vssVariableOffset += variableSize;
} }
storeFound = true; storeOffset += storeSize - 1;
storeOffset += storeSize; previousStoreEndOffset = storeOffset + 1;
previousStoreEndOffset = storeOffset; continue;
} catch (...) { } catch (...) {
// Parsing failed, try something else // Parsing failed, try something else
} }
@ -513,7 +513,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data(); VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data();
UByteArray guid = UByteArray((const char*)&vss2Header->Signature, sizeof(EFI_GUID)); UByteArray guid = UByteArray((const char*)&vss2Header->Signature, sizeof(EFI_GUID));
bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && guid == NVRAM_FDC_STORE_GUID && vss2Header->Size == 0xFFFFFFFF); bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && guid == NVRAM_FDC_STORE_GUID && vss2Header->Size == 0xFFFFFFFF);
if (fdcStoreSizeOverride) { if (fdcHeaderSizeOverrideRequired) {
originalStoreSize = vss2Header->Size; originalStoreSize = vss2Header->Size;
vss2Header->Size = fdcStoreSizeOverride; vss2Header->Size = fdcStoreSizeOverride;
} }
@ -522,7 +522,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
edk2_vss2_t parsed(&ks); edk2_vss2_t parsed(&ks);
UINT32 storeSize = parsed.vss2_size(); UINT32 storeSize = parsed.vss2_size();
// Restore original store size, if needed // Restore original store size, if needed
if (fdcStoreSizeOverride) { if (fdcHeaderSizeOverrideRequired) {
vss2Header->Size = originalStoreSize; vss2Header->Size = originalStoreSize;
} }
@ -563,18 +563,18 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
// Add header tree item // Add header tree item
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
// Add variables
UINT32 vss2VariableOffset = storeOffset + parsed.len_vss2_store_header(); UINT32 vss2VariableOffset = storeOffset + parsed.len_vss2_store_header();
for (const auto & variable : *parsed.body()->variables()) { for (const auto & variable : *parsed.body()->variables()) {
UINT8 subtype; UINT8 subtype;
UString text; UString text;
info.clear();
name.clear();
// This is thew terminating entry, needs special processing // This is the terminating entry, needs special processing
if (variable->_is_null_signature_last()) { if (variable->_is_null_signature_last()) {
// Add free space or padding after all variables, if needed // Add free space or padding after all variables, if needed
if (vss2VariableOffset < storeSize) { UINT32 freeSpaceOffset = vss2VariableOffset - storeOffset;
UByteArray freeSpace = vss2.mid(vss2VariableOffset, storeSize - vss2VariableOffset); if (freeSpaceOffset < storeSize) {
UByteArray freeSpace = vss2.mid(freeSpaceOffset, storeSize - freeSpaceOffset);
// Add info // Add info
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
@ -651,140 +651,247 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
vss2VariableOffset += variableSize; vss2VariableOffset += variableSize;
} }
storeFound = true; storeOffset += storeSize - 1;
storeOffset += storeSize; previousStoreEndOffset = storeOffset + 1;
previousStoreEndOffset = storeOffset; continue;
} catch (...) { } catch (...) {
// Parsing failed, try something else // Parsing failed, try something else
} }
// Do not try any other parsers if we are here for FDC store parsing // Do not try any other parsers if we are here for FDC store parsing
if (fdcStoreSizeOverride == 0) { if (fdcStoreSizeOverride != 0) {
// FTW continue;
try { }
if (volumeBodySize - storeOffset < sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32)) { // FTW
// No need to parse further, the rest of the volume is too small try {
throw 0; if (volumeBodySize - storeOffset < sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32)) {
} // No need to parse further, the rest of the volume is too small
throw 0;
}
UByteArray ftw = volumeBody.mid(storeOffset); UByteArray ftw = volumeBody.mid(storeOffset);
umemstream is(ftw.constData(), ftw.size()); umemstream is(ftw.constData(), ftw.size());
kaitai::kstream ks(&is); kaitai::kstream ks(&is);
edk2_ftw_t parsed(&ks); edk2_ftw_t parsed(&ks);
UINT64 storeSize; UINT64 storeSize;
UINT64 headerSize; UINT64 headerSize;
UINT32 calculatedCrc; UINT32 calculatedCrc;
UByteArray header; UByteArray header;
if (parsed._is_null_len_write_queue_64()) { if (parsed._is_null_len_write_queue_64()) {
headerSize = parsed.len_ftw_store_header_32(); headerSize = parsed.len_ftw_store_header_32();
storeSize = headerSize + parsed.len_write_queue_32(); storeSize = headerSize + parsed.len_write_queue_32();
header = ftw.left(headerSize); header = ftw.left(headerSize);
// Check block header checksum // Check block header checksum
UByteArray crcHeader = header; UByteArray crcHeader = header;
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)crcHeader.data(); EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)crcHeader.data();
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0; crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0; crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize); calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
}
else {
headerSize = parsed.len_ftw_store_header_64();
storeSize = headerSize + parsed.len_write_queue_32() + (((UINT64)parsed.len_write_queue_64()) << 32);
header = ftw.left(headerSize);
// Check block header checksum
UByteArray crcHeader = header;
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)crcHeader.data();
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
}
// FTW store at current offset parsed correctly
// Check if we need to add a padding before it
if (!outerPadding.isEmpty()) {
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
outerPadding.clear();
}
// Construct header and body
UByteArray body = ftw.mid(header.size(), storeSize - header.size());
// Add info
const EFI_GUID* guid = (const EFI_GUID*)header.constData();
UString name = UString("FTW store");
UString info = UString("Signature: ") + guidToUString(*guid, false);
info += usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh",
(UINT32)storeSize, (UINT32)storeSize,
(UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size(),
parsed.state(),
parsed.crc()) + (parsed.crc() != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
// Add header tree item
model->addItem(localOffset + storeOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
storeOffset += storeSize - 1;
previousStoreEndOffset = storeOffset + 1;
continue;
} catch (...) {
// Parsing failed, try something else
}
// Insyde FDC
try {
if (volumeBodySize - storeOffset < sizeof(FDC_VOLUME_HEADER)) {
// No need to parse further, the rest of the volume is too small
throw 0;
}
UByteArray fdc = volumeBody.mid(storeOffset);
umemstream is(fdc.constData(), fdc.size());
kaitai::kstream ks(&is);
insyde_fdc_t parsed(&ks);
UINT32 storeSize = parsed.fdc_size();
// FDC store at current offset parsed correctly
// Check if we need to add a padding before it
if (!outerPadding.isEmpty()) {
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
outerPadding.clear();
}
// Construct header and body
UByteArray header = fdc.left(parsed.len_fdc_store_header());
UByteArray body = fdc.mid(header.size(),storeSize - header.size());
// Add info
UString name = UString("FDC store");
UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
storeSize, storeSize,
(UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size());
// Add header tree item
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
// Parse FDC body as normal VSS/VSS2 storage with size override
parseNvramVolumeBody(headerIndex, (UINT32)body.size());
storeOffset += storeSize - 1;
previousStoreEndOffset = storeOffset + 1;
continue;
} catch (...) {
// Parsing failed, try something else
}
// Apple SysF
try {
if (volumeBodySize - storeOffset < sizeof(APPLE_SYSF_STORE_HEADER)) {
// No need to parse further, the rest of the volume is too small
throw 0;
}
UByteArray sysf = volumeBody.mid(storeOffset);
umemstream is(sysf.constData(), sysf.size());
kaitai::kstream ks(&is);
apple_sysf_t parsed(&ks);
UINT32 storeSize = parsed.sysf_size();
// Apple SysF store at current offset parsed correctly
// Check if we need to add a padding before it
if (!outerPadding.isEmpty()) {
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
outerPadding.clear();
}
// Construct header and body
UByteArray header = sysf.left(parsed.len_sysf_store_header());
UByteArray body = sysf.mid(header.size(), storeSize - header.size());
// Check store checksum
UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)sysf.constData(), storeSize - sizeof(UINT32));
// Add info
UString name;
UString info;
if (parsed.signature() == NVRAM_APPLE_SYSF_STORE_SIGNATURE) {
name = UString("SysF store");
info = UString("Signature: Fsys\n");
}
else {
name = UString("Diag store");
info = UString("Signature: Gaid\n");
}
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nUnknown: %02Xh\nUnknown1: %08Xh\nCRC32: %08Xh",
storeSize, storeSize,
(UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size(),
parsed.unknown(),
parsed.unknown1(),
parsed.crc()) + (parsed.crc() != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
// Add header tree item
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::SysFStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
// Add variables
UINT32 sysfVariableOffset = storeOffset + parsed.len_sysf_store_header();
for (const auto & variable : *parsed.body()->variables()) {
UINT8 subtype;
if (variable->invalid_flag()) {
subtype = Subtypes::InvalidSysFEntry;
name = UString("Invalid");
} }
else { else {
headerSize = parsed.len_ftw_store_header_64(); subtype = Subtypes::NormalSysFEntry;
storeSize = headerSize + parsed.len_write_queue_32() + (((UINT64)parsed.len_write_queue_64()) << 32); name = usprintf("%s", variable->name().c_str());
header = ftw.left(headerSize);
// Check block header checksum
UByteArray crcHeader = header;
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)crcHeader.data();
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
} }
if (variable->len_name() == 3 && variable->name() == "EOF") {
// FTW store at current offset parsed correctly header = volumeBody.mid(sysfVariableOffset, 4);
// Check if we need to add a padding before it
if (!outerPadding.isEmpty()) {
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
outerPadding.clear();
} }
else {
// Construct header and body header = volumeBody.mid(sysfVariableOffset, sizeof(UINT8) + (UINT32)variable->len_name() + sizeof(UINT16));
UByteArray body = ftw.mid(header.size(), storeSize - header.size()); body = volumeBody.mid(sysfVariableOffset + header.size(), (UINT32)variable->len_data());
}
// Add info // Add generic info
const EFI_GUID* guid = (const EFI_GUID*)header.constData(); UINT32 variableSize = (UINT32)header.size() + (UINT32)body.size();
UString name = UString("FTW store"); info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n",
UString info = UString("Signature: ") + guidToUString(*guid, false); variableSize, variableSize,
info += usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh",
(UINT32)storeSize, (UINT32)storeSize,
(UINT32)header.size(), (UINT32)header.size(), (UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size(), (UINT32)body.size(), (UINT32)body.size());
parsed.state(),
parsed.crc()) + (parsed.crc() != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
// Add header tree item // Add tree item
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); model->addItem(sysfVariableOffset, Types::SysFEntry, subtype, name, UString(), info, header, body, UByteArray(), Fixed, headerIndex);
storeFound = true; sysfVariableOffset += variableSize;
storeOffset += storeSize;
previousStoreEndOffset = storeOffset;
} catch (...) {
// Parsing failed, try something else
} }
// Insyde FDC
try {
if (volumeBodySize - storeOffset < sizeof(FDC_VOLUME_HEADER)) {
// No need to parse further, the rest of the volume is too small
throw 0;
}
UByteArray fdc = volumeBody.mid(storeOffset);
umemstream is(fdc.constData(), fdc.size());
kaitai::kstream ks(&is);
insyde_fdc_t parsed(&ks);
UINT32 storeSize = parsed.fdc_size();
// FDC store at current offset parsed correctly
// Check if we need to add a padding before it
if (!outerPadding.isEmpty()) {
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
outerPadding.clear();
}
// Construct header and body
UByteArray header = fdc.left(parsed.len_fdc_store_header());
UByteArray body = fdc.mid(header.size(),storeSize - header.size());
// Add free space or padding after all variables, if needed
UINT32 freeSpaceOffset = sysfVariableOffset - storeOffset;
if (freeSpaceOffset < storeSize) {
UByteArray freeSpace = sysf.mid(freeSpaceOffset, storeSize - freeSpaceOffset);
// Add info // Add info
UString name = UString("FDC store"); info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
storeSize, storeSize,
(UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size());
// Add header tree item // Check that remaining unparsed bytes are actually zeroes
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); if (freeSpace.count('\x00') == freeSpace.size() - 4) { // Free space, 4 last bytes are always CRC32
// Add tree item
// Parse FDC body as normal VSS/VSS2 storage with size override model->addItem(sysfVariableOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
parseNvramVolumeBody(headerIndex, (UINT32)body.size()); }
else {
storeFound = true; // Add tree item
storeOffset += storeSize; model->addItem(sysfVariableOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
previousStoreEndOffset = storeOffset; }
} catch (...) {
// Parsing failed, try something else
} }
// Apple Fsys/Gaid storeOffset += storeSize - 1;
previousStoreEndOffset = storeOffset + 1;
// Phoenix EVSA continue;
// Phoenix FlashMap } catch (...) {
// Phoenix CMDB // Parsing failed, try something else
// Phoenix SLIC Pubkey/Marker
// Intel uCode
} }
// Phoenix EVSA
// Phoenix FlashMap
// Phoenix CMDB
// Phoenix SLIC Pubkey/Marker
// Intel uCode
// Padding // Padding
if (storeOffset < volumeBodySize) { if (storeOffset < volumeBodySize) {
outerPadding += volumeBody[storeOffset]; outerPadding += volumeBody[storeOffset];
@ -795,8 +902,16 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
if (!outerPadding.isEmpty()) { if (!outerPadding.isEmpty()) {
// Add info // Add info
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size()); UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
// Add tree item
model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); // Check that remaining unparsed bytes are actually empty
if (outerPadding.count(emptyByte) == outerPadding.size()) {
// Add tree item
model->addItem(localOffset + previousStoreEndOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
}
else {
// Add tree item
model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
}
} }
return U_SUCCESS; return U_SUCCESS;

View file

@ -55,14 +55,14 @@ UString itemTypeToUString(const UINT8 type)
case Types::Vss2Store: return UString("VSS2 store"); case Types::Vss2Store: return UString("VSS2 store");
case Types::FtwStore: return UString("FTW store"); case Types::FtwStore: return UString("FTW store");
case Types::FdcStore: return UString("FDC store"); case Types::FdcStore: return UString("FDC store");
case Types::FsysStore: return UString("Fsys store"); case Types::SysFStore: return UString("SysF store");
case Types::EvsaStore: return UString("EVSA store"); case Types::EvsaStore: return UString("EVSA store");
case Types::CmdbStore: return UString("CMDB store"); case Types::CmdbStore: return UString("CMDB store");
case Types::FlashMapStore: return UString("FlashMap store"); case Types::FlashMapStore: return UString("FlashMap store");
case Types::NvarGuidStore: return UString("NVAR GUID store"); case Types::NvarGuidStore: return UString("NVAR GUID store");
case Types::NvarEntry: return UString("NVAR entry"); case Types::NvarEntry: return UString("NVAR entry");
case Types::VssEntry: return UString("VSS entry"); case Types::VssEntry: return UString("VSS entry");
case Types::FsysEntry: return UString("Fsys entry"); case Types::SysFEntry: return UString("SysF entry");
case Types::EvsaEntry: return UString("EVSA entry"); case Types::EvsaEntry: return UString("EVSA entry");
case Types::FlashMapEntry: return UString("FlashMap entry"); case Types::FlashMapEntry: return UString("FlashMap entry");
case Types::Microcode: return UString("Microcode"); case Types::Microcode: return UString("Microcode");
@ -128,9 +128,9 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
else if (subtype == Subtypes::AuthVssEntry) return UString("Auth"); else if (subtype == Subtypes::AuthVssEntry) return UString("Auth");
else if (subtype == Subtypes::IntelVssEntry) return UString("Intel"); else if (subtype == Subtypes::IntelVssEntry) return UString("Intel");
break; break;
case Types::FsysEntry: case Types::SysFEntry:
if (subtype == Subtypes::InvalidFsysEntry) return UString("Invalid"); if (subtype == Subtypes::InvalidSysFEntry) return UString("Invalid");
else if (subtype == Subtypes::NormalFsysEntry) return UString("Normal"); else if (subtype == Subtypes::NormalSysFEntry) return UString("Normal");
break; break;
case Types::EvsaEntry: case Types::EvsaEntry:
if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid"); if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid");

View file

@ -47,14 +47,14 @@ namespace Types {
Vss2Store, Vss2Store,
FtwStore, FtwStore,
FdcStore, FdcStore,
FsysStore, SysFStore,
EvsaStore, EvsaStore,
FlashMapStore, FlashMapStore,
CmdbStore, CmdbStore,
NvarGuidStore, NvarGuidStore,
NvarEntry, NvarEntry,
VssEntry, VssEntry,
FsysEntry, SysFEntry,
EvsaEntry, EvsaEntry,
FlashMapEntry, FlashMapEntry,
Microcode, Microcode,
@ -138,9 +138,9 @@ namespace Subtypes {
IntelVssEntry, IntelVssEntry,
}; };
enum FsysEntrySubtypes { enum SysFEntrySubtypes {
InvalidFsysEntry = 150, InvalidSysFEntry = 150,
NormalFsysEntry, NormalSysFEntry,
}; };
enum EvsaEntrySubtypes { enum EvsaEntrySubtypes {

View file

@ -69,6 +69,7 @@ public:
UByteArray & operator=(const UByteArray & ba) { d = ba.d; return *this; } UByteArray & operator=(const UByteArray & ba) { d = ba.d; return *this; }
UByteArray & operator+=(const UByteArray & ba) { d += ba.d; return *this; } UByteArray & operator+=(const UByteArray & ba) { d += ba.d; return *this; }
UByteArray & operator+=(const char c) { d += c; return *this; }
bool operator== (const UByteArray & ba) const { return d == ba.d; } bool operator== (const UByteArray & ba) const { return d == ba.d; }
bool operator!= (const UByteArray & ba) const { return d != ba.d; } bool operator!= (const UByteArray & ba) const { return d != ba.d; }
inline void swap(UByteArray &other) { std::swap(d, other.d); } inline void swap(UByteArray &other) { std::swap(d, other.d); }

View file

@ -81,7 +81,7 @@ UString uniqueItemName(const UModelIndex & index)
switch (model->type(index)) { switch (model->type(index)) {
case Types::NvarEntry: case Types::NvarEntry:
case Types::VssEntry: case Types::VssEntry:
case Types::FsysEntry: case Types::SysFEntry:
case Types::EvsaEntry: case Types::EvsaEntry:
case Types::FlashMapEntry: case Types::FlashMapEntry:
case Types::File: case Types::File:

View file

@ -32,6 +32,11 @@ SET(PROJECT_SOURCES
../common/Tiano/EfiTianoDecompress.c ../common/Tiano/EfiTianoDecompress.c
../common/ustring.cpp ../common/ustring.cpp
../common/generated/ami_nvar.cpp ../common/generated/ami_nvar.cpp
../common/generated/apple_sysf.cpp
../common/generated/edk2_vss.cpp
../common/generated/edk2_vss2.cpp
../common/generated/edk2_ftw.cpp
../common/generated/insyde_fdc.cpp
../common/generated/intel_acbp_v1.cpp ../common/generated/intel_acbp_v1.cpp
../common/generated/intel_acbp_v2.cpp ../common/generated/intel_acbp_v2.cpp
../common/generated/intel_keym_v1.cpp ../common/generated/intel_keym_v1.cpp