imp: can properly find available and reserved memory in dtb
This commit is contained in:
parent
03341a4512
commit
02cd9e7f51
7 changed files with 116 additions and 21 deletions
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <dtb>
|
||||||
#include <io>
|
#include <io>
|
||||||
|
|
||||||
void hal_setup(void);
|
void hal_setup(void);
|
||||||
|
@ -8,3 +9,5 @@ void hal_putc(int ch);
|
||||||
Writer hal_writer(void);
|
Writer hal_writer(void);
|
||||||
|
|
||||||
void hal_brkpoint(void);
|
void hal_brkpoint(void);
|
||||||
|
|
||||||
|
DTBNode* hal_dtb_root(void);
|
||||||
|
|
|
@ -6,29 +6,24 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
extern char __bss[], __bss_end[];
|
extern char __bss[], __bss_end[];
|
||||||
extern void kmain(void);
|
extern void kmain(void);
|
||||||
|
|
||||||
static uint8_t early_heap[kib$(20)];
|
static uint8_t early_heap[kib$(20)];
|
||||||
|
static DTBNode* dtb_root = NULL;
|
||||||
|
|
||||||
void rv32_start(__attribute__((unused)) size_t hartid, uintptr_t dtb) {
|
void rv32_start(__attribute__((unused)) size_t hartid, uintptr_t dtb) {
|
||||||
write_csr$(stvec, (uint32_t)interrupt_kernel);
|
write_csr$(stvec, (uint32_t)interrupt_kernel);
|
||||||
|
|
||||||
BumpAllocator alloc = bump_allocator_create((void*)early_heap, sizeof(early_heap));
|
BumpAllocator alloc = bump_allocator_create((void*)early_heap, sizeof(early_heap));
|
||||||
DTBNode* root = dtb_init(dtb, &alloc.base);
|
dtb_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mem_init();
|
||||||
kmain();
|
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;
|
||||||
|
}
|
||||||
|
}
|
5
src/kernel/hal/rv32/mem.h
Normal file
5
src/kernel/hal/rv32/mem.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define MEM_MAX (uint64_t)((1 << 32) - 1)
|
||||||
|
|
||||||
|
void mem_init(void);
|
|
@ -105,6 +105,7 @@ int vfmt(Writer writer, char const* fmt, va_list args) {
|
||||||
uintptr_t value = va_arg(args, uintptr_t);
|
uintptr_t value = va_arg(args, uintptr_t);
|
||||||
|
|
||||||
utoa(value, buf, 16);
|
utoa(value, buf, 16);
|
||||||
|
writer(2, "0x");
|
||||||
|
|
||||||
for (size_t i = 0; i < (sizeof(uintptr_t) * 2) - strlen(buf); i++) {
|
for (size_t i = 0; i < (sizeof(uintptr_t) * 2) - strlen(buf); i++) {
|
||||||
writer(1, "0");
|
writer(1, "0");
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include <helpers/endian.h>
|
#include <helpers/endian.h>
|
||||||
#include <helpers/mem.h>
|
#include <helpers/mem.h>
|
||||||
#include <logger>
|
#include <logger>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "mod.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) {
|
static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
|
||||||
if (dtb_header == NULL) {
|
if (dtb_header == NULL) {
|
||||||
error$("Device tree blob not initialized");
|
error$("Device tree blob not initialized");
|
||||||
abort();
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DTBNode* current_node = NULL;
|
DTBNode* current_node = NULL;
|
||||||
|
@ -36,13 +35,13 @@ static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
if (*node_name) {
|
if (*node_name) {
|
||||||
error$("Invalid device tree blob. Expected root node to be empty");
|
error$("Invalid device tree blob. Expected root node to be empty");
|
||||||
abort();
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
root = alloc->alloc(alloc, sizeof(DTBNode));
|
root = alloc->alloc(alloc, sizeof(DTBNode));
|
||||||
if (root == NULL) {
|
if (root == NULL) {
|
||||||
error$("Failed to allocate memory for device tree node");
|
error$("Failed to allocate memory for device tree node");
|
||||||
abort();
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(current_node, 0, sizeof(DTBNode));
|
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));
|
DTBNode* new_node = alloc->alloc(alloc, sizeof(DTBNode));
|
||||||
if (new_node == NULL) {
|
if (new_node == NULL) {
|
||||||
error$("Failed to allocate memory for device tree node");
|
error$("Failed to allocate memory for device tree node");
|
||||||
abort();
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(new_node, 0, sizeof(DTBNode));
|
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));
|
DTBProp* prop = alloc->alloc(alloc, sizeof(DTBProp));
|
||||||
if (prop == NULL) {
|
if (prop == NULL) {
|
||||||
error$("Failed to allocate memory for device tree property");
|
error$("Failed to allocate memory for device tree property");
|
||||||
abort();
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* prop_name = strtab + nameoff;
|
char const* prop_name = strtab + nameoff;
|
||||||
|
@ -128,7 +127,7 @@ static DTBNode* dtb_parse(FDTHeader* dtb_header, Allocator* alloc) {
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
error$("Unknown token %x", token);
|
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) {
|
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));
|
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);
|
return dtb_parse(dtb_header, alloc);
|
||||||
|
@ -174,3 +173,46 @@ DTBProp* dtb_lookup_prop(DTBNode* node, char const* name) {
|
||||||
|
|
||||||
return NULL;
|
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;
|
struct _DTBNode* parent;
|
||||||
} DTBNode;
|
} DTBNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uintptr_t addr;
|
||||||
|
size_t len;
|
||||||
|
} RegValue;
|
||||||
|
|
||||||
DTBNode* dtb_init(uintptr_t dtb, Allocator* alloc);
|
DTBNode* dtb_init(uintptr_t dtb, Allocator* alloc);
|
||||||
|
|
||||||
DTBNode* dtb_lookup(DTBNode* root, char const* name);
|
DTBNode* dtb_lookup(DTBNode* root, char const* name);
|
||||||
|
|
||||||
DTBProp* dtb_lookup_prop(DTBNode* node, 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