23 Commits

Author SHA1 Message Date
Karina aa6b7924e2 feat: custom objc runtime, msgSend, and HOTObject experiment 2026-02-01 18:03:08 +04:00
Karina 4e10985909 ref(KSH): Renamed files and folder 2026-02-01 00:39:18 +04:00
Karina c72dbc763c chore(CPIO): changed panic text 2026-02-01 00:28:19 +04:00
Karina 02b36283a5 ref(libkern): changed to match libterm 2026-02-01 00:26:22 +04:00
Karina e21f5ef52f ref(libterm): now apple-styled too 2026-01-31 22:47:42 +04:00
Karina 2be7d3bd46 fix(scheduler): garbage collector now wakes up on process terminate
fix(scheduler/spawn): now its doesnt OSPanic's when VMHeapAllocate returned nullptr for stackBaseAddress. It wakes up GC, tries again and if it failed return nullptr
2026-01-31 21:28:02 +04:00
Karina 02dc35f0df feat(core): implement spinlocks, GC and keyboard safety
* Implemented Spinlocks and applied to VM/Scheduler

* Added Garbage Collector for tasks

* Moved Getchar to IOKeyboard with locking

* Cleanup panic messages
2026-01-31 20:50:27 +04:00
Karina ee67cef4f8 ref: initramfs -> StartupVolume; /bin -> /System/CoreServices;
ref(Kernel/VM/Heap): malloc -> VMHeapAllocate; free -> VMHeapFree; realloc -> VMHeapResize
2026-01-31 16:11:45 +04:00
Karina c30d57d06e fix(ksh/regs): now it doesnt panic when typing regs in ksh
fix(kmain): Now Dewar correctly OSPanic()'s instead of returnin IOConsoleLog when no framebuffer found
2026-01-31 02:49:34 +04:00
Karina 4e6794a6c2 chore: update copyrights 2026-01-31 01:57:28 +04:00
Karina e63983c95d full refactor in kernel/: now its apple-styled; im so fucking tired 2026-01-31 01:40:10 +04:00
Karina e323e91dac chore(libterm/stdio): printf reworked, vsnprintf() and snprintf() 2026-01-30 20:22:45 +04:00
Karina 52d0bfeaae chore(cpio): moved initramfs binary files to /bin/* 2026-01-30 17:25:01 +04:00
Karina ae7e1a91d0 fix(syscall/proc): i32 in sys_exit and sys_spawn
fix(userspace/string.h): gets_s now correctly work with \b

chore(kmain): now ring3 is default when pressing any key (instead of ksh)

feat(termosh): spawn in termosh
2026-01-30 10:19:05 +04:00
Karina c5741374cd fix(syscalls/proc): sys_exit and sys_wait now returns code and pid respectively 2026-01-30 08:20:05 +04:00
Karina 385b7d7a13 wip(termosh); strspn strpbrk and strtok in string.h; 2026-01-30 08:10:08 +04:00
Karina 3f95b6d282 chore(ksh): disabled 'userspace' command due to be really broken 2026-01-30 07:20:01 +04:00
Karina 92aaa47435 docs: roadmap update 2026-01-30 07:16:24 +04:00
Karina caf2d2b4a8 v0.5.3: syscalls, minilibc.
- fix(gs): was a nightmare. now its solved. Both MSR_GS_BASE and MSR_KERNEL_GS_BASE are now initialized to , preventing null GS_BASE when interrupt occurs during the first kernel task run
- chore(syscall.asm): stability improvements. User RSP is now saved via kernel stack instead of global g_cpu, preventing stack theft when task switch occurs during a syscall
- feat(interrupts): all irq and isr handlers now conditionally perform swapgs based on the CS selector (checkin if comfing from ring 3)
- upgrade(scheduler): big update: 1) added TASK_BLOCKED state from process sync; 2) syncronized PID and Task ID to fix wakeup logic; 3) implemented sched_block and sched_exit() for proper wait/exit syscalls
2026-01-30 07:12:57 +04:00
Karina 888bc5abdd v0.5.3-pre: refactor syscall handlers and introduce libterm
Moved handlers to syscalls/, implemented libterm (malloc, stdio)
2026-01-30 04:58:43 +04:00
Karina 9c103218d0 docs: readme and roadmap 2026-01-30 00:52:43 +04:00
Karina 21270a3cc8 feat: introduce HOT! executable format and Ring 3 process isolation (v0.5.2)
- Implement custom 'HOT!' binary format and Rust-based elf2hot converter.
- Upgrade kernel loader with segment-based loading and BSS zeroing.
- Refactor scheduler for Ring 3 IRET frames and fix CS/SS selector swap.
- Add user stack allocation (0x70000000) and linker scripts for binary cleanup.
2026-01-30 00:12:11 +04:00
Karina 7d32444da2 feat(core): v0.5.1 - process isolation and syscalls
- Implemented CR3 switching in scheduler for process isolation

- Added 'process' structure and PML4 cloning (vmm_create_address_space)

- Added NASM crt0 and C entry point for userspace apps
2026-01-29 22:28:41 +04:00
173 changed files with 4805 additions and 2729 deletions
+4
View File
@@ -0,0 +1,4 @@
If:
PathMatch: .*\.h
CompileFlags:
Add: [-x, objective-c]
+3 -1
View File
@@ -2,4 +2,6 @@
build*
.venv
initrd/image.cpio
initramfs/*
initramfs/*
target
+2 -2
View File
@@ -3,7 +3,7 @@ build
.venv
kernel/data
*.md
tools/
bootloader/
bootloader/src/uefi
initramfs/
initramfs/
kernel/inc/Data
+18 -13
View File
@@ -30,23 +30,28 @@ add_subdirectory(bootloader)
add_subdirectory(kernel)
add_subdirectory(userspace)
set(SYSTEM_SERVICES
init
debug
termosh
testOBJC
)
set(VOLUME_ROOT "${CMAKE_BINARY_DIR}/StartupVolume")
set(INITRAMFS_CPIO_FILE "${CMAKE_BINARY_DIR}/StartupVolume.cpio")
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
set(INITRAMFS_SRC_DIR "${CMAKE_SOURCE_DIR}/initramfs")
set(INITRAMFS_CPIO_FILE "${CMAKE_BINARY_DIR}/initramfs.cpio")
file(GLOB_RECURSE INIT_FILES "${INITRAMFS_SRC_DIR}/*")
add_custom_command(
add_custom_command(
OUTPUT ${INITRAMFS_CPIO_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${VOLUME_ROOT}
COMMAND sh -c "find . -mindepth 1 ! -name '*.cpio' -print0 | ${CPIO_EXE} --null -ov -H newc > \"${INITRAMFS_CPIO_FILE}\""
WORKING_DIRECTORY ${INITRAMFS_SRC_DIR}
DEPENDS ${INIT_FILES} init
WORKING_DIRECTORY ${VOLUME_ROOT}
DEPENDS ${SYSTEM_SERVICES}
VERBATIM
COMMENT "Packing initramfs to cpio..."
COMMENT "Packing StartupVolume to cpio..."
)
add_custom_command(
OUTPUT ${IMG_FILE}
COMMAND dd if=/dev/zero of=${IMG_FILE} bs=1M count=64 status=none
@@ -54,7 +59,7 @@ if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
COMMAND mmd -i ${IMG_FILE} ::/EFI ::/EFI/BOOT
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} $<TARGET_FILE:BOOTX64> ::/EFI/BOOT/BOOTX64.EFI
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} ${CMAKE_BINARY_DIR}/bin/kernel.bin ::/kernel.bin
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} ${INITRAMFS_CPIO_FILE} ::/initramfs.cpio
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} ${INITRAMFS_CPIO_FILE} ::/StartupVolume.cpio
DEPENDS BOOTX64 kernel ${INITRAMFS_CPIO_FILE}
VERBATIM
COMMENT "Generating bootable image: ${IMG_FILE}"
+35 -2
View File
@@ -4,6 +4,39 @@
<img src='assets/logo.png'>
</p>
Just a hobby, won't be big and professional like Linux
> "Just a hobby, won't be big and professional like Linux."
> — *Linus Torvalds (and now me)*
Really WIP. And really just a hobby.
**termOS** is a 64-bit, UNIX-hating, bespoke operating system written from scratch in C.
Current Kernel: **Dewar** (v0.5.x)
## Philosophy
- **Zero Bloat:** We don't port libraries; we write them.
- **Custom Everything:** Why use ELF when you can invent **HOT!**? Why use GRUB when you can write your own bootloader (soon)?
## Features (v0.5.2)
- **Architecture:** x86_64 / UEFI.
- **Memory Management:** PMM (Bitmap), VMM (PML4 + Higher Half Direct Map), Kernel Heap.
- **Multitasking:** Preemptive scheduler with Round Robin.
- **Isolation:** Ring 0 (Kernel) / Ring 3 (Userspace) protection.
- **Binaries:** Custom **HOT!** executable format (parsed via custom `elf2hot` toolchain).
- **Filesystem:** VFS abstraction with CPIO Initramfs support.
- **Graphics:** `ShitGUI` (yes, really) linear framebuffer driver.
- **Shell:** `ksh` (Kernel Shell) -> transitioning to userspace `ush`
## 🔥 The HOT! Format
termOS uses its own executable format called **HOT!**.
Because parsing ELF headers is too mainstream. HOT! is a flat, segment-based format designed specifically for the Dewar kernel loader.
Made only because ELF is *Not-invented-here*
## Roadmap
See [ROADMAP.md](ROADMAP.md) for the detailed plan of world domination (or at least self-hosting).
## License
**GPL-3.0-or-later**.
+103
View File
@@ -0,0 +1,103 @@
# termOS Roadmap
## Legend
-**Done**: Implemented and working.
- 🚧 **WIP**: Currently under active development.
- 📅 **Planned**: Scheduled for future releases.
- 🤔 **Vision**: Long-term goals for v1.0.
---
## Current Status: v0.5.3 (Alpha)
*Where we are now.*
- **Core:** Ring 0 / Ring 3 isolation implemented.
- **Mem:** PMM (bitmap), VMM (PML4, HHDM).
- **Exec:** Custom **HOT!** executable format (static loader).
- **FS:** VFS + Initramfs (CPIO, read-only).
- **User:** Basic jump to userspace (hardcoded stack, no heap yet).
---
## 📅 Phase 1
*Goal: Transform the decorative userspace into a functional mechanism.*
### v0.5.4 (The Shell Update)
*Focus: Interactive Userspace*
- [x] **Userspace Shell (`termosh`)**
- Porting `ksh` logic into a standalone `.hot` binary.
- Standard I/O abstraction (stdin/stdout) to pass keyboard input to active process.
- [ ] ~~**Basic Utils** (`ls`, `cat`, `echo`)~~ *(Moved to v0.6.1 — awaiting Apple-style API)*
---
## 📅 Phase 2
*Goal: Total independence from external libraries and architectural hygiene.*
### v0.6.0 (Architecture Overhaul)
- [ ] **System-wide Naming & API Refactoring (Apple-style)**
- Replace generic types with PascalCase branding (`u64` -> `UInt64`, `i32` -> `Int32`).
- Standardize system prefixes: `VM` for Virtual Memory, `OS` for Core, `CPU` for HAL.
- Transition from `snake_case` to `PascalCase` for all kernel functions and structures.
- Implement `OSReturn` status codes for unified error handling.
- [ ] **Bootloader Independence**
- Remove `posix-uefi` library.
- Write custom UEFI entry point (pure PE).
- Kernel itself becomes a valid `.hot` executable.
- [ ] **HOT! Format Hardening**
- Fix segment alignment (Page Alignment) in `elf2hot` and kernel loader.
- Add metadata headers (stack size, permissions).
- [ ] **Concurrency Fixes**
- Implement spinlocks (`spinlock`).
- Protect allocator and process lists from interrupt race conditions.
---
## 📅 Phase 3
*Goal: Prepare the environment for self-hosting. We cannot compile on a Read-Only FS.*
### v0.7.0 (Filesystem & Input)
- [ ] **Write Support**
- Storage driver (NVMe/AHCI or Writable RAMDisk).
- Writable Filesystem (FAT32 or custom simple FS).
- [ ] **Input Subsystem**
- Input buffering, Pipe (`|`) support in shell.
- Basic TTY/PTY abstraction.
### v0.8.0 (The Editor)
- [ ] **Text Editor**
- Write a simple editor (nano-like) in userspace.
- Capabilities: Open, Edit, Save files.
---
## 📅 Phase 4
*Goal: Self-Hosting.*
### v0.9.0 (The Toolchain)
- [ ] **Linker (`hld`)**
- Native linker capable of outputting `.hot` files (running inside termOS).
- [ ] **Compiler Port**
- Port **TCC (Tiny C Compiler)** to termOS.
- Adapt libc headers for the OS environment.
### 🤔 v1.0.0 (Self-Hosting)
- [ ] **Bootstrapping**
- Compile the Dewar kernel *inside* termOS.
- Boot from the newly compiled kernel.
- Total victory.
---
## 📜 History
| Version | Date | Key Features |
| :--- | :--- | :--- |
| **v0.5.3** | 2026-01-30 | `sys_mem`, `sys_spawn`, `sys_wait`, `sys_exit` |
| **v0.5.2** | 2026-01-30 | **HOT!** format, Ring 3 isolation, VFS, CPIO parsing. |
| **v0.5.1** | 2026-01-29 | Initial userspace jumps, syscall mechanics. |
| **v0.5.0** | 2026-01-29 | Kernel officially named "Dewar". Versioning standardized. |
| **v0.4.x** | 2026-01-28 | Basic VFS, Shell improvements, basic multitasking. |
| **v0.3.x** | 2025-12-30 | Scheduler, ~~Composer~~, Heap manager. |
| **v0.2.x** | 2025-12-28 | `ksh`, Keyboard driver, HHDM, PMM/VMM. |
| **v0.1.x** | 2025-12-21 | First boot, GDT/IDT, Serial/Console, Panic handler. |
+11 -11
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include "uefi.h" // IWYU pragma: keep
#include "../../common/bootinfo.h"
@@ -78,11 +78,11 @@ int main()
efi_file_handle_t* initramfs_file;
uintn_t iinfo_size = 0;
efi_file_info_t* ifile_info = nullptr;
status = root->Open(root, &initramfs_file, L"initramfs.cpio", EFI_FILE_MODE_READ, 0);
status = root->Open(root, &initramfs_file, L"StartupVolume.cpio", EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(status)) {
print_initramfs_warning(L"initramfs.cpio is missing");
boot_info->initramfs.addr = nullptr;
print_initramfs_warning(L"StartupVolume.cpio is missing");
boot_info->initramfs.address = nullptr;
boot_info->initramfs.size = 0;
} else {
status = initramfs_file->GetInfo(initramfs_file, &fi_guid, &iinfo_size, nullptr);
@@ -105,14 +105,14 @@ int main()
// just fucking kill me
uintn_t initramfs_size_read = (uintn_t)initramfs_size;
initramfs_file->Read(initramfs_file, &initramfs_size_read, (void*)initramfs_addr);
boot_info->initramfs.addr = (void*)initramfs_addr;
boot_info->initramfs.address = (void*)initramfs_addr;
boot_info->initramfs.size = initramfs_size;
}
}
}
boot_info->framebuffer.base = (uint32_t*)gop->Mode->FrameBufferBase;
boot_info->framebuffer.base_size = gop->Mode->FrameBufferSize;
boot_info->framebuffer.baseSize = gop->Mode->FrameBufferSize;
boot_info->framebuffer.height = gop->Mode->Information->VerticalResolution;
boot_info->framebuffer.width = gop->Mode->Information->HorizontalResolution;
boot_info->framebuffer.pitch = gop->Mode->Information->PixelsPerScanLine;
@@ -139,11 +139,11 @@ int main()
break;
}
boot_info->mem.descriptor_size = desc_size;
boot_info->mem.descriptor_version = desc_version;
boot_info->mem.map_size = map_size;
boot_info->mem.map_key = map_key;
boot_info->mem.map = map;
boot_info->memoryMap.descriptorSize = desc_size;
boot_info->memoryMap.descriptorVersion = desc_version;
boot_info->memoryMap.mapSize = map_size;
boot_info->memoryMap.mapKey = map_key;
boot_info->memoryMap.map = map;
status = gBS->ExitBootServices(IM, map_key);
if (status == EFI_SUCCESS) {
+11 -11
View File
@@ -46,7 +46,7 @@ void __stdio_cleanup(void)
BS->FreePool(__argvutf8);
#endif
if(__blk_devs) {
free(__blk_devs);
MemoryFree(__blk_devs);
__blk_devs = NULL;
__blk_ndevs = 0;
}
@@ -127,7 +127,7 @@ int fclose (FILE *__stream)
if(__stream == (FILE*)__blk_devs[i].bio)
return 1;
status = __stream->Close(__stream);
free(__stream);
MemoryFree(__stream);
return !EFI_ERROR(status);
}
@@ -188,7 +188,7 @@ err: __stdio_seterrno(status);
return -1;
}
/* no need for fclose(f); */
free(f);
MemoryFree(f);
return 0;
}
@@ -250,7 +250,7 @@ FILE *fopen (const char_t *__filename, const char_t *__modes)
/* workaround a bug in TianoCore, it reports zero size even though the data is in the buffer */
if(handle_size < 1)
handle_size = (uintn_t)sizeof(handles) / sizeof(efi_handle_t);
__blk_devs = (block_file_t*)malloc(handle_size * sizeof(block_file_t));
__blk_devs = (block_file_t*)MemoryAllocate(handle_size * sizeof(block_file_t));
if(__blk_devs) {
memset(__blk_devs, 0, handle_size * sizeof(block_file_t));
for(i = __blk_ndevs = 0; i < handle_size; i++)
@@ -276,7 +276,7 @@ FILE *fopen (const char_t *__filename, const char_t *__modes)
errno = ENODEV;
return NULL;
}
ret = (FILE*)malloc(sizeof(FILE));
ret = (FILE*)MemoryAllocate(sizeof(FILE));
if(!ret) return NULL;
/* normally write means read,write,create. But for remove (internal '*' mode), we need read,write without create
* also mode 'w' in POSIX means write-only (without read), but that's not working on certain firmware, we must
@@ -292,16 +292,16 @@ FILE *fopen (const char_t *__filename, const char_t *__modes)
__modes[1] == CL('d') ? EFI_FILE_DIRECTORY : 0);
if(EFI_ERROR(status)) {
err: __stdio_seterrno(status);
free(ret); return NULL;
MemoryFree(ret); return NULL;
}
if(__modes[0] == CL('*')) return ret;
status = ret->GetInfo(ret, &infGuid, &fsiz, &info);
if(EFI_ERROR(status)) goto err;
if(__modes[1] == CL('d') && !(info.Attribute & EFI_FILE_DIRECTORY)) {
ret->Close(ret); free(ret); errno = ENOTDIR; return NULL;
ret->Close(ret); MemoryFree(ret); errno = ENOTDIR; return NULL;
}
if(__modes[1] != CL('d') && (info.Attribute & EFI_FILE_DIRECTORY)) {
ret->Close(ret); free(ret); errno = EISDIR; return NULL;
ret->Close(ret); MemoryFree(ret); errno = EISDIR; return NULL;
}
if(__modes[0] == CL('a')) fseek(ret, 0, SEEK_END);
if(__modes[0] == CL('w')) {
@@ -713,7 +713,7 @@ int sprintf(char_t *dst, const char_t* fmt, ...)
return ret;
}
int snprintf(char_t *dst, size_t maxlen, const char_t* fmt, ...)
int StringFormat(char_t *dst, size_t maxlen, const char_t* fmt, ...)
{
int ret;
__builtin_va_list args;
@@ -738,7 +738,7 @@ int vprintf(const char_t* fmt, __builtin_va_list args)
return ret;
}
int printf(const char_t* fmt, ...)
int ConsolePrint(const char_t* fmt, ...)
{
int ret;
__builtin_va_list args;
@@ -800,7 +800,7 @@ int getchar_ifany (void)
return EFI_ERROR(status) ? 0 : key.UnicodeChar;
}
int getchar (void)
int ConsoleGetCharacter (void)
{
uintn_t idx;
BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &idx);
+7 -7
View File
@@ -77,7 +77,7 @@ int64_t strtol (const char_t *s, char_t **__endptr, int __base)
return v * sign;
}
void *malloc (size_t __size)
void *MemoryAllocate (size_t __size)
{
void *ret = NULL;
efi_status_t status;
@@ -106,20 +106,20 @@ void *malloc (size_t __size)
void *calloc (size_t __nmemb, size_t __size)
{
void *ret = malloc(__nmemb * __size);
void *ret = MemoryAllocate(__nmemb * __size);
if(ret) memset(ret, 0, __nmemb * __size);
return ret;
}
void *realloc (void *__ptr, size_t __size)
void *MemoryReallocate (void *__ptr, size_t __size)
{
void *ret = NULL;
efi_status_t status;
#ifndef UEFI_NO_TRACK_ALLOC
uintn_t i;
#endif
if(!__ptr) return malloc(__size);
if(!__size) { free(__ptr); return NULL; }
if(!__ptr) return MemoryAllocate(__size);
if(!__size) { MemoryFree(__ptr); return NULL; }
#ifndef UEFI_NO_TRACK_ALLOC
/* get the slot which stores the old size for this buffer */
for(i = 0; i < __stdlib_numallocs && __stdlib_allocs[i] != (uintptr_t)__ptr; i += 2);
@@ -145,7 +145,7 @@ void *realloc (void *__ptr, size_t __size)
return ret;
}
void free (void *__ptr)
void MemoryFree (void *__ptr)
{
efi_status_t status;
#ifndef UEFI_NO_TRACK_ALLOC
@@ -341,7 +341,7 @@ uint8_t *getenv(char_t *name, uintn_t *len)
#else
status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
#endif
if(EFI_ERROR(status) || *len < 1 || !(ret = malloc((*len) + 1))) {
if(EFI_ERROR(status) || *len < 1 || !(ret = MemoryAllocate((*len) + 1))) {
*len = 0;
return NULL;
}
+2 -2
View File
@@ -116,7 +116,7 @@ void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl)
return NULL;
}
char_t *strcpy(char_t *dst, const char_t *src)
char_t *StringCopy(char_t *dst, const char_t *src)
{
char_t *s = dst;
if(src && dst && src != dst) {
@@ -178,7 +178,7 @@ int strncmp(const char_t *s1, const char_t *s2, size_t n)
char_t *strdup(const char_t *s)
{
size_t i = (strlen(s)+1) * sizeof(char_t);
char_t *s2 = (char_t *)malloc(i);
char_t *s2 = (char_t *)MemoryAllocate(i);
if(s2 != NULL) memcpy(s2, (const void*)s, i);
return s2;
}
+7 -7
View File
@@ -1314,10 +1314,10 @@ typedef int (*__compar_fn_t) (const void *, const void *);
extern int atoi (const char_t *__nptr);
extern int64_t atol (const char_t *__nptr);
extern int64_t strtol (const char_t *__nptr, char_t **__endptr, int __base);
extern void *malloc (size_t __size);
extern void *MemoryAllocate (size_t __size);
extern void *calloc (size_t __nmemb, size_t __size);
extern void *realloc (void *__ptr, size_t __size);
extern void free (void *__ptr);
extern void *MemoryReallocate (void *__ptr, size_t __size);
extern void MemoryFree (void *__ptr);
extern void abort (void);
extern void exit (int __status);
/* exit Boot Services function. Returns 0 on success. */
@@ -1355,14 +1355,14 @@ extern int fseek (FILE *__stream, long int __off, int __whence);
extern long int ftell (FILE *__stream);
extern int feof (FILE *__stream);
extern int fprintf (FILE *__stream, const char_t *__format, ...);
extern int printf (const char_t *__format, ...);
extern int ConsolePrint (const char_t *__format, ...);
extern int sprintf (char_t *__s, const char_t *__format, ...);
extern int vfprintf (FILE *__s, const char_t *__format, __builtin_va_list __arg);
extern int vprintf (const char_t *__format, __builtin_va_list __arg);
extern int vsprintf (char_t *__s, const char_t *__format, __builtin_va_list __arg);
extern int snprintf (char_t *__s, size_t __maxlen, const char_t *__format, ...);
extern int StringFormat (char_t *__s, size_t __maxlen, const char_t *__format, ...);
extern int vsnprintf (char_t *__s, size_t __maxlen, const char_t *__format, __builtin_va_list __arg);
extern int getchar (void);
extern int ConsoleGetCharacter (void);
/* non-blocking, only returns UNICODE if there's any key pressed, 0 otherwise */
extern int getchar_ifany (void);
extern int putchar (int __c);
@@ -1376,7 +1376,7 @@ extern void *memchr(const void *__s, int __c, size_t __n);
extern void *memrchr(const void *__s, int __c, size_t __n);
void *memmem(const void *haystack, size_t hl, const void *needle, size_t nl);
void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl);
extern char_t *strcpy (char_t *__dest, const char_t *__src);
extern char_t *StringCopy (char_t *__dest, const char_t *__src);
extern char_t *strncpy (char_t *__dest, const char_t *__src, size_t __n);
extern char_t *strcat (char_t *__dest, const char_t *__src);
extern char_t *strncat (char_t *__dest, const char_t *__src, size_t __n);
+21 -21
View File
@@ -1,37 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
typedef unsigned int bi_u32;
typedef unsigned long long bi_u64;
typedef unsigned int BIUInt32;
typedef unsigned long long BIUInt64;
typedef struct {
bi_u32* base;
bi_u64 base_size;
bi_u64 width;
bi_u64 height;
bi_u64 pitch;
} BI_Framebuffer;
BIUInt32* base;
BIUInt64 baseSize;
BIUInt64 width;
BIUInt64 height;
BIUInt64 pitch;
} BIFramebuffer;
typedef struct {
void* map;
bi_u64 map_size;
bi_u64 descriptor_size;
bi_u32 map_key;
bi_u32 descriptor_version;
} BI_MemoryMap;
BIUInt64 mapSize;
BIUInt64 descriptorSize;
BIUInt32 mapKey;
BIUInt32 descriptorVersion;
} BIMemoryMap;
typedef struct {
void* addr;
bi_u64 size;
} BI_Initramfs;
void* address;
BIUInt64 size;
} BIInitramfs;
typedef struct {
bi_u64 magic;
BI_Framebuffer framebuffer;
BI_MemoryMap mem;
BI_Initramfs initramfs;
BIUInt64 magic;
BIFramebuffer framebuffer;
BIMemoryMap memoryMap;
BIInitramfs initramfs;
} Bootinfo;
#define BOOTINFO_MAGIC 0x7465726D // term
+23
View File
@@ -0,0 +1,23 @@
typedef unsigned char UInt8;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
typedef unsigned long long UInt64;
#define HOT_MAGIC 0x21544F48
typedef struct HOTSegment {
UInt64 type; // 1 = rx 2 = rw
UInt64 vaddr;
UInt64 offset;
UInt64 filesz;
UInt64 memsz;
} HOTSegment;
typedef struct HOTHeader {
UInt32 magic; // "HOT!"
UInt8 version; // 1
UInt8 reserved_pad[3];
UInt64 entry_point;
UInt64 segments_count;
UInt64 reserved;
} HOTHeader;
+10 -7
View File
@@ -18,13 +18,16 @@ file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
"src/arch/${ARCH}/*.c"
"src/arch/${ARCH}/*.asm"
"src/core/*.c"
"src/drivers/*.c"
"src/mm/*.c"
"src/shell/*.c"
"src/fs/*.c"
"src/OS/*.c"
"src/OS/Exec/*.c"
"src/OS/Services/*.c"
"src/lib/*.c"
"src/IO/*.c"
"src/VM/*.c"
"src/KSH/*.c"
"src/FS/*.c"
"data/*.c"
"Data/*.c"
)
add_executable(kernel ${KERNEL_SOURCES})
@@ -33,7 +36,7 @@ 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"
"${CMAKE_CURRENT_SOURCE_DIR}/Data"
)
target_compile_options(kernel PRIVATE
@@ -1,8 +1,8 @@
// font8x16 bitmap font
// Source: https://github.com/hubenchang0515/font8x16
// License: MIT
#pragma once
#include <types.h>
unsigned char font8x16[][16] = {
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,
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
// cats licensed to their authors
// i took it from https://www.asciiart.eu/animals/cats
@@ -1,14 +1,14 @@
// Huge thanks to https://t.me/kinolenta2004 for this amazing logo
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <drivers/shitgui.h>
#include <IO/IOGraphics.h>
#define LOGO_TRANSPARENCY_KEY 0xFF00FF
// Image: 100x100
static const u32 logo_data[] = {
static const UInt32 logo_data[] = {
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
@@ -1261,8 +1261,7 @@ static const u32 logo_data[] = {
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
};
static SG_Image logo_img = {
.width = 100,
.height = 100,
.buffer = (u32*)logo_data
static IOGraphicsImage logoImage = {
.size = {100, 100},
.buffer = (UInt32*)logo_data
};
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <FS/VFS.h>
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize);
+42
View File
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef enum FSVNodeFlags {
kFSVNodeFlagFile = 0x01,
kFSVNodeFlagDirectory = 0x02,
} FSVNodeFlags;
typedef struct FSVNode FSVNode;
typedef struct FSVNodeOperations {
UInt64 (*read)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
UInt64 (*write)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
void (*open)(FSVNode* node);
void (*close)(FSVNode* node);
FSVNode* (*findDirectory)(FSVNode* node, char* name);
} FSVNodeOperations;
typedef struct FSVNode {
char name[256];
UInt32 protectionMask;
UInt32 ownerIdentifier;
UInt32 groupIdentifier;
UInt32 flags;
UInt32 inodeIdentifier;
UInt64 dataLength;
FSVNodeOperations* operations;
void* implementationData;
struct FSVNode* mountPoint;
struct FSVNode* childNode;
struct FSVNode* nextNode;
} FSVNode;
void FSVirtualFileSystemInitialize(FSVNode* rootNode);
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
FSVNode* FSVirtualFileSystemOpenPath(const char* path);
void FSVNodeClose(FSVNode* node);
+35
View File
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
enum {
kIOConsoleColorRed = 0xFF5555,
kIOConsoleColorVeryRed = 0xFF0000,
kIOConsoleColorGreen = 0x08bf39,
kIOConsoleColorVeryGreen = 0x00FF00,
kIOConsoleColorTurqoise = 0x5effaf,
kIOConsoleColorBlue = 0x5555FF,
kIOConsoleColorVeryBlue = 0x0000FF,
kIOConsoleColorLightBlue = 0x3890e8,
kIOConsoleColorYellow = 0xFFFF55,
kIOConsoleColorCyan = 0x55FFFF,
kIOConsoleColorMagneta = 0xFF55FF,
kIOConsoleColorBlack = 0x000000,
kIOConsoleColorWhite = 0xFFFFFF,
kIOConsoleColorPink = 0xFFA3B1,
};
void IOConsoleInit(IOGraphicsContext* context);
UInt64 IOConsoleGetColors();
void IOConsoleClear(IOGraphicsColor color);
IOGraphicsContext* IOConsoleGetGraphicsContext();
IOGraphicsSize IOConsoleGetDimensions();
void IOConsoleSetForegroundColor(IOGraphicsColor color);
void IOConsoleSetDefaultForegroundColor(UInt32 color);
void IOConsoleSetCursorPosition(IOGraphicsPoint* point);
void IOConsoleReadLine(char* buffer, UInt32 limit);
void IOConsolePutcharacter(char character);
void IOConsolePrint(const char *string);
void IOConsoleLog(const char *fmt, ...);
+50
View File
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// RIP shitgui -- you started it all
#pragma once
#include <types.h>
typedef UInt32 IOGraphicsColor;
typedef struct {
UInt32 x;
UInt32 y;
} IOGraphicsPoint;
typedef struct {
UInt32 width;
UInt32 height;
} IOGraphicsSize;
typedef struct {
volatile UInt32* framebuffer;
IOGraphicsSize dimensions;
UInt32 pixelsPerScanLine;
} IOGraphicsContext;
typedef struct {
IOGraphicsColor* buffer;
IOGraphicsSize size;
} IOGraphicsImage;
typedef struct {
IOGraphicsSize size;
const unsigned char* baseAddress;
} IOGraphicsFont;
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point);
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image);
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point,
IOGraphicsSize* size, IOGraphicsColor color);
void IOGraphicsDrawCharacter(
IOGraphicsContext* context,
IOGraphicsPoint* point,
char character,
IOGraphicsColor color,
IOGraphicsFont* font
);
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <OS/OSSpinlock.h>
enum {
kIOKeyboardBufferSize = 256,
};
typedef struct {
OSSpinlock lock;
char buffer[kIOKeyboardBufferSize];
volatile UInt16 head;
volatile UInt16 tail;
} IOKeyboardController;
extern IOKeyboardController gIOKeyboardController;
void IOKeyboardInterruptsHandler();
char IOKeyboardGetCharacter();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
int IOSerialInit();
void IOSerialWriteChar(char character);
void IOSerialWrite(const char *string);
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
void IOTimerInitialize(UInt32 freq);
UInt64 IOTimerInterruptsHandler(CPURegisters *regs);
UInt64 IOTimerGetTicks();
+13
View File
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
void KSHCommandKernelFetch();
void KSHCommandMeow();
void KSHCommandHelp();
void KSHCommandRegisters();
void KSHCommandSleep();
void KSHCommandDebug();
void KSHCommandRand();
void KSHCommandVer();
@@ -2,8 +2,6 @@
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
bool exec_init(const char* path);
void init_task_entry();
UInt64 KSHDebug();
@@ -3,4 +3,4 @@
#pragma once
void jump_to_userspace(void* entry, void* user_stack_top);
void KSHEntry();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <OS/OSScheduler.h>
UInt64 HOTLoad(OSProcess* process, UInt8* data);
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName);
void init_task_entry();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame);
__attribute__((noreturn)) void OSPanic(const char* msg);
+45
View File
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef enum OSProcessState {
kOSProcessStateDead,
kOSProcessStateRunning,
kOSProcessStateReady,
kOSProcessStateBlocked,
kOSProcessStateSleeping,
} OSProcessState;
typedef struct OSProcess {
UInt64 processId;
OSProcessState state;
UInt64 physicalPML4;
struct OSProcess* parent;
char name[32];
UInt64 heapStartPointer;
UInt64 heapCurrentPointer;
} OSProcess;
typedef struct OSTask {
UInt64 stackPointer;
struct OSTask* next;
UInt32 id;
UInt32 sleepTicks;
OSProcessState taskState; // reusing process_state cuz wn
UInt64 kernelStackTop;
void* kernelStackBase;
OSProcess* process;
Int32 waitingForProcess;
} OSTask;
void OSSchedulerInitialize();
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer);
UInt64 OSSchedulerNext(UInt64 currentStackPointer);
void OSSchedulerYield(UInt64 ticks);
void OSSchedulerBlock(UInt32 processID);
void OSSchedulerWakeup(UInt32 processID);
void OSSchedulerTerminate(); // suicide
extern OSTask* gOSSchedulerCurrentTask;
+19
View File
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef struct OSSpinlock {
volatile UInt32 lockValue;
} OSSpinlock;
typedef struct OSSpinlockState {
Boolean interruptsEnabled;
} OSSpinlockState;
void OSSpinlockLock(OSSpinlock* lock);
void OSSpinlockUnlock(OSSpinlock* lock);
void OSSpinlockLockIRQ(OSSpinlock* lock, OSSpinlockState* state);
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState* state);
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length);
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count);
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
void rng_init();
u64 krand();
UInt64 OSServiceMemoryAllocate(UInt64 size);
+10
View File
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
Int32 OSServiceProcessExit(Int32 code);
Int32 OSServiceProcessSpawn(const char* path);
Int32 OSServiceProcessWait(UInt64 pid);
+26
View File
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
enum {
kVMKernelHeapStart = 0xFFFFFFFFC0000000,
kVMHeapSizePages = 1024,
kVMHeapBlockHeaderMagic = 0x1CE
};
#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START)
#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START)
typedef struct VMHeapBlockHeader {
UInt64 magic;
struct VMHeapBlockHeader* next;
struct VMHeapBlockHeader* previous;
UInt64 size;
bool isFree;
} VMHeapBlockHeader;
void VMHeapInitialize();
void* VMHeapAllocate(UInt64 size);
void VMHeapFree(void* ptr);
void* VMHeapResize(void* ptr, UInt64 newSize);
+49
View File
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include "bootinfo.h"
#include <types.h>
#define kVMPageSize 4096
#define kVMSafeSpaceStartAddress 0x100000
#define kVMBlocksPerByte 8
#define BITMAP_BYTE_INDEX(address) ((address / kVMPageSize) / kVMBlocksPerByte)
#define BITMAP_BIT_OFFSET(address) ((address / kVMPageSize) % kVMBlocksPerByte)
#define BITMAP_TEST(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] & (1 << BITMAP_BIT_OFFSET(address)))
#define BITMAP_SET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] |= (1 << BITMAP_BIT_OFFSET(address)))
#define BITMAP_UNSET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] &= ~(1 << BITMAP_BIT_OFFSET(address)))
typedef struct {
UInt32 type;
UInt32 padding;
UInt64 physicalStart;
UInt64 virtualStart;
UInt64 pageCount;
UInt64 attributes;
} __attribute__((packed)) OSMemoryDescriptor;
typedef enum {
kOSMemoryTypeReserved,
kOSMemoryTypeLoaderCode,
kOSMemoryTypeLoaderData,
kOSMemoryTypeBootServicesCode,
kOSMemoryTypeBootServicesData,
kOSMemoryTypeRuntimeServicesCode,
kOSMemoryTypeRuntimeServicesData,
kOSMemoryTypeConventional,
kOSMemoryTypeUnusable,
kOSMemoryTypeACPIReclaim,
kOSMemoryTypeACPINonVolatile,
kOSMemoryTypeMappedIO,
kOSMemoryTypeMappedIOPortSpace,
kOSMemoryTypePalCode,
kOSMemoryTypePersistent,
kOSMemoryTypeMax
} OSMemoryType;
UInt64 VMPhysicalMemoryGetTotalMemorySize();
void VMPhysicalMemoryInitialize(BIMemoryMap* mmap);
void* VMPhysicalMemoryAllocatePage();
void VMPhysicalMemoryFreePage(void* addr);
+7 -3
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include "bootinfo.h"
@@ -35,5 +35,9 @@
#define HHDM_TO_PHYS(virt) ((virt) - HHDM_OFFSET)
void vmm_init(Bootinfo* info);
u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags);
void VMVirtualMemoryInitialize(Bootinfo* info);
UInt64* VMVirtualMemoryMapPage(UInt64* PML4, UInt64 physical, UInt64 virtual, UInt64 flags);
UInt64 VMVirtualMemoryCreateAddressSpace();
UInt64 VMGetCurrentCR3();
void VMLoadCR3(UInt64 PML4Address);
void VMVirtualMemorySetupUserStack(UInt64* physicalPML4);
+45
View File
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#define kHALGDTEntries 7
typedef struct {
UInt16 limitLow;
UInt16 baseLow;
UInt8 baseMiddle;
UInt8 access;
UInt8 granularity;
UInt8 baseHigh;
} __attribute__((packed)) HALGlobalDescriptorTable;
typedef struct {
UInt16 limit;
UInt64 base;
} __attribute__((packed)) HALGlobalDescriptorTablePointer;
typedef struct {
UInt32 reserved0;
UInt64 rsp0;
UInt64 rsp1;
UInt64 rsp2;
UInt64 reserved1;
UInt64 ist1;
UInt64 ist2;
UInt64 ist3;
UInt64 ist4;
UInt64 ist5;
UInt64 ist6;
UInt64 ist7;
UInt64 reserved2;
UInt16 reserved3;
UInt16 iomapBase;
} __attribute__((packed)) HALTaskStateSegment;
extern HALTaskStateSegment gHALTaskStateSegment;
void HALGlobalDescriptorTableInitialize();
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef struct {
UInt16 offsetLow;
UInt16 selector;
UInt8 ist;
UInt8 attributes;
UInt16 offsetMid;
UInt32 offsetHigh;
UInt32 reserved;
} __attribute__((packed)) HALInterruptsDescriptorTableEntry;
typedef struct {
UInt16 limit;
UInt64 base;
} __attribute__((packed)) HALInterruptsDescriptorTablePointer;
void HALInterruptsDescriptorTableInitialize();
+44
View File
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
enum {
kIOMasterCommand = 0x20,
kIOMasterData = 0x21,
kIOSlaveCommand = 0xA0,
kIOSlaveData = 0xA1,
kIOPortWaitAddress = 0x80
};
static inline void IOPortWrite8(UInt16 port, UInt8 val) {
__asm__ volatile(
"outb %0, %1"
:
: "a"(val),
"Nd"(port) );
}
static inline unsigned char IOPortRead8(UInt16 port) {
unsigned char ret;
__asm__ volatile(
"inb %1, %0"
: "=a"(ret)
: "Nd"(port)
);
return ret;
}
// sending junk to 0x80 (unused) to skip few tacts
// not ideal i know
static inline void IOSynchronizeBus() {
IOPortWrite8(kIOPortWaitAddress, 0x0);
}
static inline void IOPortWrite8WithWait(UInt16 port, UInt8 val) {
IOPortWrite8(port, val);
IOSynchronizeBus();
}
+42
View File
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef enum {
kCPUFeatureFPU = (1ULL << 0),
kCPUFeatureTSC = (1ULL << 1),
kCPUFeatureMSR = (1ULL << 2),
kCPUFeatureAPIC = (1ULL << 3),
kCPUFeatureMTRR = (1ULL << 4),
kCPUFeaturePAE = (1ULL << 5),
kCPUFeatureSSE = (1ULL << 10),
kCPUFeatureSSE2 = (1ULL << 11),
kCPUFeatureSSE3 = (1ULL << 12),
kCPUFeatureSSSE3 = (1ULL << 13),
kCPUFeatureSSE4_1 = (1ULL << 14),
kCPUFeatureSSE4_2 = (1ULL << 15),
kCPUFeatureAVX = (1ULL << 20),
kCPUFeatureF16C = (1ULL << 21),
kCPUFeatureRDRAND = (1ULL << 22),
kCPUFeatureHypervisor = (1ULL << 30)
} OSCPUFeature;
typedef struct {
UInt64 userStackPointer;
UInt64 kernelStackPointer;
UInt64 selfAddress;
UInt64 features;
char vendorID[13];
UInt32 family;
UInt32 model;
} OSCPUData;
extern OSCPUData gOSBootCPU;
void OSCPUInitialize(UInt64 kernelStackTop);
Boolean OSCPUHasFeature(OSCPUFeature feature);
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
u16 pic_remap();
UInt16 HALLegacyInterruptControllerRemap();
-40
View File
@@ -1,40 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#define CPU_FEAT_FPU (1ULL << 0)
#define CPU_FEAT_TSC (1ULL << 1)
#define CPU_FEAT_MSR (1ULL << 2)
#define CPU_FEAT_APIC (1ULL << 3)
#define CPU_FEAT_MTRR (1ULL << 4)
#define CPU_FEAT_PAE (1ULL << 5)
#define CPU_FEAT_SSE (1ULL << 10)
#define CPU_FEAT_SSE2 (1ULL << 11)
#define CPU_FEAT_SSE3 (1ULL << 12)
#define CPU_FEAT_SSSE3 (1ULL << 13)
#define CPU_FEAT_SSE4_1 (1ULL << 14)
#define CPU_FEAT_SSE4_2 (1ULL << 15)
#define CPU_FEAT_AVX (1ULL << 20)
#define CPU_FEAT_F16C (1ULL << 21)
#define CPU_FEAT_RDRAND (1ULL << 22)
#define CPU_FEAT_HYPERVISOR (1ULL << 30)
typedef struct {
u64 user_rsp;
u64 kernel_rsp;
u64 self;
u64 features;
char vendor[13];
u32 family;
u32 model;
} cpu_info;
extern cpu_info g_cpu;
void cpuinfo_init(u64 kernel_stack_top);
bool cpu_has(u64 feature);
-42
View File
@@ -1,42 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
typedef struct {
u16 limit_low;
u16 base_low;
u8 base_middle;
u8 access;
u8 granularity;
u8 base_high;
} __attribute__((packed)) GDTDescriptor;
typedef struct {
u16 limit;
u64 base;
} __attribute__((packed)) GDTPtr;
typedef struct {
u32 reserved0;
u64 rsp0;
u64 rsp1;
u64 rsp2;
u64 reserved1;
u64 ist1;
u64 ist2;
u64 ist3;
u64 ist4;
u64 ist5;
u64 ist6;
u64 ist7;
u64 reserved2;
u16 reserved3;
u16 iomap_base;
} __attribute__((packed)) TSS;
extern TSS tss;
void gdt_init();
-22
View File
@@ -1,22 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
typedef struct {
u16 offset_low;
u16 selector;
u8 ist;
u8 attributes;
u16 offset_mid;
u32 offset_high;
u32 reserved;
} __attribute__((packed)) IDTEntry;
typedef struct {
u16 limit;
u64 base;
} __attribute__((packed)) IDTPtr;
void idt_init();
-39
View File
@@ -1,39 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#define MASTER_COMMAND 0x20
#define MASTER_DATA 0x21
#define SLAVE_COMMAND 0xA0
#define SLAVE_DATA 0xA1
static inline void outb(unsigned short port, unsigned char val) {
__asm__ volatile(
"outb %0, %1"
:
: "a"(val),
"Nd"(port) );
}
static inline unsigned char inb(unsigned short 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 io_wait() {
outb(0x80, 0x0);
}
static inline void outb_wait(unsigned short port, unsigned char val) {
outb(port, val);
io_wait();
}
+17 -9
View File
@@ -3,18 +3,26 @@
#pragma once
#define MSR_EFER 0xC0000080
#define MSR_STAR 0xC0000081
#define MSR_LSTAR 0xC0000082
#define MSR_FMASK 0xC0000084
#define MSR_KERNEL_GS_BASE 0xC0000102
enum {
kHALModelSpecificRegisterExtendedFeatureEnable = 0xC0000080, // EFER
kHALModelSpecificRegisterSystemCallTarget = 0xC0000081, // STAR
kHALModelSpecificRegisterLongSystemCallTarget = 0xC0000082, // LSTAR
kHALModelSpecificRegisterSystemCallFlagMask = 0xC0000084, // FMASK
kHALModelSpecificRegisterGSBase = 0xC0000101, // GS_BASE
kHALModelSpecificRegisterKernelGSBase = 0xC0000102 // KERNEL_GS_BASE
};
#define EFER_SCE 0x01 // System Call Enable
enum {
kHALEFERSystemCallExtensionsEnable = 0x01 // SCE
};
typedef enum {
SYS_EXIT,
SYS_EXEC,
SYS_SPAWN,
SYS_MEM,
SYS_WRITE,
} syscalls;
SYS_READ,
SYS_WAIT,
} Services;
void syscall_init();
void OSServicesInitialize();
-10
View File
@@ -1,10 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
__attribute__((noreturn)) void panic_exception(Registers *regs);
__attribute__((noreturn)) void panic(const char* msg);
extern const char* exception_messages[];
-17
View File
@@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
typedef struct task {
u64 rsp;
struct task* next;
u32 id;
u32 sleep_ticks;
u64 kernel_stack_top;
} task;
void sched_init();
task* sched_spawn(void(*entry)());
u64 sched_next(u64 curr_rsp);
void yield(u64 ticks);
-8
View File
@@ -1,8 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <drivers/shitgui.h>
void show_splash(SG_Context *sg_ctx);
-10
View File
@@ -1,10 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
i32 strcmp(const char* s1, const char* s2);
i32 strncmp(const char* s1, const char* s2, u64 n);
char* strcpy(char* dest, const char* src);
char* strncpy(char* dest, const char* src, u64 n);
-21
View File
@@ -1,21 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <drivers/shitgui.h>
void console_init(SG_Context *ctx);
u64 console_get_colors();
void console_clear(u32 color);
SG_Context* console_get_context();
SG_Point console_get_dimensions();
void console_set_color(u32 color);
void console_set_default_color(u32 color);
void console_set_cursor_pos(SG_Point *p);
char console_getc();
void kprint(const char *str);
void kprintf(const char *fmt, ...);
void kgets(char* buff, u32 lim);
void cursor_blink();
void cursor_blinker_sched_task();
void console_toggle_cursor_blink();
-4
View File
@@ -1,4 +0,0 @@
#pragma once
#include <types.h>
extern u8 font8x16[128][16];
-16
View File
@@ -1,16 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
#define KB_BUFF_SIZE 256
typedef struct {
char buffer[KB_BUFF_SIZE];
u16 head;
u16 tail;
} kb_buffer;
extern kb_buffer kb_buf;
void kb_handler();
-8
View File
@@ -1,8 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
int serial_init();
void serial_writec(char chr);
void serial_write(const char *str);
-33
View File
@@ -1,33 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
typedef struct {
volatile u32 *fb;
u32 width;
u32 height;
u32 pitch;
} SG_Context;
typedef struct {
u32 x;
u32 y;
} SG_Point;
typedef struct {
u32 *buffer;
u32 height;
u32 width;
} SG_Image;
typedef struct {
u32 w;
u32 h;
const unsigned char* base;
} SG_Font;
void sg_init(SG_Context *ctx);
u32 sg_get_pixel(SG_Context *ctx, SG_Point *p);
void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img);
void sg_draw_rect(SG_Context *ctx, SG_Point *p, u32 w, u32 h, u32 color);
void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font);
-10
View File
@@ -1,10 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
void timer_init(u32 freq);
u64 timer_handler(Registers *regs);
void sleep(u64 ms);
u64 get_uptime();
-8
View File
@@ -1,8 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <fs/vfs.h>
u64 cpio_read(fs_node* node, u64 offset, u64 size, u8* buff);
fs_node* cpio_mount(void* base, u64 size);
-38
View File
@@ -1,38 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#define FS_FILE 0x01
#define FS_DIR 0x02
struct fs_node;
typedef struct fs_node fs_node;
typedef struct {
u64 (*read)(struct fs_node* node, u64 offset, u64 size, u8* buff);
u64 (*write)(struct fs_node* node, u64 offset, u64 size, u8* buff);
void (*open)(struct fs_node* node);
void (*close)(struct fs_node* node);
struct fs_node* (*finddir)(struct fs_node* node, char* name);
} fs_ops;
struct fs_node {
char name[256];
u32 mask;
u32 uid;
u32 gid;
u32 flags;
u32 inode;
u64 len;
fs_ops* ops;
void* impl_data;
struct fs_node* ptr;
struct fs_node* next;
};
void vfs_init(fs_node* root_node);
u64 vfs_read(fs_node* node, u64 offset, u64 size, u8* buff);
fs_node* vfs_open(const char* path);
void vfs_close(fs_node* node);
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
@@ -13,7 +13,7 @@ static inline int abs(int n) {
return (n < 0) ? -n : n;
}
static inline i64 i64abs(i64 n) {
static inline Int64 i64abs(Int64 n) {
return (n < 0) ? -n : n;
}
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
u64 debug();
void RandInitialize();
UInt64 Rand();
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
void SplashShow(IOGraphicsContext* IOGraphicsContextPointer);
+13
View File
@@ -0,0 +1,13 @@
// 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);
-24
View File
@@ -1,24 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
#define KERNEL_HEAP_START 0xFFFFFFFFC0000000
#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START)
#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START)
#define HEADER_MAGIC 0x1CE
typedef struct block_header {
u64 magic;
struct block_header* next;
struct block_header* prev;
u64 size;
bool is_free;
} block_header;
void heap_init();
void* malloc(u64 size);
void free(void* ptr);
void* realloc(void* ptr, u64 new_size);
-8
View File
@@ -1,8 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
void* memset(void* ptr, int value, usize num);
void* memcpy(void* dest, const void* src, u64 n);
-22
View File
@@ -1,22 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include "bootinfo.h"
#include <types.h>
#define PAGE_SIZE 4096
#define BLOCKS_PER_BYTE 8
#define SAFE_SPACE_START_ADDR 0x100000
#define BITMAP_BYTE_INDEX(addr) ((addr / PAGE_SIZE) / BLOCKS_PER_BYTE)
#define BITMAP_BIT_OFFSET(addr) ((addr / PAGE_SIZE) % BLOCKS_PER_BYTE)
#define BITMAP_TEST(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] & (1 << BITMAP_BIT_OFFSET(addr)))
#define BITMAP_SET(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] |= (1 << BITMAP_BIT_OFFSET(addr)))
#define BITMAP_UNSET(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] &= ~(1 << BITMAP_BIT_OFFSET(addr)))
u64 pmm_get_total_mem();
void pmm_init(BI_MemoryMap* mmap);
void* pmm_alloc_page();
void pmm_free_page(void* addr);
-14
View File
@@ -1,14 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
void cmd_kfetch();
void cmd_meow();
void cmd_help();
void cmd_regs();
void print_regs();
void cmd_sleep();
void cmd_debug();
void cmd_rand();
void cmd_ver();
-7
View File
@@ -1,7 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <drivers/shitgui.h>
void ksh();
+16 -47
View File
@@ -1,57 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef unsigned char UInt8;
typedef unsigned short UInt16;
typedef unsigned int UInt32;
typedef unsigned long long UInt64;
typedef signed char i8;
typedef signed short i16;
typedef signed int i32;
typedef signed long long i64;
typedef signed char Int8;
typedef signed short Int16;
typedef signed int Int32;
typedef signed long long Int64;
typedef u64 usize;
typedef u64 uintptr_t;
typedef UInt64 Size;
typedef UInt64 uintptr_t;
typedef struct {
u64 rax, rbx, rcx, rdx, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; // Pushed by us
u64 int_no, err_code; // Pushed by macro
u64 rip, cs, rflags, rsp, ss; // Pushed by CPU
} Registers;
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;
typedef struct {
u32 type;
u32 pad;
u64 physical_start;
u64 virtual_start;
u64 number_of_pages;
u64 attribute;
} __attribute__((packed)) efi_memory_descriptor_k;
typedef enum {
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiPersistentMemory,
EfiMaxMemoryType
} EFI_MEMORY_TYPE;
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#endif
#define Boolean _Bool
+1 -1
View File
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
Copyright (c) 2025 0xKarinyash */
Copyright (c) 2026 0xKarinyash */
ENTRY(_start)
+122
View File
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <types.h>
#include <FS/CPIO.h>
#include <FS/VFS.h>
#include <lib/String.h>
#include <OS/OSPanic.h>
#include <VM/Heap.h>
#include <IO/IOConsole.h>
#define FSCPIO_ALIGN4(x) (((x) + 3) & ~3)
typedef struct FSCPIOHeader {
char magic[6];
char inode[8];
char mode[8];
char userIdentifier[8];
char groupIdentifier[8];
char linkCount[8];
char modificationTime[8];
char fileLength[8];
char deviceMajor[8];
char deviceMinor[8];
char remoteDeviceMajor[8];
char remoteDeviceMinor[8];
char nameLength[8];
char checkSum[8];
} FSCPIOHeader;
static FSVNodeOperations gFSCPIOOperations = {
.read = FSCPIORead,
.write = nullptr,
.open = nullptr,
.close = nullptr,
};
static UInt64 sFSCPIOHexadecimalToUInt64(const char* string, Int32 length) {
UInt64 result = 0;
for (Int32 i = 0; i < length; i++) {
char character = string[i];
result <<= 4;
if (character >= '0' && character <= '9') result += (character - '0');
else if (character >= 'A' && character <= 'F') result += (character - 'A' + 10);
else if (character >= 'a' && character <= 'f') result += (character - 'a' + 10);
}
return result;
}
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
if (offset > node->dataLength) return 0;
if ((offset + size) > node->dataLength) size = node->dataLength - offset;
MemoryCopy(buffer, (char*)node->implementationData + offset, size);
return size;
}
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize) {
UInt8* currentPointer = (UInt8*)baseAddress;
UInt8* endPointer = currentPointer + totalSize;
FSVNode* rootNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
if (!rootNode) OSPanic("CPIO: Failed to allocate memory for root node");
MemorySet(rootNode, 0, sizeof(FSVNode));
StringCopy(rootNode->name, "/");
rootNode->flags = kFSVNodeFlagDirectory;
rootNode->operations = &gFSCPIOOperations;
FSVNode* tailNode = nullptr;
while (currentPointer < endPointer) {
FSCPIOHeader* header = (FSCPIOHeader*)currentPointer;
if (StringCompareWithLimit(header->magic, "070701", 6) != 0) {
OSPanic("CPIO: Invalid magic detected in StartupVolume");
}
UInt64 nameSize = sFSCPIOHexadecimalToUInt64(header->nameLength, 8);
UInt64 fileSize = sFSCPIOHexadecimalToUInt64(header->fileLength, 8);
char* fileName = (char*)(currentPointer + sizeof(FSCPIOHeader));
if (StringCompare(fileName, "TRAILER!!!") == 0) break;
UInt64 headerAndNameLength = sizeof(FSCPIOHeader) + nameSize;
UInt64 offsetToData = FSCPIO_ALIGN4(headerAndNameLength);
void* fileContent = (void*)(currentPointer + offsetToData);
FSVNode* newNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
if (!newNode) OSPanic("CPIO: Failed to allocate memory for new node");
MemorySet(newNode, 0, sizeof(FSVNode));
StringCopyWithLimit(newNode->name, fileName, sizeof(newNode->name) - 1);
newNode->dataLength = fileSize;
newNode->inodeIdentifier = sFSCPIOHexadecimalToUInt64(header->inode, 8);
newNode->operations = &gFSCPIOOperations;
newNode->implementationData = fileContent;
UInt64 mode = sFSCPIOHexadecimalToUInt64(header->mode, 8);
if ((mode & 0xF000) == 0x4000) {
newNode->flags = kFSVNodeFlagDirectory;
} else {
newNode->flags = kFSVNodeFlagFile;
}
if (rootNode->childNode == nullptr) {
rootNode->childNode = newNode;
} else if (tailNode) {
tailNode->nextNode = newNode;
}
tailNode = newNode;
IOConsoleLog("^bCPIO^!: Found object '^y%s^!' (size: ^y%d^!) at ^y0x%x^!\n", fileName, fileSize, fileContent);
UInt64 dataLengthAligned = FSCPIO_ALIGN4(fileSize);
currentPointer += offsetToData + dataLengthAligned;
}
return rootNode;
}
+53
View File
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <FS/VFS.h>
#include <lib/String.h>
FSVNode* gFSVirtualFileSystemRoot = nullptr;
void FSVirtualFileSystemInitialize(FSVNode* rootNode) {
gFSVirtualFileSystemRoot = rootNode;
}
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
if (!node || !node->operations || !node->operations->read) {
return 0;
}
return node->operations->read(node, offset, size, buffer);
}
FSVNode* FSVirtualFileSystemOpenPath(const char* path) {
if (!gFSVirtualFileSystemRoot) {
return nullptr;
}
if (StringCompare(path, "/") == 0) {
return gFSVirtualFileSystemRoot;
}
const char* searchName = path;
if (path[0] == '/') {
searchName++;
}
FSVNode* nodeIterator = gFSVirtualFileSystemRoot->childNode;
while (nodeIterator != nullptr) {
if (StringCompare(nodeIterator->name, searchName) == 0) {
if (nodeIterator->operations && nodeIterator->operations->open) {
nodeIterator->operations->open(nodeIterator);
}
return nodeIterator;
}
nodeIterator = nodeIterator->nextNode;
}
return nullptr;
}
void FSVNodeClose(FSVNode* node) {
if (node && node->operations && node->operations->close) {
node->operations->close(node);
}
}
+267
View File
@@ -0,0 +1,267 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOConsole.h>
#include <IO/IOSerial.h>
#include <IO/IOGraphics.h>
#include <IO/IOKeyboard.h>
#include <lib/Math.h>
#include <OS/OSScheduler.h>
#include <types.h>
#include <stdarg.h>
#include <Data/VGAFont.h>
static IOGraphicsContext* sIOGraphicsContextPointer = nullptr;
static IOGraphicsPoint sIOConsoleCursorPosition = {0};
static IOGraphicsFont sIOConsoleFont = {0};
static IOGraphicsColor sIOConsoleForegroundColor = kIOConsoleColorWhite;
static IOGraphicsColor sIOConsoleDefaultForegroundColor = kIOConsoleColorWhite;
static IOGraphicsColor sIOConsoleBackgroundColor = kIOConsoleColorBlack;
void IOConsoleInit(IOGraphicsContext *context) {
sIOGraphicsContextPointer = context;
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y = 0;
sIOConsoleFont.size.height = 16;
sIOConsoleFont.size.width = 8;
sIOConsoleFont.baseAddress = (const unsigned char*)VGAFont;
}
UInt64 IOConsoleGetColors() {
return ((UInt64) sIOConsoleForegroundColor << 32) | sIOConsoleBackgroundColor;
}
void IOConsoleClear(IOGraphicsColor color) {
if (!sIOGraphicsContextPointer) return;
IOGraphicsPoint point = {0, 0};
IOGraphicsDrawRectangle(
sIOGraphicsContextPointer,
&point,
&sIOGraphicsContextPointer->dimensions,
color
);
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y = 0;
sIOConsoleBackgroundColor = color;
}
IOGraphicsContext* IOConsoleGetGraphicsContext() {
return sIOGraphicsContextPointer;
}
IOGraphicsSize IOConsoleGetDimensions() {
return sIOGraphicsContextPointer->dimensions;
}
void IOConsoleSetCursorPosition(IOGraphicsPoint* point) {
if (!point) return;
sIOConsoleCursorPosition.x = point->x;
sIOConsoleCursorPosition.y = point->y;
}
void IOConsolePutcharacter(char character) {
IOSerialWriteChar(character);
if (!sIOGraphicsContextPointer) return;
if (character == '\n') {
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
} else if (character == '\t') {
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width * 4;
} else if (character == '\b') {
sIOConsoleCursorPosition.x -= sIOConsoleFont.size.width;
IOGraphicsDrawRectangle(
sIOGraphicsContextPointer,
&sIOConsoleCursorPosition,
&sIOConsoleFont.size,
sIOConsoleBackgroundColor
);
} else {
IOGraphicsDrawCharacter(
sIOGraphicsContextPointer,
&sIOConsoleCursorPosition,
character,
sIOConsoleForegroundColor,
&sIOConsoleFont
);
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width;
}
if (sIOConsoleCursorPosition.x >= sIOGraphicsContextPointer->dimensions.width) {
sIOConsoleCursorPosition.x = 0;
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
}
if (sIOConsoleCursorPosition.y >= sIOGraphicsContextPointer->dimensions.height) {
IOConsoleClear(sIOConsoleBackgroundColor); // TODO: do scrolling
}
}
void IOConsolePrint(const char *string) {
for (Int32 i = 0; string[i] != '\0'; i++) IOConsolePutcharacter(string[i]);
}
static void sIOConsolePrintDecimal(const Int64 number) {
if (number < 0) IOConsolePutcharacter('-');
UInt64 unsignedNumber = abs(number);
char buffer[32];
Int32 i = 0;
do {
buffer[i] = (unsignedNumber % 10) + '0';
unsignedNumber /= 10;
i++;
} while (unsignedNumber > 0);
while (--i >= 0) {
IOConsolePutcharacter(buffer[i]);
}
}
static void sIOConsolePrintHexadecimal(UInt64 unsignedNumber, UInt8 padding) {
IOConsolePutcharacter('0');
IOConsolePutcharacter('x');
if (unsignedNumber == 0) {
IOConsolePutcharacter('0');
for (Int32 i = 1; i < padding; i++) IOConsolePutcharacter('0');
return;
}
char buffer[16] = {0};
Int32 i = 0;
do {
Int32 digit = unsignedNumber % 16;
if (digit < 10) buffer[i++] = digit + '0';
else buffer[i++] = digit - 10 + 'A';
unsignedNumber /= 16;
} while (unsignedNumber > 0);
while(i < padding) {
IOConsolePutcharacter('0');
padding--;
}
while (--i >= 0) {
IOConsolePutcharacter(buffer[i]);
}
}
void IOConsoleLog(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (Int32 i = 0; fmt[i] != '\0'; i++) {
if (fmt[i] == '%') {
i++;
switch (fmt[i]) {
case 's': {
const char *string = va_arg(args, const char*);
if (!string) string = "undefined";
IOConsolePrint(string);
break;
}
case 'c': {
char character = (char)va_arg(args, int);
IOConsolePutcharacter(character);
break;
}
case 'd': {
Int32 number = va_arg(args, Int32);
sIOConsolePrintDecimal(number);
break;
}
case 'x': {
UInt64 number = va_arg(args, UInt64);
sIOConsolePrintHexadecimal(number, 0);
break;
}
case 'X' : {
UInt64 number = va_arg(args, UInt64);
sIOConsolePrintHexadecimal(number, 16);
break;
}
default: {
IOConsolePutcharacter(fmt[i]);
break;
}
}
} else if (fmt[i] == '^') {
i++;
switch (fmt[i]) {
case 'r': IOConsoleSetForegroundColor(kIOConsoleColorRed); break;
case 'R': IOConsoleSetForegroundColor(kIOConsoleColorVeryRed); break;
case 'g': IOConsoleSetForegroundColor(kIOConsoleColorGreen); break;
case 'G': IOConsoleSetForegroundColor(kIOConsoleColorVeryGreen); break;
case 't': IOConsoleSetForegroundColor(kIOConsoleColorTurqoise); break;
case 'b': IOConsoleSetForegroundColor(kIOConsoleColorBlue); break;
case 'B': IOConsoleSetForegroundColor(kIOConsoleColorVeryBlue); break;
case 'l': IOConsoleSetForegroundColor(kIOConsoleColorLightBlue); break;
case 'y': IOConsoleSetForegroundColor(kIOConsoleColorYellow); break;
case 'c': IOConsoleSetForegroundColor(kIOConsoleColorCyan); break;
case 'm': IOConsoleSetForegroundColor(kIOConsoleColorMagneta); break;
case 'p': IOConsoleSetForegroundColor(kIOConsoleColorPink); break;
case '0': IOConsoleSetForegroundColor(kIOConsoleColorBlack); break;
case 'w': IOConsoleSetForegroundColor(kIOConsoleColorWhite); break;
case '!': IOConsoleSetForegroundColor(sIOConsoleDefaultForegroundColor); break;
case '~': IOConsoleSetForegroundColor(~sIOConsoleBackgroundColor); break;
case '^': IOConsolePutcharacter('^'); break;
default: {
IOConsolePutcharacter('^');
IOConsolePutcharacter(fmt[i]);
break;
}
}
} else {
IOConsolePutcharacter(fmt[i]);
}
}
va_end(args);
}
void IOConsoleSetForegroundColor(UInt32 color) {
sIOConsoleForegroundColor = color;
}
void IOConsoleSetDefaultForegroundColor(UInt32 color) {
sIOConsoleDefaultForegroundColor = color;
}
void IOConsoleReadLine(char* buffer, UInt32 limit) {
UInt32 i = 0;
while (true) {
char character = IOKeyboardGetCharacter();
switch (character) {
case '\n': {
buffer[i] = '\0';
IOConsoleLog("\n");
return;
}
case '\b': {
if (i > 0) {
i--;
IOConsoleLog("\b \b");
}
break;
}
default: {
if (i < limit - 1) {
buffer[i] = character;
IOConsoleLog("%c", character);
i++;
}
}
}
}
}
+82
View File
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// RIP shitgui -- you started it all
#include <OS/OSScheduler.h>
#include <OS/OSPanic.h>
#include <IO/IOGraphics.h>
#include <VM/Heap.h>
#include <lib/String.h>
enum {
kIOGraphicsTransparencyKey = 0xFF00FF
};
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point) {
if (!context->framebuffer || !point || point->x >= context->dimensions.width || point->y >= context->dimensions.height) return 0;
return context->framebuffer[point->y * context->pixelsPerScanLine + point->x];
}
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image) {
if (!context->framebuffer || !image) return;
UInt32 startX = point->x;
UInt32 startY = point->y;
UInt32 drawW = image->size.width;
UInt32 drawH = image->size.height;
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
for (UInt32 y = 0; y < drawH; y++) {
volatile UInt32 *destinationPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
UInt32 *sourcePointer = &image->buffer[y * image->size.width];
for (UInt32 x = 0; x < drawW; x++) {
UInt32 color = sourcePointer[x];
if (color != kIOGraphicsTransparencyKey) destinationPointer[x] = color;
}
}
}
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsSize* size, IOGraphicsColor color) {
if (!context->framebuffer) return;
UInt32 startX = point->x;
UInt32 startY = point->y;
UInt32 drawW = size->width;
UInt32 drawH = size->height;
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
for (UInt32 y = 0; y < drawH; y++) {
volatile UInt32* rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
for (UInt32 x = 0; x < drawW; x++) rowPointer[x] = color;
}
}
void IOGraphicsDrawCharacter(IOGraphicsContext* context, IOGraphicsPoint* point, char c, IOGraphicsColor color, IOGraphicsFont* font) {
if (!context->framebuffer) return;
UInt32 startX = point->x;
UInt32 startY = point->y;
UInt32 drawW = font->size.width;
UInt32 drawH = font->size.height;
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
for (UInt32 y = 0; y < drawH; y++) {
UInt8 bitmapRow = font->baseAddress[(unsigned char)c * font->size.height + y];
volatile UInt32 *rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
for (UInt32 x = 0; x < drawW; x++) {
if (bitmapRow & (1 << (7 - x))) {
rowPointer[x] = color;
}
}
}
}
@@ -1,13 +1,15 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <drivers/keyboard.h>
#include <drivers/console.h>
#include <IO/IOKeyboard.h>
#include <IO/IOConsole.h>
#include <OS/OSSpinlock.h>
#include <OS/OSScheduler.h>
#include <io.h>
#include <IO.h>
#include <types.h>
unsigned char keyboard_map[128] = {
static unsigned char sIOKeyboardMap[128] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 0x00 - 0x09 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
@@ -46,7 +48,7 @@ unsigned char keyboard_map[128] = {
0, /* All other keys are undefined */
};
unsigned char keyboard_map_shifted[128] = {
static unsigned char sIOKeyboardMapShifted[128] = {
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 0x00 - 0x09 */
'(', ')', '_', '+', '\b', /* Backspace */
'\t', /* Tab */
@@ -85,31 +87,55 @@ unsigned char keyboard_map_shifted[128] = {
0, /* All other keys */
};
bool shift_pressed = false;
kb_buffer kb_buf = {0};
static Boolean sIOKeyboardIsShiftPressed = false;
void kb_handler() {
u16 next_head = (kb_buf.head + 1) % KB_BUFF_SIZE;
IOKeyboardController gIOKeyboardController = {0};
u8 scancode = inb(0x60);
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* arr = shift_pressed ? keyboard_map_shifted : keyboard_map;
char ascii = arr[scancode];
if (ascii && next_head != kb_buf.tail) {
kb_buf.buffer[kb_buf.head] = ascii;
kb_buf.head = next_head;
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: shift_pressed = true; break;
case 0x2A: sIOKeyboardIsShiftPressed = true; break;
default: break;
}
}
} else {
switch (scancode) {
case 0xAA: shift_pressed = false; break;
case 0xAA: sIOKeyboardIsShiftPressed = false; break;
default: break;
}
}
outb(MASTER_COMMAND, 0x20);
OSSpinlockUnlock(&gIOKeyboardController.lock);
}
char IOKeyboardGetCharacter() {
char ascii = 0;
OSSpinlockState state;
while (true) {
OSSpinlockLockIRQ(&gIOKeyboardController.lock, &state);
if (gIOKeyboardController.head != gIOKeyboardController.tail) {
ascii = gIOKeyboardController.buffer[gIOKeyboardController.tail];
gIOKeyboardController.tail = (gIOKeyboardController.tail + 1) % kIOKeyboardBufferSize;
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
return ascii;
}
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
__asm__ volatile ("sti");
OSSchedulerYield(1);
}
}
+33
View File
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOSerial.h>
#include <IO.h>
enum {
kIOCom1Port = 0x3F8,
};
int IOSerialInit() {
IOPortWrite8(kIOCom1Port + 1, 0x00); // interrupt enable register (+1) / disable interruptions
IOPortWrite8(kIOCom1Port + 3, 0x80); // line control register (+3)
IOPortWrite8(kIOCom1Port + 0, 0x03); // speed : low byte
IOPortWrite8(kIOCom1Port + 1, 0x00); // speed : high byte
IOPortWrite8(kIOCom1Port + 3, 0x03); // line control register (+3) / reset DLAB / no parity / 1 stop bit / (8N1)
IOPortWrite8(kIOCom1Port + 2, 0xC7); // FIFO Control register (+2) / 1100 0111 / last ones are enable FIFO buff / first ones to clean noise
IOPortWrite8(kIOCom1Port + 4, 0x0B); // ready :3
return 0;
}
static int IOCheckIsTransmitEmpty() {
return IOPortRead8(kIOCom1Port + 5) & 0x20; // checking 5th bit LSR
}
void IOSerialWriteChar(char character) {
while (IOCheckIsTransmitEmpty() == 0); // waiting for buffer to flush (spinlock)
IOPortWrite8(kIOCom1Port, character);
}
void IOSerialWrite(const char* string) {
for (int i = 0; string[i] != '\0'; i++) IOSerialWriteChar(string[i]);
}
+36
View File
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IO/IOTimer.h>
#include <IO.h>
#include <types.h>
#include <OS/OSScheduler.h>
enum {
kIOTimerPitBaseClock = 1193180,
kIOTimerPitCommand = 0x43,
kIOTimerPitData = 0x40,
};
static volatile UInt64 sIOTimerTicks = 0;
void IOTimerInitialize(UInt32 frequency) {
UInt32 divisor = kIOTimerPitBaseClock / frequency;
IOPortWrite8(kIOTimerPitCommand, 0x36); // 0x36 = 00110110 = channel 0, LOHI byte access, Mode 3, binary
IOPortWrite8(kIOTimerPitData, divisor & 0xFF);
IOPortWrite8(kIOTimerPitData, (divisor >> 8) & 0xFF);
UInt8 mask = IOPortRead8(0x21);
mask &= ~(1 << 0);
IOPortWrite8(0x21, mask);
}
UInt64 IOTimerInterruptsHandler(CPURegisters *registers) {
sIOTimerTicks++;
return OSSchedulerNext((UInt64)registers);
}
UInt64 IOTimerGetTicks() {
return sIOTimerTicks;
}
+106
View File
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <types.h>
#include <OSCPU.h>
#include <IO/IOConsole.h>
#include <IO/IOTimer.h>
#include <lib/String.h>
#include <lib/Rand.h>
#include <OS/OSScheduler.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
#include <KSH/KSHDebug.h>
#include <Data/cats.h>
const char* asciiLogo[] = {
" /\\___/\\ ",
" | > < | ",
" | w | ",
" |=======|__ ",
" | | | ",
" |TERMOS | | ",
" | |__| ",
" |_______| "
};
void KSHCommandKernelFetch() {
UInt64 uptimeSeconds = IOTimerGetTicks() / 1000;
IOConsoleLog("\n\n");
IOConsoleLog("^p %s ^!\t\t^g kernel^!@^gtermos\n^0", asciiLogo[0]);
IOConsoleLog("^p %s ^!\t\t^!-------------\n^!", asciiLogo[1]);
IOConsoleLog("^p %s ^!\t\t^gOS^!: termOS %s\n^!", asciiLogo[2], TERMOS_VERSION);
IOConsoleLog("^p %s ^!\t\t^gKernel^!: Dewar (x86_64), build: %s %s\n^!", asciiLogo[3], __DATE__, __TIME__);
IOConsoleLog("^p %s ^!\t\t^gUptime^!: %d seconds\n^!", asciiLogo[4], uptimeSeconds);
IOConsoleLog("^p %s ^!\t\t^gShell^!: ksh\n^!", asciiLogo[5]);
IOConsoleLog("^p %s ^!\t\t^gDE^!: shitgui\n^!", asciiLogo[6]);
IOConsoleLog("^p %s ^!\t\t^gCPU^!: %s (^yFamily^!: %d; ^yModel^!: %d)\n^!", asciiLogo[7], gOSBootCPU.vendorID, gOSBootCPU.family, gOSBootCPU.model);
IOConsoleLog("\n\n");
}
void KSHCommandMeow() {
UInt64 catsCount = sizeof(cats) / sizeof(cats[0]);
UInt8 randomNumber = Rand() % catsCount;
IOConsoleLog("Nyaaa!!\n\n%s\n\n", cats[randomNumber]);
}
void KSHCommandHelp() {
IOConsoleLog("Welcome to ^ptermOS^!'s ^gk^!ernel ^gsh^!ell!\n");
IOConsoleLog("It loads when userspace is failed to load and acts as a basic rescue environment\n");
IOConsoleLog("Available commands:\n");
IOConsoleLog("\t^rDebug^!:\n");
IOConsoleLog("\t\t^ysleep^! \t\tSleep for 3seconds\n");
IOConsoleLog("\t\t^ydbg^! \t\tTest new stuff\n");
IOConsoleLog("\t\t^yregs^! \t\tPrint current regs\n");
IOConsoleLog("\t\t^ypanic^! \t\tPanics (lol)\n");
IOConsoleLog("\t\t^yud2^! \t\tPanics with #UD\n");
IOConsoleLog("\t\t^ypf^! \t\tPanics with #PF\n");
IOConsoleLog("\t^pFun^!:\n");
IOConsoleLog("\t\t^ysplash^! \t\tShows splash (works kinda unstable)\n");
IOConsoleLog("\t\t^ymeow^! \t\tcats!!!\n");
IOConsoleLog("\t\t^ykfetch^! \t\tr/unixporn compatible\n");
IOConsoleLog("\t^bMisc^!:\n");
IOConsoleLog("\t\t^yclear^! \t\tClear console\n");
IOConsoleLog("\t\t^yhelp^! \t\tShow this menu\n");
IOConsoleLog("\t\t^yrand^! \t\tGet a random number\n");
IOConsoleLog("\t\t^yver^! \t\tDisplays termOS's version\n");
}
void KSHCommandRegisters() {
__asm__ volatile ("int3");
}
void KSHCommandSleep() {
OSSchedulerYield(3000);
}
void KSHCommandRand() {
IOConsoleLog("Your rand number (0..100) is ... ^y%d^!!\n", Rand() % 100);
}
void KSHCommandDebug() {
UInt64 status = KSHDebug();
IOConsoleLog("\nDebug ended with code %d\n", status);
return;
}
void KSHCommandVer() {
IOConsoleLog("termOS version %s\n", TERMOS_VERSION);
IOConsoleLog("Dewar Kernel (x86_64), build: %s %s\n", __DATE__, __TIME__);
IOConsoleLog("License: GPL-3.0-or-later\n");
}
void cmd_userspace() {
IOConsoleLog("Command disabled due to be really broken\n");
}
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <shell/dbgcmd.h>
#include <drivers/console.h>
#include <KSH/KSHDebug.h>
#include <IO/IOConsole.h>
u64 debug() {
UInt64 KSHDebug() {
return 0;
}
+109
View File
@@ -0,0 +1,109 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <KSH/KSHEntry.h>
#include <KSH/KSHBuiltins.h>
#include <IO/IOConsole.h>
#include <IO/IOGraphics.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <lib/String.h>
#include <lib/Rand.h>
#include <lib/Splash.h>
typedef enum {
TOKEN_EMPTY,
TOKEN_NULL,
TOKEN_ILLEGAL,
TOKEN_HELP,
TOKEN_SPLASH,
TOKEN_KFETCH,
TOKEN_MEOW,
TOKEN_SLEEP,
TOKEN_REGS,
TOKEN_DEBUG,
TOKEN_RECTEST,
TOKEN_PANIC,
TOKEN_PANIC_UD2,
TOKEN_PANIC_PF,
TOKEN_CLEAR,
TOKEN_RAND,
TOKEN_VER,
TOKEN_BACK,
TOKEN_FORWARD,
} KSHToken;
typedef struct {
char* str;
KSHToken token;
} KSHCommandMap;
static const KSHCommandMap CommandMap[] = {
{"", TOKEN_EMPTY},
// debug
{"sleep", TOKEN_SLEEP},
{"dbg", TOKEN_DEBUG},
{"regs", TOKEN_REGS},
{"panic", TOKEN_PANIC},
{"ud2", TOKEN_PANIC_UD2},
{"pf", TOKEN_PANIC_PF},
// fun
{"meow", TOKEN_MEOW},
{"splash", TOKEN_SPLASH},
{"kfetch", TOKEN_KFETCH},
// misc
{"help", TOKEN_HELP},
{"clear", TOKEN_CLEAR},
{"rand", TOKEN_RAND},
{"ver", TOKEN_VER},
{nullptr, TOKEN_NULL}
};
KSHToken KSHCharacter2Token(char* token) {
for (Int32 i = 0; CommandMap[i].str != nullptr; i++) {
if (StringCompare(token, CommandMap[i].str) == 0) return CommandMap[i].token;
}
return TOKEN_ILLEGAL;
}
void KSHEntry() {
while (true) {
IOConsoleLog("ksh_> ");
char cmdbuff[256];
IOConsoleReadLine(cmdbuff, 256);
switch(KSHCharacter2Token(cmdbuff)) {
case TOKEN_EMPTY: continue;
case TOKEN_CLEAR: IOConsoleClear((UInt32) IOConsoleGetColors() & 0xFFFFFFFF); break;
case TOKEN_RAND: KSHCommandRand(); break;
case TOKEN_VER: KSHCommandVer(); break;
case TOKEN_SLEEP: KSHCommandSleep(); break;
case TOKEN_DEBUG: KSHCommandDebug(); break;
case TOKEN_REGS: KSHCommandRegisters(); break;
case TOKEN_PANIC: OSPanic("Manually initiated panic");
case TOKEN_PANIC_UD2: __asm__ volatile ("ud2");
case TOKEN_PANIC_PF: UInt64* bad_ptr = (UInt64*)0xDEADBEEF; *bad_ptr = 666;
case TOKEN_SPLASH: SplashShow(IOConsoleGetGraphicsContext()); break;
case TOKEN_KFETCH: KSHCommandKernelFetch(); break;
case TOKEN_MEOW: KSHCommandMeow(); break;
case TOKEN_HELP: KSHCommandHelp(); break;
default: IOConsoleLog("Unknown command!!\n"); break;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Exec/HOTLoader.h>
#include <OS/OSScheduler.h>
#include <lib/String.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
#include "../../common/hot_header.h"
UInt64 HOTLoad(OSProcess* process, UInt8* data) {
HOTHeader* header = (HOTHeader*)data;
if (header->magic != HOT_MAGIC) {
return -1;
}
HOTSegment* segments = (HOTSegment*)(data + sizeof(HOTHeader));
for (UInt64 i = 0; i < header->segments_count; i++) {
HOTSegment* segment = &segments[i];
if (segment->memsz == 0) continue;
UInt64 start = segment->vaddr & ~(0xFFFULL);
UInt64 end = (segment->vaddr + segment->memsz + 0xFFF) & ~(0xFFFULL);
for (UInt64 address = start; address < end; address += kVMPageSize) {
void* physicalPage = VMPhysicalMemoryAllocatePage();
VMVirtualMemoryMapPage((UInt64*)process->physicalPML4, (UInt64)physicalPage, address, PTE_USER | PTE_RW | PTE_PRESENT);
void* kernelVirtAddress = (void*)((UInt64)physicalPage + HHDM_OFFSET);
MemorySet(kernelVirtAddress, 0, kVMPageSize);
UInt64 pageOverleapStart = (address > segment->vaddr) ? address : segment->vaddr;
UInt64 pageOverleapEnd = (address + kVMPageSize < segment->vaddr + segment->filesz)
? (address + kVMPageSize)
: (segment->vaddr + segment->filesz);
if (pageOverleapStart < pageOverleapEnd) {
UInt64 copySize = pageOverleapEnd - pageOverleapStart;
UInt64 sourceOffset = segment->offset + (pageOverleapStart - segment->vaddr);
UInt64 destinationOffset = pageOverleapStart - address;
MemoryCopy((UInt8*)kernelVirtAddress + destinationOffset, data + sourceOffset, copySize);
}
}
}
return header->entry_point;
}
+81
View File
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Exec/HOTLoader.h>
#include <OS/Exec/OSLoader.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <lib/String.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <VM/Heap.h>
#include <FS/VFS.h>
#include <IO/IOConsole.h>
#include <types.h>
extern UInt32 gOSSchedulerNextProcessID;
enum {
kOSUserStackTop = 0x70000000,
kOSHeapStart = 0x40000000
};
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName) {
FSVNode* executableFile = FSVirtualFileSystemOpenPath(executablePath);
if (!executableFile) {
return -1;
}
OSProcess* newProcess = (OSProcess*)VMHeapAllocate(sizeof(OSProcess));
if (!newProcess) {
return -2;
}
MemorySet(newProcess, 0, sizeof(OSProcess));
newProcess->processId = gOSSchedulerNextProcessID++;
newProcess->state = kOSProcessStateRunning;
newProcess->physicalPML4 = VMVirtualMemoryCreateAddressSpace();
newProcess->heapStartPointer = kOSHeapStart;
newProcess->heapCurrentPointer = kOSHeapStart;
StringCopyWithLimit(newProcess->name, processName, 31);
UInt8* imageBuffer = (UInt8*)VMHeapAllocate(executableFile->dataLength);
if (!imageBuffer) {
VMHeapFree(newProcess);
return -3;
}
FSVNodeRead(executableFile, 0, executableFile->dataLength, imageBuffer);
UInt64 entryPoint = HOTLoad(newProcess, imageBuffer);
if (!entryPoint) {
VMHeapFree(imageBuffer);
VMHeapFree(newProcess);
return -4;
}
VMHeapFree(imageBuffer);
VMVirtualMemorySetupUserStack((UInt64*)newProcess->physicalPML4);
if (!OSSchedulerSpawn((void(*)())entryPoint, newProcess, true, kOSUserStackTop)) {
VMHeapFree(newProcess);
return -5;
}
return newProcess->processId;
}
void init_task_entry() {
Int32 pid = OSLoaderProcessSpawn("/System/CoreServices/init", "init");
if (pid < 0) {
OSPanic("FATAL: Failed to spawn /System/CoreServices/init");
}
while (1) { __asm__("sti; hlt"); }
}
+166
View File
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSPanic.h>
#include <lib/Rand.h>
#include <IO/IOGraphics.h>
#include <IO/IOConsole.h>
#include <types.h>
static const char* sOSPanicFunMessages[] = {
"Execution finished abnormally with code: 0x_x",
"It's definitely your fault.",
"No more Roblox!",
"Call your mom 4 help!",
"2bad4u",
"Touch grass",
"Skill issue",
"You should just go outside actually",
"Perfect opportunity to take a shower",
"404 not found",
"Windows is locked! Password:___ Time left: 5:45:41",
"GOOOOOAL",
"\"NAM PIZDA\": hackers dropped our registry",
"geeked vs locked in",
"HEEEELP!",
"LET ME GO!",
"You little asshole, make it better",
"Go and read books for programming u idiot",
"TIME TO BRAKE! :3 Take a tea and try again later cutie",
"Code have been eaten by Aliens",
"That's all, folks!",
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
"I'll be back",
"Hastla la vista, baby",
"Ti chego mne tut nagovoril...",
"Have you tried turning it off and on again?",
"Put it in rice maybe?",
"Just hit the monitor, it usually helps",
"I think it needs a rest. Come back tomorrow",
"You clicked something wrong, didn't you?",
"You hacked it too hard, bro",
"I think you deleted the internet",
"Stop downloading RAM",
"Pro tip: dont crash",
"Stop ricing the kernel you loonixtard, TermOS is NOT Loonix",
"Attaboy, Jack. He's good. Really good.",
"Zhenih priehal",
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
"fuck off",
"Your GPU is now mining Ethereum for me. Thanks.",
"Your PC is locked!\n\t\t\t\tPay a fee of 0.019082006 bitcoins to a wallet 1KtoProchitalTotSosal to get decryption key!",
};
static const char* sOSPanicExceptionMessages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Reserved",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
"Reserved"
};
__attribute__((noreturn)) static void die() {
while (1) {
__asm__ volatile ("cli; hlt");
}
}
static void sOSPanicDrawPanicBackground() {
IOConsoleClear(0x000000);
IOConsoleSetForegroundColor(0xFFFFFF);
IOConsoleSetDefaultForegroundColor(0xFFFFFF);
UInt64 funMessagesCount = sizeof(sOSPanicFunMessages) / sizeof(sOSPanicFunMessages[0]);
UInt8 randNum = Rand() % funMessagesCount;
IOConsoleLog("\n\n");
IOConsoleLog("\t\t\t\t^bKERNEL PANIC^! :( \n");
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t^y%s^!\n", sOSPanicFunMessages[randNum]);
IOConsoleLog("\t\t--------------------------------\n");
}
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame) {
sOSPanicDrawPanicBackground();
IOConsoleLog("\t\t^yCPU EXCEPTION^!: ^b%s^! (%d)\n", sOSPanicExceptionMessages[frame->interruptNumber], frame->interruptNumber);
if (frame->errorCode) IOConsoleLog("\t\t^yError Code^!: %X\n", frame->errorCode);
IOConsoleLog("\t\t^yInstruction Pointer^! (^yRIP^!): %X\n", frame->rip);
IOConsoleLog("\t\t^yCode Segment^! (^yCS^!): %X\n", frame->cs);
IOConsoleLog("\t\t^yFlags^! (^yRFLAGS^!): %X\n", frame->rflags);
IOConsoleLog("\t\t^yStack Pointer^! (^yRSP^!): %X\n", frame->rsp);
if (frame->interruptNumber == 14) {
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t ^yPage Fault Helper^! \n");
IOConsoleLog("\t\t--------------------------------\n");
UInt64 cr2;
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
IOConsoleLog("\t\t^yFaulting Address^! (^yCR2^!): %X\n", cr2);
IOConsoleLog("\t\t^yERRCode^!: %X\n", frame->errorCode);
UInt64 present = (frame->errorCode & (1 << 0)) != 0;
UInt64 write = (frame->errorCode & (1 << 1)) != 0;
UInt64 user = (frame->errorCode & (1 << 2)) != 0;
UInt64 reserved = (frame->errorCode & (1 << 3)) != 0;
UInt64 instruction = (frame->errorCode & (1 << 4)) != 0;
IOConsoleLog("\t\t\t[^bP^!] ^yReason^!: %s\n", present ? "Page Protection violation" : "Non-present page");
IOConsoleLog("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
IOConsoleLog("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
if (reserved) IOConsoleLog("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
if (instruction) IOConsoleLog("\t\t\t[^bI^!] ^yTried to^! execute ^ycode from^! NX ^ymemory^!\n");
}
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t\t\t^yREGISTERS^!\n");
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t^yRAX^!=%X, ^yRBX^!=%X\n", frame->rax, frame->rbx);
IOConsoleLog("\t\t^yRCX^!=%X, ^yRDX^!=%X\n", frame->rcx, frame->rdx);
IOConsoleLog("\t\t^yRSI^!=%X, ^yRDI^!=%X\n", frame->rsi, frame->rdi);
IOConsoleLog("\t\t^yRBP^!=%X, ^yR8^! =%X\n", frame->rbp, frame->r8);
IOConsoleLog("\t\t^yR9^! =%X, ^yR10^!=%X \n", frame->r9, frame->r10);
IOConsoleLog("\t\t^yR11^!=%X, ^yR12^!=%X\n", frame->r11, frame->r12);
IOConsoleLog("\t\t^yR13^!=%X, ^yR14^!=%X\n", frame->r13, frame->r14);
IOConsoleLog("\t\t^yR15^!=%X\n",frame->r15);
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
die();
}
__attribute__((noreturn)) void OSPanic(const char* message) {
sOSPanicDrawPanicBackground();
IOConsoleLog("\t\t^yReason^!: %s\n", message);
IOConsoleLog("\t\t--------------------------------\n");
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
die();
}
+226
View File
@@ -0,0 +1,226 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSScheduler.h>
#include <OS/OSSpinlock.h>
#include <OS/OSPanic.h>
#include <lib/String.h>
#include <VM/Heap.h>
#include <VM/VMM.h>
#include <OSCPU.h>
#include <GDT.h>
OSTask* gOSSchedulerCurrentTask = nullptr;
UInt32 gOSSchedulerNextProcessID = 1;
extern void irq0_handler();
extern UInt64 gVMKernelPML4Physical;
static OSProcess sOSSchedulerKernelProcess;
static OSSpinlock sOSSchedulerLock;
static OSTask* sOSSchedulerGarbageCollectorTask = nullptr;
void idle_task() {
while (1) {
__asm__ volatile ("hlt");
}
}
void OSSchedulerGarbageCollector() {
OSTask* self = gOSSchedulerCurrentTask;
while (true) {
OSTask* previousTask = self;
OSTask* nextTask = previousTask->next;
while (nextTask != self) {
if (nextTask->taskState == kOSProcessStateDead) {
OSSpinlockState lockState;
OSSpinlockLockIRQ(&sOSSchedulerLock, &lockState);
previousTask->next = nextTask->next;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &lockState);
if (nextTask->kernelStackBase) {
VMHeapFree(nextTask->kernelStackBase);
}
VMHeapFree(nextTask);
nextTask = previousTask->next;
} else {
previousTask = nextTask;
nextTask = nextTask->next;
}
}
OSSchedulerYield(200);
}
}
static void sOSSchedulerPostGarbageCollectorSignal() {
if (!sOSSchedulerGarbageCollectorTask) return;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
sOSSchedulerGarbageCollectorTask->taskState = kOSProcessStateRunning;
sOSSchedulerGarbageCollectorTask->sleepTicks = 0;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerInitialize() {
sOSSchedulerKernelProcess.processId = 0;
sOSSchedulerKernelProcess.state = kOSProcessStateRunning;
sOSSchedulerKernelProcess.physicalPML4 = gVMKernelPML4Physical;
StringCopy(sOSSchedulerKernelProcess.name, "kernel");
OSTask* kernelTask = (OSTask*)VMHeapAllocate(sizeof(OSTask));
if (!kernelTask) OSPanic("Failed to initialize scheduler: OOm");
MemorySet(kernelTask, 0, sizeof(OSTask));
kernelTask->id = 0;
kernelTask->process = &sOSSchedulerKernelProcess;
kernelTask->sleepTicks = 0;
kernelTask->next = kernelTask;
kernelTask->taskState = kOSProcessStateRunning;
kernelTask->waitingForProcess = -1;
gOSSchedulerCurrentTask = kernelTask;
OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0);
sOSSchedulerGarbageCollectorTask = OSSchedulerSpawn(OSSchedulerGarbageCollector, &sOSSchedulerKernelProcess, false, 0);
return;
}
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) {
OSTask* task = (OSTask*)VMHeapAllocate(sizeof(OSTask));
if (!task) return nullptr;
if (!owner) owner = &sOSSchedulerKernelProcess;
UInt64 stackSize = 16384;
UInt8* stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
if (!stackBaseAddress) {
sOSSchedulerPostGarbageCollectorSignal();
OSSchedulerYield(0);
stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
if (!stackBaseAddress) {
VMHeapFree(task);
return nullptr;
}
}
UInt64* rsp = (UInt64*)(stackBaseAddress + stackSize);
UInt64 cs = isUser ? 0x23 : 0x08;
UInt64 ss = isUser ? 0x1b : 0x10;
UInt64 rflags = 0x202;
UInt64 targetStackPointer = 0;
if (isUser) targetStackPointer = fixedUserStackPointer;
else targetStackPointer = (UInt64)stackBaseAddress + stackSize;
*--rsp = ss; // SS -- Kernel data
*--rsp = targetStackPointer; // rsp
*--rsp = rflags; // RFLAGS -- Interrupts Enabled | Reserved bit;
*--rsp = cs; // CS -- Kernel Code;
*--rsp = (UInt64)entry; // RIP
*--rsp = 0; // int no
*--rsp = 0; // err code
for (UInt8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
task->stackPointer = (UInt64)rsp;
task->process = owner;
task->id = owner->processId;
task->sleepTicks = 0;
task->kernelStackTop = (UInt64)stackBaseAddress + stackSize;
task->kernelStackBase = stackBaseAddress;
task->taskState = kOSProcessStateRunning;
task->waitingForProcess = -1;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
task->next = gOSSchedulerCurrentTask->next;
gOSSchedulerCurrentTask->next = task;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
return task;
}
UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
if (!gOSSchedulerCurrentTask) return currentStackPointer;
OSSpinlockLock(&sOSSchedulerLock);
gOSSchedulerCurrentTask->stackPointer = currentStackPointer;
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
do {
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
taskIterator = taskIterator->next;
} while (taskIterator != gOSSchedulerCurrentTask->next);
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
OSTask* nextTask = gOSSchedulerCurrentTask->next;
while (1) {
if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning;
if (nextTask->taskState == kOSProcessStateRunning) break;
nextTask = nextTask->next;
if (nextTask == gOSSchedulerCurrentTask) {
if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break;
OSPanic("no running tasks");
}
}
if (nextTask->process->physicalPML4 != gOSSchedulerCurrentTask->process->physicalPML4) VMLoadCR3(nextTask->process->physicalPML4);
gOSSchedulerCurrentTask = nextTask;
gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop;
gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop;
OSSpinlockUnlock(&sOSSchedulerLock);
return gOSSchedulerCurrentTask->stackPointer;
}
void OSSchedulerBlock(UInt32 processID) {
gOSSchedulerCurrentTask->taskState = kOSProcessStateBlocked;
gOSSchedulerCurrentTask->waitingForProcess = processID;
__asm__ volatile("int $32");
}
void OSSchedulerWakeup(UInt32 processID) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
OSTask* iteratorTask = gOSSchedulerCurrentTask;
do {
if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) {
iteratorTask->taskState = kOSProcessStateRunning;
iteratorTask->waitingForProcess = -1;
}
iteratorTask = iteratorTask->next;
} while (iteratorTask != gOSSchedulerCurrentTask);
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerTerminate() {
UInt32 processID = gOSSchedulerCurrentTask->id;
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
OSSchedulerWakeup(processID);
sOSSchedulerPostGarbageCollectorSignal();
__asm__ volatile("int $32");
}
void OSSchedulerYield(UInt64 ticks) {
gOSSchedulerCurrentTask->sleepTicks = ticks;
gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping;
__asm__ volatile("int $32");
}
+29
View File
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSSpinlock.h>
void OSSpinlockLock(OSSpinlock* lock) {
while (__atomic_exchange_n(&lock->lockValue, 1, __ATOMIC_ACQUIRE)) {
while (lock->lockValue) {
__builtin_ia32_pause();
}
}
}
void OSSpinlockUnlock(OSSpinlock *lock) {
__atomic_store_n(&lock->lockValue, 0, __ATOMIC_RELEASE);
}
void OSSpinlockLockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
UInt64 rflags;
__asm__ volatile("pushfq; pop %0; cli" : "=r"(rflags) :: "memory"); // read flags and cli
state->interruptsEnabled = (rflags & (1 << 9)) != 0; // IF bit
OSSpinlockLock(lock);
}
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
OSSpinlockUnlock(lock);
if (state->interruptsEnabled) __asm__ volatile("sti" ::: "memory");
}
+28
View File
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Services/OSServiceIO.h>
#include <IO/IOConsole.h>
#include <IO/IOKeyboard.h>
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
if (fileDescriptor == 1 || fileDescriptor == 2) {
char* string = (char*)buffer;
for (UInt64 i = 0; i < length; i++) {
IOConsolePutcharacter(string[i]);
}
return length;
}
return 0;
}
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
char* readBuffer = (char*)buffer;
if (fileDescriptor == 0) {
for (UInt64 i = 0; i < count; i++) {
readBuffer[i] = IOKeyboardGetCharacter();
}
return count;
}
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/Services/OSServiceMemory.h>
#include <OS/OSScheduler.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
UInt64 OSServiceMemoryAllocate(UInt64 size) {
if (size == 0) return 0;
OSProcess* currentProcess = gOSSchedulerCurrentTask->process;
UInt64 addressToReturn = currentProcess->heapCurrentPointer;
UInt64 pages_needed = (size + (kVMPageSize-1)) / kVMPageSize;
for (UInt64 i = 0; i < pages_needed; i++) {
void* phycialAddress = VMPhysicalMemoryAllocatePage();
if (!phycialAddress) return 0;
VMVirtualMemoryMapPage((UInt64*)currentProcess->physicalPML4, (UInt64)phycialAddress, currentProcess->heapCurrentPointer, PTE_PRESENT | PTE_RW | PTE_USER);
MemorySet((void*)PHYS_TO_HHDM((UInt64)phycialAddress), 0, kVMPageSize);
currentProcess->heapCurrentPointer += kVMPageSize;
}
return addressToReturn;
}
+24
View File
@@ -0,0 +1,24 @@
// 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>
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) {
return OSLoaderProcessSpawn(path, path);
}
Int32 OSServiceProcessWait(UInt64 processID) {
OSSchedulerBlock(processID);
return processID;
}
+131
View File
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <VM/Heap.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
extern UInt64* gVMKernelPML4;
static VMHeapBlockHeader* sVMHeapListHead = nullptr;
static OSSpinlock sVMHeapLock = {0};
static void sVMHeapCombineForward(VMHeapBlockHeader* current) {
if (!current->next || !current->next->isFree) return;
current->size += sizeof(VMHeapBlockHeader) + current->next->size;
current->next = current->next->next;
if (current->next) current->next->previous = current; // what the fuck
}
void VMHeapInitialize() {
UInt64 heapStart = kVMKernelHeapStart;
for (UInt64 i = 0; i < kVMHeapSizePages; i++) {
UInt64 physical = (UInt64)VMPhysicalMemoryAllocatePage();
if (!physical) OSPanic("OOM during heap init");
UInt64 virtual = heapStart + (i * kVMPageSize);
VMVirtualMemoryMapPage(gVMKernelPML4, physical, virtual, PTE_PRESENT | PTE_RW);
}
sVMHeapListHead = (VMHeapBlockHeader*)heapStart;
sVMHeapListHead->magic = kVMHeapBlockHeaderMagic;
sVMHeapListHead->size = (kVMHeapSizePages * kVMPageSize) - sizeof(VMHeapBlockHeader);
sVMHeapListHead->isFree = true;
sVMHeapListHead->next = nullptr;
sVMHeapListHead->previous = nullptr;
}
static void* sVMHeapAllocateInternal(UInt64 size) {
if (size == 0) return nullptr;
UInt64 alignedSize = (size + 15) & ~15;
VMHeapBlockHeader* current = sVMHeapListHead;
while (current) {
if (current->isFree && current->size >= alignedSize) {
if (current->size > alignedSize + sizeof(VMHeapBlockHeader) + 16) {
VMHeapBlockHeader* new_block = (VMHeapBlockHeader*)((UInt64)current + sizeof(VMHeapBlockHeader) + alignedSize);
new_block->size = current->size - alignedSize - sizeof(VMHeapBlockHeader);
new_block->isFree = true;
new_block->next = current->next;
new_block->previous = current;
new_block->magic = kVMHeapBlockHeaderMagic;
if (current->next) current->next->previous = new_block;
current->next = new_block;
current->size = alignedSize;
}
current->isFree = false;
return (void*)((UInt64)current + sizeof(VMHeapBlockHeader));
}
current = current->next;
}
return nullptr;
}
static void sVMHeapFreeInternal(void* pointer) {
if (!pointer) return;
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->magic != kVMHeapBlockHeaderMagic) return;
current->isFree = true;
if (current->next && current->next->isFree) sVMHeapCombineForward(current);
if (current->previous && current->previous->isFree) sVMHeapCombineForward(current->previous);
}
void* VMHeapAllocate(UInt64 size) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
void* result = sVMHeapAllocateInternal(size);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return result;
}
void VMHeapFree(void* pointer) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
sVMHeapFreeInternal(pointer);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
}
void* VMHeapResize(void* pointer, UInt64 newSize) {
if (!pointer) return VMHeapAllocate(newSize);
if (newSize == 0) {
VMHeapFree(pointer);
return nullptr;
}
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->size >= newSize) {
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
if (current->next && current->next->isFree &&
(current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable
sVMHeapCombineForward(current);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
void* newPointer = sVMHeapAllocateInternal(newSize);
if (newPointer) {
MemoryCopy(newPointer, pointer, current->size);
sVMHeapFreeInternal(pointer);
}
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return newPointer;
}
+131
View File
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
#include <lib/Math.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
#include "bootinfo.h"
UInt8* gVMPhycalMemoryBitmap = nullptr;
UInt64 gVMPhycalMemoryBitmapSize = 0;
UInt64 gVMPhycalMemoryTotalMemorySize = 0;
static OSSpinlock sVMPMMLock = {0};
extern UInt64 _kernel_start;
extern UInt64 _kernel_end;
UInt64 VMPhysicalMemoryGetTotalMemorySize() {
return gVMPhycalMemoryTotalMemorySize;
}
void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
UInt64 descriptorCount = memoryMap->mapSize / memoryMap->descriptorSize;
UInt64 maxPhysicalAddress = 0;
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor* descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
if (descriptor->type == kOSMemoryTypeMappedIO ||
descriptor->type == kOSMemoryTypeMappedIOPortSpace ||
descriptor->type == kOSMemoryTypeUnusable ||
descriptor->type == kOSMemoryTypeReserved ||
descriptor->type == kOSMemoryTypePalCode) {
continue;
}
UInt64 nominee = descriptor->physicalStart + (descriptor->pageCount * kVMPageSize);
if (nominee > maxPhysicalAddress) {
maxPhysicalAddress = nominee;
}
}
gVMPhycalMemoryTotalMemorySize = maxPhysicalAddress;
UInt64 totalPageCount = maxPhysicalAddress / kVMPageSize;
UInt64 bitmapSize = (totalPageCount + 7) / 8;
OSMemoryDescriptor *bitmapHostDescriptor = nullptr;
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
if ((descriptor->type == kOSMemoryTypeConventional) &&
((descriptor->pageCount * kVMPageSize) >= bitmapSize) &&
(descriptor->physicalStart >= kVMSafeSpaceStartAddress)) {
bitmapHostDescriptor = descriptor;
break;
}
}
if (bitmapHostDescriptor == nullptr) {
OSPanic("PMM: Not enough RAM for memory bitmap!");
}
gVMPhycalMemoryBitmap = (UInt8*)bitmapHostDescriptor->physicalStart;
gVMPhycalMemoryBitmapSize = bitmapSize;
MemorySet(gVMPhycalMemoryBitmap, 0xFF, bitmapSize);
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
if (descriptor->type != kOSMemoryTypeConventional) {
continue;
}
UInt64 startAddress = descriptor->physicalStart;
UInt64 endAddress = startAddress + (descriptor->pageCount * kVMPageSize);
for (UInt64 addr = startAddress; addr < endAddress; addr += kVMPageSize) {
BITMAP_UNSET(gVMPhycalMemoryBitmap, addr);
}
}
UInt64 kernelStart = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_start);
UInt64 kernelEnd = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_end);
UInt64 bitmapStart = (UInt64)gVMPhycalMemoryBitmap;
UInt64 bitmapEnd = bitmapStart + gVMPhycalMemoryBitmapSize;
for (UInt64 addr = 0; addr < kVMSafeSpaceStartAddress; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
for (UInt64 addr = kernelStart; addr < kernelEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
for (UInt64 addr = bitmapStart; addr < bitmapEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
}
void* VMPhysicalMemoryAllocatePage() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) {
if (gVMPhycalMemoryBitmap[i] == 0xFF) continue;
for (UInt64 bit = 0; bit < 8; bit++) {
if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) {
UInt64 address = (i * 8 + bit) * kVMPageSize;
BITMAP_SET(gVMPhycalMemoryBitmap, address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return (void*)address;
}
}
}
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return nullptr; // Out of memory
}
void VMPhysicalMemoryFreePage(void* address) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
}
+207
View File
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <VM/VMM.h>
#include <VM/PMM.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <GDT.h>
#include <IDT.h>
#include <lib/String.h>
#include <types.h>
#include "bootinfo.h"
enum {
kVMUserStackTop = 0x70000000,
kVMUserStackSize = 0x4000
};
UInt64* gVMKernelPML4 = nullptr;
UInt64 gVMKernelPML4Physical = 0;
static OSSpinlock sVMVMMlock = {0};
static bool isInitialized = false;
extern UInt64 _kernel_start;
extern UInt64 _kernel_end;
extern UInt8* gVMPhycalMemoryBitmap;
extern UInt64 gVMPhycalMemoryBitmapSize;
extern HALGlobalDescriptorTable gHALGlobalDescriptorTable[];
extern HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[];
extern UInt8 gHALDoubleFaultStack[];
extern UInt8 stack_guard;
static UInt64* sVMGetVirtualTable(UInt64 phys) {
if (isInitialized) return (UInt64*)PHYS_TO_HHDM(phys);
return (UInt64*)phys;
}
static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
UInt64* pml4_virt = pml4;
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
UInt64 table_flags = PTE_PRESENT | PTE_RW | (flags & PTE_USER);
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
MemorySet(addr_virt, 0, kVMPageSize);
pml4_virt[pml4_idx] = (UInt64)addr | table_flags;
} else {
pml4_virt[pml4_idx] |= (flags & PTE_USER);
}
UInt64* pdpt = (UInt64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
UInt64* pdpt_virt = sVMGetVirtualTable((UInt64)pdpt);
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) {
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
MemorySet(addr_virt, 0, kVMPageSize);
pdpt_virt[pdpt_idx] = (UInt64)addr | table_flags;
} else {
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
}
UInt64* pd = (UInt64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
UInt64* pd_virt = sVMGetVirtualTable((UInt64)pd);
if (!(pd_virt[pd_idx] & PTE_PRESENT)) {
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
MemorySet(addr_virt, 0, kVMPageSize);
pd_virt[pd_idx] = (UInt64)addr | table_flags;
} else {
pd_virt[pd_idx] |= (flags & PTE_USER);
}
UInt64* pt = (UInt64*)PTE_GET_ADDR(pd_virt[pd_idx]);
UInt64* pt_virt = sVMGetVirtualTable((UInt64)pt);
pt_virt[pt_idx] = phys | flags;
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
return (UInt64*)virt;
}
static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
UInt64* pml4_virt = pml4;
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) return;
UInt64* pdpt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pml4_virt[pml4_idx]));
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) return;
UInt64* pd_virt = sVMGetVirtualTable(PTE_GET_ADDR(pdpt_virt[pdpt_idx]));
if (!(pd_virt[pd_idx] & PTE_PRESENT)) return;
UInt64* pt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pd_virt[pd_idx]));
pt_virt[pt_idx] = 0;
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
}
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, phys, virt, flags);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return result;
}
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
sVMVirtualMemoryUnmapPageInternal(pml4, virt);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
}
void VMLoadCR3(UInt64 pml4_addr) {
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
}
void VMVirtualMemoryInitialize(Bootinfo* info) {
gVMKernelPML4Physical = (UInt64)VMPhysicalMemoryAllocatePage();
gVMKernelPML4 = (UInt64*)gVMKernelPML4Physical;
MemorySet(gVMKernelPML4, 0, kVMPageSize);
UInt64 k_virt_start = (UInt64)&_kernel_start;
UInt64 k_virt_end = (UInt64)&_kernel_end;
UInt64 fb_start = (UInt64)info->framebuffer.base;
UInt64 fb_end = fb_start + info->framebuffer.baseSize;
UInt64 fb_size = fb_end - fb_start;
UInt64 max_mem = VMPhysicalMemoryGetTotalMemorySize();
for (UInt64 i = 0; i < max_mem; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, i, PHYS_TO_HHDM(i), PTE_PRESENT | PTE_RW);
for (UInt64 i = k_virt_start; i < k_virt_end; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, KERNEL_VIRT_TO_PHYS(i), i, PTE_PRESENT | PTE_RW);
for (UInt64 i = 0; i < fb_size; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, fb_start + i, FB_VIRT_BASE + i, PTE_PRESENT | PTE_RW);
VMVirtualMemoryUnmapPage(gVMKernelPML4, (UInt64)&stack_guard);
gVMPhycalMemoryBitmap = (UInt8*)PHYS_TO_HHDM((UInt64)gVMPhycalMemoryBitmap);
info->framebuffer.base = (UInt32*)FB_VIRT_BASE;
VMLoadCR3(gVMKernelPML4Physical);
isInitialized = true;
}
UInt64 VMVirtualMemoryCreateAddressSpace() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage();
if (!phys) {
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return 0;
};
UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys);
MemorySet(virt, 0, kVMPageSize);
UInt64* kernel_pml4_virt = sVMGetVirtualTable((UInt64)gVMKernelPML4);
for (UInt32 i = 256; i < 512; i++) {
virt[i] = kernel_pml4_virt[i];
}
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return phys;
}
UInt64 VMGetCurrentCR3() {
UInt64 cr3;
__asm__ volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
void VMVirtualMemorySetupUserStack(UInt64* pml4_phys) {
UInt64 stack_bottom = kVMUserStackTop - kVMUserStackSize;
for (UInt64 addr = stack_bottom; addr < kVMUserStackTop; addr += 4096) {
void* phys = VMPhysicalMemoryAllocatePage();
if (!phys) OSPanic("OOM in user stack setup");
MemorySet((void*)PHYS_TO_HHDM((UInt64)phys), 0, 4096);
VMVirtualMemoryMapPage((UInt64*)pml4_phys, (UInt64)phys, addr, PTE_PRESENT | PTE_RW | PTE_USER);
}
}
+77
View File
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// just fucking kill me already
#include <GDT.h>
HALGlobalDescriptorTable gHALGlobalDescriptorTable[kHALGDTEntries];
HALGlobalDescriptorTablePointer gHALGlobalDescriptorTablePointer;
HALTaskStateSegment gHALTaskStateSegment;
UInt8 gHALDoubleFaultStack[4096] = {0};
static void sHALGlobalDescriptorTableSetGate(int number, UInt64 base, UInt64 limit, UInt8 access, UInt8 granularity) {
gHALGlobalDescriptorTable[number].baseLow = (base & 0xFFFF); // left only low 16bit
gHALGlobalDescriptorTable[number].baseMiddle = (base >> 16) & 0xFF; // 3rd address byte
gHALGlobalDescriptorTable[number].baseHigh = (base >> 24) & 0xFF; // 4th address byte
gHALGlobalDescriptorTable[number].limitLow = (limit & 0xFFFF);
gHALGlobalDescriptorTable[number].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19)
gHALGlobalDescriptorTable[number].granularity |= granularity & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags)
gHALGlobalDescriptorTable[number].access = access;
// fuck intel
}
static void sHALTaskStateSegmentWrite(int number) {
UInt64 base = (UInt64)&gHALTaskStateSegment;
UInt64 limit = sizeof(gHALTaskStateSegment);
UInt64 access = 0x89; // TSS_PRESENT | TSS_EXECUTABLE | TSS_ACCESSED;
UInt64 granularity = 0;
sHALGlobalDescriptorTableSetGate(number, base, limit, access, granularity);
*((UInt64*)&gHALGlobalDescriptorTable[number+1]) = (base >> 32); // really scary but not really hard
// just direct write 8bytes to num+1
// basically a hack but at this point i dont care
}
extern void gdt_flush(UInt64 gdt_ptr_addr); // entry.asm
void HALGlobalDescriptorTableInitialize() {
gHALGlobalDescriptorTablePointer.limit = (sizeof(HALGlobalDescriptorTable) * kHALGDTEntries) - 1;
gHALGlobalDescriptorTablePointer.base = (UInt64)&gHALGlobalDescriptorTable;
// 0: Null
sHALGlobalDescriptorTableSetGate(0, 0, 0, 0, 0);
// 1: Kernel Code (Ring 0)
// Access: 0x9A (Present, Ring0, Exec/Read)
// Granularity: 0x20 (Long Mode bit) access ring 0 code exec code readable
sHALGlobalDescriptorTableSetGate(1, 0, 0, 0x9A, 0x20); // 0x9A = 1 00 1 1 0 1
// 0x20 = 0010 0000 bit 5 is "Long mode"
// 2: Kernel Data (Ring 0)
// Access: 0x92 (Present, Ring0, Read/Write)
sHALGlobalDescriptorTableSetGate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
// 3: User Data (Ring 3)
// Access: 0xF2 (Present, Ring3, Read/Write)
sHALGlobalDescriptorTableSetGate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
// 4: User Code (Ring 3)
// Access: 0xFA (Present, Ring3, RWX)
sHALGlobalDescriptorTableSetGate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
for (UInt64 i = 0; i < sizeof(HALTaskStateSegment); i++) ((UInt8*)&gHALTaskStateSegment)[i] = 0; // zeroifying tss struct
gHALTaskStateSegment.iomapBase = sizeof(HALTaskStateSegment);
gHALTaskStateSegment.ist1 = (UInt64)gHALDoubleFaultStack + sizeof(gHALDoubleFaultStack);
sHALTaskStateSegmentWrite(5);
gdt_flush((UInt64)&gHALGlobalDescriptorTablePointer);
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
}
+82
View File
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <IDT.h>
#include <types.h>
HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[256];
HALInterruptsDescriptorTablePointer gHALInterruptsDescriptorTablePointer;
extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3();
extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7();
extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11();
extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15();
extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19();
extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23();
extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27();
extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31();
extern void irq0(void); extern void irq1(void);
extern void idt_load(UInt64); // asm: lidt [rdi] / ret
static void sHALInterruptsDescriptorTableSetGate(int number, UInt64 handler, UInt16 selector, UInt8 flags) {
gHALInterruptsDescriptorTable[number].offsetLow = handler & 0xFFFF;
gHALInterruptsDescriptorTable[number].offsetMid = (handler >> 16) & 0xFFFF;
gHALInterruptsDescriptorTable[number].offsetHigh = (handler >> 32) & 0xFFFFFFFF;
gHALInterruptsDescriptorTable[number].selector = selector; // 0x08 (Kernel Code)
gHALInterruptsDescriptorTable[number].ist = 0;
gHALInterruptsDescriptorTable[number].attributes = flags;
gHALInterruptsDescriptorTable[number].reserved = 0;
}
void HALInterruptsDescriptorTableInitialize() {
gHALInterruptsDescriptorTablePointer.limit = (sizeof(HALInterruptsDescriptorTableEntry) * 256) - 1;
gHALInterruptsDescriptorTablePointer.base = (UInt64)&gHALInterruptsDescriptorTable;
const UInt8 flags = 0x8E;
const UInt8 selector = 0x08;
sHALInterruptsDescriptorTableSetGate(0, (UInt64)isr0, selector, flags);
sHALInterruptsDescriptorTableSetGate(1, (UInt64)isr1, selector, flags);
sHALInterruptsDescriptorTableSetGate(2, (UInt64)isr2, selector, flags);
sHALInterruptsDescriptorTableSetGate(3, (UInt64)isr3, selector, flags);
sHALInterruptsDescriptorTableSetGate(4, (UInt64)isr4, selector, flags);
sHALInterruptsDescriptorTableSetGate(5, (UInt64)isr5, selector, flags);
sHALInterruptsDescriptorTableSetGate(6, (UInt64)isr6, selector, flags);
sHALInterruptsDescriptorTableSetGate(7, (UInt64)isr7, selector, flags);
sHALInterruptsDescriptorTableSetGate(8, (UInt64)isr8, selector, flags);
sHALInterruptsDescriptorTableSetGate(9, (UInt64)isr9, selector, flags);
sHALInterruptsDescriptorTableSetGate(10, (UInt64)isr10, selector, flags);
sHALInterruptsDescriptorTableSetGate(11, (UInt64)isr11, selector, flags);
sHALInterruptsDescriptorTableSetGate(12, (UInt64)isr12, selector, flags);
sHALInterruptsDescriptorTableSetGate(13, (UInt64)isr13, selector, flags);
sHALInterruptsDescriptorTableSetGate(14, (UInt64)isr14, selector, flags);
sHALInterruptsDescriptorTableSetGate(15, (UInt64)isr15, selector, flags);
sHALInterruptsDescriptorTableSetGate(16, (UInt64)isr16, selector, flags);
sHALInterruptsDescriptorTableSetGate(17, (UInt64)isr17, selector, flags);
sHALInterruptsDescriptorTableSetGate(18, (UInt64)isr18, selector, flags);
sHALInterruptsDescriptorTableSetGate(19, (UInt64)isr19, selector, flags);
sHALInterruptsDescriptorTableSetGate(20, (UInt64)isr20, selector, flags);
sHALInterruptsDescriptorTableSetGate(21, (UInt64)isr21, selector, flags);
sHALInterruptsDescriptorTableSetGate(22, (UInt64)isr22, selector, flags);
sHALInterruptsDescriptorTableSetGate(23, (UInt64)isr23, selector, flags);
sHALInterruptsDescriptorTableSetGate(24, (UInt64)isr24, selector, flags);
sHALInterruptsDescriptorTableSetGate(25, (UInt64)isr25, selector, flags);
sHALInterruptsDescriptorTableSetGate(26, (UInt64)isr26, selector, flags);
sHALInterruptsDescriptorTableSetGate(27, (UInt64)isr27, selector, flags);
sHALInterruptsDescriptorTableSetGate(28, (UInt64)isr28, selector, flags);
sHALInterruptsDescriptorTableSetGate(29, (UInt64)isr29, selector, flags);
sHALInterruptsDescriptorTableSetGate(30, (UInt64)isr30, selector, flags);
sHALInterruptsDescriptorTableSetGate(31, (UInt64)isr31, selector, flags);
gHALInterruptsDescriptorTable[8].ist = 1; // TSS
gHALInterruptsDescriptorTable[13].ist = 1;
gHALInterruptsDescriptorTable[14].ist = 1;
sHALInterruptsDescriptorTableSetGate(32, (UInt64)irq0, selector, flags);
sHALInterruptsDescriptorTableSetGate(33, (UInt64)irq1, selector, flags);
__asm__ volatile ("lidt %0" : : "m"(gHALInterruptsDescriptorTablePointer));
}
+72
View File
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <types.h>
#include <OSCPU.h>
#define MSR_GS_BASE 0xC0000101
#define MSR_KERNEL_GS_BASE 0xC0000102
OSCPUData gOSBootCPU = {0};
static inline void CPUID(UInt32 leaf, UInt32 subleaf, UInt32 *eax, UInt32 *ebx, UInt32 *ecx, UInt32 *edx) {
__asm__ volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf), "c"(subleaf)
);
}
static inline void WRMSR(UInt32 msr, UInt64 val) {
UInt32 low = (UInt32)val;
UInt32 high = (UInt32)(val >> 32);
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
}
void OSCPUInitialize(UInt64 kernelStackTop) {
gOSBootCPU.kernelStackPointer = kernelStackTop;
gOSBootCPU.selfAddress = (UInt64)&gOSBootCPU;
WRMSR(MSR_KERNEL_GS_BASE, (UInt64)&gOSBootCPU);
UInt32 eax, ebx, ecx, edx;
CPUID(0, 0, &eax, &ebx, &ecx, &edx);
UInt32* vendorPointer = (UInt32*)gOSBootCPU.vendorID;
vendorPointer[0] = ebx;
vendorPointer[1] = edx;
vendorPointer[2] = ecx;
gOSBootCPU.vendorID[12] = '\0';
CPUID(1, 0, &eax, &ebx, &ecx, &edx);
gOSBootCPU.family = (eax >> 8) & 0xF;
gOSBootCPU.model = (eax >> 4) & 0xF;
if (gOSBootCPU.family == 6 || gOSBootCPU.family == 15) {
gOSBootCPU.model += ((eax >> 16) & 0xF) << 4;
}
if (edx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureFPU;
if (edx & (1 << 4)) gOSBootCPU.features |= kCPUFeatureTSC;
if (edx & (1 << 5)) gOSBootCPU.features |= kCPUFeatureMSR;
if (edx & (1 << 6)) gOSBootCPU.features |= kCPUFeaturePAE;
if (edx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureAPIC;
if (edx & (1 << 12)) gOSBootCPU.features |= kCPUFeatureMTRR;
if (edx & (1 << 25)) gOSBootCPU.features |= kCPUFeatureSSE;
if (edx & (1 << 26)) gOSBootCPU.features |= kCPUFeatureSSE2;
if (ecx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureSSE3;
if (ecx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureSSSE3;
if (ecx & (1 << 19)) gOSBootCPU.features |= kCPUFeatureSSE4_1;
if (ecx & (1 << 20)) gOSBootCPU.features |= kCPUFeatureSSE4_2;
if (ecx & (1 << 28)) gOSBootCPU.features |= kCPUFeatureAVX;
if (ecx & (1 << 29)) gOSBootCPU.features |= kCPUFeatureF16C;
if (ecx & (1 << 30)) gOSBootCPU.features |= kCPUFeatureRDRAND;
if (ecx & (1 << 31)) gOSBootCPU.features |= kCPUFeatureHypervisor;
}
Boolean OSCPUHasFeature(OSCPUFeature feature) {
return (gOSBootCPU.features & feature) != 0;
}
+34
View File
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <PIC.h>
#include <IO.h>
#include <types.h>
UInt16 HALLegacyInterruptControllerRemap() {
UInt8 currentMaster = IOPortRead8(kIOMasterData);
UInt8 currentSlave = IOPortRead8(kIOSlaveData);
// initialization; icw1
IOPortWrite8WithWait(kIOMasterCommand, 0x11);
IOPortWrite8WithWait(kIOSlaveCommand, 0x11);
// icw2
IOPortWrite8WithWait(kIOMasterData, 0x20); // master now controlling idt[32..39]
IOPortWrite8WithWait(kIOSlaveData, 0x28); // idt[40..47]
// icw3
IOPortWrite8WithWait(kIOMasterData, 0x04); // slave on irq2
IOPortWrite8WithWait(kIOSlaveData, 0x02); // assign id = 2 to slave
// icw4; 0x01 -- 8086 mode
IOPortWrite8WithWait(kIOMasterData, 0x01);
IOPortWrite8WithWait(kIOSlaveData, 0x01);
IOPortWrite8WithWait(kIOMasterData, 0xFD); // 1111 1101
// 0 -- means 'on'
IOPortWrite8WithWait(kIOSlaveData, 0xFF); // Everything ON
return ((UInt16) currentMaster << 8) | currentSlave;
}
-72
View File
@@ -1,72 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include "types.h"
#include <cpuinfo.h>
#define MSR_GS_BASE 0xC0000101
#define MSR_KERNEL_GS_BASE 0xC0000102
cpu_info g_cpu = {0};
static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) {
__asm__ volatile("cpuid"
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
: "a"(leaf), "c"(subleaf)
);
}
static inline void wrmsr(u32 msr, u64 val) {
u32 low = (u32)val;
u32 high = (u32)(val >> 32);
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
}
void cpuinfo_init(u64 kernel_stack_top) {
g_cpu.kernel_rsp = kernel_stack_top;
g_cpu.self = (u64)&g_cpu;
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
u32 eax, ebx, ecx, edx;
cpuid(0, 0, &eax, &ebx, &ecx, &edx);
u32* vendor_ptr = (u32*)g_cpu.vendor;
vendor_ptr[0] = ebx;
vendor_ptr[1] = edx;
vendor_ptr[2] = ecx;
g_cpu.vendor[12] = '\0';
cpuid(1, 0, &eax, &ebx, &ecx, &edx);
g_cpu.family = (eax >> 8) & 0xF;
g_cpu.model = (eax >> 4) & 0xF;
if (g_cpu.family == 6 || g_cpu.family == 15) {
g_cpu.model += ((eax >> 16) & 0xF) << 4;
}
if (edx & (1 << 0)) g_cpu.features |= CPU_FEAT_FPU;
if (edx & (1 << 4)) g_cpu.features |= CPU_FEAT_TSC;
if (edx & (1 << 5)) g_cpu.features |= CPU_FEAT_MSR;
if (edx & (1 << 6)) g_cpu.features |= CPU_FEAT_PAE;
if (edx & (1 << 9)) g_cpu.features |= CPU_FEAT_APIC;
if (edx & (1 << 12)) g_cpu.features |= CPU_FEAT_MTRR;
if (edx & (1 << 25)) g_cpu.features |= CPU_FEAT_SSE;
if (edx & (1 << 26)) g_cpu.features |= CPU_FEAT_SSE2;
if (ecx & (1 << 0)) g_cpu.features |= CPU_FEAT_SSE3;
if (ecx & (1 << 9)) g_cpu.features |= CPU_FEAT_SSSE3;
if (ecx & (1 << 19)) g_cpu.features |= CPU_FEAT_SSE4_1;
if (ecx & (1 << 20)) g_cpu.features |= CPU_FEAT_SSE4_2;
if (ecx & (1 << 28)) g_cpu.features |= CPU_FEAT_AVX;
if (ecx & (1 << 29)) g_cpu.features |= CPU_FEAT_F16C;
if (ecx & (1 << 30)) g_cpu.features |= CPU_FEAT_RDRAND;
if (ecx & (1 << 31)) g_cpu.features |= CPU_FEAT_HYPERVISOR;
}
bool cpu_has(u64 feature) {
return (g_cpu.features & feature) != 0;
}
+1 -1
View File
@@ -1,5 +1,5 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2025 0xKarinyash
; Copyright (c) 2026 0xKarinyash
bits 64
-78
View File
@@ -1,78 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// just fucking kill me already
#include <gdt.h>
#define GDT_ENTIRES 7
GDTDescriptor gdt[GDT_ENTIRES];
GDTPtr gdt_ptr;
TSS tss;
u8 double_fault_stack[4096] = {0};
void gdt_set_gate(int num, u64 base, u64 limit, u8 access, u8 gran) {
gdt[num].base_low = (base & 0xFFFF); // left only low 16bit
gdt[num].base_middle = (base >> 16) & 0xFF; // 3rd address byte
gdt[num].base_high = (base >> 24) & 0xFF; // 4th address byte
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19)
gdt[num].granularity |= gran & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags)
gdt[num].access = access;
// fuck intel
}
void write_tss(int num) {
u64 base = (u64)&tss;
u64 limit = sizeof(tss);
u64 access = 0x89; // TSS_PRESENT | TSS_EXECUTABLE | TSS_ACCESSED;
u64 gran = 0;
gdt_set_gate(num, base, limit, access, gran);
*((u64*)&gdt[num+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(u64 gdt_ptr_addr); // entry.asm
void gdt_init() {
gdt_ptr.limit = (sizeof(GDTDescriptor) * GDT_ENTIRES) - 1;
gdt_ptr.base = (u64)&gdt;
// 0: Null
gdt_set_gate(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
gdt_set_gate(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)
gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
// 3: User Data (Ring 3)
// Access: 0xF2 (Present, Ring3, Read/Write)
gdt_set_gate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
// 4: User Code (Ring 3)
// Access: 0xFA (Present, Ring3, RWX)
gdt_set_gate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // zeroifying tss struct
tss.iomap_base = sizeof(TSS);
tss.ist1 = (u64)double_fault_stack + sizeof(double_fault_stack);
write_tss(5);
gdt_flush((u64)&gdt_ptr);
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
}
-82
View File
@@ -1,82 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#include <idt.h>
#include <types.h>
IDTEntry idt[256];
IDTPtr idt_ptr;
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(u64); // asm: lidt [rdi] / ret
void idt_set_gate(int num, u64 handler, u16 sel, u8 flags) {
idt[num].offset_low = handler & 0xFFFF;
idt[num].offset_mid = (handler >> 16) & 0xFFFF;
idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF;
idt[num].selector = sel; // 0x08 (Kernel Code)
idt[num].ist = 0;
idt[num].attributes = flags;
idt[num].reserved = 0;
}
void idt_init() {
idt_ptr.limit = (sizeof(IDTEntry) * 256) - 1;
idt_ptr.base = (u64)&idt;
const u8 flags = 0x8E;
const u8 selector = 0x08;
idt_set_gate(0, (u64)isr0, selector, flags);
idt_set_gate(1, (u64)isr1, selector, flags);
idt_set_gate(2, (u64)isr2, selector, flags);
idt_set_gate(3, (u64)isr3, selector, flags);
idt_set_gate(4, (u64)isr4, selector, flags);
idt_set_gate(5, (u64)isr5, selector, flags);
idt_set_gate(6, (u64)isr6, selector, flags);
idt_set_gate(7, (u64)isr7, selector, flags);
idt_set_gate(8, (u64)isr8, selector, flags);
idt_set_gate(9, (u64)isr9, selector, flags);
idt_set_gate(10, (u64)isr10, selector, flags);
idt_set_gate(11, (u64)isr11, selector, flags);
idt_set_gate(12, (u64)isr12, selector, flags);
idt_set_gate(13, (u64)isr13, selector, flags);
idt_set_gate(14, (u64)isr14, selector, flags);
idt_set_gate(15, (u64)isr15, selector, flags);
idt_set_gate(16, (u64)isr16, selector, flags);
idt_set_gate(17, (u64)isr17, selector, flags);
idt_set_gate(18, (u64)isr18, selector, flags);
idt_set_gate(19, (u64)isr19, selector, flags);
idt_set_gate(20, (u64)isr20, selector, flags);
idt_set_gate(21, (u64)isr21, selector, flags);
idt_set_gate(22, (u64)isr22, selector, flags);
idt_set_gate(23, (u64)isr23, selector, flags);
idt_set_gate(24, (u64)isr24, selector, flags);
idt_set_gate(25, (u64)isr25, selector, flags);
idt_set_gate(26, (u64)isr26, selector, flags);
idt_set_gate(27, (u64)isr27, selector, flags);
idt_set_gate(28, (u64)isr28, selector, flags);
idt_set_gate(29, (u64)isr29, selector, flags);
idt_set_gate(30, (u64)isr30, selector, flags);
idt_set_gate(31, (u64)isr31, selector, flags);
idt[8].ist = 1; // TSS
idt[13].ist = 1;
idt[14].ist = 1;
idt_set_gate(32, (u64)irq0, selector, flags);
idt_set_gate(33, (u64)irq1, selector, flags);
__asm__ volatile ("lidt %0" : : "m"(idt_ptr));
}

Some files were not shown because too many files have changed in this diff Show More