Working kernel written on C and userspace-ready #1
@@ -192,6 +192,7 @@ static efi_status_t populate_memory_map(Bootinfo* boot_info) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
status = gBS->GetMemoryMap(&map_size, map, &map_key, &descriptor_size, &descriptor_version);
|
status = gBS->GetMemoryMap(&map_size, map, &map_key, &descriptor_size, &descriptor_version);
|
||||||
if (EFI_ERROR(status)) {
|
if (EFI_ERROR(status)) {
|
||||||
|
gBS->FreePool(map);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +207,12 @@ static efi_status_t populate_memory_map(Bootinfo* boot_info) {
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gBS->FreePool(map);
|
||||||
map_size += 2 * descriptor_size;
|
map_size += 2 * descriptor_size;
|
||||||
|
status = gBS->AllocatePool(EfiLoaderData, map_size, (void**)&map);
|
||||||
|
if (EFI_ERROR(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
#include <Types.h>
|
#include <Types.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kUARTBaseAddress = 0x09000000, // TODO: make it dynamic by parsing DTB
|
kUARTBaseAddress = 0x09000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
Int32 IOSerialPutCharacter(ASCII character);
|
void SerialUpdate(UInt64 address);
|
||||||
Int32 IOSerialPutString(const ASCII* string);
|
Int32 SerialPutCharacter(ASCII character);
|
||||||
|
Int32 SerialPutString(const ASCII* string);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
typedef unsigned char UInt8;
|
typedef unsigned char UInt8;
|
||||||
typedef unsigned short UInt16;
|
typedef unsigned short UInt16;
|
||||||
typedef unsigned int UInt32;
|
typedef unsigned int UInt32;
|
||||||
typedef unsigned long long UInt64;
|
typedef unsigned long long UInt64;
|
||||||
typedef unsigned long long UInt;
|
typedef unsigned long long UInt;
|
||||||
|
|
||||||
typedef void* Pointer;
|
typedef void* Pointer;
|
||||||
@@ -31,4 +31,3 @@ typedef UInt64 Size;
|
|||||||
typedef char ASCII;
|
typedef char ASCII;
|
||||||
|
|
||||||
typedef _Bool Boolean;
|
typedef _Bool Boolean;
|
||||||
#define loop while (1)
|
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
enum {
|
enum {
|
||||||
kVMPageSize = 4096,
|
kVMPageSize = 4096,
|
||||||
kVMBlocksPerByte = 8,
|
kVMBlocksPerByte = 8,
|
||||||
kVMMaxReservedRegions = 128,
|
kVMMaxReservedRegions = 256,
|
||||||
|
kPMMReservedRegionCount = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -28,4 +29,4 @@ typedef struct {
|
|||||||
|
|
||||||
void PMMInitialize(VMBootMemoryMap* bootMap);
|
void PMMInitialize(VMBootMemoryMap* bootMap);
|
||||||
Pointer PMMAllocatePage();
|
Pointer PMMAllocatePage();
|
||||||
void PMMFreePage(Address address);
|
void PMMFreePage(Address address);
|
||||||
|
|||||||
@@ -24,10 +24,13 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
|
|||||||
|
|
||||||
ASCII* currentNode = "";
|
ASCII* currentNode = "";
|
||||||
UInt32 currentDepth = 0;
|
UInt32 currentDepth = 0;
|
||||||
UInt32 reservedMemoryDepth = 0;
|
UInt32 reservedMemoryDepth = 0;
|
||||||
Boolean inReservedMemory = false;
|
Boolean inReservedMemory = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (bootMap->reservedCount + kPMMReservedRegionCount >= kVMMaxReservedRegions) {
|
||||||
|
OSPanic("Too many reserved memory regions!"); // should never occur but jic
|
||||||
|
}
|
||||||
UInt32 token = BytesSwap32(*(UInt32*)structs);
|
UInt32 token = BytesSwap32(*(UInt32*)structs);
|
||||||
structs += 4;
|
structs += 4;
|
||||||
|
|
||||||
@@ -81,7 +84,7 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
|
|||||||
|
|
||||||
bootMap->GIC.GICD.base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
|
bootMap->GIC.GICD.base = Merge32To64(BytesSwap32(cells[1]), BytesSwap32(cells[0]));
|
||||||
bootMap->GIC.GICD.size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
|
bootMap->GIC.GICD.size = Merge32To64(BytesSwap32(cells[3]), BytesSwap32(cells[2]));
|
||||||
|
|
||||||
bootMap->GIC.GICC.base = Merge32To64(BytesSwap32(cells[5]), BytesSwap32(cells[4]));
|
bootMap->GIC.GICC.base = Merge32To64(BytesSwap32(cells[5]), BytesSwap32(cells[4]));
|
||||||
bootMap->GIC.GICC.size = Merge32To64(BytesSwap32(cells[7]), BytesSwap32(cells[6]));
|
bootMap->GIC.GICC.size = Merge32To64(BytesSwap32(cells[7]), BytesSwap32(cells[6]));
|
||||||
}
|
}
|
||||||
@@ -99,7 +102,7 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
|
|||||||
currentDepth--;
|
currentDepth--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FDTTokenNOP: continue;
|
case FDTTokenNOP: continue;
|
||||||
case FDTTokenEnd: return;
|
case FDTTokenEnd: return;
|
||||||
default:
|
default:
|
||||||
@@ -107,4 +110,4 @@ void DTBParse(Pointer dtb, VMBootMemoryMap* bootMap) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.macro ventry type
|
.macro ventry type
|
||||||
.align 7
|
.align 7
|
||||||
sub sp, sp, #288 // save 288 bytes of stack
|
sub sp, sp, #288 // save 288 bytes of stack
|
||||||
stp x0, x1, [sp, #0] // move stack
|
stp x0, x1, [sp, #0] // move stack
|
||||||
mov x1, #\type // move type to x1
|
mov x1, #\type // move type to x1
|
||||||
b ExceptionsTrapEntry
|
b ExceptionsTrapEntry
|
||||||
.endm
|
.endm
|
||||||
@@ -54,6 +54,7 @@ ExceptionsTrapEntry:
|
|||||||
|
|
||||||
stp x30, x21, [sp, #16 * 15]
|
stp x30, x21, [sp, #16 * 15]
|
||||||
stp x22, x23, [sp, #16 * 16]
|
stp x22, x23, [sp, #16 * 16]
|
||||||
|
stp x24, xzr, [sp, #16 * 17]
|
||||||
|
|
||||||
mov x0, sp
|
mov x0, sp
|
||||||
bl ExceptionsHandler
|
bl ExceptionsHandler
|
||||||
@@ -92,4 +93,4 @@ ExceptionsVectorsInit:
|
|||||||
adr x0, ExceptionsVectorsTable
|
adr x0, ExceptionsVectorsTable
|
||||||
msr vbar_el1, x0
|
msr vbar_el1, x0
|
||||||
isb
|
isb
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -2,22 +2,28 @@
|
|||||||
#include <Arch/IO.h>
|
#include <Arch/IO.h>
|
||||||
#include <Arch/CPU.h>
|
#include <Arch/CPU.h>
|
||||||
|
|
||||||
Int32 IOSerialPutCharacter(ASCII character) {
|
static UInt64 sUARTAddress = kUARTBaseAddress;
|
||||||
|
|
||||||
|
void SerialUpdate(UInt64 address) {
|
||||||
|
sUARTAddress = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int32 SerialPutCharacter(ASCII character) {
|
||||||
// TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18)
|
// TXFF -- TRansmit FIFO Full for PL011 is 5 bit of FR reg (0x18)
|
||||||
UInt64 uartFR = kUARTBaseAddress + 0x18;
|
UInt64 uartFR = sUARTAddress + 0x18;
|
||||||
|
|
||||||
while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) {
|
while ((IOAddressRead32(uartFR) & (1 << 5)) != 0) {
|
||||||
CPUYield();
|
CPUYield();
|
||||||
}
|
}
|
||||||
|
|
||||||
IOAddressWrite32(kUARTBaseAddress, character);
|
IOAddressWrite32(sUARTAddress, character);
|
||||||
return character;
|
return character;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int32 IOSerialPutString(const ASCII* string) {
|
Int32 SerialPutString(const ASCII* string) {
|
||||||
Int i = 0;
|
Int i = 0;
|
||||||
while (string[i] != '\0') {
|
while (string[i] != '\0') {
|
||||||
IOSerialPutCharacter(string[i]);
|
SerialPutCharacter(string[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <Arch/Timer.h>
|
#include <Arch/Timer.h>
|
||||||
#include <Arch/CPU.h>
|
#include <Arch/CPU.h>
|
||||||
#include <Arch/GIC.h>
|
#include <Arch/GIC.h>
|
||||||
|
#include <IO/Serial.h>
|
||||||
#include <VM/PMM.h>
|
#include <VM/PMM.h>
|
||||||
#include <VM/VMM.h>
|
#include <VM/VMM.h>
|
||||||
#include <VM/Heap.h>
|
#include <VM/Heap.h>
|
||||||
@@ -17,9 +18,10 @@ void KernelMain(Bootinfo* bootinfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VMBootMemoryMap bootMap = {0};
|
VMBootMemoryMap bootMap = {0};
|
||||||
|
|
||||||
bootMap.reservedCount = 0;
|
bootMap.reservedCount = 0;
|
||||||
DTBParse(bootinfo->dtb, &bootMap);
|
DTBParse(bootinfo->dtb, &bootMap);
|
||||||
|
SerialUpdate(bootMap.UART.base);
|
||||||
|
|
||||||
PMMInitialize(&bootMap);
|
PMMInitialize(&bootMap);
|
||||||
VMMInitialize(&bootMap, bootinfo);
|
VMMInitialize(&bootMap, bootinfo);
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
void OSLog(const ASCII* format, ...) {
|
void OSLog(const ASCII* format, ...) {
|
||||||
ASCII buffer[kOSLogBufferSize];
|
ASCII buffer[kOSLogBufferSize];
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
StringFormatVariadic(buffer, kOSLogBufferSize, format, args);
|
StringFormatVariadic(buffer, kOSLogBufferSize, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
IOSerialPutString(buffer);
|
SerialPutString(buffer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ static const ASCII* sFunMessages[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
__attribute__((noreturn)) static void Halt() {
|
__attribute__((noreturn)) static void Halt() {
|
||||||
loop {
|
while (true) {
|
||||||
CPUDisableInterrupts();
|
CPUDisableInterrupts();
|
||||||
CPUWaitForInterrupt();
|
CPUWaitForInterrupt();
|
||||||
}
|
}
|
||||||
@@ -134,4 +134,4 @@ __attribute__((noreturn)) void OSPanicException(ExceptionsContext* frame) {
|
|||||||
|
|
||||||
DrawPanicFooter();
|
DrawPanicFooter();
|
||||||
Halt();
|
Halt();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,11 +85,11 @@ Address SchedulerNext(Address stackPointer) {
|
|||||||
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
|
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
|
||||||
taskIterator = taskIterator->next;
|
taskIterator = taskIterator->next;
|
||||||
} while (taskIterator != gOSSchedulerCurrentTask->next);
|
} while (taskIterator != gOSSchedulerCurrentTask->next);
|
||||||
|
|
||||||
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
|
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
|
||||||
|
|
||||||
OSTask* nextTask = gOSSchedulerCurrentTask->next;
|
OSTask* nextTask = gOSSchedulerCurrentTask->next;
|
||||||
loop {
|
while (true) {
|
||||||
if (nextTask->state == OSTaskStateDead) {
|
if (nextTask->state == OSTaskStateDead) {
|
||||||
nextTask = nextTask->next;
|
nextTask = nextTask->next;
|
||||||
if (nextTask == gOSSchedulerCurrentTask) OSPanic("No running tasks");
|
if (nextTask == gOSSchedulerCurrentTask) OSPanic("No running tasks");
|
||||||
@@ -110,7 +110,7 @@ Address SchedulerNext(Address stackPointer) {
|
|||||||
CPUSwitchAddressSpace(physicalL0Table);
|
CPUSwitchAddressSpace(physicalL0Table);
|
||||||
}
|
}
|
||||||
gOSSchedulerCurrentTask = nextTask;
|
gOSSchedulerCurrentTask = nextTask;
|
||||||
|
|
||||||
return gOSSchedulerCurrentTask->stackPointer;
|
return gOSSchedulerCurrentTask->stackPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,4 +118,4 @@ void SchedulerYield(UInt64 ticks) {
|
|||||||
gOSSchedulerCurrentTask->sleepTicks = ticks;
|
gOSSchedulerCurrentTask->sleepTicks = ticks;
|
||||||
gOSSchedulerCurrentTask->state = OSTaskStateSleeping;
|
gOSSchedulerCurrentTask->state = OSTaskStateSleeping;
|
||||||
CPUException(kOSSchedulerExceptionNumber);
|
CPUException(kOSSchedulerExceptionNumber);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user