Attempts at fixing paging.

Have somehow fixed the drawing routines along the way.

I also tried to implement a better keyboard handler, but that's quite a ways away right now.
This commit is contained in:
Curle 2020-04-11 22:59:39 +01:00
parent 822cfc4b9e
commit d522d40ac8
11 changed files with 577 additions and 61 deletions

View File

@ -1,3 +1,4 @@
#pragma once
/************************ /************************
*** Team Kitty, 2020 *** *** Team Kitty, 2020 ***
*** Sync *** *** Sync ***
@ -12,9 +13,29 @@
#include <kernel/system/io.h> #include <kernel/system/io.h>
#include <kernel/system/memory.h> #include <kernel/system/memory.h>
extern size_t LoadAddr;
extern bootinfo bootldr; extern bootinfo bootldr;
extern unsigned char* environment; extern unsigned char* environment;
extern uint8_t fb; extern uint8_t fb;
extern volatile unsigned char _binary_font_psf_start;
typedef struct {
uint32_t magic;
uint32_t version;
uint32_t headerSize;
uint32_t flags;
uint32_t numGlyphs;
uint32_t glyphSize;
uint32_t glyphHeight;
uint32_t glyphWidth;
uint8_t glyphs;
} __attribute__((packed)) psf_t;
size_t KernelAddr;
size_t KernelEnd;
size_t MemoryPages;
size_t MemorySize;
void DrawPixel(uint32_t x, uint32_t y, uint32_t color); void DrawPixel(uint32_t x, uint32_t y, uint32_t color);
@ -23,6 +44,8 @@ void FillScreen(uint32_t color);
void WriteString(const char* string); void WriteString(const char* string);
void WriteChar(const char character); void WriteChar(const char character);
void WriteStringWithFont(const char* string);
void InitInterrupts(); void InitInterrupts();
void InitSerial(); void InitSerial();
void InitPrint(); void InitPrint();

View File

@ -1,5 +1,43 @@
#pragma once
#include <stddef.h> #include <stddef.h>
static const char* ExceptionStrings[] = {
"Division by Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
size_t ss; size_t ss;
size_t rsp; size_t rsp;

View File

@ -1,5 +1,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <kernel/system/interrupts.h>
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#define PAGES_PER_BUCKET 8 #define PAGES_PER_BUCKET 8
@ -10,16 +11,37 @@
#define READ_BIT(i) ((OFFSET_BIT(i) >> (i % PAGES_PER_BUCKET)) & 0x1) #define READ_BIT(i) ((OFFSET_BIT(i) >> (i % PAGES_PER_BUCKET)) & 0x1)
#define GET_BUCKET32(i) (*((uint32_t*) (&Memory[i / 32]))) #define GET_BUCKET32(i) (*((uint32_t*) (&Memory[i / 32])))
#define PAGE_ALIGN(addr) (((addr) & 0xFFFFF000) + 0x1000) #define IS_ALIGNED(addr) (((size_t) addr | 0xFFFFFFFFFFFFF000) == 0)
#define PAGE_ALIGN(addr) ((((size_t) addr) & 0xFFFFFFFFFFFFF000) + 0x1000)
#define SET_PGBIT(cr0) (cr0 = cr0 | 1 << 31)
#define UNSET_PGBIT(cr0) (cr0 = cr0 ^ 1 << 31)
#define UNSET_PSEBIT(cr4) (cr4 = cr4 & 0xFFFFFFEF)
#define TOGGLE_PGEBIT(cr4) (cr4 = cr4 ^ (1 << 7))
#define SET_PAEBIT(cr4) (cr4 = cr4 | 1 << 5)
#define ERR_PRESENT 0x1
#define ERR_RW 0x2
#define ERR_USER 0x4
#define ERR_RESERVED 0x8
#define ERR_INST 0x10
extern size_t end; extern size_t end;
void ListMemoryMap();
void InitMemoryManager(); void InitMemoryManager();
size_t AllocatePage(); size_t AllocateFrame();
void FreePage(size_t PageNumber); void FreeFrame(size_t FrameNumber);
size_t FirstFreePage(); size_t SeekFrame();
void MemoryTest(); void MemoryTest();
void InitPaging();
void PageFaultHandler(INTERRUPT_FRAME frame);

View File

@ -1,11 +1,21 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
size_t KernelAddr = (size_t) &LoadAddr;
size_t KernelEnd = (size_t) &end;
void _start(void) { void _start(void) {
SerialPrintf("\r\nBooting Chroma..\r\n"); SerialPrintf("\r\nBooting Chroma..\r\n");
SerialPrintf("Kernel loaded at 0x%p, ends at 0x%p, is %d bytes long.\r\n", KernelAddr, KernelEnd, KernelEnd - KernelAddr);
ListMemoryMap();
InitPrint(); InitPrint();
WriteStringWithFont("Initty Testing");
SetupInitialGDT(); SetupInitialGDT();
SetupIDT(); SetupIDT();
InitInterrupts(); InitInterrupts();
@ -15,6 +25,7 @@ void _start(void) {
InitPaging(); InitPaging();
for(;;) { } for(;;) { }
} }

View File

@ -79,7 +79,7 @@ void UpdateKeyboard(uint8_t msg) {
if(msg & 0x80) { if(msg & 0x80) {
} else { } else {
SerialPrintf("Key pressed %c\r\n", keys[msg]); SerialPrintf("Key pressed: [\%c]\r\n", keys[msg]);
WriteChar(keys[msg]); WriteChar(keys[msg]);
} }

View File

@ -49,8 +49,7 @@ void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) {
FillScreen(0x0000FF00); FillScreen(0x0000FF00);
/* ExceptionStrings is an array of c-strings defined in kernel.h */ /* ExceptionStrings is an array of c-strings defined in kernel.h */
//serialPrint(ExceptionStrings[Exception]); SerialPrintf("%s exception!\r\n", ExceptionStrings[Exception]);
//serialPrint(" Exception.\r\n");
//printf("%s exception!", ExceptionStrings[Exception]); //printf("%s exception!", ExceptionStrings[Exception]);
//panic(); //panic();
} }
@ -61,10 +60,10 @@ void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) {
void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception) { void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception) {
if(Exception < 32) { if(Exception < 32) {
FillScreen(0x00FF0000); FillScreen(0x0000FF00);
SerialPrintf("ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode); SerialPrintf("ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode);
SerialPrintf("%s exception!\r\n", ExceptionStrings[Exception]);
while(true) {} while(true) {}
//serialPrint(ExceptionStrings[Exception]); //serialPrint(ExceptionStrings[Exception]);
//serialPrintf(" Exception. Context given: %d\r\n", Frame->ErrorCode); //serialPrintf(" Exception. Context given: %d\r\n", Frame->ErrorCode);
@ -268,7 +267,26 @@ __attribute__((interrupt)) void ISR13Handler(INTERRUPT_FRAME* Frame, size_t Erro
ISR_Error_Common(Frame, ErrorCode, 13); // General Protection ISR_Error_Common(Frame, ErrorCode, 13); // General Protection
} }
__attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { __attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 14); __asm__ __volatile__("sti");
SerialPrintf("Page fault! Caused by: [\r\n");
size_t FaultAddr = ReadControlRegister(2);
uint8_t FaultPres = ErrorCode & 0x1;
uint8_t FaultRW = ErrorCode & 0x2;
uint8_t FaultUser = ErrorCode & 0x4;
uint8_t FaultReserved = ErrorCode & 0x8;
uint8_t FaultInst = ErrorCode & 0x10;
if(!FaultPres) SerialPrintf("Accessed a page that isn't present.\r\n");
if(FaultRW || FaultUser) SerialPrintf("Accessed a Read-Only page.\r\n");
if(FaultReserved) SerialPrintf("Overwrote reserved bits.\r\n");
if(FaultInst) SerialPrintf("\"Instruction Fetch\"");
SerialPrintf("];");
ISR_Error_Common(Frame, ErrorCode, 14); // Page Fault
} }
__attribute__((interrupt)) void ISR15Handler(INTERRUPT_FRAME* Frame) { __attribute__((interrupt)) void ISR15Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 15); ISR_Common(Frame, 15);

View File

@ -0,0 +1,322 @@
#include <kernel/chroma.h>
__attribute__((aligned(4096))) static size_t Pagetable[512] = {0};
#define LAST_ENTRY 0xFF8
#define SET_ADDRESS(a,b) ((*(size_t*) (a)) = (size_t) b)
#define KiB 1 * 1024
#define MiB 1 * 1024 * KiB
#define USERWRITEABLE_FLAGS(a) ((a & 0xFFFFFF00) + 0x83)
#define PAGE_PRESENT 1
#define PAGE_RW 2
void InitPaging() {
size_t* PML4 = (size_t*) 0xFFA000; // Layer 4
size_t* PDPE_RAM = (size_t*) 0xFFE000; // Layer 3, contains map for the first 4GB of RAM
size_t* PDE_RAM = (size_t*) 0xFFF000;
size_t* PDPE_KERNEL = (size_t*) 0xFFB000; // Layer 3, contains map for the Kernel and everything it needs to run.
size_t* PDE_KERNEL_FB = (size_t*) 0xFFC000; // Layer 2, contains map for the linear framebuffer.
size_t* PT_KERNEL = (size_t*) 0xFFD000; // Layer 1, the page table for the kernel itself.
size_t fb_ptr = (size_t) &fb;
SET_ADDRESS(PML4, PDPE_RAM); // 3rd Layer entry for RAM
SET_ADDRESS(PML4 + LAST_ENTRY, PDPE_KERNEL); // 3rd Layer entry for Kernel
SET_ADDRESS(PDPE_KERNEL + LAST_ENTRY, PDE_KERNEL_FB); // 2nd Layer entry for the framebuffer
// Set the 480th entry (PDE_KERNEL_FB + (480 * 8))
// To the framebuffer + flags
SET_ADDRESS(PDE_KERNEL_FB + 3840, USERWRITEABLE_FLAGS(fb_ptr));
// In 4 byte increments, we're gonna map 3840 (the framebuffer)
// Up to (4096 - 8) in the PDE_KERNEL_FB with 2MB paging.
size_t MappingIterations = 1;
for(size_t i = 3844; i < 4088; i += 4) {
SET_ADDRESS(PDE_KERNEL_FB + i, USERWRITEABLE_FLAGS(fb_ptr) + (MappingIterations * (2 * MiB)));
MappingIterations++;
}
// Now we map the last entry of PDE_KERNEL_FB to our Page Table
SET_ADDRESS(PDE_KERNEL_FB + LAST_ENTRY, PT_KERNEL);
// Mapping the kernel into the page tables....
SET_ADDRESS(PT_KERNEL, 0xFF8001); // bootldr, bootinfo
SET_ADDRESS(PT_KERNEL + 8, 0xFF9001); // environment
// Map the kernel itself
SET_ADDRESS(PT_KERNEL + 16, KernelAddr + 1);
// Iterate through the pages, identity mapping each one
MappingIterations = 1;
size_t MappingOffset = 0x14;
for(size_t i = 0; i < ((KernelEnd - KernelAddr) >> 12); i++) {
// Page Table + (0x10 increasing by 0x04 each time) = x * 4KiB
SET_ADDRESS(PT_KERNEL + MappingOffset, (MappingIterations * (4 * KiB)));
MappingOffset += 4;
MappingIterations++;
}
// Now we need to map the core stacks. Top-down, from 0xDFF8
// There's always at least one core, so we do that one fixed.
// TODO: Account for 0-core CPUs
SET_ADDRESS(PT_KERNEL + LAST_ENTRY, 0xF14003);
MappingIterations = 1;
// For every core:
for(size_t i = 0; i < (bootldr.numcores + 3) >> 2; i++) {
// PT_KERNEL[512 - (iterations + 1)] = 0x14003 + (iterations * page-width)
SET_ADDRESS(PT_KERNEL + LAST_ENTRY - (MappingIterations * 8), 0xF14003 + (4096 * MappingIterations));
MappingIterations++;
}
SET_ADDRESS(PDPE_RAM, PDE_RAM + PAGE_PRESENT + PAGE_RW);
SET_ADDRESS(PDPE_RAM + 8, 0xF10000 + PAGE_PRESENT + PAGE_RW);
SET_ADDRESS(PDPE_RAM + 16, 0xF11000 + PAGE_PRESENT + PAGE_RW);
SET_ADDRESS(PDPE_RAM + 24, 0xF12000 + PAGE_PRESENT + PAGE_RW);
// Identity map 4GB of ram
// Each page table can only hold 512 entries, but we
// just set up 4 of them - overflowing PDE_RAM (0xF000)
// will take us into 0x10000, into 0x11000, into 0x120000.
for(size_t i = 0; i < 512 * 4/*GB*/; i++) {
// add PDE_RAM, 4
// mov eax, 0x83
// add eax, 2*1024*1024
SET_ADDRESS(PDE_RAM + (i * 4), USERWRITEABLE_FLAGS(i * (2 * MiB)));
}
// Map first 2MB of memory
SET_ADDRESS(PDE_RAM, 0xF13000 + PAGE_PRESENT + PAGE_RW);
for(size_t i = 0; i < 512; i++) {
SET_ADDRESS(0xF13000 + i * 4, i * (4 * KiB) + PAGE_PRESENT + PAGE_RW);
}
// 0xA000 should now contain our memory map.
}
void InitPagingOldImpl() {
// Disable paging so that we can work with the pagetable
//size_t registerTemp = ReadControlRegister(0);
//UNSET_PGBIT(registerTemp);
//WriteControlRegister(0, registerTemp);
// Clear space for our pagetable
size_t PagetableDest = 0x1000;
memset(PagetableDest, 0, 4096);
// Start setting pagetable indexes
*((size_t*)PagetableDest) = 0x2003; // PDP at 0x2000, present & r/w
*((size_t*)PagetableDest + 0x1000) = 0x3003; // PDT at 0x3000, present & r/w
*((size_t*)PagetableDest + 0x2000) = 0x4003; // PT at 0x4000, present & r/w
size_t value = 0x3;
size_t offset = 8;
for(size_t i = 0; i < 512; i++) { // 512 iterations (entries into the page table)
*((size_t*) PagetableDest + offset) = value; // We're setting 512 bytes with x003
// (identity mapping the first 4 megabytes of memory)
// (mapping the page table to itself)
value += 4096; // Point to start of next page
offset += 8; // + 8 bytes (next entry in list)
}
// Enable PAE paging
size_t reg = ReadControlRegister(4);
SET_PAEBIT(reg);
WriteControlRegister(4, reg);
WriteControlRegister(3, PagetableDest);
}
/* size_t registerTemp = ReadControlRegister(4);
if(registerTemp & (1 << 7)) {
TOGGLE_PGEBIT(registerTemp);
WriteControlRegister(4, registerTemp);
}
if(registerTemp & (1 << 7))
WriteControlRegister(4, registerTemp ^ (1 << 7));
size_t CPUIDReturn;
asm volatile("cpuid" : "=d" (CPUIDReturn) : "a" (0x80000001) : "%rbx", "%rcx");
if(CPUIDReturn & (1 << 26)) {
SerialPrintf("System supports 1GB pages.\r\n");
if(registerTemp & (1 << 12)) {
SerialPrintf("PML5 paging available - using that instead.\r\n");
if(MemorySize > (1ULL << 57))
SerialPrintf("System has over 128Petabytes of RAM. Please consider upgrading the OS on your supercomputer.\r\n");
size_t MaxPML5 = 1;
size_t MaxPML4 = 1;
size_t MaxPDP = 512;
size_t LastPML4Entry = 512;
size_t LastPDPEntry = 512;
size_t MemorySearchDepth = MemorySize;
while(MemorySearchDepth > (256ULL << 30)) {
MaxPML5++;
MemorySearchDepth -= (256ULL << 30);
}
if(MaxPML5 > 512)
MaxPML5 = 512;
if(MemorySearchDepth) {
LastPDPEntry = ( (MemorySearchDepth + ((1 << 30) - 1)) & (~0ULL << 30)) >> 30;
if(MaxPML5 > 512)
MaxPML5 = 512;
}
size_t PML4Size = PAGETABLE_SIZE * MaxPML5;
size_t PDPSize = PML4Size * MaxPML4;
size_t PML4Base = AllocatePagetable(PML4Size + PDPSize);
size_t PDPBase = PML4Base + PML4Size;
for(size_t PML5Entry = 0; PML5Entry < MaxPML5; PML5Entry++) {
Pagetable[PML5Entry] = PML4Base + (PML5Entry << 12);
if(PML5Entry == (MaxPML5 - 1))
MaxPML4 = LastPML4Entry;
for(size_t PML4Entry = 0; PML4Entry < MaxPML4; PML4Entry++) {
((size_t*) Pagetable[PML5Entry])[PML4Entry] = PDPBase + (((PML5Entry << 9) + PML5Entry) << 12);
if( (PML5Entry == (MaxPML5 - 1)) && (PML4Entry == (MaxPML4 -1)) )
MaxPDP = LastPDPEntry;
for(size_t PDPEntry = 0; PDPEntry < MaxPDP; PDPEntry++) {
((size_t* ) ((size_t* ) Pagetable[PML5Entry])[PML4Entry])[PDPEntry] = ( ((PML5Entry << 18) + (PML4Entry << 9) + PDPEntry) << 30) | (0x83);
}
((size_t* ) Pagetable[PML5Entry])[PML4Entry] |= 0x3;
}
Pagetable[PML5Entry] |= 0x3;
}
} else {
SerialPrintf("PML4 available - using that instead.\r\n");
size_t MemorySearchDepth = MemorySize;
if(MemorySearchDepth > (1ULL << 48))
SerialPrintf("RAM limited to 256TB.\r\n");
size_t MaxPML4 = 1;
size_t MaxPDP = 512;
size_t LastPDPEntry = 512;
while(MemorySearchDepth > (512ULL << 30)) {
MaxPML4++;
MemorySearchDepth -= (512ULL << 30);
}
if(MaxPML4 > 512)
MaxPML4 = 512;
if(MemorySearchDepth) {
LastPDPEntry = ( (MemorySearchDepth + ((1 << 30) - 1)) & (~0ULL << 30)) >> 30;
if(LastPDPEntry > 512)
LastPDPEntry = 512;
}
size_t PDPSize = PAGETABLE_SIZE * MaxPML4;
size_t PDPBase = AllocatePagetable(PDPSize);
for(size_t PML4Entry = 0; PML4Entry < MaxPML4; PML4Entry++) {
Pagetable[PML4Entry] = PDPBase + (PML4Entry << 12);
if(PML4Entry == (MaxPML4 - 1)) {
MaxPDP = LastPDPEntry;
}
for(size_t PDPEntry = 0; PDPEntry < MaxPDP; PDPEntry++) {
((size_t* ) Pagetable[PML4Entry])[PDPEntry] = (((PML4Entry << 9) + PDPEntry) << 30) | 0x83;
}
Pagetable[PML4Entry] |= 0x3;
}
}
} else {
SerialPrintf("System does not support 1GB pages - using 2MiB paging instead.\r\n");
size_t MemorySearchDepth = MemorySize;
if(MemorySearchDepth > (1ULL << 48)) {
SerialPrintf("Usable RAM is limited to 256TB, and the page table alone will use 1GB of space in memory.\r\n");
}
size_t MaxPML4 = 1, MaxPDP = 512, MaxPD = 512, LastPDPEntry = 1;
while(MemorySearchDepth > (512ULL << 30)) {
MaxPML4++;
MemorySearchDepth -= (512ULL << 30);
}
if(MaxPML4 > 512)
MaxPML4 = 512;
if(MemorySearchDepth) {
LastPDPEntry = ((MemorySearchDepth + ((1 << 30) - 1)) & (~0ULL << 30)) >> 30;
if(LastPDPEntry > 512)
LastPDPEntry = 512;
}
size_t PDPSize = PAGETABLE_SIZE * MaxPML4;
size_t PDSize = PDPSize * MaxPDP;
size_t PDPBase = AllocatePagetable(PDPSize + PDSize);
size_t PDBase = PDPBase + PDSize;
for(size_t PML4Entry = 0; PML4Entry < MaxPML4; PML4Entry++) {
Pagetable[PML4Entry] = PDBase + (PML4Entry << 12);
if(PML4Entry == (MaxPML4 - 1)) {
MaxPDP = LastPDPEntry;
}
for(size_t PDPEntry = 0; PDPEntry < MaxPDP; PDPEntry++) {
( (size_t* ) Pagetable[PML4Entry])[PDPEntry] = PDBase + (((PML4Entry << 9) + PDPEntry) << 12);
for(size_t PDEntry = 0; PDEntry < MaxPD; PDEntry++) {
( (size_t* ) ((size_t*) Pagetable[PML4Entry])[PDPEntry])[PDEntry] = (( (PML4Entry << 18) + (PDPEntry << 9) + PDPEntry) << 21) | 0x83;
}
( (size_t* ) Pagetable[PML4Entry])[PDPEntry] |= 0x3;
}
Pagetable[PML4Entry] |= 0x3;
}
}
WriteControlRegister(3, Pagetable);
registerTemp = ReadControlRegister(4);
if(!(registerTemp & (1 << 7))) {
TOGGLE_PGEBIT(registerTemp);
WriteControlRegister(4, registerTemp);
}*/

View File

@ -1,9 +1,10 @@
#include <kernel/chroma.h> #include <kernel/chroma.h>
#include <kernel/system/heap.h>
uint8_t* Memory = ((uint8_t*)(&end)); uint8_t* Memory = ((uint8_t*)(&end));
uint8_t MemoryStart; uint8_t MemoryStart;
uint32_t MemoryPages; size_t MemoryBuckets;
uint32_t MemoryLength;
void InitMemoryManager() { void InitMemoryManager() {
@ -11,7 +12,8 @@ void InitMemoryManager() {
size_t BootstructLoc = (size_t) &bootldr; size_t BootstructLoc = (size_t) &bootldr;
size_t BootstructEnd = BootstructLoc + BootstructSize; size_t BootstructEnd = BootstructLoc + BootstructSize;
size_t MemorySize = 0, MemMapEntryCount = 0; MemorySize = 0;
size_t MemMapEntryCount = 0;
MMapEnt* MemMap = &bootldr.mmap; MMapEnt* MemMap = &bootldr.mmap;
@ -25,39 +27,69 @@ void InitMemoryManager() {
MemoryPages = MemorySize / PAGE_SIZE; MemoryPages = MemorySize / PAGE_SIZE;
MemoryLength = MemoryPages / PAGES_PER_BUCKET; MemoryBuckets = MemoryPages / PAGES_PER_BUCKET;
if(MemoryLength * PAGES_PER_BUCKET < MemoryPages) if(MemoryBuckets * PAGES_PER_BUCKET < MemoryPages)
MemoryLength++; // Always round up MemoryBuckets++; // Always round up
memset(Memory, 0, MemoryLength); memset(Memory, 0, MemoryBuckets);
MemoryStart = (uint8_t*)PAGE_ALIGN(((uint32_t)(Memory + MemoryLength))); MemoryStart = (uint8_t*) PAGE_ALIGN((size_t)(Memory + MemoryBuckets));
SerialPrintf("Initializing Memory.\r\n"); SerialPrintf("Initializing Memory.\r\n");
SerialPrintf("%u MB of memory detected.\r\n", (MemorySize / 1024) / 1024); SerialPrintf("%u MB of memory detected.\r\n", (MemorySize / 1024) / 1024);
for(size_t i = 0; i < MemoryLength; i++) { for(size_t i = 0; i < MemoryBuckets; i++) {
if(Memory[i] != 0) if(Memory[i] != 0)
SerialPrintf("Memory at 0x%p is not empty!", Memory + i); SerialPrintf("Memory at 0x%p is not empty!", Memory + i);
} }
} }
size_t AllocatePage() {
size_t FreePage = FirstFreePage(); void ListMemoryMap() {
SerialPrintf("BIOS-Provided memory map:\r\n");
for(MMapEnt* MapEntry = &bootldr.mmap; MapEntry < (size_t) &bootldr + bootldr.size; MapEntry++) {
char EntryType[8] = {0};
switch(MMapEnt_Type(MapEntry)) {
case MMAP_FREE:
memcpy(EntryType, "FREE", 5);
break;
case MMAP_USED:
memcpy(EntryType, "RESERVED", 8);
break;
case MMAP_ACPI:
memcpy(EntryType, "ACPI", 4);
break;
case MMAP_MMIO:
memcpy(EntryType, "MMIO", 4);
break;
}
SerialPrintf("[ mem 0x%p-0x%p] %s\r\n", MMapEnt_Ptr(MapEntry), MMapEnt_Ptr(MapEntry) + MMapEnt_Size(MapEntry), EntryType);
}
}
size_t AllocateFrame() {
size_t FreePage = SeekFrame();
SET_BIT(FreePage); SET_BIT(FreePage);
return FreePage; return FreePage;
} }
void FreePage(size_t Page) { void FreeFrame(size_t Frame) {
UNSET_BIT(Page); UNSET_BIT(Frame);
} }
size_t FirstFreePage() { size_t SeekFrame() {
for(size_t i = 0; i < MemoryPages; i++) { for(size_t i = 0; i < MemoryPages; i++) {
if(!READ_BIT(i)) if(!READ_BIT(i))
return i; return i;
@ -70,24 +102,24 @@ size_t FirstFreePage() {
void MemoryTest() { void MemoryTest() {
SerialPrintf("Initializing basic memory test..\r\n"); SerialPrintf("Initializing basic memory test..\r\n");
bool Passed = true; bool Passed = true;
size_t FirstPage = FirstFreePage(); size_t FirstPage = SeekFrame();
void* FirstPageAlloc = AllocatePage(); void* FirstPageAlloc = (void*) AllocateFrame();
size_t SecondPage = FirstFreePage(); size_t SecondPage = SeekFrame();
void* SecondPageAlloc = AllocatePage(); void* SecondPageAlloc = (void*) AllocateFrame();
if(!(FirstPage == 0 && SecondPage == 1)) { if(!(FirstPage == 0 && SecondPage == 1)) {
Passed = false; Passed = false;
SerialPrintf("First iteration: Failed, First page %x, Second page %x.\r\n", FirstPage, SecondPage); SerialPrintf("First iteration: Failed, First page %x, Second page %x.\r\n", FirstPage, SecondPage);
} }
FreePage(SecondPage); FreeFrame(SecondPage);
SecondPage = FirstFreePage(); SecondPage = SeekFrame();
if(SecondPage != 1) if(SecondPage != 1)
Passed = false; Passed = false;
FreePage(FirstPage); FreeFrame(FirstPage);
FirstPage = FirstFreePage(); FirstPage = SeekFrame();
if(FirstPage != 0) if(FirstPage != 0)
Passed = false; Passed = false;

View File

@ -39,7 +39,7 @@ void InitPrint() {
PrintInfo.charScale = 2; PrintInfo.charScale = 2;
PrintInfo.charPosX = 0; PrintInfo.charPosX = 0;
PrintInfo.charPosY = 0; PrintInfo.charPosY = 1;
PrintInfo.scrlMode = 0; PrintInfo.scrlMode = 0;
@ -68,23 +68,23 @@ static void DrawChar(const char character, size_t x, size_t y) {
X++; X++;
} }
if((FONT[character][Row * Y + X] >> (Bit & 0x7)) & 1) { // This one is crazy. Stick with me.
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) {
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { if((FONT[character][Row * Y + X] >> (Bit & 0x7)) & 1) { // Check the bit in the bitmap, if it's solid..
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { // Take care of the scale height
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { // And the scale width
size_t offset = ((y * bootldr.fb_width + x) + size_t offset = ((y * bootldr.fb_width + x) + // Calculate the offset from the framebuffer
PrintInfo.charScale * (Row * bootldr.fb_width + Bit) + PrintInfo.charScale * (Row * bootldr.fb_width + Bit) + // With the appropriate scale
(ScaleY * bootldr.fb_width + ScaleX) + (ScaleY * bootldr.fb_width + ScaleX) + // In X and Y
PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; // With some offset to start at 0
// This one is crazy. Stick with me. *(uint32_t* )(&fb + offset * 4) // And use it to set the correct pixel on the screen
*(uint32_t* )(&fb + offset * 4)// Offset from the framebuffer, find the pixel.. = PrintInfo.charFGColor; // In the set foreground color
// and find which column we need to be in. Multiply by 4 to navigate the 4bpp array,
= PrintInfo.charFGColor; // And set the color of the pixel.
} }
} }
} else { } else {
// We need to draw the pixel transparently.. // We need to draw the pixel transparently, using the background color
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) {
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) {
if(PrintInfo.charHLColor != 0xFF000000) { if(PrintInfo.charHLColor != 0xFF000000) {
@ -93,7 +93,7 @@ static void DrawChar(const char character, size_t x, size_t y) {
(ScaleY * bootldr.fb_width + ScaleX) + (ScaleY * bootldr.fb_width + ScaleX) +
PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10;
if( y == 0 && x == 0){ if( y == 0 && x == 0){
SerialPrintf("Writing first pixel at %x\r\n", offset); //SerialPrintf("Writing first pixel at %x\r\n", offset);
} }
*(uint32_t*)(&fb + offset *4) *(uint32_t*)(&fb + offset *4)
@ -190,8 +190,8 @@ void DrawPixel(uint32_t x, uint32_t y, uint32_t color) {
} else if(y > bootldr.fb_height) { } else if(y > bootldr.fb_height) {
DrawPixel(x, y - bootldr.fb_height, color); DrawPixel(x, y - bootldr.fb_height, color);
} else { } else {
*((uint32_t*) (&fb + (y * bootldr.fb_scanline + x) * 4)) = color; *((uint32_t*) (&fb + (y * bootldr.fb_width + x) * 4)) = color;
SerialPrintf("Drawing a pixel at %d, %d with color 0x%x\r\n", x, y, color); //SerialPrintf("Drawing a pixel at %d, %d with color 0x%x\r\n", x, y, color);
} }
} }
@ -226,6 +226,21 @@ static void ProgressCursor() {
ProgressCursorS(1); ProgressCursorS(1);
} }
static void Backspace() {
SerialPrintf("Backspacing from %d to %d\r\n", PrintInfo.charPosX, PrintInfo.charPosX - 1);
if(PrintInfo.charPosX - 1 <= 0) {
if(PrintInfo.charPosY - 1 <= 0) {
PrintInfo.charPosY = 0;
} else {
PrintInfo.charPosY--;
}
PrintInfo.charPosX = 0;
} else {
PrintInfo.charPosX -= 1;
}
}
void WriteChar(const char character) { void WriteChar(const char character) {
//size_t y = PrintInfo.charPos / RowsWidth * (PrintInfo.charScale * PrintInfo.charHeight); //size_t y = PrintInfo.charPos / RowsWidth * (PrintInfo.charScale * PrintInfo.charHeight);
@ -233,19 +248,15 @@ void WriteChar(const char character) {
switch(character) { switch(character) {
case '\b': case '\b':
if(PrintInfo.charPosX - 1 == 0) { Backspace();
if(PrintInfo.charPosY - 1 == 0) { DrawChar((char) 32, PrintInfo.charPosX, PrintInfo.charPosY);
PrintInfo.charPosY = 0;
} else {
PrintInfo.charPosY--;
}
} else {
PrintInfo.charPosX = 0;
}
break; break;
case '\n': case '\n':
Newline(); Newline();
break; break;
case '\t':
ProgressCursorS(4);
break;
default: default:
DrawChar(character, PrintInfo.charPosX, PrintInfo.charPosY); DrawChar(character, PrintInfo.charPosX, PrintInfo.charPosY);
@ -255,10 +266,48 @@ void WriteChar(const char character) {
} }
void WriteString(const char* string) { void WriteString(const char* string) {
for(int i = 0; i < strlen(string); i++) { for(int i = 0; i < strlen(string); i++) {
WriteChar(string[i]); WriteChar(string[i]);
} }
} }
void WriteStringWithFont(const char *inChar)
{
psf_t *font = (psf_t*) &_binary_font_psf_start;
int drawX, drawY, kx = 0, fontLine, bitMask, offset;
int bytesPerLine = ( font -> glyphWidth + 7 ) / 8;
while(*inChar) {
unsigned char *glyph =
(unsigned char*) &_binary_font_psf_start
+ font->headerSize
+ (*inChar > 0 && *inChar < font->numGlyphs ? *inChar : 0) *
font->glyphSize;
offset = (kx * (font->glyphWidth + 1) * 4);
for( drawY = 0; drawY < font->glyphHeight ; drawY++) {
fontLine = offset;
bitMask = 1 << (font->glyphWidth - 1);
for( drawX = 0; drawX < font->glyphWidth; drawX++) {
*((uint32_t*)((uint64_t) &fb + fontLine)) =
((int) *glyph) & (bitMask) ? 0xFFFFFF : 0;
bitMask >>= 1;
fontLine += 4;
}
*((uint32_t*)((uint64_t) &fb + fontLine)) = 0;
glyph += bytesPerLine;
offset += bootldr.fb_scanline;
}
inChar++; kx++;
}
}

BIN
font.psf Normal file

Binary file not shown.

View File

@ -9,7 +9,8 @@ PHDRS
SECTIONS SECTIONS
{ {
. = 0xffffffffffe00000; . = 0xFFFFFFFFFFE00000;
LoadAddr = .;
bootldr = .; . += 4096; bootldr = .; . += 4096;
environment = .; . += 4096; environment = .; . += 4096;