imp: can properly find available and reserved memory in dtb
This commit is contained in:
parent
03341a4512
commit
f85e8aa35d
6 changed files with 113 additions and 21 deletions
|
@ -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);
|
||||
|
|
|
@ -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
42
src/kernel/hal/rv32/mem.c
Normal 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;
|
||||
}
|
||||
}
|
3
src/kernel/hal/rv32/mem.h
Normal file
3
src/kernel/hal/rv32/mem.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void mem_init(void);
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue