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