Sun Jan 24 15:43:23 2021 UTC ()
Use strlist(9).


(thorpej)
diff -r1.38 -r1.39 src/sys/dev/fdt/fdt_subr.c

cvs diff -r1.38 -r1.39 src/sys/dev/fdt/fdt_subr.c (switch to unified diff)

--- src/sys/dev/fdt/fdt_subr.c 2020/07/16 16:39:18 1.38
+++ src/sys/dev/fdt/fdt_subr.c 2021/01/24 15:43:22 1.39
@@ -1,543 +1,532 @@ @@ -1,543 +1,532 @@
1/* $NetBSD: fdt_subr.c,v 1.38 2020/07/16 16:39:18 jmcneill Exp $ */ 1/* $NetBSD: fdt_subr.c,v 1.39 2021/01/24 15:43:22 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.38 2020/07/16 16:39:18 jmcneill Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.39 2021/01/24 15:43:22 thorpej Exp $");
31 31
32#include "opt_fdt.h" 32#include "opt_fdt.h"
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/bus.h> 35#include <sys/bus.h>
36 36
37#include <libfdt.h> 37#include <libfdt.h>
38#include <dev/fdt/fdtvar.h> 38#include <dev/fdt/fdtvar.h>
39#include <dev/fdt/fdt_private.h> 39#include <dev/fdt/fdt_private.h>
40 40
41#ifndef FDT_DEFAULT_STDOUT_PATH 41#ifndef FDT_DEFAULT_STDOUT_PATH
42#define FDT_DEFAULT_STDOUT_PATH "serial0:115200n8" 42#define FDT_DEFAULT_STDOUT_PATH "serial0:115200n8"
43#endif 43#endif
44 44
45static const void *fdt_data; 45static const void *fdt_data;
46 46
47static struct fdt_conslist fdt_console_list = 47static struct fdt_conslist fdt_console_list =
48 TAILQ_HEAD_INITIALIZER(fdt_console_list); 48 TAILQ_HEAD_INITIALIZER(fdt_console_list);
49 49
50bool 50bool
51fdtbus_init(const void *data) 51fdtbus_init(const void *data)
52{ 52{
53 KASSERT(fdt_data == NULL); 53 KASSERT(fdt_data == NULL);
54 if (fdt_check_header(data) != 0) { 54 if (fdt_check_header(data) != 0) {
55 return false; 55 return false;
56 } 56 }
57 fdt_data = data; 57 fdt_data = data;
58 58
59 return true; 59 return true;
60} 60}
61 61
62const void * 62const void *
63fdtbus_get_data(void) 63fdtbus_get_data(void)
64{ 64{
65 return fdt_data; 65 return fdt_data;
66} 66}
67 67
68int 68int
69fdtbus_offset2phandle(int offset) 69fdtbus_offset2phandle(int offset)
70{ 70{
71 if (offset < 0) 71 if (offset < 0)
72 return 0; 72 return 0;
73 73
74 return offset + fdt_off_dt_struct(fdt_data); 74 return offset + fdt_off_dt_struct(fdt_data);
75} 75}
76 76
77int 77int
78fdtbus_phandle2offset(int phandle) 78fdtbus_phandle2offset(int phandle)
79{ 79{
80 const int dtoff = fdt_off_dt_struct(fdt_data); 80 const int dtoff = fdt_off_dt_struct(fdt_data);
81 81
82 if (phandle == -1) 82 if (phandle == -1)
83 phandle = dtoff; 83 phandle = dtoff;
84 84
85 if (phandle < dtoff) 85 if (phandle < dtoff)
86 return -1; 86 return -1;
87 87
88 return phandle - dtoff; 88 return phandle - dtoff;
89} 89}
90 90
91static bool fdtbus_decoderegprop = true; 91static bool fdtbus_decoderegprop = true;
92 92
93void 93void
94fdtbus_set_decoderegprop(bool decode) 94fdtbus_set_decoderegprop(bool decode)
95{ 95{
96 fdtbus_decoderegprop = decode; 96 fdtbus_decoderegprop = decode;
97} 97}
98 98
99int 99int
100fdtbus_get_addr_cells(int phandle) 100fdtbus_get_addr_cells(int phandle)
101{ 101{
102 uint32_t addr_cells; 102 uint32_t addr_cells;
103 103
104 if (of_getprop_uint32(phandle, "#address-cells", &addr_cells)) 104 if (of_getprop_uint32(phandle, "#address-cells", &addr_cells))
105 addr_cells = 2; 105 addr_cells = 2;
106 106
107 return addr_cells; 107 return addr_cells;
108} 108}
109 109
110int 110int
111fdtbus_get_size_cells(int phandle) 111fdtbus_get_size_cells(int phandle)
112{ 112{
113 uint32_t size_cells; 113 uint32_t size_cells;
114 114
115 if (of_getprop_uint32(phandle, "#size-cells", &size_cells)) 115 if (of_getprop_uint32(phandle, "#size-cells", &size_cells))
116 size_cells = 0; 116 size_cells = 0;
117 117
118 return size_cells; 118 return size_cells;
119} 119}
120 120
121int 121int
122fdtbus_get_phandle(int phandle, const char *prop) 122fdtbus_get_phandle(int phandle, const char *prop)
123{ 123{
124 u_int phandle_ref; 124 u_int phandle_ref;
125 const u_int *buf; 125 const u_int *buf;
126 int len; 126 int len;
127 127
128 buf = fdt_getprop(fdtbus_get_data(), 128 buf = fdt_getprop(fdtbus_get_data(),
129 fdtbus_phandle2offset(phandle), prop, &len); 129 fdtbus_phandle2offset(phandle), prop, &len);
130 if (buf == NULL || len < sizeof(phandle_ref)) 130 if (buf == NULL || len < sizeof(phandle_ref))
131 return -1; 131 return -1;
132 132
133 phandle_ref = be32dec(buf); 133 phandle_ref = be32dec(buf);
134 134
135 return fdtbus_get_phandle_from_native(phandle_ref); 135 return fdtbus_get_phandle_from_native(phandle_ref);
136} 136}
137 137
138int 138int
139fdtbus_get_phandle_with_data(int phandle, const char *prop, const char *cells, 139fdtbus_get_phandle_with_data(int phandle, const char *prop, const char *cells,
140 int index, struct fdt_phandle_data *data) 140 int index, struct fdt_phandle_data *data)
141{ 141{
142 int len; 142 int len;
143 const int offset = 1; 143 const int offset = 1;
144 144
145 const u_int *p = fdtbus_get_prop(phandle, prop, &len); 145 const u_int *p = fdtbus_get_prop(phandle, prop, &len);
146 if (p == NULL || len <= 0) 146 if (p == NULL || len <= 0)
147 return EINVAL; 147 return EINVAL;
148 148
149 for (int i = 0; len > 0; i++) { 149 for (int i = 0; len > 0; i++) {
150 u_int phandle_ref = be32toh(*p); 150 u_int phandle_ref = be32toh(*p);
151 const u_int iparent = fdtbus_get_phandle_from_native(phandle_ref); 151 const u_int iparent = fdtbus_get_phandle_from_native(phandle_ref);
152 uint32_t cells_num; 152 uint32_t cells_num;
153 of_getprop_uint32(iparent, cells, &cells_num); 153 of_getprop_uint32(iparent, cells, &cells_num);
154 154
155 if (index == i) { 155 if (index == i) {
156 if (data != NULL) { 156 if (data != NULL) {
157 data->phandle = iparent; 157 data->phandle = iparent;
158 data->count = cells_num; 158 data->count = cells_num;
159 data->values = p + offset; 159 data->values = p + offset;
160 } 160 }
161 goto done; 161 goto done;
162 } 162 }
163 163
164 const u_int reclen = offset + cells_num; 164 const u_int reclen = offset + cells_num;
165 len -= reclen * sizeof(u_int); 165 len -= reclen * sizeof(u_int);
166 p += reclen; 166 p += reclen;
167 } 167 }
168 return EINVAL; 168 return EINVAL;
169 169
170done: 170done:
171 return 0; 171 return 0;
172} 172}
173 173
174int 174int
175fdtbus_get_phandle_from_native(int phandle) 175fdtbus_get_phandle_from_native(int phandle)
176{ 176{
177 const int off = fdt_node_offset_by_phandle(fdt_data, phandle); 177 const int off = fdt_node_offset_by_phandle(fdt_data, phandle);
178 if (off < 0) { 178 if (off < 0) {
179 return -1; 179 return -1;
180 } 180 }
181 return fdtbus_offset2phandle(off); 181 return fdtbus_offset2phandle(off);
182} 182}
183 183
184bool 184bool
185fdtbus_get_path(int phandle, char *buf, size_t buflen) 185fdtbus_get_path(int phandle, char *buf, size_t buflen)
186{ 186{
187 const int off = fdtbus_phandle2offset(phandle); 187 const int off = fdtbus_phandle2offset(phandle);
188 if (off < 0) { 188 if (off < 0) {
189 return false; 189 return false;
190 } 190 }
191 if (fdt_get_path(fdt_data, off, buf, (int)buflen) != 0) { 191 if (fdt_get_path(fdt_data, off, buf, (int)buflen) != 0) {
192 return false; 192 return false;
193 } 193 }
194 return true; 194 return true;
195} 195}
196 196
197uint64_t 197uint64_t
198fdtbus_get_cells(const uint8_t *buf, int cells) 198fdtbus_get_cells(const uint8_t *buf, int cells)
199{ 199{
200 switch (cells) { 200 switch (cells) {
201 case 0: return 0; 201 case 0: return 0;
202 case 1: return be32dec(buf); 202 case 1: return be32dec(buf);
203 case 2: return ((uint64_t)be32dec(buf)<<32)|be32dec(buf+4); 203 case 2: return ((uint64_t)be32dec(buf)<<32)|be32dec(buf+4);
204 default: panic("fdtbus_get_cells: bad cells val %d\n", cells); 204 default: panic("fdtbus_get_cells: bad cells val %d\n", cells);
205 } 205 }
206} 206}
207 207
208static uint64_t 208static uint64_t
209fdtbus_decode_range(int phandle, uint64_t paddr) 209fdtbus_decode_range(int phandle, uint64_t paddr)
210{ 210{
211 const int parent = OF_parent(phandle); 211 const int parent = OF_parent(phandle);
212 if (parent == -1) 212 if (parent == -1)
213 return paddr; 213 return paddr;
214 214
215 if (!fdtbus_decoderegprop) 215 if (!fdtbus_decoderegprop)
216 return paddr; 216 return paddr;
217 217
218 const uint8_t *buf; 218 const uint8_t *buf;
219 int len; 219 int len;
220 220
221 buf = fdt_getprop(fdtbus_get_data(), 221 buf = fdt_getprop(fdtbus_get_data(),
222 fdtbus_phandle2offset(phandle), "ranges", &len); 222 fdtbus_phandle2offset(phandle), "ranges", &len);
223 if (buf == NULL) 223 if (buf == NULL)
224 return paddr; 224 return paddr;
225 225
226 if (len == 0) { 226 if (len == 0) {
227 /* pass through to parent */ 227 /* pass through to parent */
228 return fdtbus_decode_range(parent, paddr); 228 return fdtbus_decode_range(parent, paddr);
229 } 229 }
230 230
231 const int addr_cells = fdtbus_get_addr_cells(phandle); 231 const int addr_cells = fdtbus_get_addr_cells(phandle);
232 const int size_cells = fdtbus_get_size_cells(phandle); 232 const int size_cells = fdtbus_get_size_cells(phandle);
233 const int paddr_cells = fdtbus_get_addr_cells(parent); 233 const int paddr_cells = fdtbus_get_addr_cells(parent);
234 if (addr_cells == -1 || size_cells == -1 || paddr_cells == -1) 234 if (addr_cells == -1 || size_cells == -1 || paddr_cells == -1)
235 return paddr; 235 return paddr;
236 236
237 while (len > 0) { 237 while (len > 0) {
238 uint64_t cba, pba, cl; 238 uint64_t cba, pba, cl;
239 cba = fdtbus_get_cells(buf, addr_cells); 239 cba = fdtbus_get_cells(buf, addr_cells);
240 buf += addr_cells * 4; 240 buf += addr_cells * 4;
241 pba = fdtbus_get_cells(buf, paddr_cells); 241 pba = fdtbus_get_cells(buf, paddr_cells);
242 buf += paddr_cells * 4; 242 buf += paddr_cells * 4;
243 cl = fdtbus_get_cells(buf, size_cells); 243 cl = fdtbus_get_cells(buf, size_cells);
244 buf += size_cells * 4; 244 buf += size_cells * 4;
245 245
246#ifdef FDTBUS_DEBUG 246#ifdef FDTBUS_DEBUG
247 printf("%s: %s: cba=%#" PRIx64 ", pba=%#" PRIx64 ", cl=%#" PRIx64 "\n", __func__, fdt_get_name(fdtbus_get_data(), fdtbus_phandle2offset(phandle), NULL), cba, pba, cl); 247 printf("%s: %s: cba=%#" PRIx64 ", pba=%#" PRIx64 ", cl=%#" PRIx64 "\n", __func__, fdt_get_name(fdtbus_get_data(), fdtbus_phandle2offset(phandle), NULL), cba, pba, cl);
248#endif 248#endif
249 249
250 if (paddr >= cba && paddr < cba + cl) 250 if (paddr >= cba && paddr < cba + cl)
251 return fdtbus_decode_range(parent, pba) + (paddr - cba); 251 return fdtbus_decode_range(parent, pba) + (paddr - cba);
252 252
253 len -= (addr_cells + paddr_cells + size_cells) * 4; 253 len -= (addr_cells + paddr_cells + size_cells) * 4;
254 } 254 }
255 255
256 /* No mapping found */ 256 /* No mapping found */
257 return paddr; 257 return paddr;
258} 258}
259 259
260int 260int
261fdtbus_get_reg_byname(int phandle, const char *name, bus_addr_t *paddr, 261fdtbus_get_reg_byname(int phandle, const char *name, bus_addr_t *paddr,
262 bus_size_t *psize) 262 bus_size_t *psize)
263{ 263{
264 u_int index; 264 u_int index;
265 int error; 265 int error;
266 266
267 error = fdtbus_get_index(phandle, "reg-names", name, &index); 267 error = fdtbus_get_index(phandle, "reg-names", name, &index);
268 if (error != 0) 268 if (error != 0)
269 return ENOENT; 269 return ENOENT;
270 270
271 return fdtbus_get_reg(phandle, index, paddr, psize); 271 return fdtbus_get_reg(phandle, index, paddr, psize);
272} 272}
273 273
274int 274int
275fdtbus_get_reg(int phandle, u_int index, bus_addr_t *paddr, bus_size_t *psize) 275fdtbus_get_reg(int phandle, u_int index, bus_addr_t *paddr, bus_size_t *psize)
276{ 276{
277 uint64_t addr, size; 277 uint64_t addr, size;
278 int error; 278 int error;
279 279
280 error = fdtbus_get_reg64(phandle, index, &addr, &size); 280 error = fdtbus_get_reg64(phandle, index, &addr, &size);
281 if (error) 281 if (error)
282 return error; 282 return error;
283 283
284 if (sizeof(bus_addr_t) == 4 && (addr + size) > 0x100000000) 284 if (sizeof(bus_addr_t) == 4 && (addr + size) > 0x100000000)
285 return ERANGE; 285 return ERANGE;
286 286
287 if (paddr) 287 if (paddr)
288 *paddr = (bus_addr_t)addr; 288 *paddr = (bus_addr_t)addr;
289 if (psize) 289 if (psize)
290 *psize = (bus_size_t)size; 290 *psize = (bus_size_t)size;
291 291
292 return 0; 292 return 0;
293} 293}
294 294
295int 295int
296fdtbus_get_reg64(int phandle, u_int index, uint64_t *paddr, uint64_t *psize) 296fdtbus_get_reg64(int phandle, u_int index, uint64_t *paddr, uint64_t *psize)
297{ 297{
298 uint64_t addr, size; 298 uint64_t addr, size;
299 const uint8_t *buf; 299 const uint8_t *buf;
300 int len; 300 int len;
301 301
302 const int addr_cells = fdtbus_get_addr_cells(OF_parent(phandle)); 302 const int addr_cells = fdtbus_get_addr_cells(OF_parent(phandle));
303 const int size_cells = fdtbus_get_size_cells(OF_parent(phandle)); 303 const int size_cells = fdtbus_get_size_cells(OF_parent(phandle));
304 if (addr_cells == -1 || size_cells == -1) 304 if (addr_cells == -1 || size_cells == -1)
305 return EINVAL; 305 return EINVAL;
306 306
307 buf = fdt_getprop(fdtbus_get_data(), 307 buf = fdt_getprop(fdtbus_get_data(),
308 fdtbus_phandle2offset(phandle), "reg", &len); 308 fdtbus_phandle2offset(phandle), "reg", &len);
309 if (buf == NULL || len <= 0) 309 if (buf == NULL || len <= 0)
310 return EINVAL; 310 return EINVAL;
311 311
312 const u_int reglen = size_cells * 4 + addr_cells * 4; 312 const u_int reglen = size_cells * 4 + addr_cells * 4;
313 if (reglen == 0) 313 if (reglen == 0)
314 return EINVAL; 314 return EINVAL;
315 315
316 if (index >= len / reglen) 316 if (index >= len / reglen)
317 return ENXIO; 317 return ENXIO;
318 318
319 buf += index * reglen; 319 buf += index * reglen;
320 addr = fdtbus_get_cells(buf, addr_cells); 320 addr = fdtbus_get_cells(buf, addr_cells);
321 buf += addr_cells * 4; 321 buf += addr_cells * 4;
322 size = fdtbus_get_cells(buf, size_cells); 322 size = fdtbus_get_cells(buf, size_cells);
323 323
324 if (paddr) { 324 if (paddr) {
325 *paddr = fdtbus_decode_range(OF_parent(phandle), addr); 325 *paddr = fdtbus_decode_range(OF_parent(phandle), addr);
326#ifdef FDTBUS_DEBUG 326#ifdef FDTBUS_DEBUG
327 const char *name = fdt_get_name(fdtbus_get_data(), 327 const char *name = fdt_get_name(fdtbus_get_data(),
328 fdtbus_phandle2offset(phandle), NULL); 328 fdtbus_phandle2offset(phandle), NULL);
329 printf("fdt: [%s] decoded addr #%u: %" PRIx64 329 printf("fdt: [%s] decoded addr #%u: %" PRIx64
330 " -> %" PRIx64 "\n", name, index, addr, *paddr); 330 " -> %" PRIx64 "\n", name, index, addr, *paddr);
331#endif 331#endif
332 } 332 }
333 if (psize) 333 if (psize)
334 *psize = size; 334 *psize = size;
335 335
336 return 0; 336 return 0;
337} 337}
338 338
339#if defined(FDT) 339#if defined(FDT)
340const struct fdt_console * 340const struct fdt_console *
341fdtbus_get_console(void) 341fdtbus_get_console(void)
342{ 342{
343 static const struct fdt_console_info *booted_console = NULL; 343 static const struct fdt_console_info *booted_console = NULL;
344 344
345 if (booted_console == NULL) { 345 if (booted_console == NULL) {
346 __link_set_decl(fdt_consoles, struct fdt_console_info); 346 __link_set_decl(fdt_consoles, struct fdt_console_info);
347 struct fdt_console_info * const *info; 347 struct fdt_console_info * const *info;
348 const struct fdt_console_info *best_info = NULL; 348 const struct fdt_console_info *best_info = NULL;
349 const int phandle = fdtbus_get_stdout_phandle(); 349 const int phandle = fdtbus_get_stdout_phandle();
350 int best_match = 0; 350 int best_match = 0;
351 351
352 if (phandle == -1) { 352 if (phandle == -1) {
353 printf("WARNING: no console device\n"); 353 printf("WARNING: no console device\n");
354 return NULL; 354 return NULL;
355 } 355 }
356 356
357 __link_set_foreach(info, fdt_consoles) { 357 __link_set_foreach(info, fdt_consoles) {
358 const int match = (*info)->ops->match(phandle); 358 const int match = (*info)->ops->match(phandle);
359 if (match > best_match) { 359 if (match > best_match) {
360 best_match = match; 360 best_match = match;
361 best_info = *info; 361 best_info = *info;
362 } 362 }
363 } 363 }
364 364
365 booted_console = best_info; 365 booted_console = best_info;
366 } 366 }
367 367
368 return booted_console == NULL ? NULL : booted_console->ops; 368 return booted_console == NULL ? NULL : booted_console->ops;
369} 369}
370#endif 370#endif
371 371
372const char * 372const char *
373fdtbus_get_stdout_path(void) 373fdtbus_get_stdout_path(void)
374{ 374{
375 const char *prop; 375 const char *prop;
376 376
377 const int off = fdt_path_offset(fdtbus_get_data(), "/chosen"); 377 const int off = fdt_path_offset(fdtbus_get_data(), "/chosen");
378 if (off >= 0) { 378 if (off >= 0) {
379 prop = fdt_getprop(fdtbus_get_data(), off, "stdout-path", NULL); 379 prop = fdt_getprop(fdtbus_get_data(), off, "stdout-path", NULL);
380 if (prop != NULL) 380 if (prop != NULL)
381 return prop; 381 return prop;
382 } 382 }
383 383
384 /* If the stdout-path property is not found, return the default */ 384 /* If the stdout-path property is not found, return the default */
385 return FDT_DEFAULT_STDOUT_PATH; 385 return FDT_DEFAULT_STDOUT_PATH;
386} 386}
387 387
388int 388int
389fdtbus_get_stdout_phandle(void) 389fdtbus_get_stdout_phandle(void)
390{ 390{
391 const char *prop, *p; 391 const char *prop, *p;
392 int off, len; 392 int off, len;
393 393
394 prop = fdtbus_get_stdout_path(); 394 prop = fdtbus_get_stdout_path();
395 if (prop == NULL) 395 if (prop == NULL)
396 return -1; 396 return -1;
397 397
398 p = strchr(prop, ':'); 398 p = strchr(prop, ':');
399 len = p == NULL ? strlen(prop) : (p - prop); 399 len = p == NULL ? strlen(prop) : (p - prop);
400 if (*prop != '/') { 400 if (*prop != '/') {
401 /* Alias */ 401 /* Alias */
402 prop = fdt_get_alias_namelen(fdtbus_get_data(), prop, len); 402 prop = fdt_get_alias_namelen(fdtbus_get_data(), prop, len);
403 if (prop == NULL) 403 if (prop == NULL)
404 return -1; 404 return -1;
405 len = strlen(prop); 405 len = strlen(prop);
406 } 406 }
407 off = fdt_path_offset_namelen(fdtbus_get_data(), prop, len); 407 off = fdt_path_offset_namelen(fdtbus_get_data(), prop, len);
408 if (off < 0) 408 if (off < 0)
409 return -1; 409 return -1;
410 410
411 return fdtbus_offset2phandle(off); 411 return fdtbus_offset2phandle(off);
412} 412}
413 413
414int 414int
415fdtbus_get_stdout_speed(void) 415fdtbus_get_stdout_speed(void)
416{ 416{
417 const char *prop, *p; 417 const char *prop, *p;
418 418
419 prop = fdtbus_get_stdout_path(); 419 prop = fdtbus_get_stdout_path();
420 if (prop == NULL) 420 if (prop == NULL)
421 return -1; 421 return -1;
422 422
423 p = strchr(prop, ':'); 423 p = strchr(prop, ':');
424 if (p == NULL) 424 if (p == NULL)
425 return -1; 425 return -1;
426 426
427 return (int)strtoul(p + 1, NULL, 10); 427 return (int)strtoul(p + 1, NULL, 10);
428} 428}
429 429
430tcflag_t 430tcflag_t
431fdtbus_get_stdout_flags(void) 431fdtbus_get_stdout_flags(void)
432{ 432{
433 const char *prop, *p; 433 const char *prop, *p;
434 tcflag_t flags = TTYDEF_CFLAG; 434 tcflag_t flags = TTYDEF_CFLAG;
435 char *ep; 435 char *ep;
436 436
437 prop = fdtbus_get_stdout_path(); 437 prop = fdtbus_get_stdout_path();
438 if (prop == NULL) 438 if (prop == NULL)
439 return flags; 439 return flags;
440 440
441 p = strchr(prop, ':'); 441 p = strchr(prop, ':');
442 if (p == NULL) 442 if (p == NULL)
443 return flags; 443 return flags;
444 444
445 ep = NULL; 445 ep = NULL;
446 (void)strtoul(p + 1, &ep, 10); 446 (void)strtoul(p + 1, &ep, 10);
447 if (ep == NULL) 447 if (ep == NULL)
448 return flags; 448 return flags;
449 449
450 /* <baud>{<parity>{<bits>{<flow>}}} */ 450 /* <baud>{<parity>{<bits>{<flow>}}} */
451 while (*ep) { 451 while (*ep) {
452 switch (*ep) { 452 switch (*ep) {
453 /* parity */ 453 /* parity */
454 case 'n': flags &= ~(PARENB|PARODD); break; 454 case 'n': flags &= ~(PARENB|PARODD); break;
455 case 'e': flags &= ~PARODD; flags |= PARENB; break; 455 case 'e': flags &= ~PARODD; flags |= PARENB; break;
456 case 'o': flags |= (PARENB|PARODD); break; 456 case 'o': flags |= (PARENB|PARODD); break;
457 /* bits */ 457 /* bits */
458 case '5': flags &= ~CSIZE; flags |= CS5; break; 458 case '5': flags &= ~CSIZE; flags |= CS5; break;
459 case '6': flags &= ~CSIZE; flags |= CS6; break; 459 case '6': flags &= ~CSIZE; flags |= CS6; break;
460 case '7': flags &= ~CSIZE; flags |= CS7; break; 460 case '7': flags &= ~CSIZE; flags |= CS7; break;
461 case '8': flags &= ~CSIZE; flags |= CS8; break; 461 case '8': flags &= ~CSIZE; flags |= CS8; break;
462 /* flow */ 462 /* flow */
463 case 'r': flags |= CRTSCTS; break; 463 case 'r': flags |= CRTSCTS; break;
464 } 464 }
465 ep++; 465 ep++;
466 } 466 }
467 467
468 return flags; 468 return flags;
469} 469}
470 470
471bool 471bool
472fdtbus_status_okay(int phandle) 472fdtbus_status_okay(int phandle)
473{ 473{
474 const int off = fdtbus_phandle2offset(phandle); 474 const int off = fdtbus_phandle2offset(phandle);
475 475
476 const char *prop = fdt_getprop(fdtbus_get_data(), off, "status", NULL); 476 const char *prop = fdt_getprop(fdtbus_get_data(), off, "status", NULL);
477 if (prop == NULL) 477 if (prop == NULL)
478 return true; 478 return true;
479 479
480 return strncmp(prop, "ok", 2) == 0; 480 return strncmp(prop, "ok", 2) == 0;
481} 481}
482 482
483const void * 483const void *
484fdtbus_get_prop(int phandle, const char *prop, int *plen) 484fdtbus_get_prop(int phandle, const char *prop, int *plen)
485{ 485{
486 const int off = fdtbus_phandle2offset(phandle); 486 const int off = fdtbus_phandle2offset(phandle);
487 487
488 return fdt_getprop(fdtbus_get_data(), off, prop, plen); 488 return fdt_getprop(fdtbus_get_data(), off, prop, plen);
489} 489}
490 490
491const char * 491const char *
492fdtbus_get_string(int phandle, const char *prop) 492fdtbus_get_string(int phandle, const char *prop)
493{ 493{
494 const int off = fdtbus_phandle2offset(phandle); 494 const int off = fdtbus_phandle2offset(phandle);
495 495
496 if (strcmp(prop, "name") == 0) 496 if (strcmp(prop, "name") == 0)
497 return fdt_get_name(fdtbus_get_data(), off, NULL); 497 return fdt_get_name(fdtbus_get_data(), off, NULL);
498 else 498 else
499 return fdt_getprop(fdtbus_get_data(), off, prop, NULL); 499 return fdt_getprop(fdtbus_get_data(), off, prop, NULL);
500} 500}
501 501
502const char * 502const char *
503fdtbus_get_string_index(int phandle, const char *prop, u_int index) 503fdtbus_get_string_index(int phandle, const char *prop, u_int index)
504{ 504{
505 const char *names, *name; 505 const char *names;
506 int len, cur; 506 int len;
507 507
508 if ((len = OF_getproplen(phandle, prop)) < 0) 508 if ((len = OF_getproplen(phandle, prop)) < 0)
509 return NULL; 509 return NULL;
510 510
511 names = fdtbus_get_string(phandle, prop); 511 names = fdtbus_get_string(phandle, prop);
512 512
513 for (name = names, cur = 0; len > 0; 513 return strlist_string(names, len, index);
514 len -= strlen(name) + 1, name += strlen(name) + 1, cur++) { 
515 if (index == cur) 
516 return name; 
517 } 
518 
519 return NULL; 
520} 514}
521 515
522int 516int
523fdtbus_get_index(int phandle, const char *prop, const char *name, u_int *idx) 517fdtbus_get_index(int phandle, const char *prop, const char *name, u_int *idx)
524{ 518{
525 const char *p; 519 const char *p;
526 size_t pl; 520 int len, index;
527 u_int index; 
528 int len; 
529 521
530 p = fdtbus_get_prop(phandle, prop, &len); 522 p = fdtbus_get_prop(phandle, prop, &len);
531 if (p == NULL || len <= 0) 523 if (p == NULL || len <= 0)
532 return -1; 524 return -1;
533 525
534 for (index = 0; len > 0; 526 index = strlist_index(p, len, name);
535 pl = strlen(p) + 1, len -= pl, p += pl, index++) { 527 if (index == -1)
536 if (strcmp(p, name) == 0) { 528 return -1;
537 *idx = index; 
538 return 0; 
539 } 
540 } 
541 529
542 return -1; 530 *idx = index;
 531 return 0;
543} 532}