imp: can properly find available and reserved memory in dtb

This commit is contained in:
Jordan ⌨️ 2025-04-20 17:26:21 +02:00
parent 03341a4512
commit f85e8aa35d
6 changed files with 113 additions and 21 deletions

View file

@ -1,5 +1,6 @@
#pragma once
#include <dtb>
#include <io>
void hal_setup(void);
@ -8,3 +9,5 @@ void hal_putc(int ch);
Writer hal_writer(void);
void hal_brkpoint(void);
DTBNode* hal_dtb_root(void);

View file

@ -6,29 +6,24 @@
#include <string.h>
#include "exception.h"
#include "mem.h"
extern char __bss[], __bss_end[];
extern void kmain(void);
static uint8_t early_heap[kib$(20)];
static DTBNode* dtb_root = NULL;
void rv32_start(__attribute__((unused)) size_t hartid, uintptr_t dtb) {
write_csr$(stvec, (uint32_t)interrupt_kernel);
BumpAllocator alloc = bump_allocator_create((void*)early_heap, sizeof(early_heap));
DTBNode* root = dtb_init(dtb, &alloc.base);
DTBNode* mem = dtb_lookup(root, "reserved-memory");
if (mem == NULL) {
error$("Failed to find reserved-memory node in device tree");
__asm__ volatile("ebreak");
}
DTBProp* prop = mem->props;
while (prop != NULL) {
debug$("prop: %s", prop->name);
prop = prop->next;
}
dtb_root = dtb_init(dtb, &alloc.base);
mem_init();
kmain();
}
DTBNode* hal_dtb_root(void) {
return dtb_root;
}

42
src/kernel/hal/rv32/mem.c Normal file
View file

@ -0,0 +1,42 @@
#include <hal>
#include <helpers/mem.h>
#include <logger>
#include "mem.h"
void mem_init(void) {
DTBNode* root = hal_dtb_root();
if (root == NULL) {
error$("No DTB found");
hal_brkpoint();
}
DTBNode* mem = dtb_lookup(root, "memory");
if (mem == NULL) {
error$("No memory node found in DTB");
hal_brkpoint();
}
RegValue reg_val = dtb_lookup_reg(mem);
if (reg_val.len == 0) {
warn$("Memory node size is larger than 4GB. Defaulting to 4GB");
reg_val.len = align_down$(gib$(4) - 1, 4096);
}
debug$("Memory node found at %x with size %x", reg_val.addr, reg_val.len);
DTBNode* reserved = dtb_lookup(root, "reserved-memory");
if (reserved == NULL) {
error$("No reserved memory node found in DTB");
hal_brkpoint();
}
DTBNode* child = reserved->children;
while (child != NULL) {
RegValue reg = dtb_lookup_reg(child);
debug$("Reserved memory node with name %s found at %x with size %x", child->name, reg.addr, reg.len);
child = child->next;
}
}

View file

@ -0,0 +1,3 @@
#pragma once
void mem_init(void);

View file

@ -1,7 +1,6 @@
#include <helpers/endian.h>
#include <helpers/mem.h>
#include <logger>
#include <stdlib.h>
#include <string.h>
#include "mod.h"
@ -15,7 +14,7 @@ static uint32_t read_offset(uint8_t** offset) {
static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
if (dtb_header == NULL) {
error$("Device tree blob not initialized");
abort();
return NULL;
}
DTBNode* current_node = NULL;
@ -36,13 +35,13 @@ static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
if (!root) {
if (*node_name) {
error$("Invalid device tree blob. Expected root node to be empty");
abort();
return NULL;
}
root = alloc->alloc(alloc, sizeof(DTBNode));
if (root == NULL) {
error$("Failed to allocate memory for device tree node");
abort();
return NULL;
}
memset(current_node, 0, sizeof(DTBNode));
@ -55,7 +54,7 @@ static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
DTBNode* new_node = alloc->alloc(alloc, sizeof(DTBNode));
if (new_node == NULL) {
error$("Failed to allocate memory for device tree node");
abort();
return NULL;
}
memset(new_node, 0, sizeof(DTBNode));
@ -94,7 +93,7 @@ static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
DTBProp* prop = alloc->alloc(alloc, sizeof(DTBProp));
if (prop == NULL) {
error$("Failed to allocate memory for device tree property");
abort();
return NULL;
}
char const* prop_name = strtab + nameoff;
@ -128,7 +127,7 @@ static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
default: {
error$("Unknown token %x", token);
abort();
return NULL;
}
}
}
@ -141,7 +140,7 @@ DTBNode* dtb_init(uintptr_t dtb, Allocator* alloc) {
if (from_be32(dtb_header->magic) != DTB_MAGIC) {
error$("Invalid device tree blob magic number. Excecting %x, got %x", DTB_MAGIC, from_be32(dtb_header->magic));
abort();
return NULL;
}
return dtb_parse(dtb_header, alloc);
@ -174,3 +173,46 @@ DTBProp* dtb_lookup_prop(DTBNode* node, char const* name) {
return NULL;
}
RegValue dtb_lookup_reg(DTBNode* node) {
RegValue reg = {0};
DTBProp* prop = dtb_lookup_prop(node, "reg");
if (prop == NULL) {
error$("Failed to find reg property in device tree node %s", node->name);
return reg;
}
uint8_t* offset = (uint8_t*)prop->value;
DTBProp* address_cells_prop = dtb_lookup_prop(node->parent, "#address-cells");
if (address_cells_prop == NULL) {
error$("Failed to find #address-cells property in device tree node %s", node->parent->name);
return reg;
}
DTBProp* size_cells_prop = dtb_lookup_prop(node->parent, "#size-cells");
if (size_cells_prop == NULL) {
error$("Failed to find #size-cells property in device tree node %s", node->parent->name);
return reg;
}
size_t address_cells = from_be32(*(uint32_t*)address_cells_prop->value);
size_t size_cells = from_be32(*(uint32_t*)size_cells_prop->value);
uint64_t tmp_addr = 0;
uint64_t tmp_len = 0;
for (size_t i = 0; i < address_cells; i++) {
tmp_addr = (tmp_addr << 32) | read_offset(&offset);
}
for (size_t i = 0; i < size_cells; i++) {
tmp_len = (tmp_len << 32) | read_offset(&offset);
}
reg.addr = tmp_addr;
reg.len = tmp_len;
return reg;
}

View file

@ -40,8 +40,15 @@ typedef struct _DTBNode {
struct _DTBNode* parent;
} DTBNode;
typedef struct {
uintptr_t addr;
size_t len;
} RegValue;
DTBNode* dtb_init(uintptr_t dtb, Allocator* alloc);
DTBNode* dtb_lookup(DTBNode* root, char const* name);
DTBProp* dtb_lookup_prop(DTBNode* node, char const* name);
RegValue dtb_lookup_reg(DTBNode* node);