From 822cfc4b9ef25d8a8c92238598be9ffb5edf8a6d Mon Sep 17 00:00:00 2001 From: Curle Date: Thu, 6 Feb 2020 20:20:58 +0000 Subject: [PATCH] Complete overhaul of the Legacy system. Now with reasonable architecture, plus added x86_64. --- chroma/inc/kernel/boot/boot.h | 108 ++++++ chroma/inc/kernel/chroma.h | 31 ++ chroma/inc/kernel/system/descriptors.h | 68 ++++ chroma/inc/kernel/system/interrupts.h | 80 +++++ chroma/inc/kernel/system/io.h | 63 ++++ chroma/inc/kernel/system/memory.h | 25 ++ chroma/inc/kernel/video/bitmapfont.h | 466 +++++++++++++++++++++++++ chroma/kernel.c | 20 ++ chroma/system/cpu.c | 202 +++++++++++ chroma/system/drivers/keyboard.c | 115 ++++++ chroma/system/interrupts.c | 378 ++++++++++++++++++++ chroma/system/mem.c | 124 +++++++ chroma/system/rw.c | 216 ++++++++++++ chroma/system/serial.c | 40 +++ chroma/video/draw.c | 264 ++++++++++++++ chroma/video/print.c | 109 ++++++ chroma/video/tty.c | 61 ++++ iso/boot/bootloader | Bin 0 -> 11776 bytes iso/boot/grub/grub.cfg | 4 + linker.ld | 31 ++ 20 files changed, 2405 insertions(+) create mode 100644 chroma/inc/kernel/boot/boot.h create mode 100644 chroma/inc/kernel/chroma.h create mode 100644 chroma/inc/kernel/system/descriptors.h create mode 100644 chroma/inc/kernel/system/interrupts.h create mode 100644 chroma/inc/kernel/system/io.h create mode 100644 chroma/inc/kernel/system/memory.h create mode 100644 chroma/inc/kernel/video/bitmapfont.h create mode 100644 chroma/kernel.c create mode 100644 chroma/system/cpu.c create mode 100644 chroma/system/drivers/keyboard.c create mode 100644 chroma/system/interrupts.c create mode 100644 chroma/system/mem.c create mode 100644 chroma/system/rw.c create mode 100644 chroma/system/serial.c create mode 100644 chroma/video/draw.c create mode 100644 chroma/video/print.c create mode 100644 chroma/video/tty.c create mode 100644 iso/boot/bootloader create mode 100644 iso/boot/grub/grub.cfg create mode 100644 linker.ld diff --git a/chroma/inc/kernel/boot/boot.h b/chroma/inc/kernel/boot/boot.h new file mode 100644 index 0000000..7f21343 --- /dev/null +++ b/chroma/inc/kernel/boot/boot.h @@ -0,0 +1,108 @@ + +#ifndef _BOOTLOADER_H_ +#define _BOOTLOADER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define BOOT_MAGIC "BOOT" + +/* minimum protocol level: + * hardcoded kernel name, static kernel memory addresses */ +#define PROTOCOL_MINIMAL 0 +/* static protocol level: + * kernel name parsed from environment, static kernel memory addresses */ +#define PROTOCOL_STATIC 1 +/* dynamic protocol level: + * kernel name parsed, kernel memory addresses from ELF or PE symbols */ +#define PROTOCOL_DYNAMIC 2 +/* big-endian flag */ +#define PROTOCOL_BIGENDIAN 0x80 + +/* loader types, just informational */ +#define LOADER_BIOS (0<<2) +#define LOADER_UEFI (1<<2) +#define LOADER_RPI (2<<2) + +/* framebuffer pixel format, only 32 bits supported */ +#define FB_ARGB 0 +#define FB_RGBA 1 +#define FB_ABGR 2 +#define FB_BGRA 3 + +/* mmap entry, type is stored in least significant tetrad (half byte) of size + * this means size described in 16 byte units (not a problem, most modern + * firmware report memory in pages, 4096 byte units anyway). */ +typedef struct { + uint64_t ptr; + uint64_t size; +} __attribute__((packed)) MMapEnt; + +#define MMapEnt_Ptr(a) (a->ptr) +#define MMapEnt_Size(a) (a->size & 0xFFFFFFFFFFFFFFF0) +#define MMapEnt_Type(a) (a->size & 0xF) +#define MMapEnt_IsFree(a) ((a->size&0xF)==1) + +#define MMAP_USED 0 /* don't use. Reserved or unknown regions */ +#define MMAP_FREE 1 /* usable memory */ +#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */ +#define MMAP_MMIO 3 /* memory mapped IO region */ + +#define INITRD_MAXSIZE 16 /* Mb */ + +typedef struct { + /* first 64 bytes is platform independent */ + uint8_t magic[4]; /* 'BOOT' magic */ + uint32_t size; /* length of bootboot structure, minimum 128 */ + uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */ + uint8_t fb_type; /* framebuffer type, see FB_* above */ + uint16_t numcores; /* number of processor cores */ + uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */ + int16_t timezone; /* in minutes -1440..1440 */ + uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */ + uint64_t initrd_ptr; /* ramdisk image position and size */ + uint64_t initrd_size; + uint8_t *fb_ptr; /* framebuffer pointer and dimensions */ + uint32_t fb_size; + uint32_t fb_width; + uint32_t fb_height; + uint32_t fb_scanline; + + /* the rest (64 bytes) is platform specific */ + union { + struct { + uint64_t acpi_ptr; + uint64_t smbi_ptr; + uint64_t efi_ptr; + uint64_t mp_ptr; + uint64_t unused0; + uint64_t unused1; + uint64_t unused2; + uint64_t unused3; + } x86_64; + struct { + uint64_t acpi_ptr; + uint64_t mmio_ptr; + uint64_t efi_ptr; + uint64_t unused0; + uint64_t unused1; + uint64_t unused2; + uint64_t unused3; + uint64_t unused4; + } aarch64; + } arch; + + /* from 128th byte, MMapEnt[], more records may follow */ + MMapEnt mmap; + /* use like this: + * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; + * until you reach bootboot->size */ +} __attribute__((packed)) bootinfo; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/chroma/inc/kernel/chroma.h b/chroma/inc/kernel/chroma.h new file mode 100644 index 0000000..acaede6 --- /dev/null +++ b/chroma/inc/kernel/chroma.h @@ -0,0 +1,31 @@ +/************************ + *** Team Kitty, 2020 *** + *** Sync *** + ***********************/ + +#include +#include +#include +#include + +#include +#include +#include + +extern bootinfo bootldr; +extern unsigned char* environment; +extern uint8_t fb; + + +void DrawPixel(uint32_t x, uint32_t y, uint32_t color); +void FillScreen(uint32_t color); + +void WriteString(const char* string); +void WriteChar(const char character); + +void InitInterrupts(); +void InitSerial(); +void InitPrint(); + +void SetupInitialGDT(); +void SetupIDT(); diff --git a/chroma/inc/kernel/system/descriptors.h b/chroma/inc/kernel/system/descriptors.h new file mode 100644 index 0000000..3d71caa --- /dev/null +++ b/chroma/inc/kernel/system/descriptors.h @@ -0,0 +1,68 @@ +#include +#include + +typedef struct __attribute__((packed)) { + uint16_t LowLimit; + uint16_t BaseLow; + uint8_t BaseMid; + uint8_t Access; + uint8_t Granularity; + uint8_t BaseHigh; +} GDT_ENTRY; + +typedef struct __attribute__((packed)) { + uint16_t Limit; + size_t Base; +} DESC_TBL; + +typedef struct __attribute__((packed)) { + uint16_t BaseLow; + uint16_t Segment; + uint8_t ISTAndZero; + uint8_t SegmentType; + uint16_t BaseMid; + uint32_t BaseHigh; + uint32_t Reserved; +} IDT_GATE; + +typedef struct __attribute__((packed)) { + uint16_t BaseLow; + uint16_t SegmentSelector; + uint8_t ISTAndZero; + uint8_t Misc; + uint16_t BaseHigh; +} IDT_ENTRY; + +typedef struct __attribute__((packed)) { + uint16_t SegmentLimitLow; + uint16_t BaseLow; + uint8_t BaseMid1; + uint8_t SegmentType; + uint8_t SegmentLimitHigh; + uint8_t BaseMid2; + uint32_t BaseHigh; + uint32_t Reserved; +} TSS_ENTRY; + +typedef struct __attribute__((packed)) { + uint32_t Reserved0; + size_t RSP0; + size_t RSP1; + size_t RSP2; + + size_t Reserved12; + + size_t IST1; + size_t IST2; + size_t IST3; + size_t IST4; + size_t IST5; + size_t IST6; + size_t IST7; + + size_t Reserved34; + uint16_t Reserved5; + + uint16_t IOMap; +} TSS64; + diff --git a/chroma/inc/kernel/system/interrupts.h b/chroma/inc/kernel/system/interrupts.h new file mode 100644 index 0000000..ec3a498 --- /dev/null +++ b/chroma/inc/kernel/system/interrupts.h @@ -0,0 +1,80 @@ +#include + +typedef struct __attribute__((packed)) { + size_t ss; + size_t rsp; + size_t rflags; + size_t cs; + size_t rip; +} INTERRUPT_FRAME; + +typedef struct __attribute__((packed)) { + size_t ErrorCode; + size_t rip; + size_t cs; + size_t rflags; + size_t rsp; + size_t ss; +} EXCEPTION_FRAME; + +static void* IRQ_Handlers[16] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt); +void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt); +void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception); + +void RemapIRQControllers(); + +void ISR0Handler(INTERRUPT_FRAME* Frame); // Divide-By-Zero +void ISR1Handler(INTERRUPT_FRAME* Frame); // Debug +void ISR2Handler(INTERRUPT_FRAME* Frame); // Non-Maskable Interrupt +void ISR3Handler(INTERRUPT_FRAME* Frame); // Breakpoint +void ISR4Handler(INTERRUPT_FRAME* Frame); // Overflow +void ISR5Handler(INTERRUPT_FRAME* Frame); // Out-of-Bounds +void ISR6Handler(INTERRUPT_FRAME* Frame); // Invalid Opcode +void ISR7Handler(INTERRUPT_FRAME* Frame); // No Coprocessor +void ISR8Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Double Fault +void ISR9Handler(INTERRUPT_FRAME* Frame); // Coprocessor Overrun +void ISR10Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Invalid TSS +void ISR11Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Segment Not Present +void ISR12Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Stack Segment Fault +void ISR13Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // General Protection Fault +void ISR14Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Page Fault +void ISR15Handler(INTERRUPT_FRAME* Frame); // Unknown Interrupt +void ISR16Handler(INTERRUPT_FRAME* Frame); // Math Error / Coprocessor Fault +void ISR17Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Alignment Error +void ISR18Handler(INTERRUPT_FRAME* Frame); // Machine Check +void ISR19Handler(INTERRUPT_FRAME* Frame); // SSE Math Error +void ISR20Handler(INTERRUPT_FRAME* Frame); // Virtualization +void ISR21Handler(INTERRUPT_FRAME* Frame); +void ISR22Handler(INTERRUPT_FRAME* Frame); +void ISR23Handler(INTERRUPT_FRAME* Frame); +void ISR24Handler(INTERRUPT_FRAME* Frame); +void ISR25Handler(INTERRUPT_FRAME* Frame); +void ISR26Handler(INTERRUPT_FRAME* Frame); +void ISR27Handler(INTERRUPT_FRAME* Frame); +void ISR28Handler(INTERRUPT_FRAME* Frame); +void ISR29Handler(INTERRUPT_FRAME* Frame); +void ISR30Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Security Fault +void ReservedISRHandler(INTERRUPT_FRAME* Frame); + + +void IRQ0Handler(INTERRUPT_FRAME* Frame); +void IRQ1Handler(INTERRUPT_FRAME* Frame); +void IRQ2Handler(INTERRUPT_FRAME* Frame); +void IRQ3Handler(INTERRUPT_FRAME* Frame); +void IRQ4Handler(INTERRUPT_FRAME* Frame); +void IRQ5Handler(INTERRUPT_FRAME* Frame); +void IRQ6Handler(INTERRUPT_FRAME* Frame); +void IRQ7Handler(INTERRUPT_FRAME* Frame); +void IRQ8Handler(INTERRUPT_FRAME* Frame); +void IRQ9Handler(INTERRUPT_FRAME* Frame); +void IRQ10Handler(INTERRUPT_FRAME* Frame); +void IRQ11Handler(INTERRUPT_FRAME* Frame); +void IRQ12Handler(INTERRUPT_FRAME* Frame); +void IRQ13Handler(INTERRUPT_FRAME* Frame); +void IRQ14Handler(INTERRUPT_FRAME* Frame); +void IRQ15Handler(INTERRUPT_FRAME* Frame); diff --git a/chroma/inc/kernel/system/io.h b/chroma/inc/kernel/system/io.h new file mode 100644 index 0000000..91ed1ad --- /dev/null +++ b/chroma/inc/kernel/system/io.h @@ -0,0 +1,63 @@ +#include + +uint8_t kbdSBuffer[8]; +uint8_t InputBuffer[128]; + +typedef struct { + uint8_t ACK; + uint8_t SelfTest; + uint8_t Echo; + uint8_t EchoCount; + uint8_t Error; + + + +} KBD_FLAGS; + +KBD_FLAGS KbdFlags; + + +DESC_TBL ReadGDT(void); +void WriteGDT(DESC_TBL GDTData); + +DESC_TBL ReadIDT(void); +void WriteIDT(DESC_TBL IDTData); + +uint16_t ReadLDT(void); +void WriteLDT(uint16_t LDTData); + +uint16_t ReadTSR(void); +void WriteTSR(uint16_t TSRData); + + +uint32_t ReadPort(uint16_t Port, int Length); +uint32_t WritePort(uint16_t Port, uint32_t Data, int Length); +size_t ReadModelSpecificRegister(size_t MSR); +size_t WriteModelSpecificRegister(size_t MSR, size_t Data); + +uint32_t ReadVexMXCSR(void); +uint32_t WriteVexMXCSR(uint32_t Data); + +uint32_t ReadMXCSR(void); +uint32_t WriteMXCSR(uint32_t Data); + +size_t ReadControlRegister(int CRX); +size_t WriteControlRegister(int CRX, size_t Data); + +size_t ReadExtendedControlRegister(size_t XCRX); +size_t WriteExtendedControlRegister(size_t XCRX, size_t Data); + +// XCS = Extended Code Segment +size_t ReadXCS(void); + +void UpdateKeyboard(uint8_t scancode); +void WaitFor8042(); +void Send8042(size_t); + +void WriteSerialChar(const char); +void WriteSerialString(const char*, size_t); + +int SerialPrintf(const char* restrict format, ...); + +void* memcpy(void* dest, void const* src, size_t len); +void* memset(void* dst, int src, size_t len); \ No newline at end of file diff --git a/chroma/inc/kernel/system/memory.h b/chroma/inc/kernel/system/memory.h new file mode 100644 index 0000000..6c0b631 --- /dev/null +++ b/chroma/inc/kernel/system/memory.h @@ -0,0 +1,25 @@ +#include +#include + +#define PAGE_SIZE 4096 +#define PAGES_PER_BUCKET 8 + +#define OFFSET_BIT(i) Memory[i / PAGES_PER_BUCKET] +#define SET_BIT(i) OFFSET_BIT(i) = OFFSET_BIT(i) | (1 << (i % PAGES_PER_BUCKET)) +#define UNSET_BIT(i) OFFSET_BIT(i) = OFFSET_BIT(i) & (~(1 << (i % PAGES_PER_BUCKET))) +#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) + +extern size_t end; + +void InitMemoryManager(); + +size_t AllocatePage(); + +void FreePage(size_t PageNumber); + +size_t FirstFreePage(); + +void MemoryTest(); \ No newline at end of file diff --git a/chroma/inc/kernel/video/bitmapfont.h b/chroma/inc/kernel/video/bitmapfont.h new file mode 100644 index 0000000..ab347c6 --- /dev/null +++ b/chroma/inc/kernel/video/bitmapfont.h @@ -0,0 +1,466 @@ +/************************ + *** Team Kitty, 2019 *** + *** Sync *** + ***********************/ + +// This file contains all of the bitmap fonts made by me (Curle) and taken from the public domain +// eg. http://dimensionalrift.homelinux.net/combuster/mos3/?p=viewsource&file=/modules/gfx/font8_8.asm + + +const unsigned char bitfont_latin[128][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space) + { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!) + { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (") + { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#) + { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($) + { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%) + { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&) + { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (') + { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (() + { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ()) + { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*) + { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,) + { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.) + { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/) + { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0) + { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1) + { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2) + { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3) + { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4) + { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5) + { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6) + { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7) + { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8) + { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9) + { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:) + { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//) + { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<) + { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=) + { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>) + { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?) + { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@) + { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A) + { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B) + { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C) + { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D) + { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E) + { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F) + { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G) + { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H) + { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I) + { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J) + { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K) + { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L) + { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M) + { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N) + { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O) + { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P) + { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q) + { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R) + { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S) + { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T) + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U) + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V) + { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W) + { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X) + { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y) + { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z) + { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([) + { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\) + { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (]) + { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_) + { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`) + { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a) + { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b) + { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c) + { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d) + { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e) + { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f) + { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g) + { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h) + { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i) + { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j) + { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k) + { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l) + { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m) + { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n) + { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o) + { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p) + { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q) + { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r) + { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s) + { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v) + { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w) + { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y) + { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z) + { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({) + { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|) + { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (}) + { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F +}; + + +const unsigned char bitfont_extra[96][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A0 (no break space) + { 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 (inverted !) + { 0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18}, // U+00A2 (dollarcents) + { 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00}, // U+00A3 (pound sterling) + { 0x00, 0x00, 0x63, 0x3E, 0x36, 0x3E, 0x63, 0x00}, // U+00A4 (currency mark) + { 0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C}, // U+00A5 (yen) + { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+00A6 (broken pipe) + { 0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E}, // U+00A7 (paragraph) + { 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A8 (diaeresis) + { 0x3C, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3C}, // U+00A9 (copyright symbol) + { 0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00}, // U+00AA (superscript a) + { 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00AB (<<) + { 0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00}, // U+00AC (gun pointing left) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AD (soft hyphen) + { 0x3C, 0x42, 0x9D, 0xA5, 0x9D, 0xA5, 0x42, 0x3C}, // U+00AE (registered symbol) + { 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AF (macron) + { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B0 (degree) + { 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00}, // U+00B1 (plusminus) + { 0x1C, 0x30, 0x18, 0x0C, 0x3C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 2) + { 0x1C, 0x30, 0x18, 0x30, 0x1C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 3) + { 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00B2 (aigu) + { 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03}, // U+00B5 (mu) + { 0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00}, // U+00B6 (pilcrow) + { 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, // U+00B7 (central dot) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1E}, // U+00B8 (cedille) + { 0x08, 0x0C, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B9 (superscript 1) + { 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00BA (superscript 0) + { 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00BB (>>) + { 0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03}, // U+00BC (1/4) + { 0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0}, // U+00BD (1/2) + { 0x03, 0xC4, 0x63, 0xB4, 0xDB, 0xAC, 0xE6, 0x80}, // U+00BE (3/4) + { 0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00}, // U+00BF (inverted ?) + { 0x07, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C0 (A grave) + { 0x70, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C1 (A aigu) + { 0x1C, 0x36, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C2 (A circumflex) + { 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C3 (A ~) + { 0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00}, // U+00C4 (A umlaut) + { 0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00}, // U+00C5 (A ring) + { 0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00}, // U+00C6 (AE) + { 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E}, // U+00C7 (C cedille) + { 0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C8 (E grave) + { 0x38, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C9 (E aigu) + { 0x0C, 0x12, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CA (E circumflex) + { 0x36, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CB (E umlaut) + { 0x07, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CC (I grave) + { 0x38, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CD (I aigu) + { 0x0C, 0x12, 0x00, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CE (I circumflex) + { 0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CF (I umlaut) + { 0x3F, 0x66, 0x6F, 0x6F, 0x66, 0x66, 0x3F, 0x00}, // U+00D0 (Eth) + { 0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00}, // U+00D1 (N ~) + { 0x0E, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D2 (O grave) + { 0x70, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D3 (O aigu) + { 0x3C, 0x66, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D4 (O circumflex) + { 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x63, 0x3E, 0x00}, // U+00D5 (O ~) + { 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+00D6 (O umlaut) + { 0x00, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x00, 0x00}, // U+00D7 (multiplicative x) + { 0x5C, 0x36, 0x73, 0x7B, 0x6F, 0x36, 0x1D, 0x00}, // U+00D8 (O stroke) + { 0x0E, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00D9 (U grave) + { 0x70, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DA (U aigu) + { 0x3C, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DB (U circumflex) + { 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+00DC (U umlaut) + { 0x70, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00}, // U+00DD (Y aigu) + { 0x0F, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+00DE (Thorn) + { 0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03}, // U+00DF (beta) + { 0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E0 (a grave) + { 0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E1 (a aigu) + { 0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00}, // U+00E2 (a circumflex) + { 0x6E, 0x3B, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E3 (a ~) + { 0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E4 (a umlaut) + { 0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E5 (a ring) + { 0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00}, // U+00E6 (ae) + { 0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+00E7 (c cedille) + { 0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E8 (e grave) + { 0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E9 (e aigu) + { 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00}, // U+00EA (e circumflex) + { 0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00EB (e umlaut) + { 0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EC (i grave) + { 0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00ED (i augu) + { 0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EE (i circumflex) + { 0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EF (i umlaut) + { 0x1B, 0x0E, 0x1B, 0x30, 0x3E, 0x33, 0x1E, 0x00}, // U+00F0 (eth) + { 0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00}, // U+00F1 (n ~) + { 0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F2 (o grave) + { 0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F3 (o aigu) + { 0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F4 (o circumflex) + { 0x6E, 0x3B, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F5 (o ~) + { 0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F6 (o umlaut) + { 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00}, // U+00F7 (division) + { 0x00, 0x60, 0x3C, 0x76, 0x7E, 0x6E, 0x3C, 0x06}, // U+00F8 (o stroke) + { 0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00F9 (u grave) + { 0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FA (u aigu) + { 0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FB (u circumflex) + { 0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FC (u umlaut) + { 0x00, 0x38, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+00FD (y aigu) + { 0x00, 0x00, 0x06, 0x3E, 0x66, 0x3E, 0x06, 0x00}, // U+00FE (thorn) + { 0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F} // U+00FF (y umlaut) +}; + +const unsigned char bitfont_greek[58][8] = { + { 0x2D, 0x00, 0x0C, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0390 (iota with tonos and diaeresis) + { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0391 (Alpha) + { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0392 (Beta) + { 0x3F, 0x33, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00}, // U+0393 (Gamma) + { 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x7F, 0x00}, // U+0394 (Delta) + { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0395 (Epsilon) + { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+0396 (Zeta) + { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0397 (Eta) + { 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x36, 0x1C, 0x00}, // U+0398 (Theta) + { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0399 (Iota) + { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+039A (Kappa) + { 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x63, 0x00}, // U+039B (Lambda) + { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+039C (Mu) + { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+039D (Nu) + { 0x7F, 0x63, 0x00, 0x3E, 0x00, 0x63, 0x7F, 0x00}, // U+039E (Xi) + { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+039F (Omikron) + { 0x7F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00}, // U+03A0 (Pi) + { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+03A1 (Rho) + { 0x00, 0x01, 0x02, 0x04, 0x4F, 0x90, 0xA0, 0x40}, // U+03A2 + { 0x7F, 0x63, 0x06, 0x0C, 0x06, 0x63, 0x7F, 0x00}, // U+03A3 (Sigma 2) + { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+03A4 (Tau) + { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+03A5 (Upsilon) + { 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x00}, // U+03A6 (Phi) + { 0x63, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x63, 0x00}, // U+03A7 (Chi) + { 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00}, // U+03A8 (Psi) + { 0x3E, 0x63, 0x63, 0x63, 0x36, 0x36, 0x77, 0x00}, // U+03A9 (Omega) + { 0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0399 (Iota with diaeresis) + { 0x33, 0x00, 0x33, 0x33, 0x1E, 0x0C, 0x1E, 0x00}, // U+03A5 (Upsilon with diaeresis) + { 0x70, 0x00, 0x6E, 0x3B, 0x13, 0x3B, 0x6E, 0x00}, // U+03AC (alpha aigu) + { 0x38, 0x00, 0x1E, 0x03, 0x0E, 0x03, 0x1E, 0x00}, // U+03AD (epsilon aigu) + { 0x38, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x30}, // U+03AE (eta aigu) + { 0x38, 0x00, 0x0C, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+03AF (iota aigu) + { 0x2D, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+03B0 (upsilon with tonos and diaeresis) + { 0x00, 0x00, 0x6E, 0x3B, 0x13, 0x3B, 0x6E, 0x00}, // U+03B1 (alpha) + { 0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03}, // U+03B2 (beta) + { 0x00, 0x00, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x00}, // U+03B3 (gamma) + { 0x38, 0x0C, 0x18, 0x3E, 0x33, 0x33, 0x1E, 0x00}, // U+03B4 (delta) + { 0x00, 0x00, 0x1E, 0x03, 0x0E, 0x03, 0x1E, 0x00}, // U+03B5 (epsilon) + { 0x00, 0x3F, 0x06, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+03B6 (zeta) + { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x30}, // U+03B7 (eta) + { 0x00, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x1E, 0x00}, // U+03B8 (theta) + { 0x00, 0x00, 0x0C, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+03B9 (iota) + { 0x00, 0x00, 0x33, 0x1B, 0x0F, 0x1B, 0x33, 0x00}, // U+03BA (kappa) + { 0x00, 0x03, 0x06, 0x0C, 0x1C, 0x36, 0x63, 0x00}, // U+03BB (lambda) + { 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03}, // U+03BC (mu) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+03BD (nu) + { 0x1E, 0x03, 0x0E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+03BE (xi) + { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+03BF (omikron) + { 0x00, 0x00, 0x7F, 0x36, 0x36, 0x36, 0x36, 0x00}, // U+03C0 (pi) + { 0x00, 0x00, 0x3C, 0x66, 0x66, 0x36, 0x06, 0x06}, // U+03C1 (rho) + { 0x00, 0x00, 0x3E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+03C2 (sigma 1) + { 0x00, 0x00, 0x7E, 0x1B, 0x1B, 0x1B, 0x0E, 0x00}, // U+03C3 (sigma 2) + { 0x00, 0x00, 0x7E, 0x18, 0x18, 0x58, 0x30, 0x00}, // U+03C4 (tau) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+03C5 (upsilon) + { 0x00, 0x00, 0x76, 0xDB, 0xDB, 0x7E, 0x18, 0x00}, // U+03C6 (phi) + { 0x00, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+03C7 (chi) + { 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x00}, // U+03C8 (psi) + { 0x00, 0x00, 0x36, 0x63, 0x6B, 0x7F, 0x36, 0x00} // U+03C9 (omega) +}; + +const unsigned char bitfont_box[128][8] = { + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, // U+2500 (thin horizontal) + { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // U+2501 (thick horizontal) + { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // U+2502 (thin vertical) + { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // U+2503 (thich vertical) + { 0x00, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00}, // U+2504 (thin horizontal dashed) + { 0x00, 0x00, 0x00, 0xBB, 0xBB, 0x00, 0x00, 0x00}, // U+2505 (thick horizontal dashed) + { 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08}, // U+2506 (thin vertical dashed) + { 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18}, // U+2507 (thich vertical dashed) + { 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00}, // U+2508 (thin horizontal dotted) + { 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00}, // U+2509 (thick horizontal dotted) + { 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08}, // U+250A (thin vertical dotted) + { 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18}, // U+250B (thich vertical dotted) + { 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08}, // U+250C (down L, right L) + { 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x08, 0x08, 0x08}, // U+250D (down L, right H) + { 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18}, // U+250E (down H, right L) + { 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18}, // U+250F (down H, right H) + { 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08}, // U+2510 (down L, left L) + { 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x08, 0x08, 0x08}, // U+2511 (down L, left H) + { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18}, // U+2512 (down H, left L) + { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18}, // U+2513 (down H, left H) + { 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00}, // U+2514 (up L, right L) + { 0x08, 0x08, 0x08, 0xf8, 0xf8, 0x00, 0x00, 0x00}, // U+2515 (up L, right H) + { 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00}, // U+2516 (up H, right L) + { 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00}, // U+2517 (up H, right H) + { 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00}, // U+2518 (up L, left L) + { 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x00, 0x00, 0x00}, // U+2519 (up L, left H) + { 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00}, // U+251A (up H, left L) + { 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00}, // U+251B (up H, left H) + { 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08}, // U+251C (down L, right L, up L) + { 0x08, 0x08, 0x08, 0xf8, 0xf8, 0x08, 0x08, 0x08}, // U+251D (down L, right H, up L) + { 0x18, 0x18, 0x18, 0x18, 0xf8, 0x08, 0x08, 0x08}, // U+251E (down L, right L, up H) + { 0x08, 0x08, 0x08, 0x08, 0xf8, 0x18, 0x18, 0x18}, // U+251F (down H, right L, up L) + { 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18}, // U+2520 (down H, right L, up H) + { 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x08, 0x08, 0x08}, // U+2521 (down L, right H, up H) + { 0x08, 0x08, 0x08, 0xf8, 0xf8, 0x18, 0x18, 0x18}, // U+2522 (down H, right H, up L) + { 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18}, // U+2523 (down H, right H, up H) + { 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08}, // U+2524 (down L, left L, up L) + { 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x08, 0x08, 0x08}, // U+2525 (down L, left H, up L) + { 0x18, 0x18, 0x18, 0x18, 0x1f, 0x08, 0x08, 0x08}, // U+2526 (down L, left L, up H) + { 0x08, 0x08, 0x08, 0x08, 0x1f, 0x18, 0x18, 0x18}, // U+2527 (down H, left L, up L) + { 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18}, // U+2528 (down H, left L, up H) + { 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x08, 0x08, 0x08}, // U+2529 (down L, left H, up H) + { 0x08, 0x08, 0x08, 0x1f, 0x1f, 0x18, 0x18, 0x18}, // U+252A (down H, left H, up L) + { 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18}, // U+252B (down H, left H, up H) + { 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08}, // U+252C (down L, right L, left L) + { 0x00, 0x00, 0x00, 0x0f, 0xff, 0x08, 0x08, 0x08}, // U+252D (down L, right L, left H) + { 0x00, 0x00, 0x00, 0xf8, 0xff, 0x08, 0x08, 0x08}, // U+252E (down L, right H, left L) + { 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0x08, 0x08}, // U+252F (down L, right H, left H) + { 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18}, // U+2530 (down H, right L, left L) + { 0x00, 0x00, 0x00, 0x1f, 0xff, 0x18, 0x18, 0x18}, // U+2531 (down H, right L, left H) + { 0x00, 0x00, 0x00, 0xf8, 0xff, 0x18, 0x18, 0x18}, // U+2532 (down H, right H, left L) + { 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18}, // U+2533 (down H, right H, left H) + { 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00}, // U+2534 (up L, right L, left L) + { 0x08, 0x08, 0x08, 0x0f, 0xff, 0x00, 0x00, 0x00}, // U+2535 (up L, right L, left H) + { 0x08, 0x08, 0x08, 0xf8, 0xff, 0x00, 0x00, 0x00}, // U+2536 (up L, right H, left L) + { 0x08, 0x08, 0x08, 0xff, 0xff, 0x00, 0x00, 0x00}, // U+2537 (up L, right H, left H) + { 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00}, // U+2538 (up H, right L, left L) + { 0x18, 0x18, 0x18, 0x1f, 0xff, 0x00, 0x00, 0x00}, // U+2539 (up H, right L, left H) + { 0x18, 0x18, 0x18, 0xf8, 0xff, 0x00, 0x00, 0x00}, // U+253A (up H, right H, left L) + { 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00}, // U+253B (up H, right H, left H) + { 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08}, // U+253C (up L, right L, left L, down L) + { 0x08, 0x08, 0x08, 0x0f, 0xff, 0x08, 0x08, 0x08}, // U+253D (up L, right L, left H, down L) + { 0x08, 0x08, 0x08, 0xf8, 0xff, 0x08, 0x08, 0x08}, // U+253E (up L, right H, left L, down L) + { 0x08, 0x08, 0x08, 0xff, 0xff, 0x08, 0x08, 0x08}, // U+253F (up L, right H, left H, down L) + { 0x18, 0x18, 0x18, 0x18, 0xff, 0x08, 0x08, 0x08}, // U+2540 (up H, right L, left L, down L) + { 0x08, 0x08, 0x08, 0x08, 0xff, 0x18, 0x18, 0x18}, // U+2541 (up L, right L, left L, down H) + { 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18}, // U+2542 (up H, right L, left L, down H) + { 0x18, 0x18, 0x18, 0x1f, 0xff, 0x08, 0x08, 0x08}, // U+2543 (up H, right L, left H, down L) + { 0x18, 0x18, 0x18, 0xf8, 0xff, 0x08, 0x08, 0x08}, // U+2544 (up H, right H, left L, down L) + { 0x08, 0x08, 0x08, 0x1f, 0xff, 0x18, 0x18, 0x18}, // U+2545 (up L, right L, left H, down H) + { 0x08, 0x08, 0x08, 0xf8, 0xff, 0x18, 0x18, 0x18}, // U+2546 (up L, right H, left L, down H) + { 0x08, 0x08, 0x08, 0xff, 0xff, 0x18, 0x18, 0x18}, // U+2547 (up L, right H, left H, down H) + { 0x18, 0x18, 0x18, 0xff, 0xff, 0x08, 0x08, 0x08}, // U+254B (up H, right H, left H, down L) + { 0x18, 0x18, 0x18, 0xf8, 0xff, 0x18, 0x18, 0x18}, // U+254A (up H, right H, left L, down H) + { 0x18, 0x18, 0x18, 0x1f, 0xff, 0x18, 0x18, 0x18}, // U+2549 (up H, right L, left H, down H) + { 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18}, // U+254B (up H, right H, left H, down H) + { 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00}, // U+254C (thin horizontal broken) + { 0x00, 0x00, 0x00, 0xE7, 0xE7, 0x00, 0x00, 0x00}, // U+254D (thick horizontal broken) + { 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08}, // U+254E (thin vertical broken) + { 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18}, // U+254F (thich vertical broken) + { 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2550 (double horizontal) + { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, // U+2551 (double vertical) + { 0x00, 0x00, 0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+2552 (down L, right D) + { 0x00, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x14, 0x14}, // U+2553 (down D, right L) + { 0x00, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14}, // U+2554 (down D, right D) + { 0x00, 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2555 (down L, left D) + { 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14}, // U+2556 (down D, left L) + { 0x00, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14}, // U+2557 (down D, left D) + { 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x00, 0x00}, // U+2558 (up L, right D) + { 0x14, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x00, 0x00}, // U+2559 (up D, right L) + { 0x14, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00}, // U+255A (up D, right D) + { 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00}, // U+255B (up L, left D) + { 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00}, // U+255C (up D, left L) + { 0x14, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00}, // U+255D (up D, left D) + { 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+255E (up L, down L, right D) + { 0x14, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x14, 0x14}, // U+255F (up D, down D, right L) + { 0x14, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14}, // U+2560 (up D, down D, right D) + { 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2561 (up L, down L, left D) + { 0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14}, // U+2562 (up D, down D, left L) + { 0x14, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14}, // U+2563 (up D, down D, left D) + { 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x08, 0x08}, // U+2564 (left D, right D, down L) + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x14, 0x14}, // U+2565 (left L, right L, down D) + { 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14}, // U+2566 (left D, right D, down D) + { 0x08, 0x08, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2567 (left D, right D, up L) + { 0x14, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x00, 0x00}, // U+2568 (left L, right L, up D) + { 0x14, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00}, // U+2569 (left D, right D, up D) + { 0x08, 0x08, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0x08}, // U+256A (left D, right D, down L, up L) + { 0x14, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x14, 0x14}, // U+256B (left L, right L, down D, up D) + { 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14}, // U+256C (left D, right D, down D, up D) + { 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x08, 0x08}, // U+256D (curve down-right) + { 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x08}, // U+256E (curve down-left) + { 0x08, 0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00}, // U+256F (curve up-left) + { 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00}, // U+2570 (curve up-right) + { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, // U+2571 (diagonal bottom-left to top-right) + { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, // U+2572 (diagonal bottom-right to top-left) + { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}, // U+2573 (diagonal cross) + { 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00}, // U+2574 (left L) + { 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}, // U+2575 (up L) + { 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00}, // U+2576 (right L) + { 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08}, // U+2577 (down L) + { 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00}, // U+2578 (left H) + { 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, // U+2579 (up H) + { 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x00}, // U+257A (right H) + { 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18}, // U+257B (down H) + { 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00}, // U+257C (right H, left L) + { 0x08, 0x08, 0x08, 0x08, 0x18, 0x18, 0x18, 0x18}, // U+257D (up L, down H) + { 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00}, // U+257E (right L, left H) + { 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0x08} // U+257F (up H, down L) +}; + +const unsigned char bitfont_block[32][8] = { + { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, // U+2580 (top half) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+2581 (box 1/8) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}, // U+2582 (box 2/8) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF}, // U+2583 (box 3/8) + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2584 (bottom half) + { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2585 (box 5/8) + { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2586 (box 6/8) + { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2587 (box 7/8) + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2588 (solid) + { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}, // U+2589 (box 7/8) + { 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F}, // U+258A (box 6/8) + { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, // U+258B (box 5/8) + { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, // U+258C (left half) + { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}, // U+258D (box 3/8) + { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}, // U+258E (box 2/8) + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, // U+258F (box 1/8) + { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, // U+2590 (right half) + { 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00}, // U+2591 (25% solid) + { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}, // U+2592 (50% solid) + { 0xFF, 0xAA, 0xFF, 0x55, 0xFF, 0xAA, 0xFF, 0x55}, // U+2593 (75% solid) + { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+2594 (box 1/8) + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, // U+2595 (box 1/8) + { 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F}, // U+2596 (box bottom left) + { 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0}, // U+2597 (box bottom right) + { 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00}, // U+2598 (box top left) + { 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2599 (boxes left and bottom) + { 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0}, // U+259A (boxes top-left and bottom right) + { 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F}, // U+259B (boxes top and left) + { 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0}, // U+259C (boxes top and right) + { 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00}, // U+259D (box top right) + { 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F}, // U+259E (boxes top right and bottom left) + { 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF}, // U+259F (boxes right and bottom) +}; \ No newline at end of file diff --git a/chroma/kernel.c b/chroma/kernel.c new file mode 100644 index 0000000..5cf36ec --- /dev/null +++ b/chroma/kernel.c @@ -0,0 +1,20 @@ +#include + + +void _start(void) { + + SerialPrintf("\r\nBooting Chroma..\r\n"); + InitPrint(); + + SetupInitialGDT(); + SetupIDT(); + InitInterrupts(); + + InitMemoryManager(); + MemoryTest(); + + InitPaging(); + + for(;;) { } + +} diff --git a/chroma/system/cpu.c b/chroma/system/cpu.c new file mode 100644 index 0000000..b191728 --- /dev/null +++ b/chroma/system/cpu.c @@ -0,0 +1,202 @@ +#include +#include + +#define NMI_STACK 4096 +#define DF_STACK 4096 +#define MC_STACK 4096 +#define BP_STACK 4096 + +__attribute__((aligned(64))) static volatile unsigned char NMIStack[NMI_STACK] = {0}; +__attribute__((aligned(64))) static volatile unsigned char DFStack[DF_STACK] = {0}; +__attribute__((aligned(64))) static volatile unsigned char MCStack[MC_STACK] = {0}; +__attribute__((aligned(64))) static volatile unsigned char BPStack[BP_STACK] = {0}; + +__attribute__((aligned(64))) static volatile size_t InitGDT[5] = { + 0, + 0x00af9a000000ffff, + 0x00cf92000000ffff, + 0x0080890000000067, + 0 +}; + +__attribute__((aligned(64))) static volatile TSS64 TSSEntries = {0}; + +__attribute__((aligned(64))) static volatile IDT_GATE IDTEntries[256] = {0}; + +static void RefreshCS() { + + __asm__ __volatile__ ("mov $16, %ax \n\t" // 16 = 0x10 = index 2 of GDT + "mov %ax, %ds \n\t" // Next few lines prepare the processor for the sudden change into the data segment + "mov %ax, %es \n\t" // + "mov %ax, %fs \n\t" // + "mov %ax, %gs \n\t" // + "mov %ax, %ss \n\t" // + "movq $8, %rdx \n\t" // 8 = 0x8 = index 1 of GDT + "leaq 4(%rip), %rax \n\t" // Returns execution to immediately after the iret, required for changing %cs while in long mode. - this is currently literally the only way to do it. + "pushq %rdx \n\t" // + "pushq %rax \n\t" // + "lretq \n\t"); // +} + + +void SetupInitialGDT() { + DESC_TBL GDTData = {0}; + size_t TSSBase = (uint64_t) (&TSSEntries); + + uint16_t TSSLower = (uint16_t) TSSBase; + uint8_t TSSMid1 = (uint8_t) (TSSBase >> 16); + uint8_t TSSMid2 = (uint8_t) (TSSBase >> 24); + uint32_t TSSHigher = (uint32_t) (TSSBase >> 32); + + GDTData.Limit = sizeof(InitGDT) - 1; + GDTData.Base = (size_t) InitGDT; + + ( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseLow = TSSLower; + ( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseMid1 = TSSMid1; + ( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseMid2 = TSSMid2; + ( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseHigh = TSSHigher; + + WriteGDT(GDTData); + WriteTSR(3 << 3); + RefreshCS(); +} + +static void SetISR(size_t ISRNum, size_t ISRAddr) { + uint16_t ISRBaseLow = (uint16_t) ISRAddr; + uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16); + uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32); + + IDTEntries[ISRNum].BaseLow = ISRBaseLow; + IDTEntries[ISRNum].Segment = 0x08; + IDTEntries[ISRNum].ISTAndZero = 0; + IDTEntries[ISRNum].SegmentType = 0x8E; + IDTEntries[ISRNum].BaseMid = ISRBaseMid; + IDTEntries[ISRNum].BaseHigh = ISRBaseHigh; + IDTEntries[ISRNum].Reserved = 0; +} + +static void SetISRNMI(size_t ISRNum, size_t ISRAddr) { + uint16_t ISRBaseLow = (uint16_t) ISRAddr; + uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16); + uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32); + + IDTEntries[ISRNum].BaseLow = ISRBaseLow; + IDTEntries[ISRNum].Segment = 0x08; + IDTEntries[ISRNum].ISTAndZero = 1; + IDTEntries[ISRNum].SegmentType = 0x8E; + IDTEntries[ISRNum].BaseMid = ISRBaseMid; + IDTEntries[ISRNum].BaseHigh = ISRBaseHigh; + IDTEntries[ISRNum].Reserved = 0; +} + +static void SetISRDF(size_t ISRNum, size_t ISRAddr) { + uint16_t ISRBaseLow = (uint16_t) ISRAddr; + uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16); + uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32); + + IDTEntries[ISRNum].BaseLow = ISRBaseLow; + IDTEntries[ISRNum].Segment = 0x08; + IDTEntries[ISRNum].ISTAndZero = 2; + IDTEntries[ISRNum].SegmentType = 0x8E; + IDTEntries[ISRNum].BaseMid = ISRBaseMid; + IDTEntries[ISRNum].BaseHigh = ISRBaseHigh; + IDTEntries[ISRNum].Reserved = 0; +} + +static void SetISRMC(size_t ISRNum, size_t ISRAddr) { + uint16_t ISRBaseLow = (uint16_t) ISRAddr; + uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16); + uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32); + + IDTEntries[ISRNum].BaseLow = ISRBaseLow; + IDTEntries[ISRNum].Segment = 0x08; + IDTEntries[ISRNum].ISTAndZero = 3; + IDTEntries[ISRNum].SegmentType = 0x8E; + IDTEntries[ISRNum].BaseMid = ISRBaseMid; + IDTEntries[ISRNum].BaseHigh = ISRBaseHigh; + IDTEntries[ISRNum].Reserved = 0; +} + +static void SetISRBP(size_t ISRNum, size_t ISRAddr) { + uint16_t ISRBaseLow = (uint16_t) ISRAddr; + uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16); + uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32); + + IDTEntries[ISRNum].BaseLow = ISRBaseLow; + IDTEntries[ISRNum].Segment = 0x08; + IDTEntries[ISRNum].ISTAndZero = 4; + IDTEntries[ISRNum].SegmentType = 0x8E; + IDTEntries[ISRNum].BaseMid = ISRBaseMid; + IDTEntries[ISRNum].BaseHigh = ISRBaseHigh; + IDTEntries[ISRNum].Reserved = 0; +} + +void SetupIDT() { + DESC_TBL IDTData = {0}; + IDTData.Limit = (sizeof(IDT_GATE) * 256) - 1; + IDTData.Base = (size_t) &IDTEntries; + + //memset(&IDTEntries, 0, sizeof(IDT_GATE) * 256); + + RemapIRQControllers(); + + *(size_t*) (&TSSEntries.IST1) = (size_t) (NMIStack + NMI_STACK); + *(size_t*) (&TSSEntries.IST2) = (size_t) (DFStack + DF_STACK); + *(size_t*) (&TSSEntries.IST3) = (size_t) (MCStack + MC_STACK); + *(size_t*) (&TSSEntries.IST4) = (size_t) (BPStack + BP_STACK); + + SetISR (0, (size_t) ISR0Handler); + SetISRBP (1, (size_t) ISR1Handler); + SetISRNMI (2, (size_t) ISR2Handler); + SetISRBP (3, (size_t) ISR3Handler); + SetISR (4, (size_t) ISR4Handler); + SetISR (5, (size_t) ISR5Handler); + SetISR (6, (size_t) ISR6Handler); + SetISR (7, (size_t) ISR7Handler); + SetISRDF (8, (size_t) ISR8Handler); + SetISR (9, (size_t) ISR9Handler); + SetISR (10, (size_t) ISR10Handler); + SetISR (11, (size_t) ISR11Handler); + SetISR (12, (size_t) ISR12Handler); + SetISR (13, (size_t) ISR13Handler); + SetISR (14, (size_t) ISR14Handler); + SetISR (15, (size_t) ISR15Handler); + SetISR (16, (size_t) ISR16Handler); + SetISR (17, (size_t) ISR17Handler); + SetISRMC (18, (size_t) ISR18Handler); + SetISR (19, (size_t) ISR19Handler); + SetISR (20, (size_t) ISR20Handler); + SetISR (30, (size_t) ISR30Handler); + + for(size_t i = 1; i < 11; i++) { + if(i != 9) { + SetISR(i + 20, (size_t) ReservedISRHandler); + } + } + + SetISR(32, (size_t) IRQ0Handler); + SetISR(33, (size_t) IRQ1Handler); + SetISR(34, (size_t) IRQ2Handler); + SetISR(35, (size_t) IRQ3Handler); + SetISR(36, (size_t) IRQ4Handler); + SetISR(37, (size_t) IRQ5Handler); + SetISR(38, (size_t) IRQ6Handler); + SetISR(39, (size_t) IRQ7Handler); + SetISR(40, (size_t) IRQ8Handler); + SetISR(41, (size_t) IRQ9Handler); + SetISR(42, (size_t) IRQ10Handler); + SetISR(43, (size_t) IRQ11Handler); + SetISR(44, (size_t) IRQ12Handler); + SetISR(45, (size_t) IRQ13Handler); + SetISR(46, (size_t) IRQ14Handler); + SetISR(47, (size_t) IRQ15Handler); + + + //TODO: ISRs 32 to 256 + + WriteIDT(IDTData); + +} + + + diff --git a/chroma/system/drivers/keyboard.c b/chroma/system/drivers/keyboard.c new file mode 100644 index 0000000..2f5ec47 --- /dev/null +++ b/chroma/system/drivers/keyboard.c @@ -0,0 +1,115 @@ +#include + +char keys[128] = { + 0, 27, + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#', + 0, + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, + '*', 0, + ' ', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, + '-', + 0, + 0, + 0, + '+', + 0, + 0, + 0, + 0, + 0, + 0, 0, 0, + 0, + 0, + 0, +}; + + + +void UpdateKeyboard(uint8_t msg) { + + InputBuffer[0] = msg; + + switch(msg) { + case 0x0: + KbdFlags.Error = 1; + //ResendBuffer(); + break; + case 0xAA: + KbdFlags.SelfTest = 1; + break; + case 0xEE: + KbdFlags.Echo = 0; + KbdFlags.EchoCount = 2; + KbdEcho(); + break; + case 0xFA: + KbdFlags.ACK = 1; + //ProgressBuffer(); + break; + case 0xFC: + case 0xFD: + KbdFlags.SelfTest = 0; + KbdFlags.Error = 1; + //RestartKbd(); + break; + case 0xFE: + //ResendBuffer(); + break; + case 0xFF: + KbdFlags.Error = 1; + //ResendBuffer(); + break; + default: + break; + } + + + + if(msg & 0x80) { + + } else { + SerialPrintf("Key pressed %c\r\n", keys[msg]); + WriteChar(keys[msg]); + } + +} + +void KbdEcho() { + if(!KbdFlags.EchoCount) { + if(!KbdFlags.Echo) { + Send8042(0xEE); + } + } else { + KbdFlags.EchoCount = 0; + KbdFlags.Echo = 0; + } +} + +void Send8042(size_t info) { + for(size_t i = 0; i < 8; i++) { + unsigned char chr = (unsigned char) info; + if(chr != 0) { + WritePort(0x60, chr, 1); + WaitFor8042(); + } + } +} + +void WaitFor8042() { + + bool full = true; + while(full) { + full = ReadPort(0x64, 1) & 1; + } +} \ No newline at end of file diff --git a/chroma/system/interrupts.c b/chroma/system/interrupts.c new file mode 100644 index 0000000..e66e6d3 --- /dev/null +++ b/chroma/system/interrupts.c @@ -0,0 +1,378 @@ +/************************ + *** Team Kitty, 2019 *** + *** Sync *** + ***********************/ + +/* This file contains all of the ISR and IRQ + * (Interrupt Service Request) functions. + * + * As they use the GCC interrupt attribute, + * this file must be compiled without red- + * zone protection, thus all of these + * functions are in their own file to + * accomodate this. + * + * Additionally, the kernel now has SSE/AVX support. + * So this file and this file *alone* must be compiled with + * -mgeneral-regs-only + * + * Calling a function like so: + * + * __attribute__((interrupt)) isr1(registers_t* frame) {} + * + * allows the function to be used to serve + * interrupts - GCC compiles it under unique + * conditions, as it preserves the state of + * the processor and stack between execution, + * as well as using the IRET instruction to + * return to the middle of the previous function. + * + * There is also a version of the interrupt + * attribute which allows for error handlers, + * these having a size_t input as an error code. + */ + +#include +#include +#include + +typedef unsigned long long int uword_t; + +/* All of the ISR routines call this function for now. + ! This function is NOT leaf, and it might clobber the stack. + ! Be careful! +*/ +void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) { + /* Only the first 32 ISR/IRQs are reserved for exceptions by the CPU. We can handle up to 512 interrupts total, though. */ + if(Exception < 32) { + + FillScreen(0x0000FF00); + /* ExceptionStrings is an array of c-strings defined in kernel.h */ + + //serialPrint(ExceptionStrings[Exception]); + //serialPrint(" Exception.\r\n"); + //printf("%s exception!", ExceptionStrings[Exception]); + //panic(); + } +} + +/* The common handler for exceptions that throw error codes, which give us useful insight + into what went wrong. In pure Curle style, though, we just ignore the error code. */ +void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception) { + if(Exception < 32) { + + FillScreen(0x00FF0000); + + SerialPrintf("ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode); + + while(true) {} + //serialPrint(ExceptionStrings[Exception]); + //serialPrintf(" Exception. Context given: %d\r\n", Frame->ErrorCode); + //printf("%s exception. Context: %x", ExceptionStrings[Exception], Frame->ErrorCode); + //panic(); + + } + +} + +/* Likewise, this function is common to all IRQ handlers. It calls the assigned routine, + which was set up earlier by irq_install.*/ +void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) { + // First we need to define a function pointer.. + void (*Handler)(INTERRUPT_FRAME* Frame); + + // Tell the user we've got an interrupt in.. + //serial_print(0x3F8, "[INFO] Received IRQ: " + interrupt); + //printf("[INFO] Received IRQ: %x", Interrupt); + + /* We set all uninitialized routines to 0, so the if(handler) check here allows us to + safely tell whether we've actually got something for this IRQ. */ + Handler = IRQ_Handlers[Interrupt]; + // If there's something there, + if(Handler) { + SerialPrintf("IRQ %d raised!\r\n", Interrupt); + // Call the handler. + Handler(Frame); + } + /* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */ + if(Interrupt > 7) + WritePort(0xA0, 0x20, 1); + + /* In either case, we tell the Master PIC it's been read to receive any IRQ. */ + WritePort(0x20, 0x20, 1); +} + +/* However, in order to actually be able to receive IRQs, we need to remap the PICs. */ +void RemapIRQControllers() { + /* 0x20 is the Master PIC, + 0xA0 is the Slave PIC. */ + WritePort(0x20, 0x11, 1); + WritePort(0xA0, 0x11, 1); + WritePort(0x21, 0x20, 1); + WritePort(0xA1, 0x28, 1); + WritePort(0x21, 0x04, 1); + WritePort(0xA1, 0x02, 1); + WritePort(0x21, 0x01, 1); + WritePort(0xA1, 0x01, 1); + WritePort(0x21, 0x0, 1); + WritePort(0xA1, 0x0, 1); +} + +/* In order to actually handle the IRQs, though, we need to tell the kernel *where* the handlers are. */ +/* A simple wrapper that adds a function pointer to the IRQ array. */ +void InstallIRQ(int IRQ, void (*Handler)(INTERRUPT_FRAME* Frame)) { + IRQ_Handlers[IRQ] = Handler; +} + +/* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */ +void UninstallIRQHandler(int IRQ) { + IRQ_Handlers[IRQ] = 0; // 0 is used in the common check to make sure that the function is callable. + // This removes this irq from that check, ergo the function will no longer be called. +} + +void EmptyIRQ(INTERRUPT_FRAME* frame) { + // Flash the borders green, then back to blue + + for(size_t y = 0; y < bootldr.fb_height; y++) { + for(size_t x = 0; x < 20; x++) { + DrawPixel(x, y, 0x0000FF00); + } + + for(size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) { + DrawPixel(x, y, 0x0000FF00); + } + } + + for(size_t x = 0; x < bootldr.fb_width; x++) { + for(size_t y = 0; y < 20; y++) { + DrawPixel(x, y, 0x0000FF00); + } + + for(size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) { + DrawPixel(x, y, 0x0000FF00); + } + } + + for(size_t y = 0; y < bootldr.fb_height; y++) { + for(size_t x = 0; x < 20; x++) { + DrawPixel(x, y, 0x000000FF); + } + + for(size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) { + DrawPixel(x, y, 0x000000FF); + } + } + + for(size_t x = 0; x < bootldr.fb_width; x++) { + for(size_t y = 0; y < 20; y++) { + DrawPixel(x, y, 0x000000FF); + } + + for(size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) { + DrawPixel(x, y, 0x000000FF); + } + } +} + +static void KeyboardCallback(INTERRUPT_FRAME* frame) { + + uint8_t msg = ReadPort(0x60, 1); + + UpdateKeyboard(msg); + + WaitFor8042(); +} + +void InitInterrupts() { + size_t RFLAGS = ReadControlRegister('f'); + + if(!(RFLAGS & (1 << 9))) { + WriteControlRegister('f', RFLAGS | (1 << 9)); + } + + + InstallIRQ(1, &KeyboardCallback); + + Send8042(0xF002); + + __asm__ __volatile__("sti"); +} + + +/* The interrupt numbers, their meanings, and + * special information is laid out below: + * + * 0 - Divide by Zero + * 1 - Debug + * 2 - Non-Maskable + * 3 - Breakpoint + * 4 - Into Detected Overflow + * 5 - Out of Bounds + * 6 - Invalid Opcode + * 7 - No Coprocessor + * 8 - Double Fault * (With Error) + * 9 - Coprocessor Segment Overrun + * 10 - Bad TSS * (With Error) + * 11 - Segment Not Present * (With Error) + * 12 - Stack Fault * (With Error) + * 13 - General Protection Fault * (With Error) + * 14 - Page Fault * (With Error) + * 15 - Unknown Interrupt + * 16 - Coprocessor Fault + * 17 - Alignment Check + * 18 - Machine Check + * 19 to 31 - Reserved + */ + +__attribute__((interrupt)) void ISR0Handler(INTERRUPT_FRAME* Frame) { + + ISR_Common(Frame, 0); +} +__attribute__((interrupt)) void ISR1Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 1); +} +__attribute__((interrupt)) void ISR2Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 2); +} +__attribute__((interrupt)) void ISR3Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 3); +} +__attribute__((interrupt)) void ISR4Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 4); +} +__attribute__((interrupt)) void ISR5Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 5); +} +__attribute__((interrupt)) void ISR6Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 6); +} +__attribute__((interrupt)) void ISR7Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 7); +} +__attribute__((interrupt)) void ISR8Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 8); +} +__attribute__((interrupt)) void ISR9Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 9); +} +__attribute__((interrupt)) void ISR10Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 10); +} +__attribute__((interrupt)) void ISR11Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 11); +} +__attribute__((interrupt)) void ISR12Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 12); +} +__attribute__((interrupt)) void ISR13Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 13); // General Protection +} +__attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 14); +} +__attribute__((interrupt)) void ISR15Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 15); +} +__attribute__((interrupt)) void ISR16Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 16); +} +__attribute__((interrupt)) void ISR17Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 17); +} +__attribute__((interrupt)) void ISR18Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 18); +} +__attribute__((interrupt)) void ISR19Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 19); +} +__attribute__((interrupt)) void ISR20Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 20); +} +__attribute__((interrupt)) void ISR21Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 21); +} +__attribute__((interrupt)) void ISR22Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 22); +} +__attribute__((interrupt)) void ISR23Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 23); +} +__attribute__((interrupt)) void ISR24Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 24); +} +__attribute__((interrupt)) void ISR25Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 25); +} +__attribute__((interrupt)) void ISR26Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 26); +} +__attribute__((interrupt)) void ISR27Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 27); +} +__attribute__((interrupt)) void ISR28Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 28); +} +__attribute__((interrupt)) void ISR29Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 29); +} +__attribute__((interrupt)) void ISR30Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) { + ISR_Error_Common(Frame, ErrorCode, 30); +} +__attribute__((interrupt)) void ISR31Handler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 31); +} + +__attribute__((interrupt)) void ReservedISRHandler(INTERRUPT_FRAME* Frame) { + ISR_Common(Frame, 33); // if < 32, isn't handled. + // Effectively disables this ISR. +} + + +__attribute__((interrupt)) void IRQ0Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 0); +} +__attribute__((interrupt)) void IRQ1Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 1); // Keyboard handler +} +__attribute__((interrupt)) void IRQ2Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 2); +} +__attribute__((interrupt)) void IRQ3Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 3); +} +__attribute__((interrupt)) void IRQ4Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 4); +} +__attribute__((interrupt)) void IRQ5Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 5); +} +__attribute__((interrupt)) void IRQ6Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 6); +} +__attribute__((interrupt)) void IRQ7Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 7); +} +__attribute__((interrupt)) void IRQ8Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 8); +} +__attribute__((interrupt)) void IRQ9Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 9); +} +__attribute__((interrupt)) void IRQ10Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 10); +} +__attribute__((interrupt)) void IRQ11Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 11); +} +__attribute__((interrupt)) void IRQ12Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 12); +} +__attribute__((interrupt)) void IRQ13Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 13); +} +__attribute__((interrupt)) void IRQ14Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 14); +} +__attribute__((interrupt)) void IRQ15Handler(INTERRUPT_FRAME* Frame) { + IRQ_Common(Frame, 15); +} \ No newline at end of file diff --git a/chroma/system/mem.c b/chroma/system/mem.c new file mode 100644 index 0000000..849681d --- /dev/null +++ b/chroma/system/mem.c @@ -0,0 +1,124 @@ +#include + +uint8_t* Memory = ((uint8_t*)(&end)); +uint8_t MemoryStart; +uint32_t MemoryPages; +uint32_t MemoryLength; + +void InitMemoryManager() { + + size_t BootstructSize = bootldr.size; + size_t BootstructLoc = (size_t) &bootldr; + + size_t BootstructEnd = BootstructLoc + BootstructSize; + size_t MemorySize = 0, MemMapEntryCount = 0; + + MMapEnt* MemMap = &bootldr.mmap; + + while((size_t) MemMap < BootstructEnd) { + if(MMapEnt_IsFree(MemMap)) { + MemorySize += MMapEnt_Size(MemMap); + } + MemMapEntryCount++; + MemMap++; + } + + + MemoryPages = MemorySize / PAGE_SIZE; + MemoryLength = MemoryPages / PAGES_PER_BUCKET; + + if(MemoryLength * PAGES_PER_BUCKET < MemoryPages) + MemoryLength++; // Always round up + + + memset(Memory, 0, MemoryLength); + + MemoryStart = (uint8_t*)PAGE_ALIGN(((uint32_t)(Memory + MemoryLength))); + + + SerialPrintf("Initializing Memory.\r\n"); + + SerialPrintf("%u MB of memory detected.\r\n", (MemorySize / 1024) / 1024); + + for(size_t i = 0; i < MemoryLength; i++) { + if(Memory[i] != 0) + SerialPrintf("Memory at 0x%p is not empty!", Memory + i); + } + +} + +size_t AllocatePage() { + size_t FreePage = FirstFreePage(); + SET_BIT(FreePage); + return FreePage; +} + +void FreePage(size_t Page) { + UNSET_BIT(Page); +} + +size_t FirstFreePage() { + for(size_t i = 0; i < MemoryPages; i++) { + if(!READ_BIT(i)) + return i; + } + + SerialPrintf("Memory manager: Critical!\r\n"); + return (size_t) -1; +} + +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(); + + 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(); + + if(SecondPage != 1) + Passed = false; + + FreePage(FirstPage); + FirstPage = FirstFreePage(); + + if(FirstPage != 0) + Passed = false; + + if(Passed) + SerialPrintf("Memory test passed.\r\n"); + else { + SerialPrintf("Memory test failed.\r\n"); + SerialPrintf("First page %x, Second page %x.\r\n", FirstPage, SecondPage); + } +} + +void* memcpy(void* dest, void const* src, size_t len) { + unsigned char* dst = (unsigned char*) dest; + const unsigned char* source = (const unsigned char*) src; + + for(size_t i = 0; i < len; i++) { + dst[i] = source[i]; + } + + return dest; +} + +void* memset(void* dst, int src, size_t len) { + unsigned char* buf = (unsigned char*) dst; + + for(size_t i = 0; i < len; i++) { + buf[i] = (unsigned char) src; + } + + return dst; +} + + diff --git a/chroma/system/rw.c b/chroma/system/rw.c new file mode 100644 index 0000000..c6d3e03 --- /dev/null +++ b/chroma/system/rw.c @@ -0,0 +1,216 @@ +#include + +uint32_t ReadPort(uint16_t Port, int Length) { + uint32_t Data = 0; + uint16_t Data16 = 0; + uint8_t Data8 = 0; + + if(Length == 1) { + __asm__ __volatile__ ("inb %[address], %[value]" : [value] "=a" (Data8) : [address] "d" (Port) :); + Data = (uint32_t) Data8; + } else if(Length == 2) { + __asm__ __volatile__ ("inw %[address], %[value]" : [value] "=a" (Data16) : [address] "d" (Port) :); + Data = (uint32_t) Data16; + } else if(Length == 4) + __asm__ __volatile__ ("inl %[address], %[value]" : [value] "=a" (Data) : [address] "d" (Port) :); + //else + //printf("Readport: Invalid length\r\n"); + + return Data; +} + +uint32_t WritePort(uint16_t Port, uint32_t Data, int Length) { + if(Length == 1) + __asm__ __volatile__ ("outb %[value], %[address]" : : [value] "a" ((uint8_t) Data), [address] "d" (Port) :); + else if(Length == 2) + __asm__ __volatile__ ("outw %[value], %[address]" : : [value] "a" ((uint16_t) Data), [address] "d" (Port) :); + else if(Length == 4) + __asm__ __volatile__ ("outl %[value], %[address]" : : [value] "a" (Data), [address] "d" (Port) :); + //else + //printf("WritePort: Invalid length.\r\n"); + + return Data; +} + +size_t ReadModelSpecificRegister(size_t MSR) { + size_t RegHigh = 0, RegLow = 0; + + __asm__ __volatile__ ("rdmsr" : "=a" (RegLow), "=d" (RegHigh) : "c" (MSR) :); + + return RegHigh << 32 | RegLow; +} + +size_t WriteModelSpecificRegister(size_t MSR, size_t Data) { + size_t DataLow = 0, DataHigh = 0; + + DataLow = ((uint32_t*) &Data)[0]; + DataHigh = ((uint32_t*) &Data)[1]; + + __asm__ __volatile__ ("wrmsr" : : "a" (DataLow), "c" (MSR), "d" (DataHigh) :); + + return Data; +} + +uint32_t ReadVexMXCSR() { + uint32_t Data; + + __asm__ __volatile__ ("vstmxcsr %[dest]" : [dest] "=m" (Data) : :); + return Data; +} + +uint32_t WriteVexMXCSR(uint32_t Data) { + + __asm__ __volatile__ ("vldmxcsr %[src]" : : [src] "m" (Data) :); + return Data; +} + +uint32_t ReadMXCSR() { + uint32_t Data; + + __asm__ __volatile__ ("stmxcsr %[dest]" : [dest] "=m" (Data) : :); + return Data; +} + +uint32_t WriteMXCSR(uint32_t Data) { + + __asm__ __volatile__ ("ldmxcsr %[src]" : : [src] "m" (Data) :); + return Data; +} + +size_t ReadControlRegister(int CRX) { + + size_t Data; + + switch(CRX) { + case 0: + __asm__ __volatile__ ("mov %%cr0, %[dest]" : [dest] "=r" (Data) : :); + break; + case 1: + __asm__ __volatile__ ("mov %%cr1, %[dest]" : [dest] "=r" (Data) : :); + break; + case 2: + __asm__ __volatile__ ("mov %%cr2, %[dest]" : [dest] "=r" (Data) : :); + break; + case 3: + __asm__ __volatile__ ("mov %%cr3, %[dest]" : [dest] "=r" (Data) : :); + break; + case 4: + __asm__ __volatile__ ("mov %%cr4, %[dest]" : [dest] "=r" (Data) : :); + break; + case 8: + __asm__ __volatile__ ("mov %%cr8, %[dest]" : [dest] "=r" (Data) : :); + break; + case 'f': + __asm__ __volatile__ ("pushfq\n\t" "popq %[dest]" : [dest] "=r" (Data) : :); + break; + default: + break; + } + + return Data; +} + +size_t WriteControlRegister(int CRX, size_t Data) { + switch(CRX) { + case 0: + __asm__ __volatile__ ("mov %[dest], %%cr0" : : [dest] "r" (Data) : ); + break; + case 1: + __asm__ __volatile__ ("mov %[dest], %%cr1" : : [dest] "r" (Data) : ); + break; + case 2: + __asm__ __volatile__ ("mov %[dest], %%cr2" : : [dest] "r" (Data) : ); + break; + case 3: + __asm__ __volatile__ ("mov %[dest], %%cr3" : : [dest] "r" (Data) : ); + break; + case 4: + __asm__ __volatile__ ("mov %[dest], %%cr4" : : [dest] "r" (Data) : ); + break; + case 8: + __asm__ __volatile__ ("mov %[dest], %%cr8" : : [dest] "r" (Data) : ); + break; + case 'f': + __asm__ __volatile__ ("pushq %[dest]\n\t" "popfq" : : [dest] "r" (Data) : "cc"); + break; + default: + break; + } + + return Data; +} + +size_t ReadExtendedControlRegister(size_t XCRX) { + size_t RegHigh = 0, RegLow = 0; + + __asm__ __volatile__("xgetbv" : "=a" (RegLow), "=d" (RegHigh) : "c" (XCRX) :); + + return (RegHigh << 32 | RegLow); +} + +size_t WriteExtendedControlRegister(size_t XCRX, size_t Data){ + + __asm__ __volatile__("xsetbv" : : "a" ( ((uint32_t*) &Data)[0]), "c" (XCRX), "d" ( ((uint32_t*) &Data)[1] ) :); + return Data; +} + +size_t ReadXCS() { + size_t Data; + + __asm__ __volatile__("mov %%cs, %[dest]" : [dest] "=r" (Data) : :); + return Data; +} + +DESC_TBL ReadGDT() { + DESC_TBL GDTData = {0}; + + __asm__ __volatile__("sgdt %[dest]" : [dest] "=m" (GDTData) : :); + + return GDTData; +} + +void WriteGDT(DESC_TBL GDTData) { + + __asm__ __volatile__("lgdt %[src]" : : [src] "m" (GDTData) :); +} + +DESC_TBL ReadIDT() { + DESC_TBL IDTData = {0}; + + __asm__ __volatile__("sidt %[dest]" : [dest] "=m" (IDTData) : :); + + return IDTData; +} + +void WriteIDT(DESC_TBL IDTData) { + + __asm__ __volatile__("lidt %[src]" : : [src] "m" (IDTData) :); +} + +uint16_t ReadLDT() { + uint16_t LDTData; + + __asm__ __volatile__("sldt %[dest]" : [dest] "=m" (LDTData) : :); + + return LDTData; +} + +void WriteLDT(uint16_t LDTData) { + + __asm__ __volatile__("lldt %[src]" : : [src] "m" (LDTData) :); +} + +uint16_t ReadTSR() { + uint16_t TSRData; + + __asm__ __volatile__("str %[dest]" : [dest] "=m" (TSRData) : :); + + return TSRData; +} + +void WriteTSR(uint16_t TSRData) { + + __asm__ __volatile__("ltr %[src]" : : [src] "m" (TSRData) :); +} + + diff --git a/chroma/system/serial.c b/chroma/system/serial.c new file mode 100644 index 0000000..10e8856 --- /dev/null +++ b/chroma/system/serial.c @@ -0,0 +1,40 @@ +#include + +#define SERIAL_DATA(base) (base) +#define SERIAL_DLAB(base) (base + 1) +#define SERIAL_FIFO(base) (base + 2) +#define SERIAL_LINE(base) (base + 3) +#define SERIAL_MODEM(base) (base + 4) +#define SERIAL_LINE_STATUS(base) (base + 5) +#define COM1 0x3F8 + +void InitSerial() { + // Disable interrupts + WritePort(SERIAL_DLAB(COM1), 0x00, 1); + // Set baud rate to /3 (115200 bits/sec) + WritePort(SERIAL_LINE(COM1), 0x80, 1); + WritePort(SERIAL_DATA(COM1), 0x03, 1); + WritePort(SERIAL_DLAB(COM1), 0x00, 1); + // Set serial to 8 bits, no parity and one stop bit. + WritePort(SERIAL_LINE(COM1), 0x03, 1); + // Enable FIFO and clear all buffers + WritePort(SERIAL_FIFO(COM1), 0xC7, 1); + // Enable IRQs, set RTS and DSR + WritePort(SERIAL_MODEM(COM1), 0x03, 1); +} + + +int CheckSerial() { + return ReadPort(SERIAL_LINE_STATUS(COM1), 1); +} + +void WriteSerialChar(const char chr) { + while(!(CheckSerial() & 0x20)); + WritePort(COM1, chr, 1); +} + +void WriteSerialString(const char* str, size_t len) { + for(size_t i = 0; i < len; i++) { + WriteSerialChar(str[i]); + } +} \ No newline at end of file diff --git a/chroma/video/draw.c b/chroma/video/draw.c new file mode 100644 index 0000000..b2aecac --- /dev/null +++ b/chroma/video/draw.c @@ -0,0 +1,264 @@ +#include +#include + +#define FONT bitfont_latin + +static size_t strlen(const char* String) { + size_t Len = 0; + while(String[Len] != '\0') { + Len++; + } + return Len; +} + +typedef struct { + uint32_t charHeight; + uint32_t charWidth; + uint32_t charFGColor; + uint32_t charHLColor; + uint32_t charBGColor; + uint32_t minX; + uint32_t minY; + uint32_t charScale; + size_t charPosX; + size_t charPosY; + size_t charsPerRow; + size_t rowsPerScrn; + uint32_t scrlMode; +} PRINTINFO; + +PRINTINFO PrintInfo = {0}; + +void InitPrint() { + PrintInfo.charHeight = 8; + PrintInfo.charWidth = 8; + PrintInfo.charFGColor = 0x00FFFFFF; + PrintInfo.charHLColor = 0x00000000; + PrintInfo.charBGColor = 0x00000000; + + PrintInfo.charScale = 2; + + PrintInfo.charPosX = 0; + PrintInfo.charPosY = 0; + + PrintInfo.scrlMode = 0; + + PrintInfo.charsPerRow = bootldr.fb_width / (PrintInfo.charScale * PrintInfo.charWidth) - 5; + PrintInfo.rowsPerScrn = bootldr.fb_height / (PrintInfo.charScale * PrintInfo.charHeight); + SerialPrintf("A single character is %ux%u pixels.\r\n", PrintInfo.charScale * PrintInfo.charWidth, PrintInfo.charScale * PrintInfo.charHeight); + SerialPrintf("The screen is %ux%u, meaning you can fit %ux%u characters on screen.\r\n", bootldr.fb_width, bootldr.fb_height, PrintInfo.charsPerRow, PrintInfo.rowsPerScrn); + +} + +static void DrawChar(const char character, size_t x, size_t y) { + x = x + PrintInfo.charPosX * (PrintInfo.charScale * PrintInfo.charWidth); + y = y + PrintInfo.charPosY * (PrintInfo.charScale * PrintInfo.charHeight); + + uint32_t Y = PrintInfo.charWidth >> 3, X = 0; + + if((PrintInfo.charWidth & 0x7) != 0) { + Y++; + } + + for(uint32_t Row = 0; Row < PrintInfo.charHeight; Row++) { + + + for(uint32_t Bit = 0; Bit < PrintInfo.charWidth; Bit++) { + if ( ((Bit & 0x7) == 0) && (Bit > 0)) { + 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++) { + + 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; + + // 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. + } + } + } else { + // We need to draw the pixel transparently.. + for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { + for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { + if(PrintInfo.charHLColor != 0xFF000000) { + 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; + if( y == 0 && x == 0){ + SerialPrintf("Writing first pixel at %x\r\n", offset); + } + + *(uint32_t*)(&fb + offset *4) + = PrintInfo.charHLColor; + + } + } + } + } + } + } + + + + + /* + uint32_t Y = PrintInfo.charWidth >> 3, X = 0; + + + if((PrintInfo.charWidth & 0x7) != 0) { + Y++; + } + + for(size_t CharRow = 0; CharRow < PrintInfo.charHeight; CharRow++) { + for(size_t CharPixel = 0; CharPixel < PrintInfo.charWidth; CharPixel++) { + if( CharPixel && (CharPixel & 0x7) == 0) { + X++; + } + + for(size_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) { + for(size_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) { + + if(FONT[character][CharRow * Y + X] >> (CharRow & 0x7) & 1) { + + size_t offset = (y * bootldr.fb_width + x) + + (PrintInfo.charScale * (CharRow * bootldr.fb_width + CharPixel)) + + (ScaleY * (bootldr.fb_width + ScaleX)); + + + *((uint32_t*) (&fb + offset * 4)) + = PrintInfo.charFGColor; + //DrawPixel(x * PrintInfo.charWidth + X, Y + y + PrintInfo.charHeight, 0x00FF0000); + } + } + } + } + } + + uint32_t Y = PrintInfo.charWidth >> 3, X = 0; + + + if((PrintInfo.charWidth & 0x7) != 0) { + Y++; + } + + for(uint32_t Row = 0; Row < PrintInfo.charHeight; Row++) { + for(uint32_t Bit = 0; Bit < PrintInfo.charWidth; Bit++) { + if( ((Bit & 0x7) == 0) && (Bit > 0)) + X++; + + 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) { + size_t offset = (y * bootldr.fb_width + x) + + (PrintInfo.charScale * (Row * bootldr.fb_width + Bit)) + + (ScaleY * (bootldr.fb_width + ScaleX)); + SerialPrintf("Drawing pixel at offset %x, at y %d, x %d, row %d, bit %d with scaley %d and scalex %d. charScale %d and charWidth %d, making a charLength %d.\r\n", offset, y, x, Row, Bit, ScaleX, ScaleY, PrintInfo.charScale, PrintInfo.charWidth, PrintInfo.charScale * PrintInfo.charWidth); + + *((uint32_t*) (&fb + offset * 4)) + = PrintInfo.charFGColor; + } else { + if(PrintInfo.charHLColor != 0xFF000000) { + size_t offset = (y * bootldr.fb_width + x) + + (PrintInfo.charScale * (Row * bootldr.fb_width + Bit)) + + (ScaleY * (bootldr.fb_width + ScaleX)); + SerialPrintf("Drawing pixel at offset %x\r\n", offset); + + *((uint32_t*) (&fb + offset * 4)) + = PrintInfo.charHLColor; + } + } + } + } + } + } + + */ +} + +void DrawPixel(uint32_t x, uint32_t y, uint32_t color) { + if(x > bootldr.fb_width) { + DrawPixel(x - bootldr.fb_width, y + (PrintInfo.charHeight * PrintInfo.charScale), color); + //FillScreen(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); + } +} + +void FillScreen(uint32_t color) { + for(size_t y = 0; y < bootldr.fb_height; y++) { + for(size_t x = 0; x < bootldr.fb_width; x++) { + DrawPixel(x, y, color); + } + } +} + +static void ProgressCursorS(size_t Steps) { + if(PrintInfo.charPosX + Steps > PrintInfo.charsPerRow) { + PrintInfo.charPosX = 0; + size_t Rows = Steps / PrintInfo.charsPerRow; + if(PrintInfo.charPosY + Rows > PrintInfo.rowsPerScrn) { + size_t RowsLeft = PrintInfo.rowsPerScrn - PrintInfo.charPosY; + ProgressCursorS((Rows - RowsLeft) * PrintInfo.charsPerRow); + } else { + PrintInfo.charPosY++; + } + } else { + PrintInfo.charPosX += Steps; + } +} + +static void Newline() { + ProgressCursorS(PrintInfo.charsPerRow); +} + +static void ProgressCursor() { + ProgressCursorS(1); +} + +void WriteChar(const char character) { + + //size_t y = PrintInfo.charPos / RowsWidth * (PrintInfo.charScale * PrintInfo.charHeight); + //size_t x = (PrintInfo.charPos % RowsWidth) * (PrintInfo.charScale * PrintInfo.charWidth); + + switch(character) { + case '\b': + if(PrintInfo.charPosX - 1 == 0) { + if(PrintInfo.charPosY - 1 == 0) { + PrintInfo.charPosY = 0; + } else { + PrintInfo.charPosY--; + } + } else { + PrintInfo.charPosX = 0; + } + break; + case '\n': + Newline(); + break; + default: + DrawChar(character, PrintInfo.charPosX, PrintInfo.charPosY); + + ProgressCursor(); + break; + } + +} + + + +void WriteString(const char* string) { + for(int i = 0; i < strlen(string); i++) { + WriteChar(string[i]); + } +} diff --git a/chroma/video/print.c b/chroma/video/print.c new file mode 100644 index 0000000..2a7ba12 --- /dev/null +++ b/chroma/video/print.c @@ -0,0 +1,109 @@ +#include + +static size_t strlen(const char* String) { + size_t Len = 0; + while(String[Len] != '\0') { + Len++; + } + return Len; +} + +static void NumToStr(char* Buffer, size_t Num, size_t Base) { + size_t Temp, i = 0, j = 0; + + do { + Temp = Num % Base; + Buffer[i++] = (Temp < 10) ? (Temp + '0') : (Temp + 'a' - 10); + } while (Num /= Base); + + Buffer[i--] = 0; + + for(j = 0; j < i; j++, i--) { + Temp = Buffer[j]; + Buffer[j] = Buffer[i]; + Buffer[i] = Temp; + } + +} + +int SerialPrintf(const char* restrict Format, ...) { + va_list Parameters; + va_start(Parameters, Format); + + int CharsWritten = 0; + size_t Base, Num; + + char BufferStr[512] = {0}; + + while(*Format != '\0') { + size_t Limit = UINT64_MAX - CharsWritten; + + if(*Format == '%') { + if(*(++Format) == '%') + Format++; + + + switch(*Format) { + case 'c': + Format++; + + char c = (char) va_arg(Parameters, int); + + WriteSerialString(&c, sizeof(c)); + + CharsWritten++; + break; + case 's': + Format++; + const char* Str = va_arg(Parameters, char*); + + size_t Len = strlen(Str); + + if(Limit < Len) + return -1; + + WriteSerialString(Str, Len); + + CharsWritten += Len; + break; + case 'd': + case 'u': + case 'p': + case 'x': + + Num = va_arg(Parameters, size_t); + Base = 0; + + + if(*Format == 'd' || *Format == 'u') { + Base = 10; // Decimal & Unsigned are base 10 + } else { + Base = 16; // Hex and Ptr are base 16 + } + Format++; + + NumToStr(BufferStr, Num, Base); + Len = strlen(BufferStr); + + WriteSerialString(BufferStr, Len); + + CharsWritten += Len; + break; + //case 'p': + //uint8_t Base = 16; + //size_t Dest = (uintptr_t) va_arg(Parameters, void*); + default: + WriteSerialString("%u", 2); + break; + } + + } else { + WriteSerialChar(*Format); + Format++; + } + } + + va_end(Parameters); + return CharsWritten; +} + diff --git a/chroma/video/tty.c b/chroma/video/tty.c new file mode 100644 index 0000000..98af3c8 --- /dev/null +++ b/chroma/video/tty.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +#include + +static const size_t TERM_WIDTH = 80; +static const size_t TERM_HEIGHT = 25; + +size_t TERM_ROW; +size_t TERM_COL; +uint8_t TERM_COLOR; + +uint16_t* TERM_BUFFER; + +void Term_Init(void) { + + TERM_ROW = 0; + TERM_COL = 0; + TERM_COLOR = VGACharColor(VGA_COLOR_LIGHTGREY, VGA_COLOR_BLACK); + + TERM_BUFFER = (uint16_t*) 0xB8000; + + for(size_t y = 0; y < TERM_HEIGHT; y++) { + for(size_t x = 0; x < TERM_WIDTH; x++) { + const size_t index = y * TERM_WIDTH + x; + TERM_BUFFER[index] = VGAChar(' ', TERM_COLOR); + } + } +} + +void Term_SetColor(uint8_t color) { + TERM_COLOR = color; +} + +void Term_PutVGAChar(char c, uint8_t color, size_t x, size_t y) { + const size_t index = y * TERM_WIDTH + x; + TERM_BUFFER[index] = VGAChar(c, color); +} + +void Term_PutChar(char c) { + Term_PutVGAChar(c, TERM_COLOR, TERM_COL, TERM_ROW); + + if(++TERM_COL == TERM_WIDTH) { + TERM_COL = 0; + if(++TERM_ROW == TERM_HEIGHT) + TERM_ROW = 0; + } +} + +void Term_Write(const char* str, size_t len) { + for(size_t i = 0; i < len; i++) + Term_PutChar(str[i]); +} + +void Term_WriteString(const char* str) { + Term_Write(str, strlen(str)); +} + diff --git a/iso/boot/bootloader b/iso/boot/bootloader new file mode 100644 index 0000000000000000000000000000000000000000..a6e5838de62e4dca48c18f16c0b68b3004c37893 GIT binary patch literal 11776 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 literal 0 HcmV?d00001 diff --git a/iso/boot/grub/grub.cfg b/iso/boot/grub/grub.cfg new file mode 100644 index 0000000..16868b3 --- /dev/null +++ b/iso/boot/grub/grub.cfg @@ -0,0 +1,4 @@ +menuentry "Sync" { + multiboot /boot/bootloader + module /boot/initrd +} diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..71e23fd --- /dev/null +++ b/linker.ld @@ -0,0 +1,31 @@ + +mmio = 0xfffffffff8000000; +fb = 0xfffffffffc000000; + +PHDRS +{ + boot PT_LOAD; +} + +SECTIONS +{ + . = 0xffffffffffe00000; + bootldr = .; . += 4096; + environment = .; . += 4096; + + + .text : { + KEEP(*(.text.boot)) *(.text .text.*) + *(.rodata .rodata.*) + *(.data .data.*) + } :boot + .bss (NOLOAD) : { + . = ALIGN(16); + *(.bss .bss.*) + *(COMMON) + } :boot + + /DISCARD/ : { *(.eh_frame) *(.comment) } + + end = .; +}