This source file includes following definitions.
- node_offset
- setprop
- setprop_string
- setprop_cell
- getprop
- get_cell_size
- merge_fdt_bootargs
- hex_str
- atags_to_fdt
1
2 #include <asm/setup.h>
3 #include <libfdt.h>
4
5 #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
6 #define do_extend_cmdline 1
7 #else
8 #define do_extend_cmdline 0
9 #endif
10
11 #define NR_BANKS 16
12
13 static int node_offset(void *fdt, const char *node_path)
14 {
15 int offset = fdt_path_offset(fdt, node_path);
16 if (offset == -FDT_ERR_NOTFOUND)
17 offset = fdt_add_subnode(fdt, 0, node_path);
18 return offset;
19 }
20
21 static int setprop(void *fdt, const char *node_path, const char *property,
22 uint32_t *val_array, int size)
23 {
24 int offset = node_offset(fdt, node_path);
25 if (offset < 0)
26 return offset;
27 return fdt_setprop(fdt, offset, property, val_array, size);
28 }
29
30 static int setprop_string(void *fdt, const char *node_path,
31 const char *property, const char *string)
32 {
33 int offset = node_offset(fdt, node_path);
34 if (offset < 0)
35 return offset;
36 return fdt_setprop_string(fdt, offset, property, string);
37 }
38
39 static int setprop_cell(void *fdt, const char *node_path,
40 const char *property, uint32_t val)
41 {
42 int offset = node_offset(fdt, node_path);
43 if (offset < 0)
44 return offset;
45 return fdt_setprop_cell(fdt, offset, property, val);
46 }
47
48 static const void *getprop(const void *fdt, const char *node_path,
49 const char *property, int *len)
50 {
51 int offset = fdt_path_offset(fdt, node_path);
52
53 if (offset == -FDT_ERR_NOTFOUND)
54 return NULL;
55
56 return fdt_getprop(fdt, offset, property, len);
57 }
58
59 static uint32_t get_cell_size(const void *fdt)
60 {
61 int len;
62 uint32_t cell_size = 1;
63 const uint32_t *size_len = getprop(fdt, "/", "#size-cells", &len);
64
65 if (size_len)
66 cell_size = fdt32_to_cpu(*size_len);
67 return cell_size;
68 }
69
70 static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
71 {
72 char cmdline[COMMAND_LINE_SIZE];
73 const char *fdt_bootargs;
74 char *ptr = cmdline;
75 int len = 0;
76
77
78 fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len);
79 if (fdt_bootargs)
80 if (len < COMMAND_LINE_SIZE) {
81 memcpy(ptr, fdt_bootargs, len);
82
83
84 ptr += len - 1;
85 }
86
87
88 if (fdt_cmdline) {
89 len = strlen(fdt_cmdline);
90 if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) {
91 *ptr++ = ' ';
92 memcpy(ptr, fdt_cmdline, len);
93 ptr += len;
94 }
95 }
96 *ptr = '\0';
97
98 setprop_string(fdt, "/chosen", "bootargs", cmdline);
99 }
100
101 static void hex_str(char *out, uint32_t value)
102 {
103 uint32_t digit;
104 int idx;
105
106 for (idx = 7; idx >= 0; idx--) {
107 digit = value >> 28;
108 value <<= 4;
109 digit &= 0xf;
110 if (digit < 10)
111 digit += '0';
112 else
113 digit += 'A'-10;
114 *out++ = digit;
115 }
116 *out = '\0';
117 }
118
119
120
121
122
123
124
125
126
127 int atags_to_fdt(void *atag_list, void *fdt, int total_space)
128 {
129 struct tag *atag = atag_list;
130
131
132 uint32_t mem_reg_property[2 * 2 * NR_BANKS];
133 int memcount = 0;
134 int ret, memsize;
135
136
137 if ((u32)atag_list & 0x3)
138 return 1;
139
140
141 if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
142 return 0;
143
144
145 if (atag->hdr.tag != ATAG_CORE ||
146 (atag->hdr.size != tag_size(tag_core) &&
147 atag->hdr.size != 2))
148 return 1;
149
150
151 ret = fdt_open_into(fdt, fdt, total_space);
152 if (ret < 0)
153 return ret;
154
155 for_each_tag(atag, atag_list) {
156 if (atag->hdr.tag == ATAG_CMDLINE) {
157
158
159
160
161
162
163 if (do_extend_cmdline)
164 merge_fdt_bootargs(fdt,
165 atag->u.cmdline.cmdline);
166 else
167 setprop_string(fdt, "/chosen", "bootargs",
168 atag->u.cmdline.cmdline);
169 } else if (atag->hdr.tag == ATAG_MEM) {
170 if (memcount >= sizeof(mem_reg_property)/4)
171 continue;
172 if (!atag->u.mem.size)
173 continue;
174 memsize = get_cell_size(fdt);
175
176 if (memsize == 2) {
177
178
179
180 uint64_t *mem_reg_prop64 =
181 (uint64_t *)mem_reg_property;
182 mem_reg_prop64[memcount++] =
183 cpu_to_fdt64(atag->u.mem.start);
184 mem_reg_prop64[memcount++] =
185 cpu_to_fdt64(atag->u.mem.size);
186 } else {
187 mem_reg_property[memcount++] =
188 cpu_to_fdt32(atag->u.mem.start);
189 mem_reg_property[memcount++] =
190 cpu_to_fdt32(atag->u.mem.size);
191 }
192
193 } else if (atag->hdr.tag == ATAG_INITRD2) {
194 uint32_t initrd_start, initrd_size;
195 initrd_start = atag->u.initrd.start;
196 initrd_size = atag->u.initrd.size;
197 setprop_cell(fdt, "/chosen", "linux,initrd-start",
198 initrd_start);
199 setprop_cell(fdt, "/chosen", "linux,initrd-end",
200 initrd_start + initrd_size);
201 } else if (atag->hdr.tag == ATAG_SERIAL) {
202 char serno[16+2];
203 hex_str(serno, atag->u.serialnr.high);
204 hex_str(serno+8, atag->u.serialnr.low);
205 setprop_string(fdt, "/", "serial-number", serno);
206 }
207 }
208
209 if (memcount) {
210 setprop(fdt, "/memory", "reg", mem_reg_property,
211 4 * memcount * memsize);
212 }
213
214 return fdt_pack(fdt);
215 }