os-workshop

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Ahw/inc/hw/devicetree.h | 30++++++++++++++++++++++++++++++
Amisc/devicetree.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aproject/devicetree.mk | 5+++++
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