Common: Started writing a DTB/FDT parser
This commit is contained in:
parent
4367e38f39
commit
ad1ac3f9d7
5 changed files with 174 additions and 0 deletions
117
kernel/common/dtb/dtb.cpp
Normal file
117
kernel/common/dtb/dtb.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
#include "dtb/dtb.h"
|
||||
|
||||
#include <opensbi/extensions/legacy.h>
|
||||
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<typename T>
|
||||
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<typename T>
|
||||
struct big_endian {
|
||||
T value() {
|
||||
return bswap(m_value);
|
||||
}
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] FdtHeader {
|
||||
big_endian<uint32_t> magic;
|
||||
big_endian<uint32_t> size;
|
||||
big_endian<uint32_t> struct_offset;
|
||||
big_endian<uint32_t> strings_offset;
|
||||
big_endian<uint32_t> reserved_map_offset;
|
||||
big_endian<uint32_t> version;
|
||||
big_endian<uint32_t> last_compatible_version;
|
||||
big_endian<uint32_t> boot_cpu_id;
|
||||
big_endian<uint32_t> strings_size;
|
||||
big_endian<uint32_t> struct_size;
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] FdtReserveEntry {
|
||||
big_endian<uint64_t> address;
|
||||
big_endian<uint64_t> size;
|
||||
};
|
||||
};
|
||||
|
||||
int validate_and_parse_header(DeviceTree &dt, void *base) {
|
||||
auto header = reinterpret_cast<FdtHeader *>(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<char *>(base) + header->reserved_map_offset.value();
|
||||
dt.structure_block =
|
||||
reinterpret_cast<char *>(base) + header->struct_offset.value();
|
||||
dt.strings_block =
|
||||
reinterpret_cast<char *>(base) + header->strings_offset.value();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_reserved_regions(DeviceTree dt) {
|
||||
auto regions = reinterpret_cast<FdtReserveEntry *>(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
|
34
kernel/common/dtb/include/dtb/dtb.h
Normal file
34
kernel/common/dtb/include/dtb/dtb.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace dtb {
|
||||
|
||||
struct DtbMeta {
|
||||
void *base;
|
||||
size_t size;
|
||||
uint32_t version;
|
||||
uint32_t last_compatible_version;
|
||||
uint32_t boot_cpu_id;
|
||||
};
|
||||
|
||||
struct ReservedRegion {
|
||||
uintptr_t address;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct DeviceTree {
|
||||
DtbMeta meta;
|
||||
void *memory_reservation_block;
|
||||
void *structure_block;
|
||||
void *strings_block;
|
||||
};
|
||||
|
||||
int validate_and_parse_header(DeviceTree &dt, void *base);
|
||||
|
||||
void print_reserved_regions(DeviceTree dt);
|
||||
|
||||
void print_structure_block(DeviceTree dt);
|
||||
|
||||
} // End namespace dtb
|
9
kernel/common/dtb/meson.build
Normal file
9
kernel/common/dtb/meson.build
Normal file
|
@ -0,0 +1,9 @@
|
|||
kernel_sources += [
|
||||
files(
|
||||
'dtb.cpp',
|
||||
),
|
||||
]
|
||||
|
||||
kernel_includes += include_directories(
|
||||
'include'
|
||||
)
|
|
@ -1,6 +1,8 @@
|
|||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <dtb/dtb.h>
|
||||
|
||||
#include <opensbi/opensbi.h>
|
||||
#include <opensbi/extensions/legacy.h>
|
||||
#include <opensbi/extensions/base.h>
|
||||
|
@ -275,6 +277,17 @@ isr_frame_t global_isr_frames[2];
|
|||
extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||
(void)hart;
|
||||
(void)dtb;
|
||||
// D1 doesnt give me dtb ptr?
|
||||
// dtb = (void *)0x5fb38580;
|
||||
|
||||
dtb::DeviceTree dt;
|
||||
int res = dtb::validate_and_parse_header(dt, dtb);
|
||||
if(!res) {
|
||||
fmt("validate_and_parse_header: {}\n", res);
|
||||
fmt("magic: {}\n", dt.meta.base);
|
||||
dtb::print_reserved_regions(dt);
|
||||
dtb::print_structure_block(dt);
|
||||
}
|
||||
|
||||
namespace legacy = drivers::opensbi::legacy;
|
||||
namespace base = drivers::opensbi::base;
|
||||
|
|
|
@ -9,6 +9,7 @@ kernel_includes = [
|
|||
]
|
||||
|
||||
subdir('drivers/opensbi')
|
||||
subdir('common/dtb')
|
||||
|
||||
includes = [
|
||||
# arch_includes,
|
||||
|
|
Loading…
Reference in a new issue