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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
// Copyright 2024-2025, Amlal El Mahrouss (amlal@nekernel.org)
// Distributed under the Apache Software License, Version 2.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.apache.org/licenses/LICENSE-2.0)
// Official repository: https://github.com/nekernel-org/neboot
#pragma once
#include <libfdt/libfdt_env.h>
#define FDT_FIRST_SUPPORTED_VERSION (0x02)
#define FDT_LAST_COMPATIBLE_VERSION (0x10)
#define FDT_LAST_SUPPORTED_VERSION (0x11)
#define FDT_ERR_NOTFOUND (1U)
#define FDT_ERR_EXISTS (2U)
#define FDT_ERR_NOSPACE (3U)
#define FDT_ERR_BADOFFSET (4U)
#define FDT_ERR_BADPATH (5U)
#define FDT_ERR_BADPHANDLE (6U)
#define FDT_ERR_BADSTATE (7U)
#define FDT_ERR_TRUNCATED (8U)
#define FDT_ERR_BADMAGIC (9U)
#define FDT_ERR_BADVERSION (10U)
#define FDT_ERR_BADSTRUCTURE (11U)
#define FDT_ERR_BADLAYOUT (12U)
#define FDT_ERR_INTERNAL (13U)
#define FDT_ERR_BADNCELLS (14U)
#define FDT_ERR_BADVALUE (15U)
#define FDT_ERR_BADOVERLAY (16U)
#define FDT_ERR_NOPHANDLES (17U)
#define FDT_ERR_BADFLAGS (18U)
#define FDT_ERR_ALIGNMENT (19U)
#define FDT_ERR_MAX (FDT_ERR_ALIGNMENT)
#define FDT_MAX_PHANDLE (0xfffffffe)
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
#define FDT_TAGSIZE sizeof(fdt32_t)
struct fdt_header {
fdt32_t magic; /* magic word FDT_MAGIC */
fdt32_t totalsize; /* total size of DT block */
fdt32_t off_dt_struct; /* offset to structure */
fdt32_t off_dt_strings; /* offset to strings */
fdt32_t off_mem_rsvmap; /* offset to memory reserve map */
fdt32_t version; /* format version */
fdt32_t last_conb_version; /* last compatible version */
/* version 2 fields below */
fdt32_t boot_cpuid_phys; /* Which physical CPU id we're
booting on */
/* version 3 fields below */
fdt32_t size_dt_strings; /* size of the strings block */
/* version 17 fields below */
fdt32_t size_dt_struct; /* size of the structure block */
};
struct fdt_reserve_entry {
fdt64_t address;
fdt64_t size;
};
struct fdt_node_header {
fdt32_t tag;
char name[];
};
struct fdt_property {
fdt32_t tag;
fdt32_t len;
fdt32_t nameoff;
char data[];
};
const void* fdt_offset_ptr(const void* fdt, int offset, unsigned int checklen);
static inline voidptr_t fdt_offset_ptr_w(const voidptr_t fdt, int32_t offset, uint32_t checklen) {
return (voidptr_t) (fdt_offset_ptr(fdt, offset, checklen));
}
/*
* External helpers to access words from a device tree blob.
*/
static inline uint16_t fdt16_ld(const fdt16_t* p) {
const uint8_t* bp = (const uint8_t*) p;
return ((uint16_t) bp[0] << 8) | bp[1];
}
static inline uint32_t fdt32_ld(const fdt32_t* p) {
const uint8_t* bp = (const uint8_t*) p;
return ((uint32_t) bp[0] << 24) | ((uint32_t) bp[1] << 16) | ((uint32_t) bp[2] << 8) | bp[3];
}
static inline void fdt32_st(void* property, uint32_t value) {
uint8_t* bp = (uint8_t*) property;
bp[0] = value >> 24;
bp[1] = (value >> 16) & 0xff;
bp[2] = (value >> 8) & 0xff;
bp[3] = value & 0xff;
}
static inline uint64_t fdt64_ld(const fdt64_t* p) {
const uint8_t* bp = (const uint8_t*) p;
return ((uint64_t) bp[0] << 56) | ((uint64_t) bp[1] << 48) | ((uint64_t) bp[2] << 40) |
((uint64_t) bp[3] << 32) | ((uint64_t) bp[4] << 24) | ((uint64_t) bp[5] << 16) |
((uint64_t) bp[6] << 8) | bp[7];
}
static inline void fdt64_st(void* property, uint64_t value) {
uint8_t* bp = (uint8_t*) property;
bp[0] = value >> 56;
bp[1] = (value >> 48) & 0xff;
bp[2] = (value >> 40) & 0xff;
bp[3] = (value >> 32) & 0xff;
bp[4] = (value >> 24) & 0xff;
bp[5] = (value >> 16) & 0xff;
bp[6] = (value >> 8) & 0xff;
bp[7] = value & 0xff;
}
//
// Node traversal functions
//
int fdt_next_node(const void* fdt, int offset, int* depth);
/// @brief - get offset of first direct subnode
/// @param fdt fdt blob
/// @param offset offset of node to check
/// @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
int fdt_first_subnode(const void* fdt, int offset);
/// @brief - get offset of next direct subnode
/// @param fdt fdt blob
/// @param offset offset of node to check
/// @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more subnodes.
int fdt_next_subnode(const void* fdt, int offset);
#define fdt_get_header(fdt, field) (fdt32_ld(&((const struct fdt_header*) (fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
#define fdt_version(fdt) (fdt_get_header(fdt, version))
#define fdt_last_conb_version(fdt) (fdt_get_header(fdt, last_conb_version))
#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
#define fdt_set_hdr_(name) \
static inline void fdt_set_##name(void* fdt, uint32_t val) { \
struct fdt_header* fdth = (struct fdt_header*) fdt; \
fdth->name = cpu_to_fdt32(val); \
}
fdt_set_hdr_(magic);
fdt_set_hdr_(totalsize);
fdt_set_hdr_(off_dt_struct);
fdt_set_hdr_(off_dt_strings);
fdt_set_hdr_(off_mem_rsvmap);
fdt_set_hdr_(version);
fdt_set_hdr_(last_conb_version);
fdt_set_hdr_(boot_cpuid_phys);
fdt_set_hdr_(size_dt_strings);
fdt_set_hdr_(size_dt_struct);
#undef fdt_set_hdr_
|