├── src ├── libc │ ├── .gitignore │ ├── include │ │ ├── sys │ │ │ └── cdefs.h │ │ ├── stdlib.h │ │ ├── string.h │ │ └── stdio.h │ ├── stdio │ │ ├── puts.c │ │ ├── putchar.c │ │ └── printf.c │ ├── arch │ │ ├── arm │ │ │ └── make.config │ │ └── i386 │ │ │ └── make.config │ ├── string │ │ ├── strlen.c │ │ ├── memset.c │ │ ├── memcpy.c │ │ ├── memcmp.c │ │ ├── strncpy.c │ │ └── memmove.c │ ├── stdlib │ │ └── abort.c │ ├── security │ │ └── stack_smash_protector.c │ └── Makefile └── kernel │ ├── include │ ├── kernel │ │ ├── main.h │ │ ├── control.h │ │ ├── display │ │ │ ├── termcolor.h │ │ │ └── color.h │ │ ├── panic.h │ │ ├── version.h │ │ ├── types.h │ │ ├── arch │ │ │ ├── i386 │ │ │ │ ├── ports.h │ │ │ │ ├── drivers │ │ │ │ │ ├── serial_log.h │ │ │ │ │ ├── textmode_log.h │ │ │ │ │ ├── bga_log.h │ │ │ │ │ └── bga.h │ │ │ │ └── gdt.h │ │ │ └── arm │ │ │ │ └── integrator-cp │ │ │ │ └── drivers │ │ │ │ └── serial_log.h │ │ ├── log.h │ │ └── boot │ │ │ └── multiboot.h │ └── data │ │ └── font-unscii.h │ ├── arch │ ├── arm │ │ └── integrator-cp │ │ │ ├── halt.s │ │ │ ├── linker.ld │ │ │ ├── make.config │ │ │ ├── crt │ │ │ ├── crtn.c │ │ │ └── crti.c │ │ │ ├── boot.s │ │ │ ├── arch_start.cpp │ │ │ └── drivers │ │ │ └── serial_log.cpp │ └── i386 │ │ ├── make.config │ │ ├── gdt_asm.s │ │ ├── pc │ │ ├── halt.S │ │ ├── crt │ │ │ ├── crtn.S │ │ │ └── crti.S │ │ ├── make.config │ │ ├── linker.ld │ │ ├── ports.cpp │ │ ├── arch_start.cpp │ │ ├── log.cpp │ │ ├── drivers │ │ │ ├── serial_log.cpp │ │ │ ├── textmode_log.cpp │ │ │ ├── bga_log.cpp │ │ │ └── bga.cpp │ │ ├── boot.S │ │ └── memory.cpp │ │ └── gdt.cpp │ ├── main.cpp │ ├── version.cpp │ ├── panic.cpp │ ├── log.cpp │ ├── Makefile │ └── boot_log_renderer.cpp ├── scripts ├── default-host.sh ├── target-triplet-to-arch.sh └── config.sh ├── gdbinit ├── .gdbinit ├── clang-format.sh ├── .gitattributes ├── qemu-arm.sh ├── .clang-format ├── qemu.sh ├── clean.sh ├── sysroot.sh ├── iso.sh ├── .gitignore ├── README.md ├── docs └── Scheduling.md └── bochsrc /src/libc/.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.d 3 | *.o 4 | -------------------------------------------------------------------------------- /scripts/default-host.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo i686-elf 3 | -------------------------------------------------------------------------------- /gdbinit: -------------------------------------------------------------------------------- 1 | file kernel/nyx.elf 2 | target remote localhost:1234 -------------------------------------------------------------------------------- /src/kernel/include/kernel/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | int kmain(); -------------------------------------------------------------------------------- /.gdbinit: -------------------------------------------------------------------------------- 1 | file src/kernel/kernel.elf 2 | break kernel_start 3 | target remote :1234 -------------------------------------------------------------------------------- /clang-format.sh: -------------------------------------------------------------------------------- 1 | find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\|h\)' -exec clang-format -style=file -i {} \; 2 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/control.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern "C"[[noreturn]] void kernel_halt_system(); -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.{cmd,[cC][mM][dD]} text eol=crlf 3 | *.{bat,[bB][aA][tT]} text eol=crlf -------------------------------------------------------------------------------- /src/libc/include/sys/cdefs.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYS_CDEFS_H 2 | #define _SYS_CDEFS_H 1 3 | 4 | #define __nyx_libc 1 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/libc/stdio/puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int puts(const char* string) { 4 | return printf("%s\n", string); 5 | } 6 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/display/termcolor.h: -------------------------------------------------------------------------------- 1 | 2 | #define TERMINAL_TRANSPARENT 0xFF 3 | 4 | struct TermColor { 5 | char color; 6 | }; -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/halt.s: -------------------------------------------------------------------------------- 1 | .section .text 2 | .global kernel_halt_system 3 | kernel_halt_system: 4 | 5 | .continue_halt: 6 | -------------------------------------------------------------------------------- /qemu-arm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | . ./build.sh 4 | qemu-system-arm -kernel build/sysroot/boot/kernel.elf -machine integratorcp -m 128 -serial stdio 5 | -------------------------------------------------------------------------------- /src/libc/arch/arm/make.config: -------------------------------------------------------------------------------- 1 | ARCH_CFLAGS= 2 | ARCH_CPPFLAGS= 3 | KERNEL_ARCH_CFLAGS= 4 | KERNEL_ARCH_CPPFLAGS= 5 | 6 | ARCH_FREEOBJS=\ 7 | 8 | ARCH_HOSTEDOBJS=\ 9 | -------------------------------------------------------------------------------- /src/libc/arch/i386/make.config: -------------------------------------------------------------------------------- 1 | ARCH_CFLAGS= 2 | ARCH_CPPFLAGS= 3 | KERNEL_ARCH_CFLAGS= 4 | KERNEL_ARCH_CPPFLAGS= 5 | 6 | ARCH_FREEOBJS=\ 7 | 8 | ARCH_HOSTEDOBJS=\ 9 | -------------------------------------------------------------------------------- /src/libc/string/strlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t strlen(const char* str) { 4 | size_t len = 0; 5 | while (str[len]) 6 | len++; 7 | return len; 8 | } 9 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | IndentWidth: '4' 4 | AllowShortFunctionsOnASingleLine: Empty 5 | BreakConstructorInitializersBeforeComma: false 6 | ColumnLimit: 0 -------------------------------------------------------------------------------- /scripts/target-triplet-to-arch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if echo "$1" | grep -Eq 'i[[:digit:]]86-'; then 3 | echo i386 4 | else 5 | echo "$1" | grep -Eo '^[[:alnum:]_]*' 6 | fi 7 | -------------------------------------------------------------------------------- /qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | . ./iso.sh 4 | 5 | qemu-system-$(./scripts/target-triplet-to-arch.sh $HOST) -cdrom build/artifact.iso -vga std -machine q35 -cpu coreduo -m 256M -boot once=d -------------------------------------------------------------------------------- /src/kernel/arch/i386/make.config: -------------------------------------------------------------------------------- 1 | KERNEL_ISA_CFLAGS= 2 | KERNEL_ISA_CPPFLAGS= 3 | KERNEL_ISA_LDFLAGS= 4 | KERNEL_ISA_LIBS= 5 | KERNEL_ISA_OBJS=\ 6 | $(ISA_DIR)/gdt.o \ 7 | $(ISA_DIR)/gdt_asm.o -------------------------------------------------------------------------------- /src/kernel/include/kernel/panic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void panic(const char* s); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | . ./scripts/config.sh 4 | 5 | for PROJECT in $PROJECTS; do 6 | (cd src/$PROJECT && $MAKE clean) 7 | done 8 | 9 | echo "[CLEAN] build/" 10 | 11 | rm -rf ./build/ 12 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/gdt_asm.s: -------------------------------------------------------------------------------- 1 | 2 | .global gdt_flush 3 | .intel_syntax noprefix 4 | 5 | gdt_flush: 6 | mov eax, [esp+4] 7 | lgdt [eax] 8 | 9 | jmp 0x08:.flush 10 | .flush: 11 | ret 12 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/halt.S: -------------------------------------------------------------------------------- 1 | .section .text 2 | .global kernel_halt_system 3 | .type kernel_halt_system, @function 4 | kernel_halt_system: 5 | cli 6 | .continue_halt: 7 | hlt 8 | jmp .continue_halt 9 | -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY (_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x10000; 6 | .text : { *(.text*) *(.rodata*) } 7 | .data : { *(.data*) } 8 | .bss : { *(.bss*) *(COMMON*) } 9 | } -------------------------------------------------------------------------------- /sysroot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | . ./scripts/config.sh 4 | 5 | mkdir -p "$SYSROOT" 6 | 7 | for PROJECT in $SYSTEM_HEADER_PROJECTS; do 8 | (cd src/$PROJECT && DESTDIR="$SYSROOT" $MAKE install-headers) 9 | done 10 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void kernel_print_version(); 4 | 5 | #ifndef ARCH_NAME 6 | #define ARCH_NAME "unknown" 7 | #endif 8 | 9 | #ifndef PLATFORM_NAME 10 | #define PLATFORM_NAME "unknown" 11 | #endif -------------------------------------------------------------------------------- /src/libc/string/memset.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void* memset(void* bufptr, int value, size_t size) { 4 | unsigned char* buf = (unsigned char*) bufptr; 5 | for (size_t i = 0; i < size; i++) 6 | buf[i] = (unsigned char) value; 7 | return bufptr; 8 | } 9 | -------------------------------------------------------------------------------- /src/kernel/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int kmain() { 5 | g_log.Log(LOG_NOTICE, "kernel", "Entered Kernel Main."); 6 | //while (true) { 7 | //} 8 | panic("Kernel main exited..."); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/make.config: -------------------------------------------------------------------------------- 1 | KERNEL_ARCH_CFLAGS= 2 | KERNEL_ARCH_CPPFLAGS= 3 | KERNEL_ARCH_LDFLAGS= 4 | KERNEL_ARCH_LIBS= 5 | KERNEL_ARCH_OBJS=\ 6 | $(ARCHDIR)/boot.o \ 7 | $(ARCHDIR)/halt.o \ 8 | $(ARCHDIR)/arch_start.o \ 9 | $(ARCHDIR)/drivers/serial_log.o -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/crt/crtn.S: -------------------------------------------------------------------------------- 1 | .section .init 2 | /* gcc will nicely put the contents of crtend.o's .init section here. */ 3 | popl %ebp 4 | ret 5 | 6 | .section .fini 7 | /* gcc will nicely put the contents of crtend.o's .fini section here. */ 8 | popl %ebp 9 | ret 10 | -------------------------------------------------------------------------------- /src/libc/include/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDLIB_H 2 | #define _STDLIB_H 1 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | __attribute__((__noreturn__)) void abort(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/kernel/version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void kernel_print_version() { 5 | g_log.Log(LOG_INFO, "kernel", "Cedille v. 0.0.0.1"); 6 | g_log.Log(LOG_INFO, "kernel", "Written by Corwin McKnight"); 7 | g_log.Log(LOG_INFO, "kernel", "Running on: %s %s", ARCH_NAME, PLATFORM_NAME); 8 | } -------------------------------------------------------------------------------- /src/kernel/include/kernel/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef uintptr_t virtual_address_t; 6 | typedef uintptr_t phys_address_t; 7 | 8 | // Define these in each platforms memory.cpp 9 | 10 | virtual_address_t kPhysToVirtual(phys_address_t x); 11 | phys_address_t kVirtualToPhys(virtual_address_t x); -------------------------------------------------------------------------------- /src/kernel/include/kernel/display/color.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Color { 4 | unsigned char r; 5 | unsigned char g; 6 | unsigned char b; 7 | 8 | Color(unsigned char r, unsigned char g, unsigned char b) { 9 | this->r = r; 10 | this->g = g; 11 | this->b = b; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/crt/crtn.c: -------------------------------------------------------------------------------- 1 | /* crtn.c for ARM - BPABI - use -std=c99 */ 2 | typedef void (*func_ptr)(void); 3 | 4 | func_ptr _init_array_end[0] __attribute__((used, section(".init_array"), aligned(sizeof(func_ptr)))) = {}; 5 | func_ptr _fini_array_end[0] __attribute__((used, section(".fini_array"), aligned(sizeof(func_ptr)))) = {}; -------------------------------------------------------------------------------- /src/libc/stdio/putchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if defined(__is_libk) 4 | 5 | void kernel_log_char(char c); 6 | 7 | #endif 8 | 9 | int putchar(int ic) 10 | { 11 | #if defined(__is_libk) 12 | kernel_log_char((char)ic); 13 | #else 14 | // TODO: Implement stdio and the write system call. 15 | #endif 16 | return ic; 17 | } 18 | -------------------------------------------------------------------------------- /src/libc/string/memcpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void *memcpy(void *restrict dstptr, const void *restrict srcptr, size_t size) 4 | { 5 | unsigned char *dst = (unsigned char *)dstptr; 6 | const unsigned char *src = (const unsigned char *)srcptr; 7 | for (size_t i = 0; i < size; i++) 8 | dst[i] = src[i]; 9 | return dstptr; 10 | } 11 | -------------------------------------------------------------------------------- /src/libc/string/memcmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int memcmp(const void* aptr, const void* bptr, size_t size) { 4 | const unsigned char* a = (const unsigned char*) aptr; 5 | const unsigned char* b = (const unsigned char*) bptr; 6 | for (size_t i = 0; i < size; i++) { 7 | if (a[i] < b[i]) 8 | return -1; 9 | else if (b[i] < a[i]) 10 | return 1; 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/kernel/panic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const char *panicstr; 5 | 6 | extern "C" [[noreturn]] void panic(const char *s) { 7 | // Save string if no terminal access... 8 | panicstr = s; 9 | 10 | // Log error to console 11 | g_log.Log(LOG_PANIC, "panic", s); 12 | 13 | // Halt the system: 14 | kernel_halt_system(); 15 | } -------------------------------------------------------------------------------- /src/libc/string/strncpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *strncpy(char *destination, const char *source, size_t n) 4 | { 5 | size_t size = strlen(source); 6 | if (size > n) 7 | { 8 | size = n; 9 | } 10 | if (size != n) 11 | { 12 | memset(destination + size, '\0', n - size); 13 | } 14 | 15 | return memcpy(destination, source, size); 16 | } -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/crt/crti.S: -------------------------------------------------------------------------------- 1 | .section .init 2 | .global _init 3 | .type _init, @function 4 | _init: 5 | push %ebp 6 | movl %esp, %ebp 7 | /* gcc will nicely put the contents of crtbegin.o's .init section here. */ 8 | 9 | .section .fini 10 | .global _fini 11 | .type _fini, @function 12 | _fini: 13 | push %ebp 14 | movl %esp, %ebp 15 | /* gcc will nicely put the contents of crtbegin.o's .fini section here. */ 16 | -------------------------------------------------------------------------------- /src/libc/string/memmove.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void* memmove(void* dstptr, const void* srcptr, size_t size) { 4 | unsigned char* dst = (unsigned char*) dstptr; 5 | const unsigned char* src = (const unsigned char*) srcptr; 6 | if (dst < src) { 7 | for (size_t i = 0; i < size; i++) 8 | dst[i] = src[i]; 9 | } else { 10 | for (size_t i = size; i != 0; i--) 11 | dst[i-1] = src[i-1]; 12 | } 13 | return dstptr; 14 | } 15 | -------------------------------------------------------------------------------- /iso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | . ./build.sh 4 | 5 | mkdir -p ./build/isodir 6 | mkdir -p ./build/isodir/boot 7 | mkdir -p ./build/isodir/boot/grub 8 | 9 | cp -r ./build/sysroot/* ./build/isodir/ 10 | 11 | cat > ./build/isodir/boot/grub/grub.cfg << EOF 12 | set default=0 13 | set timeout=0 14 | menuentry "Cedille" { 15 | multiboot /boot/kernel.elf 16 | } 17 | EOF 18 | 19 | grub-mkrescue -o build/artifact.iso ./build/isodir -quiet 20 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/i386/ports.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /// Outputs a byte to port 5 | void outb(uint16_t port, uint8_t value); 6 | /// Outputs a word to port 7 | void outw(uint16_t port, uint16_t value); 8 | /// Outputs a long to port 9 | void outl(uint16_t port, uint32_t value); 10 | /// Inputs a byte from port 11 | uint8_t inb(uint16_t port); 12 | /// Inputs a word from port 13 | uint16_t inw(uint16_t port); 14 | -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/boot.s: -------------------------------------------------------------------------------- 1 | interrupt_vector_table: 2 | b . @ Reset 3 | b . 4 | b . @ SWI instruction 5 | b . 6 | b . 7 | b . 8 | b . 9 | b . 10 | 11 | .comm stack, 0x10000 @ Reserve 64k stack in the BSS 12 | _start: 13 | .globl _start 14 | ldr sp, =stack+0x10000 @ Set up the stack 15 | bl _init @ Call initialization 16 | bl kernel_start @ Jump to the main function 17 | 1: 18 | b 1b @ Halt 19 | -------------------------------------------------------------------------------- /src/libc/stdlib/abort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #if defined(__is_libk) 5 | #include 6 | #endif 7 | 8 | __attribute__((__noreturn__)) void abort(void) 9 | { 10 | #if defined(__is_libk) 11 | // TODO: Add proper kernel panic. 12 | panic("abort() was called!"); 13 | #else 14 | // TODO: Abnormally terminate the process as if by SIGABRT. 15 | printf("abort()!\n"); 16 | #endif 17 | while (1) 18 | { 19 | } 20 | __builtin_unreachable(); 21 | } 22 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/make.config: -------------------------------------------------------------------------------- 1 | KERNEL_PLATFORM_CFLAGS= 2 | KERNEL_PLATFORM_CPPFLAGS= 3 | KERNEL_PLATFORM_LDFLAGS= 4 | KERNEL_PLATFORM_LIBS= 5 | KERNEL_PLATFORM_OBJS=\ 6 | $(PLATFORM_DIR)/boot.o \ 7 | $(PLATFORM_DIR)/halt.o \ 8 | $(PLATFORM_DIR)/arch_start.o \ 9 | $(PLATFORM_DIR)/memory.o \ 10 | $(PLATFORM_DIR)/log.o \ 11 | $(PLATFORM_DIR)/ports.o \ 12 | $(PLATFORM_DIR)/drivers/textmode_log.o \ 13 | $(PLATFORM_DIR)/drivers/bga.o \ 14 | $(PLATFORM_DIR)/drivers/bga_log.o \ 15 | $(PLATFORM_DIR)/drivers/serial_log.o -------------------------------------------------------------------------------- /src/libc/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRING_H 2 | #define _STRING_H 1 3 | 4 | #include 5 | 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | int memcmp(const void*, const void*, size_t); 13 | void* memcpy(void* __restrict, const void* __restrict, size_t); 14 | void* memmove(void*, const void*, size_t); 15 | void* memset(void*, int, size_t); 16 | size_t strlen(const char*); 17 | char* strncpy(char* destination, const char* source, size_t num); 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/libc/include/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDIO_H 2 | #define _STDIO_H 1 3 | 4 | #include 5 | #include 6 | 7 | #define EOF (-1) 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | int printf(const char *__restrict, ...); 14 | int putchar(int); 15 | int puts(const char *); 16 | 17 | int vsprintf(char *buf, const char *fmt, va_list args); 18 | int sprintf(char *buf, const char *fmt, ...); 19 | int vprintf(const char *fmt, va_list args); 20 | int printf(const char *fmt, ...); 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/libc/security/stack_smash_protector.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if UINT32_MAX == UINTPTR_MAX 6 | #define STACK_CHK_GUARD 0xe2dee396 7 | #else 8 | #define STACK_CHK_GUARD 0x595e9fbd94fda766 9 | #endif 10 | 11 | uintptr_t __stack_chk_guard = STACK_CHK_GUARD; 12 | 13 | __attribute__((noreturn)) void __stack_chk_fail(void) 14 | { 15 | #if defined(__is_libk) 16 | panic("Stack was smashed!"); 17 | #else 18 | printf("Stack smashed\n"); 19 | #endif 20 | while (1) 21 | { 22 | } 23 | __builtin_unreachable(); 24 | } -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/i386/drivers/serial_log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class SerialLog : public KernelLogImpl { 6 | private: 7 | int x = 0; 8 | int y = 0; 9 | 10 | char foreColor = 0xF; 11 | char backColor = 0x0; 12 | 13 | void SendChar(char c); 14 | void Scroll(); 15 | 16 | public: 17 | virtual void Init(); 18 | virtual void Clear(); 19 | virtual void Newline(); 20 | virtual void ChangeForegroundColor(unsigned char c); 21 | virtual void ChangeBackgroundColor(unsigned char c); 22 | virtual void Print(char c); 23 | }; -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/crt/crti.c: -------------------------------------------------------------------------------- 1 | /* crti.c for ARM - BPABI - use -std=c99 */ 2 | typedef void (*func_ptr)(void); 3 | 4 | extern func_ptr _init_array_start[0], _init_array_end[0]; 5 | extern func_ptr _fini_array_start[0], _fini_array_end[0]; 6 | 7 | void _init(void) { 8 | for (func_ptr* func = _init_array_start; func != _init_array_end; func++) 9 | (*func)(); 10 | } 11 | 12 | void _fini(void) { 13 | for (func_ptr* func = _fini_array_start; func != _fini_array_end; func++) 14 | (*func)(); 15 | } 16 | 17 | func_ptr _init_array_start[0] __attribute__((used, section(".init_array"), aligned(sizeof(func_ptr)))) = {}; 18 | func_ptr _fini_array_start[0] __attribute__((used, section(".fini_array"), aligned(sizeof(func_ptr)))) = {}; -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/arch_start.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | SerialLogger serialLog; 5 | 6 | void init_logging() { 7 | g_log.Init(&serialLog); 8 | g_log.Log(LOG_DEBUG, "arm", "Initialised serial logging"); 9 | } 10 | 11 | extern "C" void kernel_start(void) { 12 | init_logging(); 13 | 14 | kernel_print_version(); 15 | 16 | g_log.Log(LOG_DEBUG, "log", "Debug!"); 17 | g_log.Log(LOG_INFO, "log", "Info!"); 18 | g_log.Log(LOG_NOTICE, "log", "Notice!"); 19 | g_log.Log(LOG_MESSAGE, "log", "Message!"); 20 | g_log.Log(LOG_WARN, "log", "Warn!"); 21 | g_log.Log(LOG_ERROR, "log", "Error :("); 22 | g_log.Log(LOG_PANIC, "log", "PANIC!!!"); 23 | } 24 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/arm/integrator-cp/drivers/serial_log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class SerialLogger : public KernelLogImpl { 6 | private: 7 | int x = 0; 8 | int y = 0; 9 | 10 | char foreColor = 0xF; 11 | char backColor = 0x0; 12 | 13 | void SendChar(char c); 14 | void SendString(const char* s); 15 | void Scroll(); 16 | unsigned char AnsiEscapeColor(unsigned char termColor, bool background); 17 | unsigned char ConvertTermTo256(unsigned char termColor); 18 | 19 | public: 20 | virtual void Init(); 21 | virtual void Clear(); 22 | virtual void Newline(); 23 | virtual void ChangeForegroundColor(unsigned char c); 24 | virtual void ChangeBackgroundColor(unsigned char c); 25 | virtual void Print(char c); 26 | }; -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 0xC0100000; 6 | 7 | kernel_link_memory_start = .; 8 | 9 | .text ALIGN(0x1000) : AT (ADDR (.text) - 0xC0000000) 10 | { 11 | *(.multiboot) 12 | *(.text) 13 | } 14 | 15 | /* Read-only data. */ 16 | .rodata ALIGN(0x1000) : AT (ADDR (.rodata) - 0xC0000000) 17 | { 18 | *(.rodata) 19 | } 20 | 21 | /* Read-write data (initialized) */ 22 | .data ALIGN(0x1000) : AT (ADDR (.data) - 0xC0000000) 23 | { 24 | *(.data) 25 | } 26 | 27 | /* Read-write data (uninitialized) and stack */ 28 | .bss ALIGN(0x1000) : AT (ADDR (.bss) - 0xC0000000) 29 | { 30 | *(COMMON) 31 | *(.bss) 32 | *(.bootstrap_stack) 33 | } 34 | 35 | /DISCARD/ : 36 | { 37 | *(.comment) 38 | } 39 | 40 | kernel_link_memory_end = .; 41 | } 42 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/i386/drivers/textmode_log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class x86TextModeLog : public KernelLogImpl { 6 | private: 7 | int x = 0; 8 | int y = 0; 9 | 10 | const uintptr_t baseAddr = 0xC03FF000; 11 | 12 | uint8_t* buffer = (uint8_t*)baseAddr; 13 | 14 | char foreColor = 0xF; 15 | char backColor = 0x0; 16 | 17 | void DrawChar(int xpos, int ypos, char c, char fore, char back); 18 | void Scroll(); 19 | 20 | public: 21 | virtual void Init(); 22 | virtual void Clear(); 23 | virtual void Newline(); 24 | virtual void ChangeForegroundColor(unsigned char c); 25 | virtual void ChangeBackgroundColor(unsigned char c); 26 | virtual void Print(char c); 27 | virtual void Scroll(int linesDown); 28 | }; -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/i386/drivers/bga_log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class x86BGALog : public KernelLogImpl { 6 | private: 7 | int x = 0; 8 | int y = 0; 9 | 10 | unsigned int font_width = 8; 11 | unsigned int font_height = 8; 12 | unsigned char foreColor = 0xF; 13 | unsigned char backColor = 0x0; 14 | 15 | void DrawChar(int xpos, int ypos, char c, unsigned char fore, 16 | unsigned char back); 17 | void Scroll(); 18 | 19 | public: 20 | virtual void Init(); 21 | virtual void Clear(); 22 | virtual void Newline(); 23 | virtual void ChangeForegroundColor(unsigned char c); 24 | virtual void ChangeBackgroundColor(unsigned char c); 25 | virtual void Print(char c); 26 | virtual void Scroll(int linesDown); 27 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Backups 2 | *~ 3 | 4 | # Compiled Dynamic libraries 5 | *.so 6 | *.dylib 7 | 8 | # Compiled Static libraries 9 | *.lai 10 | *.la 11 | *.a 12 | 13 | # Compiled executables 14 | *.elf 15 | *.aout 16 | 17 | # Mac stuff 18 | libiconv* 19 | .DS_Store 20 | 21 | # Build artifacts 22 | *.iso 23 | *.img 24 | *.bin 25 | *.mod 26 | *.map 27 | # Compiled Object files 28 | *.slo 29 | *.lo 30 | *.o 31 | *.d 32 | 33 | # Development artifacts 34 | *.log 35 | *.tags* 36 | ldcedilz 37 | iso/system/cedille 38 | t/gcc/* 39 | *.elf 40 | *.aout 41 | toolkit/arm-2008q3/ 42 | libiconv* 43 | .DS_Store 44 | 45 | *.iso 46 | *.img 47 | *.bin 48 | *.mod 49 | *.map 50 | 51 | initutil 52 | *.log 53 | *.tags* 54 | build/ 55 | 56 | .cproject 57 | .project 58 | .settings/ 59 | 60 | temp/ 61 | 62 | .vscode/ 63 | 64 | # GTags 65 | GTAGS 66 | GRTAGS 67 | GPATH 68 | 69 | 70 | # Personal scripts 71 | virtualbox.sh -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/ports.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void outb(uint16_t port, uint8_t value) { 5 | asm volatile("outb %1, %0" 6 | : 7 | : "dN"(port), "a"(value)); 8 | } 9 | 10 | void outw(uint16_t port, uint16_t value) { 11 | asm volatile("outw %1, %0" 12 | : 13 | : "dN"(port), "a"(value)); 14 | } 15 | 16 | void outl(uint16_t port, uint32_t value) { 17 | asm volatile("outl %1, %0" 18 | : 19 | : "dN"(port), "a"(value)); 20 | } 21 | 22 | uint8_t inb(uint16_t port) { 23 | uint8_t ret; 24 | asm volatile("inb %1, %0" 25 | : "=a"(ret) 26 | : "dN"(port)); 27 | return ret; 28 | } 29 | 30 | uint16_t inw(uint16_t port) { 31 | uint16_t ret; 32 | asm volatile("inw %w1, %0" 33 | : "=a"(ret) 34 | : "dN"(port)); 35 | return ret; 36 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Cédlle Hybrid kernel 2 | 3 | The Cédille Kernel is a kernel in development. It's goal is to be a complete toy kernel 4 | that can self host. 5 | 6 | ## Building 7 | 8 | Note: You *must* use a Cross Compiler. 9 | 10 | 1. Ensure your cross compiler is in PATH. 11 | 2. Set HOST to your specific architecture, or leave it as default for the default x86 architecture. 12 | 3. Call build.sh; the kernel should compile. 13 | 14 | You can prefix any command with HOST="target-triple" to target that host. 15 | 16 | Now that you have a kernel built: 17 | 18 | * To generate an iso image, call iso.sh 19 | * To run the kernel in qemu, call qemu.sh 20 | * To reset everything, run clean.sh 21 | 22 | To configure the kernel build process (such as flags), 23 | modify `scripts/config.sh` 24 | 25 | ### Finding your host value 26 | 27 | The value of HOST is the first two parts of the target triple for the platform. 28 | 29 | For example, for i686-elf-gcc, your HOST is i686-elf. -------------------------------------------------------------------------------- /scripts/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SYSTEM_HEADER_PROJECTS="libc kernel" 3 | PROJECTS="libc kernel" 4 | 5 | export MAKE=${MAKE:-make} 6 | export HOST=${HOST:-$(./scripts/default-host.sh)} 7 | export PLATFORM=${PLATFORM:-pc} 8 | export AR=${HOST}-ar 9 | export AS=${HOST}-as 10 | export CC=${HOST}-gcc 11 | export CPP=${HOST}-g++ 12 | export STRIP=${HOST}-strip 13 | 14 | export PREFIX=/usr 15 | export EXEC_PREFIX=$PREFIX 16 | export BOOTDIR=/boot 17 | export LIBDIR=$EXEC_PREFIX/lib 18 | export INCLUDEDIR=$PREFIX/include 19 | 20 | export CFLAGS='-Og -g -fstack-protector' 21 | export CPPFLAGS='-Og -g -fstack-protector -fno-exceptions -fno-rtti' 22 | 23 | # Configure the cross-compiler to use the desired system root. 24 | export SYSROOT="$(pwd)/build/sysroot" 25 | export CC="$CC --sysroot=$SYSROOT -isystem=$INCLUDEDIR" 26 | export CPP="$CPP --sysroot=$SYSROOT -isystem=$INCLUDEDIR" 27 | 28 | CONVERTED_ARCH=$(./scripts/target-triplet-to-arch.sh $HOST) 29 | 30 | echo "[CONFIG] $HOST ($CONVERTED_ARCH) on $PLATFORM" 31 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/i386/gdt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class x86TableGDT { 6 | private: 7 | /// An entry in the GDT 8 | struct gdt_entry { 9 | unsigned short limit_low; 10 | unsigned short base_low; 11 | unsigned char base_middle; 12 | unsigned char access; 13 | unsigned char granularity; 14 | unsigned char base_high; 15 | } __attribute__((packed)); 16 | 17 | /// Pointer to the GDT 18 | struct gdt_ptr { 19 | unsigned short limit; 20 | unsigned int base; 21 | } __attribute__((packed)); 22 | 23 | private: 24 | /// The number of entries in the GDT 25 | const static int numEntries = 5; 26 | /// The actual GDT. Actually will contain the entries 27 | struct gdt_entry gdt[numEntries]; 28 | struct gdt_ptr ptr; 29 | /// Sets the GDT entry in gdt. 30 | void 31 | SetGate(signed int num, uint32_t base, uint32_t limit, uint8_t access, 32 | uint8_t gran); 33 | 34 | public: 35 | /// Sets up the GDT. 36 | void Setup(); 37 | }; 38 | 39 | extern x86TableGDT g_table_gdt; -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/arch_start.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void load_memory_map(multiboot_info_t* mbd); 13 | void init_logging(); 14 | 15 | extern "C" void kernel_start(multiboot_info_t* mbd, unsigned int magic) { 16 | init_logging(); 17 | // Verify boot state... 18 | if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { 19 | g_log.Log(LOG_PANIC, "multiboot", "Multiboot magic was: 0x%X", magic); 20 | panic("Multiboot magic was incorrect. Should be 0x2BADB002"); 21 | } 22 | // Print version first thing. 23 | kernel_print_version(); 24 | 25 | // Init GDT 26 | g_log.Log(LOG_DEBUG, "start", "Initialising GDT"); 27 | g_table_gdt.Setup(); 28 | g_log.Log(LOG_DEBUG, "start", "Initialised GDT successfully."); 29 | 30 | // Now lets poke around and see what memory we can access 31 | load_memory_map(mbd); 32 | 33 | g_log.Log(LOG_NOTICE, "start", "Finished early setup, entering kernel main!"); 34 | kmain(); 35 | } 36 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/log.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | //#define USE_BGA 5 | //#define USE_SERIAL 6 | #define USE_TEXTMODE 7 | 8 | x86TextModeLog textmodeLog; 9 | DummyLog dummyLog; 10 | #ifdef USE_BGA 11 | #include 12 | #include 13 | 14 | x86BGALog bgaLog; 15 | 16 | static void init_bga() { 17 | g_log.Init(&textmodeLog); 18 | g_log.Log(LOG_INFO, "log", "Initialised text mode..."); 19 | // Check if we have BGA 20 | if (x86driver_bga.Supported()) { 21 | x86driver_bga.Initialise(); 22 | g_log.Init(&bgaLog); 23 | 24 | } else { 25 | g_log.Log(LOG_WARN, "log", 26 | "BGA unsupported, continuing to use text mode."); 27 | } 28 | } 29 | #endif 30 | 31 | #ifdef USE_TEXTMODE 32 | static void init_textmode() { 33 | g_log.Init(&textmodeLog); 34 | g_log.Log(LOG_INFO, "log", "Initialised text mode..."); 35 | } 36 | #endif 37 | 38 | void init_logging() { 39 | g_log.Init(&dummyLog); 40 | #ifdef USE_TEXTMODE 41 | init_textmode(); 42 | #endif 43 | #ifdef USE_BGA 44 | init_bga(); 45 | #endif 46 | g_log.Log(LOG_DEBUG, "log", "Log Initialised"); 47 | g_log.renderer.SignalFullRender(); 48 | } 49 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/gdt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" void gdt_flush(void* ptr); 4 | 5 | void x86TableGDT::SetGate(signed int num, uint32_t base, uint32_t limit, uint8_t access, 6 | uint8_t gran) { 7 | gdt[num].base_low = (base & 0xFFFF); 8 | gdt[num].base_middle = (base >> 16) & 0xFF; 9 | gdt[num].base_high = (base >> 24) & 0xFF; 10 | 11 | gdt[num].limit_low = (limit & 0xFFFF); 12 | 13 | gdt[num].granularity = (limit >> 16) & 0x0F; 14 | gdt[num].granularity |= gran & 0xF0; 15 | 16 | gdt[num].access = access; 17 | } 18 | 19 | void x86TableGDT::Setup() { 20 | ptr.limit = (sizeof(struct gdt_entry) * numEntries) - 1; 21 | ptr.base = (uint32_t)&gdt; 22 | 23 | SetGate(0, 0, 0, 0, 0); // Null segment 24 | SetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment 25 | SetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment 26 | SetGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment 27 | SetGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment 28 | //SetGate(5, (uint32_t)&tls_bss_middle, 0xFFFFFFFF, 0x93, 0xCF); // GS TLS segment 29 | //SetGate(6, (uint32_t)&tls_bss_middle, 0xFFFFFFFF, 0x93, 0xCF); // FS TLS segment 30 | gdt_flush((void*)&ptr); 31 | } 32 | 33 | x86TableGDT g_table_gdt; -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/drivers/serial_log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define PORT 0x3F8 // COM1 7 | 8 | void SerialLog::Init() { 9 | outb(PORT + 1, 0x00); // Disable all interrupts 10 | outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) 11 | outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud 12 | outb(PORT + 1, 0x00); // (hi byte) 13 | outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit 14 | outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold 15 | outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set 16 | 17 | width = 80; 18 | height = 25; 19 | isSerial = true; 20 | } 21 | void SerialLog::SendChar(char c) { 22 | while ((inb(PORT + 5) & 0x20) == 0) { 23 | } 24 | outb(PORT, c); 25 | } 26 | 27 | void SerialLog::Clear() { 28 | SendChar(27); 29 | SendChar('['); 30 | SendChar('2'); 31 | SendChar('J'); 32 | 33 | SendChar(27); 34 | SendChar('['); 35 | SendChar('H'); 36 | } 37 | 38 | void SerialLog::Newline() { 39 | // Fill blank space with attribute... 40 | for (unsigned int i = x; i < width; i++) { 41 | SendChar(' '); 42 | } 43 | // Reset and scroll 44 | y++; 45 | x = left_margin; 46 | for (unsigned int i = 0; i < left_margin; i++) { 47 | SendChar(' '); 48 | } 49 | } 50 | 51 | void SerialLog::ChangeForegroundColor(unsigned char c) { 52 | foreColor = c; 53 | } 54 | void SerialLog::ChangeBackgroundColor(unsigned char c) { 55 | backColor = c; 56 | } 57 | void SerialLog::Print(char c) { 58 | if (c == '\n') { 59 | Newline(); 60 | return; 61 | } 62 | SendChar(c); 63 | x++; 64 | } -------------------------------------------------------------------------------- /docs/Scheduling.md: -------------------------------------------------------------------------------- 1 | # Scheduling 2 | 3 | Scheduling in Cédille is preemptive. 4 | The scheduler uses 3 bins: a queue of active processes, a list of blocked processes, and a sleeping delta-queue. 5 | 6 | ## Active Processes 7 | 8 | Active processes are processes that are currently able to be scheduled to run on a CPU. 9 | 10 | Each process is assigned a usage factor. While a process is being run, it's usage factor will go up. The longer a process does not execute, the lower it's usage factor will go, until it is at the minimum. Blocked processes also have their usage factor decay. 11 | 12 | The usage factor is based on the amount of real-time has passed and the amount of time that the process has run. 13 | 14 | The usage factor will affect the priority of the process. A lower usage factor will mean a higher priority. Priority can also be influenced by a factor called 'niceness'. System processes have a niceness of 100, while user processes have a niceness of 0. This means that System processes will almost-always be scheduled over user processes, but system processes are far more likely to be blocked. 15 | 16 | Every tick, the scheduler will look for the highest priority process to schedule. If it cannot schedule any processes, the scheduler will try again next clock cycle. 17 | 18 | ## Blocked Processes 19 | 20 | Blocked processes wait for events, such as an signal, or lock. 21 | 22 | Processes will wait in a list until they are unblocked. 23 | 24 | ## Sleeping Processes 25 | 26 | Sleeping processes are put into a delta-queue, sorted by how many ticks are remaining before a process is awoken. 27 | 28 | If a process is uninteruptable, it will not respond to an early-wake. Instead, the process that attempted to wake the uninteruptable process will block. 29 | 30 | ## Multiprocessing 31 | 32 | Each CPU will have it's own set of each queue. 33 | -------------------------------------------------------------------------------- /bochsrc: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1 3 | config_interface: textconfig 4 | display_library: x 5 | memory: host=64, guest=64 6 | romimage: file="/usr/share/bochs/BIOS-bochs-latest" 7 | vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" 8 | boot: cdrom 9 | floppy_bootsig_check: disabled=0 10 | # no floppya 11 | # no floppyb 12 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 13 | ata0-master: type=cdrom, path="build/artifact.iso", status=inserted, biosdetect=auto, model="Generic 1234" 14 | ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 15 | ata2: enabled=0 16 | ata3: enabled=0 17 | pci: enabled=1, chipset=i440fx 18 | vga: extension=vbe, update_freq=5 19 | cpu: count=1, ips=20000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 20 | cpuid: family=6, model=0x03, stepping=3, mmx=1, apic=xapic, sse=ssse3, sse4a=0, sep=1, aes=0, xsave=0, xsaveopt=0, movbe=0, adx=0, smep=0, avx=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, tbm=0, fma4=0, vmx=1, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, mwait=1 21 | cpuid: vendor_string="GenuineIntel" 22 | cpuid: brand_string=" Intel(R) Pentium(R) 4 CPU " 23 | 24 | print_timestamps: enabled=0 25 | debugger_log: - 26 | magic_break: enabled=0 27 | port_e9_hack: enabled=0 28 | private_colormap: enabled=0 29 | clock: sync=realtime, time0=local, rtc_sync=0 30 | # no cmosimage 31 | # no loader 32 | log: - 33 | logprefix: %t%e%d 34 | panic: action=ask 35 | error: action=report 36 | info: action=report 37 | debug: action=ignore 38 | keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap= 39 | user_shortcut: keys=none 40 | mouse: enabled=0, type=ps2, toggle=ctrl+mbutton 41 | parport1: enabled=1, file="" 42 | parport2: enabled=0 43 | com1: enabled=1, mode=null, dev="" 44 | com2: enabled=0 45 | com3: enabled=0 46 | com4: enabled=0 47 | -------------------------------------------------------------------------------- /src/libc/Makefile: -------------------------------------------------------------------------------- 1 | DEFAULT_HOST!=../../scripts/default-host.sh 2 | HOST?=DEFAULT_HOST 3 | HOSTARCH!=../../scripts/target-triplet-to-arch.sh $(HOST) 4 | 5 | CFLAGS?=-O2 -g 6 | CPPFLAGS?= 7 | LDFLAGS?= 8 | LIBS?= 9 | 10 | DESTDIR?= 11 | PREFIX?=/usr/local 12 | EXEC_PREFIX?=$(PREFIX) 13 | INCLUDEDIR?=$(PREFIX)/include 14 | LIBDIR?=$(EXEC_PREFIX)/lib 15 | 16 | CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra -D__is_libc -Iinclude 17 | CPPFLAGS:=$(CPPFLAGS) -ffreestanding -Wall -Wextra -D__is_libc -Iinclude 18 | LIBK_CFLAGS:=$(CFLAGS) -D__is_libk 19 | LIBK_CPPFLAGS:=$(CPPFLAGS) -D__is_libk 20 | 21 | ARCHDIR=arch/$(HOSTARCH) 22 | 23 | include $(ARCHDIR)/make.config 24 | 25 | CFLAGS:=$(CFLAGS) $(ARCH_CFLAGS) 26 | CPPFLAGS:=$(CPPFLAGS) $(ARCH_CPPFLAGS) 27 | LIBK_CFLAGS:=$(LIBK_CFLAGS) $(KERNEL_ARCH_CFLAGS) 28 | LIBK_CPPFLAGS:=$(LIBK_CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS) 29 | 30 | FREEOBJS=\ 31 | $(ARCH_FREEOBJS) \ 32 | stdio/printf.o \ 33 | stdio/putchar.o \ 34 | stdio/puts.o \ 35 | stdlib/abort.o \ 36 | string/memcmp.o \ 37 | string/memcpy.o \ 38 | string/memmove.o \ 39 | string/memset.o \ 40 | string/strncpy.o \ 41 | string/strlen.o \ 42 | security/stack_smash_protector.o \ 43 | 44 | HOSTEDOBJS=\ 45 | $(ARCH_HOSTEDOBJS) \ 46 | 47 | OBJS=\ 48 | $(FREEOBJS) \ 49 | $(HOSTEDOBJS) \ 50 | 51 | LIBK_OBJS=$(FREEOBJS:.o=.libk.o) 52 | 53 | #BINARIES=libc.a libk.a # Not ready for libc yet. 54 | BINARIES=libk.a 55 | 56 | .PHONY: all clean install install-headers install-libs 57 | .SUFFIXES: .o .libk.o .c .S 58 | 59 | all: $(BINARIES) 60 | 61 | libc.a: $(OBJS) 62 | @echo "[ ARC ] $(OBJS)" 63 | @$(AR) rcs $@ $(OBJS) 64 | 65 | libk.a: $(LIBK_OBJS) 66 | @echo "[ ARC ] $@" 67 | @$(AR) rcs $@ $(LIBK_OBJS) 68 | 69 | .c.o: 70 | @echo "[ C ] $<" 71 | @$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) 72 | 73 | .c.S: 74 | @echo "[ C ] $<" 75 | @$(CC) -MD -c $< -o $@ $(CFLAGS) 76 | 77 | .c.libk.o: 78 | @echo "[ C ] $<" 79 | @$(CC) -MD -c $< -o $@ -std=gnu11 $(LIBK_CFLAGS) 80 | 81 | .S.libk.o: 82 | @echo "[ ASM ] $<" 83 | @$(CC) -MD -c $< -o $@ $(LIBK_CFLAGS) 84 | 85 | clean: 86 | @echo "[CLEAN] src/libc" 87 | @rm -f $(BINARIES) *.a 88 | @rm -f $(OBJS) $(LIBK_OBJS) *.o */*.o */*/*.o 89 | @rm -f $(OBJS:.o=.d) $(LIBK_OBJS:.o=.d) *.d */*.d */*/*.d 90 | 91 | 92 | install: install-headers install-libs 93 | 94 | install-headers: 95 | @echo "[ INS ] libc headers..." 96 | @mkdir -p $(DESTDIR)$(INCLUDEDIR) 97 | @cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/. 98 | 99 | install-libs: $(BINARIES) 100 | @echo "[ INS ] libc binaries..." 101 | @mkdir -p $(DESTDIR)$(LIBDIR) 102 | @cp $(BINARIES) $(DESTDIR)$(LIBDIR) 103 | 104 | -include $(OBJS:.o=.d) 105 | -include $(LIBK_OBJS:.o=.d) 106 | -------------------------------------------------------------------------------- /src/kernel/include/kernel/arch/i386/drivers/bga.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 16 6 | #define VBE_DISPI_4BPP_PLANE_SHIFT 22 7 | 8 | #define VBE_DISPI_BANK_ADDRESS 0xA0000 9 | #define VBE_DISPI_BANK_SIZE_KB 64 10 | 11 | #define VBE_DISPI_MAX_XRES 2560 12 | #define VBE_DISPI_MAX_YRES 1600 13 | #define VBE_DISPI_MAX_BPP 32 14 | 15 | #define VBE_DISPI_IOPORT_INDEX 0x01CE 16 | #define VBE_DISPI_IOPORT_DATA 0x01CF 17 | 18 | #define VBE_DISPI_INDEX_ID 0x0 19 | #define VBE_DISPI_INDEX_XRES 0x1 20 | #define VBE_DISPI_INDEX_YRES 0x2 21 | #define VBE_DISPI_INDEX_BPP 0x3 22 | #define VBE_DISPI_INDEX_ENABLE 0x4 23 | #define VBE_DISPI_INDEX_BANK 0x5 24 | #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 25 | #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 26 | #define VBE_DISPI_INDEX_X_OFFSET 0x8 27 | #define VBE_DISPI_INDEX_Y_OFFSET 0x9 28 | #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa 29 | 30 | #define VBE_DISPI_ID0 0xB0C0 31 | #define VBE_DISPI_ID1 0xB0C1 32 | #define VBE_DISPI_ID2 0xB0C2 33 | #define VBE_DISPI_ID3 0xB0C3 34 | #define VBE_DISPI_ID4 0xB0C4 35 | #define VBE_DISPI_ID5 0xB0C5 36 | 37 | #define VBE_DISPI_BPP_4 0x04 38 | #define VBE_DISPI_BPP_8 0x08 39 | #define VBE_DISPI_BPP_15 0x0F 40 | #define VBE_DISPI_BPP_16 0x10 41 | #define VBE_DISPI_BPP_24 0x18 42 | #define VBE_DISPI_BPP_32 0x20 43 | 44 | #define VBE_DISPI_DISABLED 0x00 45 | #define VBE_DISPI_ENABLED 0x01 46 | #define VBE_DISPI_GETCAPS 0x02 47 | #define VBE_DISPI_8BIT_DAC 0x20 48 | #define VBE_DISPI_LFB_ENABLED 0x40 49 | #define VBE_DISPI_NOCLEARMEM 0x80 50 | 51 | class BGA { 52 | public: 53 | unsigned int screenWidth = 800; 54 | unsigned int screenHeight = 600; 55 | 56 | void Initialise(); 57 | bool Supported(); 58 | void PlotPixel(unsigned int x, unsigned int y, Color color); 59 | void LineCopy(int lineSrc, int lineDest); 60 | 61 | private: 62 | bool featureFrameBuffer = false; 63 | 64 | uint16_t currentBank = 0; 65 | uint32_t bytesPerBank = 0x10000; 66 | uint32_t bytesPerPixel = 4; 67 | 68 | uint32_t *buffer = (uint32_t *)0xA0000; 69 | 70 | void ChangeBank(uint16_t bank); 71 | uint16_t GetBankForPixel(unsigned int x, unsigned int y); 72 | void PlotPixel(unsigned int x, unsigned int y, uint32_t color); 73 | uintptr_t GetLineAddress(unsigned int line) { 74 | return line * screenWidth * bytesPerPixel; 75 | } 76 | uintptr_t GetBankBaseAddress() { 77 | return currentBank * bytesPerBank; 78 | } 79 | 80 | uintptr_t GetAbsoluteAddress(unsigned int line) { 81 | uint32_t address = (((screenWidth * line)) * bytesPerPixel) - 82 | (currentBank * bytesPerBank); 83 | return 0xA0000 + address; 84 | } 85 | }; 86 | extern BGA x86driver_bga; -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/drivers/textmode_log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void x86TextModeLog::Init() { 7 | // Disable blinking 8 | inb(0x03DA); // Set to index state 9 | outb(0x03C0, 0x30); // Write index to address mode control register 10 | char regcontents = inb(0x03C1); // Get contents 11 | regcontents &= 0xF7; // Unset bit 3 (blink) 12 | outb(0x03C0, regcontents); // Write result to 0x3C0, which is in data mode. 13 | 14 | width = 80; 15 | height = 25; 16 | } 17 | 18 | void x86TextModeLog::DrawChar(int xpos, int ypos, char c, char fore, 19 | char back) { 20 | int location = ((ypos * width) + xpos) * 2; 21 | uint8_t attrib = (back << 4) | (fore & 0x0F); 22 | buffer[location] = c; 23 | buffer[location + 1] = attrib; 24 | } 25 | 26 | void x86TextModeLog::Scroll(int linesDown) { 27 | if (linesDown < 0) { 28 | //TODO: Implement 29 | asm("hlt"); 30 | return; 31 | } 32 | 33 | linesDown = 1; 34 | 35 | uint32_t screen_size = width * height * 2; 36 | uint32_t line_down_offset = width * (linesDown)*2; 37 | uint32_t needed_region_start = baseAddr + line_down_offset; 38 | uint32_t needed_region_size = screen_size - line_down_offset; 39 | uint8_t tempBuffer[needed_region_size]; 40 | 41 | // Step 1: Copy needed part of screen to buffer 42 | memcpy(&tempBuffer, (void*)(needed_region_start), needed_region_size); 43 | 44 | // Step 2: Copy buffer to screen. 45 | memcpy((void*)baseAddr, &tempBuffer, needed_region_size); 46 | 47 | // Step 3: Clear lines at bottom 48 | memset((void*)(baseAddr + needed_region_size), 0, line_down_offset); 49 | 50 | y -= linesDown; 51 | } 52 | 53 | void x86TextModeLog::Clear() { 54 | x = 0; 55 | y = 0; 56 | for (unsigned int y = 0; y < height; y++) { 57 | for (unsigned int x = 0; x < width; x++) { 58 | DrawChar(x, y, ' ', foreColor, backColor); 59 | } 60 | } 61 | 62 | x = left_margin; 63 | } 64 | 65 | void x86TextModeLog::Newline() { 66 | // Fill blank space with attribute... 67 | for (unsigned int i = x; i < width; i++) { 68 | DrawChar(i, y, ' ', foreColor, backColor); 69 | } 70 | // Reset and scroll 71 | y++; 72 | x = left_margin; 73 | for (unsigned int i = 0; i < left_margin; i++) { 74 | DrawChar(i, y, ' ', foreColor, backColor); 75 | } 76 | } 77 | 78 | void x86TextModeLog::ChangeForegroundColor(unsigned char c) { 79 | foreColor = c; 80 | } 81 | void x86TextModeLog::ChangeBackgroundColor(unsigned char c) { 82 | backColor = c; 83 | } 84 | void x86TextModeLog::Print(char c) { 85 | if (c == '\n') { 86 | Newline(); 87 | return; 88 | } 89 | if (x >= (signed int)width) { 90 | Newline(); 91 | } 92 | DrawChar(x, y, c, foreColor, backColor); 93 | 94 | x++; 95 | } -------------------------------------------------------------------------------- /src/kernel/log.cpp: -------------------------------------------------------------------------------- 1 | #include "kernel/log.h" 2 | #include 3 | #include 4 | #include 5 | 6 | KernelLog g_log; 7 | 8 | const unsigned char log_severity_table[] = { 9 | // Fore, Back 10 | 0x08, 0xFF, // Debug 11 | 0x0F, 0xFF, // Message (Default) 12 | 0x0B, 0xFF, // Info 13 | 0x0D, 0xFF, // Notice 14 | 0x0E, 0x08, // Warn 15 | 0x0C, 0x08, // Error 16 | 0x04, 0x0F, // Panic 17 | }; 18 | 19 | void KernelLog::Init(KernelLogImpl* impl) { 20 | this->impl = impl; 21 | 22 | defaultColor.fore = 0x0F; 23 | defaultColor.back = 0x00; 24 | 25 | impl->Init(); 26 | impl->Clear(); 27 | 28 | renderer.Init(); 29 | renderer.SignalFullRender(); 30 | } 31 | 32 | void KernelLog::Log(char c) { 33 | impl->Print(c); 34 | } 35 | 36 | LogColor KernelLog::GetSeverityColor(unsigned int severity) { 37 | LogColor c; 38 | c.fore = log_severity_table[severity * 2]; 39 | c.back = log_severity_table[(severity * 2) + 1]; 40 | return c; 41 | } 42 | 43 | void KernelLog::Log(LogEntry newEntry) { 44 | // Attempt to insert message 45 | AppendEntry(newEntry); 46 | renderer.SignalNewEntry(); 47 | } 48 | 49 | void KernelLog::Log(const char* str) { 50 | Log(LOG_MESSAGE, "", str); 51 | } 52 | 53 | void KernelLog::Log(const char* tag, const char* str) { 54 | Log(LOG_MESSAGE, tag, str); 55 | } 56 | 57 | void KernelLog::Log(unsigned int severity, const char* tag, const char* fmt, 58 | ...) { 59 | LogEntry newEntry; 60 | newEntry.severity = severity; 61 | newEntry.tag = tag; 62 | newEntry.color = currentColor; 63 | 64 | char buffer[LOG_MAX_MESSAGE_SIZE]; 65 | 66 | va_list args; 67 | va_start(args, fmt); 68 | vsprintf(buffer, fmt, args); 69 | va_end(args); 70 | 71 | strncpy(newEntry.message, buffer, LOG_MAX_MESSAGE_SIZE); 72 | newEntry.message[LOG_MAX_MESSAGE_SIZE - 1] = 0; // Force null character 73 | 74 | Log(newEntry); 75 | } 76 | 77 | void KernelLog::SetBackgroundColor(char color) { 78 | currentColor.back = color; 79 | impl->ChangeBackgroundColor(color); 80 | } 81 | 82 | void KernelLog::SetForegroundColor(char color) { 83 | currentColor.fore = color; 84 | impl->ChangeForegroundColor(color); 85 | } 86 | 87 | void KernelLog::SetColors(LogColor colors) { 88 | SetForegroundColor(colors.fore); 89 | SetBackgroundColor(colors.back); 90 | } 91 | 92 | void KernelLog::AppendEntry(LogEntry entry) { 93 | if (log_entry_index >= LOG_MAX_ENTRIES - 1) { 94 | // Shift all entries down by one, discarding the oldest... 95 | for (int i = 1; i < LOG_MAX_ENTRIES - 1; i++) { 96 | entry_buffer[i - 1] = entry_buffer[i]; 97 | } 98 | log_entry_index--; 99 | } 100 | 101 | entry_buffer[log_entry_index++] = entry; 102 | } 103 | 104 | // C shim 105 | extern "C" void kernel_log_char(char c) { 106 | g_log.Log(c); 107 | } 108 | 109 | // Dummy log stuff 110 | 111 | void DummyLog::Init() {} 112 | void DummyLog::Clear() {} 113 | void DummyLog::Newline() {} 114 | void DummyLog::ChangeForegroundColor(unsigned char c) { 115 | c = c; 116 | } 117 | void DummyLog::ChangeBackgroundColor(unsigned char c) { 118 | c = c; 119 | } 120 | void DummyLog::Print(char c) { 121 | c = c; 122 | } -------------------------------------------------------------------------------- /src/kernel/arch/arm/integrator-cp/drivers/serial_log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define SERIAL_BASE 0x16000000 8 | #define SERIAL_FLAG_REGISTER 0x16000018 9 | #define SERIAL_BUFFER_FULL (1 << 5) 10 | 11 | void SerialLogger::Init() { 12 | width = 80; 13 | height = 25; 14 | isSerial = true; 15 | } 16 | void SerialLogger::SendChar(char c) { 17 | /* Wait until the serial buffer is empty */ 18 | while (*(volatile unsigned long*)(SERIAL_FLAG_REGISTER) & (SERIAL_BUFFER_FULL)) { 19 | } 20 | 21 | /* Put our character, c, into the serial buffer */ 22 | *(volatile unsigned long*)SERIAL_BASE = c; 23 | 24 | /* Print a carriage return if this is a newline, as the cursor's x position will not reset to 0*/ 25 | if (c == '\n') { 26 | SendChar('\r'); 27 | } 28 | } 29 | 30 | void SerialLogger::SendString(const char* s) { 31 | size_t i = 0; 32 | while (s[i] != 0) { 33 | SendChar(s[i]); 34 | i++; 35 | } 36 | } 37 | 38 | unsigned char SerialLogger::AnsiEscapeColor(unsigned char termColor, bool background) { 39 | // HACK: Cooincidentally converts to ansi. 40 | unsigned char ansiEscape = 30 + termColor; 41 | if (termColor > 7) { 42 | termColor = 90 + (termColor - 7); 43 | } 44 | 45 | if (background) { 46 | ansiEscape += 10; 47 | } 48 | 49 | return ansiEscape; 50 | } 51 | 52 | unsigned char SerialLogger::ConvertTermTo256(unsigned char termColor) { 53 | const unsigned char conversion_mappings[] = { 54 | 0, // 0x0 55 | 4, // 0x1 56 | 2, // 0x2 57 | 6, // 0x3 58 | 1, // 0x4 59 | 5, // 0x5 60 | 3, // 0x6 61 | 7, // 0x7 62 | 8, // 0x8 63 | 12, // 0x9 64 | 10, // 0xA 65 | 14, // 0xB 66 | 9, // 0xC 67 | 13, // 0xD 68 | 11, // 0xE 69 | 15, // 0xF 70 | }; 71 | 72 | if (termColor <= sizeof(conversion_mappings)) { 73 | return conversion_mappings[termColor]; 74 | } 75 | 76 | return termColor; 77 | } 78 | 79 | void SerialLogger::Clear() { 80 | SendChar(27); 81 | SendString("[2J"); 82 | 83 | SendChar(27); 84 | SendString("[H"); 85 | } 86 | 87 | void SerialLogger::Newline() { 88 | // Fill blank space with attribute... 89 | for (unsigned int i = x; i < width; i++) { 90 | SendChar(' '); 91 | } 92 | 93 | // Send to serial 94 | SendChar(27); // Down one line 95 | SendString("[1B"); 96 | SendChar('\r'); // Move cursor back to x = 0 97 | 98 | // Reset and 99 | y++; 100 | x = left_margin; 101 | 102 | for (unsigned int i = 0; i < left_margin; i++) { 103 | SendChar(' '); 104 | } 105 | } 106 | 107 | void SerialLogger::ChangeForegroundColor(unsigned char c) { 108 | foreColor = c; 109 | 110 | // Send Color to Terminal 111 | SendChar(27); 112 | printf("[38;5;%dm", ConvertTermTo256(c)); 113 | } 114 | void SerialLogger::ChangeBackgroundColor(unsigned char c) { 115 | backColor = c; 116 | /* 117 | FIXME: Broken. Sometimes get an extra space at the end of some characters. 118 | // Send Color to Terminal 119 | SendChar(27); 120 | printf("[48;5;%dm", ConvertTermTo256(c)); 121 | */ 122 | } 123 | void SerialLogger::Print(char c) { 124 | if (c == '\n' && x < width) { 125 | Newline(); 126 | return; 127 | } else if (x >= width) { 128 | Newline(); 129 | } 130 | SendChar(c); 131 | x++; 132 | } 133 | 134 | void SerialLogger::Scroll() { 135 | } -------------------------------------------------------------------------------- /src/kernel/include/kernel/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define LOG_DEBUG 0 4 | #define LOG_MESSAGE 1 5 | #define LOG_INFO 2 6 | #define LOG_NOTICE 3 7 | #define LOG_WARN 4 8 | #define LOG_ERROR 5 9 | #define LOG_PANIC 6 10 | 11 | #define LOG_MAX_MESSAGE_SIZE 128 // Maximum message size for message 12 | #define LOG_MAX_ENTRIES 200 // 2 screens of entries... 13 | 14 | struct LogColor { 15 | unsigned char fore; 16 | unsigned char back; 17 | }; 18 | 19 | struct LogEntry { 20 | unsigned char severity; 21 | const char* tag; 22 | char message[LOG_MAX_MESSAGE_SIZE]; 23 | LogColor color; 24 | }; 25 | 26 | class KernelLogImpl { 27 | public: 28 | virtual void Init() { 29 | width = 80; 30 | height = 25; 31 | } 32 | virtual void Clear() = 0; 33 | virtual void Newline() = 0; 34 | virtual void ChangeForegroundColor(unsigned char c) = 0; 35 | virtual void ChangeBackgroundColor(unsigned char c) = 0; 36 | virtual void Print(char c) = 0; 37 | virtual void Scroll(int linesDown) { 38 | linesDown = linesDown; 39 | } 40 | unsigned int left_margin = 0; 41 | unsigned int width; 42 | unsigned int height; 43 | 44 | bool isSerial = false; 45 | }; 46 | 47 | class BootLogRenderer { 48 | private: 49 | bool requestFullRender = false; 50 | bool scrollAppend = false; 51 | int log_tag_width = 6; 52 | int log_scroll_previous = 0; 53 | int log_scroll_current = 0; 54 | 55 | void PrintEntry(LogEntry e); 56 | void PrintTag(const char* tag); 57 | void PrintMessage(const char* msg); 58 | 59 | void UpdateRender(); 60 | void StateFull(); 61 | void StateAppend(); 62 | void StateScrollUp(); 63 | void StateScrollDown(); 64 | enum RenderState { Append, 65 | ScrollUp, 66 | ScrollDown, 67 | Full }; 68 | 69 | public: 70 | void Init(); 71 | void SignalNewEntry(); 72 | void SignalFullRender(); 73 | }; 74 | 75 | class KernelLog { 76 | private: 77 | KernelLogImpl* impl; 78 | 79 | public: 80 | BootLogRenderer renderer; 81 | 82 | private: 83 | // Log Entry Stuff 84 | LogEntry entry_buffer[LOG_MAX_ENTRIES]; 85 | unsigned int log_entry_index = 0; 86 | bool usingStaticMemory = true; 87 | 88 | // Use when heap is working... 89 | void TransitionToDynamicMemory(); 90 | // Coloring 91 | LogColor currentColor; 92 | LogColor defaultColor; 93 | LogColor GetSeverityColor(unsigned int severity); 94 | void SetForegroundColor(char c); 95 | void SetBackgroundColor(char c); 96 | 97 | // Printing... 98 | void AppendEntry(LogEntry entry); 99 | void Log(LogEntry entry); 100 | 101 | public: 102 | void Init(KernelLogImpl* impl); 103 | 104 | void Log(char c); 105 | void Log(const char* str); 106 | void Log(const char* tag, const char* str); 107 | // void Log(unsigned int severity, const char* tag, const char* str); 108 | void Log(unsigned int severity, const char* tag, const char* str, ...); 109 | 110 | void SetColors(LogColor colors); 111 | 112 | friend class BootLogRenderer; 113 | }; 114 | 115 | class DummyLog : public KernelLogImpl { 116 | private: 117 | int x = 0; 118 | int y = 0; 119 | 120 | public: 121 | virtual void Init(); 122 | virtual void Clear(); 123 | virtual void Newline(); 124 | virtual void ChangeForegroundColor(unsigned char c); 125 | virtual void ChangeBackgroundColor(unsigned char c); 126 | virtual void Print(char c); 127 | }; 128 | extern KernelLog g_log; -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/boot.S: -------------------------------------------------------------------------------- 1 | # Declare constants for the multiboot header. 2 | .set ALIGN, 1<<0 # align loaded modules on page boundaries 3 | .set MEMINFO, 1<<1 # provide memory map 4 | .set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field 5 | .set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header 6 | .set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot 7 | 8 | # Declare a header as in the Multiboot Standard. 9 | .section .multiboot 10 | .align 4 11 | .long MAGIC 12 | .long FLAGS 13 | .long CHECKSUM 14 | 15 | # Reserve a stack for the initial thread. 16 | .section .bootstrap_stack, "aw", @nobits 17 | .align 16 18 | stack_bottom: 19 | .skip 16384 # 16 KiB 20 | stack_top: 21 | 22 | .section .bss, "aw", @nobits 23 | .align 4096 24 | boot_page_directory: 25 | .skip 4096 26 | boot_page_table1: 27 | .skip 4096 28 | 29 | # The kernel entry point. 30 | .section .text 31 | .global _start 32 | .type _start, @function 33 | _start: 34 | # Setup paging 35 | 36 | # edi = physical address of boot_page_table_1 37 | movl $(boot_page_table1 - 0xC0000000), %edi 38 | 39 | # Map pages 0 -> 1023 40 | movl $0, %esi 41 | movl $1023, %ecx 42 | 1: 43 | # Map 0x00000000 -> kernel_memory_end 44 | cmpl $(0), %esi # Start at 0x00000000 45 | jl 2f 46 | cmpl $(kernel_link_memory_end - 0xC0000000), %esi 47 | jge 3f 48 | 49 | # Map physical address as "present, writable". Note that this maps 50 | # .text and .rodata as writable. Mind security and map them as non-writable. 51 | movl %esi, %edx 52 | orl $0x003, %edx 53 | movl %edx, (%edi) 54 | 55 | 2: 56 | # Size of page is 4096 bytes. 57 | addl $4096, %esi 58 | # Size of entries in boot_page_table1 is 4 bytes. 59 | addl $4, %edi 60 | # Loop to the next entry if we haven't finished. 61 | loop 1b 62 | 63 | 3: 64 | # Map VGA video memory to 0xC03FF000 as "present, writable". 65 | movl $(0x000B8000 | 0x003), boot_page_table1 - 0xC0000000 + 1023 * 4 66 | 67 | # The page table is used at both page directory entry 0 (virtually from 0x0 68 | # to 0x3FFFFF) (thus identity mapping the kernel) and page directory entry 69 | # 768 (virtually from 0xC0000000 to 0xC03FFFFF) (thus mapping it in the 70 | # higher half). The kernel is identity mapped because enabling paging does 71 | # not change the next instruction, which continues to be physical. The CPU 72 | # would instead page fault if there was no identity mapping. 73 | 74 | # Map the page table to both virtual addresses 0x00000000 and 0xC0000000. 75 | movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0 76 | movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4 77 | 78 | # Set cr3 to the address of the boot_page_directory. 79 | movl $(boot_page_directory - 0xC0000000), %ecx 80 | movl %ecx, %cr3 81 | 82 | # Enable paging and the write-protect bit. 83 | movl %cr0, %ecx 84 | orl $0x80010000, %ecx 85 | movl %ecx, %cr0 86 | 87 | # Jump to higher half with an absolute jump. 88 | lea 4f, %ecx 89 | jmp *%ecx 90 | 91 | 4: 92 | # Setup stack 93 | movl $stack_top, %esp 94 | xor %ebp, %ebp # Set EBP to null 95 | push %ebp # Push null return address to signal end of stack. Useful for debugging. 96 | 97 | # Push multiboot paramaters to stack for call to kernel_start 98 | # Push magic 99 | push %eax 100 | # Convert EAX (Grub multiboot structure) to a virtual address. Then push 101 | add $0xC0000000, %ebx 102 | push %ebx 103 | 104 | # Call the global constructors. 105 | call _init 106 | 107 | # Transfer control to the main kernel. 108 | call kernel_start 109 | 110 | # Hang if kernel_main unexpectedly returns. 111 | 5: cli 112 | hlt 113 | jmp 5b 114 | .size _start, . - _start 115 | 116 | 117 | # GDT functions -------------------------------------------------------------------------------- /src/kernel/Makefile: -------------------------------------------------------------------------------- 1 | DEFAULT_HOST!=../../scripts/default-host.sh 2 | HOST?=DEFAULT_HOST 3 | HOSTARCH!=../../scripts/target-triplet-to-arch.sh $(HOST) 4 | PLATFORM?=pc 5 | ASMFLAGS ?= -felf 6 | CFLAGS?=-Og -g 7 | CPPFLAGS?= 8 | LDFLAGS?= 9 | LIBS?= 10 | 11 | DESTDIR?= 12 | PREFIX?=/usr/local 13 | EXEC_PREFIX?=$(PREFIX) 14 | BOOTDIR?=$(EXEC_PREFIX)/boot 15 | INCLUDEDIR?=$(PREFIX)/include 16 | 17 | DEFINES:=-DARCH_NAME=\"${HOSTARCH}\" -DPLATFORM_NAME=\"${PLATFORM}\" 18 | 19 | CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra -D__is_kernel -Iinclude $(DEFINES) 20 | CPPFLAGS:=$(CPPFLAGS) -ffreestanding -Wall -Wextra -D__is_kernel -Iinclude $(DEFINES) 21 | LDFLAGS:=$(LDFLAGS) 22 | LIBS:=$(LIBS) -nostdlib -lk -lgcc 23 | 24 | ISA_DIR=arch/$(HOSTARCH) 25 | PLATFORM_DIR=arch/$(HOSTARCH)/$(PLATFORM) 26 | 27 | include $(ISA_DIR)/make.config 28 | include $(PLATFORM_DIR)/make.config 29 | 30 | CFLAGS:=$(CFLAGS) $(KERNEL_PLATFORM_CFLAGS) 31 | CPPFLAGS:=$(CPPFLAGS) $(KERNEL_PLATFORM_CPPFLAGS) 32 | LDFLAGS:=$(LDFLAGS) $(KERNEL_PLATFORM_LDFLAGS) 33 | LIBS:=$(LIBS) $(KERNEL_PLATFORM_LIBS) 34 | 35 | KERNEL_OBJS=\ 36 | $(KERNEL_ISA_OBJS) \ 37 | $(KERNEL_PLATFORM_OBJS) \ 38 | main.o \ 39 | log.o \ 40 | boot_log_renderer.o \ 41 | panic.o \ 42 | version.o 43 | 44 | OBJS=\ 45 | $(PLATFORM_DIR)/crt/crti.o \ 46 | $(PLATFORM_DIR)/crt/crtbegin.o \ 47 | $(KERNEL_OBJS) \ 48 | $(PLATFORM_DIR)/crt/crtend.o \ 49 | $(PLATFORM_DIR)/crt/crtn.o \ 50 | 51 | LINK_LIST=\ 52 | $(LDFLAGS) \ 53 | $(PLATFORM_DIR)/crt/crti.o \ 54 | $(PLATFORM_DIR)/crt/crtbegin.o \ 55 | $(KERNEL_OBJS) \ 56 | $(LIBS) \ 57 | $(PLATFORM_DIR)/crt/crtend.o \ 58 | $(PLATFORM_DIR)/crt/crtn.o \ 59 | 60 | .PHONY: all clean install install-headers install-kernel 61 | .SUFFIXES: .o .c .S .asm .nasm 62 | 63 | all: kernel.elf 64 | 65 | kernel.elf: $(OBJS) $(PLATFORM_DIR)/linker.ld 66 | @echo "[ ELF ] Compiling Kernel..." 67 | @$(CPP) -T $(PLATFORM_DIR)/linker.ld -o $@ $(CPPFLAGS) $(LINK_LIST) 68 | 69 | @echo "[ ELF ] Kernel Compiled Successfully" 70 | 71 | 72 | $(PLATFORM_DIR)/crt/crtbegin.o $(PLATFORM_DIR)/crt/crtend.o: 73 | @OBJ=`$(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ 74 | 75 | .c.o: 76 | @echo "[ C ] $<" 77 | @$(CC) -MD -c $< -o $@ -std=gnu14 $(CFLAGS) 78 | 79 | .cpp.o: 80 | @echo "[ CXX ] $<" 81 | @$(CPP) -MD -c $< -o $@ -std=gnu++14 $(CPPFLAGS) 82 | 83 | .S.o: 84 | @echo "[ ASM ] $<" 85 | @$(CC) -MD -c $< -o $@ $(CFLAGS) 86 | 87 | .s.o: 88 | @echo "[ ASM ] $<" 89 | @$(CC) -MD -c $< -o $@ $(CFLAGS) 90 | .nasm.o: 91 | @nasm $(ASMFLAGS) $< -o $@ 92 | 93 | clean: 94 | @echo "[CLEAN] src/kernel" 95 | @rm -f kernel.elf 96 | @rm -f $(OBJS) *.o */*.o */*/*.o 97 | @rm -f $(OBJS:.o=.d) *.d */*.d */*/*.d 98 | @find . -name \*.expand -type f -delete 99 | @find . -name \*.vregs -type f -delete 100 | @find . -name \*.into_cfglayout -type f -delete 101 | @find . -name \*.jump -type f -delete 102 | @find . -name \*.subreg* -type f -delete 103 | @find . -name \*.dfinit -type f -delete 104 | @find . -name \*.cse* -type f -delete 105 | @find . -name \*.fwprop* -type f -delete 106 | @find . -name \*.cprop* -type f -delete 107 | @find . -name \*.pre -type f -delete 108 | @find . -name \*.ce* -type f -delete 109 | @find . -name \*.reginfo -type f -delete 110 | @find . -name \*.loop* -type f -delete 111 | @find . -name \*.dse* -type f -delete 112 | @find . -name \*.init-regs -type f -delete 113 | @find . -name \*.combine -type f -delete 114 | @find . -name \*.split* -type f -delete 115 | 116 | install: install-headers install-kernel 117 | 118 | install-headers: 119 | @mkdir -p $(DESTDIR)$(INCLUDEDIR)/kernel/ 120 | @cp -R --preserve=timestamps include/kernel/. $(DESTDIR)$(INCLUDEDIR)/kernel/. 121 | 122 | install-kernel: kernel.elf 123 | @echo "[ INS ] Installing Kernel to sysroot /boot" 124 | @mkdir -p $(DESTDIR)$(BOOTDIR) 125 | @cp kernel.elf $(DESTDIR)$(BOOTDIR) 126 | @wc -c kernel.elf 127 | 128 | -include $(OBJS:.o=.d) 129 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/drivers/bga_log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | Color log_to_color_mappings[] = { 7 | Color(0x00, 0x00, 0x00), // 0x0 8 | Color(0x00, 0x00, 0xAA), // 0x1 9 | Color(0x00, 0xAA, 0x00), // 0x2 10 | Color(0x00, 0xAA, 0xAA), // 0x3 11 | Color(0xAA, 0x00, 0x00), // 0x4 12 | Color(0xAA, 0x00, 0xAA), // 0x5 13 | Color(0xAA, 0x55, 0x00), // 0x6 14 | Color(0xAA, 0xAA, 0xAA), // 0x7 15 | Color(0x55, 0x55, 0x55), // 0x8 16 | Color(0x55, 0x55, 0xFF), // 0x9 17 | Color(0x55, 0xFF, 0x55), // 0xA 18 | Color(0x55, 0xFF, 0xFF), // 0xB 19 | Color(0xFF, 0x55, 0x55), // 0xC 20 | Color(0xFF, 0x55, 0xFF), // 0xD 21 | Color(0xFF, 0xFF, 0x55), // 0xE 22 | Color(0xFF, 0xFF, 0xFF), // 0xF 23 | }; 24 | 25 | void x86BGALog::Init() { 26 | width = x86driver_bga.screenWidth / font_width; 27 | height = x86driver_bga.screenHeight / font_height; 28 | g_log.Log(LOG_INFO, "log", "BGA logging running at %dx%d (%dx%d chars)", x86driver_bga.screenWidth, x86driver_bga.screenHeight, width, height); 29 | } 30 | 31 | void x86BGALog::DrawChar(int xpos, int ypos, char c, unsigned char fore, unsigned char back) { 32 | Color foreColor = log_to_color_mappings[fore]; 33 | Color backColor = log_to_color_mappings[back]; 34 | 35 | // Render blank characters as a Space 36 | if (c < 32) { 37 | c = 32; 38 | } 39 | 40 | // Draw the glyph 41 | unsigned int glyph_index = c - 32; 42 | unsigned int glyph_x, glyph_y; 43 | unsigned int screen_x = xpos * font_width; 44 | unsigned int screen_y = ypos * font_height; 45 | 46 | for (glyph_y = 0; glyph_y < font_height; glyph_y++) { 47 | for (glyph_x = 0; glyph_x < font_width; glyph_x++) { 48 | unsigned char data = font_unscii8_bitmap[(uint8_t)glyph_index][glyph_y]; 49 | 50 | #ifndef FONT_RENDER_INVERSE 51 | bool glyph_hit = (data >> (font_width - glyph_x)) & 1; 52 | #else 53 | bool glyph_hit = (data >> (glyph_x)) & 1; 54 | #endif 55 | 56 | if (glyph_hit) { 57 | x86driver_bga.PlotPixel(screen_x + glyph_x, screen_y + glyph_y, foreColor); 58 | } else { 59 | x86driver_bga.PlotPixel(screen_x + glyph_x, screen_y + glyph_y, backColor); 60 | } 61 | } 62 | } 63 | } 64 | 65 | void x86BGALog::Scroll(int linesDown) { 66 | // We essentially need to copy the whole screen up by font_height pixels 67 | for (unsigned int i = 8; i < x86driver_bga.screenHeight; i++) { 68 | x86driver_bga.LineCopy(i, i - 8); 69 | } 70 | y -= linesDown; 71 | } 72 | 73 | void x86BGALog::Clear() { 74 | x = 0; 75 | y = 0; 76 | for (unsigned int y = 0; y < x86driver_bga.screenHeight; y++) { 77 | for (unsigned int x = 0; x < x86driver_bga.screenWidth; x++) { 78 | x86driver_bga.PlotPixel(0, 0, Color(0, 0, 0)); 79 | } 80 | } 81 | x = left_margin; 82 | } 83 | 84 | void x86BGALog::Newline() { 85 | // Fill blank space with attribute... 86 | if (backColor != 0) { // Optimization: Since the screen is by default black (0), don't overwrite any pixels that are already that color. 87 | for (unsigned int i = x; i < width; i++) { 88 | DrawChar(i, y, ' ', foreColor, backColor); 89 | } 90 | } 91 | // Reset and scroll 92 | y++; 93 | x = left_margin; 94 | for (unsigned int i = 0; i < left_margin; i++) { 95 | DrawChar(i, y, ' ', foreColor, backColor); 96 | } 97 | } 98 | 99 | void x86BGALog::ChangeForegroundColor(unsigned char c) { 100 | foreColor = c; 101 | } 102 | void x86BGALog::ChangeBackgroundColor(unsigned char c) { 103 | backColor = c; 104 | } 105 | void x86BGALog::Print(char c) { 106 | if (c == '\n') { 107 | Newline(); 108 | return; 109 | } 110 | if ((unsigned int)x >= width) { 111 | Newline(); 112 | } 113 | DrawChar(x, y, c, foreColor, backColor); 114 | 115 | x++; 116 | } -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/drivers/bga.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | BGA x86driver_bga; 6 | 7 | inline void BlBochsVbeWrite(uint16_t index, uint16_t value) { 8 | outw(VBE_DISPI_IOPORT_INDEX, index); 9 | outw(VBE_DISPI_IOPORT_DATA, value); 10 | } 11 | 12 | inline void BGA::ChangeBank(uint16_t bankNo) { 13 | if (bankNo == currentBank) { 14 | return; 15 | } 16 | currentBank = bankNo; 17 | BlBochsVbeWrite(VBE_DISPI_INDEX_BANK, bankNo); 18 | } 19 | 20 | inline uint16_t BGA::GetBankForPixel(unsigned int x, unsigned int y) { 21 | uint32_t address = ((screenWidth * y) + x) * bytesPerPixel; 22 | uint16_t bankNo = address / bytesPerBank; 23 | return bankNo; 24 | } 25 | 26 | inline void BGA::PlotPixel(unsigned int x, unsigned int y, uint32_t color) { 27 | // Set pixel bank... 28 | uint16_t pixelBank = GetBankForPixel(x, y); 29 | if (pixelBank != currentBank) { 30 | currentBank = pixelBank; 31 | BlBochsVbeWrite(VBE_DISPI_INDEX_BANK, pixelBank); 32 | } 33 | 34 | uint32_t address = ((screenWidth * y) + x) * bytesPerPixel; 35 | address -= currentBank * bytesPerBank; 36 | 37 | buffer[(address >> 2)] = color; 38 | } 39 | 40 | void BGA::PlotPixel(unsigned int x, unsigned int y, Color color) { 41 | // Convert color to 0RGB 42 | uint32_t c = color.b ^ (color.g << 8) ^ (color.r << 16); 43 | PlotPixel(x, y, c); 44 | } 45 | 46 | void BGA::LineCopy(int lineSrc, int lineDest) { 47 | // There are four possibilities here. They are ordered from 48 | // Fastest to slowest 49 | 50 | // 1. Both lines are in the same bank. Simply do a memcpy. 51 | // 2. The source line is two banks, but the destination 52 | // is in one. Copy source to a buffer, then copy buffer 53 | // to the destination. 54 | // 3. The source line is one bank, but the destination 55 | // is in two. Copy source to a buffer, then copy part 56 | // of the buffer to the destination, switch banks, 57 | // and the other part of the buffer to it's destination. 58 | // 4. Both lines are in two banks. Copy part of source 59 | // to a buffer, switch banks, then the other part of source. 60 | // Then, copy part of the of the buffer to the dest, 61 | // switch banks, and the other part of the buffer to dest 62 | 63 | // First, identify the banks that each lines start and end point will be in. 64 | // Because of the size of the banks, a line can only be split by 1 bank, so 65 | // two samples are okay. 66 | 67 | uint16_t src_bank_head = GetBankForPixel(0, lineSrc); 68 | uint16_t src_bank_tail = GetBankForPixel(screenWidth - 1, lineSrc); 69 | uint16_t dest_bank_head = GetBankForPixel(0, lineDest); 70 | uint16_t dest_bank_tail = GetBankForPixel(screenWidth - 1, lineDest); 71 | bool src_two_banks = src_bank_head != src_bank_tail; 72 | bool dest_two_banks = dest_bank_head != dest_bank_tail; 73 | unsigned int lineWidth = screenWidth * bytesPerPixel; 74 | 75 | // No splits... 76 | if (!src_two_banks && !dest_two_banks) { 77 | if (src_bank_head == dest_bank_head) { 78 | // Just memcpy, no bank switching required. 79 | ChangeBank(src_bank_head); // Ensure we're in the correct bank... 80 | 81 | memcpy((void*)(GetAbsoluteAddress(lineDest)), 82 | (void*)(GetAbsoluteAddress(lineSrc)), lineWidth); 83 | 84 | } else { 85 | uint8_t buffer[lineWidth]; 86 | // Memcpy to buffer 87 | ChangeBank(src_bank_head); 88 | memcpy(&buffer, (void*)(GetAbsoluteAddress(lineSrc)), lineWidth); 89 | // Switch banks 90 | ChangeBank(dest_bank_head); 91 | // Memcpy from buffer 92 | memcpy((void*)(GetAbsoluteAddress(lineDest)), &buffer, lineWidth); 93 | } 94 | } else { 95 | // 3 possibilities, src is split, dest is split, or both are split... 96 | // TODO: Finish 97 | } 98 | } 99 | 100 | void BGA::Initialise() { 101 | BlBochsVbeWrite(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); 102 | BlBochsVbeWrite(VBE_DISPI_INDEX_XRES, screenWidth); 103 | BlBochsVbeWrite(VBE_DISPI_INDEX_YRES, screenHeight); 104 | BlBochsVbeWrite(VBE_DISPI_INDEX_BPP, VBE_DISPI_BPP_32); 105 | if (featureFrameBuffer) { 106 | BlBochsVbeWrite(VBE_DISPI_INDEX_ENABLE, 107 | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); 108 | } else { 109 | BlBochsVbeWrite(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED); 110 | } 111 | // Force bank to be 0... 112 | currentBank = 1; 113 | ChangeBank(0); 114 | PlotPixel(1, 1, 0xFFFFFFFF); 115 | } 116 | 117 | bool BGA::Supported() { 118 | // Ask for BGA ID... 119 | outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); 120 | uint16_t version = inw(VBE_DISPI_IOPORT_DATA); 121 | 122 | if (version >= VBE_DISPI_ID0 && version <= VBE_DISPI_ID5) { 123 | g_log.Log(LOG_MESSAGE, "bga", "Card version 0x%04X detected", version); 124 | if (version == VBE_DISPI_ID5) { 125 | g_log.Log(LOG_DEBUG, "bga", 126 | "Latest card version, enabling frame buffer"); 127 | featureFrameBuffer = false; // We're not ready for it just yet... 128 | } else { 129 | g_log.Log(LOG_DEBUG, "bga", 130 | "Older card version, using (slower) banked mode"); 131 | } 132 | return true; 133 | } else { 134 | g_log.Log(LOG_DEBUG, "bga", "Not found"); 135 | } 136 | 137 | return false; 138 | } -------------------------------------------------------------------------------- /src/kernel/boot_log_renderer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void BootLogRenderer::Init() { 7 | log_tag_width = 10; 8 | log_scroll_current = 0; 9 | } 10 | 11 | void BootLogRenderer::SignalNewEntry() { 12 | log_scroll_current = g_log.log_entry_index - g_log.impl->height; 13 | 14 | if (log_scroll_current < 0) { 15 | log_scroll_current = 0; 16 | } 17 | 18 | if (LOG_MAX_ENTRIES < g_log.impl->height) { 19 | // Do nothing, because we can fit every entry on screen. 20 | } else if (log_scroll_current > (int)(LOG_MAX_ENTRIES - g_log.impl->height)) { 21 | log_scroll_current = LOG_MAX_ENTRIES - g_log.impl->height; 22 | scrollAppend = true; 23 | } 24 | 25 | UpdateRender(); 26 | } 27 | 28 | void BootLogRenderer::UpdateRender() { 29 | // Determine what kind of change happened 30 | // There are 4 kinds of changes 31 | // Append (Nothing is scrolled. Usually for the first few boot messages) 32 | // Scroll up (new entry added) 33 | // Scroll down (user attempts to scroll to view previous messages) 34 | // Full Render (Last resort) 35 | RenderState currentState = Append; 36 | 37 | if (requestFullRender == true) { 38 | currentState = Full; 39 | requestFullRender = false; 40 | } else if (log_scroll_current == 0 && log_scroll_previous == 0) { 41 | currentState = Append; 42 | } else if (log_scroll_current >= log_scroll_previous) { 43 | currentState = ScrollUp; 44 | } else if (log_scroll_current == (int)(LOG_MAX_ENTRIES - g_log.impl->height)) { 45 | currentState = ScrollUp; 46 | } else if (log_scroll_current < log_scroll_previous) { 47 | currentState = ScrollDown; 48 | } 49 | 50 | if (requestFullRender == true) { 51 | currentState = Full; 52 | requestFullRender = false; 53 | } 54 | 55 | // Serial devices handle their own scrolling, so we only append data to them. 56 | if (g_log.impl->isSerial) { 57 | currentState = Append; 58 | } 59 | 60 | switch (currentState) { 61 | case RenderState::Append: 62 | StateAppend(); 63 | break; 64 | case RenderState::ScrollDown: 65 | StateScrollDown(); 66 | break; 67 | case RenderState::ScrollUp: 68 | StateScrollUp(); 69 | break; 70 | default: 71 | case RenderState::Full: 72 | StateFull(); 73 | break; 74 | } 75 | log_scroll_previous = log_scroll_current; 76 | } 77 | 78 | void BootLogRenderer::PrintEntry(LogEntry entry) { 79 | //LogColor oldColor = g_log.currentColor; 80 | LogColor toSet = g_log.GetSeverityColor(entry.severity); 81 | 82 | // Set to defaults... 83 | if (toSet.fore == TERMINAL_TRANSPARENT) { 84 | toSet.fore = g_log.defaultColor.fore; 85 | } 86 | 87 | if (toSet.back == TERMINAL_TRANSPARENT) { 88 | toSet.back = g_log.defaultColor.back; 89 | } 90 | 91 | g_log.SetColors(toSet); 92 | 93 | // Print the message to the terminal. 94 | 95 | PrintTag(entry.tag); 96 | PrintMessage(entry.message); 97 | g_log.impl->Print('\n'); 98 | 99 | // Set color again 100 | //g_log.SetColors(oldColor); 101 | } 102 | 103 | void BootLogRenderer::PrintTag(const char* tag) { 104 | // How much padding between tag and layout characters 105 | const int padding_size = 2; 106 | 107 | int tag_len = strlen(tag); 108 | int tag_padding_len = tag_len + padding_size; 109 | 110 | // If tag + pad length is bigger then what we've reserved, expand. 111 | if (tag_padding_len > log_tag_width) { 112 | log_tag_width = tag_padding_len; 113 | } 114 | 115 | // Print right justified 116 | int right_space_width = log_tag_width - tag_padding_len; 117 | for (int i = 0; i < right_space_width; i++) { 118 | g_log.impl->Print(' '); 119 | } 120 | printf("%s: ", tag); 121 | } 122 | 123 | void BootLogRenderer::PrintMessage(const char* str) { 124 | // Set left margin... 125 | g_log.impl->left_margin = log_tag_width; 126 | // Print 127 | printf("%s", str); 128 | // Reset left margin 129 | g_log.impl->left_margin = 0; 130 | } 131 | 132 | void BootLogRenderer::StateFull() { 133 | // Set the background color so we clear to the correct color 134 | // TODO: Should be default color. 135 | LogColor oldColor = g_log.currentColor; 136 | g_log.SetBackgroundColor(0); 137 | g_log.impl->Clear(); 138 | // Set the background color back 139 | g_log.SetBackgroundColor(oldColor.back); 140 | 141 | size_t max_scroll = g_log.impl->height + log_scroll_current; 142 | if (max_scroll > LOG_MAX_ENTRIES - 1) { 143 | max_scroll = LOG_MAX_ENTRIES - 1; 144 | } 145 | 146 | // Render entries to the terminal. 147 | for (size_t i = log_scroll_current; i < max_scroll; i++) { 148 | if (i >= g_log.log_entry_index) { 149 | break; 150 | } 151 | PrintEntry(g_log.entry_buffer[i]); 152 | } 153 | } 154 | 155 | void BootLogRenderer::StateAppend() { 156 | // Just print the last entry... 157 | PrintEntry(g_log.entry_buffer[g_log.log_entry_index - 1]); 158 | } 159 | 160 | void BootLogRenderer::StateScrollDown() {} 161 | 162 | void BootLogRenderer::StateScrollUp() { 163 | int amountToScroll = log_scroll_current - log_scroll_previous; 164 | 165 | // We must scroll down at least one line 166 | // if we're in the scroll up state 167 | if (amountToScroll < 1) { 168 | amountToScroll = 1; 169 | } 170 | // Scroll and print entry... 171 | g_log.impl->Scroll(amountToScroll); 172 | PrintEntry(g_log.entry_buffer[g_log.log_entry_index - 1]); 173 | } 174 | 175 | void BootLogRenderer::SignalFullRender() { 176 | requestFullRender = true; 177 | } 178 | -------------------------------------------------------------------------------- /src/kernel/arch/i386/pc/memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define KERNEL_PHYS_TO_VIRTUAL(x) x + 0xC0000000 8 | #define MAX_MEMORY_REGION_ENTRIES 32 9 | extern virtual_address_t kernel_link_memory_start; 10 | extern virtual_address_t kernel_link_memory_end; 11 | 12 | virtual_address_t kPhysToVirtual(phys_address_t x) { 13 | return x + 0xC0000000; 14 | } 15 | 16 | phys_address_t kVirtualToPhys(virtual_address_t x) { 17 | return x - 0xC0000000; 18 | } 19 | 20 | struct MemoryRegion { 21 | enum Type { 22 | Used = 0, 23 | Avalable = 1, 24 | ACPI = 2, 25 | NVS = 3, 26 | Other, 27 | ISAHole 28 | }; 29 | Type type; 30 | uintptr_t start_address; 31 | uintptr_t size; 32 | bool valid = false; 33 | 34 | uintptr_t end_address() { 35 | return start_address + size - 1; 36 | } 37 | }; 38 | 39 | MemoryRegion boot_memory_table[MAX_MEMORY_REGION_ENTRIES]; 40 | 41 | void init_table() { 42 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 43 | boot_memory_table[i].valid = false; 44 | } 45 | } 46 | static const char* typestrings[] = { 47 | "Used", 48 | "Avalable", 49 | "ACPI", 50 | "NVS", 51 | "Bad RAM", 52 | "ISA", 53 | "Unknown"}; 54 | 55 | void display_memory_table(MemoryRegion table[]) { 56 | // Display old memory map before cleanup 57 | g_log.Log(LOG_DEBUG, "mmap", "IX | Type | Start | End"); 58 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 59 | if (table[i].valid) { 60 | g_log.Log(LOG_DEBUG, "mmap", "%2d %8s 0x%08X => 0x%08X", i, typestrings[table[i].type], table[i].start_address, table[i].end_address()); 61 | } 62 | } 63 | } 64 | 65 | void cleanup_mappings() { 66 | display_memory_table(boot_memory_table); 67 | g_log.Log(LOG_INFO, "mmap", "Cleaning up memory map from GRUB..."); 68 | MemoryRegion new_memory_table[MAX_MEMORY_REGION_ENTRIES]; 69 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 70 | new_memory_table[i].valid = false; 71 | } 72 | int new_entries = 0; 73 | 74 | // First, copy table, and fix any nonsense stuff 75 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 76 | if (boot_memory_table[i].valid) { 77 | if (boot_memory_table[i].size == 0) { 78 | continue; 79 | } 80 | 81 | new_memory_table[new_entries] = boot_memory_table[i]; 82 | new_entries++; 83 | } 84 | } 85 | 86 | // Secondly, see if any avalable block is intersected by any other kind of block. 87 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 88 | bool found_collision = false; 89 | if (new_memory_table[i].valid) { 90 | if (new_memory_table[i].type != MemoryRegion::Type::Avalable) { 91 | continue; 92 | } 93 | //g_log.Log(LOG_INFO, "memcln", "Found avalable region %d. Checking for intersections", i); 94 | MemoryRegion avalable_region = new_memory_table[i]; 95 | for (int k = 0; k < MAX_MEMORY_REGION_ENTRIES; k++) { 96 | if (new_memory_table[k].valid) { 97 | if (new_memory_table[k].type == MemoryRegion::Type::Avalable) { 98 | continue; 99 | } 100 | // Here we have a non-avalable region. Check to see if it intersects with the avalable block. 101 | MemoryRegion suspect = new_memory_table[k]; 102 | 103 | bool inside_test = (suspect.start_address > avalable_region.start_address) && 104 | (suspect.end_address() < avalable_region.end_address()); 105 | bool start_test = (suspect.start_address < avalable_region.start_address) && 106 | (suspect.end_address() < avalable_region.end_address()) && 107 | (suspect.end_address() > avalable_region.start_address); 108 | bool end_test = suspect.start_address > avalable_region.start_address && 109 | suspect.start_address < avalable_region.end_address(); 110 | 111 | if (inside_test) { 112 | found_collision = true; 113 | g_log.Log(LOG_DEBUG, "memcln", "Region %d (type %s) is inside %d!", k, typestrings[new_memory_table[k].type], i); 114 | 115 | // We must split the avalable block into two blocks... 116 | // Create second block AFTER the collision =====XXXX[this] 117 | MemoryRegion avalable_region_new = avalable_region; 118 | avalable_region_new.start_address = suspect.end_address() + 1; 119 | avalable_region_new.size = avalable_region.size - suspect.size - (suspect.start_address - avalable_region.start_address); 120 | new_memory_table[new_entries] = avalable_region_new; 121 | new_entries++; 122 | // Truncate before the collision [this]XXXX====== 123 | avalable_region.size = suspect.start_address - avalable_region.start_address; 124 | new_memory_table[i] = avalable_region; 125 | 126 | break; 127 | } 128 | if (start_test) { 129 | g_log.Log(LOG_WARN, "memcln", "Region %d cuts off the start of %d!", k, i); 130 | 131 | break; 132 | } 133 | if (end_test) { 134 | g_log.Log(LOG_WARN, "memcln", "Region %d cutting off the end of %d!", k, i); 135 | break; 136 | } 137 | } 138 | } 139 | 140 | if (found_collision) { 141 | //display_memory_table(new_memory_table); 142 | g_log.Log(LOG_DEBUG, "memcln", "Region %d collided, checking for more collisions...", i); 143 | i--; 144 | //asm("hlt"); 145 | } 146 | } 147 | } 148 | 149 | // Arrange in ascending order 150 | for (int i = 0; i < new_entries; ++i) { 151 | for (int j = i + 1; j < new_entries; ++j) { 152 | if (new_memory_table[i].start_address > new_memory_table[j].start_address) { 153 | MemoryRegion a = new_memory_table[i]; 154 | new_memory_table[i] = new_memory_table[j]; 155 | new_memory_table[j] = a; 156 | } 157 | } 158 | } 159 | 160 | // Finally, copy back 161 | new_entries = 0; 162 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 163 | boot_memory_table[i].valid = false; 164 | } 165 | for (int i = 0; i < MAX_MEMORY_REGION_ENTRIES; i++) { 166 | if (new_memory_table[i].valid) { 167 | boot_memory_table[new_entries] = new_memory_table[i]; 168 | new_entries++; 169 | } 170 | } 171 | 172 | display_memory_table(boot_memory_table); 173 | } 174 | 175 | void load_memory_map(multiboot_info_t* mbd) { 176 | init_table(); 177 | unsigned int entries = 0; 178 | uintptr_t avalable_memory_estimate = 0; 179 | multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)(mbd->mmap_addr + 0xC0000000); 180 | 181 | g_log.Log(LOG_DEBUG, "mmap", "Memory map address is @ 0x%X and is 0x%X bytes long", KERNEL_PHYS_TO_VIRTUAL(mbd->mmap_addr), mbd->mmap_length); 182 | 183 | // Loop over the memory map. 184 | while ((multiboot_uint32_t)mmap < KERNEL_PHYS_TO_VIRTUAL(mbd->mmap_addr) + mbd->mmap_length) { 185 | // Get the next entry address 186 | mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(mmap->size)); 187 | 188 | // Sanitize the type to prevent printing arbitrary strings. Probably not needed. 189 | 190 | if (mmap->type == 1) { 191 | avalable_memory_estimate += mmap->len_lo; 192 | } 193 | 194 | // Now add this as a memory region. 195 | boot_memory_table[entries].type = (MemoryRegion::Type)mmap->type; 196 | boot_memory_table[entries].start_address = mmap->addr_lo; 197 | boot_memory_table[entries].size = mmap->len_lo; 198 | boot_memory_table[entries].valid = true; 199 | entries++; 200 | } 201 | 202 | uintptr_t avalable_memory_est_mb = avalable_memory_estimate / 1024 / 1024; 203 | 204 | g_log.Log(LOG_DEBUG, "mmap", "Memory map has %d entries", entries); 205 | g_log.Log(LOG_DEBUG, "mmap", "Have about 0x%08X bytes (%d MB) free", avalable_memory_estimate, avalable_memory_est_mb); 206 | g_log.Log(LOG_DEBUG, "mmap", "Kernel is at 0x%08X => 0x%08X", &kernel_link_memory_start, &kernel_link_memory_end); 207 | 208 | if (avalable_memory_estimate < 1024 * 1024 * 16) { // 4MB 209 | panic( 210 | "*** LOW MEMORY *** \n" 211 | "System has less then 16MB of RAM free.\n" 212 | "Cedille requires a minimum of 16MB of RAM to boot."); 213 | } 214 | cleanup_mappings(); 215 | } -------------------------------------------------------------------------------- /src/kernel/include/kernel/boot/multiboot.h: -------------------------------------------------------------------------------- 1 | /* multiboot.h - Multiboot header file. */ 2 | /* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY 17 | * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 19 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #ifndef MULTIBOOT_HEADER 23 | #define MULTIBOOT_HEADER 1 24 | 25 | /* How many bytes from the start of the file we search for the header. */ 26 | #define MULTIBOOT_SEARCH 8192 27 | #define MULTIBOOT_HEADER_ALIGN 4 28 | 29 | /* The magic field should contain this. */ 30 | #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 31 | 32 | /* This should be in %eax. */ 33 | #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 34 | 35 | /* Alignment of multiboot modules. */ 36 | #define MULTIBOOT_MOD_ALIGN 0x00001000 37 | 38 | /* Alignment of the multiboot info structure. */ 39 | #define MULTIBOOT_INFO_ALIGN 0x00000004 40 | 41 | /* Flags set in the 'flags' member of the multiboot header. */ 42 | 43 | /* Align all boot modules on i386 page (4KB) boundaries. */ 44 | #define MULTIBOOT_PAGE_ALIGN 0x00000001 45 | 46 | /* Must pass memory information to OS. */ 47 | #define MULTIBOOT_MEMORY_INFO 0x00000002 48 | 49 | /* Must pass video information to OS. */ 50 | #define MULTIBOOT_VIDEO_MODE 0x00000004 51 | 52 | /* This flag indicates the use of the address fields in the header. */ 53 | #define MULTIBOOT_AOUT_KLUDGE 0x00010000 54 | 55 | /* Flags to be set in the 'flags' member of the multiboot info structure. */ 56 | 57 | /* is there basic lower/upper memory information? */ 58 | #define MULTIBOOT_INFO_MEMORY 0x00000001 59 | /* is there a boot device set? */ 60 | #define MULTIBOOT_INFO_BOOTDEV 0x00000002 61 | /* is the command-line defined? */ 62 | #define MULTIBOOT_INFO_CMDLINE 0x00000004 63 | /* are there modules to do something with? */ 64 | #define MULTIBOOT_INFO_MODS 0x00000008 65 | 66 | /* These next two are mutually exclusive */ 67 | 68 | /* is there a symbol table loaded? */ 69 | #define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 70 | /* is there an ELF section header table? */ 71 | #define MULTIBOOT_INFO_ELF_SHDR 0X00000020 72 | 73 | /* is there a full memory map? */ 74 | #define MULTIBOOT_INFO_MEM_MAP 0x00000040 75 | 76 | /* Is there drive info? */ 77 | #define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 78 | 79 | /* Is there a config table? */ 80 | #define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 81 | 82 | /* Is there a boot loader name? */ 83 | #define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 84 | 85 | /* Is there a APM table? */ 86 | #define MULTIBOOT_INFO_APM_TABLE 0x00000400 87 | 88 | /* Is there video information? */ 89 | #define MULTIBOOT_INFO_VBE_INFO 0x00000800 90 | #define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 91 | 92 | #ifndef ASM_FILE 93 | 94 | typedef unsigned char multiboot_uint8_t; 95 | typedef unsigned short multiboot_uint16_t; 96 | typedef unsigned int multiboot_uint32_t; 97 | typedef unsigned long long multiboot_uint64_t; 98 | 99 | struct multiboot_header { 100 | /* Must be MULTIBOOT_MAGIC - see above. */ 101 | multiboot_uint32_t magic; 102 | 103 | /* Feature flags. */ 104 | multiboot_uint32_t flags; 105 | 106 | /* The above fields plus this one must equal 0 mod 2^32. */ 107 | multiboot_uint32_t checksum; 108 | 109 | /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ 110 | multiboot_uint32_t header_addr; 111 | multiboot_uint32_t load_addr; 112 | multiboot_uint32_t load_end_addr; 113 | multiboot_uint32_t bss_end_addr; 114 | multiboot_uint32_t entry_addr; 115 | 116 | /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ 117 | multiboot_uint32_t mode_type; 118 | multiboot_uint32_t width; 119 | multiboot_uint32_t height; 120 | multiboot_uint32_t depth; 121 | }; 122 | 123 | /* The symbol table for a.out. */ 124 | struct multiboot_aout_symbol_table { 125 | multiboot_uint32_t tabsize; 126 | multiboot_uint32_t strsize; 127 | multiboot_uint32_t addr; 128 | multiboot_uint32_t reserved; 129 | }; 130 | typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; 131 | 132 | /* The section header table for ELF. */ 133 | struct multiboot_elf_section_header_table { 134 | multiboot_uint32_t num; 135 | multiboot_uint32_t size; 136 | multiboot_uint32_t addr; 137 | multiboot_uint32_t shndx; 138 | }; 139 | typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; 140 | 141 | struct multiboot_info { 142 | /* Multiboot info version number */ 143 | multiboot_uint32_t flags; 144 | 145 | /* Available memory from BIOS */ 146 | multiboot_uint32_t mem_lower; 147 | multiboot_uint32_t mem_upper; 148 | 149 | /* "root" partition */ 150 | multiboot_uint32_t boot_device; 151 | 152 | /* Kernel command line */ 153 | multiboot_uint32_t cmdline; 154 | 155 | /* Boot-Module list */ 156 | multiboot_uint32_t mods_count; 157 | multiboot_uint32_t mods_addr; 158 | 159 | union { 160 | multiboot_aout_symbol_table_t aout_sym; 161 | multiboot_elf_section_header_table_t elf_sec; 162 | } u; 163 | 164 | /* Memory Mapping buffer */ 165 | multiboot_uint32_t mmap_length; 166 | multiboot_uint32_t mmap_addr; 167 | 168 | /* Drive Info buffer */ 169 | multiboot_uint32_t drives_length; 170 | multiboot_uint32_t drives_addr; 171 | 172 | /* ROM configuration table */ 173 | multiboot_uint32_t config_table; 174 | 175 | /* Boot Loader Name */ 176 | multiboot_uint32_t boot_loader_name; 177 | 178 | /* APM table */ 179 | multiboot_uint32_t apm_table; 180 | 181 | /* Video */ 182 | multiboot_uint32_t vbe_control_info; 183 | multiboot_uint32_t vbe_mode_info; 184 | multiboot_uint16_t vbe_mode; 185 | multiboot_uint16_t vbe_interface_seg; 186 | multiboot_uint16_t vbe_interface_off; 187 | multiboot_uint16_t vbe_interface_len; 188 | 189 | multiboot_uint64_t framebuffer_addr; 190 | multiboot_uint32_t framebuffer_pitch; 191 | multiboot_uint32_t framebuffer_width; 192 | multiboot_uint32_t framebuffer_height; 193 | multiboot_uint8_t framebuffer_bpp; 194 | #define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 195 | #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 196 | #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 197 | multiboot_uint8_t framebuffer_type; 198 | union { 199 | struct 200 | { 201 | multiboot_uint32_t framebuffer_palette_addr; 202 | multiboot_uint16_t framebuffer_palette_num_colors; 203 | }; 204 | struct 205 | { 206 | multiboot_uint8_t framebuffer_red_field_position; 207 | multiboot_uint8_t framebuffer_red_mask_size; 208 | multiboot_uint8_t framebuffer_green_field_position; 209 | multiboot_uint8_t framebuffer_green_mask_size; 210 | multiboot_uint8_t framebuffer_blue_field_position; 211 | multiboot_uint8_t framebuffer_blue_mask_size; 212 | }; 213 | }; 214 | }; 215 | typedef struct multiboot_info multiboot_info_t; 216 | 217 | struct multiboot_color { 218 | multiboot_uint8_t red; 219 | multiboot_uint8_t green; 220 | multiboot_uint8_t blue; 221 | }; 222 | 223 | struct multiboot_mmap_entry { 224 | multiboot_uint32_t size; 225 | multiboot_uint32_t addr_lo, addr_hi; 226 | multiboot_uint32_t len_lo, len_hi; 227 | #define MULTIBOOT_MEMORY_AVAILABLE 1 228 | #define MULTIBOOT_MEMORY_RESERVED 2 229 | #define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 230 | #define MULTIBOOT_MEMORY_NVS 4 231 | #define MULTIBOOT_MEMORY_BADRAM 5 232 | multiboot_uint32_t type; 233 | } __attribute__((packed)); 234 | typedef struct multiboot_mmap_entry multiboot_memory_map_t; 235 | 236 | struct multiboot_mod_list { 237 | /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ 238 | multiboot_uint32_t mod_start; 239 | multiboot_uint32_t mod_end; 240 | 241 | /* Module command line */ 242 | multiboot_uint32_t cmdline; 243 | 244 | /* padding to take it to 16 bytes (must be zero) */ 245 | multiboot_uint32_t pad; 246 | }; 247 | typedef struct multiboot_mod_list multiboot_module_t; 248 | 249 | /* APM BIOS info. */ 250 | struct multiboot_apm_info { 251 | multiboot_uint16_t version; 252 | multiboot_uint16_t cseg; 253 | multiboot_uint32_t offset; 254 | multiboot_uint16_t cseg_16; 255 | multiboot_uint16_t dseg; 256 | multiboot_uint16_t flags; 257 | multiboot_uint16_t cseg_len; 258 | multiboot_uint16_t cseg_16_len; 259 | multiboot_uint16_t dseg_len; 260 | }; 261 | 262 | #endif /* ! ASM_FILE */ 263 | 264 | #endif /* ! MULTIBOOT_HEADER */ -------------------------------------------------------------------------------- /src/libc/stdio/printf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* flags used in processing format string */ 8 | #define PR_LJ 0x01 /* left justify */ 9 | #define PR_CA 0x02 /* use A-F instead of a-f for hex */ 10 | #define PR_SG 0x04 /* signed numeric conversion (%d vs. %u) */ 11 | #define PR_32 0x08 /* long (32-bit) numeric conversion */ 12 | #define PR_16 0x10 /* short (16-bit) numeric conversion */ 13 | #define PR_WS 0x20 /* PR_SG set and num was < 0 */ 14 | #define PR_LZ 0x40 /* pad left with '0' instead of ' ' */ 15 | #define PR_FP 0x80 /* pointers are far */ 16 | /* largest number handled is 2^32-1, lowest radix handled is 8. 17 | 2^32-1 in base 8 has 11 digits (add 5 for trailing NUL and for slop) */ 18 | #define PR_BUFLEN 16 19 | //#define NULL 0 20 | 21 | #define UNUSED(x) (void)(x) 22 | 23 | unsigned int strlen_unsigned(const unsigned char *str) 24 | { 25 | unsigned const char *wrk = str; 26 | int retval; 27 | for (retval = 0; *wrk != '\0'; wrk++) 28 | retval++; 29 | return retval; 30 | } 31 | 32 | typedef int (*fnptr_t)(unsigned c, void **helper); 33 | /***************************************************************************** 34 | name: do_printf 35 | action: minimal subfunction for ?printf, calls function 36 | 'fn' with arg 'ptr' for each character to be output 37 | returns:total number of characters output 38 | *****************************************************************************/ 39 | int do_printf(const char *fmt, va_list args, fnptr_t fn, void *ptr) 40 | { 41 | unsigned flags, actual_wd, count, given_wd; 42 | unsigned char *where, buf[PR_BUFLEN]; 43 | unsigned char state, radix; 44 | //unsigned char *color_value; 45 | long num; 46 | 47 | state = flags = count = given_wd = 0; 48 | /* begin scanning format specifier list */ 49 | for (; *fmt; fmt++) 50 | { 51 | switch (state) 52 | { 53 | /* STATE 0: AWAITING % */ 54 | case 0: 55 | if (*fmt != '%') /* not %... */ 56 | { 57 | fn(*fmt, &ptr); /* ...just echo it */ 58 | count++; 59 | break; 60 | } 61 | /* found %, get next char and advance state to check if next char is a flag */ 62 | state++; 63 | fmt++; 64 | /* FALL THROUGH */ 65 | /* STATE 1: AWAITING FLAGS (%-0) */ 66 | case 1: 67 | if (*fmt == '%') /* %% */ 68 | { 69 | fn(*fmt, &ptr); 70 | count++; 71 | state = flags = given_wd = 0; 72 | break; 73 | } 74 | if (*fmt == '-') 75 | { 76 | if (flags & PR_LJ) /* %-- is illegal */ 77 | state = flags = given_wd = 0; 78 | else 79 | flags |= PR_LJ; 80 | break; 81 | } 82 | /* not a flag char: advance state to check if it's field width */ 83 | state++; 84 | /* check now for '%0...' */ 85 | if (*fmt == '0') 86 | { 87 | flags |= PR_LZ; 88 | fmt++; 89 | } 90 | /* FALL THROUGH */ 91 | /* STATE 2: AWAITING (NUMERIC) FIELD WIDTH */ 92 | case 2: 93 | if (*fmt >= '0' && *fmt <= '9') 94 | { 95 | given_wd = 10 * given_wd + 96 | (*fmt - '0'); 97 | break; 98 | } 99 | /* not field width: advance state to check if it's a modifier */ 100 | state++; 101 | /* FALL THROUGH */ 102 | /* STATE 3: AWAITING MODIFIER CHARS (FNlh) */ 103 | case 3: 104 | if (*fmt == 'F') 105 | { 106 | flags |= PR_FP; 107 | break; 108 | } 109 | if (*fmt == 'N') 110 | break; 111 | if (*fmt == 'l') 112 | { 113 | flags |= PR_32; 114 | break; 115 | } 116 | if (*fmt == 'h') 117 | { 118 | flags |= PR_16; 119 | break; 120 | } 121 | /* not modifier: advance state to check if it's a conversion char */ 122 | state++; 123 | /* FALL THROUGH */ 124 | /* STATE 4: AWAITING CONVERSION CHARS (Xxpndiuocs) */ 125 | case 4: 126 | where = buf + PR_BUFLEN - 1; 127 | *where = '\0'; 128 | switch (*fmt) 129 | { 130 | case 'X': 131 | flags |= PR_CA; 132 | /* FALL THROUGH */ 133 | case 'x': 134 | case 'p': 135 | case 'n': 136 | radix = 16; 137 | goto DO_NUM; 138 | case 'd': 139 | case 'i': 140 | flags |= PR_SG; 141 | /* FALL THROUGH */ 142 | case 'u': 143 | radix = 10; 144 | goto DO_NUM; 145 | case 'o': 146 | radix = 8; 147 | /* load the value to be printed. l=long=32 bits: */ 148 | DO_NUM: 149 | if (flags & PR_32) 150 | num = va_arg(args, unsigned long); 151 | /* h=short=16 bits (signed or unsigned) */ 152 | else if (flags & PR_16) 153 | { 154 | if (flags & PR_SG) 155 | num = va_arg(args, int); // was short 156 | else 157 | num = va_arg(args, unsigned int); // was unsigned short 158 | } 159 | /* no h nor l: sizeof(int) bits (signed or unsigned) */ 160 | else 161 | { 162 | if (flags & PR_SG) 163 | num = va_arg(args, int); 164 | else 165 | num = va_arg(args, unsigned int); 166 | } 167 | /* take care of sign */ 168 | if (flags & PR_SG) 169 | { 170 | if (num < 0) 171 | { 172 | flags |= PR_WS; 173 | num = -num; 174 | } 175 | } 176 | /* convert binary to octal/decimal/hex ASCII 177 | OK, I found my mistake. The math here is _always_ unsigned */ 178 | do 179 | { 180 | unsigned long temp; 181 | 182 | temp = (unsigned long)num % radix; 183 | where--; 184 | if (temp < 10) 185 | *where = temp + '0'; 186 | else if (flags & PR_CA) 187 | *where = temp - 10 + 'A'; 188 | else 189 | *where = temp - 10 + 'a'; 190 | num = (unsigned long)num / radix; 191 | } while (num != 0); 192 | goto EMIT; 193 | case 'c': 194 | /* disallow pad-left-with-zeroes for %c */ 195 | flags &= ~PR_LZ; 196 | where--; 197 | *where = (unsigned char)va_arg(args, 198 | unsigned int); // was unsigned char 199 | actual_wd = 1; 200 | goto EMIT2; 201 | break; 202 | case 's': 203 | /* disallow pad-left-with-zeroes for %s */ 204 | flags &= ~PR_LZ; 205 | where = va_arg(args, unsigned char *); 206 | if (where == NULL) 207 | { 208 | where = (unsigned char *)"(null)"; 209 | } 210 | EMIT: 211 | actual_wd = strlen_unsigned(where); 212 | if (flags & PR_WS) 213 | actual_wd++; 214 | /* if we pad left with ZEROES, do the sign now */ 215 | if ((flags & (PR_WS | PR_LZ)) == 216 | (PR_WS | PR_LZ)) 217 | { 218 | fn('-', &ptr); 219 | count++; 220 | } 221 | /* pad on left with spaces or zeroes (for right justify) */ 222 | EMIT2: 223 | if ((flags & PR_LJ) == 0) 224 | { 225 | while (given_wd > actual_wd) 226 | { 227 | fn(flags & PR_LZ ? '0' : ' ', &ptr); 228 | count++; 229 | given_wd--; 230 | } 231 | } 232 | /* if we pad left with SPACES, do the sign now */ 233 | if ((flags & (PR_WS | PR_LZ)) == PR_WS) 234 | { 235 | fn('-', &ptr); 236 | count++; 237 | } 238 | /* emit string/char/converted number */ 239 | while (*where != '\0') 240 | { 241 | fn(*where++, &ptr); 242 | count++; 243 | } 244 | /* pad on right with spaces (for left justify) */ 245 | if (given_wd < actual_wd) 246 | given_wd = 0; 247 | else 248 | given_wd -= actual_wd; 249 | for (; given_wd; given_wd--) 250 | { 251 | fn(' ', &ptr); 252 | count++; 253 | } 254 | break; 255 | default: 256 | break; 257 | } 258 | state = flags = given_wd = 0; 259 | break; 260 | default: 261 | state = flags = given_wd = 0; 262 | break; 263 | } 264 | } 265 | return count; 266 | } 267 | #if 1 /* testing */ 268 | /***************************************************************************** 269 | SPRINTF 270 | *****************************************************************************/ 271 | static int vsprintf_help(unsigned c, void **ptr) 272 | { 273 | 274 | char *dst; 275 | dst = (char *)*ptr; 276 | *dst++ = (char)c; 277 | *ptr = dst; 278 | return 0; 279 | } 280 | /***************************************************************************** 281 | *****************************************************************************/ 282 | int vsprintf(char *buf, const char *fmt, va_list args) 283 | { 284 | int rv; 285 | 286 | rv = do_printf(fmt, args, vsprintf_help, (void *)buf); 287 | buf[rv] = '\0'; 288 | return rv; 289 | } 290 | /***************************************************************************** 291 | *****************************************************************************/ 292 | int sprintf(char *buf, const char *fmt, ...) 293 | { 294 | va_list args; 295 | int rv; 296 | 297 | va_start(args, fmt); 298 | rv = vsprintf(buf, fmt, args); 299 | va_end(args); 300 | return rv; 301 | } 302 | /***************************************************************************** 303 | PRINTF 304 | You must write your own putchar() 305 | *****************************************************************************/ 306 | int vprintf_help(unsigned c, void **ptr) 307 | { 308 | UNUSED(ptr); 309 | putchar(c); 310 | return 0; 311 | } 312 | 313 | /***************************************************************************** 314 | *****************************************************************************/ 315 | int vprintf(const char *fmt, va_list args) 316 | { 317 | return do_printf(fmt, args, vprintf_help, NULL); 318 | } 319 | 320 | /***************************************************************************** 321 | *****************************************************************************/ 322 | int printf(const char *fmt, ...) 323 | { 324 | va_list args; 325 | int rv; 326 | 327 | va_start(args, fmt); 328 | rv = vprintf(fmt, args); 329 | va_end(args); 330 | return rv; 331 | } 332 | #endif 333 | -------------------------------------------------------------------------------- /src/kernel/include/data/font-unscii.h: -------------------------------------------------------------------------------- 1 | #include 2 | static const uint8_t font_unscii8_bitmap[][8] = { 3 | 4 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 5 | {0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 6 | {0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 7 | {0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00}, // U+0023 8 | {0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0x00}, // U+0024 9 | {0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00}, // U+0025 10 | {0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00}, // U+0026 11 | {0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 12 | {0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00}, // U+0028 13 | {0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00}, // U+0029 14 | {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A 15 | {0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, // U+002B 16 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30}, // U+002C 17 | {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, // U+002D 18 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}, // U+002E 19 | {0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x00}, // U+002F 20 | {0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x3C, 0x00}, // U+0030 21 | {0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, // U+0031 22 | {0x3C, 0x66, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00}, // U+0032 23 | {0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00}, // U+0033 24 | {0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x00}, // U+0034 25 | {0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00}, // U+0035 26 | {0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00}, // U+0036 27 | {0x7E, 0x06, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x00}, // U+0037 28 | {0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00}, // U+0038 29 | {0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00}, // U+0039 30 | {0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00}, // U+003A 31 | {0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30}, // U+003B 32 | {0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00}, // U+003C 33 | {0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, // U+003D 34 | {0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00}, // U+003E 35 | {0x3C, 0x66, 0x06, 0x0C, 0x18, 0x00, 0x18, 0x00}, // U+003F 36 | {0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x7C, 0x00}, // U+0040 37 | {0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+0041 38 | {0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00}, // U+0042 39 | {0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00}, // U+0043 40 | {0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00}, // U+0044 41 | {0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00}, // U+0045 42 | {0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00}, // U+0046 43 | {0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3E, 0x00}, // U+0047 44 | {0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00}, // U+0048 45 | {0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, // U+0049 46 | {0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x00}, // U+004A 47 | {0xC6, 0xCC, 0xD8, 0xF0, 0xD8, 0xCC, 0xC6, 0x00}, // U+004B 48 | {0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00}, // U+004C 49 | {0xC6, 0xEE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0x00}, // U+004D 50 | {0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00}, // U+004E 51 | {0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+004F 52 | {0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00}, // U+0050 53 | {0x3C, 0x66, 0x66, 0x66, 0x66, 0x6C, 0x36, 0x00}, // U+0051 54 | {0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00}, // U+0052 55 | {0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00}, // U+0053 56 | {0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+0054 57 | {0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+0055 58 | {0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+0056 59 | {0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00}, // U+0057 60 | {0xC3, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0xC3, 0x00}, // U+0058 61 | {0xC3, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+0059 62 | {0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00}, // U+005A 63 | {0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00}, // U+005B 64 | {0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x00}, // U+005C 65 | {0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00}, // U+005D 66 | {0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00}, // U+005E 67 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F 68 | {0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 69 | {0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00}, // U+0061 70 | {0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00}, // U+0062 71 | {0x00, 0x00, 0x3C, 0x60, 0x60, 0x60, 0x3C, 0x00}, // U+0063 72 | {0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00}, // U+0064 73 | {0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, // U+0065 74 | {0x1C, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x30, 0x00}, // U+0066 75 | {0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x7C}, // U+0067 76 | {0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00}, // U+0068 77 | {0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+0069 78 | {0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x78}, // U+006A 79 | {0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00}, // U+006B 80 | {0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+006C 81 | {0x00, 0x00, 0xCC, 0xFE, 0xD6, 0xD6, 0xC6, 0x00}, // U+006D 82 | {0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00}, // U+006E 83 | {0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+006F 84 | {0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60}, // U+0070 85 | {0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x06}, // U+0071 86 | {0x00, 0x00, 0x7C, 0x66, 0x60, 0x60, 0x60, 0x00}, // U+0072 87 | {0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00}, // U+0073 88 | {0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x1E, 0x00}, // U+0074 89 | {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00}, // U+0075 90 | {0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+0076 91 | {0x00, 0x00, 0xC6, 0xC6, 0xD6, 0x7C, 0x6C, 0x00}, // U+0077 92 | {0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00}, // U+0078 93 | {0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C}, // U+0079 94 | {0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00}, // U+007A 95 | {0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0x00}, // U+007B 96 | {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+007C 97 | {0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0x00}, // U+007D 98 | {0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E 99 | {0xC0, 0xA0, 0xAE, 0xA4, 0xC4, 0x04, 0x04, 0x00}, // U+007F 100 | {0xE0, 0xA0, 0xEE, 0xAA, 0xEA, 0x0A, 0x0E, 0x00}, // U+0080 101 | {0xE0, 0xA0, 0xE4, 0xAC, 0xE4, 0x04, 0x0E, 0x00}, // U+0081 102 | {0xE0, 0xA0, 0xEE, 0xA2, 0xEE, 0x08, 0x0E, 0x00}, // U+0082 103 | {0xE0, 0xA0, 0xEE, 0xA2, 0xEE, 0x02, 0x0E, 0x00}, // U+0083 104 | {0xE0, 0x40, 0x4E, 0x4A, 0xEA, 0x0A, 0x0A, 0x00}, // U+0084 105 | {0xE0, 0xA0, 0xA8, 0xA8, 0xA8, 0x08, 0x0E, 0x00}, // U+0085 106 | {0xE0, 0x80, 0xEE, 0x28, 0xEE, 0x02, 0x0E, 0x00}, // U+0086 107 | {0xE0, 0x80, 0xCE, 0x88, 0xEE, 0x02, 0x0E, 0x00}, // U+0087 108 | {0xA0, 0xA0, 0xEE, 0xA8, 0xAE, 0x02, 0x0E, 0x00}, // U+0088 109 | {0xA0, 0xA0, 0xE2, 0xA2, 0xA2, 0x0A, 0x0E, 0x00}, // U+0089 110 | {0xA0, 0xA0, 0xAE, 0xA8, 0x4E, 0x02, 0x0E, 0x00}, // U+008A 111 | {0xE0, 0xA0, 0xEC, 0x8A, 0x8A, 0x0A, 0x0C, 0x00}, // U+008B 112 | {0xE0, 0xA0, 0xEA, 0x8A, 0x8A, 0x0A, 0x0E, 0x00}, // U+008C 113 | {0xC0, 0xA0, 0xCE, 0xA4, 0xA4, 0x04, 0x0E, 0x00}, // U+008D 114 | {0xE0, 0x80, 0xEE, 0x22, 0xEE, 0x08, 0x0E, 0x00}, // U+008E 115 | {0xE0, 0x80, 0xEE, 0x22, 0xE6, 0x02, 0x0E, 0x00}, // U+008F 116 | {0xC0, 0xA0, 0xAE, 0xA8, 0xC8, 0x08, 0x0E, 0x00}, // U+0090 117 | {0xE0, 0xA0, 0xE4, 0x8C, 0x84, 0x04, 0x0E, 0x00}, // U+0091 118 | {0xE0, 0xA0, 0xEE, 0x82, 0x8E, 0x08, 0x0E, 0x00}, // U+0092 119 | {0xE0, 0x80, 0xEE, 0x28, 0xEC, 0x08, 0x0E, 0x00}, // U+0093 120 | {0xE0, 0x80, 0x8E, 0x88, 0xE8, 0x08, 0x0E, 0x00}, // U+0094 121 | {0xA0, 0xE0, 0xEA, 0xAA, 0xAE, 0x0E, 0x0A, 0x00}, // U+0095 122 | {0xE0, 0x80, 0xEE, 0x2A, 0xEE, 0x08, 0x08, 0x00}, // U+0096 123 | {0xE0, 0x80, 0xCE, 0x8A, 0xEE, 0x08, 0x08, 0x00}, // U+0097 124 | {0xE0, 0xA0, 0xEE, 0x2A, 0xEE, 0x0A, 0x0E, 0x00}, // U+0098 125 | {0xE0, 0xA0, 0xEE, 0x2A, 0xEE, 0x02, 0x0E, 0x00}, // U+0099 126 | {0xE0, 0xA0, 0xEE, 0x2A, 0xEE, 0x0A, 0x0A, 0x00}, // U+009A 127 | {0xE0, 0x80, 0x8E, 0x88, 0xEE, 0x02, 0x0E, 0x00}, // U+009B 128 | {0xE0, 0x80, 0xEE, 0x24, 0xE4, 0x04, 0x04, 0x00}, // U+009C 129 | {0xE0, 0xA0, 0xAE, 0xA8, 0xEE, 0x02, 0x0E, 0x00}, // U+009D 130 | {0xE0, 0xA0, 0xEA, 0x8E, 0x8E, 0x0A, 0x0A, 0x00}, // U+009E 131 | {0xE0, 0xA0, 0xEE, 0xAA, 0xAE, 0x08, 0x08, 0x00}, // U+009F 132 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A0 133 | {0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 134 | {0x00, 0x18, 0x7E, 0xD8, 0xD8, 0x7E, 0x18, 0x00}, // U+00A2 135 | {0x38, 0x6C, 0x60, 0xF0, 0x60, 0x66, 0xFC, 0x00}, // U+00A3 136 | {0x66, 0x3C, 0x66, 0x3C, 0x66, 0x00, 0x00, 0x00}, // U+00A4 137 | {0xC3, 0x66, 0x3C, 0x18, 0x3C, 0x18, 0x18, 0x00}, // U+00A5 138 | {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+00A6 139 | {0x3C, 0x60, 0x3C, 0x66, 0x66, 0x3C, 0x06, 0x3C}, // U+00A7 140 | {0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A8 141 | {0x7E, 0x81, 0x9D, 0xB1, 0xB1, 0x9D, 0x81, 0x7E}, // U+00A9 142 | {0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00}, // U+00AA 143 | {0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00AB 144 | {0x00, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // U+00AC 145 | {0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00}, // U+00AD 146 | {0x7E, 0x81, 0xB9, 0xA5, 0xB9, 0xA5, 0x81, 0x7E}, // U+00AE 147 | {0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AF 148 | {0x3C, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00B0 149 | {0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00}, // U+00B1 150 | {0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00}, // U+00B2 151 | {0x78, 0x0C, 0x18, 0x0C, 0x78, 0x00, 0x00, 0x00}, // U+00B3 152 | {0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00B4 153 | {0x00, 0x00, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0}, // U+00B5 154 | {0x3E, 0x7A, 0x7A, 0x3A, 0x1A, 0x1A, 0x1A, 0x00}, // U+00B6 155 | {0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00}, // U+00B7 156 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0x00}, // U+00B8 157 | {0x30, 0x70, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00}, // U+00B9 158 | {0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00}, // U+00BA 159 | {0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00BB 160 | {0x43, 0xC6, 0x4C, 0x5A, 0x36, 0x6A, 0xCF, 0x02}, // U+00BC 161 | {0x40, 0xC6, 0x4C, 0x5E, 0x33, 0x66, 0xCC, 0x0F}, // U+00BD 162 | {0xC0, 0x23, 0x66, 0x2D, 0xDB, 0x35, 0x67, 0x01}, // U+00BE 163 | {0x18, 0x00, 0x18, 0x30, 0x60, 0x66, 0x3C, 0x00}, // U+00BF 164 | {0x70, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+00C0 165 | {0x0E, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+00C1 166 | {0x18, 0x66, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x00}, // U+00C2 167 | {0x76, 0xDC, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x00}, // U+00C3 168 | {0x66, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+00C4 169 | {0x18, 0x18, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x00}, // U+00C5 170 | {0x3F, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCF, 0x00}, // U+00C6 171 | {0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18}, // U+00C7 172 | {0x70, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+00C8 173 | {0x0E, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+00C9 174 | {0x18, 0x66, 0x00, 0xFE, 0xF0, 0xC0, 0xFE, 0x00}, // U+00CA 175 | {0x66, 0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x00}, // U+00CB 176 | {0x70, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x00}, // U+00CC 177 | {0x0E, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x00}, // U+00CD 178 | {0x18, 0x66, 0x00, 0x7E, 0x18, 0x18, 0x7E, 0x00}, // U+00CE 179 | {0x66, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x00}, // U+00CF 180 | {0x78, 0x6C, 0x66, 0xF6, 0x66, 0x6C, 0x78, 0x00}, // U+00D0 181 | {0x76, 0xDC, 0x00, 0xC6, 0xF6, 0xDE, 0xC6, 0x00}, // U+00D1 182 | {0x70, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00D2 183 | {0x0E, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00D3 184 | {0x18, 0x66, 0x00, 0x7C, 0xC6, 0xC6, 0x7C, 0x00}, // U+00D4 185 | {0x76, 0xDC, 0x00, 0x7C, 0xC6, 0xC6, 0x7C, 0x00}, // U+00D5 186 | {0x66, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00D6 187 | {0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, 0x00}, // U+00D7 188 | {0x3E, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x7C, 0x00}, // U+00D8 189 | {0x70, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00D9 190 | {0x0E, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00DA 191 | {0x18, 0x66, 0x00, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00DB 192 | {0x66, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00}, // U+00DC 193 | {0x0E, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00}, // U+00DD 194 | {0xC0, 0xC0, 0xFC, 0xC6, 0xFC, 0xC0, 0xC0, 0x00}, // U+00DE 195 | {0x3C, 0x66, 0x66, 0x6C, 0x66, 0x66, 0x6C, 0x00}, // U+00DF 196 | {0x70, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00}, // U+00E0 197 | {0x0E, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00}, // U+00E1 198 | {0x18, 0x66, 0x00, 0x3E, 0x66, 0xC6, 0x7E, 0x00}, // U+00E2 199 | {0x76, 0xDC, 0x00, 0x3E, 0x66, 0xC6, 0x7E, 0x00}, // U+00E3 200 | {0x66, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00}, // U+00E4 201 | {0x18, 0x18, 0x00, 0x3E, 0x66, 0xC6, 0x7E, 0x00}, // U+00E5 202 | {0x00, 0x00, 0x7E, 0x1B, 0x7F, 0xD8, 0x77, 0x00}, // U+00E6 203 | {0x00, 0x00, 0x3C, 0x60, 0x60, 0x60, 0x3C, 0x18}, // U+00E7 204 | {0x70, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, // U+00E8 205 | {0x0E, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, // U+00E9 206 | {0x18, 0x66, 0x00, 0x3C, 0x7E, 0x60, 0x3C, 0x00}, // U+00EA 207 | {0x66, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, // U+00EB 208 | {0x70, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EC 209 | {0x0E, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00ED 210 | {0x18, 0x66, 0x00, 0x38, 0x18, 0x18, 0x3C, 0x00}, // U+00EE 211 | {0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EF 212 | {0x0C, 0x3E, 0x0C, 0x7C, 0xCC, 0xCC, 0x78, 0x00}, // U+00F0 213 | {0x76, 0xDC, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x00}, // U+00F1 214 | {0x70, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00F2 215 | {0x0E, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00F3 216 | {0x18, 0x66, 0x00, 0x3C, 0x66, 0x66, 0x3C, 0x00}, // U+00F4 217 | {0x76, 0xDC, 0x00, 0x3C, 0x66, 0x66, 0x3C, 0x00}, // U+00F5 218 | {0x66, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00F6 219 | {0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00}, // U+00F7 220 | {0x00, 0x02, 0x7C, 0xCE, 0xD6, 0xE6, 0x7C, 0x80}, // U+00F8 221 | {0x70, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00}, // U+00F9 222 | {0x0E, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00}, // U+00FA 223 | {0x18, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x00}, // U+00FB 224 | {0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00}, // U+00FC 225 | {0x0E, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C}, // U+00FD 226 | {0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60}, // U+00FE 227 | {0x66, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C}, // U+00FF 228 | }; --------------------------------------------------------------------------------