commit 08ac4203fbde7508c7080b47a4302f31c29a72cf
parent 695273ab769633cb35ba201eb6538884391e6a96
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 23 Apr 2022 18:51:38 -0700
project: devicetree
- header for flat devicetree stuff
- test program to dump the devicetree
Diffstat:
3 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/hw/inc/hw/devicetree.h b/hw/inc/hw/devicetree.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef struct {
+ uint32_t magic;
+ uint32_t totalsize;
+ uint32_t off_dt_struct; // byte offset from header to struct
+ uint32_t off_dt_strings; // byte offset from header to strings
+ uint32_t off_mem_rsvmap; // byte offset from header to rsvmap
+ uint32_t version;
+ uint32_t last_comp_version;
+ uint32_t boot_cpuid_phys;
+ uint32_t size_dt_strings; // byte len
+ uint32_t size_dt_struct; // byte len
+} fdt_header_t;
+
+#define FDT_MAGIC 0xd00dfeed
+
+#define FDT_PADDING 0x00000000
+#define FDT_BEGIN_NODE 0x00000001
+#define FDT_END_NODE 0x00000002
+#define FDT_PROP 0x00000003
+#define FDT_NOP 0x00000004
+#define FDT_END 0x00000009
+
+typedef struct {
+ uint32_t len; // value len in bytes
+ uint32_t nameoff; // name offset from string table start
+} fdt_prop;
diff --git a/misc/devicetree.c b/misc/devicetree.c
@@ -0,0 +1,80 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#include <hw/debug.h>
+#include <hw/riscv.h>
+#include <hw/devicetree.h>
+
+#include <string.h>
+
+static inline uint32_t swap(uint32_t n) {
+ return (n >> 24) | (n << 24) |
+ ((n >> 8) & 0x0000FF00) |
+ ((n << 8) & 0x00FF0000);
+}
+
+void xindent(unsigned count) {
+ while (count-- > 0) {
+ xputs(" ");
+ }
+}
+
+void fdt_walk(fdt_header_t* fdt) {
+ uint32_t* data = (void*) (((uintptr_t) fdt) + swap(fdt->off_dt_struct));
+ char* strtab = (char*) (((uintptr_t) fdt) + swap(fdt->off_dt_strings));
+ unsigned indent = 0;
+ for (;;) {
+ switch(swap(*data++)) {
+ case FDT_PADDING:
+ xindent(indent);
+ xprintf("PADDING\n");
+ continue;
+ case FDT_NOP:
+ continue;
+ case FDT_BEGIN_NODE: {
+ char *name = (void*) data;
+ uint32_t len = strlen(name) + 1;
+ xindent(indent);
+ xprintf("NODE '%s'\n", name);
+ indent++;
+ data += ((len + 3) >> 2);
+ break;
+ }
+ case FDT_END_NODE:
+ indent--;
+ break;
+ case FDT_PROP: {
+ uint32_t len = swap(*data++);
+ uint32_t name = swap(*data++);
+ xindent(indent);
+ xprintf("PROP '%s' %u '%s'\n", strtab + name, len, (char*) (void*) data);
+ data += ((len + 3) >> 2);
+ break;
+ }
+ default:
+ xprintf("HUH %08x\n", swap(data[-1]));
+ return;
+ case FDT_END:
+ xprintf("END\n");
+ return;
+ }
+ }
+}
+
+void start(unsigned _, fdt_header_t* fdt) {
+ xprintf("fdt %p\n", fdt);
+ xprintf("fdt.magic %08x\n", swap(fdt->magic));
+ xprintf("fdt.version %08x\n", swap(fdt->version));
+ xprintf("fdt.struct %08x %08x\n",
+ swap(fdt->off_dt_struct), swap(fdt->size_dt_struct));
+ xprintf("fdt.strings %08x %08x\n",
+ swap(fdt->off_dt_strings), swap(fdt->size_dt_strings));
+
+ fdt_walk(fdt);
+
+ for (unsigned n = 0x10001000; n < 0x10009000; n+= 0x1000) {
+ unsigned *x = (void*) n;
+ xprintf("%08x: %08x %08x %08x %08x\n",
+ n, x[0], x[1], x[2], x[3]);
+ }
+}
diff --git a/project/devicetree.mk b/project/devicetree.mk
@@ -0,0 +1,5 @@
+
+APP := devicetree
+SRC := hw/src/start.S misc/devicetree.c
+SRC += hw/src/debug.c $(LIBC_SRC)
+include make/app.mk