fdt_ddb.c revision 1.2 1 1.2 skrll /* $NetBSD: fdt_ddb.c,v 1.2 2021/03/06 13:21:26 skrll Exp $ */
2 1.1 skrll
3 1.1 skrll /*-
4 1.1 skrll * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 1.1 skrll * All rights reserved.
6 1.1 skrll *
7 1.1 skrll * This code is derived from software contributed to The NetBSD Foundation
8 1.1 skrll * by Nick Hudson
9 1.1 skrll *
10 1.1 skrll * Redistribution and use in source and binary forms, with or without
11 1.1 skrll * modification, are permitted provided that the following conditions
12 1.1 skrll * are met:
13 1.1 skrll * 1. Redistributions of source code must retain the above copyright
14 1.1 skrll * notice, this list of conditions and the following disclaimer.
15 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 skrll * notice, this list of conditions and the following disclaimer in the
17 1.1 skrll * documentation and/or other materials provided with the distribution.
18 1.1 skrll *
19 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 skrll * POSSIBILITY OF SUCH DAMAGE.
30 1.1 skrll */
31 1.1 skrll
32 1.1 skrll
33 1.1 skrll #include <sys/cdefs.h>
34 1.2 skrll __KERNEL_RCSID(0, "$NetBSD: fdt_ddb.c,v 1.2 2021/03/06 13:21:26 skrll Exp $");
35 1.1 skrll
36 1.1 skrll #include <sys/param.h>
37 1.1 skrll
38 1.1 skrll #include <libfdt.h>
39 1.1 skrll #include <dev/fdt/fdt_ddb.h>
40 1.1 skrll #include <dev/fdt/fdtvar.h>
41 1.1 skrll
42 1.1 skrll #define FDT_MAX_DEPTH 16
43 1.1 skrll
44 1.1 skrll static bool
45 1.1 skrll fdt_isprint(const void *data, int len)
46 1.1 skrll {
47 1.1 skrll const uint8_t *c = (const uint8_t *)data;
48 1.1 skrll
49 1.1 skrll if (len == 0)
50 1.1 skrll return false;
51 1.1 skrll
52 1.2 skrll /* Count consecutive zeroes */
53 1.2 skrll int cz = 0;
54 1.1 skrll for (size_t j = 0; j < len; j++) {
55 1.2 skrll if (c[j] == '\0')
56 1.2 skrll cz++;
57 1.2 skrll else if (isprint(c[j]))
58 1.2 skrll cz = 0;
59 1.2 skrll else
60 1.2 skrll return false;
61 1.2 skrll if (cz > 1)
62 1.1 skrll return false;
63 1.1 skrll }
64 1.1 skrll return true;
65 1.1 skrll }
66 1.1 skrll
67 1.1 skrll static void
68 1.1 skrll fdt_print_properties(const void *fdt, int node,
69 1.1 skrll void (*pr)(const char *, ...) __printflike(1, 2))
70 1.1 skrll {
71 1.1 skrll int property;
72 1.1 skrll
73 1.1 skrll fdt_for_each_property_offset(property, fdt, node) {
74 1.1 skrll int len;
75 1.1 skrll const struct fdt_property *prop =
76 1.1 skrll fdt_get_property_by_offset(fdt, property, &len);
77 1.1 skrll const char *name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
78 1.1 skrll
79 1.1 skrll pr(" %s", name);
80 1.1 skrll if (len == 0) {
81 1.1 skrll pr("\n");
82 1.1 skrll continue;
83 1.1 skrll }
84 1.1 skrll if (fdt_isprint(prop->data, len)) {
85 1.1 skrll const uint8_t *c = (const uint8_t *)prop->data;
86 1.1 skrll
87 1.1 skrll pr(" = \"");
88 1.1 skrll for (size_t j = 0; j < len; j++) {
89 1.1 skrll if (c[j] == '\0') {
90 1.1 skrll if (j + 1 != len)
91 1.1 skrll pr("\", \"");
92 1.1 skrll } else
93 1.1 skrll pr("%c", c[j]);
94 1.1 skrll }
95 1.1 skrll pr("\"\n");
96 1.1 skrll continue;
97 1.1 skrll }
98 1.1 skrll if ((len % 4) == 0) {
99 1.1 skrll const uint32_t *cell = (const uint32_t *)prop->data;
100 1.1 skrll size_t count = len / sizeof(uint32_t);
101 1.1 skrll
102 1.1 skrll pr(" = <");
103 1.1 skrll for (size_t j = 0; j < count; j++) {
104 1.1 skrll pr("%#" PRIx32 "%s", fdt32_to_cpu(cell[j]),
105 1.1 skrll (j != count - 1) ? " " : "");
106 1.1 skrll }
107 1.1 skrll pr(">\n");
108 1.1 skrll } else {
109 1.1 skrll const uint8_t *byte = (const uint8_t *)prop->data;
110 1.1 skrll
111 1.1 skrll pr(" = [");
112 1.1 skrll for (size_t j = 0; j < len; j++) {
113 1.1 skrll pr("%02x%s", byte[j],
114 1.1 skrll (j != len - 1) ? " " : "");
115 1.1 skrll }
116 1.1 skrll pr("]\n");
117 1.1 skrll }
118 1.1 skrll }
119 1.1 skrll }
120 1.1 skrll
121 1.1 skrll
122 1.1 skrll void
123 1.1 skrll fdt_print(const void *addr, bool full,
124 1.1 skrll void (*pr)(const char *, ...) __printflike(1, 2))
125 1.1 skrll {
126 1.1 skrll const void *fdt = addr;
127 1.1 skrll const char *pname[FDT_MAX_DEPTH] = { NULL };
128 1.1 skrll
129 1.1 skrll int error = fdt_check_header(fdt);
130 1.1 skrll if (error) {
131 1.1 skrll pr("Invalid FDT at %p\n", fdt);
132 1.1 skrll return;
133 1.1 skrll }
134 1.1 skrll
135 1.1 skrll int depth = 0;
136 1.1 skrll for (int node = fdt_path_offset(fdt, "/");
137 1.1 skrll node >= 0 && depth >= 0;
138 1.1 skrll node = fdt_next_node(fdt, node, &depth)) {
139 1.1 skrll const char *name = fdt_get_name(fdt, node, NULL);
140 1.1 skrll
141 1.1 skrll if (depth > FDT_MAX_DEPTH) {
142 1.1 skrll pr("max depth exceeded: %d\n", depth);
143 1.1 skrll continue;
144 1.1 skrll }
145 1.1 skrll pname[depth] = name;
146 1.1 skrll /*
147 1.1 skrll * change conditional for when alternative root nodes
148 1.1 skrll * can be specified
149 1.1 skrll */
150 1.1 skrll if (depth == 0)
151 1.1 skrll pr("/");
152 1.1 skrll for (size_t i = 1; i <= depth; i++) {
153 1.1 skrll if (pname[i] == NULL)
154 1.1 skrll break;
155 1.1 skrll pr("/%s", pname[i]);
156 1.1 skrll }
157 1.1 skrll pr("\n");
158 1.1 skrll if (!full)
159 1.1 skrll continue;
160 1.1 skrll fdt_print_properties(fdt, node, pr);
161 1.1 skrll }
162 1.1 skrll }
163