REF: Renamed kernel -> System; userspace -> Runtime; bootloader -> Boot
del: KSH
This commit is contained in:
@@ -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..."
|
||||
)
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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, ...);
|
||||
@@ -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
|
||||
);
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
UInt16 HALLegacyInterruptControllerRemap();
|
||||
@@ -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();
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"); }
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user