#include "dtb/dtb.h" #include using drivers::opensbi::legacy::console_putchar; extern void fmt(const char *f, ...); namespace dtb { // TEMP void puts(const char *s) { while(*s) console_putchar(*s++); } namespace { template inline T bswap(T value) { if constexpr(sizeof(T) == 1) return value; else if constexpr (sizeof(T) == 2) return __builtin_bswap16(value); else if constexpr (sizeof(T) == 4) return __builtin_bswap32(value); else if constexpr (sizeof(T) == 8) return __builtin_bswap64(value); else __builtin_trap(); } template struct big_endian { T value() { return bswap(m_value); } private: T m_value; }; struct [[gnu::packed]] FdtHeader { big_endian magic; big_endian size; big_endian struct_offset; big_endian strings_offset; big_endian reserved_map_offset; big_endian version; big_endian last_compatible_version; big_endian boot_cpu_id; big_endian strings_size; big_endian struct_size; }; struct [[gnu::packed]] FdtReserveEntry { big_endian address; big_endian size; }; }; int validate_and_parse_header(DeviceTree &dt, void *base) { auto header = reinterpret_cast(base); // Make sure the base address is acutally valid if(header->magic.value() != 0xD00DFEED) { fmt("magic @ {}\n", header); fmt("magic is {}\n", header->magic.value()); puts("Bad magic\n"); return -1; } // TODO: I would rather copy all data to pointers we own so I // can be sure we have control over it and can remove this pointer dt.meta.base = base; // Copy metadata and fix it's endianness dt.meta.size = header->size.value(); dt.meta.version = header->version.value(); dt.meta.last_compatible_version = header->last_compatible_version.value(); dt.meta.boot_cpu_id = header->boot_cpu_id.value(); // Calculate other block pointers dt.memory_reservation_block = reinterpret_cast(base) + header->reserved_map_offset.value(); dt.structure_block = reinterpret_cast(base) + header->struct_offset.value(); dt.strings_block = reinterpret_cast(base) + header->strings_offset.value(); return 0; } void print_reserved_regions(DeviceTree dt) { auto regions = reinterpret_cast(dt.memory_reservation_block); int i = 0; fmt("Print mem regions\n"); while(true) { fmt("----- {}\n", i); auto region = regions[i++]; if(region.address.value() == 0 && region.size.value() == 0) break; fmt("address {}\n", region.address.value()); fmt("size {}\n", region.size.value()); } } void print_structure_block(DeviceTree dt) { fmt("is start? {}\n", *(uint32_t *)dt.structure_block); puts("asdasd\n"); puts(((char *)dt.structure_block+4)); puts("asdasd\n"); fmt("is start? {}\n", *(uint32_t *)((char *)dt.structure_block+8)); fmt("is len? {}\n", *(uint32_t *)((char *)dt.structure_block+8+4)); fmt("is off? {}\n", *(uint32_t *)((char *)dt.structure_block+8+8)); puts(((char *)((char *)dt.strings_block+0x1d))); puts("\n"); } } // End namespace dtb