diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c index a3af5a5400c8..530c8b238403 100644 --- a/sys/ddb/db_command.c +++ b/sys/ddb/db_command.c @@ -66,6 +66,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.173 2020/10/30 07:17:29 skrll Exp $ #ifdef _KERNEL_OPT #include "opt_aio.h" #include "opt_ddb.h" +#include "opt_fdt.h" #include "opt_kgdb.h" #include "opt_mqueue.h" #include "opt_inet.h" @@ -102,6 +103,11 @@ __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.173 2020/10/30 07:17:29 skrll Exp $ #include +#ifdef FDT +#include +#include +#endif + /* * Results of command search. */ @@ -219,6 +225,9 @@ static void db_vnode_print_cmd(db_expr_t, bool, db_expr_t, const char *); static void db_vnode_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *); static void db_vmem_print_cmd(db_expr_t, bool, db_expr_t, const char *); +#ifdef FDT +static void db_fdt_print_cmd(db_expr_t, bool, db_expr_t, const char *); +#endif static const struct db_command db_show_cmds[] = { { DDB_ADD_CMD("all", NULL, @@ -239,6 +248,10 @@ static const struct db_command db_show_cmds[] = { { DDB_ADD_CMD("devices", db_show_all_devices, 0,NULL,NULL,NULL) }, { DDB_ADD_CMD("event", db_event_print_cmd, 0, "Print all the non-zero evcnt(9) event counters.", "[/fitm]",NULL) }, +#ifdef FDT + { DDB_ADD_CMD("fdt", db_fdt_print_cmd, 0, + "Show FDT information", NULL, NULL) }, +#endif { DDB_ADD_CMD("files", db_show_files_cmd, 0, "Print the files open by process at address", "[/f] address", NULL) }, @@ -1346,6 +1359,27 @@ db_show_lockstats(db_expr_t addr, bool have_addr, #endif } +#ifdef FDT +/*ARGSUSED*/ +static void +db_fdt_print_cmd(db_expr_t addr, bool have_addr, + db_expr_t count, const char *modif) +{ +#ifdef _KERNEL /* XXX CRASH(8) */ + bool full = false; + + if (modif[0] == 'f') + full = true; + + fdt_print(have_addr ? (void *)(uintptr_t)addr : fdtbus_get_data(), + full, db_printf); +#else + also; + db_kernelonly(); +#endif +} +#endif + /* * Call random function: * !expr(arg,arg,arg) diff --git a/sys/dev/fdt/fdt_ddb.c b/sys/dev/fdt/fdt_ddb.c new file mode 100644 index 000000000000..a30bc7763a3b --- /dev/null +++ b/sys/dev/fdt/fdt_ddb.c @@ -0,0 +1,154 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +__KERNEL_RCSID(0, "$NetBSD$"); + +#include + +#include +#include +#include + +#define FDT_MAX_DEPTH 16 + +static bool +fdt_isprint(const void *data, int len) +{ + const uint8_t *c = (const uint8_t *)data; + + if (len == 0) + return false; + + for (size_t j = 0; j < len; j++) { + if (!(isprint(c[j]) || c[j] == '\0')) + return false; + } + return true; +} + +static void +fdt_print_properties(const void *fdt, int node, + void (*pr)(const char *, ...) __printflike(1, 2)) +{ + int property; + + fdt_for_each_property_offset(property, fdt, node) { + int len; + const struct fdt_property *prop = + fdt_get_property_by_offset(fdt, property, &len); + const char *name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + + pr(" %s", name); + if (len == 0) { + pr("\n"); + continue; + } + if (fdt_isprint(prop->data, len)) { + const uint8_t *c = (const uint8_t *)prop->data; + + pr(" = \""); + for (size_t j = 0; j < len; j++) { + if (c[j] == '\0') { + if (j + 1 != len) + pr("\", \""); + } else + pr("%c", c[j]); + } + pr("\"\n"); + continue; + } + if ((len % 4) == 0) { + const uint32_t *cell = (const uint32_t *)prop->data; + size_t count = len / sizeof(uint32_t); + + pr(" = <"); + for (size_t j = 0; j < count; j++) { + pr("%#" PRIx32 "%s", fdt32_to_cpu(cell[j]), + (j != count - 1) ? " " : ""); + } + pr(">\n"); + } else { + const uint8_t *byte = (const uint8_t *)prop->data; + + pr(" = ["); + for (size_t j = 0; j < len; j++) { + pr("%02x%s", byte[j], + (j != len - 1) ? " " : ""); + } + pr("]\n"); + } + } +} + + +void +fdt_print(const void *addr, bool full, + void (*pr)(const char *, ...) __printflike(1, 2)) +{ + const void *fdt = addr; + const char *pname[FDT_MAX_DEPTH] = { NULL }; + + int error = fdt_check_header(fdt); + if (error) { + pr("Invalid FDT at %p\n", fdt); + return; + } + + int depth = 0; + for (int node = fdt_path_offset(fdt, "/"); + node >= 0 && depth >= 0; + node = fdt_next_node(fdt, node, &depth)) { + const char *name = fdt_get_name(fdt, node, NULL); + + if (depth > FDT_MAX_DEPTH) { + pr("max depth exceeded: %d\n", depth); + continue; + } + pname[depth] = name; + /* + * change conditional for when alternative root nodes + * can be specified + */ + if (depth == 0) + pr("/"); + for (size_t i = 1; i <= depth; i++) { + if (pname[i] == NULL) + break; + pr("/%s", pname[i]); + } + pr("\n"); + if (!full) + continue; + fdt_print_properties(fdt, node, pr); + } +} diff --git a/sys/dev/fdt/fdt_ddb.h b/sys/dev/fdt/fdt_ddb.h new file mode 100644 index 000000000000..3ac34a6dedd6 --- /dev/null +++ b/sys/dev/fdt/fdt_ddb.h @@ -0,0 +1,38 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _FDT_DDB_H +#define _FDT_DDB_H + +void fdt_print(const void *, bool, void (*)(const char *, ...) __printflike(1, 2)); + +#endif diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index 6e7151ff84b5..ba56a5cec8b1 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -58,6 +58,7 @@ file dev/fdt/fdt_subr.c fdtbase file dev/fdt/fdt_clock.c fdt file dev/fdt/fdt_dai.c fdt file dev/fdt/fdt_dma.c fdt +file dev/fdt/fdt_ddb.c fdt & ddb file dev/fdt/fdt_gpio.c fdt file dev/fdt/fdt_i2c.c fdt file dev/fdt/fdt_intr.c fdt