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:
parent
822cfc4b9e
commit
97576bab02
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
@ -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(;;) { }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
322
chroma/system/memory/paging.c
Normal file
322
chroma/system/memory/paging.c
Normal 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);
|
||||||
|
}*/
|
|
@ -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;
|
|
@ -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++) {
|
|
||||||
|
|
||||||
size_t offset = ((y * bootldr.fb_width + x) +
|
if((FONT[character][Row * Y + X] >> (Bit & 0x7)) & 1) { // Check the bit in the bitmap, if it's solid..
|
||||||
PrintInfo.charScale * (Row * bootldr.fb_width + Bit) +
|
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { // Take care of the scale height
|
||||||
(ScaleY * bootldr.fb_width + ScaleX) +
|
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { // And the scale width
|
||||||
PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10;
|
|
||||||
|
|
||||||
// This one is crazy. Stick with me.
|
size_t offset = ((y * bootldr.fb_width + x) + // Calculate the offset from the framebuffer
|
||||||
*(uint32_t* )(&fb + offset * 4)// Offset from the framebuffer, find the pixel..
|
PrintInfo.charScale * (Row * bootldr.fb_width + Bit) + // With the appropriate scale
|
||||||
// and find which column we need to be in. Multiply by 4 to navigate the 4bpp array,
|
(ScaleY * bootldr.fb_width + ScaleX) + // In X and Y
|
||||||
= PrintInfo.charFGColor; // And set the color of the pixel.
|
PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10; // With some offset to start at 0
|
||||||
|
|
||||||
|
*(uint32_t* )(&fb + offset * 4) // And use it to set the correct pixel on the screen
|
||||||
|
= PrintInfo.charFGColor; // In the set foreground color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user