5d4a871e1f4ed42761f69cda5b3940da8b777257
[riscv-isa-sim.git] / riscv / devicetree.h
1 // See LICENSE for license details.
2
3 #ifndef _RISCV_DEVICETREE_H
4 #define _RISCV_DEVICETREE_H
5
6 #include <stdint.h>
7 #include <string.h>
8 #include <string>
9 #include <map>
10 #include <vector>
11 #include <arpa/inet.h>
12
13 #define FDT_MAGIC 0xd00dfeedU
14 #define FDT_VERSION 17
15 #define FDT_COMP_VERSION 16
16 #define FDT_BEGIN_NODE 1
17 #define FDT_END_NODE 2
18 #define FDT_PROP 3
19 #define FDT_END 9
20
21 struct fdt_header {
22 uint32_t magic;
23 uint32_t totalsize;
24 uint32_t off_dt_struct;
25 uint32_t off_dt_strings;
26 uint32_t off_rsvmap;
27 uint32_t version;
28 uint32_t last_comp_version;
29 uint32_t boot_cpuid_phys;
30 uint32_t size_dt_strings;
31 uint32_t size_dt_struct;
32 };
33
34 struct fdt_reserve_entry {
35 uint64_t address;
36 uint64_t size;
37 };
38
39 struct string_table {
40 std::map<std::string, size_t> strings;
41 std::vector<char> data;
42
43 size_t add(std::string s) {
44 if (!strings.count(s)) {
45 strings[s] = data.size();
46 data.insert(data.end(), s.begin(), s.end());
47 data.push_back(0);
48 }
49 return strings[s];
50 }
51 };
52
53 struct device_tree {
54 device_tree() {
55 memset(rsvmap, 0, sizeof(rsvmap));
56 }
57
58 void begin_node(std::string s) {
59 std::vector<uint32_t> name = s2v(s);
60 sblock.push_back(FDT_BEGIN_NODE);
61 sblock.insert(sblock.end(), name.begin(), name.end());
62 }
63
64 void end_node() {
65 sblock.push_back(FDT_END_NODE);
66 }
67
68 std::vector<char> finalize() {
69 sblock.push_back(FDT_END);
70
71 struct fdt_header h;
72 h.size_dt_struct = sblock.size() * sizeof(sblock[0]);
73 h.size_dt_strings = strings.data.size();
74 h.magic = FDT_MAGIC;
75 h.off_rsvmap = sizeof(h);
76 h.off_dt_struct = h.off_rsvmap + sizeof(rsvmap);
77 h.off_dt_strings = h.off_dt_struct + h.size_dt_struct;
78 h.totalsize = h.off_dt_strings + h.size_dt_strings;
79 h.version = FDT_VERSION;
80 h.last_comp_version = FDT_COMP_VERSION;
81 h.boot_cpuid_phys = 0;
82
83 for (uint32_t* p = &h.magic; p < &h.magic + sizeof(h)/sizeof(uint32_t); p++)
84 *p = htonl(*p);
85 for (uint32_t& p : sblock)
86 p = htonl(p);
87
88 std::vector<char> res;
89 res.insert(res.end(), (char*)&h, (char*)&h + sizeof(h));
90 res.insert(res.end(), (char*)&rsvmap, (char*)&rsvmap + sizeof(rsvmap));
91 res.insert(res.end(), (char*)&sblock[0],
92 (char*)&sblock[0] + sblock.size() * sizeof(sblock[0]));
93 res.insert(res.end(), strings.data.begin(), strings.data.end());
94 return res;
95 }
96
97 void add_prop(std::string name, uint32_t data)
98 {
99 add_prop(name, std::vector<uint32_t>(1, data), sizeof(data));
100 }
101
102 void add_reg(std::vector<uint64_t> values)
103 {
104 std::vector<uint32_t> v;
105 for (auto x : values) {
106 v.push_back(x >> 32);
107 v.push_back(x);
108 }
109 add_prop("reg", v, v.size() * sizeof(v[0]));
110 }
111
112 void add_prop(std::string name, std::string data)
113 {
114 add_prop(name, s2v(data), data.size()+1);
115 }
116
117 private:
118 struct string_table strings;
119 std::vector<uint32_t> sblock;
120 struct fdt_reserve_entry rsvmap[1];
121
122 std::vector<uint32_t> s2v(std::string data) {
123 std::vector<char> v(data.begin(), data.end());
124 do {
125 v.push_back(0);
126 } while (v.size() % 4);
127
128 std::vector<uint32_t> words;
129 for (size_t i = 0; i < v.size(); i += 4)
130 words.push_back((v[i] << 24) | (v[i+1] << 16) | (v[i+2] << 8) | v[i+3]);
131 return words;
132 }
133
134 void add_prop(std::string name, std::vector<uint32_t> data, size_t len) {
135 sblock.push_back(FDT_PROP);
136 sblock.push_back(len);
137 sblock.push_back(strings.add(name));
138 sblock.insert(sblock.end(), data.begin(), data.end());
139 }
140 };
141
142 #endif