1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "libfdt.h"
7 #include "dtb_node.h"
8
dtb_node_find_and_add_subnode(void * fdt,char * name)9 static off_t dtb_node_find_and_add_subnode(void *fdt, char* name)
10 {
11 off_t chosen_offset = 0;
12
13 chosen_offset = fdt_subnode_offset(fdt, 0, name);
14
15 if (chosen_offset == -FDT_ERR_NOTFOUND)
16 {
17 chosen_offset = fdt_add_subnode(fdt, 0, name);
18 }
19
20 return chosen_offset;
21 }
22
dtb_node_set_linux_cmdline(void * fdt,char * cmdline)23 size_t dtb_node_set_linux_cmdline(void *fdt, char *cmdline)
24 {
25 off_t chosen_offset;
26 size_t cmdline_size;
27
28 if (cmdline == NULL || fdt == NULL)
29 {
30 goto end;
31 }
32
33 chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen");
34 cmdline_size = strlen(cmdline);
35
36 /* install bootargs */
37 if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS)
38 {
39 if (fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size) < 0)
40 {
41 fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE);
42 fdt_setprop(fdt, chosen_offset, "bootargs", cmdline, cmdline_size);
43 }
44 }
45
46 end:
47 return fdt_totalsize(fdt);
48 }
49
dtb_node_set_linux_initrd(void * fdt,uint64_t initrd_addr,size_t initrd_size)50 size_t dtb_node_set_linux_initrd(void *fdt, uint64_t initrd_addr, size_t initrd_size)
51 {
52 uint64_t addr, size_ptr;
53 off_t chosen_offset;
54 int i;
55
56 if (fdt == NULL)
57 {
58 goto end;
59 }
60
61 chosen_offset = dtb_node_find_and_add_subnode(fdt, "chosen");
62
63 /* update the entry */
64 for (i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i)
65 {
66 fdt_get_mem_rsv(fdt, i, &addr, &size_ptr);
67 if (addr == initrd_addr)
68 {
69 fdt_del_mem_rsv(fdt, i);
70 break;
71 }
72 }
73
74 /* add the memory */
75 if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
76 {
77 /* move the memory */
78 fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_DTB_PAD_SIZE);
79 if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
80 {
81 goto end;
82 }
83 }
84
85 /* install initrd */
86 if (chosen_offset >= 0 || chosen_offset == -FDT_ERR_EXISTS)
87 {
88 chosen_offset = fdt_path_offset(fdt, "/chosen");
89
90 if (IN_64BITS_MODE)
91 {
92 fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-start", initrd_addr);
93 fdt_setprop_u64(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size);
94 }
95 else
96 {
97 fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-start", initrd_addr);
98 fdt_setprop_u32(fdt, chosen_offset, "linux,initrd-end", initrd_addr + initrd_size);
99 }
100 }
101
102 end:
103 return fdt_totalsize(fdt);
104 }
105
dtb_node_set_dtb_property(void * fdt,char * pathname,char * property_name,uint32_t * cells,size_t cells_size)106 size_t dtb_node_set_dtb_property(void *fdt, char *pathname, char *property_name, uint32_t *cells, size_t cells_size)
107 {
108 int node_off;
109
110 if (fdt == NULL)
111 {
112 goto end;
113 }
114
115 node_off = fdt_path_offset(fdt, pathname);
116
117 if (node_off >= 0 && cells_size != 0)
118 {
119 fdt_setprop(fdt, node_off, property_name, cells, cells_size);
120 }
121
122 end:
123 return fdt_totalsize(fdt);
124 }
125
dtb_node_add_dtb_memreserve(void * fdt,uint64_t address,uint64_t size)126 size_t dtb_node_add_dtb_memreserve(void *fdt, uint64_t address, uint64_t size)
127 {
128 if (fdt == NULL)
129 {
130 goto end;
131 }
132
133 fdt_add_mem_rsv(fdt, address, size);
134
135 end:
136 return fdt_totalsize(fdt);
137 }
138
dtb_node_del_dtb_memreserve(void * fdt,uint64_t address)139 size_t dtb_node_del_dtb_memreserve(void *fdt, uint64_t address)
140 {
141 int i;
142 int num_mem_rsvmap;
143 uint32_t off_mem_rsvmap;
144 struct fdt_reserve_entry *rsvmap;
145
146 if (fdt == NULL)
147 {
148 goto end;
149 }
150
151 num_mem_rsvmap = fdt_num_mem_rsv(fdt);
152 off_mem_rsvmap = fdt_off_mem_rsvmap(fdt);
153 rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap);
154
155 for (i = 0; i < num_mem_rsvmap; ++i)
156 {
157 if (address == fdt64_to_cpu(rsvmap[i].address))
158 {
159 fdt_del_mem_rsv(fdt, i);
160 break;
161 }
162 }
163
164 end:
165 return fdt_totalsize(fdt);
166 }
167