os-workshop

same materials and sample source for RV32 OS projects
git clone http://frotz.net/git/os-workshop.git
Log | Files | Refs

devicetree.c (2409B)


      1 // Copyright 2022, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0
      3 
      4 #include <hw/debug.h>
      5 #include <hw/riscv.h>
      6 #include <hw/devicetree.h>
      7 
      8 #include <string.h>
      9 
     10 static inline uint32_t swap(uint32_t n) {
     11 	return (n >> 24) | (n << 24) |
     12 		((n >> 8) & 0x0000FF00) |
     13 		((n << 8) & 0x00FF0000);
     14 }
     15 
     16 int isstring(const char* s) {
     17 	switch (s[0]) {
     18 	case 'b':
     19 		if (!strcmp(s, "bootargs")) return 1;
     20 	case 'c':
     21 		if (!strcmp(s, "compatible")) return 1;
     22 		break;
     23 	case 'd':
     24 		if (!strcmp(s, "device_type")) return 1;
     25 		break;
     26 	case 'm':
     27 		if (!strcmp(s, "model")) return 1;
     28 		if (!strcmp(s, "mmu-type")) return 1;
     29 		break;
     30 	case 'r':
     31 		if (!strcmp(s, "riscv.isa")) return 1;
     32 		break;
     33 	}
     34 	return 0;
     35 }
     36 
     37 void xindent(unsigned count) {
     38 	while (count-- > 0) {
     39 		xputs("  ");
     40 	}
     41 }
     42 
     43 void fdt_walk(fdt_header_t* fdt) {
     44 	uint32_t* data = (void*) (((uintptr_t) fdt) + swap(fdt->off_dt_struct));
     45 	char* strtab = (char*) (((uintptr_t) fdt) + swap(fdt->off_dt_strings));
     46 	unsigned indent = 0;
     47 	for (;;) {
     48 		switch(swap(*data++)) {
     49 		case FDT_PADDING:
     50 		case FDT_NOP:
     51 			continue;
     52 		case FDT_BEGIN_NODE: {
     53 			char *name = (void*) data;
     54 			uint32_t len = strlen(name) + 1;	
     55 			xindent(indent);
     56 			xprintf("NODE '%s'\n", name);
     57 			indent++;
     58 			data += ((len + 3) >> 2);
     59 			break;
     60 		}
     61 		case FDT_END_NODE:
     62 			indent--;
     63 			break;
     64 		case FDT_PROP: {
     65 			uint32_t len = swap(*data++);
     66 			uint32_t name = swap(*data++);
     67 			xindent(indent);
     68 			xprintf("PROP '%s' %u:", strtab + name, len);
     69 			if (isstring(strtab + name)) {
     70 				xprintf(" '%s'\n", (char*) data);
     71 			} else {
     72 				for (unsigned n = 0; n < len; n++) {
     73 					xprintf(" %02x", ((uint8_t*)data)[n]);
     74 				}
     75 				xprintf("\n");
     76 			}
     77 			data += ((len + 3) >> 2);
     78 			break;
     79 		}
     80 		default:
     81 			xprintf("HUH %08x\n", swap(data[-1]));
     82 			return;
     83 		case FDT_END:
     84 			xprintf("END\n");
     85 			return;
     86 		}
     87 	}
     88 }
     89 
     90 void start(unsigned _, fdt_header_t* fdt) {
     91 	xprintf("fdt         %p\n", fdt);
     92 	xprintf("fdt.magic   %08x\n", swap(fdt->magic));
     93 	xprintf("fdt.version %08x\n", swap(fdt->version));
     94 	xprintf("fdt.struct  %08x %08x\n",
     95 		swap(fdt->off_dt_struct), swap(fdt->size_dt_struct));
     96 	xprintf("fdt.strings %08x %08x\n",
     97 		swap(fdt->off_dt_strings), swap(fdt->size_dt_strings));
     98 
     99 	fdt_walk(fdt);
    100 
    101 	for (unsigned n = 0x10001000; n < 0x10009000; n+= 0x1000) {
    102 		unsigned *x = (void*) n;
    103 		xprintf("%08x: %08x %08x %08x %08x\n",
    104 			n, x[0], x[1], x[2], x[3]);
    105 	}
    106 }