-
-
Notifications
You must be signed in to change notification settings - Fork 184
/
fdt.hexpat
125 lines (100 loc) · 3.01 KB
/
fdt.hexpat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#pragma author WerWolv
#pragma description Flat Linux Device Tree blob
#pragma endian big
import std.sys;
import std.io;
import std.core;
import type.magic;
import type.size;
// 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();