From 97576bab0241d777291040be45b14933457b5fa4 Mon Sep 17 00:00:00 2001 From: Curle Date: Sat, 11 Apr 2020 22:59:39 +0100 Subject: [PATCH] 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. --- chroma/inc/kernel/chroma.h | 23 ++ chroma/inc/kernel/system/interrupts.h | 38 +++ chroma/inc/kernel/system/memory.h | 32 ++- chroma/kernel.c | 11 + chroma/system/drivers/keyboard.c | 2 +- chroma/system/interrupts.c | 28 +- chroma/system/memory/paging.c | 322 ++++++++++++++++++++++ chroma/system/{mem.c => memory/physmem.c} | 76 +++-- chroma/video/draw.c | 103 +++++-- font.psf | Bin 0 -> 2080 bytes linker.ld | 3 +- 11 files changed, 577 insertions(+), 61 deletions(-) create mode 100644 chroma/system/memory/paging.c rename chroma/system/{mem.c => memory/physmem.c} (55%) create mode 100644 font.psf diff --git a/chroma/inc/kernel/chroma.h b/chroma/inc/kernel/chroma.h index acaede6..0f3000b 100644 --- a/chroma/inc/kernel/chroma.h +++ b/chroma/inc/kernel/chroma.h @@ -1,3 +1,4 @@ +#pragma once /************************ *** Team Kitty, 2020 *** *** Sync *** @@ -12,9 +13,29 @@ #include #include +extern size_t LoadAddr; extern bootinfo bootldr; extern unsigned char* environment; 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); @@ -23,6 +44,8 @@ void FillScreen(uint32_t color); void WriteString(const char* string); void WriteChar(const char character); +void WriteStringWithFont(const char* string); + void InitInterrupts(); void InitSerial(); void InitPrint(); diff --git a/chroma/inc/kernel/system/interrupts.h b/chroma/inc/kernel/system/interrupts.h index ec3a498..565c8f3 100644 --- a/chroma/inc/kernel/system/interrupts.h +++ b/chroma/inc/kernel/system/interrupts.h @@ -1,5 +1,43 @@ +#pragma once #include +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)) { size_t ss; size_t rsp; diff --git a/chroma/inc/kernel/system/memory.h b/chroma/inc/kernel/system/memory.h index 6c0b631..e65b05f 100644 --- a/chroma/inc/kernel/system/memory.h +++ b/chroma/inc/kernel/system/memory.h @@ -1,5 +1,6 @@ #include #include +#include #define PAGE_SIZE 4096 #define PAGES_PER_BUCKET 8 @@ -10,16 +11,37 @@ #define READ_BIT(i) ((OFFSET_BIT(i) >> (i % PAGES_PER_BUCKET)) & 0x1) #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; +void ListMemoryMap(); + 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(); \ No newline at end of file +void MemoryTest(); + +void InitPaging(); + +void PageFaultHandler(INTERRUPT_FRAME frame); \ No newline at end of file diff --git a/chroma/kernel.c b/chroma/kernel.c index 5cf36ec..6422b9d 100644 --- a/chroma/kernel.c +++ b/chroma/kernel.c @@ -1,11 +1,21 @@ #include +size_t KernelAddr = (size_t) &LoadAddr; +size_t KernelEnd = (size_t) &end; + void _start(void) { + 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(); + WriteStringWithFont("Initty Testing"); + SetupInitialGDT(); SetupIDT(); InitInterrupts(); @@ -15,6 +25,7 @@ void _start(void) { InitPaging(); + for(;;) { } } diff --git a/chroma/system/drivers/keyboard.c b/chroma/system/drivers/keyboard.c index 2f5ec47..a4fe573 100644 --- a/chroma/system/drivers/keyboard.c +++ b/chroma/system/drivers/keyboard.c @@ -79,7 +79,7 @@ void UpdateKeyboard(uint8_t msg) { if(msg & 0x80) { } else { - SerialPrintf("Key pressed %c\r\n", keys[msg]); + SerialPrintf("Key pressed: [\%c]\r\n", keys[msg]); WriteChar(keys[msg]); } diff --git a/chroma/system/interrupts.c b/chroma/system/interrupts.c index e66e6d3..9a08447 100644 --- a/chroma/system/interrupts.c +++ b/chroma/system/interrupts.c @@ -49,8 +49,7 @@ void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) { FillScreen(0x0000FF00); /* ExceptionStrings is an array of c-strings defined in kernel.h */ - //serialPrint(ExceptionStrings[Exception]); - //serialPrint(" Exception.\r\n"); + SerialPrintf("%s exception!\r\n", ExceptionStrings[Exception]); //printf("%s exception!", ExceptionStrings[Exception]); //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) { if(Exception < 32) { - FillScreen(0x00FF0000); + FillScreen(0x0000FF00); SerialPrintf("ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode); - + SerialPrintf("%s exception!\r\n", ExceptionStrings[Exception]); while(true) {} //serialPrint(ExceptionStrings[Exception]); //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 } __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) { ISR_Common(Frame, 15); diff --git a/chroma/system/memory/paging.c b/chroma/system/memory/paging.c new file mode 100644 index 0000000..36522a6 --- /dev/null +++ b/chroma/system/memory/paging.c @@ -0,0 +1,322 @@ +#include + +__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); + }*/ \ No newline at end of file diff --git a/chroma/system/mem.c b/chroma/system/memory/physmem.c similarity index 55% rename from chroma/system/mem.c rename to chroma/system/memory/physmem.c index 849681d..d8c03b5 100644 --- a/chroma/system/mem.c +++ b/chroma/system/memory/physmem.c @@ -1,9 +1,10 @@ #include +#include uint8_t* Memory = ((uint8_t*)(&end)); uint8_t MemoryStart; -uint32_t MemoryPages; -uint32_t MemoryLength; +size_t MemoryBuckets; + void InitMemoryManager() { @@ -11,7 +12,8 @@ void InitMemoryManager() { size_t BootstructLoc = (size_t) &bootldr; size_t BootstructEnd = BootstructLoc + BootstructSize; - size_t MemorySize = 0, MemMapEntryCount = 0; + MemorySize = 0; + size_t MemMapEntryCount = 0; MMapEnt* MemMap = &bootldr.mmap; @@ -25,39 +27,69 @@ void InitMemoryManager() { MemoryPages = MemorySize / PAGE_SIZE; - MemoryLength = MemoryPages / PAGES_PER_BUCKET; + MemoryBuckets = MemoryPages / PAGES_PER_BUCKET; - if(MemoryLength * PAGES_PER_BUCKET < MemoryPages) - MemoryLength++; // Always round up + if(MemoryBuckets * PAGES_PER_BUCKET < MemoryPages) + 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("%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) 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); return FreePage; } -void FreePage(size_t Page) { - UNSET_BIT(Page); +void FreeFrame(size_t Frame) { + UNSET_BIT(Frame); } -size_t FirstFreePage() { +size_t SeekFrame() { for(size_t i = 0; i < MemoryPages; i++) { if(!READ_BIT(i)) return i; @@ -70,24 +102,24 @@ size_t FirstFreePage() { void MemoryTest() { SerialPrintf("Initializing basic memory test..\r\n"); bool Passed = true; - size_t FirstPage = FirstFreePage(); - void* FirstPageAlloc = AllocatePage(); - size_t SecondPage = FirstFreePage(); - void* SecondPageAlloc = AllocatePage(); + size_t FirstPage = SeekFrame(); + void* FirstPageAlloc = (void*) AllocateFrame(); + size_t SecondPage = SeekFrame(); + void* SecondPageAlloc = (void*) AllocateFrame(); if(!(FirstPage == 0 && SecondPage == 1)) { Passed = false; SerialPrintf("First iteration: Failed, First page %x, Second page %x.\r\n", FirstPage, SecondPage); } - FreePage(SecondPage); - SecondPage = FirstFreePage(); + FreeFrame(SecondPage); + SecondPage = SeekFrame(); if(SecondPage != 1) Passed = false; - FreePage(FirstPage); - FirstPage = FirstFreePage(); + FreeFrame(FirstPage); + FirstPage = SeekFrame(); if(FirstPage != 0) Passed = false; diff --git a/chroma/video/draw.c b/chroma/video/draw.c index b2aecac..fdd2f5b 100644 --- a/chroma/video/draw.c +++ b/chroma/video/draw.c @@ -39,7 +39,7 @@ void InitPrint() { PrintInfo.charScale = 2; PrintInfo.charPosX = 0; - PrintInfo.charPosY = 0; + PrintInfo.charPosY = 1; PrintInfo.scrlMode = 0; @@ -68,23 +68,23 @@ static void DrawChar(const char character, size_t x, size_t y) { X++; } - if((FONT[character][Row * Y + X] >> (Bit & 0x7)) & 1) { - for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { - for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { + // This one is crazy. Stick with me. + + 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) + - PrintInfo.charScale * (Row * bootldr.fb_width + Bit) + - (ScaleY * bootldr.fb_width + ScaleX) + - PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; + size_t offset = ((y * bootldr.fb_width + x) + // Calculate the offset from the framebuffer + PrintInfo.charScale * (Row * bootldr.fb_width + Bit) + // With the appropriate scale + (ScaleY * bootldr.fb_width + ScaleX) + // In X and Y + 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)// Offset from the framebuffer, find the pixel.. - // 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. + *(uint32_t* )(&fb + offset * 4) // And use it to set the correct pixel on the screen + = PrintInfo.charFGColor; // In the set foreground color } } } 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 ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { 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) + PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; 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) @@ -190,8 +190,8 @@ void DrawPixel(uint32_t x, uint32_t y, uint32_t color) { } else if(y > bootldr.fb_height) { DrawPixel(x, y - bootldr.fb_height, color); } else { - *((uint32_t*) (&fb + (y * bootldr.fb_scanline + x) * 4)) = color; - SerialPrintf("Drawing a pixel at %d, %d with color 0x%x\r\n", x, y, 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); } } @@ -226,6 +226,21 @@ static void ProgressCursor() { 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) { //size_t y = PrintInfo.charPos / RowsWidth * (PrintInfo.charScale * PrintInfo.charHeight); @@ -233,19 +248,15 @@ void WriteChar(const char character) { switch(character) { case '\b': - if(PrintInfo.charPosX - 1 == 0) { - if(PrintInfo.charPosY - 1 == 0) { - PrintInfo.charPosY = 0; - } else { - PrintInfo.charPosY--; - } - } else { - PrintInfo.charPosX = 0; - } + Backspace(); + DrawChar((char) 32, PrintInfo.charPosX, PrintInfo.charPosY); break; case '\n': Newline(); break; + case '\t': + ProgressCursorS(4); + break; default: DrawChar(character, PrintInfo.charPosX, PrintInfo.charPosY); @@ -255,10 +266,48 @@ void WriteChar(const char character) { } - - void WriteString(const char* string) { for(int i = 0; i < strlen(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++; + } +} diff --git a/font.psf b/font.psf new file mode 100644 index 0000000000000000000000000000000000000000..3e67693f59d769c6453826ed9012a09818a9b9af GIT binary patch literal 2080 zcmZuyJ!>0D7#>_KR}4bsa4{l9ij>P897`AyNSU9IYDvN-#T4cWA-F-duJC{G54fL@ zbcRKSsZ2^0kr1w|CInT73$wcC{TS^A?#0^Ocb@nAWBljmHB10uHuk&-tTrh=e)ws&!OD& zIEIK5^uV;cAqPZ!>YLZE8&T)Oo2%>Vs~g29qhEiU-GXLf!8ai9;6V6SzrQL$XZt(h z&)=WF2YuY#w{qaz+VA{Y-GAtCq&H0R97LTP}vkkfS*({VNnjTr}Y#bM;bqUfqI81m+h>gY@@8Zx*QlcZQH7K zK7Ag#@Vv*zRTX1)k7G11R(<<=LH8K`*G8P>6EwU3UbcBQLcDrdc zzA+V~qku&I5fcz;;va?g%@P^5OI=X&5D09V@E~~Cy!$l!RKIJqUdq??exScisd*th zd180!kA{!Q3qIj#==c2|u4Xehy%&66Gadb4RA`6UDj_MD1UD@KOKcBz-DPA(or1q5ydEtm(tybNSpz)=EZHy?o@Kj5#f#%<( zOKRRS&!3ldDNDr-Zm_fJ^mt!+Ss!Z|r*4Yf|9RrJEz9A>qB1iZkNaxw>YA#JAvjuy z2?LPpcM4Ad;=11?6cd&p<5l=jbC0yXz^5dB8!cbqupg#mU+as}tcLwB3NykwfKV4G zLtX|z