metal-cos/sys/arm64/mbentry.c

133 lines
2.7 KiB
C

/*
* Multiboot C Entry
*/
#include <stdbool.h>
#include <stdint.h>
#include <sys/kassert.h>
#include <sys/cdefs.h>
#include "../dev/console.h"
#include <machine/mrt.h>
#include <machine/pmap.h>
#include <machine/paging.h>
#include <machine/bootinfo.h>
#include <sys/contrib/libfdt/libfdt.h>
#define PAGE_ALIGN __attribute__((aligned(PGSIZE)))
#define DATA_SECTION __attribute__((section(".data")))
extern void Machine_EarlyInit();
extern void Machine_Init();
extern void PAlloc_AddRegion(uintptr_t start, uintptr_t len);
struct bootinfo kbootinfo;
//
// parse the total memory
//
static bool
machineboot_parse_dtb()
{
const void * dtb = kbootinfo.dtb_addr;
if (fdt_num_mem_rsv(kbootinfo.dtb_addr) > 0) {
/* XXX: don't support memory reservation for now */
return false;
}
int offset = -1;
kbootinfo.mem_region_sz = 0;
while(true) {
offset = fdt_node_offset_by_prop_value(dtb, offset, "device_type",
"memory", strlen("memory") + 1);
if (offset < 0) {
break;
}
if (kbootinfo.mem_region_sz >= MAX_BOOT_MEM_REGIONS) {
// max region reached
return false;
}
int lenp;
const struct fdt_property * prop = fdt_get_property(dtb, offset, "reg", &lenp);
if (prop == NULL || lenp != 4 * sizeof(uint32_t)) {
// invalid memory block spec
return false;
}
const uint32_t * ptr = (const uint32_t *)prop->data;
const uint64_t base = fdt32_to_cpu(ptr[1]) | ((uint64_t)fdt32_to_cpu(ptr[0]) << 32);
const uint64_t limit = fdt32_to_cpu(ptr[3]) | ((uint64_t)fdt32_to_cpu(ptr[2]) << 32);
kbootinfo.mem_region_base[kbootinfo.mem_region_sz] = base;
kbootinfo.mem_region_len[kbootinfo.mem_region_sz] = limit;
kbootinfo.mem_region_sz++;
}
return kbootinfo.mem_region_sz > 0;
}
void
MachineBoot_Entry(unsigned long magic, paddr_t dtb_paddr, unsigned long dtb_len)
{
if (magic != 0x10CA5201) {
Halt();
}
// initialize metal mode
mtl_init();
// early metal paging init
vm_early_paging_init();
// parse dtb files
if (fdt_check_full((const void *)DMPA2VA(dtb_paddr), dtb_len) != 0) {
Halt();
}
kbootinfo.dtb_addr = (const void *)DMPA2VA(dtb_paddr);
kbootinfo.dtb_len = dtb_len;
if (!machineboot_parse_dtb()){
Halt();
}
// Main initialization
Machine_Init();
return;
}
void
MachineBoot_AddMem()
{
unsigned int i;
uintptr_t initRamEnd = 32*1024*1024;
for (i = 0; i < kbootinfo.mem_region_sz; i++)
{
uintptr_t start = kbootinfo.mem_region_base[i];
uintptr_t len = kbootinfo.mem_region_len[i];
if (start + len < initRamEnd)
continue;
if (start < initRamEnd) {
len = initRamEnd - start;
start = initRamEnd;
}
kprintf("Initializing physical memory region: base = 0x%lx, len = 0x%lx ... ", start, len);
PAlloc_AddRegion(start + MEM_DIRECTMAP_BASE, len);
kprintf("Done!\n");
}
}