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
|
// 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/ne-foss-org/neboot
#include <libfdt/libfdt_env.h>
extern fdt32_t* fdt_getprop(const void* fdt, int nodeoffset, const char* name, int* len);
extern fdt32_t* fdt_append_prop(const void* fdt, int nodeoffset, const char* name, uint8_t* data,
int32_t len);
#ifndef FDT_MAX_NCELLS
#define FDT_MAX_NCELLS (4)
#endif
#ifndef FDT_BAD_NCELLS
#define FDT_BAD_NCELLS (14)
#endif
#ifndef FDT_NOT_FOUND
#define FDT_NOT_FOUND (1)
#endif
#ifndef FDT_BAD_VALUE
#define FDT_BAD_VALUE (15)
#endif
static int fdt_cells(const void* fdt, int nodeoffset, const char* name) {
const fdt32_t* c = null;
uint32_t val = 0;
int len = 0;
c = fdt_getprop(fdt, nodeoffset, name, &len);
if (c == null) return len;
if (len != sizeof(*c)) return len;
val = fdt32_to_cpu(*c);
if (val > FDT_MAX_NCELLS) return -FDT_BAD_NCELLS;
return (int) val;
}
int fdt_address_cells(const void* fdt, int nodeoffset) {
int val = 0;
val = fdt_cells(fdt, nodeoffset, "#address-cells");
if (val == 0) return -FDT_BAD_NCELLS;
if (val == -FDT_NOT_FOUND) return 2;
return (int) val;
}
int fdt_size_cells(const void* fdt, int nodeoffset) {
int val = 0;
val = fdt_cells(fdt, nodeoffset, "#size-cells");
if (val == -FDT_NOT_FOUND) return 2;
return (int) val;
}
int fdt_append_prop_addr_range(void* fdt, int parent, int nodeoffset, const char* name,
uint64_t addr, uint64_t size) {
int addr_cells, size_cells, ret;
uint8_t data[sizeof(fdt64_t) * 2], *prop;
ret = fdt_address_cells(fdt, nodeoffset);
if (ret < 0) return ret;
addr_cells = ret;
ret = fdt_size_cells(fdt, nodeoffset);
if (ret < 0) return ret;
size_cells = ret;
// check address validity
prop = data;
if (addr_cells == 1) {
// seems to do a check according to two parameters.
// addr > __UINT32_MAX__ detects any out of range addresses?
// ((__UINT32_MAX__ + 1 - addr) < size check if it's lower than it's size
if ((addr > __UINT32_MAX__) || ((__UINT32_MAX__ + 1 - addr) < size)) return -FDT_BAD_VALUE;
// finally set the flat device tree.
fdt32_st(prop, (uint32_t) addr);
} else if (addr_cells == 2) {
// no need to check, apparently.
fdt64_st(prop, addr);
} else {
return -FDT_BAD_NCELLS;
}
// access size
prop += addr_cells * sizeof(fdt32_t);
if (size_cells == 1) {
if (size > __UINT32_MAX__) return -FDT_BAD_VALUE;
fdt32_st(prop, (uint32_t) size);
} else if (size_cells == 2) {
fdt64_st(prop, size);
} else {
return -FDT_BAD_NCELLS;
}
return fdt_append_prop(fdt, nodeoffset, name, data, (addr_cells + size_cells) * sizeof(fdt32_t));
}
|