mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
126 lines
3.0 KiB
Rust
126 lines
3.0 KiB
Rust
#pragma author WerWolv
|
|
#pragma description Flat Linux Device Tree blob
|
|
|
|
#pragma endian big
|
|
|
|
#include <std/sys.pat>
|
|
#include <std/io.pat>
|
|
#include <std/core.pat>
|
|
|
|
#include <type/magic.pat>
|
|
#include <type/size.pat>
|
|
|
|
// These are used in order for the children to be able to find strings
|
|
u64 fdt_addr;
|
|
u64 str_offset;
|
|
|
|
|
|
struct FDTHeader {
|
|
type::Magic<"\xD0\x0D\xFE\xED"> magic;
|
|
u32 totalsize;
|
|
u32 off_dt_struct;
|
|
u32 off_dt_strings;
|
|
u32 off_mem_rsvmap;
|
|
u32 version;
|
|
u32 last_comp_version;
|
|
u32 boot_cpuid_phys;
|
|
u32 size_dt_strings;
|
|
u32 size_dt_struct;
|
|
};
|
|
|
|
struct AlignTo<auto Alignment> {
|
|
padding[Alignment- ((($ - 1) % Alignment) + 1)];
|
|
} [[hidden]];
|
|
|
|
struct FDTReserveEntry {
|
|
u64 address;
|
|
type::Size<u64> size;
|
|
|
|
if (address == 0x00 && size == 0x00)
|
|
break;
|
|
};
|
|
|
|
enum FDTToken : u32 {
|
|
FDT_BEGIN_NODE = 0x00000001,
|
|
FDT_END_NODE = 0x00000002,
|
|
FDT_PROP = 0x00000003,
|
|
FDT_NOP = 0x00000004,
|
|
FDT_END = 0x00000009
|
|
};
|
|
|
|
union FDTPropValue<auto len> {
|
|
u32 prop_array[len / sizeof(u32)];
|
|
char string[len];
|
|
};
|
|
|
|
struct FDTProp {
|
|
FDTToken tok[[hidden]];
|
|
u32 len [[hidden]];
|
|
u32 nameoff [[hidden]];
|
|
if (len > 0) {
|
|
// if len is zero, value is absent and no need to include it
|
|
FDTPropValue<len> value;
|
|
}
|
|
AlignTo<4>;
|
|
char name[] @ fdt_addr + str_offset + nameoff;
|
|
|
|
std::core::set_display_name(this, name);
|
|
std::print(std::format("{:x} token {} len {} {}",
|
|
$, tok, len,nameoff));
|
|
FDTToken token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
|
if (token != FDTToken::FDT_PROP) {
|
|
break;
|
|
}
|
|
};
|
|
|
|
struct FDTNode {
|
|
FDTToken token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
|
|
|
if (token == FDTToken::FDT_BEGIN_NODE) {
|
|
FDTToken tok[[hidden]];
|
|
char name[];
|
|
AlignTo<4>;
|
|
std::core::set_display_name(this, name[0] ? name : "/");
|
|
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
|
|
|
if(token == FDTToken::FDT_PROP) {
|
|
FDTProp props[while(true)];
|
|
}
|
|
|
|
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
|
if(token == FDTToken::FDT_END_NODE) {
|
|
FDTToken[[hidden]];
|
|
break;
|
|
}
|
|
|
|
FDTNode children[while(true)][[inline]];
|
|
} else if(token == FDTToken::FDT_NOP) {
|
|
// TODO this may break the pattern, I've so far not encountered it
|
|
}
|
|
|
|
// ew duplication
|
|
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
|
if(token == FDTToken::FDT_END_NODE) {
|
|
FDTToken[[hidden]];
|
|
break;
|
|
}
|
|
};
|
|
|
|
struct FDTStructureBlock {
|
|
FDTNode;
|
|
};
|
|
|
|
|
|
struct FDT {
|
|
FDTHeader header;
|
|
std::assert(header.version == 17, "Unsupported format version");
|
|
fdt_addr = addressof(this);
|
|
str_offset = header.off_dt_strings;
|
|
|
|
FDTStructureBlock structureBlocks @ fdt_addr + header.off_dt_struct;
|
|
FDTReserveEntry reserveEntries[while(true)] @ fdt_addr + header.off_mem_rsvmap;
|
|
};
|
|
|
|
std::mem::MagicSearch<"\xD0\x0D\xFE\xED", FDT> fdt @ std::mem::base_address();
|
|
|