REF: Renamed kernel -> System; userspace -> Runtime; bootloader -> Boot

del: KSH
This commit is contained in:
Karina
2026-04-04 19:44:39 +04:00
parent 2f58f64175
commit 47735bb1bd
117 changed files with 10 additions and 274 deletions
+69
View File
@@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.20)
project(dewar LANGUAGES C ASM_NASM)
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
if (NOT DEFINED ARCH)
set(ARCH "x86_64")
endif()
message(STATUS "Dewar kernel: Building for architecture '${ARCH}'")
file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
"src/kmain.c"
"src/arch/${ARCH}/*.c"
"src/arch/${ARCH}/*.asm"
"src/OS/*.c"
"src/OS/Exec/*.c"
"src/OS/Services/*.c"
"src/lib/*.c"
"src/IO/*.c"
"src/VM/*.c"
"src/FS/*.c"
"Data/*.c"
)
add_executable(kernel ${KERNEL_SOURCES})
target_include_directories(kernel PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../common"
"${CMAKE_CURRENT_SOURCE_DIR}/inc"
"${CMAKE_CURRENT_SOURCE_DIR}/inc/arch/${ARCH}"
"${CMAKE_CURRENT_SOURCE_DIR}/Data"
)
target_compile_options(kernel PRIVATE
$<$<COMPILE_LANGUAGE:C>:
-ffreestanding
-mno-red-zone
-fno-stack-protector
-fno-builtin
-Wall -Wextra
-mcmodel=kernel
-g
>
)
target_link_options(kernel PRIVATE
-nostdlib
-static
-no-pie
-T "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld"
-z max-page-size=0x1000
)
set_target_properties(kernel PROPERTIES
OUTPUT_NAME "kernel.elf"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
add_custom_command(TARGET kernel POST_BUILD
COMMAND objcopy -O binary $<TARGET_FILE:kernel> $<TARGET_FILE_DIR:kernel>/kernel.bin
COMMENT "Generating raw binary kernel.bin..."
)
+134
View File
@@ -0,0 +1,134 @@
#pragma once
#include <types.h>
unsigned char VGAFont[][16] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x00,
{ 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x01,
{ 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x02,
{ 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, }, //0x03,
{ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x04,
{ 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x05,
{ 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x06,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x07,
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, //0x08,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x09,
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }, //0x0A,
{ 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, }, //0x0B,
{ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x0C,
{ 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, }, //0x0D,
{ 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, }, //0x0E,
{ 0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x0F,
{ 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, }, //0x10,
{ 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, }, //0x11,
{ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x12,
{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, }, //0x13,
{ 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, }, //0x14,
{ 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, }, //0x15,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, }, //0x16,
{ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x17,
{ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x18,
{ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x19,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x1A,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x1B, esc
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x1C,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x1D,
{ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x1E,
{ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x1F,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x20, ' '
{ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x21, '!'
{ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x22, '"'
{ 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, }, //0x23, '#'
{ 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, }, //0x24, '$'
{ 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, }, //0x25, '%'
{ 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, }, //0x26, '&'
{ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x27, '''
{ 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, }, //0x28, '('
{ 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, }, //0x29, ')'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x2A, '*'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x2B, '+'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, }, //0x2C, '
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x2D, '-'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x2E, '.'
{ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, }, //0x2F, '/'
{ 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xD6, 0xD6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, }, //0x30, '0'
{ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x31, '1'
{ 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, }, //0x32, '2'
{ 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x33, '3'
{ 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, }, //0x34, '4'
{ 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x35, '5'
{ 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x36, '6'
{ 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, }, //0x37, '7'
{ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x38, '8'
{ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, }, //0x39, '9'
{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x3A, ':'
{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, }, //0x3B, ';'
{ 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, }, //0x3C, '<'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x3D, '='
{ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, }, //0x3E, '>'
{ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x3F, '?'
{ 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x40, '@'
{ 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x41, 'A'
{ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, }, //0x42, 'B'
{ 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x43, 'C'
{ 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, }, //0x44, 'D'
{ 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, }, //0x45, 'E'
{ 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, }, //0x46, 'F'
{ 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, }, //0x47, 'G'
{ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x48, 'H'
{ 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x49, 'I'
{ 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, }, //0x4A, 'J'
{ 0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, }, //0x4B, 'K'
{ 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, }, //0x4C, 'L'
{ 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x4D, 'M'
{ 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x4E, 'N'
{ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x4F, 'O'
{ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, }, //0x50, 'P'
{ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, }, //0x51, 'Q'
{ 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, }, //0x52, 'R'
{ 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x53, 'S'
{ 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x54, 'T'
{ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x55, 'U'
{ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, }, //0x56, 'V'
{ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00, }, //0x57, 'W'
{ 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x58, 'X'
{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x59, 'Y'
{ 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, }, //0x5A, 'Z'
{ 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x5B, '['
{ 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, }, //0x5C, '\'
{ 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x5D, ']'
{ 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x5E, '^'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, }, //0x5F, '_'
{ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x60, '`'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, }, //0x61, 'a'
{ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x62, 'b'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x63, 'c'
{ 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, }, //0x64, 'd'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x65, 'e'
{ 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, }, //0x66, 'f'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, }, //0x67, 'g'
{ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, }, //0x68, 'h'
{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x69, 'i'
{ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, }, //0x6A, 'j'
{ 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, }, //0x6B, 'k'
{ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, }, //0x6C, 'l'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x6D, 'm'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, }, //0x6E, 'n'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x6F, 'o'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, }, //0x70, 'p'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, }, //0x71, 'q'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, }, //0x72, 'r'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, }, //0x73, 's'
{ 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, }, //0x74, 't'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, }, //0x75, 'u'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x76, 'v'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, }, //0x77, 'w'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, }, //0x78, 'x'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, }, //0x79, 'y'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, }, //0x7A, 'z'
{ 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00, }, //0x7B, '{'
{ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, }, //0x7C, '|'
{ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, }, //0x7D, '}'
{ 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x7E, '~'
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x7F, delete
};
+40
View File
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// cats licensed to their authors
// i took it from https://www.asciiart.eu/animals/cats
#pragma once
const char *cats[] = {
" _\n"
" | \\\n"
" | |\n"
" | |\n"
" |\\ | |\n"
" /, ~\\ / /\n"
"X `-.....-------./ /\n"
" ~-. ~ ~ |\n"
" \\ / |\n"
" \\ /_ ___\\ /\n"
" | /\\ ~~~~~ \\ |\n"
" | | \\ || |\n"
" | |\\ \\ || )\n"
" (_/ (_/ ((_/\n",
" _._ _,-'\"\"`-._\n"
"(,-.`._,'( |\\`-/|\n"
" `-.-' \\ )-`( , o o)\n"
" `- \\`_`\"'-\n",
" /\\_/\\\n"
"( o.o )\n"
" > ^ <\n",
" /\\_____/\\\n"
" / o o \\\n"
" ( == ^ == )\n"
" ) (\n"
" ( )\n"
" ( ( ) ( ) )\n"
"(___(__)___(__)__)\n"
};
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <FS/VFS.h>
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize);
+42
View File
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef enum FSVNodeFlags {
kFSVNodeFlagFile = 0x01,
kFSVNodeFlagDirectory = 0x02,
} FSVNodeFlags;
typedef struct FSVNode FSVNode;
typedef struct FSVNodeOperations {
UInt64 (*read)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
UInt64 (*write)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
void (*open)(FSVNode* node);
void (*close)(FSVNode* node);
FSVNode* (*findDirectory)(FSVNode* node, char* name);
} FSVNodeOperations;
typedef struct FSVNode {
char name[256];
UInt32 protectionMask;
UInt32 ownerIdentifier;
UInt32 groupIdentifier;
UInt32 flags;
UInt32 inodeIdentifier;
UInt64 dataLength;
FSVNodeOperations* operations;
void* implementationData;
struct FSVNode* mountPoint;
struct FSVNode* childNode;
struct FSVNode* nextNode;
} FSVNode;
void FSVirtualFileSystemInitialize(FSVNode* rootNode);
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
FSVNode* FSVirtualFileSystemOpenPath(const char* path);
void FSVNodeClose(FSVNode* node);
+35
View File
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
enum {
kIOConsoleColorRed = 0xFF5555,
kIOConsoleColorVeryRed = 0xFF0000,
kIOConsoleColorGreen = 0x08bf39,
kIOConsoleColorVeryGreen = 0x00FF00,
kIOConsoleColorTurqoise = 0x5effaf,
kIOConsoleColorBlue = 0x5555FF,
kIOConsoleColorVeryBlue = 0x0000FF,
kIOConsoleColorLightBlue = 0x3890e8,
kIOConsoleColorYellow = 0xFFFF55,
kIOConsoleColorCyan = 0x55FFFF,
kIOConsoleColorMagneta = 0xFF55FF,
kIOConsoleColorBlack = 0x000000,
kIOConsoleColorWhite = 0xFFFFFF,
kIOConsoleColorPink = 0xFFA3B1,
};
void IOConsoleInit(IOGraphicsContext* context);
UInt64 IOConsoleGetColors();
void IOConsoleClear(IOGraphicsColor color);
IOGraphicsContext* IOConsoleGetGraphicsContext();
IOGraphicsSize IOConsoleGetDimensions();
void IOConsoleSetForegroundColor(IOGraphicsColor color);
void IOConsoleSetDefaultForegroundColor(UInt32 color);
void IOConsoleSetCursorPosition(IOGraphicsPoint* point);
void IOConsoleReadLine(char* buffer, UInt32 limit);
void IOConsolePutcharacter(char character);
void IOConsolePrint(const char *string);
void IOConsoleLog(const char *fmt, ...);
+50
View File
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// RIP shitgui -- you started it all
#pragma once
#include <types.h>
typedef UInt32 IOGraphicsColor;
typedef struct {
UInt32 x;
UInt32 y;
} IOGraphicsPoint;
typedef struct {
UInt32 width;
UInt32 height;
} IOGraphicsSize;
typedef struct {
volatile UInt32* framebuffer;
IOGraphicsSize dimensions;
UInt32 pixelsPerScanLine;
} IOGraphicsContext;
typedef struct {
IOGraphicsColor* buffer;
IOGraphicsSize size;
} IOGraphicsImage;
typedef struct {
IOGraphicsSize size;
const unsigned char* baseAddress;
} IOGraphicsFont;
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point);
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image);
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point,
IOGraphicsSize* size, IOGraphicsColor color);
void IOGraphicsDrawCharacter(
IOGraphicsContext* context,
IOGraphicsPoint* point,
char character,
IOGraphicsColor color,
IOGraphicsFont* font
);
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <OS/OSSpinlock.h>
enum {
kIOKeyboardBufferSize = 256,
};
typedef struct {
OSSpinlock lock;
char buffer[kIOKeyboardBufferSize];
volatile UInt16 head;
volatile UInt16 tail;
} IOKeyboardController;
extern IOKeyboardController gIOKeyboardController;
void IOKeyboardInterruptsHandler();
char IOKeyboardGetCharacter();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
int IOSerialInit();
void IOSerialWriteChar(char character);
void IOSerialWrite(const char *string);
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
void IOTimerInitialize(UInt32 freq);
UInt64 IOTimerInterruptsHandler(CPURegisters *regs);
UInt64 IOTimerGetTicks();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <OS/OSScheduler.h>
UInt64 HOTLoad(OSProcess* process, UInt8* data);
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName);
void initTask();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame);
__attribute__((noreturn)) void OSPanic(const char* msg);
+45
View File
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef enum OSProcessState {
kOSProcessStateDead,
kOSProcessStateRunning,
kOSProcessStateReady,
kOSProcessStateBlocked,
kOSProcessStateSleeping,
} OSProcessState;
typedef struct OSProcess {
UInt64 processId;
OSProcessState state;
UInt64 physicalPML4;
struct OSProcess* parent;
char name[32];
UInt64 heapStartPointer;
UInt64 heapCurrentPointer;
} OSProcess;
typedef struct OSTask {
UInt64 stackPointer;
struct OSTask* next;
UInt32 id;
UInt32 sleepTicks;
OSProcessState taskState; // reusing process_state cuz wn
UInt64 kernelStackTop;
void* kernelStackBase;
OSProcess* process;
Int32 waitingForProcess;
} OSTask;
void OSSchedulerInitialize();
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer);
UInt64 OSSchedulerNext(UInt64 currentStackPointer);
void OSSchedulerYield(UInt64 ticks);
void OSSchedulerBlock(UInt32 processID);
void OSSchedulerWakeup(UInt32 processID);
void OSSchedulerTerminate(); // suicide
extern OSTask* gOSSchedulerCurrentTask;
+19
View File
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef struct OSSpinlock {
volatile UInt32 lockValue;
} OSSpinlock;
typedef struct OSSpinlockState {
Boolean interruptsEnabled;
} OSSpinlockState;
void OSSpinlockLock(OSSpinlock* lock);
void OSSpinlockUnlock(OSSpinlock* lock);
void OSSpinlockLockIRQ(OSSpinlock* lock, OSSpinlockState* state);
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState* state);
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length);
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count);
+7
View File
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
UInt64 OSServiceMemoryAllocate(UInt64 size);
+10
View File
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
Int32 OSServiceProcessExit(Int32 code);
Int32 OSServiceProcessSpawn(const char* path);
Int32 OSServiceProcessWait(UInt64 pid);
+26
View File
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
enum {
kVMKernelHeapStart = 0xFFFFFFFFC0000000,
kVMHeapSizePages = 1024,
kVMHeapBlockHeaderMagic = 0x1CE
};
#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START)
#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START)
typedef struct VMHeapBlockHeader {
UInt64 magic;
struct VMHeapBlockHeader* next;
struct VMHeapBlockHeader* previous;
UInt64 size;
bool isFree;
} VMHeapBlockHeader;
void VMHeapInitialize();
void* VMHeapAllocate(UInt64 size);
void VMHeapFree(void* ptr);
void* VMHeapResize(void* ptr, UInt64 newSize);
+49
View File
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include "bootinfo.h"
#include <types.h>
#define kVMPageSize 4096
#define kVMSafeSpaceStartAddress 0x100000
#define kVMBlocksPerByte 8
#define BITMAP_BYTE_INDEX(address) ((address / kVMPageSize) / kVMBlocksPerByte)
#define BITMAP_BIT_OFFSET(address) ((address / kVMPageSize) % kVMBlocksPerByte)
#define BITMAP_TEST(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] & (1 << BITMAP_BIT_OFFSET(address)))
#define BITMAP_SET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] |= (1 << BITMAP_BIT_OFFSET(address)))
#define BITMAP_UNSET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] &= ~(1 << BITMAP_BIT_OFFSET(address)))
typedef struct {
UInt32 type;
UInt32 padding;
UInt64 physicalStart;
UInt64 virtualStart;
UInt64 pageCount;
UInt64 attributes;
} __attribute__((packed)) OSMemoryDescriptor;
typedef enum {
kOSMemoryTypeReserved,
kOSMemoryTypeLoaderCode,
kOSMemoryTypeLoaderData,
kOSMemoryTypeBootServicesCode,
kOSMemoryTypeBootServicesData,
kOSMemoryTypeRuntimeServicesCode,
kOSMemoryTypeRuntimeServicesData,
kOSMemoryTypeConventional,
kOSMemoryTypeUnusable,
kOSMemoryTypeACPIReclaim,
kOSMemoryTypeACPINonVolatile,
kOSMemoryTypeMappedIO,
kOSMemoryTypeMappedIOPortSpace,
kOSMemoryTypePalCode,
kOSMemoryTypePersistent,
kOSMemoryTypeMax
} OSMemoryType;
UInt64 VMPhysicalMemoryGetTotalMemorySize();
void VMPhysicalMemoryInitialize(BIMemoryMap* mmap);
void* VMPhysicalMemoryAllocatePage();
void VMPhysicalMemoryFreePage(void* addr);
+43
View File
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include "bootinfo.h"
#include <types.h>
#define PTE_PRESENT (1ULL << 0) // 0 -- not present: page fault when trying to access; 1 -- present, can RW
#define PTE_RW (1ULL << 1) // 0 -- RO: page fault trying to write; 1 -- RW
#define PTE_USER (1ULL << 2) // 0 -- Ring 0: R3 get segfault gtrying to access; 1 -- Ring 3
#define PTE_PWT (1ULL << 3) // 1 -- skip L1/L2 cache when writing to RAM
#define PTE_PCD (1ULL << 4) // 1 -- cache disabled for page
#define PTE_ACCESSED (1ULL << 5) // CPU sets it (by itself) to 1 when RW this page
#define PTE_DIRTY (1ULL << 6) // CPU sets it when writing to this page
#define PTE_NX (1ULL << 63) // No execute
#define PTE_ADDR_MASK 0x000FFFFFFFFFF000 // mask to get clean physical addres that located at bits 12-51
#define PTE_GET_ADDR(entry) ((entry) & PTE_ADDR_MASK) // get physical address
#define PTE_GET_FLAGS(entry) ((entry) & ~PTE_ADDR_MASK) // get flags
#define VMM_PT_INDEX(virt) (((virt) >> 12) & 0x1FF) // Table Index (bits 12-20)
#define VMM_PD_INDEX(virt) (((virt) >> 21) & 0x1FF) // Page Directory Index (bits 21-29)
#define VMM_PDPT_INDEX(virt) (((virt) >> 30) & 0x1FF) // PDPT Index (bits 30-38)
#define VMM_PML4_INDEX(virt) (((virt) >> 39) & 0x1FF) // PML4 Index (bits 39-47): main page
#define KERNEL_VMA 0xFFFFFFFF80000000
#define HHDM_OFFSET 0xFFFF888000000000
#define FB_VIRT_BASE 0xFFFFFFFFFC000000
#define KERNEL_VIRT_TO_PHYS(virt) ((virt) - KERNEL_VMA)
#define PHYS_TO_HHDM(phys) ((phys) + HHDM_OFFSET)
#define HHDM_TO_PHYS(virt) ((virt) - HHDM_OFFSET)
void VMVirtualMemoryInitialize(Bootinfo* info);
UInt64* VMVirtualMemoryMapPage(UInt64* PML4, UInt64 physical, UInt64 virtual, UInt64 flags);
UInt64 VMVirtualMemoryCreateAddressSpace();
UInt64 VMGetCurrentCR3();
void VMLoadCR3(UInt64 PML4Address);
void VMVirtualMemorySetupUserStack(UInt64* physicalPML4);
+45
View File
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#define kHALGDTEntries 7
typedef struct {
UInt16 limitLow;
UInt16 baseLow;
UInt8 baseMiddle;
UInt8 access;
UInt8 granularity;
UInt8 baseHigh;
} __attribute__((packed)) HALGlobalDescriptorTable;
typedef struct {
UInt16 limit;
UInt64 base;
} __attribute__((packed)) HALGlobalDescriptorTablePointer;
typedef struct {
UInt32 reserved0;
UInt64 rsp0;
UInt64 rsp1;
UInt64 rsp2;
UInt64 reserved1;
UInt64 ist1;
UInt64 ist2;
UInt64 ist3;
UInt64 ist4;
UInt64 ist5;
UInt64 ist6;
UInt64 ist7;
UInt64 reserved2;
UInt16 reserved3;
UInt16 iomapBase;
} __attribute__((packed)) HALTaskStateSegment;
extern HALTaskStateSegment gHALTaskStateSegment;
void HALGlobalDescriptorTableInitialize();
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef struct {
UInt16 offsetLow;
UInt16 selector;
UInt8 ist;
UInt8 attributes;
UInt16 offsetMid;
UInt32 offsetHigh;
UInt32 reserved;
} __attribute__((packed)) HALInterruptsDescriptorTableEntry;
typedef struct {
UInt16 limit;
UInt64 base;
} __attribute__((packed)) HALInterruptsDescriptorTablePointer;
void HALInterruptsDescriptorTableInitialize();
+44
View File
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
enum {
kIOMasterCommand = 0x20,
kIOMasterData = 0x21,
kIOSlaveCommand = 0xA0,
kIOSlaveData = 0xA1,
kIOPortWaitAddress = 0x80
};
static inline void IOPortWrite8(UInt16 port, UInt8 val) {
__asm__ volatile(
"outb %0, %1"
:
: "a"(val),
"Nd"(port) );
}
static inline unsigned char IOPortRead8(UInt16 port) {
unsigned char ret;
__asm__ volatile(
"inb %1, %0"
: "=a"(ret)
: "Nd"(port)
);
return ret;
}
// sending junk to 0x80 (unused) to skip few tacts
// not ideal i know
static inline void IOSynchronizeBus() {
IOPortWrite8(kIOPortWaitAddress, 0x0);
}
static inline void IOPortWrite8WithWait(UInt16 port, UInt8 val) {
IOPortWrite8(port, val);
IOSynchronizeBus();
}
+42
View File
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef enum {
kCPUFeatureFPU = (1ULL << 0),
kCPUFeatureTSC = (1ULL << 1),
kCPUFeatureMSR = (1ULL << 2),
kCPUFeatureAPIC = (1ULL << 3),
kCPUFeatureMTRR = (1ULL << 4),
kCPUFeaturePAE = (1ULL << 5),
kCPUFeatureSSE = (1ULL << 10),
kCPUFeatureSSE2 = (1ULL << 11),
kCPUFeatureSSE3 = (1ULL << 12),
kCPUFeatureSSSE3 = (1ULL << 13),
kCPUFeatureSSE4_1 = (1ULL << 14),
kCPUFeatureSSE4_2 = (1ULL << 15),
kCPUFeatureAVX = (1ULL << 20),
kCPUFeatureF16C = (1ULL << 21),
kCPUFeatureRDRAND = (1ULL << 22),
kCPUFeatureHypervisor = (1ULL << 30)
} OSCPUFeature;
typedef struct {
UInt64 userStackPointer;
UInt64 kernelStackPointer;
UInt64 selfAddress;
UInt64 features;
char vendorID[13];
UInt32 family;
UInt32 model;
} OSCPUData;
extern OSCPUData gOSBootCPU;
void OSCPUInitialize(UInt64 kernelStackTop);
Boolean OSCPUHasFeature(OSCPUFeature feature);
+6
View File
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
UInt16 HALLegacyInterruptControllerRemap();
+28
View File
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
enum {
kHALModelSpecificRegisterExtendedFeatureEnable = 0xC0000080, // EFER
kHALModelSpecificRegisterSystemCallTarget = 0xC0000081, // STAR
kHALModelSpecificRegisterLongSystemCallTarget = 0xC0000082, // LSTAR
kHALModelSpecificRegisterSystemCallFlagMask = 0xC0000084, // FMASK
kHALModelSpecificRegisterGSBase = 0xC0000101, // GS_BASE
kHALModelSpecificRegisterKernelGSBase = 0xC0000102 // KERNEL_GS_BASE
};
enum {
kHALEFERSystemCallExtensionsEnable = 0x01 // SCE
};
typedef enum {
SYS_EXIT,
SYS_SPAWN,
SYS_MEM,
SYS_WRITE,
SYS_READ,
SYS_WAIT,
} Services;
void OSServicesInitialize();
+19
View File
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#define MAX(a, b) ({ \
auto _a = (a); \
auto _b = (b); \
_a > _b ? _a : _b; \
})
static inline int abs(int n) {
return (n < 0) ? -n : n;
}
static inline Int64 i64abs(Int64 n) {
return (n < 0) ? -n : n;
}
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
void RandInitialize();
UInt64 Rand();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
void SplashShow(IOGraphicsContext* IOGraphicsContextPointer);
+14
View File
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
void* MemorySet(void* destination, UInt8 value, UInt64 count);
void* MemoryCopy(void* destination, const void* source, UInt64 count);
Int32 StringCompare(const char* firstString, const char* secondString);
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit);
char* StringCopy(char* destination, const char* source);
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit);
UInt64 StringGetLength(const char* string);
const char* StringFindLastOccurrenceOfCharacter(const char* string, char separator);
+26
View File
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
typedef unsigned char UInt8;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
typedef unsigned long long UInt64;
typedef signed char Int8;
typedef signed short Int16;
typedef signed int Int32;
typedef signed long long Int64;
typedef UInt64 Size;
typedef UInt64 uintptr_t;
typedef struct {
UInt64 rax, rbx, rcx, rdx, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; // Pushed by us
UInt64 interruptNumber, errorCode; // Pushed by macro
UInt64 rip, cs, rflags, rsp, ss; // Pushed by CPU
} CPURegisters;
#define Boolean _Bool
+51
View File
@@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
Copyright (c) 2026 0xKarinyash */
ENTRY(_start)
KERNEL_VMA_OFFSET = 0xFFFFFFFF80000000;
KERNEL_PHYS_START = 0x00100000;
SECTIONS
{
. = KERNEL_VMA_OFFSET + KERNEL_PHYS_START;
_kernel_start = .;
_kernel_phys_start = . - KERNEL_VMA_OFFSET;
.text : AT(ADDR(.text) - KERNEL_VMA_OFFSET) {
*(.text.entry)
*(.text*)
}
.rodata : AT(ADDR(.rodata) - KERNEL_VMA_OFFSET) {
*(.rodata*)
}
.data : AT(ADDR(.data) - KERNEL_VMA_OFFSET) {
*(.data*)
}
.bss : AT(ADDR(.bss) - KERNEL_VMA_OFFSET) {
*(.bss*)
*(COMMON)
}
.stack (ALIGN(16)) : AT(ADDR(.stack) - KERNEL_VMA_OFFSET) {
*(.stack)
}
. = ALIGN(4096);
_kernel_end = .;
_kernel_phys_end = . - KERNEL_VMA_OFFSET;
/DISCARD/ : {
*(.note*)
*(.comment*)
*(.eh_frame*)
*(.interp)
*(.dynsym)
*(.dynstr)
}
}
+122
View File
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <types.h>
#include <FS/CPIO.h>
#include <FS/VFS.h>
#include <lib/String.h>
#include <OS/OSPanic.h>
#include <VM/Heap.h>
#include <IO/IOConsole.h>
#define FSCPIO_ALIGN4(x) (((x) + 3) & ~3)
typedef struct FSCPIOHeader {
char magic[6];
char inode[8];
char mode[8];
char userIdentifier[8];
char groupIdentifier[8];
char linkCount[8];
char modificationTime[8];
char fileLength[8];
char deviceMajor[8];
char deviceMinor[8];
char remoteDeviceMajor[8];
char remoteDeviceMinor[8];
char nameLength[8];
char checkSum[8];
} FSCPIOHeader;
static FSVNodeOperations gFSCPIOOperations = {
.read = FSCPIORead,
.write = nullptr,
.open = nullptr,
.close = nullptr,
};
static UInt64 sFSCPIOHexadecimalToUInt64(const char* string, Int32 length) {
UInt64 result = 0;
for (Int32 i = 0; i < length; i++) {
char character = string[i];
result <<= 4;
if (character >= '0' && character <= '9') result += (character - '0');
else if (character >= 'A' && character <= 'F') result += (character - 'A' + 10);
else if (character >= 'a' && character <= 'f') result += (character - 'a' + 10);
}
return result;
}
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
if (offset > node->dataLength) return 0;
if ((offset + size) > node->dataLength) size = node->dataLength - offset;
MemoryCopy(buffer, (char*)node->implementationData + offset, size);
return size;
}
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize) {
UInt8* currentPointer = (UInt8*)baseAddress;
UInt8* endPointer = currentPointer + totalSize;
FSVNode* rootNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
if (!rootNode) OSPanic("CPIO: Failed to allocate memory for root node");
MemorySet(rootNode, 0, sizeof(FSVNode));
StringCopy(rootNode->name, "/");
rootNode->flags = kFSVNodeFlagDirectory;
rootNode->operations = &gFSCPIOOperations;
FSVNode* tailNode = nullptr;
while (currentPointer < endPointer) {
FSCPIOHeader* header = (FSCPIOHeader*)currentPointer;
if (StringCompareWithLimit(header->magic, "070701", 6) != 0) {
OSPanic("CPIO: Invalid magic detected in StartupVolume");
}
UInt64 nameSize = sFSCPIOHexadecimalToUInt64(header->nameLength, 8);
UInt64 fileSize = sFSCPIOHexadecimalToUInt64(header->fileLength, 8);
char* fileName = (char*)(currentPointer + sizeof(FSCPIOHeader));
if (StringCompare(fileName, "TRAILER!!!") == 0) break;
UInt64 headerAndNameLength = sizeof(FSCPIOHeader) + nameSize;
UInt64 offsetToData = FSCPIO_ALIGN4(headerAndNameLength);
void* fileContent = (void*)(currentPointer + offsetToData);
FSVNode* newNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
if (!newNode) OSPanic("CPIO: Failed to allocate memory for new node");
MemorySet(newNode, 0, sizeof(FSVNode));
StringCopyWithLimit(newNode->name, fileName, sizeof(newNode->name) - 1);
newNode->dataLength = fileSize;
newNode->inodeIdentifier = sFSCPIOHexadecimalToUInt64(header->inode, 8);
newNode->operations = &gFSCPIOOperations;
newNode->implementationData = fileContent;
UInt64 mode = sFSCPIOHexadecimalToUInt64(header->mode, 8);
if ((mode & 0xF000) == 0x4000) {
newNode->flags = kFSVNodeFlagDirectory;
} else {
newNode->flags = kFSVNodeFlagFile;
}
if (rootNode->childNode == nullptr) {
rootNode->childNode = newNode;
} else if (tailNode) {
tailNode->nextNode = newNode;
}
tailNode = newNode;
IOConsoleLog("^bCPIO^!: Found object '^y%s^!' (size: ^y%d^!) at ^y0x%x^!\n", fileName, fileSize, fileContent);
UInt64 dataLengthAligned = FSCPIO_ALIGN4(fileSize);
currentPointer += offsetToData + dataLengthAligned;
}
return rootNode;
}
+53
View File
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <FS/VFS.h>
#include <lib/String.h>
FSVNode* gFSVirtualFileSystemRoot = nullptr;
void FSVirtualFileSystemInitialize(FSVNode* rootNode) {
gFSVirtualFileSystemRoot = rootNode;
}
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
if (!node || !node->operations || !node->operations->read) {
return 0;
}
return node->operations->read(node, offset, size, buffer);
}
FSVNode* FSVirtualFileSystemOpenPath(const char* path) {
if (!gFSVirtualFileSystemRoot) {
return nullptr;
}
if (StringCompare(path, "/") == 0) {
return gFSVirtualFileSystemRoot;
}
const char* searchName = path;
if (path[0] == '/') {
searchName++;
}
FSVNode* nodeIterator = gFSVirtualFileSystemRoot->childNode;
while (nodeIterator != nullptr) {
if (StringCompare(nodeIterator->name, searchName) == 0) {
if (nodeIterator->operations && nodeIterator->operations->open) {
nodeIterator->operations->open(nodeIterator);
}
return nodeIterator;
}
nodeIterator = nodeIterator->nextNode;
}
return nullptr;
}
void FSVNodeClose(FSVNode* node) {
if (node && node->operations && node->operations->close) {
node->operations->close(node);
}
}
+267
View File
@@ -0,0 +1,267 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOConsole.h>
#include <IO/IOSerial.h>
#include <IO/IOGraphics.h>
#include <IO/IOKeyboard.h>
#include <lib/Math.h>
#include <OS/OSScheduler.h>
#include <types.h>
#include <stdarg.h>
#include <Data/VGAFont.h>
static IOGraphicsContext* sIOGraphicsContextPointer = nullptr;
static IOGraphicsPoint sIOConsoleCursorPosition = {0};
static IOGraphicsFont sIOConsoleFont = {0};
static IOGraphicsColor sIOConsoleForegroundColor = kIOConsoleColorWhite;
static IOGraphicsColor sIOConsoleDefaultForegroundColor = kIOConsoleColorWhite;
static IOGraphicsColor sIOConsoleBackgroundColor = kIOConsoleColorBlack;
void IOConsoleInit(IOGraphicsContext *context) {
sIOGraphicsContextPointer = context;
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y = 0;
sIOConsoleFont.size.height = 16;
sIOConsoleFont.size.width = 8;
sIOConsoleFont.baseAddress = (const unsigned char*)VGAFont;
}
UInt64 IOConsoleGetColors() {
return ((UInt64) sIOConsoleForegroundColor << 32) | sIOConsoleBackgroundColor;
}
void IOConsoleClear(IOGraphicsColor color) {
if (!sIOGraphicsContextPointer) return;
IOGraphicsPoint point = {0, 0};
IOGraphicsDrawRectangle(
sIOGraphicsContextPointer,
&point,
&sIOGraphicsContextPointer->dimensions,
color
);
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y = 0;
sIOConsoleBackgroundColor = color;
}
IOGraphicsContext* IOConsoleGetGraphicsContext() {
return sIOGraphicsContextPointer;
}
IOGraphicsSize IOConsoleGetDimensions() {
return sIOGraphicsContextPointer->dimensions;
}
void IOConsoleSetCursorPosition(IOGraphicsPoint* point) {
if (!point) return;
sIOConsoleCursorPosition.x = point->x;
sIOConsoleCursorPosition.y = point->y;
}
void IOConsolePutcharacter(char character) {
IOSerialWriteChar(character);
if (!sIOGraphicsContextPointer) return;
if (character == '\n') {
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
} else if (character == '\t') {
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width * 4;
} else if (character == '\b') {
sIOConsoleCursorPosition.x -= sIOConsoleFont.size.width;
IOGraphicsDrawRectangle(
sIOGraphicsContextPointer,
&sIOConsoleCursorPosition,
&sIOConsoleFont.size,
sIOConsoleBackgroundColor
);
} else {
IOGraphicsDrawCharacter(
sIOGraphicsContextPointer,
&sIOConsoleCursorPosition,
character,
sIOConsoleForegroundColor,
&sIOConsoleFont
);
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width;
}
if (sIOConsoleCursorPosition.x >= sIOGraphicsContextPointer->dimensions.width) {
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
}
if (sIOConsoleCursorPosition.y >= sIOGraphicsContextPointer->dimensions.height) {
IOConsoleClear(sIOConsoleBackgroundColor); // TODO: do scrolling
}
}
void IOConsolePrint(const char *string) {
for (Int32 i = 0; string[i] != '\0'; i++) IOConsolePutcharacter(string[i]);
}
static void sIOConsolePrintDecimal(const Int64 number) {
if (number < 0) IOConsolePutcharacter('-');
UInt64 unsignedNumber = abs(number);
char buffer[32];
Int32 i = 0;
do {
buffer[i] = (unsignedNumber % 10) + '0';
unsignedNumber /= 10;
i++;
} while (unsignedNumber > 0);
while (--i >= 0) {
IOConsolePutcharacter(buffer[i]);
}
}
static void sIOConsolePrintHexadecimal(UInt64 unsignedNumber, UInt8 padding) {
IOConsolePutcharacter('0');
IOConsolePutcharacter('x');
if (unsignedNumber == 0) {
IOConsolePutcharacter('0');
for (Int32 i = 1; i < padding; i++) IOConsolePutcharacter('0');
return;
}
char buffer[16] = {0};
Int32 i = 0;
do {
Int32 digit = unsignedNumber % 16;
if (digit < 10) buffer[i++] = digit + '0';
else buffer[i++] = digit - 10 + 'A';
unsignedNumber /= 16;
} while (unsignedNumber > 0);
while(i < padding) {
IOConsolePutcharacter('0');
padding--;
}
while (--i >= 0) {
IOConsolePutcharacter(buffer[i]);
}
}
void IOConsoleLog(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (Int32 i = 0; fmt[i] != '\0'; i++) {
if (fmt[i] == '%') {
i++;
switch (fmt[i]) {
case 's': {
const char *string = va_arg(args, const char*);
if (!string) string = "undefined";
IOConsolePrint(string);
break;
}
case 'c': {
char character = (char)va_arg(args, int);
IOConsolePutcharacter(character);
break;
}
case 'd': {
Int32 number = va_arg(args, Int32);
sIOConsolePrintDecimal(number);
break;
}
case 'x': {
UInt64 number = va_arg(args, UInt64);
sIOConsolePrintHexadecimal(number, 0);
break;
}
case 'X' : {
UInt64 number = va_arg(args, UInt64);
sIOConsolePrintHexadecimal(number, 16);
break;
}
default: {
IOConsolePutcharacter(fmt[i]);
break;
}
}
} else if (fmt[i] == '^') {
i++;
switch (fmt[i]) {
case 'r': IOConsoleSetForegroundColor(kIOConsoleColorRed); break;
case 'R': IOConsoleSetForegroundColor(kIOConsoleColorVeryRed); break;
case 'g': IOConsoleSetForegroundColor(kIOConsoleColorGreen); break;
case 'G': IOConsoleSetForegroundColor(kIOConsoleColorVeryGreen); break;
case 't': IOConsoleSetForegroundColor(kIOConsoleColorTurqoise); break;
case 'b': IOConsoleSetForegroundColor(kIOConsoleColorBlue); break;
case 'B': IOConsoleSetForegroundColor(kIOConsoleColorVeryBlue); break;
case 'l': IOConsoleSetForegroundColor(kIOConsoleColorLightBlue); break;
case 'y': IOConsoleSetForegroundColor(kIOConsoleColorYellow); break;
case 'c': IOConsoleSetForegroundColor(kIOConsoleColorCyan); break;
case 'm': IOConsoleSetForegroundColor(kIOConsoleColorMagneta); break;
case 'p': IOConsoleSetForegroundColor(kIOConsoleColorPink); break;
case '0': IOConsoleSetForegroundColor(kIOConsoleColorBlack); break;
case 'w': IOConsoleSetForegroundColor(kIOConsoleColorWhite); break;
case '!': IOConsoleSetForegroundColor(sIOConsoleDefaultForegroundColor); break;
case '~': IOConsoleSetForegroundColor(~sIOConsoleBackgroundColor); break;
case '^': IOConsolePutcharacter('^'); break;
default: {
IOConsolePutcharacter('^');
IOConsolePutcharacter(fmt[i]);
break;
}
}
} else {
IOConsolePutcharacter(fmt[i]);
}
}
va_end(args);
}
void IOConsoleSetForegroundColor(UInt32 color) {
sIOConsoleForegroundColor = color;
}
void IOConsoleSetDefaultForegroundColor(UInt32 color) {
sIOConsoleDefaultForegroundColor = color;
}
void IOConsoleReadLine(char* buffer, UInt32 limit) {
UInt32 i = 0;
while (true) {
char character = IOKeyboardGetCharacter();
switch (character) {
case '\n': {
buffer[i] = '\0';
IOConsoleLog("\n");
return;
}
case '\b': {
if (i > 0) {
i--;
IOConsoleLog("\b \b");
}
break;
}
default: {
if (i < limit - 1) {
buffer[i] = character;
IOConsoleLog("%c", character);
i++;
}
}
}
}
}
+82
View File
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// RIP shitgui -- you started it all
#include <OS/OSScheduler.h>
#include <OS/OSPanic.h>
#include <IO/IOGraphics.h>
#include <VM/Heap.h>
#include <lib/String.h>
enum {
kIOGraphicsTransparencyKey = 0xFF00FF
};
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point) {
if (!context->framebuffer || !point || point->x >= context->dimensions.width || point->y >= context->dimensions.height) return 0;
return context->framebuffer[point->y * context->pixelsPerScanLine + point->x];
}
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image) {
if (!context->framebuffer || !image) return;
UInt32 startX = point->x;
UInt32 startY = point->y;
UInt32 drawW = image->size.width;
UInt32 drawH = image->size.height;
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
for (UInt32 y = 0; y < drawH; y++) {
volatile UInt32 *destinationPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
UInt32 *sourcePointer = &image->buffer[y * image->size.width];
for (UInt32 x = 0; x < drawW; x++) {
UInt32 color = sourcePointer[x];
if (color != kIOGraphicsTransparencyKey) destinationPointer[x] = color;
}
}
}
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsSize* size, IOGraphicsColor color) {
if (!context->framebuffer) return;
UInt32 startX = point->x;
UInt32 startY = point->y;
UInt32 drawW = size->width;
UInt32 drawH = size->height;
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
for (UInt32 y = 0; y < drawH; y++) {
volatile UInt32* rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
for (UInt32 x = 0; x < drawW; x++) rowPointer[x] = color;
}
}
void IOGraphicsDrawCharacter(IOGraphicsContext* context, IOGraphicsPoint* point, char c, IOGraphicsColor color, IOGraphicsFont* font) {
if (!context->framebuffer) return;
UInt32 startX = point->x;
UInt32 startY = point->y;
UInt32 drawW = font->size.width;
UInt32 drawH = font->size.height;
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
for (UInt32 y = 0; y < drawH; y++) {
UInt8 bitmapRow = font->baseAddress[(unsigned char)c * font->size.height + y];
volatile UInt32 *rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
for (UInt32 x = 0; x < drawW; x++) {
if (bitmapRow & (1 << (7 - x))) {
rowPointer[x] = color;
}
}
}
}
+141
View File
@@ -0,0 +1,141 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOKeyboard.h>
#include <IO/IOConsole.h>
#include <OS/OSSpinlock.h>
#include <OS/OSScheduler.h>
#include <IO.h>
#include <types.h>
static unsigned char sIOKeyboardMap[128] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 0x00 - 0x09 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'q', 'w', 'e', 'r', /* 0x10 - 0x13 */
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
0, /* 0x1D - Control */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 0x1E - 0x27 */
'\'', '`', 0, /* Left shift */
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 0x2C - 0x32 */
'm', ',', '.', '/', 0, /* Right shift */
'*',
0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 0x3B - F1 key ... > */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* < ... F10 */
0, /* 0x45 - Num lock*/
0, /* Scroll Lock */
0, /* Home key */
0, /* Up Arrow */
0, /* Page Up */
'-',
0, /* Left Arrow */
0,
0, /* Right Arrow */
'+',
0, /* 0x4F - End key*/
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert Key */
0, /* Delete Key */
0, 0, 0,
0, /* F11 Key */
0, /* F12 Key */
0, /* All other keys are undefined */
};
static unsigned char sIOKeyboardMapShifted[128] = {
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 0x00 - 0x09 */
'(', ')', '_', '+', '\b', /* Backspace */
'\t', /* Tab */
'Q', 'W', 'E', 'R', /* 0x10 - 0x13 */
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */
0, /* 0x1D - Control */
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 0x1E - 0x27 */
'"', '~', 0, /* Left shift (0x2A) */
'|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 0x2C - 0x32 */
'M', '<', '>', '?', 0, /* Right shift (0x36) */
'*',
0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 0x3B - F1 key ... > */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* < ... F10 */
0, /* 0x45 - Num lock*/
0, /* Scroll Lock */
0, /* Home key */
0, /* Up Arrow */
0, /* Page Up */
'-',
0, /* Left Arrow */
0,
0, /* Right Arrow */
'+',
0, /* 0x4F - End key*/
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert Key */
0, /* Delete Key */
0, 0, 0,
0, /* F11 Key */
0, /* F12 Key */
0, /* All other keys */
};
static Boolean sIOKeyboardIsShiftPressed = false;
IOKeyboardController gIOKeyboardController = {0};
void IOKeyboardInterruptsHandler() {
OSSpinlockLock(&gIOKeyboardController.lock);
UInt16 nextHead = (gIOKeyboardController.head + 1) % kIOKeyboardBufferSize;
UInt8 scancode = IOPortRead8(0x60);
// make code 0x00 - 0x7F; break code = make code + 0x80
if (scancode < 0x80) {
unsigned char* keyMap = sIOKeyboardIsShiftPressed ? sIOKeyboardMapShifted : sIOKeyboardMap;
char ascii = keyMap[scancode];
if (ascii && nextHead != gIOKeyboardController.tail) {
gIOKeyboardController.buffer[gIOKeyboardController.head] = ascii;
gIOKeyboardController.head = nextHead;
} else {
switch (scancode) {
case 0x2A: sIOKeyboardIsShiftPressed = true; break;
default: break;
}
}
} else {
switch (scancode) {
case 0xAA: sIOKeyboardIsShiftPressed = false; break;
default: break;
}
}
OSSpinlockUnlock(&gIOKeyboardController.lock);
}
char IOKeyboardGetCharacter() {
char ascii = 0;
OSSpinlockState state;
while (true) {
OSSpinlockLockIRQ(&gIOKeyboardController.lock, &state);
if (gIOKeyboardController.head != gIOKeyboardController.tail) {
ascii = gIOKeyboardController.buffer[gIOKeyboardController.tail];
gIOKeyboardController.tail = (gIOKeyboardController.tail + 1) % kIOKeyboardBufferSize;
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
return ascii;
}
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
__asm__ volatile ("sti");
OSSchedulerYield(1);
}
}
+33
View File
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOSerial.h>
#include <IO.h>
enum {
kIOCom1Port = 0x3F8,
};
int IOSerialInit() {
IOPortWrite8(kIOCom1Port + 1, 0x00); // interrupt enable register (+1) / disable interruptions
IOPortWrite8(kIOCom1Port + 3, 0x80); // line control register (+3)
IOPortWrite8(kIOCom1Port + 0, 0x03); // speed : low byte
IOPortWrite8(kIOCom1Port + 1, 0x00); // speed : high byte
IOPortWrite8(kIOCom1Port + 3, 0x03); // line control register (+3) / reset DLAB / no parity / 1 stop bit / (8N1)
IOPortWrite8(kIOCom1Port + 2, 0xC7); // FIFO Control register (+2) / 1100 0111 / last ones are enable FIFO buff / first ones to clean noise
IOPortWrite8(kIOCom1Port + 4, 0x0B); // ready :3
return 0;
}
static int IOCheckIsTransmitEmpty() {
return IOPortRead8(kIOCom1Port + 5) & 0x20; // checking 5th bit LSR
}
void IOSerialWriteChar(char character) {
while (IOCheckIsTransmitEmpty() == 0); // waiting for buffer to flush (spinlock)
IOPortWrite8(kIOCom1Port, character);
}
void IOSerialWrite(const char* string) {
for (int i = 0; string[i] != '\0'; i++) IOSerialWriteChar(string[i]);
}
+36
View File
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOTimer.h>
#include <IO.h>
#include <types.h>
#include <OS/OSScheduler.h>
enum {
kIOTimerPitBaseClock = 1193180,
kIOTimerPitCommand = 0x43,
kIOTimerPitData = 0x40,
};
static volatile UInt64 sIOTimerTicks = 0;
void IOTimerInitialize(UInt32 frequency) {
UInt32 divisor = kIOTimerPitBaseClock / frequency;
IOPortWrite8(kIOTimerPitCommand, 0x36); // 0x36 = 00110110 = channel 0, LOHI byte access, Mode 3, binary
IOPortWrite8(kIOTimerPitData, divisor & 0xFF);
IOPortWrite8(kIOTimerPitData, (divisor >> 8) & 0xFF);
UInt8 mask = IOPortRead8(0x21);
mask &= ~(1 << 0);
IOPortWrite8(0x21, mask);
}
UInt64 IOTimerInterruptsHandler(CPURegisters *registers) {
sIOTimerTicks++;
return OSSchedulerNext((UInt64)registers);
}
UInt64 IOTimerGetTicks() {
return sIOTimerTicks;
}
+48
View File
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Exec/HOTLoader.h>
#include <OS/OSScheduler.h>
#include <lib/String.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
#include "../../common/hot_header.h"
UInt64 HOTLoad(OSProcess* process, UInt8* data) {
HOTHeader* header = (HOTHeader*)data;
if (header->magic != HOT_MAGIC) {
return -1;
}
HOTSegment* segments = (HOTSegment*)(data + sizeof(HOTHeader));
for (UInt64 i = 0; i < header->segments_count; i++) {
HOTSegment* segment = &segments[i];
if (segment->memsz == 0) continue;
UInt64 start = segment->vaddr & ~(0xFFFULL);
UInt64 end = (segment->vaddr + segment->memsz + 0xFFF) & ~(0xFFFULL);
for (UInt64 address = start; address < end; address += kVMPageSize) {
void* physicalPage = VMPhysicalMemoryAllocatePage();
VMVirtualMemoryMapPage((UInt64*)process->physicalPML4, (UInt64)physicalPage, address, PTE_USER | PTE_RW | PTE_PRESENT);
void* kernelVirtAddress = (void*)((UInt64)physicalPage + HHDM_OFFSET);
MemorySet(kernelVirtAddress, 0, kVMPageSize);
UInt64 pageOverleapStart = (address > segment->vaddr) ? address : segment->vaddr;
UInt64 pageOverleapEnd = (address + kVMPageSize < segment->vaddr + segment->filesz)
? (address + kVMPageSize)
: (segment->vaddr + segment->filesz);
if (pageOverleapStart < pageOverleapEnd) {
UInt64 copySize = pageOverleapEnd - pageOverleapStart;
UInt64 sourceOffset = segment->offset + (pageOverleapStart - segment->vaddr);
UInt64 destinationOffset = pageOverleapStart - address;
MemoryCopy((UInt8*)kernelVirtAddress + destinationOffset, data + sourceOffset, copySize);
}
}
}
return header->entry_point;
}
+81
View File
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Exec/HOTLoader.h>
#include <OS/Exec/OSLoader.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <lib/String.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
#include <FS/VFS.h>
#include <IO/IOConsole.h>
#include <types.h>
extern UInt32 gOSSchedulerNextProcessID;
enum {
kOSUserStackTop = 0x70000000,
kOSHeapStart = 0x40000000
};
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName) {
FSVNode* executableFile = FSVirtualFileSystemOpenPath(executablePath);
if (!executableFile) {
return -1;
}
OSProcess* newProcess = (OSProcess*)VMHeapAllocate(sizeof(OSProcess));
if (!newProcess) {
return -2;
}
MemorySet(newProcess, 0, sizeof(OSProcess));
newProcess->processId = gOSSchedulerNextProcessID++;
newProcess->state = kOSProcessStateRunning;
newProcess->physicalPML4 = VMVirtualMemoryCreateAddressSpace();
newProcess->heapStartPointer = kOSHeapStart;
newProcess->heapCurrentPointer = kOSHeapStart;
StringCopyWithLimit(newProcess->name, processName, 31);
UInt8* imageBuffer = (UInt8*)VMHeapAllocate(executableFile->dataLength);
if (!imageBuffer) {
VMHeapFree(newProcess);
return -3;
}
FSVNodeRead(executableFile, 0, executableFile->dataLength, imageBuffer);
UInt64 entryPoint = HOTLoad(newProcess, imageBuffer);
if (!entryPoint) {
VMHeapFree(imageBuffer);
VMHeapFree(newProcess);
return -4;
}
VMHeapFree(imageBuffer);
VMVirtualMemorySetupUserStack((UInt64*)newProcess->physicalPML4);
if (!OSSchedulerSpawn((void(*)())entryPoint, newProcess, true, kOSUserStackTop)) {
VMHeapFree(newProcess);
return -5;
}
return newProcess->processId;
}
void initTask() {
Int32 pid = OSLoaderProcessSpawn("/System/CoreServices/init", "init");
if (pid < 0) {
OSPanic("FATAL: Failed to spawn /System/CoreServices/init");
}
while (1) { __asm__("sti; hlt"); }
}
+166
View File
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSPanic.h>
#include <lib/Rand.h>
#include <IO/IOGraphics.h>
#include <IO/IOConsole.h>
#include <types.h>
static const char* sOSPanicFunMessages[] = {
"Execution finished abnormally with code: 0x_x",
"It's definitely your fault.",
"No more Roblox!",
"Call your mom 4 help!",
"2bad4u",
"Touch grass",
"Skill issue",
"You should just go outside actually",
"Perfect opportunity to take a shower",
"404 not found",
"Windows is locked! Password:___ Time left: 5:45:41",
"GOOOOOAL",
"\"NAM PIZDA\": hackers dropped our registry",
"geeked vs locked in",
"HEEEELP!",
"LET ME GO!",
"You little asshole, make it better",
"Go and read books for programming u idiot",
"TIME TO BRAKE! :3 Take a tea and try again later cutie",
"Code have been eaten by Aliens",
"That's all, folks!",
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
"I'll be back",
"Hastla la vista, baby",
"Ti chego mne tut nagovoril...",
"Have you tried turning it off and on again?",
"Put it in rice maybe?",
"Just hit the monitor, it usually helps",
"I think it needs a rest. Come back tomorrow",
"You clicked something wrong, didn't you?",
"You hacked it too hard, bro",
"I think you deleted the internet",
"Stop downloading RAM",
"Pro tip: dont crash",
"Stop ricing the kernel you loonixtard, TermOS is NOT Loonix",
"Attaboy, Jack. He's good. Really good.",
"Zhenih priehal",
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
"fuck off",
"Your GPU is now mining Ethereum for me. Thanks.",
"Your PC is locked!\n\t\t\t\tPay a fee of 0.019082006 bitcoins to a wallet 1KtoProchitalTotSosal to get decryption key!",
};
static const char* sOSPanicExceptionMessages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Reserved",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
"Reserved"
};
__attribute__((noreturn)) static void die() {
while (1) {
__asm__ volatile ("cli; hlt");
}
}
static void sOSPanicDrawPanicBackground() {
IOConsoleClear(0x000000);
IOConsoleSetForegroundColor(0xFFFFFF);
IOConsoleSetDefaultForegroundColor(0xFFFFFF);
UInt64 funMessagesCount = sizeof(sOSPanicFunMessages) / sizeof(sOSPanicFunMessages[0]);
UInt8 randNum = Rand() % funMessagesCount;
IOConsoleLog("\n\n");
IOConsoleLog("\t\t\t\t^bKERNEL PANIC^! :( \n");
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t^y%s^!\n", sOSPanicFunMessages[randNum]);
IOConsoleLog("\t\t--------------------------------\n");
}
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame) {
sOSPanicDrawPanicBackground();
IOConsoleLog("\t\t^yCPU EXCEPTION^!: ^b%s^! (%d)\n", sOSPanicExceptionMessages[frame->interruptNumber], frame->interruptNumber);
if (frame->errorCode) IOConsoleLog("\t\t^yError Code^!: %X\n", frame->errorCode);
IOConsoleLog("\t\t^yInstruction Pointer^! (^yRIP^!): %X\n", frame->rip);
IOConsoleLog("\t\t^yCode Segment^! (^yCS^!): %X\n", frame->cs);
IOConsoleLog("\t\t^yFlags^! (^yRFLAGS^!): %X\n", frame->rflags);
IOConsoleLog("\t\t^yStack Pointer^! (^yRSP^!): %X\n", frame->rsp);
if (frame->interruptNumber == 14) {
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t ^yPage Fault Helper^! \n");
IOConsoleLog("\t\t--------------------------------\n");
UInt64 cr2;
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
IOConsoleLog("\t\t^yFaulting Address^! (^yCR2^!): %X\n", cr2);
IOConsoleLog("\t\t^yERRCode^!: %X\n", frame->errorCode);
UInt64 present = (frame->errorCode & (1 << 0)) != 0;
UInt64 write = (frame->errorCode & (1 << 1)) != 0;
UInt64 user = (frame->errorCode & (1 << 2)) != 0;
UInt64 reserved = (frame->errorCode & (1 << 3)) != 0;
UInt64 instruction = (frame->errorCode & (1 << 4)) != 0;
IOConsoleLog("\t\t\t[^bP^!] ^yReason^!: %s\n", present ? "Page Protection violation" : "Non-present page");
IOConsoleLog("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
IOConsoleLog("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
if (reserved) IOConsoleLog("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
if (instruction) IOConsoleLog("\t\t\t[^bI^!] ^yTried to^! execute ^ycode from^! NX ^ymemory^!\n");
}
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t\t\t^yREGISTERS^!\n");
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t^yRAX^!=%X, ^yRBX^!=%X\n", frame->rax, frame->rbx);
IOConsoleLog("\t\t^yRCX^!=%X, ^yRDX^!=%X\n", frame->rcx, frame->rdx);
IOConsoleLog("\t\t^yRSI^!=%X, ^yRDI^!=%X\n", frame->rsi, frame->rdi);
IOConsoleLog("\t\t^yRBP^!=%X, ^yR8^! =%X\n", frame->rbp, frame->r8);
IOConsoleLog("\t\t^yR9^! =%X, ^yR10^!=%X \n", frame->r9, frame->r10);
IOConsoleLog("\t\t^yR11^!=%X, ^yR12^!=%X\n", frame->r11, frame->r12);
IOConsoleLog("\t\t^yR13^!=%X, ^yR14^!=%X\n", frame->r13, frame->r14);
IOConsoleLog("\t\t^yR15^!=%X\n",frame->r15);
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
die();
}
__attribute__((noreturn)) void OSPanic(const char* message) {
sOSPanicDrawPanicBackground();
IOConsoleLog("\t\t^yReason^!: %s\n", message);
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
die();
}
+226
View File
@@ -0,0 +1,226 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSScheduler.h>
#include <OS/OSSpinlock.h>
#include <OS/OSPanic.h>
#include <lib/String.h>
#include <VM/Heap.h>
#include <VM/VMM.h>
#include <OSCPU.h>
#include <GDT.h>
OSTask* gOSSchedulerCurrentTask = nullptr;
UInt32 gOSSchedulerNextProcessID = 1;
extern void irq0_handler();
extern UInt64 gVMKernelPML4Physical;
static OSProcess sOSSchedulerKernelProcess;
static OSSpinlock sOSSchedulerLock;
static OSTask* sOSSchedulerGarbageCollectorTask = nullptr;
void idle_task() {
while (1) {
__asm__ volatile ("hlt");
}
}
void OSSchedulerGarbageCollector() {
OSTask* self = gOSSchedulerCurrentTask;
while (true) {
OSTask* previousTask = self;
OSTask* nextTask = previousTask->next;
while (nextTask != self) {
if (nextTask->taskState == kOSProcessStateDead) {
OSSpinlockState lockState;
OSSpinlockLockIRQ(&sOSSchedulerLock, &lockState);
previousTask->next = nextTask->next;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &lockState);
if (nextTask->kernelStackBase) {
VMHeapFree(nextTask->kernelStackBase);
}
VMHeapFree(nextTask);
nextTask = previousTask->next;
} else {
previousTask = nextTask;
nextTask = nextTask->next;
}
}
OSSchedulerYield(200);
}
}
static void sOSSchedulerPostGarbageCollectorSignal() {
if (!sOSSchedulerGarbageCollectorTask) return;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
sOSSchedulerGarbageCollectorTask->taskState = kOSProcessStateRunning;
sOSSchedulerGarbageCollectorTask->sleepTicks = 0;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerInitialize() {
sOSSchedulerKernelProcess.processId = 0;
sOSSchedulerKernelProcess.state = kOSProcessStateRunning;
sOSSchedulerKernelProcess.physicalPML4 = gVMKernelPML4Physical;
StringCopy(sOSSchedulerKernelProcess.name, "kernel");
OSTask* kernelTask = (OSTask*)VMHeapAllocate(sizeof(OSTask));
if (!kernelTask) OSPanic("Failed to initialize scheduler: OOm");
MemorySet(kernelTask, 0, sizeof(OSTask));
kernelTask->id = 0;
kernelTask->process = &sOSSchedulerKernelProcess;
kernelTask->sleepTicks = 0;
kernelTask->next = kernelTask;
kernelTask->taskState = kOSProcessStateRunning;
kernelTask->waitingForProcess = -1;
gOSSchedulerCurrentTask = kernelTask;
OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0);
sOSSchedulerGarbageCollectorTask = OSSchedulerSpawn(OSSchedulerGarbageCollector, &sOSSchedulerKernelProcess, false, 0);
return;
}
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) {
OSTask* task = (OSTask*)VMHeapAllocate(sizeof(OSTask));
if (!task) return nullptr;
if (!owner) owner = &sOSSchedulerKernelProcess;
UInt64 stackSize = 16384;
UInt8* stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
if (!stackBaseAddress) {
sOSSchedulerPostGarbageCollectorSignal();
OSSchedulerYield(0);
stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
if (!stackBaseAddress) {
VMHeapFree(task);
return nullptr;
}
}
UInt64* rsp = (UInt64*)(stackBaseAddress + stackSize);
UInt64 cs = isUser ? 0x23 : 0x08;
UInt64 ss = isUser ? 0x1b : 0x10;
UInt64 rflags = 0x202;
UInt64 targetStackPointer = 0;
if (isUser) targetStackPointer = fixedUserStackPointer;
else targetStackPointer = (UInt64)stackBaseAddress + stackSize;
*--rsp = ss; // SS -- Kernel data
*--rsp = targetStackPointer; // rsp
*--rsp = rflags; // RFLAGS -- Interrupts Enabled | Reserved bit;
*--rsp = cs; // CS -- Kernel Code;
*--rsp = (UInt64)entry; // RIP
*--rsp = 0; // int no
*--rsp = 0; // err code
for (UInt8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
task->stackPointer = (UInt64)rsp;
task->process = owner;
task->id = owner->processId;
task->sleepTicks = 0;
task->kernelStackTop = (UInt64)stackBaseAddress + stackSize;
task->kernelStackBase = stackBaseAddress;
task->taskState = kOSProcessStateRunning;
task->waitingForProcess = -1;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
task->next = gOSSchedulerCurrentTask->next;
gOSSchedulerCurrentTask->next = task;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
return task;
}
UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
if (!gOSSchedulerCurrentTask) return currentStackPointer;
OSSpinlockLock(&sOSSchedulerLock);
gOSSchedulerCurrentTask->stackPointer = currentStackPointer;
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
do {
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
taskIterator = taskIterator->next;
} while (taskIterator != gOSSchedulerCurrentTask->next);
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
OSTask* nextTask = gOSSchedulerCurrentTask->next;
while (1) {
if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning;
if (nextTask->taskState == kOSProcessStateRunning) break;
nextTask = nextTask->next;
if (nextTask == gOSSchedulerCurrentTask) {
if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break;
OSPanic("no running tasks");
}
}
if (nextTask->process->physicalPML4 != gOSSchedulerCurrentTask->process->physicalPML4) VMLoadCR3(nextTask->process->physicalPML4);
gOSSchedulerCurrentTask = nextTask;
gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop;
gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop;
OSSpinlockUnlock(&sOSSchedulerLock);
return gOSSchedulerCurrentTask->stackPointer;
}
void OSSchedulerBlock(UInt32 processID) {
gOSSchedulerCurrentTask->taskState = kOSProcessStateBlocked;
gOSSchedulerCurrentTask->waitingForProcess = processID;
__asm__ volatile("int $32");
}
void OSSchedulerWakeup(UInt32 processID) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
OSTask* iteratorTask = gOSSchedulerCurrentTask;
do {
if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) {
iteratorTask->taskState = kOSProcessStateRunning;
iteratorTask->waitingForProcess = -1;
}
iteratorTask = iteratorTask->next;
} while (iteratorTask != gOSSchedulerCurrentTask);
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerTerminate() {
UInt32 processID = gOSSchedulerCurrentTask->id;
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
OSSchedulerWakeup(processID);
sOSSchedulerPostGarbageCollectorSignal();
__asm__ volatile("int $32");
}
void OSSchedulerYield(UInt64 ticks) {
gOSSchedulerCurrentTask->sleepTicks = ticks;
gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping;
__asm__ volatile("int $32");
}
+29
View File
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSSpinlock.h>
void OSSpinlockLock(OSSpinlock* lock) {
while (__atomic_exchange_n(&lock->lockValue, 1, __ATOMIC_ACQUIRE)) {
while (lock->lockValue) {
__builtin_ia32_pause();
}
}
}
void OSSpinlockUnlock(OSSpinlock *lock) {
__atomic_store_n(&lock->lockValue, 0, __ATOMIC_RELEASE);
}
void OSSpinlockLockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
UInt64 rflags;
__asm__ volatile("pushfq; pop %0; cli" : "=r"(rflags) :: "memory"); // read flags and cli
state->interruptsEnabled = (rflags & (1 << 9)) != 0; // IF bit
OSSpinlockLock(lock);
}
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
OSSpinlockUnlock(lock);
if (state->interruptsEnabled) __asm__ volatile("sti" ::: "memory");
}
+28
View File
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Services/OSServiceIO.h>
#include <IO/IOConsole.h>
#include <IO/IOKeyboard.h>
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
if (fileDescriptor == 1 || fileDescriptor == 2) {
char* string = (char*)buffer;
for (UInt64 i = 0; i < length; i++) {
IOConsolePutcharacter(string[i]);
}
return length;
}
return 0;
}
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
char* readBuffer = (char*)buffer;
if (fileDescriptor == 0) {
for (UInt64 i = 0; i < count; i++) {
readBuffer[i] = IOKeyboardGetCharacter();
}
return count;
}
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Services/OSServiceMemory.h>
#include <OS/OSScheduler.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
UInt64 OSServiceMemoryAllocate(UInt64 size) {
if (size == 0) return 0;
OSProcess* currentProcess = gOSSchedulerCurrentTask->process;
UInt64 addressToReturn = currentProcess->heapCurrentPointer;
UInt64 pages_needed = (size + (kVMPageSize-1)) / kVMPageSize;
for (UInt64 i = 0; i < pages_needed; i++) {
void* phycialAddress = VMPhysicalMemoryAllocatePage();
if (!phycialAddress) return 0;
VMVirtualMemoryMapPage((UInt64*)currentProcess->physicalPML4, (UInt64)phycialAddress, currentProcess->heapCurrentPointer, PTE_PRESENT | PTE_RW | PTE_USER);
MemorySet((void*)PHYS_TO_HHDM((UInt64)phycialAddress), 0, kVMPageSize);
currentProcess->heapCurrentPointer += kVMPageSize;
}
return addressToReturn;
}
+32
View File
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Services/OSServiceProcess.h>
#include <OS/OSScheduler.h>
#include <OS/OSPanic.h>
#include <OS/Exec/OSLoader.h>
#include <IO/IOConsole.h>
#include <lib/String.h>
Int32 OSServiceProcessExit(Int32 code) {
IOConsoleLog("\n[Dewar] process \"%s\" exited with code %d\n", gOSSchedulerCurrentTask->process->name, code);
OSSchedulerTerminate();
return code;
}
Int32 OSServiceProcessSpawn(const char* path) {
const char* name = StringFindLastOccurrenceOfCharacter(path, '/');
if (name) name++;
else name = path;
return OSLoaderProcessSpawn(path, name);
}
Int32 OSServiceProcessWait(UInt64 processID) {
OSSchedulerBlock(processID);
return processID;
}
+131
View File
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <VM/Heap.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
extern UInt64* gVMKernelPML4;
static VMHeapBlockHeader* sVMHeapListHead = nullptr;
static OSSpinlock sVMHeapLock = {0};
static void sVMHeapCombineForward(VMHeapBlockHeader* current) {
if (!current->next || !current->next->isFree) return;
current->size += sizeof(VMHeapBlockHeader) + current->next->size;
current->next = current->next->next;
if (current->next) current->next->previous = current; // what the fuck
}
void VMHeapInitialize() {
UInt64 heapStart = kVMKernelHeapStart;
for (UInt64 i = 0; i < kVMHeapSizePages; i++) {
UInt64 physical = (UInt64)VMPhysicalMemoryAllocatePage();
if (!physical) OSPanic("OOM during heap init");
UInt64 virtual = heapStart + (i * kVMPageSize);
VMVirtualMemoryMapPage(gVMKernelPML4, physical, virtual, PTE_PRESENT | PTE_RW);
}
sVMHeapListHead = (VMHeapBlockHeader*)heapStart;
sVMHeapListHead->magic = kVMHeapBlockHeaderMagic;
sVMHeapListHead->size = (kVMHeapSizePages * kVMPageSize) - sizeof(VMHeapBlockHeader);
sVMHeapListHead->isFree = true;
sVMHeapListHead->next = nullptr;
sVMHeapListHead->previous = nullptr;
}
static void* sVMHeapAllocateInternal(UInt64 size) {
if (size == 0) return nullptr;
UInt64 alignedSize = (size + 15) & ~15;
VMHeapBlockHeader* current = sVMHeapListHead;
while (current) {
if (current->isFree && current->size >= alignedSize) {
if (current->size > alignedSize + sizeof(VMHeapBlockHeader) + 16) {
VMHeapBlockHeader* new_block = (VMHeapBlockHeader*)((UInt64)current + sizeof(VMHeapBlockHeader) + alignedSize);
new_block->size = current->size - alignedSize - sizeof(VMHeapBlockHeader);
new_block->isFree = true;
new_block->next = current->next;
new_block->previous = current;
new_block->magic = kVMHeapBlockHeaderMagic;
if (current->next) current->next->previous = new_block;
current->next = new_block;
current->size = alignedSize;
}
current->isFree = false;
return (void*)((UInt64)current + sizeof(VMHeapBlockHeader));
}
current = current->next;
}
return nullptr;
}
static void sVMHeapFreeInternal(void* pointer) {
if (!pointer) return;
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->magic != kVMHeapBlockHeaderMagic) return;
current->isFree = true;
if (current->next && current->next->isFree) sVMHeapCombineForward(current);
if (current->previous && current->previous->isFree) sVMHeapCombineForward(current->previous);
}
void* VMHeapAllocate(UInt64 size) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
void* result = sVMHeapAllocateInternal(size);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return result;
}
void VMHeapFree(void* pointer) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
sVMHeapFreeInternal(pointer);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
}
void* VMHeapResize(void* pointer, UInt64 newSize) {
if (!pointer) return VMHeapAllocate(newSize);
if (newSize == 0) {
VMHeapFree(pointer);
return nullptr;
}
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->size >= newSize) {
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
if (current->next && current->next->isFree &&
(current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable
sVMHeapCombineForward(current);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
void* newPointer = sVMHeapAllocateInternal(newSize);
if (newPointer) {
MemoryCopy(newPointer, pointer, current->size);
sVMHeapFreeInternal(pointer);
}
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return newPointer;
}
+131
View File
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
#include <lib/Math.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
#include "bootinfo.h"
UInt8* gVMPhycalMemoryBitmap = nullptr;
UInt64 gVMPhycalMemoryBitmapSize = 0;
UInt64 gVMPhycalMemoryTotalMemorySize = 0;
static OSSpinlock sVMPMMLock = {0};
extern UInt64 _kernel_start;
extern UInt64 _kernel_end;
UInt64 VMPhysicalMemoryGetTotalMemorySize() {
return gVMPhycalMemoryTotalMemorySize;
}
void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
UInt64 descriptorCount = memoryMap->mapSize / memoryMap->descriptorSize;
UInt64 maxPhysicalAddress = 0;
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor* descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
if (descriptor->type == kOSMemoryTypeMappedIO ||
descriptor->type == kOSMemoryTypeMappedIOPortSpace ||
descriptor->type == kOSMemoryTypeUnusable ||
descriptor->type == kOSMemoryTypeReserved ||
descriptor->type == kOSMemoryTypePalCode) {
continue;
}
UInt64 nominee = descriptor->physicalStart + (descriptor->pageCount * kVMPageSize);
if (nominee > maxPhysicalAddress) {
maxPhysicalAddress = nominee;
}
}
gVMPhycalMemoryTotalMemorySize = maxPhysicalAddress;
UInt64 totalPageCount = maxPhysicalAddress / kVMPageSize;
UInt64 bitmapSize = (totalPageCount + 7) / 8;
OSMemoryDescriptor *bitmapHostDescriptor = nullptr;
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
if ((descriptor->type == kOSMemoryTypeConventional) &&
((descriptor->pageCount * kVMPageSize) >= bitmapSize) &&
(descriptor->physicalStart >= kVMSafeSpaceStartAddress)) {
bitmapHostDescriptor = descriptor;
break;
}
}
if (bitmapHostDescriptor == nullptr) {
OSPanic("PMM: Not enough RAM for memory bitmap!");
}
gVMPhycalMemoryBitmap = (UInt8*)bitmapHostDescriptor->physicalStart;
gVMPhycalMemoryBitmapSize = bitmapSize;
MemorySet(gVMPhycalMemoryBitmap, 0xFF, bitmapSize);
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
if (descriptor->type != kOSMemoryTypeConventional) {
continue;
}
UInt64 startAddress = descriptor->physicalStart;
UInt64 endAddress = startAddress + (descriptor->pageCount * kVMPageSize);
for (UInt64 addr = startAddress; addr < endAddress; addr += kVMPageSize) {
BITMAP_UNSET(gVMPhycalMemoryBitmap, addr);
}
}
UInt64 kernelStart = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_start);
UInt64 kernelEnd = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_end);
UInt64 bitmapStart = (UInt64)gVMPhycalMemoryBitmap;
UInt64 bitmapEnd = bitmapStart + gVMPhycalMemoryBitmapSize;
for (UInt64 addr = 0; addr < kVMSafeSpaceStartAddress; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
for (UInt64 addr = kernelStart; addr < kernelEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
for (UInt64 addr = bitmapStart; addr < bitmapEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
}
void* VMPhysicalMemoryAllocatePage() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) {
if (gVMPhycalMemoryBitmap[i] == 0xFF) continue;
for (UInt64 bit = 0; bit < 8; bit++) {
if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) {
UInt64 address = (i * 8 + bit) * kVMPageSize;
BITMAP_SET(gVMPhycalMemoryBitmap, address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return (void*)address;
}
}
}
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return nullptr; // Out of memory
}
void VMPhysicalMemoryFreePage(void* address) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
}
+207
View File
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <VM/VMM.h>
#include <VM/PMM.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <GDT.h>
#include <IDT.h>
#include <lib/String.h>
#include <types.h>
#include "bootinfo.h"
enum {
kVMUserStackTop = 0x70000000,
kVMUserStackSize = 0x4000
};
UInt64* gVMKernelPML4 = nullptr;
UInt64 gVMKernelPML4Physical = 0;
static OSSpinlock sVMVMMlock = {0};
static bool isInitialized = false;
extern UInt64 _kernel_start;
extern UInt64 _kernel_end;
extern UInt8* gVMPhycalMemoryBitmap;
extern UInt64 gVMPhycalMemoryBitmapSize;
extern HALGlobalDescriptorTable gHALGlobalDescriptorTable[];
extern HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[];
extern UInt8 gHALDoubleFaultStack[];
extern UInt8 stack_guard;
static UInt64* sVMGetVirtualTable(UInt64 phys) {
if (isInitialized) return (UInt64*)PHYS_TO_HHDM(phys);
return (UInt64*)phys;
}
static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
UInt64* pml4_virt = pml4;
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
UInt64 table_flags = PTE_PRESENT | PTE_RW | (flags & PTE_USER);
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
MemorySet(addr_virt, 0, kVMPageSize);
pml4_virt[pml4_idx] = (UInt64)addr | table_flags;
} else {
pml4_virt[pml4_idx] |= (flags & PTE_USER);
}
UInt64* pdpt = (UInt64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
UInt64* pdpt_virt = sVMGetVirtualTable((UInt64)pdpt);
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) {
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
MemorySet(addr_virt, 0, kVMPageSize);
pdpt_virt[pdpt_idx] = (UInt64)addr | table_flags;
} else {
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
}
UInt64* pd = (UInt64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
UInt64* pd_virt = sVMGetVirtualTable((UInt64)pd);
if (!(pd_virt[pd_idx] & PTE_PRESENT)) {
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
MemorySet(addr_virt, 0, kVMPageSize);
pd_virt[pd_idx] = (UInt64)addr | table_flags;
} else {
pd_virt[pd_idx] |= (flags & PTE_USER);
}
UInt64* pt = (UInt64*)PTE_GET_ADDR(pd_virt[pd_idx]);
UInt64* pt_virt = sVMGetVirtualTable((UInt64)pt);
pt_virt[pt_idx] = phys | flags;
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
return (UInt64*)virt;
}
static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
UInt64* pml4_virt = pml4;
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) return;
UInt64* pdpt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pml4_virt[pml4_idx]));
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) return;
UInt64* pd_virt = sVMGetVirtualTable(PTE_GET_ADDR(pdpt_virt[pdpt_idx]));
if (!(pd_virt[pd_idx] & PTE_PRESENT)) return;
UInt64* pt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pd_virt[pd_idx]));
pt_virt[pt_idx] = 0;
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
}
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, phys, virt, flags);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return result;
}
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
sVMVirtualMemoryUnmapPageInternal(pml4, virt);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
}
void VMLoadCR3(UInt64 pml4_addr) {
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
}
void VMVirtualMemoryInitialize(Bootinfo* info) {
gVMKernelPML4Physical = (UInt64)VMPhysicalMemoryAllocatePage();
gVMKernelPML4 = (UInt64*)gVMKernelPML4Physical;
MemorySet(gVMKernelPML4, 0, kVMPageSize);
UInt64 k_virt_start = (UInt64)&_kernel_start;
UInt64 k_virt_end = (UInt64)&_kernel_end;
UInt64 fb_start = (UInt64)info->framebuffer.base;
UInt64 fb_end = fb_start + info->framebuffer.baseSize;
UInt64 fb_size = fb_end - fb_start;
UInt64 max_mem = VMPhysicalMemoryGetTotalMemorySize();
for (UInt64 i = 0; i < max_mem; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, i, PHYS_TO_HHDM(i), PTE_PRESENT | PTE_RW);
for (UInt64 i = k_virt_start; i < k_virt_end; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, KERNEL_VIRT_TO_PHYS(i), i, PTE_PRESENT | PTE_RW);
for (UInt64 i = 0; i < fb_size; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, fb_start + i, FB_VIRT_BASE + i, PTE_PRESENT | PTE_RW);
VMVirtualMemoryUnmapPage(gVMKernelPML4, (UInt64)&stack_guard);
gVMPhycalMemoryBitmap = (UInt8*)PHYS_TO_HHDM((UInt64)gVMPhycalMemoryBitmap);
info->framebuffer.base = (UInt32*)FB_VIRT_BASE;
VMLoadCR3(gVMKernelPML4Physical);
isInitialized = true;
}
UInt64 VMVirtualMemoryCreateAddressSpace() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage();
if (!phys) {
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return 0;
};
UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys);
MemorySet(virt, 0, kVMPageSize);
UInt64* kernel_pml4_virt = sVMGetVirtualTable((UInt64)gVMKernelPML4);
for (UInt32 i = 256; i < 512; i++) {
virt[i] = kernel_pml4_virt[i];
}
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return phys;
}
UInt64 VMGetCurrentCR3() {
UInt64 cr3;
__asm__ volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
void VMVirtualMemorySetupUserStack(UInt64* pml4_phys) {
UInt64 stack_bottom = kVMUserStackTop - kVMUserStackSize;
for (UInt64 addr = stack_bottom; addr < kVMUserStackTop; addr += 4096) {
void* phys = VMPhysicalMemoryAllocatePage();
if (!phys) OSPanic("OOM in user stack setup");
MemorySet((void*)PHYS_TO_HHDM((UInt64)phys), 0, 4096);
VMVirtualMemoryMapPage((UInt64*)pml4_phys, (UInt64)phys, addr, PTE_PRESENT | PTE_RW | PTE_USER);
}
}
+77
View File
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// just fucking kill me already
#include <GDT.h>
HALGlobalDescriptorTable gHALGlobalDescriptorTable[kHALGDTEntries];
HALGlobalDescriptorTablePointer gHALGlobalDescriptorTablePointer;
HALTaskStateSegment gHALTaskStateSegment;
UInt8 gHALDoubleFaultStack[4096] = {0};
static void sHALGlobalDescriptorTableSetGate(int number, UInt64 base, UInt64 limit, UInt8 access, UInt8 granularity) {
gHALGlobalDescriptorTable[number].baseLow = (base & 0xFFFF); // left only low 16bit
gHALGlobalDescriptorTable[number].baseMiddle = (base >> 16) & 0xFF; // 3rd address byte
gHALGlobalDescriptorTable[number].baseHigh = (base >> 24) & 0xFF; // 4th address byte
gHALGlobalDescriptorTable[number].limitLow = (limit & 0xFFFF);
gHALGlobalDescriptorTable[number].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19)
gHALGlobalDescriptorTable[number].granularity |= granularity & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags)
gHALGlobalDescriptorTable[number].access = access;
// fuck intel
}
static void sHALTaskStateSegmentWrite(int number) {
UInt64 base = (UInt64)&gHALTaskStateSegment;
UInt64 limit = sizeof(gHALTaskStateSegment);
UInt64 access = 0x89; // TSS_PRESENT | TSS_EXECUTABLE | TSS_ACCESSED;
UInt64 granularity = 0;
sHALGlobalDescriptorTableSetGate(number, base, limit, access, granularity);
*((UInt64*)&gHALGlobalDescriptorTable[number+1]) = (base >> 32); // really scary but not really hard
// just direct write 8bytes to num+1
// basically a hack but at this point i dont care
}
extern void gdt_flush(UInt64 gdt_ptr_addr); // entry.asm
void HALGlobalDescriptorTableInitialize() {
gHALGlobalDescriptorTablePointer.limit = (sizeof(HALGlobalDescriptorTable) * kHALGDTEntries) - 1;
gHALGlobalDescriptorTablePointer.base = (UInt64)&gHALGlobalDescriptorTable;
// 0: Null
sHALGlobalDescriptorTableSetGate(0, 0, 0, 0, 0);
// 1: Kernel Code (Ring 0)
// Access: 0x9A (Present, Ring0, Exec/Read)
// Granularity: 0x20 (Long Mode bit) access ring 0 code exec code readable
sHALGlobalDescriptorTableSetGate(1, 0, 0, 0x9A, 0x20); // 0x9A = 1 00 1 1 0 1
// 0x20 = 0010 0000 bit 5 is "Long mode"
// 2: Kernel Data (Ring 0)
// Access: 0x92 (Present, Ring0, Read/Write)
sHALGlobalDescriptorTableSetGate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
// 3: User Data (Ring 3)
// Access: 0xF2 (Present, Ring3, Read/Write)
sHALGlobalDescriptorTableSetGate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
// 4: User Code (Ring 3)
// Access: 0xFA (Present, Ring3, RWX)
sHALGlobalDescriptorTableSetGate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
for (UInt64 i = 0; i < sizeof(HALTaskStateSegment); i++) ((UInt8*)&gHALTaskStateSegment)[i] = 0; // zeroifying tss struct
gHALTaskStateSegment.iomapBase = sizeof(HALTaskStateSegment);
gHALTaskStateSegment.ist1 = (UInt64)gHALDoubleFaultStack + sizeof(gHALDoubleFaultStack);
sHALTaskStateSegmentWrite(5);
gdt_flush((UInt64)&gHALGlobalDescriptorTablePointer);
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
}
+82
View File
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IDT.h>
#include <types.h>
HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[256];
HALInterruptsDescriptorTablePointer gHALInterruptsDescriptorTablePointer;
extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3();
extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7();
extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11();
extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15();
extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19();
extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23();
extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27();
extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31();
extern void irq0(void); extern void irq1(void);
extern void idt_load(UInt64); // asm: lidt [rdi] / ret
static void sHALInterruptsDescriptorTableSetGate(int number, UInt64 handler, UInt16 selector, UInt8 flags) {
gHALInterruptsDescriptorTable[number].offsetLow = handler & 0xFFFF;
gHALInterruptsDescriptorTable[number].offsetMid = (handler >> 16) & 0xFFFF;
gHALInterruptsDescriptorTable[number].offsetHigh = (handler >> 32) & 0xFFFFFFFF;
gHALInterruptsDescriptorTable[number].selector = selector; // 0x08 (Kernel Code)
gHALInterruptsDescriptorTable[number].ist = 0;
gHALInterruptsDescriptorTable[number].attributes = flags;
gHALInterruptsDescriptorTable[number].reserved = 0;
}
void HALInterruptsDescriptorTableInitialize() {
gHALInterruptsDescriptorTablePointer.limit = (sizeof(HALInterruptsDescriptorTableEntry) * 256) - 1;
gHALInterruptsDescriptorTablePointer.base = (UInt64)&gHALInterruptsDescriptorTable;
const UInt8 flags = 0x8E;
const UInt8 selector = 0x08;
sHALInterruptsDescriptorTableSetGate(0, (UInt64)isr0, selector, flags);
sHALInterruptsDescriptorTableSetGate(1, (UInt64)isr1, selector, flags);
sHALInterruptsDescriptorTableSetGate(2, (UInt64)isr2, selector, flags);
sHALInterruptsDescriptorTableSetGate(3, (UInt64)isr3, selector, flags);
sHALInterruptsDescriptorTableSetGate(4, (UInt64)isr4, selector, flags);
sHALInterruptsDescriptorTableSetGate(5, (UInt64)isr5, selector, flags);
sHALInterruptsDescriptorTableSetGate(6, (UInt64)isr6, selector, flags);
sHALInterruptsDescriptorTableSetGate(7, (UInt64)isr7, selector, flags);
sHALInterruptsDescriptorTableSetGate(8, (UInt64)isr8, selector, flags);
sHALInterruptsDescriptorTableSetGate(9, (UInt64)isr9, selector, flags);
sHALInterruptsDescriptorTableSetGate(10, (UInt64)isr10, selector, flags);
sHALInterruptsDescriptorTableSetGate(11, (UInt64)isr11, selector, flags);
sHALInterruptsDescriptorTableSetGate(12, (UInt64)isr12, selector, flags);
sHALInterruptsDescriptorTableSetGate(13, (UInt64)isr13, selector, flags);
sHALInterruptsDescriptorTableSetGate(14, (UInt64)isr14, selector, flags);
sHALInterruptsDescriptorTableSetGate(15, (UInt64)isr15, selector, flags);
sHALInterruptsDescriptorTableSetGate(16, (UInt64)isr16, selector, flags);
sHALInterruptsDescriptorTableSetGate(17, (UInt64)isr17, selector, flags);
sHALInterruptsDescriptorTableSetGate(18, (UInt64)isr18, selector, flags);
sHALInterruptsDescriptorTableSetGate(19, (UInt64)isr19, selector, flags);
sHALInterruptsDescriptorTableSetGate(20, (UInt64)isr20, selector, flags);
sHALInterruptsDescriptorTableSetGate(21, (UInt64)isr21, selector, flags);
sHALInterruptsDescriptorTableSetGate(22, (UInt64)isr22, selector, flags);
sHALInterruptsDescriptorTableSetGate(23, (UInt64)isr23, selector, flags);
sHALInterruptsDescriptorTableSetGate(24, (UInt64)isr24, selector, flags);
sHALInterruptsDescriptorTableSetGate(25, (UInt64)isr25, selector, flags);
sHALInterruptsDescriptorTableSetGate(26, (UInt64)isr26, selector, flags);
sHALInterruptsDescriptorTableSetGate(27, (UInt64)isr27, selector, flags);
sHALInterruptsDescriptorTableSetGate(28, (UInt64)isr28, selector, flags);
sHALInterruptsDescriptorTableSetGate(29, (UInt64)isr29, selector, flags);
sHALInterruptsDescriptorTableSetGate(30, (UInt64)isr30, selector, flags);
sHALInterruptsDescriptorTableSetGate(31, (UInt64)isr31, selector, flags);
gHALInterruptsDescriptorTable[8].ist = 1; // TSS
gHALInterruptsDescriptorTable[13].ist = 1;
gHALInterruptsDescriptorTable[14].ist = 1;
sHALInterruptsDescriptorTableSetGate(32, (UInt64)irq0, selector, flags);
sHALInterruptsDescriptorTableSetGate(33, (UInt64)irq1, selector, flags);
__asm__ volatile ("lidt %0" : : "m"(gHALInterruptsDescriptorTablePointer));
}
+72
View File
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <types.h>
#include <OSCPU.h>
#define MSR_GS_BASE 0xC0000101
#define MSR_KERNEL_GS_BASE 0xC0000102
OSCPUData gOSBootCPU = {0};
static inline void CPUID(UInt32 leaf, UInt32 subleaf, UInt32 *eax, UInt32 *ebx, UInt32 *ecx, UInt32 *edx) {
__asm__ volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf), "c"(subleaf)
);
}
static inline void WRMSR(UInt32 msr, UInt64 val) {
UInt32 low = (UInt32)val;
UInt32 high = (UInt32)(val >> 32);
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
}
void OSCPUInitialize(UInt64 kernelStackTop) {
gOSBootCPU.kernelStackPointer = kernelStackTop;
gOSBootCPU.selfAddress = (UInt64)&gOSBootCPU;
WRMSR(MSR_KERNEL_GS_BASE, (UInt64)&gOSBootCPU);
UInt32 eax, ebx, ecx, edx;
CPUID(0, 0, &eax, &ebx, &ecx, &edx);
UInt32* vendorPointer = (UInt32*)gOSBootCPU.vendorID;
vendorPointer[0] = ebx;
vendorPointer[1] = edx;
vendorPointer[2] = ecx;
gOSBootCPU.vendorID[12] = '\0';
CPUID(1, 0, &eax, &ebx, &ecx, &edx);
gOSBootCPU.family = (eax >> 8) & 0xF;
gOSBootCPU.model = (eax >> 4) & 0xF;
if (gOSBootCPU.family == 6 || gOSBootCPU.family == 15) {
gOSBootCPU.model += ((eax >> 16) & 0xF) << 4;
}
if (edx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureFPU;
if (edx & (1 << 4)) gOSBootCPU.features |= kCPUFeatureTSC;
if (edx & (1 << 5)) gOSBootCPU.features |= kCPUFeatureMSR;
if (edx & (1 << 6)) gOSBootCPU.features |= kCPUFeaturePAE;
if (edx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureAPIC;
if (edx & (1 << 12)) gOSBootCPU.features |= kCPUFeatureMTRR;
if (edx & (1 << 25)) gOSBootCPU.features |= kCPUFeatureSSE;
if (edx & (1 << 26)) gOSBootCPU.features |= kCPUFeatureSSE2;
if (ecx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureSSE3;
if (ecx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureSSSE3;
if (ecx & (1 << 19)) gOSBootCPU.features |= kCPUFeatureSSE4_1;
if (ecx & (1 << 20)) gOSBootCPU.features |= kCPUFeatureSSE4_2;
if (ecx & (1 << 28)) gOSBootCPU.features |= kCPUFeatureAVX;
if (ecx & (1 << 29)) gOSBootCPU.features |= kCPUFeatureF16C;
if (ecx & (1 << 30)) gOSBootCPU.features |= kCPUFeatureRDRAND;
if (ecx & (1 << 31)) gOSBootCPU.features |= kCPUFeatureHypervisor;
}
Boolean OSCPUHasFeature(OSCPUFeature feature) {
return (gOSBootCPU.features & feature) != 0;
}
+34
View File
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <PIC.h>
#include <IO.h>
#include <types.h>
UInt16 HALLegacyInterruptControllerRemap() {
UInt8 currentMaster = IOPortRead8(kIOMasterData);
UInt8 currentSlave = IOPortRead8(kIOSlaveData);
// initialization; icw1
IOPortWrite8WithWait(kIOMasterCommand, 0x11);
IOPortWrite8WithWait(kIOSlaveCommand, 0x11);
// icw2
IOPortWrite8WithWait(kIOMasterData, 0x20); // master now controlling idt[32..39]
IOPortWrite8WithWait(kIOSlaveData, 0x28); // idt[40..47]
// icw3
IOPortWrite8WithWait(kIOMasterData, 0x04); // slave on irq2
IOPortWrite8WithWait(kIOSlaveData, 0x02); // assign id = 2 to slave
// icw4; 0x01 -- 8086 mode
IOPortWrite8WithWait(kIOMasterData, 0x01);
IOPortWrite8WithWait(kIOSlaveData, 0x01);
IOPortWrite8WithWait(kIOMasterData, 0xFD); // 1111 1101
// 0 -- means 'on'
IOPortWrite8WithWait(kIOSlaveData, 0xFF); // Everything ON
return ((UInt16) currentMaster << 8) | currentSlave;
}
+110
View File
@@ -0,0 +1,110 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2026 0xKarinyash
bits 64
%define KERNEL_VMA 0xFFFFFFFF80000000
%define PAGE_PRESENT (1 << 0)
%define PAGE_RW (1 << 1)
%define PAGE_HUGE (1 << 7)
section .bss
align 4096
pml4_table:
resb 4096
pdpt_table:
resb 4096
pd_table:
resb 4096
section .stack nobits
align 4096
global stack_guard
stack_guard:
resb 4096
global stack_bottom
stack_bottom:
resb 16384
global stack_top
stack_top:
section .text.entry
global _start
global gdt_flush
extern kmain
_start:
cli
mov r12, rdi
mov rsp, stack_top
mov rax, KERNEL_VMA
sub rsp, rax
mov rdi, pml4_table
sub rdi, KERNEL_VMA
mov rsi, pdpt_table
sub rsi, KERNEL_VMA
mov rdx, pd_table
sub rdx, KERNEL_VMA
mov rax, rsi
or rax, PAGE_PRESENT | PAGE_RW
mov [rdi], rax
mov [rdi + 4088], rax
mov rax, rdx
or rax, PAGE_PRESENT | PAGE_RW
mov [rsi], rax
mov [rsi + 4080], rax
mov rcx, 0
mov rbx, 512
mov rax, rdx
.fill_pd_loop:
mov r8, rcx
or r8, PAGE_PRESENT | PAGE_RW | PAGE_HUGE
mov [rax], r8
add rcx, 0x200000
add rax, 8
dec rbx
jnz .fill_pd_loop
mov cr3, rdi
mov rax, .higher_half
jmp rax
.higher_half:
mov rsp, stack_top
mov rdi, r12
xor rbp, rbp
call kmain
.hang:
cli
hlt
jmp .hang
gdt_flush:
lgdt [rdi]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
pop rdi
push 0x08
push rdi
retfq
+157
View File
@@ -0,0 +1,157 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2026 0xKarinyash
bits 64
extern isr_handler_c
extern irq_handler_c
section .text
%macro ISR_NOERRCODE 1
global isr%1
isr%1:
push 0
push %1
jmp isr_common_stub
%endmacro
%macro ISR_ERRCODE 1
global isr%1
isr%1:
push %1
jmp isr_common_stub
%endmacro
%macro PUSHALL 0
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rbp
push rdi
push rsi
push rdx
push rcx
push rbx
push rax
%endmacro
%macro POPALL 0
pop rax
pop rbx
pop rcx
pop rdx
pop rsi
pop rdi
pop rbp
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
%endmacro
%macro IRQ_HANDLER 2
global %2
%2:
push 0 ; dummy err code
push %1 ; int_no
; [rsp] = int_no (8)
; [rsp + 8] = err_code (8)
; [rsp + 16] = RIP (8)
; [rsp + 24] = CS (8)
test qword [rsp + 24], 3
jz .skip_swap
swapgs
.skip_swap:
PUSHALL
mov rdi, rsp
cld
call irq_handler_c
mov rsp, rax
; PUSHALL - 15 * 8 = 120 bytes
; + int_no (8) + err_code (8) = 136 bytes
; [rsp + 136] = RIP
; [rsp + 144] = CS
test qword [rsp + 144], 3
jz .skip_swap_back
swapgs
.skip_swap_back:
POPALL
add rsp, 16
iretq
%endmacro
ISR_NOERRCODE 0 ; Divide by zero
ISR_NOERRCODE 1 ; Debug
ISR_NOERRCODE 2 ; NMI
ISR_NOERRCODE 3 ; Breakpoint
ISR_NOERRCODE 4 ; Overflow
ISR_NOERRCODE 5 ; Bound Range Exceeded
ISR_NOERRCODE 6 ; Invalid Opcode
ISR_NOERRCODE 7 ; Device Not Available
ISR_ERRCODE 8 ; Double Fault
ISR_NOERRCODE 9 ; Coprocessor Segment Overrun
ISR_ERRCODE 10 ; Invalid TSS
ISR_ERRCODE 11 ; Segment Not Present
ISR_ERRCODE 12 ; Stack-Segment Fault
ISR_ERRCODE 13 ; General Protection Fault
ISR_ERRCODE 14 ; Page Fault
ISR_NOERRCODE 15 ; Reserved
ISR_NOERRCODE 16 ; x87 Floating-Point Exception
ISR_ERRCODE 17 ; Alignment Check
ISR_NOERRCODE 18 ; Machine Check
ISR_NOERRCODE 19 ; SIMD Floating-Point Exception
ISR_NOERRCODE 20 ; Virtualization Exception
ISR_NOERRCODE 21 ; Reserved
ISR_NOERRCODE 22 ; Reserved
ISR_NOERRCODE 23 ; Reserved
ISR_NOERRCODE 24 ; Reserved
ISR_NOERRCODE 25 ; Reserved
ISR_NOERRCODE 26 ; Reserved
ISR_NOERRCODE 27 ; Reserved
ISR_NOERRCODE 28 ; Reserved
ISR_NOERRCODE 29 ; Reserved
ISR_ERRCODE 30 ; Security Exception
ISR_NOERRCODE 31 ; Reserved
isr_common_stub:
test qword [rsp + 24], 3
jz .skip_swap
swapgs
.skip_swap:
PUSHALL
mov rdi, rsp
call isr_handler_c
test qword [rsp + 144], 3
jz .skip_swap_back
swapgs
.skip_swap_back:
POPALL
add rsp, 16
iretq
global idt_load
idt_load:
lidt [rdi]
ret
IRQ_HANDLER 32, irq0
IRQ_HANDLER 33, irq1
+50
View File
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <IO/IOKeyboard.h>
#include <IO/IOConsole.h>
#include <IO/IOTimer.h>
#include <OS/Services/OSServiceProcess.h>
#include <types.h>
void isr_handler_c(CPURegisters* frame) {
if (frame->interruptNumber == 3) {
IOConsoleLog("--------------------------------\n");
IOConsoleLog("\t\t^gREGISTERS^!\n");
IOConsoleLog("--------------------------------\n");
IOConsoleLog("^gRAX^!=%X, ^gRBX^!=%X\n", frame->rax, frame->rbx);
IOConsoleLog("^gRCX^!=%X, ^gRDX^!=%X\n", frame->rcx, frame->rdx);
IOConsoleLog("^gRSI^!=%X, ^gRDI^!=%X\n", frame->rsi, frame->rdi);
IOConsoleLog("^gRBP^!=%X, ^gR8^! =%X\n", frame->rbp, frame->r8);
IOConsoleLog("^gR9^! =%X, ^gR10^!=%X \n", frame->r9, frame->r10);
IOConsoleLog("^gR11^!=%X, ^gR12^!=%X\n", frame->r11, frame->r12);
IOConsoleLog("^gR13^!=%X, ^gR14^!=%X\n", frame->r13, frame->r14);
IOConsoleLog("^gR15^!=%X\n",frame->r15);
IOConsoleLog("--------------------------------\n");
return;
}
if ((frame->cs & 3) != 0) {
IOConsoleLog("\n[Dewar] Process '%s' (PID %d) Segmentation Fault at %X\n",
gOSSchedulerCurrentTask->process->name, gOSSchedulerCurrentTask->process->processId, frame->rip);
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
OSServiceProcessExit(-1);
OSSchedulerNext((UInt64)frame);
return;
}
OSPanicException(frame);
}
UInt64 irq_handler_c(CPURegisters* regs) {
UInt64 curr_rsp = (UInt64)regs;
switch (regs->interruptNumber) {
case 32: curr_rsp = IOTimerInterruptsHandler(regs); break;
case 33: IOKeyboardInterruptsHandler(); break;
default: break;
}
IOPortWrite8(kIOMasterCommand, 0x20);
return curr_rsp;
}
+69
View File
@@ -0,0 +1,69 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2026 0xKarinyash
bits 64
extern syscall_dispatch
global syscall_entry
section .text
syscall_entry:
swapgs
mov [gs:0], rsp ; saving users rsp in g_cpu.user_rsp
mov rsp, [gs:8] ; load kernel rsp from g_cpu.kernel_rsp
push qword [gs:0]
push r11 ; rflags
push rcx ; rip
push rbp
push rbx
push rdi
push rsi
push rdx
push r10
push r8
push r9
push r12
push r13
push r14
push r15
; preparing c code
; c waits rdi, rsi, rdx, rcx, r8, r9
; user sent rax, rdi, rsi, rdx, r10, r8 (rax=id)
mov r9, r8 ; 6th arg
mov r8, r10 ; 5th arg
mov rcx, rdx ; 4th arg
mov rdx, rsi ; 3rd arg
mov rsi, rdi ; 2nd arg
mov rdi, rax ; 1st arg (id)
call syscall_dispatch
; restoring context except RAX (result there)
pop r15
pop r14
pop r13
pop r12
pop r9
pop r8
pop r10
pop rdx
pop rsi
pop rdi
pop rbx
pop rbp
pop rcx ; rip
pop r11 ; rflags
pop rsp
swapgs
o64 sysret
+66
View File
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OSCPU.h>
#include <syscall.h>
#include <types.h>
#include <IO/IOConsole.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <OS/Services/OSServiceProcess.h>
#include <OS/Services/OSServiceMemory.h>
#include <OS/Services/OSServiceIO.h>
static inline void WRMSR(UInt32 msr, UInt64 value) {
UInt32 low = (UInt32)value;
UInt32 high = (UInt32)(value >> 32);
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
}
static inline UInt64 RDMSR(UInt32 msr) {
UInt32 low, high;
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
return ((UInt64)high << 32) | low;
}
extern void syscall_entry();
void OSServicesInitialize() {
UInt64 efer = RDMSR(kHALModelSpecificRegisterExtendedFeatureEnable);
WRMSR(kHALModelSpecificRegisterExtendedFeatureEnable, efer | 1); // Enabling SCE in EFER. Just enabling 0 bit
// setting up STAR
// 32:47 kernel selector (0x08)
// 48:64 user selector (0x01 cuz sysret adds +16 for CS and +8 for SS)
UInt64 star = (0x13ULL << 48) | (0x08ULL << 32);
WRMSR(kHALModelSpecificRegisterSystemCallTarget, star);
WRMSR(kHALModelSpecificRegisterLongSystemCallTarget, (UInt64)syscall_entry); // setting handler adress
// masking flags (IA32_FMASK)
// 9 bit for finterrupts in syscall (IF) and few more necessary flags
WRMSR(kHALModelSpecificRegisterSystemCallFlagMask, 0x200); // masking only IF
if (gOSBootCPU.kernelStackPointer == 0) {
void* physicalStackPointer = VMPhysicalMemoryAllocatePage();
gOSBootCPU.kernelStackPointer = (UInt64)physicalStackPointer + HHDM_OFFSET + 4096;
}
WRMSR(kHALModelSpecificRegisterGSBase, (UInt64)&gOSBootCPU);
WRMSR(kHALModelSpecificRegisterKernelGSBase, (UInt64)&gOSBootCPU);
}
UInt64 syscall_dispatch(UInt64 id, UInt64 arg1, UInt64 arg2, UInt64 arg3, UInt64 arg4, UInt64 arg5) {
switch (id) {
case SYS_EXIT: return OSServiceProcessExit(arg1);
case SYS_SPAWN: return OSServiceProcessSpawn((const char*)arg1);
case SYS_MEM: return OSServiceMemoryAllocate(arg1);
case SYS_WRITE: return OSServiceIOWrite(arg1, arg2, arg3);
case SYS_READ: return OSServiceIORead(arg1, arg2, arg3);
case SYS_WAIT: return OSServiceProcessWait(arg1);
default:
IOConsoleLog("[Dewar] Unknown syscall %d\n", id);
return -1;
}
}
+103
View File
@@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include "bootinfo.h"
#include <types.h>
#include <IO/IOGraphics.h>
#include <IO/IOSerial.h>
#include <IO/IOConsole.h>
#include <IO/IOTimer.h>
#include <IO/IOKeyboard.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <OS/Exec/OSLoader.h>
#include <lib/Splash.h>
#include <lib/Rand.h>
#include <GDT.h>
#include <IDT.h>
#include <PIC.h>
#include <OSCPU.h>
#include <syscall.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
#include <FS/CPIO.h>
#include <FS/VFS.h>
enum {
kDefaultConsoleForegroundColor = 0xffffff,
kDefaultConsoleBackgroundColor = 0x111111,
};
extern UInt64 _kernel_end;
extern void* stack_top;
static IOGraphicsContext sIOGraphicsContext;
void kmain(Bootinfo* info) {
IOSerialInit();
IOSerialWrite("Kernel started\n");
IOConsoleInit(&sIOGraphicsContext);
if (info->magic != BOOTINFO_MAGIC) OSPanic("Corrupt bootinfo!");
OSCPUInitialize((UInt64)&stack_top);
IOConsoleLog("Got CPUINFO\n");
RandInitialize();
IOConsoleLog("Random initialized\n");
HALGlobalDescriptorTableInitialize();
IOConsoleLog("GDT initialized\n");
HALInterruptsDescriptorTableInitialize();
IOConsoleLog("IDT initialized\n");
HALLegacyInterruptControllerRemap();
IOConsoleLog("PIC remapped\n");
VMPhysicalMemoryInitialize(&info->memoryMap);
IOConsoleLog("PMM initialized\n");
VMVirtualMemoryInitialize(info);
IOConsoleLog("VMM initialized\n");
IOTimerInitialize(1000);
IOConsoleLog("Timer initialized\n");
VMHeapInitialize();
IOConsoleLog("Heap initialized\n");
OSSchedulerInitialize();
IOConsoleLog("Scheduler initialized\n");
OSServicesInitialize();
IOConsoleLog("Syscalls initialized");
info = (Bootinfo*)PHYS_TO_HHDM((UInt64)info);
FSVNode* root = FSCPIOMount(PHYS_TO_HHDM(info->initramfs.address), info->initramfs.size);
FSVirtualFileSystemInitialize(root);
IOConsoleLog("VFS initialized\n");
UInt32 *framebuffer = (UInt32*)info->framebuffer.base;
if (!framebuffer) return OSPanic("No framebuffer found!!");
sIOGraphicsContext.framebuffer = framebuffer;
sIOGraphicsContext.dimensions.height = info->framebuffer.height;
sIOGraphicsContext.dimensions.width = info->framebuffer.width;
sIOGraphicsContext.pixelsPerScanLine = info->framebuffer.pitch;
IOConsoleClear(kDefaultConsoleBackgroundColor);
IOConsoleSetForegroundColor(kDefaultConsoleForegroundColor);
IOConsoleSetDefaultForegroundColor(kDefaultConsoleForegroundColor);
SplashShow(&sIOGraphicsContext);
if (!info->initramfs.address) {
OSPanic("Failed to load StartupVolume.");
}
OSSchedulerSpawn(initTask, nullptr, false, 0);
__asm__ volatile("sti");
while (true) __asm__ volatile("hlt");
}
+45
View File
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include "bootinfo.h"
#include <lib/Rand.h>
#include <OSCPU.h>
#include <types.h>
static UInt64 sPseudorandState = 0;
static inline UInt64 RDTSC() {
UInt32 lo, hi;
__asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi));
return ((UInt64)hi << 32) | lo;
}
void RandInitialize() {
sPseudorandState = RDTSC();
if (sPseudorandState == 0) sPseudorandState = BOOTINFO_MAGIC; // why not reuse "termOS"?
}
static UInt64 RandXorshift() {
UInt64 x = sPseudorandState;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return sPseudorandState = x;
}
static bool RandHardware(UInt64 *value) {
UInt8 ok;
__asm__ volatile ("rdrand %0; setc %1"
: "=r" (*value), "=qm" (ok));
return ok != 0;
}
UInt64 Rand() {
UInt64 result;
if (OSCPUHasFeature(kCPUFeatureRDRAND)) {
if (RandHardware(&result)) return result;
}
return RandXorshift();
}
+18
View File
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOGraphics.h>
#include <IO/IOConsole.h>
#include <Data/logo.h>
void SplashShow(IOGraphicsContext* IOGraphicsContextPointer) {
IOGraphicsPoint logoPoint = {0, 10};
IOGraphicsPoint startPoint = {75, 55}; // greeting
IOGraphicsPoint normalTextPoint = {0, 120}; // not nice to hardcode nums like that but we have what we have
IOGraphicsDrawImage(IOGraphicsContextPointer, &logoPoint, &logoImage);
IOConsoleSetCursorPosition(&startPoint);
IOConsoleLog("Welcome to ^ptermOS^!!!!\n");
IOConsoleSetCursorPosition(&normalTextPoint);
}
+86
View File
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <lib/String.h>
void* MemorySet(void* destination, UInt8 value, UInt64 count) {
UInt8* bytePointer = (UInt8*) destination;
while (count--) {
*bytePointer++ = (UInt8)value;
}
return destination;
}
void* MemoryCopy(void* destination, const void* source, UInt64 count) {
UInt8* destinationBuffer = (UInt8*)destination;
const UInt8* sourceBuffer = (const UInt8*)source;
while (count >= 8) {
*(UInt64*)destinationBuffer = *(const UInt64*)sourceBuffer;
destinationBuffer += 8;
sourceBuffer += 8;
count -= 8;
}
while (count > 0) {
*destinationBuffer++ = *sourceBuffer++;
count--;
}
return destination;
}
Int32 StringCompare(const char* firstString, const char* secondString) {
while (*firstString && (*firstString == *secondString)) {
firstString++;
secondString++;
}
return *(const unsigned char*)firstString - *(const unsigned char*)secondString;
}
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit) {
while (limit > 0) {
if (*firstString != *secondString) return *(unsigned char*)firstString - *(unsigned char*)secondString;
if (*firstString == '\0') return 0;
firstString++;
secondString++;
limit--;
}
return 0;
}
char* StringCopy(char* destination, const char* source) {
char* saved = destination;
while (*source) *destination++ = *source++;
*destination = 0;
return saved;
}
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit) {
char* saved = destination;
while (*source && limit > 0) {
*destination++ = *source++;
limit--;
}
while (limit > 0) {
*destination++ = 0;
limit--;
}
return saved;
}
UInt64 StringGetLength(const char* string) {
UInt64 result = 0;
for (result = 0; string[result]; result++);
return result;
}
const char* StringFindLastOccurrenceOfCharacter(const char* string, char separator) {
const char* lastSeparator = nullptr;
do {
if (*string == separator) lastSeparator = (char*)string;
} while (*string++);
return lastSeparator;
}