AquilaOS documentation
How it works, and its code
Toggle main menu visibility
Loading...
Searching...
No Matches
fdt.c
Go to the documentation of this file.
1
16
17
#include <
core/system.h
>
18
#include <
core/string.h
>
19
#include <
boot/boot.h
>
20
#include <
mm/mm.h
>
21
22
/* The FDT's magic number, and its structure's tokens. */
23
#define FDT_MAGIC 0xD00DFEED
24
#define FDT_BEGIN_NODE 1
25
#define FDT_END_NODE 2
26
#define FDT_PROP 3
27
#define FDT_NOP 4
28
#define FDT_END 9
29
31
struct
fdt_header
{
32
uint32_t
magic
;
33
uint32_t
totalsize
;
34
uint32_t
off_dt_struct
;
35
uint32_t
off_dt_strings
;
36
uint32_t
off_mem_rsvmap
;
37
uint32_t
version
;
38
uint32_t
last_comp_version
;
39
uint32_t
boot_cpuid_phys
;
40
uint32_t
size_dt_strings
;
41
uint32_t
size_dt_struct
;
42
};
43
45
static
inline
uint32_t
be32
(
const
void
*p)
46
{
47
const
uint8_t
*b = p;
48
return
(
uint32_t
) b[0] << 24 | (
uint32_t
) b[1] << 16 | (
uint32_t
) b[2] << 8 | b[3];
49
}
50
52
static
uint64_t
cells
(
const
void
*p,
int
cells
)
53
{
54
uint64_t
v = 0;
55
56
for
(
int
i = 0; i <
cells
; ++i)
57
v = v << 32 |
be32
((
const
uint8_t
*) p + 4 * i);
58
59
return
v;
60
}
61
62
/* The most memory regions that are kept. */
63
#define MMAP_MAX 16
64
65
/* What the devicetree says, in the kernel's form. */
66
static
struct
boot
boot
;
67
static
mmap_t
mmap
[
MMAP_MAX
];
68
static
module_t
modules
[1];
69
static
char
cmdline
[1024];
70
78
struct
boot
*
fdt_boot
(
uintptr_t
dtb)
79
{
80
const
struct
fdt_header
*h =
PHYS2VIRT
(dtb);
81
82
boot
.
cmdline
=
cmdline
;
83
boot
.
mmap
=
mmap
;
84
boot
.
modules
=
modules
;
85
86
if
(
be32
(&h->
magic
) !=
FDT_MAGIC
) {
87
printk
(
"fdt: no devicetree at %p\n"
, (
void
*) dtb);
88
return
&
boot
;
89
}
90
91
const
uint8_t
*structs = (
const
uint8_t
*) h +
be32
(&h->
off_dt_struct
);
92
const
char
*strings = (
const
char
*) h +
be32
(&h->
off_dt_strings
);
93
94
int
addr_cells = 2, size_cells = 2, depth = 0;
95
int
in_memory = 0, in_chosen = 0;
96
uint64_t
initrd_start = 0, initrd_end = 0;
97
98
for
(
const
uint8_t
*p = structs;;) {
99
uint32_t
token =
be32
(p);
100
p += 4;
101
102
if
(token ==
FDT_BEGIN_NODE
) {
103
const
char
*name = (
const
char
*) p;
104
size_t
len = strlen(name);
105
p += (len + 1 + 3) & ~3;
106
++depth;
107
108
/* /memory or /memory@40000000, and /chosen */
109
in_memory = depth == 2 && !strncmp(name,
"memory"
, 6) && (name[6] ==
'@'
|| !name[6]);
110
in_chosen = depth == 2 && !strcmp(name,
"chosen"
);
111
}
else
if
(token ==
FDT_END_NODE
) {
112
--depth;
113
in_memory = in_chosen = 0;
114
}
else
if
(token ==
FDT_PROP
) {
115
uint32_t
len =
be32
(p), nameoff =
be32
(p + 4);
116
const
uint8_t
*val = p + 8;
117
const
char
*name = strings + nameoff;
118
p += 8 + ((len + 3) & ~3);
119
120
if
(depth == 1 && !strcmp(name,
"#address-cells"
))
121
addr_cells =
be32
(val);
122
else
if
(depth == 1 && !strcmp(name,
"#size-cells"
))
123
size_cells =
be32
(val);
124
else
if
(in_memory && !strcmp(name,
"reg"
)) {
125
size_t
entry = 4 * (addr_cells + size_cells);
126
127
for
(
size_t
off = 0; off + entry <= len &&
boot
.
mmap_count
<
MMAP_MAX
; off += entry) {
128
uint64_t
start =
cells
(val + off, addr_cells);
129
uint64_t
size =
cells
(val + off + 4 * addr_cells, size_cells);
130
131
mmap
[
boot
.
mmap_count
++] = (
mmap_t
) {
132
.type =
MMAP_USABLE
,
133
.start = start,
134
.end = start + size,
135
};
136
137
boot
.
total_mem
+= size / 1024;
138
}
139
}
else
if
(in_chosen && !strcmp(name,
"bootargs"
)) {
140
size_t
n =
MIN
(len,
sizeof
(
cmdline
) - 1);
141
memcpy
(
cmdline
, val, n);
142
cmdline
[n] = 0;
143
}
else
if
(in_chosen && !strcmp(name,
"linux,initrd-start"
)) {
144
initrd_start =
cells
(val, len / 4);
145
}
else
if
(in_chosen && !strcmp(name,
"linux,initrd-end"
)) {
146
initrd_end =
cells
(val, len / 4);
147
}
148
}
else
if
(token ==
FDT_NOP
) {
149
continue
;
150
}
else
{
151
break
;
/* FDT_END, or a token it doesn't know */
152
}
153
}
154
155
/* the initrd is the one module, as Multiboot's first one is */
156
if
(initrd_end > initrd_start) {
157
modules
[0] = (
module_t
) {
158
.paddr = initrd_start,
159
.size = initrd_end - initrd_start,
160
.cmdline =
""
,
161
};
162
163
boot
.
modules_count
= 1;
164
}
165
166
return
&
boot
;
167
}
fdt_boot
struct boot * fdt_boot(uintptr_t dtb)
Reads the boot loader's devicetree into a struct boot.
Definition
fdt.c:78
PHYS2VIRT
#define PHYS2VIRT(paddr)
Definition
mm.h:26
modules
static module_t modules[1]
Definition
fdt.c:68
mmap
static mmap_t mmap[MMAP_MAX]
Definition
fdt.c:67
FDT_PROP
#define FDT_PROP
Definition
fdt.c:26
MMAP_MAX
#define MMAP_MAX
Definition
fdt.c:63
FDT_MAGIC
#define FDT_MAGIC
Definition
fdt.c:23
FDT_BEGIN_NODE
#define FDT_BEGIN_NODE
Definition
fdt.c:24
FDT_NOP
#define FDT_NOP
Definition
fdt.c:27
FDT_END_NODE
#define FDT_END_NODE
Definition
fdt.c:25
be32
static uint32_t be32(const void *p)
Reads a big-endian 32-bit number.
Definition
fdt.c:45
cells
static uint64_t cells(const void *p, int cells)
Reads cells big-endian 32-bit cells at p as one number.
Definition
fdt.c:52
cmdline
static char cmdline[1024]
Definition
fdt.c:69
boot.h
MMAP_USABLE
@ MMAP_USABLE
Definition
boot.h:23
system.h
MIN
#define MIN(a, b)
Definition
system.h:11
mm.h
memcpy
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
Definition
libc.c:11
printk
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition
printk.c:249
uintptr_t
__SIZE_TYPE__ uintptr_t
Definition
stddef.h:12
uint32_t
unsigned int uint32_t
Definition
stddef.h:22
uint8_t
unsigned char uint8_t
Definition
stddef.h:20
uint64_t
unsigned long long int uint64_t
Definition
stddef.h:23
string.h
boot
Definition
boot.h:35
boot::mmap_count
int mmap_count
Definition
boot.h:40
boot::cmdline
char * cmdline
Definition
boot.h:36
boot::modules
module_t * modules
Definition
boot.h:41
boot::total_mem
uintptr_t total_mem
Definition
boot.h:37
boot::mmap
mmap_t * mmap
Definition
boot.h:42
boot::modules_count
int modules_count
Definition
boot.h:39
fdt_header
The FDT's header (big-endian).
Definition
fdt.c:31
fdt_header::size_dt_strings
uint32_t size_dt_strings
Definition
fdt.c:40
fdt_header::off_dt_strings
uint32_t off_dt_strings
Definition
fdt.c:35
fdt_header::magic
uint32_t magic
Definition
fdt.c:32
fdt_header::size_dt_struct
uint32_t size_dt_struct
Definition
fdt.c:41
fdt_header::last_comp_version
uint32_t last_comp_version
Definition
fdt.c:38
fdt_header::off_dt_struct
uint32_t off_dt_struct
Definition
fdt.c:34
fdt_header::off_mem_rsvmap
uint32_t off_mem_rsvmap
Definition
fdt.c:36
fdt_header::version
uint32_t version
Definition
fdt.c:37
fdt_header::totalsize
uint32_t totalsize
Definition
fdt.c:33
fdt_header::boot_cpuid_phys
uint32_t boot_cpuid_phys
Definition
fdt.c:39
mmap_t
Definition
boot.h:28
module_t
Definition
boot.h:15
kernel
arch
aarch64
platform
virt
fdt.c
Generated by
1.18.0