@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Types.h>
|
#include <Types.h>
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
|
||||||
typedef struct FDTHeader {
|
typedef struct FDTHeader {
|
||||||
UInt32 magic; // 0xd00dfeed
|
UInt32 magic; // 0xd00dfeed
|
||||||
@@ -32,4 +33,4 @@ enum {
|
|||||||
kFDTHeaderMagic = 0xd00dfeed,
|
kFDTHeaderMagic = 0xd00dfeed,
|
||||||
};
|
};
|
||||||
|
|
||||||
void DTBParse(Pointer dtb);
|
void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Types.h>
|
||||||
|
|
||||||
|
void* memset(void* destination, int value, Size count);
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Types.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kVMPageSize = 4096,
|
||||||
|
kVMBlocksPerByte = 8,
|
||||||
|
kVMMaxReservedRegions = 128,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt64 base;
|
||||||
|
Size size;
|
||||||
|
} VMMemoryRegion;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VMMemoryRegion totalRAM;
|
||||||
|
VMMemoryRegion reserved[kVMMaxReservedRegions];
|
||||||
|
UInt32 reservedCount;
|
||||||
|
} VMBootMemoryMap;
|
||||||
|
|
||||||
|
void PMMInitialize(VMBootMemoryMap* bootMap);
|
||||||
|
Pointer PMMAllocatePage();
|
||||||
|
void PMMFreePage(Address address);
|
||||||
+45
-10
@@ -1,22 +1,33 @@
|
|||||||
|
#include "Types.h"
|
||||||
#include <Arch/DTB.h>
|
#include <Arch/DTB.h>
|
||||||
#include <OS/Panic.h>
|
#include <OS/Panic.h>
|
||||||
#include <OS/Log.h>
|
#include <OS/Log.h>
|
||||||
#include <Lib/Bytes.h>
|
#include <Lib/Bytes.h>
|
||||||
#include <Lib/Align.h>
|
#include <Lib/Align.h>
|
||||||
#include <Lib/String.h>
|
#include <Lib/String.h>
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
|
||||||
void DTBParse(Pointer dtb) {
|
void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
|
||||||
FDTHeader* header = (FDTHeader*)dtb;
|
FDTHeader* header = (FDTHeader*)dtb;
|
||||||
if (BytesSwap32(header->magic) != kFDTHeaderMagic) {
|
if (BytesSwap32(header->magic) != kFDTHeaderMagic) {
|
||||||
OSPanic("Invalid DTB magic");
|
OSPanic("Invalid DTB magic");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32 index = bootMap->reservedCount;
|
||||||
|
bootMap->reserved[index].base = (Address)dtb;
|
||||||
|
bootMap->reserved[index].size = BytesSwap32(header->totalSize);
|
||||||
|
bootMap->reservedCount++;
|
||||||
|
|
||||||
UInt32 offStruct = BytesSwap32(header->offDtStruct);
|
UInt32 offStruct = BytesSwap32(header->offDtStruct);
|
||||||
UInt32 offStrings = BytesSwap32(header->offDtStrings);
|
UInt32 offStrings = BytesSwap32(header->offDtStrings);
|
||||||
|
|
||||||
BytePointer structs = (BytePointer)dtb + offStruct;
|
BytePointer structs = (BytePointer)dtb + offStruct;
|
||||||
ASCII* strings = (ASCII*)dtb + offStrings;
|
ASCII* strings = (ASCII*)dtb + offStrings;
|
||||||
|
|
||||||
ASCII* currentNode = "";
|
ASCII* currentNode = "";
|
||||||
|
UInt32 currentDepth = 0;
|
||||||
|
UInt32 reservedMemoryDepth = 0;
|
||||||
|
bool inReservedMemory = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
UInt32 token = BytesSwap32(*(UInt32*)structs);
|
UInt32 token = BytesSwap32(*(UInt32*)structs);
|
||||||
@@ -24,35 +35,59 @@ void DTBParse(Pointer dtb) {
|
|||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case FDTTokenBeginNode: {
|
case FDTTokenBeginNode: {
|
||||||
|
currentDepth++;
|
||||||
currentNode = (ASCII*)structs;
|
currentNode = (ASCII*)structs;
|
||||||
|
|
||||||
|
if (StringStartsWith(currentNode, "reserved-memory")) {
|
||||||
|
inReservedMemory = true;
|
||||||
|
reservedMemoryDepth = currentDepth;
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 nameLength = StringGetLength(currentNode);
|
UInt32 nameLength = StringGetLength(currentNode);
|
||||||
structs += (nameLength + 1);
|
structs += (nameLength + 1);
|
||||||
structs = (BytePointer)AlignUp64((Address)structs, 4);
|
structs = (BytePointer)AlignUp64((Address)structs, 4);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FDTTokenProperty: {
|
case FDTTokenProperty: {
|
||||||
UInt32 propertyLength = BytesSwap32(*(UInt32*)structs);
|
UInt32 propertyLength = BytesSwap32(*(UInt32*)structs);
|
||||||
UInt32 nameOffset = BytesSwap32(*(UInt32*)(structs + 4));
|
UInt32 nameOffset = BytesSwap32(*(UInt32*)(structs + 4));
|
||||||
structs += 8;
|
structs += 8;
|
||||||
|
|
||||||
ASCII* propertyName = strings + nameOffset;
|
ASCII* propertyName = strings + nameOffset;
|
||||||
if (StringCompare(propertyName, "reg") == 0 && StringStartsWith(currentNode, "memory")) {
|
|
||||||
|
if (StringCompare(propertyName, "reg") == 0) {
|
||||||
|
if (StringStartsWith(currentNode, "memory")) {
|
||||||
UInt32* cells = (UInt32*)structs;
|
UInt32* cells = (UInt32*)structs;
|
||||||
|
Address base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
|
||||||
|
Size size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
|
||||||
|
|
||||||
UInt64 base = Merge32To64(BytesSwap32(cells[0]), BytesSwap32(cells[1]));
|
bootMap->totalRAM.base = base;
|
||||||
UInt64 size = Merge32To64(BytesSwap32(cells[2]), BytesSwap32(cells[3]));
|
bootMap->totalRAM.size = size;
|
||||||
|
|
||||||
OSLog("Memory: base=0x%x, size=0x%x\n", base, size);
|
|
||||||
}
|
}
|
||||||
|
else if (inReservedMemory && currentDepth > reservedMemoryDepth) {
|
||||||
|
UInt32* cells = (UInt32*)structs;
|
||||||
|
Address base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
|
||||||
|
Size size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
|
||||||
|
|
||||||
|
UInt32 index = bootMap->reservedCount;
|
||||||
|
bootMap->reserved[index].base = base;
|
||||||
|
bootMap->reserved[index].size = size;
|
||||||
|
bootMap->reservedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
structs += propertyLength;
|
structs += propertyLength;
|
||||||
structs = (BytePointer)AlignUp64((Address)structs, 4);
|
structs = (BytePointer)AlignUp64((Address)structs, 4);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FDTTokenEndNode: break;
|
case FDTTokenEndNode: {
|
||||||
|
if (inReservedMemory && currentDepth == reservedMemoryDepth) {
|
||||||
|
inReservedMemory = false;
|
||||||
|
}
|
||||||
|
currentDepth--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case FDTTokenNOP: continue;
|
case FDTTokenNOP: continue;
|
||||||
case FDTTokenEnd: return;
|
case FDTTokenEnd: return;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "../Common/bootinfo.h"
|
#include "../Common/bootinfo.h"
|
||||||
|
#include <VM/PMM.h>
|
||||||
#include <Arch/DTB.h>
|
#include <Arch/DTB.h>
|
||||||
#include <OS/Log.h>
|
#include <OS/Log.h>
|
||||||
#include <OS/Panic.h>
|
#include <OS/Panic.h>
|
||||||
@@ -9,5 +10,8 @@ void KernelMain(Bootinfo* bootinfo) {
|
|||||||
OSPanic("Invalid bootinfo magic");
|
OSPanic("Invalid bootinfo magic");
|
||||||
}
|
}
|
||||||
|
|
||||||
DTBParse(bootinfo->dtb);
|
VMBootMemoryMap bootMap = {0};
|
||||||
|
bootMap.reservedCount = 0;
|
||||||
|
DTBParse(bootinfo->dtb, &bootMap);
|
||||||
|
PMMInitialize(&bootMap);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include <Lib/Stubs.h>
|
||||||
|
#include <Lib/String.h>
|
||||||
|
|
||||||
|
void* memset(void* destination, int value, Size count) {
|
||||||
|
return StringSet(destination, value, count);
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#include <VM/PMM.h>
|
||||||
|
#include <Lib/String.h>
|
||||||
|
|
||||||
|
extern char _kernelStart[];
|
||||||
|
extern char _kernelEnd[];
|
||||||
|
|
||||||
|
static inline Size BitmapGetByteIndex(Address address) {
|
||||||
|
return (address / kVMPageSize) / kVMBlocksPerByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UInt8 BitmapGetBitOffset(Address address) {
|
||||||
|
return (UInt8)((address / kVMPageSize) % kVMBlocksPerByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Boolean BitmapTest(const MemoryPointer bitmap, Address address) {
|
||||||
|
return (bitmap[BitmapGetByteIndex(address)] & (1U << BitmapGetBitOffset(address))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void BitmapSet(MemoryPointer bitmap, Address address) {
|
||||||
|
bitmap[BitmapGetByteIndex(address)] |= (1U << BitmapGetBitOffset(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void BitmapUnset(MemoryPointer bitmap, Address address) {
|
||||||
|
bitmap[BitmapGetByteIndex(address)] &= ~(1U << BitmapGetBitOffset(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryPointer sPMMBitmap;
|
||||||
|
static Size sPMMBitmapSize;
|
||||||
|
static Size sPMMTotalPages;
|
||||||
|
|
||||||
|
void PMMInitialize(VMBootMemoryMap* bootMap) {
|
||||||
|
UInt32 vIndex = bootMap->reservedCount;
|
||||||
|
bootMap->reserved[vIndex].base = 0x0;
|
||||||
|
bootMap->reserved[vIndex].size = bootMap->totalRAM.base;
|
||||||
|
bootMap->reservedCount++;
|
||||||
|
|
||||||
|
UInt32 kIndex = bootMap->reservedCount;
|
||||||
|
bootMap->reserved[kIndex].base = (Address)_kernelStart;
|
||||||
|
bootMap->reserved[kIndex].size = (Address)_kernelEnd - (Address)_kernelStart;
|
||||||
|
bootMap->reservedCount++;
|
||||||
|
|
||||||
|
sPMMTotalPages = bootMap->totalRAM.size / kVMPageSize;
|
||||||
|
sPMMBitmapSize = sPMMTotalPages / kVMBlocksPerByte;
|
||||||
|
sPMMBitmap = (MemoryPointer)_kernelEnd;
|
||||||
|
|
||||||
|
StringSet(sPMMBitmap, 0, sPMMBitmapSize);
|
||||||
|
|
||||||
|
UInt32 bIndex = bootMap->reservedCount;
|
||||||
|
bootMap->reserved[bIndex].base = (Address)sPMMBitmap;
|
||||||
|
bootMap->reserved[bIndex].size = sPMMBitmapSize;
|
||||||
|
bootMap->reservedCount++;
|
||||||
|
|
||||||
|
for (Size i = 0; i < bootMap->reservedCount; i++) {
|
||||||
|
Address regionBase = bootMap->reserved[i].base;
|
||||||
|
Size regionSize = bootMap->reserved[i].size;
|
||||||
|
|
||||||
|
Size pagesToReserve = (regionSize + kVMPageSize - 1) / kVMPageSize;
|
||||||
|
|
||||||
|
for (Size p = 0; p < pagesToReserve; p++) {
|
||||||
|
Address pageAdress = regionBase + (p * kVMPageSize);
|
||||||
|
BitmapSet(sPMMBitmap, pageAdress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pointer PMMAllocatePage() {
|
||||||
|
for (Size i = 0; i < sPMMBitmapSize; i++) {
|
||||||
|
if (sPMMBitmap[i] == 0xFF) continue;
|
||||||
|
for (Size bit = 0; bit < kVMBlocksPerByte; bit++) {
|
||||||
|
if ((sPMMBitmap[i] & (1 << bit)) == 0) {
|
||||||
|
Address address = (i * kVMBlocksPerByte + bit) * kVMPageSize;
|
||||||
|
BitmapSet(sPMMBitmap, address);
|
||||||
|
return (Pointer)address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMMFreePage(Address address) {
|
||||||
|
BitmapUnset(sPMMBitmap, address);
|
||||||
|
}
|
||||||
@@ -7,14 +7,22 @@ PHDRS
|
|||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x40100000;
|
. = 0x40100000;
|
||||||
|
_kernelStart = .;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
*(.text.boot)
|
*(.text.boot)
|
||||||
*(.text*)
|
*(.text*)
|
||||||
} :text
|
} :text
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
.rodata : { *(.rodata*) } :text
|
.rodata : { *(.rodata*) } :text
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
.data : { *(.data*) } :data
|
.data : { *(.data*) } :data
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
.bss : { *(.bss*) *(COMMON) } :data
|
.bss : { *(.bss*) *(COMMON) } :data
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
_kernelEnd = .;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user