Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa6b7924e2 | |||
| 4e10985909 | |||
| c72dbc763c | |||
| 02b36283a5 | |||
| e21f5ef52f | |||
| 2be7d3bd46 | |||
| 02dc35f0df | |||
| ee67cef4f8 | |||
| c30d57d06e | |||
| 4e6794a6c2 | |||
| e63983c95d | |||
| e323e91dac | |||
| 52d0bfeaae | |||
| ae7e1a91d0 | |||
| c5741374cd | |||
| 385b7d7a13 | |||
| 3f95b6d282 | |||
| 92aaa47435 | |||
| caf2d2b4a8 | |||
| 888bc5abdd | |||
| 9c103218d0 | |||
| 21270a3cc8 | |||
| 7d32444da2 | |||
| 55ea8fc533 | |||
| 3f3a026432 | |||
| 8a6994ebd8 | |||
| 3525c81d9e | |||
| d01a91c993 |
+4
-1
@@ -1,4 +1,7 @@
|
|||||||
.cache
|
.cache
|
||||||
build*
|
build*
|
||||||
.venv
|
.venv
|
||||||
initrd/image.cpio
|
initrd/image.cpio
|
||||||
|
initramfs/*
|
||||||
|
|
||||||
|
target
|
||||||
+3
-2
@@ -3,6 +3,7 @@ build
|
|||||||
.venv
|
.venv
|
||||||
kernel/data
|
kernel/data
|
||||||
*.md
|
*.md
|
||||||
tools/
|
|
||||||
bootloader/
|
bootloader/
|
||||||
bootloader/src/uefi
|
bootloader/src/uefi
|
||||||
|
initramfs/
|
||||||
|
kernel/inc/Data
|
||||||
+37
-16
@@ -6,32 +6,52 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
|||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
|
||||||
add_subdirectory(bootloader)
|
|
||||||
add_subdirectory(kernel)
|
|
||||||
|
|
||||||
find_program(MCOPY_EXE mcopy)
|
find_program(MCOPY_EXE mcopy)
|
||||||
find_program(MKFS_EXE mkfs.fat)
|
find_program(MKFS_EXE mkfs.fat)
|
||||||
find_program(CPIO_EXE cpio)
|
find_program(CPIO_EXE cpio)
|
||||||
find_program(QEMU_EXE qemu-system-x86_64)
|
find_program(QEMU_EXE qemu-system-x86_64)
|
||||||
set(OVMF_PATH "/usr/share/edk2/ovmf/OVMF_CODE.fd" CACHE FILEPATH "Path to OVMF bios")
|
set(OVMF_PATH "/usr/share/edk2/ovmf/OVMF_CODE.fd" CACHE FILEPATH "Path to OVMF bios")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND git describe --tags --always --dirty
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE KERNEL_VERSION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT KERNEL_VERSION)
|
||||||
|
set(KERNEL_VERSION "unknown-version")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Building termOS version: ${KERNEL_VERSION}")
|
||||||
|
add_compile_definitions(TERMOS_VERSION=\"${KERNEL_VERSION}\")
|
||||||
|
|
||||||
|
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)
|
if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
|
||||||
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
|
add_custom_command(
|
||||||
|
|
||||||
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(
|
|
||||||
OUTPUT ${INITRAMFS_CPIO_FILE}
|
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}\""
|
COMMAND sh -c "find . -mindepth 1 ! -name '*.cpio' -print0 | ${CPIO_EXE} --null -ov -H newc > \"${INITRAMFS_CPIO_FILE}\""
|
||||||
WORKING_DIRECTORY ${INITRAMFS_SRC_DIR}
|
WORKING_DIRECTORY ${VOLUME_ROOT}
|
||||||
DEPENDS ${INIT_FILES}
|
DEPENDS ${SYSTEM_SERVICES}
|
||||||
VERBATIM
|
VERBATIM
|
||||||
COMMENT "Packing initramfs to cpio..."
|
COMMENT "Packing StartupVolume to cpio..."
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${IMG_FILE}
|
OUTPUT ${IMG_FILE}
|
||||||
COMMAND dd if=/dev/zero of=${IMG_FILE} bs=1M count=64 status=none
|
COMMAND dd if=/dev/zero of=${IMG_FILE} bs=1M count=64 status=none
|
||||||
@@ -39,7 +59,7 @@ if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
|
|||||||
COMMAND mmd -i ${IMG_FILE} ::/EFI ::/EFI/BOOT
|
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} $<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} ${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}
|
DEPENDS BOOTX64 kernel ${INITRAMFS_CPIO_FILE}
|
||||||
VERBATIM
|
VERBATIM
|
||||||
COMMENT "Generating bootable image: ${IMG_FILE}"
|
COMMENT "Generating bootable image: ${IMG_FILE}"
|
||||||
@@ -58,6 +78,7 @@ if(QEMU_EXE)
|
|||||||
-net none
|
-net none
|
||||||
-serial stdio
|
-serial stdio
|
||||||
-m 512M
|
-m 512M
|
||||||
|
-s
|
||||||
DEPENDS image
|
DEPENDS image
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
@@ -4,6 +4,39 @@
|
|||||||
<img src='assets/logo.png'>
|
<img src='assets/logo.png'>
|
||||||
</p>
|
</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
@@ -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. |
|
||||||
@@ -4,6 +4,7 @@ set(UEFI_COMPILE_OPTIONS
|
|||||||
-std=c23
|
-std=c23
|
||||||
-target x86_64-unknown-windows-msvc
|
-target x86_64-unknown-windows-msvc
|
||||||
-Wall -Wextra
|
-Wall -Wextra
|
||||||
|
-fno-builtin
|
||||||
$<$<CONFIG:Release>:-Werror>
|
$<$<CONFIG:Release>:-Werror>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#include "uefi.h" // IWYU pragma: keep
|
#include "uefi.h" // IWYU pragma: keep
|
||||||
#include "../../common/bootinfo.h"
|
#include "../../common/bootinfo.h"
|
||||||
@@ -78,11 +78,11 @@ int main()
|
|||||||
efi_file_handle_t* initramfs_file;
|
efi_file_handle_t* initramfs_file;
|
||||||
uintn_t iinfo_size = 0;
|
uintn_t iinfo_size = 0;
|
||||||
efi_file_info_t* ifile_info = nullptr;
|
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)) {
|
if (EFI_ERROR(status)) {
|
||||||
print_initramfs_warning(L"initramfs.cpio is missing");
|
print_initramfs_warning(L"StartupVolume.cpio is missing");
|
||||||
boot_info->initramfs.addr = nullptr;
|
boot_info->initramfs.address = nullptr;
|
||||||
boot_info->initramfs.size = 0;
|
boot_info->initramfs.size = 0;
|
||||||
} else {
|
} else {
|
||||||
status = initramfs_file->GetInfo(initramfs_file, &fi_guid, &iinfo_size, nullptr);
|
status = initramfs_file->GetInfo(initramfs_file, &fi_guid, &iinfo_size, nullptr);
|
||||||
@@ -105,14 +105,14 @@ int main()
|
|||||||
// just fucking kill me
|
// just fucking kill me
|
||||||
uintn_t initramfs_size_read = (uintn_t)initramfs_size;
|
uintn_t initramfs_size_read = (uintn_t)initramfs_size;
|
||||||
initramfs_file->Read(initramfs_file, &initramfs_size_read, (void*)initramfs_addr);
|
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->initramfs.size = initramfs_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_info->framebuffer.base = (uint32_t*)gop->Mode->FrameBufferBase;
|
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.height = gop->Mode->Information->VerticalResolution;
|
||||||
boot_info->framebuffer.width = gop->Mode->Information->HorizontalResolution;
|
boot_info->framebuffer.width = gop->Mode->Information->HorizontalResolution;
|
||||||
boot_info->framebuffer.pitch = gop->Mode->Information->PixelsPerScanLine;
|
boot_info->framebuffer.pitch = gop->Mode->Information->PixelsPerScanLine;
|
||||||
@@ -139,11 +139,11 @@ int main()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_info->mem.descriptor_size = desc_size;
|
boot_info->memoryMap.descriptorSize = desc_size;
|
||||||
boot_info->mem.descriptor_version = desc_version;
|
boot_info->memoryMap.descriptorVersion = desc_version;
|
||||||
boot_info->mem.map_size = map_size;
|
boot_info->memoryMap.mapSize = map_size;
|
||||||
boot_info->mem.map_key = map_key;
|
boot_info->memoryMap.mapKey = map_key;
|
||||||
boot_info->mem.map = map;
|
boot_info->memoryMap.map = map;
|
||||||
|
|
||||||
status = gBS->ExitBootServices(IM, map_key);
|
status = gBS->ExitBootServices(IM, map_key);
|
||||||
if (status == EFI_SUCCESS) {
|
if (status == EFI_SUCCESS) {
|
||||||
|
|||||||
+11
-11
@@ -46,7 +46,7 @@ void __stdio_cleanup(void)
|
|||||||
BS->FreePool(__argvutf8);
|
BS->FreePool(__argvutf8);
|
||||||
#endif
|
#endif
|
||||||
if(__blk_devs) {
|
if(__blk_devs) {
|
||||||
free(__blk_devs);
|
MemoryFree(__blk_devs);
|
||||||
__blk_devs = NULL;
|
__blk_devs = NULL;
|
||||||
__blk_ndevs = 0;
|
__blk_ndevs = 0;
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ int fclose (FILE *__stream)
|
|||||||
if(__stream == (FILE*)__blk_devs[i].bio)
|
if(__stream == (FILE*)__blk_devs[i].bio)
|
||||||
return 1;
|
return 1;
|
||||||
status = __stream->Close(__stream);
|
status = __stream->Close(__stream);
|
||||||
free(__stream);
|
MemoryFree(__stream);
|
||||||
return !EFI_ERROR(status);
|
return !EFI_ERROR(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ err: __stdio_seterrno(status);
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* no need for fclose(f); */
|
/* no need for fclose(f); */
|
||||||
free(f);
|
MemoryFree(f);
|
||||||
return 0;
|
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 */
|
/* workaround a bug in TianoCore, it reports zero size even though the data is in the buffer */
|
||||||
if(handle_size < 1)
|
if(handle_size < 1)
|
||||||
handle_size = (uintn_t)sizeof(handles) / sizeof(efi_handle_t);
|
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) {
|
if(__blk_devs) {
|
||||||
memset(__blk_devs, 0, handle_size * sizeof(block_file_t));
|
memset(__blk_devs, 0, handle_size * sizeof(block_file_t));
|
||||||
for(i = __blk_ndevs = 0; i < handle_size; i++)
|
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;
|
errno = ENODEV;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ret = (FILE*)malloc(sizeof(FILE));
|
ret = (FILE*)MemoryAllocate(sizeof(FILE));
|
||||||
if(!ret) return NULL;
|
if(!ret) return NULL;
|
||||||
/* normally write means read,write,create. But for remove (internal '*' mode), we need read,write without create
|
/* 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
|
* 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);
|
__modes[1] == CL('d') ? EFI_FILE_DIRECTORY : 0);
|
||||||
if(EFI_ERROR(status)) {
|
if(EFI_ERROR(status)) {
|
||||||
err: __stdio_seterrno(status);
|
err: __stdio_seterrno(status);
|
||||||
free(ret); return NULL;
|
MemoryFree(ret); return NULL;
|
||||||
}
|
}
|
||||||
if(__modes[0] == CL('*')) return ret;
|
if(__modes[0] == CL('*')) return ret;
|
||||||
status = ret->GetInfo(ret, &infGuid, &fsiz, &info);
|
status = ret->GetInfo(ret, &infGuid, &fsiz, &info);
|
||||||
if(EFI_ERROR(status)) goto err;
|
if(EFI_ERROR(status)) goto err;
|
||||||
if(__modes[1] == CL('d') && !(info.Attribute & EFI_FILE_DIRECTORY)) {
|
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)) {
|
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('a')) fseek(ret, 0, SEEK_END);
|
||||||
if(__modes[0] == CL('w')) {
|
if(__modes[0] == CL('w')) {
|
||||||
@@ -713,7 +713,7 @@ int sprintf(char_t *dst, const char_t* fmt, ...)
|
|||||||
return ret;
|
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;
|
int ret;
|
||||||
__builtin_va_list args;
|
__builtin_va_list args;
|
||||||
@@ -738,7 +738,7 @@ int vprintf(const char_t* fmt, __builtin_va_list args)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int printf(const char_t* fmt, ...)
|
int ConsolePrint(const char_t* fmt, ...)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
__builtin_va_list args;
|
__builtin_va_list args;
|
||||||
@@ -800,7 +800,7 @@ int getchar_ifany (void)
|
|||||||
return EFI_ERROR(status) ? 0 : key.UnicodeChar;
|
return EFI_ERROR(status) ? 0 : key.UnicodeChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getchar (void)
|
int ConsoleGetCharacter (void)
|
||||||
{
|
{
|
||||||
uintn_t idx;
|
uintn_t idx;
|
||||||
BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &idx);
|
BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &idx);
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ int64_t strtol (const char_t *s, char_t **__endptr, int __base)
|
|||||||
return v * sign;
|
return v * sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *malloc (size_t __size)
|
void *MemoryAllocate (size_t __size)
|
||||||
{
|
{
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
@@ -106,20 +106,20 @@ void *malloc (size_t __size)
|
|||||||
|
|
||||||
void *calloc (size_t __nmemb, 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);
|
if(ret) memset(ret, 0, __nmemb * __size);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *realloc (void *__ptr, size_t __size)
|
void *MemoryReallocate (void *__ptr, size_t __size)
|
||||||
{
|
{
|
||||||
void *ret = NULL;
|
void *ret = NULL;
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
#ifndef UEFI_NO_TRACK_ALLOC
|
#ifndef UEFI_NO_TRACK_ALLOC
|
||||||
uintn_t i;
|
uintn_t i;
|
||||||
#endif
|
#endif
|
||||||
if(!__ptr) return malloc(__size);
|
if(!__ptr) return MemoryAllocate(__size);
|
||||||
if(!__size) { free(__ptr); return NULL; }
|
if(!__size) { MemoryFree(__ptr); return NULL; }
|
||||||
#ifndef UEFI_NO_TRACK_ALLOC
|
#ifndef UEFI_NO_TRACK_ALLOC
|
||||||
/* get the slot which stores the old size for this buffer */
|
/* 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);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free (void *__ptr)
|
void MemoryFree (void *__ptr)
|
||||||
{
|
{
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
#ifndef UEFI_NO_TRACK_ALLOC
|
#ifndef UEFI_NO_TRACK_ALLOC
|
||||||
@@ -341,7 +341,7 @@ uint8_t *getenv(char_t *name, uintn_t *len)
|
|||||||
#else
|
#else
|
||||||
status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
|
status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
|
||||||
#endif
|
#endif
|
||||||
if(EFI_ERROR(status) || *len < 1 || !(ret = malloc((*len) + 1))) {
|
if(EFI_ERROR(status) || *len < 1 || !(ret = MemoryAllocate((*len) + 1))) {
|
||||||
*len = 0;
|
*len = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl)
|
|||||||
return NULL;
|
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;
|
char_t *s = dst;
|
||||||
if(src && dst && src != 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)
|
char_t *strdup(const char_t *s)
|
||||||
{
|
{
|
||||||
size_t i = (strlen(s)+1) * sizeof(char_t);
|
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);
|
if(s2 != NULL) memcpy(s2, (const void*)s, i);
|
||||||
return s2;
|
return s2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1314,10 +1314,10 @@ typedef int (*__compar_fn_t) (const void *, const void *);
|
|||||||
extern int atoi (const char_t *__nptr);
|
extern int atoi (const char_t *__nptr);
|
||||||
extern int64_t atol (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 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 *calloc (size_t __nmemb, size_t __size);
|
||||||
extern void *realloc (void *__ptr, size_t __size);
|
extern void *MemoryReallocate (void *__ptr, size_t __size);
|
||||||
extern void free (void *__ptr);
|
extern void MemoryFree (void *__ptr);
|
||||||
extern void abort (void);
|
extern void abort (void);
|
||||||
extern void exit (int __status);
|
extern void exit (int __status);
|
||||||
/* exit Boot Services function. Returns 0 on success. */
|
/* 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 long int ftell (FILE *__stream);
|
||||||
extern int feof (FILE *__stream);
|
extern int feof (FILE *__stream);
|
||||||
extern int fprintf (FILE *__stream, const char_t *__format, ...);
|
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 sprintf (char_t *__s, const char_t *__format, ...);
|
||||||
extern int vfprintf (FILE *__s, const char_t *__format, __builtin_va_list __arg);
|
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 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 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 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 */
|
/* non-blocking, only returns UNICODE if there's any key pressed, 0 otherwise */
|
||||||
extern int getchar_ifany (void);
|
extern int getchar_ifany (void);
|
||||||
extern int putchar (int __c);
|
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);
|
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 *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);
|
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 *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 *strcat (char_t *__dest, const char_t *__src);
|
||||||
extern char_t *strncat (char_t *__dest, const char_t *__src, size_t __n);
|
extern char_t *strncat (char_t *__dest, const char_t *__src, size_t __n);
|
||||||
|
|||||||
+21
-21
@@ -1,37 +1,37 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef unsigned int bi_u32;
|
typedef unsigned int BIUInt32;
|
||||||
typedef unsigned long long bi_u64;
|
typedef unsigned long long BIUInt64;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bi_u32* base;
|
BIUInt32* base;
|
||||||
bi_u64 base_size;
|
BIUInt64 baseSize;
|
||||||
bi_u64 width;
|
BIUInt64 width;
|
||||||
bi_u64 height;
|
BIUInt64 height;
|
||||||
bi_u64 pitch;
|
BIUInt64 pitch;
|
||||||
} BI_Framebuffer;
|
} BIFramebuffer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* map;
|
void* map;
|
||||||
bi_u64 map_size;
|
BIUInt64 mapSize;
|
||||||
bi_u64 descriptor_size;
|
BIUInt64 descriptorSize;
|
||||||
bi_u32 map_key;
|
BIUInt32 mapKey;
|
||||||
bi_u32 descriptor_version;
|
BIUInt32 descriptorVersion;
|
||||||
} BI_MemoryMap;
|
} BIMemoryMap;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void* addr;
|
void* address;
|
||||||
bi_u64 size;
|
BIUInt64 size;
|
||||||
} BI_Initramfs;
|
} BIInitramfs;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bi_u64 magic;
|
BIUInt64 magic;
|
||||||
BI_Framebuffer framebuffer;
|
BIFramebuffer framebuffer;
|
||||||
BI_MemoryMap mem;
|
BIMemoryMap memoryMap;
|
||||||
BI_Initramfs initramfs;
|
BIInitramfs initramfs;
|
||||||
} Bootinfo;
|
} Bootinfo;
|
||||||
|
|
||||||
#define BOOTINFO_MAGIC 0x7465726D // term
|
#define BOOTINFO_MAGIC 0x7465726D // term
|
||||||
@@ -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;
|
||||||
@@ -1 +0,0 @@
|
|||||||
Meow!!
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Nyaaa
|
|
||||||
+12
-9
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
project(termOS_krn LANGUAGES C ASM_NASM)
|
project(dewar LANGUAGES C ASM_NASM)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 23)
|
set(CMAKE_C_STANDARD 23)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
@@ -9,7 +9,7 @@ if (NOT DEFINED ARCH)
|
|||||||
set(ARCH "x86_64")
|
set(ARCH "x86_64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "TermOS Kernel: Building for architecture '${ARCH}'")
|
message(STATUS "Dewar kernel: Building for architecture '${ARCH}'")
|
||||||
|
|
||||||
|
|
||||||
file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
|
file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
|
||||||
@@ -18,13 +18,16 @@ file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
|
|||||||
"src/arch/${ARCH}/*.c"
|
"src/arch/${ARCH}/*.c"
|
||||||
"src/arch/${ARCH}/*.asm"
|
"src/arch/${ARCH}/*.asm"
|
||||||
|
|
||||||
"src/core/*.c"
|
"src/OS/*.c"
|
||||||
"src/drivers/*.c"
|
"src/OS/Exec/*.c"
|
||||||
"src/mm/*.c"
|
"src/OS/Services/*.c"
|
||||||
"src/shell/*.c"
|
"src/lib/*.c"
|
||||||
"src/fs/*.c"
|
"src/IO/*.c"
|
||||||
|
"src/VM/*.c"
|
||||||
|
"src/KSH/*.c"
|
||||||
|
"src/FS/*.c"
|
||||||
|
|
||||||
"data/*.c"
|
"Data/*.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(kernel ${KERNEL_SOURCES})
|
add_executable(kernel ${KERNEL_SOURCES})
|
||||||
@@ -33,7 +36,7 @@ target_include_directories(kernel PRIVATE
|
|||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../common"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../common"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
"${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/inc/arch/${ARCH}"
|
"${CMAKE_CURRENT_SOURCE_DIR}/inc/arch/${ARCH}"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/data"
|
"${CMAKE_CURRENT_SOURCE_DIR}/Data"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(kernel PRIVATE
|
target_compile_options(kernel PRIVATE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// font8x16 bitmap font
|
#pragma once
|
||||||
// Source: https://github.com/hubenchang0515/font8x16
|
#include <types.h>
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
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, 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, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x01,
|
||||||
{ 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x02,
|
{ 0x00, 0x00, 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
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
// cats licensed to their authors
|
// cats licensed to their authors
|
||||||
// i took it from https://www.asciiart.eu/animals/cats
|
// 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
|
// Huge thanks to https://t.me/kinolenta2004 for this amazing logo
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <drivers/shitgui.h>
|
#include <IO/IOGraphics.h>
|
||||||
|
|
||||||
#define LOGO_TRANSPARENCY_KEY 0xFF00FF
|
#define LOGO_TRANSPARENCY_KEY 0xFF00FF
|
||||||
|
|
||||||
// Image: 100x100
|
// 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,
|
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,
|
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
|
||||||
};
|
};
|
||||||
|
|
||||||
static SG_Image logo_img = {
|
static IOGraphicsImage logoImage = {
|
||||||
.width = 100,
|
.size = {100, 100},
|
||||||
.height = 100,
|
.buffer = (UInt32*)logo_data
|
||||||
.buffer = (u32*)logo_data
|
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
#include <FS/VFS.h>
|
||||||
|
|
||||||
|
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||||
|
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize);
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef enum FSVNodeFlags {
|
||||||
|
kFSVNodeFlagFile = 0x01,
|
||||||
|
kFSVNodeFlagDirectory = 0x02,
|
||||||
|
} FSVNodeFlags;
|
||||||
|
|
||||||
|
typedef struct FSVNode FSVNode;
|
||||||
|
|
||||||
|
typedef struct FSVNodeOperations {
|
||||||
|
UInt64 (*read)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||||
|
UInt64 (*write)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||||
|
void (*open)(FSVNode* node);
|
||||||
|
void (*close)(FSVNode* node);
|
||||||
|
FSVNode* (*findDirectory)(FSVNode* node, char* name);
|
||||||
|
} FSVNodeOperations;
|
||||||
|
|
||||||
|
typedef struct FSVNode {
|
||||||
|
char name[256];
|
||||||
|
UInt32 protectionMask;
|
||||||
|
UInt32 ownerIdentifier;
|
||||||
|
UInt32 groupIdentifier;
|
||||||
|
UInt32 flags;
|
||||||
|
UInt32 inodeIdentifier;
|
||||||
|
UInt64 dataLength;
|
||||||
|
|
||||||
|
FSVNodeOperations* operations;
|
||||||
|
void* implementationData;
|
||||||
|
|
||||||
|
struct FSVNode* mountPoint;
|
||||||
|
struct FSVNode* childNode;
|
||||||
|
struct FSVNode* nextNode;
|
||||||
|
} FSVNode;
|
||||||
|
|
||||||
|
void FSVirtualFileSystemInitialize(FSVNode* rootNode);
|
||||||
|
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||||
|
FSVNode* FSVirtualFileSystemOpenPath(const char* path);
|
||||||
|
void FSVNodeClose(FSVNode* node);
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <IO/IOGraphics.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kIOConsoleColorRed = 0xFF5555,
|
||||||
|
kIOConsoleColorVeryRed = 0xFF0000,
|
||||||
|
kIOConsoleColorGreen = 0x08bf39,
|
||||||
|
kIOConsoleColorVeryGreen = 0x00FF00,
|
||||||
|
kIOConsoleColorTurqoise = 0x5effaf,
|
||||||
|
kIOConsoleColorBlue = 0x5555FF,
|
||||||
|
kIOConsoleColorVeryBlue = 0x0000FF,
|
||||||
|
kIOConsoleColorLightBlue = 0x3890e8,
|
||||||
|
kIOConsoleColorYellow = 0xFFFF55,
|
||||||
|
kIOConsoleColorCyan = 0x55FFFF,
|
||||||
|
kIOConsoleColorMagneta = 0xFF55FF,
|
||||||
|
kIOConsoleColorBlack = 0x000000,
|
||||||
|
kIOConsoleColorWhite = 0xFFFFFF,
|
||||||
|
kIOConsoleColorPink = 0xFFA3B1,
|
||||||
|
};
|
||||||
|
|
||||||
|
void IOConsoleInit(IOGraphicsContext* context);
|
||||||
|
UInt64 IOConsoleGetColors();
|
||||||
|
void IOConsoleClear(IOGraphicsColor color);
|
||||||
|
IOGraphicsContext* IOConsoleGetGraphicsContext();
|
||||||
|
IOGraphicsSize IOConsoleGetDimensions();
|
||||||
|
void IOConsoleSetForegroundColor(IOGraphicsColor color);
|
||||||
|
void IOConsoleSetDefaultForegroundColor(UInt32 color);
|
||||||
|
void IOConsoleSetCursorPosition(IOGraphicsPoint* point);
|
||||||
|
void IOConsoleReadLine(char* buffer, UInt32 limit);
|
||||||
|
void IOConsolePutcharacter(char character);
|
||||||
|
void IOConsolePrint(const char *string);
|
||||||
|
void IOConsoleLog(const char *fmt, ...);
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
// RIP shitgui -- you started it all
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef UInt32 IOGraphicsColor;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt32 x;
|
||||||
|
UInt32 y;
|
||||||
|
} IOGraphicsPoint;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt32 width;
|
||||||
|
UInt32 height;
|
||||||
|
} IOGraphicsSize;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile UInt32* framebuffer;
|
||||||
|
IOGraphicsSize dimensions;
|
||||||
|
UInt32 pixelsPerScanLine;
|
||||||
|
} IOGraphicsContext;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
IOGraphicsColor* buffer;
|
||||||
|
IOGraphicsSize size;
|
||||||
|
} IOGraphicsImage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
IOGraphicsSize size;
|
||||||
|
const unsigned char* baseAddress;
|
||||||
|
} IOGraphicsFont;
|
||||||
|
|
||||||
|
|
||||||
|
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point);
|
||||||
|
|
||||||
|
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image);
|
||||||
|
|
||||||
|
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point,
|
||||||
|
IOGraphicsSize* size, IOGraphicsColor color);
|
||||||
|
|
||||||
|
void IOGraphicsDrawCharacter(
|
||||||
|
IOGraphicsContext* context,
|
||||||
|
IOGraphicsPoint* point,
|
||||||
|
char character,
|
||||||
|
IOGraphicsColor color,
|
||||||
|
IOGraphicsFont* font
|
||||||
|
);
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kIOKeyboardBufferSize = 256,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OSSpinlock lock;
|
||||||
|
char buffer[kIOKeyboardBufferSize];
|
||||||
|
volatile UInt16 head;
|
||||||
|
volatile UInt16 tail;
|
||||||
|
} IOKeyboardController;
|
||||||
|
|
||||||
|
extern IOKeyboardController gIOKeyboardController;
|
||||||
|
|
||||||
|
void IOKeyboardInterruptsHandler();
|
||||||
|
char IOKeyboardGetCharacter();
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int IOSerialInit();
|
||||||
|
void IOSerialWriteChar(char character);
|
||||||
|
void IOSerialWrite(const char *string);
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
void IOTimerInitialize(UInt32 freq);
|
||||||
|
UInt64 IOTimerInterruptsHandler(CPURegisters *regs);
|
||||||
|
UInt64 IOTimerGetTicks();
|
||||||
@@ -0,0 +1,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();
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
u64 shitrand();
|
UInt64 KSHDebug();
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void KSHEntry();
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
|
||||||
|
UInt64 HOTLoad(OSProcess* process, UInt8* data);
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName);
|
||||||
|
void init_task_entry();
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame);
|
||||||
|
__attribute__((noreturn)) void OSPanic(const char* msg);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef enum OSProcessState {
|
||||||
|
kOSProcessStateDead,
|
||||||
|
kOSProcessStateRunning,
|
||||||
|
kOSProcessStateReady,
|
||||||
|
kOSProcessStateBlocked,
|
||||||
|
kOSProcessStateSleeping,
|
||||||
|
} OSProcessState;
|
||||||
|
|
||||||
|
typedef struct OSProcess {
|
||||||
|
UInt64 processId;
|
||||||
|
OSProcessState state;
|
||||||
|
UInt64 physicalPML4;
|
||||||
|
struct OSProcess* parent;
|
||||||
|
char name[32];
|
||||||
|
UInt64 heapStartPointer;
|
||||||
|
UInt64 heapCurrentPointer;
|
||||||
|
} OSProcess;
|
||||||
|
|
||||||
|
typedef struct OSTask {
|
||||||
|
UInt64 stackPointer;
|
||||||
|
struct OSTask* next;
|
||||||
|
UInt32 id;
|
||||||
|
UInt32 sleepTicks;
|
||||||
|
OSProcessState taskState; // reusing process_state cuz wn
|
||||||
|
UInt64 kernelStackTop;
|
||||||
|
void* kernelStackBase;
|
||||||
|
OSProcess* process;
|
||||||
|
Int32 waitingForProcess;
|
||||||
|
} OSTask;
|
||||||
|
|
||||||
|
void OSSchedulerInitialize();
|
||||||
|
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer);
|
||||||
|
UInt64 OSSchedulerNext(UInt64 currentStackPointer);
|
||||||
|
void OSSchedulerYield(UInt64 ticks);
|
||||||
|
void OSSchedulerBlock(UInt32 processID);
|
||||||
|
void OSSchedulerWakeup(UInt32 processID);
|
||||||
|
void OSSchedulerTerminate(); // suicide
|
||||||
|
|
||||||
|
extern OSTask* gOSSchedulerCurrentTask;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct OSSpinlock {
|
||||||
|
volatile UInt32 lockValue;
|
||||||
|
} OSSpinlock;
|
||||||
|
|
||||||
|
typedef struct OSSpinlockState {
|
||||||
|
Boolean interruptsEnabled;
|
||||||
|
} OSSpinlockState;
|
||||||
|
|
||||||
|
void OSSpinlockLock(OSSpinlock* lock);
|
||||||
|
void OSSpinlockUnlock(OSSpinlock* lock);
|
||||||
|
void OSSpinlockLockIRQ(OSSpinlock* lock, OSSpinlockState* state);
|
||||||
|
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState* state);
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length);
|
||||||
|
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
UInt64 OSServiceMemoryAllocate(UInt64 size);
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
Int32 OSServiceProcessExit(Int32 code);
|
||||||
|
Int32 OSServiceProcessSpawn(const char* path);
|
||||||
|
Int32 OSServiceProcessWait(UInt64 pid);
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kVMKernelHeapStart = 0xFFFFFFFFC0000000,
|
||||||
|
kVMHeapSizePages = 1024,
|
||||||
|
kVMHeapBlockHeaderMagic = 0x1CE
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START)
|
||||||
|
#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START)
|
||||||
|
typedef struct VMHeapBlockHeader {
|
||||||
|
UInt64 magic;
|
||||||
|
struct VMHeapBlockHeader* next;
|
||||||
|
struct VMHeapBlockHeader* previous;
|
||||||
|
UInt64 size;
|
||||||
|
bool isFree;
|
||||||
|
} VMHeapBlockHeader;
|
||||||
|
|
||||||
|
void VMHeapInitialize();
|
||||||
|
void* VMHeapAllocate(UInt64 size);
|
||||||
|
void VMHeapFree(void* ptr);
|
||||||
|
void* VMHeapResize(void* ptr, UInt64 newSize);
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "bootinfo.h"
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#define kVMPageSize 4096
|
||||||
|
#define kVMSafeSpaceStartAddress 0x100000
|
||||||
|
#define kVMBlocksPerByte 8
|
||||||
|
|
||||||
|
#define BITMAP_BYTE_INDEX(address) ((address / kVMPageSize) / kVMBlocksPerByte)
|
||||||
|
#define BITMAP_BIT_OFFSET(address) ((address / kVMPageSize) % kVMBlocksPerByte)
|
||||||
|
#define BITMAP_TEST(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] & (1 << BITMAP_BIT_OFFSET(address)))
|
||||||
|
#define BITMAP_SET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] |= (1 << BITMAP_BIT_OFFSET(address)))
|
||||||
|
#define BITMAP_UNSET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] &= ~(1 << BITMAP_BIT_OFFSET(address)))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt32 type;
|
||||||
|
UInt32 padding;
|
||||||
|
UInt64 physicalStart;
|
||||||
|
UInt64 virtualStart;
|
||||||
|
UInt64 pageCount;
|
||||||
|
UInt64 attributes;
|
||||||
|
} __attribute__((packed)) OSMemoryDescriptor;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
kOSMemoryTypeReserved,
|
||||||
|
kOSMemoryTypeLoaderCode,
|
||||||
|
kOSMemoryTypeLoaderData,
|
||||||
|
kOSMemoryTypeBootServicesCode,
|
||||||
|
kOSMemoryTypeBootServicesData,
|
||||||
|
kOSMemoryTypeRuntimeServicesCode,
|
||||||
|
kOSMemoryTypeRuntimeServicesData,
|
||||||
|
kOSMemoryTypeConventional,
|
||||||
|
kOSMemoryTypeUnusable,
|
||||||
|
kOSMemoryTypeACPIReclaim,
|
||||||
|
kOSMemoryTypeACPINonVolatile,
|
||||||
|
kOSMemoryTypeMappedIO,
|
||||||
|
kOSMemoryTypeMappedIOPortSpace,
|
||||||
|
kOSMemoryTypePalCode,
|
||||||
|
kOSMemoryTypePersistent,
|
||||||
|
kOSMemoryTypeMax
|
||||||
|
} OSMemoryType;
|
||||||
|
|
||||||
|
UInt64 VMPhysicalMemoryGetTotalMemorySize();
|
||||||
|
void VMPhysicalMemoryInitialize(BIMemoryMap* mmap);
|
||||||
|
void* VMPhysicalMemoryAllocatePage();
|
||||||
|
void VMPhysicalMemoryFreePage(void* addr);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "bootinfo.h"
|
#include "bootinfo.h"
|
||||||
@@ -35,5 +35,9 @@
|
|||||||
#define HHDM_TO_PHYS(virt) ((virt) - HHDM_OFFSET)
|
#define HHDM_TO_PHYS(virt) ((virt) - HHDM_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
void vmm_init(Bootinfo* info);
|
void VMVirtualMemoryInitialize(Bootinfo* info);
|
||||||
u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags);
|
UInt64* VMVirtualMemoryMapPage(UInt64* PML4, UInt64 physical, UInt64 virtual, UInt64 flags);
|
||||||
|
UInt64 VMVirtualMemoryCreateAddressSpace();
|
||||||
|
UInt64 VMGetCurrentCR3();
|
||||||
|
void VMLoadCR3(UInt64 PML4Address);
|
||||||
|
void VMVirtualMemorySetupUserStack(UInt64* physicalPML4);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#define kHALGDTEntries 7
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt16 limitLow;
|
||||||
|
UInt16 baseLow;
|
||||||
|
UInt8 baseMiddle;
|
||||||
|
UInt8 access;
|
||||||
|
UInt8 granularity;
|
||||||
|
UInt8 baseHigh;
|
||||||
|
} __attribute__((packed)) HALGlobalDescriptorTable;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt16 limit;
|
||||||
|
UInt64 base;
|
||||||
|
} __attribute__((packed)) HALGlobalDescriptorTablePointer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt32 reserved0;
|
||||||
|
UInt64 rsp0;
|
||||||
|
UInt64 rsp1;
|
||||||
|
UInt64 rsp2;
|
||||||
|
UInt64 reserved1;
|
||||||
|
UInt64 ist1;
|
||||||
|
UInt64 ist2;
|
||||||
|
UInt64 ist3;
|
||||||
|
UInt64 ist4;
|
||||||
|
UInt64 ist5;
|
||||||
|
UInt64 ist6;
|
||||||
|
UInt64 ist7;
|
||||||
|
UInt64 reserved2;
|
||||||
|
UInt16 reserved3;
|
||||||
|
UInt16 iomapBase;
|
||||||
|
} __attribute__((packed)) HALTaskStateSegment;
|
||||||
|
|
||||||
|
|
||||||
|
extern HALTaskStateSegment gHALTaskStateSegment;
|
||||||
|
|
||||||
|
void HALGlobalDescriptorTableInitialize();
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt16 offsetLow;
|
||||||
|
UInt16 selector;
|
||||||
|
UInt8 ist;
|
||||||
|
UInt8 attributes;
|
||||||
|
UInt16 offsetMid;
|
||||||
|
UInt32 offsetHigh;
|
||||||
|
UInt32 reserved;
|
||||||
|
} __attribute__((packed)) HALInterruptsDescriptorTableEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt16 limit;
|
||||||
|
UInt64 base;
|
||||||
|
} __attribute__((packed)) HALInterruptsDescriptorTablePointer;
|
||||||
|
|
||||||
|
void HALInterruptsDescriptorTableInitialize();
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kIOMasterCommand = 0x20,
|
||||||
|
kIOMasterData = 0x21,
|
||||||
|
kIOSlaveCommand = 0xA0,
|
||||||
|
kIOSlaveData = 0xA1,
|
||||||
|
kIOPortWaitAddress = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void IOPortWrite8(UInt16 port, UInt8 val) {
|
||||||
|
__asm__ volatile(
|
||||||
|
"outb %0, %1"
|
||||||
|
:
|
||||||
|
: "a"(val),
|
||||||
|
"Nd"(port) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned char IOPortRead8(UInt16 port) {
|
||||||
|
unsigned char ret;
|
||||||
|
__asm__ volatile(
|
||||||
|
"inb %1, %0"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "Nd"(port)
|
||||||
|
);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sending junk to 0x80 (unused) to skip few tacts
|
||||||
|
// not ideal i know
|
||||||
|
static inline void IOSynchronizeBus() {
|
||||||
|
IOPortWrite8(kIOPortWaitAddress, 0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void IOPortWrite8WithWait(UInt16 port, UInt8 val) {
|
||||||
|
IOPortWrite8(port, val);
|
||||||
|
IOSynchronizeBus();
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
kCPUFeatureFPU = (1ULL << 0),
|
||||||
|
kCPUFeatureTSC = (1ULL << 1),
|
||||||
|
kCPUFeatureMSR = (1ULL << 2),
|
||||||
|
kCPUFeatureAPIC = (1ULL << 3),
|
||||||
|
kCPUFeatureMTRR = (1ULL << 4),
|
||||||
|
kCPUFeaturePAE = (1ULL << 5),
|
||||||
|
|
||||||
|
kCPUFeatureSSE = (1ULL << 10),
|
||||||
|
kCPUFeatureSSE2 = (1ULL << 11),
|
||||||
|
kCPUFeatureSSE3 = (1ULL << 12),
|
||||||
|
kCPUFeatureSSSE3 = (1ULL << 13),
|
||||||
|
kCPUFeatureSSE4_1 = (1ULL << 14),
|
||||||
|
kCPUFeatureSSE4_2 = (1ULL << 15),
|
||||||
|
|
||||||
|
kCPUFeatureAVX = (1ULL << 20),
|
||||||
|
kCPUFeatureF16C = (1ULL << 21),
|
||||||
|
kCPUFeatureRDRAND = (1ULL << 22),
|
||||||
|
|
||||||
|
kCPUFeatureHypervisor = (1ULL << 30)
|
||||||
|
} OSCPUFeature;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UInt64 userStackPointer;
|
||||||
|
UInt64 kernelStackPointer;
|
||||||
|
UInt64 selfAddress;
|
||||||
|
|
||||||
|
UInt64 features;
|
||||||
|
char vendorID[13];
|
||||||
|
UInt32 family;
|
||||||
|
UInt32 model;
|
||||||
|
} OSCPUData;
|
||||||
|
|
||||||
|
extern OSCPUData gOSBootCPU;
|
||||||
|
|
||||||
|
void OSCPUInitialize(UInt64 kernelStackTop);
|
||||||
|
Boolean OSCPUHasFeature(OSCPUFeature feature);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
u16 pic_remap();
|
UInt16 HALLegacyInterruptControllerRemap();
|
||||||
@@ -1,40 +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;
|
|
||||||
|
|
||||||
void gdt_init();
|
|
||||||
@@ -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();
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kHALModelSpecificRegisterExtendedFeatureEnable = 0xC0000080, // EFER
|
||||||
|
kHALModelSpecificRegisterSystemCallTarget = 0xC0000081, // STAR
|
||||||
|
kHALModelSpecificRegisterLongSystemCallTarget = 0xC0000082, // LSTAR
|
||||||
|
kHALModelSpecificRegisterSystemCallFlagMask = 0xC0000084, // FMASK
|
||||||
|
kHALModelSpecificRegisterGSBase = 0xC0000101, // GS_BASE
|
||||||
|
kHALModelSpecificRegisterKernelGSBase = 0xC0000102 // KERNEL_GS_BASE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kHALEFERSystemCallExtensionsEnable = 0x01 // SCE
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SYS_EXIT,
|
||||||
|
SYS_SPAWN,
|
||||||
|
SYS_MEM,
|
||||||
|
SYS_WRITE,
|
||||||
|
SYS_READ,
|
||||||
|
SYS_WAIT,
|
||||||
|
} Services;
|
||||||
|
|
||||||
|
void OSServicesInitialize();
|
||||||
@@ -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[];
|
|
||||||
@@ -1,16 +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;
|
|
||||||
} task_t;
|
|
||||||
|
|
||||||
void sched_init();
|
|
||||||
task_t* sched_spawn(void(*entry)());
|
|
||||||
u64 sched_next(u64 curr_rsp);
|
|
||||||
void yield(u64 ticks);
|
|
||||||
@@ -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);
|
|
||||||
|
|
||||||
@@ -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);
|
|
||||||
@@ -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();
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
extern u8 font8x16[128][16];
|
|
||||||
@@ -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();
|
|
||||||
@@ -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);
|
|
||||||
@@ -1,41 +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;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SG_Context *ctx;
|
|
||||||
SG_Point pos;
|
|
||||||
const char *title;
|
|
||||||
} SG_Window;
|
|
||||||
|
|
||||||
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);
|
|
||||||
SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position);
|
|
||||||
void composer_task();
|
|
||||||
@@ -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();
|
|
||||||
@@ -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);
|
|
||||||
@@ -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
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ static inline int abs(int n) {
|
|||||||
return (n < 0) ? -n : n;
|
return (n < 0) ? -n : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline i64 i64abs(i64 n) {
|
static inline Int64 i64abs(Int64 n) {
|
||||||
return (n < 0) ? -n : n;
|
return (n < 0) ? -n : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
u64 debug();
|
void RandInitialize();
|
||||||
|
UInt64 Rand();
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <IO/IOGraphics.h>
|
||||||
|
|
||||||
|
void SplashShow(IOGraphicsContext* IOGraphicsContextPointer);
|
||||||
|
|
||||||
@@ -0,0 +1,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);
|
||||||
@@ -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);
|
|
||||||
@@ -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);
|
|
||||||
@@ -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);
|
|
||||||
@@ -1,13 +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();
|
|
||||||
int rectest(int a);
|
|
||||||
@@ -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
@@ -1,57 +1,26 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef unsigned char u8;
|
typedef unsigned char UInt8;
|
||||||
typedef unsigned short u16;
|
typedef unsigned short UInt16;
|
||||||
typedef unsigned int u32;
|
typedef unsigned int UInt32;
|
||||||
typedef unsigned long long u64;
|
typedef unsigned long long UInt64;
|
||||||
|
|
||||||
typedef signed char i8;
|
typedef signed char Int8;
|
||||||
typedef signed short i16;
|
typedef signed short Int16;
|
||||||
typedef signed int i32;
|
typedef signed int Int32;
|
||||||
typedef signed long long i64;
|
typedef signed long long Int64;
|
||||||
|
|
||||||
typedef u64 usize;
|
typedef UInt64 Size;
|
||||||
typedef u64 uintptr_t;
|
typedef UInt64 uintptr_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 rax, rbx, rcx, rdx, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; // Pushed by us
|
UInt64 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
|
UInt64 interruptNumber, errorCode; // Pushed by macro
|
||||||
u64 rip, cs, rflags, rsp, ss; // Pushed by CPU
|
UInt64 rip, cs, rflags, rsp, ss; // Pushed by CPU
|
||||||
} Registers;
|
} 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 {
|
#define Boolean _Bool
|
||||||
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
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
Copyright (c) 2025 0xKarinyash */
|
Copyright (c) 2026 0xKarinyash */
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <FS/CPIO.h>
|
||||||
|
#include <FS/VFS.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <VM/Heap.h>
|
||||||
|
#include <IO/IOConsole.h>
|
||||||
|
|
||||||
|
#define FSCPIO_ALIGN4(x) (((x) + 3) & ~3)
|
||||||
|
|
||||||
|
typedef struct FSCPIOHeader {
|
||||||
|
char magic[6];
|
||||||
|
char inode[8];
|
||||||
|
char mode[8];
|
||||||
|
char userIdentifier[8];
|
||||||
|
char groupIdentifier[8];
|
||||||
|
char linkCount[8];
|
||||||
|
char modificationTime[8];
|
||||||
|
char fileLength[8];
|
||||||
|
char deviceMajor[8];
|
||||||
|
char deviceMinor[8];
|
||||||
|
char remoteDeviceMajor[8];
|
||||||
|
char remoteDeviceMinor[8];
|
||||||
|
char nameLength[8];
|
||||||
|
char checkSum[8];
|
||||||
|
} FSCPIOHeader;
|
||||||
|
|
||||||
|
static FSVNodeOperations gFSCPIOOperations = {
|
||||||
|
.read = FSCPIORead,
|
||||||
|
.write = nullptr,
|
||||||
|
.open = nullptr,
|
||||||
|
.close = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
static UInt64 sFSCPIOHexadecimalToUInt64(const char* string, Int32 length) {
|
||||||
|
UInt64 result = 0;
|
||||||
|
for (Int32 i = 0; i < length; i++) {
|
||||||
|
char character = string[i];
|
||||||
|
result <<= 4;
|
||||||
|
if (character >= '0' && character <= '9') result += (character - '0');
|
||||||
|
else if (character >= 'A' && character <= 'F') result += (character - 'A' + 10);
|
||||||
|
else if (character >= 'a' && character <= 'f') result += (character - 'a' + 10);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
|
||||||
|
if (offset > node->dataLength) return 0;
|
||||||
|
if ((offset + size) > node->dataLength) size = node->dataLength - offset;
|
||||||
|
|
||||||
|
MemoryCopy(buffer, (char*)node->implementationData + offset, size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize) {
|
||||||
|
UInt8* currentPointer = (UInt8*)baseAddress;
|
||||||
|
UInt8* endPointer = currentPointer + totalSize;
|
||||||
|
|
||||||
|
FSVNode* rootNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
|
||||||
|
if (!rootNode) OSPanic("CPIO: Failed to allocate memory for root node");
|
||||||
|
|
||||||
|
MemorySet(rootNode, 0, sizeof(FSVNode));
|
||||||
|
StringCopy(rootNode->name, "/");
|
||||||
|
rootNode->flags = kFSVNodeFlagDirectory;
|
||||||
|
rootNode->operations = &gFSCPIOOperations;
|
||||||
|
|
||||||
|
FSVNode* tailNode = nullptr;
|
||||||
|
|
||||||
|
while (currentPointer < endPointer) {
|
||||||
|
FSCPIOHeader* header = (FSCPIOHeader*)currentPointer;
|
||||||
|
|
||||||
|
if (StringCompareWithLimit(header->magic, "070701", 6) != 0) {
|
||||||
|
OSPanic("CPIO: Invalid magic detected in StartupVolume");
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 nameSize = sFSCPIOHexadecimalToUInt64(header->nameLength, 8);
|
||||||
|
UInt64 fileSize = sFSCPIOHexadecimalToUInt64(header->fileLength, 8);
|
||||||
|
|
||||||
|
char* fileName = (char*)(currentPointer + sizeof(FSCPIOHeader));
|
||||||
|
if (StringCompare(fileName, "TRAILER!!!") == 0) break;
|
||||||
|
|
||||||
|
UInt64 headerAndNameLength = sizeof(FSCPIOHeader) + nameSize;
|
||||||
|
UInt64 offsetToData = FSCPIO_ALIGN4(headerAndNameLength);
|
||||||
|
void* fileContent = (void*)(currentPointer + offsetToData);
|
||||||
|
|
||||||
|
FSVNode* newNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
|
||||||
|
if (!newNode) OSPanic("CPIO: Failed to allocate memory for new node");
|
||||||
|
|
||||||
|
MemorySet(newNode, 0, sizeof(FSVNode));
|
||||||
|
StringCopyWithLimit(newNode->name, fileName, sizeof(newNode->name) - 1);
|
||||||
|
|
||||||
|
newNode->dataLength = fileSize;
|
||||||
|
newNode->inodeIdentifier = sFSCPIOHexadecimalToUInt64(header->inode, 8);
|
||||||
|
newNode->operations = &gFSCPIOOperations;
|
||||||
|
newNode->implementationData = fileContent;
|
||||||
|
|
||||||
|
UInt64 mode = sFSCPIOHexadecimalToUInt64(header->mode, 8);
|
||||||
|
if ((mode & 0xF000) == 0x4000) {
|
||||||
|
newNode->flags = kFSVNodeFlagDirectory;
|
||||||
|
} else {
|
||||||
|
newNode->flags = kFSVNodeFlagFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootNode->childNode == nullptr) {
|
||||||
|
rootNode->childNode = newNode;
|
||||||
|
} else if (tailNode) {
|
||||||
|
tailNode->nextNode = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
tailNode = newNode;
|
||||||
|
|
||||||
|
IOConsoleLog("^bCPIO^!: Found object '^y%s^!' (size: ^y%d^!) at ^y0x%x^!\n", fileName, fileSize, fileContent);
|
||||||
|
|
||||||
|
UInt64 dataLengthAligned = FSCPIO_ALIGN4(fileSize);
|
||||||
|
currentPointer += offsetToData + dataLengthAligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <FS/VFS.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
|
||||||
|
FSVNode* gFSVirtualFileSystemRoot = nullptr;
|
||||||
|
|
||||||
|
void FSVirtualFileSystemInitialize(FSVNode* rootNode) {
|
||||||
|
gFSVirtualFileSystemRoot = rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
|
||||||
|
if (!node || !node->operations || !node->operations->read) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->operations->read(node, offset, size, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSVNode* FSVirtualFileSystemOpenPath(const char* path) {
|
||||||
|
if (!gFSVirtualFileSystemRoot) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringCompare(path, "/") == 0) {
|
||||||
|
return gFSVirtualFileSystemRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* searchName = path;
|
||||||
|
if (path[0] == '/') {
|
||||||
|
searchName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSVNode* nodeIterator = gFSVirtualFileSystemRoot->childNode;
|
||||||
|
while (nodeIterator != nullptr) {
|
||||||
|
if (StringCompare(nodeIterator->name, searchName) == 0) {
|
||||||
|
if (nodeIterator->operations && nodeIterator->operations->open) {
|
||||||
|
nodeIterator->operations->open(nodeIterator);
|
||||||
|
}
|
||||||
|
return nodeIterator;
|
||||||
|
}
|
||||||
|
nodeIterator = nodeIterator->nextNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FSVNodeClose(FSVNode* node) {
|
||||||
|
if (node && node->operations && node->operations->close) {
|
||||||
|
node->operations->close(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <IO/IOConsole.h>
|
||||||
|
#include <IO/IOSerial.h>
|
||||||
|
#include <IO/IOGraphics.h>
|
||||||
|
#include <IO/IOKeyboard.h>
|
||||||
|
|
||||||
|
#include <lib/Math.h>
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <Data/VGAFont.h>
|
||||||
|
|
||||||
|
static IOGraphicsContext* sIOGraphicsContextPointer = nullptr;
|
||||||
|
static IOGraphicsPoint sIOConsoleCursorPosition = {0};
|
||||||
|
static IOGraphicsFont sIOConsoleFont = {0};
|
||||||
|
static IOGraphicsColor sIOConsoleForegroundColor = kIOConsoleColorWhite;
|
||||||
|
static IOGraphicsColor sIOConsoleDefaultForegroundColor = kIOConsoleColorWhite;
|
||||||
|
static IOGraphicsColor sIOConsoleBackgroundColor = kIOConsoleColorBlack;
|
||||||
|
|
||||||
|
void IOConsoleInit(IOGraphicsContext *context) {
|
||||||
|
sIOGraphicsContextPointer = context;
|
||||||
|
sIOConsoleCursorPosition.x = 0;
|
||||||
|
sIOConsoleCursorPosition.y = 0;
|
||||||
|
|
||||||
|
sIOConsoleFont.size.height = 16;
|
||||||
|
sIOConsoleFont.size.width = 8;
|
||||||
|
sIOConsoleFont.baseAddress = (const unsigned char*)VGAFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 IOConsoleGetColors() {
|
||||||
|
return ((UInt64) sIOConsoleForegroundColor << 32) | sIOConsoleBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsoleClear(IOGraphicsColor color) {
|
||||||
|
if (!sIOGraphicsContextPointer) return;
|
||||||
|
|
||||||
|
IOGraphicsPoint point = {0, 0};
|
||||||
|
IOGraphicsDrawRectangle(
|
||||||
|
sIOGraphicsContextPointer,
|
||||||
|
&point,
|
||||||
|
&sIOGraphicsContextPointer->dimensions,
|
||||||
|
color
|
||||||
|
);
|
||||||
|
|
||||||
|
sIOConsoleCursorPosition.x = 0;
|
||||||
|
sIOConsoleCursorPosition.y = 0;
|
||||||
|
sIOConsoleBackgroundColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOGraphicsContext* IOConsoleGetGraphicsContext() {
|
||||||
|
return sIOGraphicsContextPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOGraphicsSize IOConsoleGetDimensions() {
|
||||||
|
return sIOGraphicsContextPointer->dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsoleSetCursorPosition(IOGraphicsPoint* point) {
|
||||||
|
if (!point) return;
|
||||||
|
sIOConsoleCursorPosition.x = point->x;
|
||||||
|
sIOConsoleCursorPosition.y = point->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsolePutcharacter(char character) {
|
||||||
|
IOSerialWriteChar(character);
|
||||||
|
if (!sIOGraphicsContextPointer) return;
|
||||||
|
if (character == '\n') {
|
||||||
|
sIOConsoleCursorPosition.x = 0;
|
||||||
|
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
|
||||||
|
} else if (character == '\t') {
|
||||||
|
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width * 4;
|
||||||
|
} else if (character == '\b') {
|
||||||
|
sIOConsoleCursorPosition.x -= sIOConsoleFont.size.width;
|
||||||
|
IOGraphicsDrawRectangle(
|
||||||
|
sIOGraphicsContextPointer,
|
||||||
|
&sIOConsoleCursorPosition,
|
||||||
|
&sIOConsoleFont.size,
|
||||||
|
sIOConsoleBackgroundColor
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
IOGraphicsDrawCharacter(
|
||||||
|
sIOGraphicsContextPointer,
|
||||||
|
&sIOConsoleCursorPosition,
|
||||||
|
character,
|
||||||
|
sIOConsoleForegroundColor,
|
||||||
|
&sIOConsoleFont
|
||||||
|
);
|
||||||
|
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sIOConsoleCursorPosition.x >= sIOGraphicsContextPointer->dimensions.width) {
|
||||||
|
sIOConsoleCursorPosition.x = 0;
|
||||||
|
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
|
||||||
|
}
|
||||||
|
if (sIOConsoleCursorPosition.y >= sIOGraphicsContextPointer->dimensions.height) {
|
||||||
|
IOConsoleClear(sIOConsoleBackgroundColor); // TODO: do scrolling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsolePrint(const char *string) {
|
||||||
|
for (Int32 i = 0; string[i] != '\0'; i++) IOConsolePutcharacter(string[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sIOConsolePrintDecimal(const Int64 number) {
|
||||||
|
if (number < 0) IOConsolePutcharacter('-');
|
||||||
|
UInt64 unsignedNumber = abs(number);
|
||||||
|
char buffer[32];
|
||||||
|
Int32 i = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
buffer[i] = (unsignedNumber % 10) + '0';
|
||||||
|
unsignedNumber /= 10;
|
||||||
|
i++;
|
||||||
|
} while (unsignedNumber > 0);
|
||||||
|
|
||||||
|
while (--i >= 0) {
|
||||||
|
IOConsolePutcharacter(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sIOConsolePrintHexadecimal(UInt64 unsignedNumber, UInt8 padding) {
|
||||||
|
IOConsolePutcharacter('0');
|
||||||
|
IOConsolePutcharacter('x');
|
||||||
|
|
||||||
|
if (unsignedNumber == 0) {
|
||||||
|
IOConsolePutcharacter('0');
|
||||||
|
for (Int32 i = 1; i < padding; i++) IOConsolePutcharacter('0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[16] = {0};
|
||||||
|
Int32 i = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
Int32 digit = unsignedNumber % 16;
|
||||||
|
if (digit < 10) buffer[i++] = digit + '0';
|
||||||
|
else buffer[i++] = digit - 10 + 'A';
|
||||||
|
unsignedNumber /= 16;
|
||||||
|
} while (unsignedNumber > 0);
|
||||||
|
|
||||||
|
while(i < padding) {
|
||||||
|
IOConsolePutcharacter('0');
|
||||||
|
padding--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--i >= 0) {
|
||||||
|
IOConsolePutcharacter(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IOConsoleLog(const char *fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
for (Int32 i = 0; fmt[i] != '\0'; i++) {
|
||||||
|
if (fmt[i] == '%') {
|
||||||
|
i++;
|
||||||
|
switch (fmt[i]) {
|
||||||
|
case 's': {
|
||||||
|
const char *string = va_arg(args, const char*);
|
||||||
|
if (!string) string = "undefined";
|
||||||
|
IOConsolePrint(string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c': {
|
||||||
|
char character = (char)va_arg(args, int);
|
||||||
|
IOConsolePutcharacter(character);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': {
|
||||||
|
Int32 number = va_arg(args, Int32);
|
||||||
|
sIOConsolePrintDecimal(number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x': {
|
||||||
|
UInt64 number = va_arg(args, UInt64);
|
||||||
|
sIOConsolePrintHexadecimal(number, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'X' : {
|
||||||
|
UInt64 number = va_arg(args, UInt64);
|
||||||
|
sIOConsolePrintHexadecimal(number, 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
IOConsolePutcharacter(fmt[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (fmt[i] == '^') {
|
||||||
|
i++;
|
||||||
|
switch (fmt[i]) {
|
||||||
|
case 'r': IOConsoleSetForegroundColor(kIOConsoleColorRed); break;
|
||||||
|
case 'R': IOConsoleSetForegroundColor(kIOConsoleColorVeryRed); break;
|
||||||
|
case 'g': IOConsoleSetForegroundColor(kIOConsoleColorGreen); break;
|
||||||
|
case 'G': IOConsoleSetForegroundColor(kIOConsoleColorVeryGreen); break;
|
||||||
|
case 't': IOConsoleSetForegroundColor(kIOConsoleColorTurqoise); break;
|
||||||
|
case 'b': IOConsoleSetForegroundColor(kIOConsoleColorBlue); break;
|
||||||
|
case 'B': IOConsoleSetForegroundColor(kIOConsoleColorVeryBlue); break;
|
||||||
|
case 'l': IOConsoleSetForegroundColor(kIOConsoleColorLightBlue); break;
|
||||||
|
case 'y': IOConsoleSetForegroundColor(kIOConsoleColorYellow); break;
|
||||||
|
case 'c': IOConsoleSetForegroundColor(kIOConsoleColorCyan); break;
|
||||||
|
case 'm': IOConsoleSetForegroundColor(kIOConsoleColorMagneta); break;
|
||||||
|
case 'p': IOConsoleSetForegroundColor(kIOConsoleColorPink); break;
|
||||||
|
case '0': IOConsoleSetForegroundColor(kIOConsoleColorBlack); break;
|
||||||
|
case 'w': IOConsoleSetForegroundColor(kIOConsoleColorWhite); break;
|
||||||
|
|
||||||
|
case '!': IOConsoleSetForegroundColor(sIOConsoleDefaultForegroundColor); break;
|
||||||
|
case '~': IOConsoleSetForegroundColor(~sIOConsoleBackgroundColor); break;
|
||||||
|
|
||||||
|
case '^': IOConsolePutcharacter('^'); break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
IOConsolePutcharacter('^');
|
||||||
|
IOConsolePutcharacter(fmt[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IOConsolePutcharacter(fmt[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsoleSetForegroundColor(UInt32 color) {
|
||||||
|
sIOConsoleForegroundColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsoleSetDefaultForegroundColor(UInt32 color) {
|
||||||
|
sIOConsoleDefaultForegroundColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOConsoleReadLine(char* buffer, UInt32 limit) {
|
||||||
|
UInt32 i = 0;
|
||||||
|
while (true) {
|
||||||
|
char character = IOKeyboardGetCharacter();
|
||||||
|
switch (character) {
|
||||||
|
case '\n': {
|
||||||
|
buffer[i] = '\0';
|
||||||
|
IOConsoleLog("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case '\b': {
|
||||||
|
if (i > 0) {
|
||||||
|
i--;
|
||||||
|
IOConsoleLog("\b \b");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (i < limit - 1) {
|
||||||
|
buffer[i] = character;
|
||||||
|
IOConsoleLog("%c", character);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
// RIP shitgui -- you started it all
|
||||||
|
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <IO/IOGraphics.h>
|
||||||
|
#include <VM/Heap.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kIOGraphicsTransparencyKey = 0xFF00FF
|
||||||
|
};
|
||||||
|
|
||||||
|
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point) {
|
||||||
|
if (!context->framebuffer || !point || point->x >= context->dimensions.width || point->y >= context->dimensions.height) return 0;
|
||||||
|
return context->framebuffer[point->y * context->pixelsPerScanLine + point->x];
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image) {
|
||||||
|
if (!context->framebuffer || !image) return;
|
||||||
|
|
||||||
|
UInt32 startX = point->x;
|
||||||
|
UInt32 startY = point->y;
|
||||||
|
UInt32 drawW = image->size.width;
|
||||||
|
UInt32 drawH = image->size.height;
|
||||||
|
|
||||||
|
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
|
||||||
|
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
|
||||||
|
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
|
||||||
|
|
||||||
|
for (UInt32 y = 0; y < drawH; y++) {
|
||||||
|
volatile UInt32 *destinationPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
|
||||||
|
UInt32 *sourcePointer = &image->buffer[y * image->size.width];
|
||||||
|
for (UInt32 x = 0; x < drawW; x++) {
|
||||||
|
UInt32 color = sourcePointer[x];
|
||||||
|
if (color != kIOGraphicsTransparencyKey) destinationPointer[x] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsSize* size, IOGraphicsColor color) {
|
||||||
|
if (!context->framebuffer) return;
|
||||||
|
|
||||||
|
UInt32 startX = point->x;
|
||||||
|
UInt32 startY = point->y;
|
||||||
|
UInt32 drawW = size->width;
|
||||||
|
UInt32 drawH = size->height;
|
||||||
|
|
||||||
|
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
|
||||||
|
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
|
||||||
|
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
|
||||||
|
|
||||||
|
|
||||||
|
for (UInt32 y = 0; y < drawH; y++) {
|
||||||
|
volatile UInt32* rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
|
||||||
|
for (UInt32 x = 0; x < drawW; x++) rowPointer[x] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOGraphicsDrawCharacter(IOGraphicsContext* context, IOGraphicsPoint* point, char c, IOGraphicsColor color, IOGraphicsFont* font) {
|
||||||
|
if (!context->framebuffer) return;
|
||||||
|
|
||||||
|
UInt32 startX = point->x;
|
||||||
|
UInt32 startY = point->y;
|
||||||
|
UInt32 drawW = font->size.width;
|
||||||
|
UInt32 drawH = font->size.height;
|
||||||
|
|
||||||
|
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
|
||||||
|
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
|
||||||
|
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
|
||||||
|
|
||||||
|
for (UInt32 y = 0; y < drawH; y++) {
|
||||||
|
UInt8 bitmapRow = font->baseAddress[(unsigned char)c * font->size.height + y];
|
||||||
|
volatile UInt32 *rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
|
||||||
|
for (UInt32 x = 0; x < drawW; x++) {
|
||||||
|
if (bitmapRow & (1 << (7 - x))) {
|
||||||
|
rowPointer[x] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
#include <drivers/keyboard.h>
|
#include <IO/IOKeyboard.h>
|
||||||
#include <drivers/console.h>
|
#include <IO/IOConsole.h>
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
|
||||||
#include <io.h>
|
#include <IO.h>
|
||||||
#include <types.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 */
|
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 0x00 - 0x09 */
|
||||||
'9', '0', '-', '=', '\b', /* Backspace */
|
'9', '0', '-', '=', '\b', /* Backspace */
|
||||||
'\t', /* Tab */
|
'\t', /* Tab */
|
||||||
@@ -46,7 +48,7 @@ unsigned char keyboard_map[128] = {
|
|||||||
0, /* All other keys are undefined */
|
0, /* All other keys are undefined */
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned char keyboard_map_shifted[128] = {
|
static unsigned char sIOKeyboardMapShifted[128] = {
|
||||||
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 0x00 - 0x09 */
|
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 0x00 - 0x09 */
|
||||||
'(', ')', '_', '+', '\b', /* Backspace */
|
'(', ')', '_', '+', '\b', /* Backspace */
|
||||||
'\t', /* Tab */
|
'\t', /* Tab */
|
||||||
@@ -85,31 +87,55 @@ unsigned char keyboard_map_shifted[128] = {
|
|||||||
0, /* All other keys */
|
0, /* All other keys */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool shift_pressed = false;
|
static Boolean sIOKeyboardIsShiftPressed = false;
|
||||||
kb_buffer kb_buf = {0};
|
|
||||||
|
|
||||||
void kb_handler() {
|
IOKeyboardController gIOKeyboardController = {0};
|
||||||
u16 next_head = (kb_buf.head + 1) % KB_BUFF_SIZE;
|
|
||||||
|
|
||||||
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
|
// make code 0x00 - 0x7F; break code = make code + 0x80
|
||||||
if (scancode < 0x80) {
|
if (scancode < 0x80) {
|
||||||
unsigned char* arr = shift_pressed ? keyboard_map_shifted : keyboard_map;
|
unsigned char* keyMap = sIOKeyboardIsShiftPressed ? sIOKeyboardMapShifted : sIOKeyboardMap;
|
||||||
char ascii = arr[scancode];
|
char ascii = keyMap[scancode];
|
||||||
if (ascii && next_head != kb_buf.tail) {
|
if (ascii && nextHead != gIOKeyboardController.tail) {
|
||||||
kb_buf.buffer[kb_buf.head] = ascii;
|
gIOKeyboardController.buffer[gIOKeyboardController.head] = ascii;
|
||||||
kb_buf.head = next_head;
|
gIOKeyboardController.head = nextHead;
|
||||||
} else {
|
} else {
|
||||||
switch (scancode) {
|
switch (scancode) {
|
||||||
case 0x2A: shift_pressed = true; break;
|
case 0x2A: sIOKeyboardIsShiftPressed = true; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (scancode) {
|
switch (scancode) {
|
||||||
case 0xAA: shift_pressed = false; break;
|
case 0xAA: sIOKeyboardIsShiftPressed = false; break;
|
||||||
default: 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <IO/IOSerial.h>
|
||||||
|
#include <IO.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kIOCom1Port = 0x3F8,
|
||||||
|
};
|
||||||
|
|
||||||
|
int IOSerialInit() {
|
||||||
|
IOPortWrite8(kIOCom1Port + 1, 0x00); // interrupt enable register (+1) / disable interruptions
|
||||||
|
IOPortWrite8(kIOCom1Port + 3, 0x80); // line control register (+3)
|
||||||
|
IOPortWrite8(kIOCom1Port + 0, 0x03); // speed : low byte
|
||||||
|
IOPortWrite8(kIOCom1Port + 1, 0x00); // speed : high byte
|
||||||
|
IOPortWrite8(kIOCom1Port + 3, 0x03); // line control register (+3) / reset DLAB / no parity / 1 stop bit / (8N1)
|
||||||
|
IOPortWrite8(kIOCom1Port + 2, 0xC7); // FIFO Control register (+2) / 1100 0111 / last ones are enable FIFO buff / first ones to clean noise
|
||||||
|
IOPortWrite8(kIOCom1Port + 4, 0x0B); // ready :3
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int IOCheckIsTransmitEmpty() {
|
||||||
|
return IOPortRead8(kIOCom1Port + 5) & 0x20; // checking 5th bit LSR
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOSerialWriteChar(char character) {
|
||||||
|
while (IOCheckIsTransmitEmpty() == 0); // waiting for buffer to flush (spinlock)
|
||||||
|
IOPortWrite8(kIOCom1Port, character);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOSerialWrite(const char* string) {
|
||||||
|
for (int i = 0; string[i] != '\0'; i++) IOSerialWriteChar(string[i]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <IO/IOTimer.h>
|
||||||
|
#include <IO.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kIOTimerPitBaseClock = 1193180,
|
||||||
|
kIOTimerPitCommand = 0x43,
|
||||||
|
kIOTimerPitData = 0x40,
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile UInt64 sIOTimerTicks = 0;
|
||||||
|
|
||||||
|
void IOTimerInitialize(UInt32 frequency) {
|
||||||
|
UInt32 divisor = kIOTimerPitBaseClock / frequency;
|
||||||
|
|
||||||
|
IOPortWrite8(kIOTimerPitCommand, 0x36); // 0x36 = 00110110 = channel 0, LOHI byte access, Mode 3, binary
|
||||||
|
IOPortWrite8(kIOTimerPitData, divisor & 0xFF);
|
||||||
|
IOPortWrite8(kIOTimerPitData, (divisor >> 8) & 0xFF);
|
||||||
|
|
||||||
|
UInt8 mask = IOPortRead8(0x21);
|
||||||
|
mask &= ~(1 << 0);
|
||||||
|
IOPortWrite8(0x21, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 IOTimerInterruptsHandler(CPURegisters *registers) {
|
||||||
|
sIOTimerTicks++;
|
||||||
|
return OSSchedulerNext((UInt64)registers);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 IOTimerGetTicks() {
|
||||||
|
return sIOTimerTicks;
|
||||||
|
}
|
||||||
@@ -0,0 +1,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");
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <KSH/KSHDebug.h>
|
||||||
|
#include <IO/IOConsole.h>
|
||||||
|
|
||||||
|
UInt64 KSHDebug() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/Exec/HOTLoader.h>
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <VM/Heap.h>
|
||||||
|
|
||||||
|
#include "../../common/hot_header.h"
|
||||||
|
|
||||||
|
UInt64 HOTLoad(OSProcess* process, UInt8* data) {
|
||||||
|
HOTHeader* header = (HOTHeader*)data;
|
||||||
|
if (header->magic != HOT_MAGIC) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HOTSegment* segments = (HOTSegment*)(data + sizeof(HOTHeader));
|
||||||
|
for (UInt64 i = 0; i < header->segments_count; i++) {
|
||||||
|
HOTSegment* segment = &segments[i];
|
||||||
|
if (segment->memsz == 0) continue;
|
||||||
|
|
||||||
|
UInt64 start = segment->vaddr & ~(0xFFFULL);
|
||||||
|
UInt64 end = (segment->vaddr + segment->memsz + 0xFFF) & ~(0xFFFULL);
|
||||||
|
|
||||||
|
for (UInt64 address = start; address < end; address += kVMPageSize) {
|
||||||
|
void* physicalPage = VMPhysicalMemoryAllocatePage();
|
||||||
|
VMVirtualMemoryMapPage((UInt64*)process->physicalPML4, (UInt64)physicalPage, address, PTE_USER | PTE_RW | PTE_PRESENT);
|
||||||
|
void* kernelVirtAddress = (void*)((UInt64)physicalPage + HHDM_OFFSET);
|
||||||
|
MemorySet(kernelVirtAddress, 0, kVMPageSize);
|
||||||
|
UInt64 pageOverleapStart = (address > segment->vaddr) ? address : segment->vaddr;
|
||||||
|
UInt64 pageOverleapEnd = (address + kVMPageSize < segment->vaddr + segment->filesz)
|
||||||
|
? (address + kVMPageSize)
|
||||||
|
: (segment->vaddr + segment->filesz);
|
||||||
|
if (pageOverleapStart < pageOverleapEnd) {
|
||||||
|
UInt64 copySize = pageOverleapEnd - pageOverleapStart;
|
||||||
|
UInt64 sourceOffset = segment->offset + (pageOverleapStart - segment->vaddr);
|
||||||
|
UInt64 destinationOffset = pageOverleapStart - address;
|
||||||
|
|
||||||
|
MemoryCopy((UInt8*)kernelVirtAddress + destinationOffset, data + sourceOffset, copySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return header->entry_point;
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/Exec/HOTLoader.h>
|
||||||
|
#include <OS/Exec/OSLoader.h>
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <VM/Heap.h>
|
||||||
|
|
||||||
|
#include <FS/VFS.h>
|
||||||
|
|
||||||
|
#include <IO/IOConsole.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
extern UInt32 gOSSchedulerNextProcessID;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kOSUserStackTop = 0x70000000,
|
||||||
|
kOSHeapStart = 0x40000000
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName) {
|
||||||
|
FSVNode* executableFile = FSVirtualFileSystemOpenPath(executablePath);
|
||||||
|
if (!executableFile) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSProcess* newProcess = (OSProcess*)VMHeapAllocate(sizeof(OSProcess));
|
||||||
|
if (!newProcess) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemorySet(newProcess, 0, sizeof(OSProcess));
|
||||||
|
newProcess->processId = gOSSchedulerNextProcessID++;
|
||||||
|
newProcess->state = kOSProcessStateRunning;
|
||||||
|
newProcess->physicalPML4 = VMVirtualMemoryCreateAddressSpace();
|
||||||
|
newProcess->heapStartPointer = kOSHeapStart;
|
||||||
|
newProcess->heapCurrentPointer = kOSHeapStart;
|
||||||
|
StringCopyWithLimit(newProcess->name, processName, 31);
|
||||||
|
|
||||||
|
UInt8* imageBuffer = (UInt8*)VMHeapAllocate(executableFile->dataLength);
|
||||||
|
if (!imageBuffer) {
|
||||||
|
VMHeapFree(newProcess);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSVNodeRead(executableFile, 0, executableFile->dataLength, imageBuffer);
|
||||||
|
|
||||||
|
UInt64 entryPoint = HOTLoad(newProcess, imageBuffer);
|
||||||
|
if (!entryPoint) {
|
||||||
|
VMHeapFree(imageBuffer);
|
||||||
|
VMHeapFree(newProcess);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMHeapFree(imageBuffer);
|
||||||
|
|
||||||
|
VMVirtualMemorySetupUserStack((UInt64*)newProcess->physicalPML4);
|
||||||
|
|
||||||
|
if (!OSSchedulerSpawn((void(*)())entryPoint, newProcess, true, kOSUserStackTop)) {
|
||||||
|
VMHeapFree(newProcess);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProcess->processId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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"); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <lib/Rand.h>
|
||||||
|
|
||||||
|
#include <IO/IOGraphics.h>
|
||||||
|
#include <IO/IOConsole.h>
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
static const char* sOSPanicFunMessages[] = {
|
||||||
|
"Execution finished abnormally with code: 0x_x",
|
||||||
|
"It's definitely your fault.",
|
||||||
|
"No more Roblox!",
|
||||||
|
"Call your mom 4 help!",
|
||||||
|
"2bad4u",
|
||||||
|
"Touch grass",
|
||||||
|
"Skill issue",
|
||||||
|
"You should just go outside actually",
|
||||||
|
"Perfect opportunity to take a shower",
|
||||||
|
"404 not found",
|
||||||
|
"Windows is locked! Password:___ Time left: 5:45:41",
|
||||||
|
"GOOOOOAL",
|
||||||
|
"\"NAM PIZDA\": hackers dropped our registry",
|
||||||
|
"geeked vs locked in",
|
||||||
|
"HEEEELP!",
|
||||||
|
"LET ME GO!",
|
||||||
|
"You little asshole, make it better",
|
||||||
|
"Go and read books for programming u idiot",
|
||||||
|
"TIME TO BRAKE! :3 Take a tea and try again later cutie",
|
||||||
|
"Code have been eaten by Aliens",
|
||||||
|
"That's all, folks!",
|
||||||
|
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
|
||||||
|
"I'll be back",
|
||||||
|
"Hastla la vista, baby",
|
||||||
|
"Ti chego mne tut nagovoril...",
|
||||||
|
"Have you tried turning it off and on again?",
|
||||||
|
"Put it in rice maybe?",
|
||||||
|
"Just hit the monitor, it usually helps",
|
||||||
|
"I think it needs a rest. Come back tomorrow",
|
||||||
|
"You clicked something wrong, didn't you?",
|
||||||
|
"You hacked it too hard, bro",
|
||||||
|
"I think you deleted the internet",
|
||||||
|
"Stop downloading RAM",
|
||||||
|
"Pro tip: dont crash",
|
||||||
|
"Stop ricing the kernel you loonixtard, TermOS is NOT Loonix",
|
||||||
|
"Attaboy, Jack. He's good. Really good.",
|
||||||
|
"Zhenih priehal",
|
||||||
|
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
|
||||||
|
"fuck off",
|
||||||
|
"Your GPU is now mining Ethereum for me. Thanks.",
|
||||||
|
"Your PC is locked!\n\t\t\t\tPay a fee of 0.019082006 bitcoins to a wallet 1KtoProchitalTotSosal to get decryption key!",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const char* sOSPanicExceptionMessages[] = {
|
||||||
|
"Division By Zero",
|
||||||
|
"Debug",
|
||||||
|
"Non Maskable Interrupt",
|
||||||
|
"Breakpoint",
|
||||||
|
"Into Detected Overflow",
|
||||||
|
"Out of Bounds",
|
||||||
|
"Invalid Opcode",
|
||||||
|
"Device Not Available",
|
||||||
|
"Double Fault",
|
||||||
|
"Coprocessor Segment Overrun",
|
||||||
|
"Bad TSS",
|
||||||
|
"Segment Not Present",
|
||||||
|
"Stack Fault",
|
||||||
|
"General Protection Fault",
|
||||||
|
"Page Fault",
|
||||||
|
"Reserved",
|
||||||
|
"x87 Floating-Point Exception",
|
||||||
|
"Alignment Check",
|
||||||
|
"Machine Check",
|
||||||
|
"SIMD Floating-Point Exception",
|
||||||
|
"Virtualization Exception",
|
||||||
|
"Control Protection Exception",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Reserved",
|
||||||
|
"Hypervisor Injection Exception",
|
||||||
|
"VMM Communication Exception",
|
||||||
|
"Security Exception",
|
||||||
|
"Reserved"
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((noreturn)) static void die() {
|
||||||
|
while (1) {
|
||||||
|
__asm__ volatile ("cli; hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sOSPanicDrawPanicBackground() {
|
||||||
|
IOConsoleClear(0x000000);
|
||||||
|
IOConsoleSetForegroundColor(0xFFFFFF);
|
||||||
|
IOConsoleSetDefaultForegroundColor(0xFFFFFF);
|
||||||
|
|
||||||
|
UInt64 funMessagesCount = sizeof(sOSPanicFunMessages) / sizeof(sOSPanicFunMessages[0]);
|
||||||
|
UInt8 randNum = Rand() % funMessagesCount;
|
||||||
|
|
||||||
|
IOConsoleLog("\n\n");
|
||||||
|
IOConsoleLog("\t\t\t\t^bKERNEL PANIC^! :( \n");
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
IOConsoleLog("\t\t^y%s^!\n", sOSPanicFunMessages[randNum]);
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame) {
|
||||||
|
sOSPanicDrawPanicBackground();
|
||||||
|
|
||||||
|
IOConsoleLog("\t\t^yCPU EXCEPTION^!: ^b%s^! (%d)\n", sOSPanicExceptionMessages[frame->interruptNumber], frame->interruptNumber);
|
||||||
|
if (frame->errorCode) IOConsoleLog("\t\t^yError Code^!: %X\n", frame->errorCode);
|
||||||
|
IOConsoleLog("\t\t^yInstruction Pointer^! (^yRIP^!): %X\n", frame->rip);
|
||||||
|
IOConsoleLog("\t\t^yCode Segment^! (^yCS^!): %X\n", frame->cs);
|
||||||
|
IOConsoleLog("\t\t^yFlags^! (^yRFLAGS^!): %X\n", frame->rflags);
|
||||||
|
IOConsoleLog("\t\t^yStack Pointer^! (^yRSP^!): %X\n", frame->rsp);
|
||||||
|
if (frame->interruptNumber == 14) {
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
IOConsoleLog("\t\t ^yPage Fault Helper^! \n");
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
UInt64 cr2;
|
||||||
|
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||||
|
IOConsoleLog("\t\t^yFaulting Address^! (^yCR2^!): %X\n", cr2);
|
||||||
|
IOConsoleLog("\t\t^yERRCode^!: %X\n", frame->errorCode);
|
||||||
|
UInt64 present = (frame->errorCode & (1 << 0)) != 0;
|
||||||
|
UInt64 write = (frame->errorCode & (1 << 1)) != 0;
|
||||||
|
UInt64 user = (frame->errorCode & (1 << 2)) != 0;
|
||||||
|
UInt64 reserved = (frame->errorCode & (1 << 3)) != 0;
|
||||||
|
UInt64 instruction = (frame->errorCode & (1 << 4)) != 0;
|
||||||
|
IOConsoleLog("\t\t\t[^bP^!] ^yReason^!: %s\n", present ? "Page Protection violation" : "Non-present page");
|
||||||
|
IOConsoleLog("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
|
||||||
|
IOConsoleLog("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
|
||||||
|
if (reserved) IOConsoleLog("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
|
||||||
|
if (instruction) IOConsoleLog("\t\t\t[^bI^!] ^yTried to^! execute ^ycode from^! NX ^ymemory^!\n");
|
||||||
|
}
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
IOConsoleLog("\t\t\t\t^yREGISTERS^!\n");
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
IOConsoleLog("\t\t^yRAX^!=%X, ^yRBX^!=%X\n", frame->rax, frame->rbx);
|
||||||
|
IOConsoleLog("\t\t^yRCX^!=%X, ^yRDX^!=%X\n", frame->rcx, frame->rdx);
|
||||||
|
IOConsoleLog("\t\t^yRSI^!=%X, ^yRDI^!=%X\n", frame->rsi, frame->rdi);
|
||||||
|
IOConsoleLog("\t\t^yRBP^!=%X, ^yR8^! =%X\n", frame->rbp, frame->r8);
|
||||||
|
IOConsoleLog("\t\t^yR9^! =%X, ^yR10^!=%X \n", frame->r9, frame->r10);
|
||||||
|
IOConsoleLog("\t\t^yR11^!=%X, ^yR12^!=%X\n", frame->r11, frame->r12);
|
||||||
|
IOConsoleLog("\t\t^yR13^!=%X, ^yR14^!=%X\n", frame->r13, frame->r14);
|
||||||
|
IOConsoleLog("\t\t^yR15^!=%X\n",frame->r15);
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
|
||||||
|
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn)) void OSPanic(const char* message) {
|
||||||
|
sOSPanicDrawPanicBackground();
|
||||||
|
|
||||||
|
IOConsoleLog("\t\t^yReason^!: %s\n", message);
|
||||||
|
IOConsoleLog("\t\t--------------------------------\n");
|
||||||
|
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
|
||||||
|
|
||||||
|
die();
|
||||||
|
}
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
#include <VM/Heap.h>
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <OSCPU.h>
|
||||||
|
#include <GDT.h>
|
||||||
|
|
||||||
|
OSTask* gOSSchedulerCurrentTask = nullptr;
|
||||||
|
UInt32 gOSSchedulerNextProcessID = 1;
|
||||||
|
|
||||||
|
extern void irq0_handler();
|
||||||
|
extern UInt64 gVMKernelPML4Physical;
|
||||||
|
|
||||||
|
static OSProcess sOSSchedulerKernelProcess;
|
||||||
|
static OSSpinlock sOSSchedulerLock;
|
||||||
|
|
||||||
|
static OSTask* sOSSchedulerGarbageCollectorTask = nullptr;
|
||||||
|
|
||||||
|
void idle_task() {
|
||||||
|
while (1) {
|
||||||
|
__asm__ volatile ("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSchedulerGarbageCollector() {
|
||||||
|
OSTask* self = gOSSchedulerCurrentTask;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
OSTask* previousTask = self;
|
||||||
|
OSTask* nextTask = previousTask->next;
|
||||||
|
|
||||||
|
while (nextTask != self) {
|
||||||
|
if (nextTask->taskState == kOSProcessStateDead) {
|
||||||
|
OSSpinlockState lockState;
|
||||||
|
OSSpinlockLockIRQ(&sOSSchedulerLock, &lockState);
|
||||||
|
|
||||||
|
previousTask->next = nextTask->next;
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &lockState);
|
||||||
|
|
||||||
|
if (nextTask->kernelStackBase) {
|
||||||
|
VMHeapFree(nextTask->kernelStackBase);
|
||||||
|
}
|
||||||
|
VMHeapFree(nextTask);
|
||||||
|
|
||||||
|
nextTask = previousTask->next;
|
||||||
|
} else {
|
||||||
|
previousTask = nextTask;
|
||||||
|
nextTask = nextTask->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSSchedulerYield(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sOSSchedulerPostGarbageCollectorSignal() {
|
||||||
|
if (!sOSSchedulerGarbageCollectorTask) return;
|
||||||
|
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
|
||||||
|
|
||||||
|
sOSSchedulerGarbageCollectorTask->taskState = kOSProcessStateRunning;
|
||||||
|
sOSSchedulerGarbageCollectorTask->sleepTicks = 0;
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSchedulerInitialize() {
|
||||||
|
sOSSchedulerKernelProcess.processId = 0;
|
||||||
|
sOSSchedulerKernelProcess.state = kOSProcessStateRunning;
|
||||||
|
sOSSchedulerKernelProcess.physicalPML4 = gVMKernelPML4Physical;
|
||||||
|
StringCopy(sOSSchedulerKernelProcess.name, "kernel");
|
||||||
|
|
||||||
|
OSTask* kernelTask = (OSTask*)VMHeapAllocate(sizeof(OSTask));
|
||||||
|
if (!kernelTask) OSPanic("Failed to initialize scheduler: OOm");
|
||||||
|
|
||||||
|
MemorySet(kernelTask, 0, sizeof(OSTask));
|
||||||
|
|
||||||
|
kernelTask->id = 0;
|
||||||
|
kernelTask->process = &sOSSchedulerKernelProcess;
|
||||||
|
kernelTask->sleepTicks = 0;
|
||||||
|
kernelTask->next = kernelTask;
|
||||||
|
kernelTask->taskState = kOSProcessStateRunning;
|
||||||
|
kernelTask->waitingForProcess = -1;
|
||||||
|
|
||||||
|
gOSSchedulerCurrentTask = kernelTask;
|
||||||
|
OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0);
|
||||||
|
sOSSchedulerGarbageCollectorTask = OSSchedulerSpawn(OSSchedulerGarbageCollector, &sOSSchedulerKernelProcess, false, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) {
|
||||||
|
OSTask* task = (OSTask*)VMHeapAllocate(sizeof(OSTask));
|
||||||
|
if (!task) return nullptr;
|
||||||
|
if (!owner) owner = &sOSSchedulerKernelProcess;
|
||||||
|
|
||||||
|
UInt64 stackSize = 16384;
|
||||||
|
UInt8* stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
|
||||||
|
if (!stackBaseAddress) {
|
||||||
|
sOSSchedulerPostGarbageCollectorSignal();
|
||||||
|
OSSchedulerYield(0);
|
||||||
|
stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
|
||||||
|
if (!stackBaseAddress) {
|
||||||
|
VMHeapFree(task);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UInt64* rsp = (UInt64*)(stackBaseAddress + stackSize);
|
||||||
|
|
||||||
|
UInt64 cs = isUser ? 0x23 : 0x08;
|
||||||
|
UInt64 ss = isUser ? 0x1b : 0x10;
|
||||||
|
UInt64 rflags = 0x202;
|
||||||
|
UInt64 targetStackPointer = 0;
|
||||||
|
if (isUser) targetStackPointer = fixedUserStackPointer;
|
||||||
|
else targetStackPointer = (UInt64)stackBaseAddress + stackSize;
|
||||||
|
|
||||||
|
*--rsp = ss; // SS -- Kernel data
|
||||||
|
*--rsp = targetStackPointer; // rsp
|
||||||
|
*--rsp = rflags; // RFLAGS -- Interrupts Enabled | Reserved bit;
|
||||||
|
*--rsp = cs; // CS -- Kernel Code;
|
||||||
|
*--rsp = (UInt64)entry; // RIP
|
||||||
|
|
||||||
|
*--rsp = 0; // int no
|
||||||
|
*--rsp = 0; // err code
|
||||||
|
|
||||||
|
for (UInt8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
|
||||||
|
|
||||||
|
task->stackPointer = (UInt64)rsp;
|
||||||
|
task->process = owner;
|
||||||
|
task->id = owner->processId;
|
||||||
|
task->sleepTicks = 0;
|
||||||
|
task->kernelStackTop = (UInt64)stackBaseAddress + stackSize;
|
||||||
|
task->kernelStackBase = stackBaseAddress;
|
||||||
|
task->taskState = kOSProcessStateRunning;
|
||||||
|
task->waitingForProcess = -1;
|
||||||
|
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
|
||||||
|
|
||||||
|
task->next = gOSSchedulerCurrentTask->next;
|
||||||
|
gOSSchedulerCurrentTask->next = task;
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
|
||||||
|
if (!gOSSchedulerCurrentTask) return currentStackPointer;
|
||||||
|
|
||||||
|
OSSpinlockLock(&sOSSchedulerLock);
|
||||||
|
|
||||||
|
gOSSchedulerCurrentTask->stackPointer = currentStackPointer;
|
||||||
|
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
|
||||||
|
taskIterator = taskIterator->next;
|
||||||
|
} while (taskIterator != gOSSchedulerCurrentTask->next);
|
||||||
|
|
||||||
|
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
|
||||||
|
|
||||||
|
OSTask* nextTask = gOSSchedulerCurrentTask->next;
|
||||||
|
while (1) {
|
||||||
|
if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning;
|
||||||
|
if (nextTask->taskState == kOSProcessStateRunning) break;
|
||||||
|
nextTask = nextTask->next;
|
||||||
|
|
||||||
|
if (nextTask == gOSSchedulerCurrentTask) {
|
||||||
|
if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break;
|
||||||
|
OSPanic("no running tasks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextTask->process->physicalPML4 != gOSSchedulerCurrentTask->process->physicalPML4) VMLoadCR3(nextTask->process->physicalPML4);
|
||||||
|
gOSSchedulerCurrentTask = nextTask;
|
||||||
|
gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop;
|
||||||
|
gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop;
|
||||||
|
|
||||||
|
OSSpinlockUnlock(&sOSSchedulerLock);
|
||||||
|
return gOSSchedulerCurrentTask->stackPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSchedulerBlock(UInt32 processID) {
|
||||||
|
gOSSchedulerCurrentTask->taskState = kOSProcessStateBlocked;
|
||||||
|
gOSSchedulerCurrentTask->waitingForProcess = processID;
|
||||||
|
__asm__ volatile("int $32");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSchedulerWakeup(UInt32 processID) {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
|
||||||
|
|
||||||
|
OSTask* iteratorTask = gOSSchedulerCurrentTask;
|
||||||
|
do {
|
||||||
|
if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) {
|
||||||
|
iteratorTask->taskState = kOSProcessStateRunning;
|
||||||
|
iteratorTask->waitingForProcess = -1;
|
||||||
|
}
|
||||||
|
iteratorTask = iteratorTask->next;
|
||||||
|
} while (iteratorTask != gOSSchedulerCurrentTask);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OSSchedulerTerminate() {
|
||||||
|
UInt32 processID = gOSSchedulerCurrentTask->id;
|
||||||
|
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
|
||||||
|
|
||||||
|
OSSchedulerWakeup(processID);
|
||||||
|
sOSSchedulerPostGarbageCollectorSignal();
|
||||||
|
__asm__ volatile("int $32");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSchedulerYield(UInt64 ticks) {
|
||||||
|
gOSSchedulerCurrentTask->sleepTicks = ticks;
|
||||||
|
gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping;
|
||||||
|
__asm__ volatile("int $32");
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
|
||||||
|
void OSSpinlockLock(OSSpinlock* lock) {
|
||||||
|
while (__atomic_exchange_n(&lock->lockValue, 1, __ATOMIC_ACQUIRE)) {
|
||||||
|
while (lock->lockValue) {
|
||||||
|
__builtin_ia32_pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSpinlockUnlock(OSSpinlock *lock) {
|
||||||
|
__atomic_store_n(&lock->lockValue, 0, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSpinlockLockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
|
||||||
|
UInt64 rflags;
|
||||||
|
__asm__ volatile("pushfq; pop %0; cli" : "=r"(rflags) :: "memory"); // read flags and cli
|
||||||
|
state->interruptsEnabled = (rflags & (1 << 9)) != 0; // IF bit
|
||||||
|
|
||||||
|
OSSpinlockLock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
|
||||||
|
OSSpinlockUnlock(lock);
|
||||||
|
if (state->interruptsEnabled) __asm__ volatile("sti" ::: "memory");
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/Services/OSServiceIO.h>
|
||||||
|
#include <IO/IOConsole.h>
|
||||||
|
#include <IO/IOKeyboard.h>
|
||||||
|
|
||||||
|
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
|
||||||
|
if (fileDescriptor == 1 || fileDescriptor == 2) {
|
||||||
|
char* string = (char*)buffer;
|
||||||
|
for (UInt64 i = 0; i < length; i++) {
|
||||||
|
IOConsolePutcharacter(string[i]);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
|
||||||
|
char* readBuffer = (char*)buffer;
|
||||||
|
if (fileDescriptor == 0) {
|
||||||
|
for (UInt64 i = 0; i < count; i++) {
|
||||||
|
readBuffer[i] = IOKeyboardGetCharacter();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <OS/Services/OSServiceMemory.h>
|
||||||
|
|
||||||
|
#include <OS/OSScheduler.h>
|
||||||
|
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
|
||||||
|
UInt64 OSServiceMemoryAllocate(UInt64 size) {
|
||||||
|
if (size == 0) return 0;
|
||||||
|
OSProcess* currentProcess = gOSSchedulerCurrentTask->process;
|
||||||
|
UInt64 addressToReturn = currentProcess->heapCurrentPointer;
|
||||||
|
|
||||||
|
UInt64 pages_needed = (size + (kVMPageSize-1)) / kVMPageSize;
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < pages_needed; i++) {
|
||||||
|
void* phycialAddress = VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!phycialAddress) return 0;
|
||||||
|
|
||||||
|
VMVirtualMemoryMapPage((UInt64*)currentProcess->physicalPML4, (UInt64)phycialAddress, currentProcess->heapCurrentPointer, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||||
|
MemorySet((void*)PHYS_TO_HHDM((UInt64)phycialAddress), 0, kVMPageSize);
|
||||||
|
|
||||||
|
currentProcess->heapCurrentPointer += kVMPageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addressToReturn;
|
||||||
|
}
|
||||||
@@ -0,0 +1,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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <VM/Heap.h>
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
extern UInt64* gVMKernelPML4;
|
||||||
|
static VMHeapBlockHeader* sVMHeapListHead = nullptr;
|
||||||
|
static OSSpinlock sVMHeapLock = {0};
|
||||||
|
|
||||||
|
static void sVMHeapCombineForward(VMHeapBlockHeader* current) {
|
||||||
|
if (!current->next || !current->next->isFree) return;
|
||||||
|
current->size += sizeof(VMHeapBlockHeader) + current->next->size;
|
||||||
|
current->next = current->next->next;
|
||||||
|
if (current->next) current->next->previous = current; // what the fuck
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMHeapInitialize() {
|
||||||
|
UInt64 heapStart = kVMKernelHeapStart;
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < kVMHeapSizePages; i++) {
|
||||||
|
UInt64 physical = (UInt64)VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!physical) OSPanic("OOM during heap init");
|
||||||
|
|
||||||
|
UInt64 virtual = heapStart + (i * kVMPageSize);
|
||||||
|
VMVirtualMemoryMapPage(gVMKernelPML4, physical, virtual, PTE_PRESENT | PTE_RW);
|
||||||
|
}
|
||||||
|
|
||||||
|
sVMHeapListHead = (VMHeapBlockHeader*)heapStart;
|
||||||
|
sVMHeapListHead->magic = kVMHeapBlockHeaderMagic;
|
||||||
|
sVMHeapListHead->size = (kVMHeapSizePages * kVMPageSize) - sizeof(VMHeapBlockHeader);
|
||||||
|
sVMHeapListHead->isFree = true;
|
||||||
|
sVMHeapListHead->next = nullptr;
|
||||||
|
sVMHeapListHead->previous = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* sVMHeapAllocateInternal(UInt64 size) {
|
||||||
|
if (size == 0) return nullptr;
|
||||||
|
UInt64 alignedSize = (size + 15) & ~15;
|
||||||
|
|
||||||
|
VMHeapBlockHeader* current = sVMHeapListHead;
|
||||||
|
while (current) {
|
||||||
|
if (current->isFree && current->size >= alignedSize) {
|
||||||
|
if (current->size > alignedSize + sizeof(VMHeapBlockHeader) + 16) {
|
||||||
|
VMHeapBlockHeader* new_block = (VMHeapBlockHeader*)((UInt64)current + sizeof(VMHeapBlockHeader) + alignedSize);
|
||||||
|
new_block->size = current->size - alignedSize - sizeof(VMHeapBlockHeader);
|
||||||
|
new_block->isFree = true;
|
||||||
|
new_block->next = current->next;
|
||||||
|
new_block->previous = current;
|
||||||
|
new_block->magic = kVMHeapBlockHeaderMagic;
|
||||||
|
|
||||||
|
if (current->next) current->next->previous = new_block;
|
||||||
|
current->next = new_block;
|
||||||
|
current->size = alignedSize;
|
||||||
|
}
|
||||||
|
current->isFree = false;
|
||||||
|
return (void*)((UInt64)current + sizeof(VMHeapBlockHeader));
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sVMHeapFreeInternal(void* pointer) {
|
||||||
|
if (!pointer) return;
|
||||||
|
|
||||||
|
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
|
||||||
|
if (current->magic != kVMHeapBlockHeaderMagic) return;
|
||||||
|
|
||||||
|
current->isFree = true;
|
||||||
|
if (current->next && current->next->isFree) sVMHeapCombineForward(current);
|
||||||
|
if (current->previous && current->previous->isFree) sVMHeapCombineForward(current->previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* VMHeapAllocate(UInt64 size) {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMHeapLock, &state);
|
||||||
|
|
||||||
|
void* result = sVMHeapAllocateInternal(size);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMHeapFree(void* pointer) {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMHeapLock, &state);
|
||||||
|
|
||||||
|
sVMHeapFreeInternal(pointer);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* VMHeapResize(void* pointer, UInt64 newSize) {
|
||||||
|
if (!pointer) return VMHeapAllocate(newSize);
|
||||||
|
if (newSize == 0) {
|
||||||
|
VMHeapFree(pointer);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMHeapLock, &state);
|
||||||
|
|
||||||
|
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
|
||||||
|
if (current->size >= newSize) {
|
||||||
|
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current->next && current->next->isFree &&
|
||||||
|
(current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable
|
||||||
|
sVMHeapCombineForward(current);
|
||||||
|
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* newPointer = sVMHeapAllocateInternal(newSize);
|
||||||
|
if (newPointer) {
|
||||||
|
MemoryCopy(newPointer, pointer, current->size);
|
||||||
|
sVMHeapFreeInternal(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
|
||||||
|
return newPointer;
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <lib/String.h>
|
||||||
|
#include <lib/Math.h>
|
||||||
|
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include "bootinfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
UInt8* gVMPhycalMemoryBitmap = nullptr;
|
||||||
|
UInt64 gVMPhycalMemoryBitmapSize = 0;
|
||||||
|
UInt64 gVMPhycalMemoryTotalMemorySize = 0;
|
||||||
|
|
||||||
|
static OSSpinlock sVMPMMLock = {0};
|
||||||
|
|
||||||
|
extern UInt64 _kernel_start;
|
||||||
|
extern UInt64 _kernel_end;
|
||||||
|
|
||||||
|
UInt64 VMPhysicalMemoryGetTotalMemorySize() {
|
||||||
|
return gVMPhycalMemoryTotalMemorySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
|
||||||
|
UInt64 descriptorCount = memoryMap->mapSize / memoryMap->descriptorSize;
|
||||||
|
UInt64 maxPhysicalAddress = 0;
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < descriptorCount; i++) {
|
||||||
|
OSMemoryDescriptor* descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
|
||||||
|
|
||||||
|
if (descriptor->type == kOSMemoryTypeMappedIO ||
|
||||||
|
descriptor->type == kOSMemoryTypeMappedIOPortSpace ||
|
||||||
|
descriptor->type == kOSMemoryTypeUnusable ||
|
||||||
|
descriptor->type == kOSMemoryTypeReserved ||
|
||||||
|
descriptor->type == kOSMemoryTypePalCode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 nominee = descriptor->physicalStart + (descriptor->pageCount * kVMPageSize);
|
||||||
|
if (nominee > maxPhysicalAddress) {
|
||||||
|
maxPhysicalAddress = nominee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gVMPhycalMemoryTotalMemorySize = maxPhysicalAddress;
|
||||||
|
|
||||||
|
UInt64 totalPageCount = maxPhysicalAddress / kVMPageSize;
|
||||||
|
UInt64 bitmapSize = (totalPageCount + 7) / 8;
|
||||||
|
OSMemoryDescriptor *bitmapHostDescriptor = nullptr;
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < descriptorCount; i++) {
|
||||||
|
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
|
||||||
|
|
||||||
|
if ((descriptor->type == kOSMemoryTypeConventional) &&
|
||||||
|
((descriptor->pageCount * kVMPageSize) >= bitmapSize) &&
|
||||||
|
(descriptor->physicalStart >= kVMSafeSpaceStartAddress)) {
|
||||||
|
bitmapHostDescriptor = descriptor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitmapHostDescriptor == nullptr) {
|
||||||
|
OSPanic("PMM: Not enough RAM for memory bitmap!");
|
||||||
|
}
|
||||||
|
|
||||||
|
gVMPhycalMemoryBitmap = (UInt8*)bitmapHostDescriptor->physicalStart;
|
||||||
|
gVMPhycalMemoryBitmapSize = bitmapSize;
|
||||||
|
|
||||||
|
MemorySet(gVMPhycalMemoryBitmap, 0xFF, bitmapSize);
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < descriptorCount; i++) {
|
||||||
|
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
|
||||||
|
|
||||||
|
if (descriptor->type != kOSMemoryTypeConventional) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 startAddress = descriptor->physicalStart;
|
||||||
|
UInt64 endAddress = startAddress + (descriptor->pageCount * kVMPageSize);
|
||||||
|
|
||||||
|
for (UInt64 addr = startAddress; addr < endAddress; addr += kVMPageSize) {
|
||||||
|
BITMAP_UNSET(gVMPhycalMemoryBitmap, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 kernelStart = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_start);
|
||||||
|
UInt64 kernelEnd = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_end);
|
||||||
|
|
||||||
|
UInt64 bitmapStart = (UInt64)gVMPhycalMemoryBitmap;
|
||||||
|
UInt64 bitmapEnd = bitmapStart + gVMPhycalMemoryBitmapSize;
|
||||||
|
|
||||||
|
for (UInt64 addr = 0; addr < kVMSafeSpaceStartAddress; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
|
||||||
|
for (UInt64 addr = kernelStart; addr < kernelEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
|
||||||
|
for (UInt64 addr = bitmapStart; addr < bitmapEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* VMPhysicalMemoryAllocatePage() {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMPMMLock, &state);
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) {
|
||||||
|
if (gVMPhycalMemoryBitmap[i] == 0xFF) continue;
|
||||||
|
|
||||||
|
for (UInt64 bit = 0; bit < 8; bit++) {
|
||||||
|
if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) {
|
||||||
|
UInt64 address = (i * 8 + bit) * kVMPageSize;
|
||||||
|
BITMAP_SET(gVMPhycalMemoryBitmap, address);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
|
||||||
|
return (void*)address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
|
||||||
|
return nullptr; // Out of memory
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMPhysicalMemoryFreePage(void* address) {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMPMMLock, &state);
|
||||||
|
|
||||||
|
BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
#include <VM/VMM.h>
|
||||||
|
#include <VM/PMM.h>
|
||||||
|
|
||||||
|
#include <OS/OSPanic.h>
|
||||||
|
#include <OS/OSSpinlock.h>
|
||||||
|
|
||||||
|
#include <GDT.h>
|
||||||
|
#include <IDT.h>
|
||||||
|
|
||||||
|
#include <lib/String.h>
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include "bootinfo.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kVMUserStackTop = 0x70000000,
|
||||||
|
kVMUserStackSize = 0x4000
|
||||||
|
};
|
||||||
|
|
||||||
|
UInt64* gVMKernelPML4 = nullptr;
|
||||||
|
UInt64 gVMKernelPML4Physical = 0;
|
||||||
|
static OSSpinlock sVMVMMlock = {0};
|
||||||
|
static bool isInitialized = false;
|
||||||
|
|
||||||
|
extern UInt64 _kernel_start;
|
||||||
|
extern UInt64 _kernel_end;
|
||||||
|
extern UInt8* gVMPhycalMemoryBitmap;
|
||||||
|
extern UInt64 gVMPhycalMemoryBitmapSize;
|
||||||
|
extern HALGlobalDescriptorTable gHALGlobalDescriptorTable[];
|
||||||
|
extern HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[];
|
||||||
|
extern UInt8 gHALDoubleFaultStack[];
|
||||||
|
extern UInt8 stack_guard;
|
||||||
|
|
||||||
|
static UInt64* sVMGetVirtualTable(UInt64 phys) {
|
||||||
|
if (isInitialized) return (UInt64*)PHYS_TO_HHDM(phys);
|
||||||
|
return (UInt64*)phys;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
|
||||||
|
UInt64 pt_idx = VMM_PT_INDEX(virt);
|
||||||
|
UInt64 pd_idx = VMM_PD_INDEX(virt);
|
||||||
|
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||||
|
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||||
|
|
||||||
|
UInt64* pml4_virt = pml4;
|
||||||
|
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
|
||||||
|
|
||||||
|
UInt64 table_flags = PTE_PRESENT | PTE_RW | (flags & PTE_USER);
|
||||||
|
|
||||||
|
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
|
||||||
|
UInt64* addr = VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!addr) return nullptr;
|
||||||
|
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
|
||||||
|
MemorySet(addr_virt, 0, kVMPageSize);
|
||||||
|
pml4_virt[pml4_idx] = (UInt64)addr | table_flags;
|
||||||
|
} else {
|
||||||
|
pml4_virt[pml4_idx] |= (flags & PTE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64* pdpt = (UInt64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
|
||||||
|
UInt64* pdpt_virt = sVMGetVirtualTable((UInt64)pdpt);
|
||||||
|
|
||||||
|
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) {
|
||||||
|
UInt64* addr = VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!addr) return nullptr;
|
||||||
|
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
|
||||||
|
MemorySet(addr_virt, 0, kVMPageSize);
|
||||||
|
pdpt_virt[pdpt_idx] = (UInt64)addr | table_flags;
|
||||||
|
} else {
|
||||||
|
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64* pd = (UInt64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
|
||||||
|
UInt64* pd_virt = sVMGetVirtualTable((UInt64)pd);
|
||||||
|
|
||||||
|
if (!(pd_virt[pd_idx] & PTE_PRESENT)) {
|
||||||
|
UInt64* addr = VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!addr) return nullptr;
|
||||||
|
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
|
||||||
|
MemorySet(addr_virt, 0, kVMPageSize);
|
||||||
|
pd_virt[pd_idx] = (UInt64)addr | table_flags;
|
||||||
|
} else {
|
||||||
|
pd_virt[pd_idx] |= (flags & PTE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64* pt = (UInt64*)PTE_GET_ADDR(pd_virt[pd_idx]);
|
||||||
|
UInt64* pt_virt = sVMGetVirtualTable((UInt64)pt);
|
||||||
|
pt_virt[pt_idx] = phys | flags;
|
||||||
|
|
||||||
|
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
|
||||||
|
|
||||||
|
return (UInt64*)virt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) {
|
||||||
|
UInt64 pt_idx = VMM_PT_INDEX(virt);
|
||||||
|
UInt64 pd_idx = VMM_PD_INDEX(virt);
|
||||||
|
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||||
|
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||||
|
|
||||||
|
UInt64* pml4_virt = pml4;
|
||||||
|
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
|
||||||
|
|
||||||
|
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) return;
|
||||||
|
UInt64* pdpt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pml4_virt[pml4_idx]));
|
||||||
|
|
||||||
|
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) return;
|
||||||
|
UInt64* pd_virt = sVMGetVirtualTable(PTE_GET_ADDR(pdpt_virt[pdpt_idx]));
|
||||||
|
|
||||||
|
if (!(pd_virt[pd_idx] & PTE_PRESENT)) return;
|
||||||
|
UInt64* pt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pd_virt[pd_idx]));
|
||||||
|
|
||||||
|
pt_virt[pt_idx] = 0;
|
||||||
|
|
||||||
|
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMVMMlock, &state);
|
||||||
|
|
||||||
|
UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, phys, virt, flags);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMVMMlock, &state);
|
||||||
|
|
||||||
|
sVMVirtualMemoryUnmapPageInternal(pml4, virt);
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VMLoadCR3(UInt64 pml4_addr) {
|
||||||
|
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMVirtualMemoryInitialize(Bootinfo* info) {
|
||||||
|
gVMKernelPML4Physical = (UInt64)VMPhysicalMemoryAllocatePage();
|
||||||
|
gVMKernelPML4 = (UInt64*)gVMKernelPML4Physical;
|
||||||
|
MemorySet(gVMKernelPML4, 0, kVMPageSize);
|
||||||
|
|
||||||
|
UInt64 k_virt_start = (UInt64)&_kernel_start;
|
||||||
|
UInt64 k_virt_end = (UInt64)&_kernel_end;
|
||||||
|
|
||||||
|
UInt64 fb_start = (UInt64)info->framebuffer.base;
|
||||||
|
UInt64 fb_end = fb_start + info->framebuffer.baseSize;
|
||||||
|
UInt64 fb_size = fb_end - fb_start;
|
||||||
|
|
||||||
|
UInt64 max_mem = VMPhysicalMemoryGetTotalMemorySize();
|
||||||
|
for (UInt64 i = 0; i < max_mem; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, i, PHYS_TO_HHDM(i), PTE_PRESENT | PTE_RW);
|
||||||
|
for (UInt64 i = k_virt_start; i < k_virt_end; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, KERNEL_VIRT_TO_PHYS(i), i, PTE_PRESENT | PTE_RW);
|
||||||
|
for (UInt64 i = 0; i < fb_size; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, fb_start + i, FB_VIRT_BASE + i, PTE_PRESENT | PTE_RW);
|
||||||
|
VMVirtualMemoryUnmapPage(gVMKernelPML4, (UInt64)&stack_guard);
|
||||||
|
|
||||||
|
gVMPhycalMemoryBitmap = (UInt8*)PHYS_TO_HHDM((UInt64)gVMPhycalMemoryBitmap);
|
||||||
|
info->framebuffer.base = (UInt32*)FB_VIRT_BASE;
|
||||||
|
VMLoadCR3(gVMKernelPML4Physical);
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 VMVirtualMemoryCreateAddressSpace() {
|
||||||
|
OSSpinlockState state;
|
||||||
|
OSSpinlockLockIRQ(&sVMVMMlock, &state);
|
||||||
|
|
||||||
|
UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!phys) {
|
||||||
|
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys);
|
||||||
|
MemorySet(virt, 0, kVMPageSize);
|
||||||
|
|
||||||
|
UInt64* kernel_pml4_virt = sVMGetVirtualTable((UInt64)gVMKernelPML4);
|
||||||
|
|
||||||
|
for (UInt32 i = 256; i < 512; i++) {
|
||||||
|
virt[i] = kernel_pml4_virt[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||||
|
return phys;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 VMGetCurrentCR3() {
|
||||||
|
UInt64 cr3;
|
||||||
|
__asm__ volatile("mov %%cr3, %0" : "=r"(cr3));
|
||||||
|
return cr3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VMVirtualMemorySetupUserStack(UInt64* pml4_phys) {
|
||||||
|
UInt64 stack_bottom = kVMUserStackTop - kVMUserStackSize;
|
||||||
|
for (UInt64 addr = stack_bottom; addr < kVMUserStackTop; addr += 4096) {
|
||||||
|
void* phys = VMPhysicalMemoryAllocatePage();
|
||||||
|
if (!phys) OSPanic("OOM in user stack setup");
|
||||||
|
MemorySet((void*)PHYS_TO_HHDM((UInt64)phys), 0, 4096);
|
||||||
|
VMVirtualMemoryMapPage((UInt64*)pml4_phys, (UInt64)phys, addr, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
// just fucking kill me already
|
||||||
|
|
||||||
|
#include <GDT.h>
|
||||||
|
|
||||||
|
HALGlobalDescriptorTable gHALGlobalDescriptorTable[kHALGDTEntries];
|
||||||
|
HALGlobalDescriptorTablePointer gHALGlobalDescriptorTablePointer;
|
||||||
|
HALTaskStateSegment gHALTaskStateSegment;
|
||||||
|
UInt8 gHALDoubleFaultStack[4096] = {0};
|
||||||
|
|
||||||
|
static void sHALGlobalDescriptorTableSetGate(int number, UInt64 base, UInt64 limit, UInt8 access, UInt8 granularity) {
|
||||||
|
gHALGlobalDescriptorTable[number].baseLow = (base & 0xFFFF); // left only low 16bit
|
||||||
|
gHALGlobalDescriptorTable[number].baseMiddle = (base >> 16) & 0xFF; // 3rd address byte
|
||||||
|
gHALGlobalDescriptorTable[number].baseHigh = (base >> 24) & 0xFF; // 4th address byte
|
||||||
|
|
||||||
|
gHALGlobalDescriptorTable[number].limitLow = (limit & 0xFFFF);
|
||||||
|
gHALGlobalDescriptorTable[number].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19)
|
||||||
|
gHALGlobalDescriptorTable[number].granularity |= granularity & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags)
|
||||||
|
gHALGlobalDescriptorTable[number].access = access;
|
||||||
|
|
||||||
|
// fuck intel
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void sHALTaskStateSegmentWrite(int number) {
|
||||||
|
UInt64 base = (UInt64)&gHALTaskStateSegment;
|
||||||
|
UInt64 limit = sizeof(gHALTaskStateSegment);
|
||||||
|
UInt64 access = 0x89; // TSS_PRESENT | TSS_EXECUTABLE | TSS_ACCESSED;
|
||||||
|
UInt64 granularity = 0;
|
||||||
|
|
||||||
|
sHALGlobalDescriptorTableSetGate(number, base, limit, access, granularity);
|
||||||
|
*((UInt64*)&gHALGlobalDescriptorTable[number+1]) = (base >> 32); // really scary but not really hard
|
||||||
|
// just direct write 8bytes to num+1
|
||||||
|
// basically a hack but at this point i dont care
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void gdt_flush(UInt64 gdt_ptr_addr); // entry.asm
|
||||||
|
|
||||||
|
void HALGlobalDescriptorTableInitialize() {
|
||||||
|
gHALGlobalDescriptorTablePointer.limit = (sizeof(HALGlobalDescriptorTable) * kHALGDTEntries) - 1;
|
||||||
|
gHALGlobalDescriptorTablePointer.base = (UInt64)&gHALGlobalDescriptorTable;
|
||||||
|
|
||||||
|
// 0: Null
|
||||||
|
sHALGlobalDescriptorTableSetGate(0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
// 1: Kernel Code (Ring 0)
|
||||||
|
// Access: 0x9A (Present, Ring0, Exec/Read)
|
||||||
|
// Granularity: 0x20 (Long Mode bit) access ring 0 code exec code readable
|
||||||
|
sHALGlobalDescriptorTableSetGate(1, 0, 0, 0x9A, 0x20); // 0x9A = 1 00 1 1 0 1
|
||||||
|
// 0x20 = 0010 0000 bit 5 is "Long mode"
|
||||||
|
// 2: Kernel Data (Ring 0)
|
||||||
|
// Access: 0x92 (Present, Ring0, Read/Write)
|
||||||
|
sHALGlobalDescriptorTableSetGate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
|
||||||
|
|
||||||
|
// 3: User Data (Ring 3)
|
||||||
|
// Access: 0xF2 (Present, Ring3, Read/Write)
|
||||||
|
sHALGlobalDescriptorTableSetGate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
|
||||||
|
|
||||||
|
// 4: User Code (Ring 3)
|
||||||
|
// Access: 0xFA (Present, Ring3, RWX)
|
||||||
|
sHALGlobalDescriptorTableSetGate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
|
||||||
|
|
||||||
|
for (UInt64 i = 0; i < sizeof(HALTaskStateSegment); i++) ((UInt8*)&gHALTaskStateSegment)[i] = 0; // zeroifying tss struct
|
||||||
|
|
||||||
|
gHALTaskStateSegment.iomapBase = sizeof(HALTaskStateSegment);
|
||||||
|
gHALTaskStateSegment.ist1 = (UInt64)gHALDoubleFaultStack + sizeof(gHALDoubleFaultStack);
|
||||||
|
sHALTaskStateSegmentWrite(5);
|
||||||
|
|
||||||
|
gdt_flush((UInt64)&gHALGlobalDescriptorTablePointer);
|
||||||
|
|
||||||
|
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
|
||||||
|
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <IDT.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[256];
|
||||||
|
HALInterruptsDescriptorTablePointer gHALInterruptsDescriptorTablePointer;
|
||||||
|
|
||||||
|
extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3();
|
||||||
|
extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7();
|
||||||
|
extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11();
|
||||||
|
extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15();
|
||||||
|
extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19();
|
||||||
|
extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23();
|
||||||
|
extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27();
|
||||||
|
extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31();
|
||||||
|
extern void irq0(void); extern void irq1(void);
|
||||||
|
|
||||||
|
extern void idt_load(UInt64); // asm: lidt [rdi] / ret
|
||||||
|
|
||||||
|
static void sHALInterruptsDescriptorTableSetGate(int number, UInt64 handler, UInt16 selector, UInt8 flags) {
|
||||||
|
gHALInterruptsDescriptorTable[number].offsetLow = handler & 0xFFFF;
|
||||||
|
gHALInterruptsDescriptorTable[number].offsetMid = (handler >> 16) & 0xFFFF;
|
||||||
|
gHALInterruptsDescriptorTable[number].offsetHigh = (handler >> 32) & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
gHALInterruptsDescriptorTable[number].selector = selector; // 0x08 (Kernel Code)
|
||||||
|
gHALInterruptsDescriptorTable[number].ist = 0;
|
||||||
|
gHALInterruptsDescriptorTable[number].attributes = flags;
|
||||||
|
gHALInterruptsDescriptorTable[number].reserved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HALInterruptsDescriptorTableInitialize() {
|
||||||
|
gHALInterruptsDescriptorTablePointer.limit = (sizeof(HALInterruptsDescriptorTableEntry) * 256) - 1;
|
||||||
|
gHALInterruptsDescriptorTablePointer.base = (UInt64)&gHALInterruptsDescriptorTable;
|
||||||
|
|
||||||
|
const UInt8 flags = 0x8E;
|
||||||
|
const UInt8 selector = 0x08;
|
||||||
|
|
||||||
|
|
||||||
|
sHALInterruptsDescriptorTableSetGate(0, (UInt64)isr0, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(1, (UInt64)isr1, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(2, (UInt64)isr2, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(3, (UInt64)isr3, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(4, (UInt64)isr4, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(5, (UInt64)isr5, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(6, (UInt64)isr6, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(7, (UInt64)isr7, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(8, (UInt64)isr8, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(9, (UInt64)isr9, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(10, (UInt64)isr10, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(11, (UInt64)isr11, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(12, (UInt64)isr12, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(13, (UInt64)isr13, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(14, (UInt64)isr14, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(15, (UInt64)isr15, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(16, (UInt64)isr16, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(17, (UInt64)isr17, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(18, (UInt64)isr18, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(19, (UInt64)isr19, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(20, (UInt64)isr20, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(21, (UInt64)isr21, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(22, (UInt64)isr22, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(23, (UInt64)isr23, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(24, (UInt64)isr24, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(25, (UInt64)isr25, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(26, (UInt64)isr26, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(27, (UInt64)isr27, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(28, (UInt64)isr28, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(29, (UInt64)isr29, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(30, (UInt64)isr30, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(31, (UInt64)isr31, selector, flags);
|
||||||
|
|
||||||
|
gHALInterruptsDescriptorTable[8].ist = 1; // TSS
|
||||||
|
gHALInterruptsDescriptorTable[13].ist = 1;
|
||||||
|
gHALInterruptsDescriptorTable[14].ist = 1;
|
||||||
|
|
||||||
|
sHALInterruptsDescriptorTableSetGate(32, (UInt64)irq0, selector, flags);
|
||||||
|
sHALInterruptsDescriptorTableSetGate(33, (UInt64)irq1, selector, flags);
|
||||||
|
|
||||||
|
__asm__ volatile ("lidt %0" : : "m"(gHALInterruptsDescriptorTablePointer));
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <OSCPU.h>
|
||||||
|
|
||||||
|
#define MSR_GS_BASE 0xC0000101
|
||||||
|
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||||
|
|
||||||
|
OSCPUData gOSBootCPU = {0};
|
||||||
|
|
||||||
|
static inline void CPUID(UInt32 leaf, UInt32 subleaf, UInt32 *eax, UInt32 *ebx, UInt32 *ecx, UInt32 *edx) {
|
||||||
|
__asm__ volatile("cpuid"
|
||||||
|
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||||
|
: "a"(leaf), "c"(subleaf)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void WRMSR(UInt32 msr, UInt64 val) {
|
||||||
|
UInt32 low = (UInt32)val;
|
||||||
|
UInt32 high = (UInt32)(val >> 32);
|
||||||
|
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCPUInitialize(UInt64 kernelStackTop) {
|
||||||
|
gOSBootCPU.kernelStackPointer = kernelStackTop;
|
||||||
|
gOSBootCPU.selfAddress = (UInt64)&gOSBootCPU;
|
||||||
|
WRMSR(MSR_KERNEL_GS_BASE, (UInt64)&gOSBootCPU);
|
||||||
|
|
||||||
|
|
||||||
|
UInt32 eax, ebx, ecx, edx;
|
||||||
|
|
||||||
|
CPUID(0, 0, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
UInt32* vendorPointer = (UInt32*)gOSBootCPU.vendorID;
|
||||||
|
vendorPointer[0] = ebx;
|
||||||
|
vendorPointer[1] = edx;
|
||||||
|
vendorPointer[2] = ecx;
|
||||||
|
gOSBootCPU.vendorID[12] = '\0';
|
||||||
|
|
||||||
|
CPUID(1, 0, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
gOSBootCPU.family = (eax >> 8) & 0xF;
|
||||||
|
gOSBootCPU.model = (eax >> 4) & 0xF;
|
||||||
|
if (gOSBootCPU.family == 6 || gOSBootCPU.family == 15) {
|
||||||
|
gOSBootCPU.model += ((eax >> 16) & 0xF) << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureFPU;
|
||||||
|
if (edx & (1 << 4)) gOSBootCPU.features |= kCPUFeatureTSC;
|
||||||
|
if (edx & (1 << 5)) gOSBootCPU.features |= kCPUFeatureMSR;
|
||||||
|
if (edx & (1 << 6)) gOSBootCPU.features |= kCPUFeaturePAE;
|
||||||
|
if (edx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureAPIC;
|
||||||
|
if (edx & (1 << 12)) gOSBootCPU.features |= kCPUFeatureMTRR;
|
||||||
|
|
||||||
|
if (edx & (1 << 25)) gOSBootCPU.features |= kCPUFeatureSSE;
|
||||||
|
if (edx & (1 << 26)) gOSBootCPU.features |= kCPUFeatureSSE2;
|
||||||
|
if (ecx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureSSE3;
|
||||||
|
if (ecx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureSSSE3;
|
||||||
|
if (ecx & (1 << 19)) gOSBootCPU.features |= kCPUFeatureSSE4_1;
|
||||||
|
if (ecx & (1 << 20)) gOSBootCPU.features |= kCPUFeatureSSE4_2;
|
||||||
|
|
||||||
|
if (ecx & (1 << 28)) gOSBootCPU.features |= kCPUFeatureAVX;
|
||||||
|
if (ecx & (1 << 29)) gOSBootCPU.features |= kCPUFeatureF16C;
|
||||||
|
if (ecx & (1 << 30)) gOSBootCPU.features |= kCPUFeatureRDRAND;
|
||||||
|
|
||||||
|
if (ecx & (1 << 31)) gOSBootCPU.features |= kCPUFeatureHypervisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean OSCPUHasFeature(OSCPUFeature feature) {
|
||||||
|
return (gOSBootCPU.features & feature) != 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <PIC.h>
|
||||||
|
#include <IO.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
|
||||||
|
UInt16 HALLegacyInterruptControllerRemap() {
|
||||||
|
UInt8 currentMaster = IOPortRead8(kIOMasterData);
|
||||||
|
UInt8 currentSlave = IOPortRead8(kIOSlaveData);
|
||||||
|
|
||||||
|
// initialization; icw1
|
||||||
|
IOPortWrite8WithWait(kIOMasterCommand, 0x11);
|
||||||
|
IOPortWrite8WithWait(kIOSlaveCommand, 0x11);
|
||||||
|
|
||||||
|
// icw2
|
||||||
|
IOPortWrite8WithWait(kIOMasterData, 0x20); // master now controlling idt[32..39]
|
||||||
|
IOPortWrite8WithWait(kIOSlaveData, 0x28); // idt[40..47]
|
||||||
|
|
||||||
|
// icw3
|
||||||
|
IOPortWrite8WithWait(kIOMasterData, 0x04); // slave on irq2
|
||||||
|
IOPortWrite8WithWait(kIOSlaveData, 0x02); // assign id = 2 to slave
|
||||||
|
|
||||||
|
// icw4; 0x01 -- 8086 mode
|
||||||
|
IOPortWrite8WithWait(kIOMasterData, 0x01);
|
||||||
|
IOPortWrite8WithWait(kIOSlaveData, 0x01);
|
||||||
|
|
||||||
|
IOPortWrite8WithWait(kIOMasterData, 0xFD); // 1111 1101
|
||||||
|
// 0 -- means 'on'
|
||||||
|
IOPortWrite8WithWait(kIOSlaveData, 0xFF); // Everything ON
|
||||||
|
|
||||||
|
return ((UInt16) currentMaster << 8) | currentSlave;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
; Copyright (c) 2025 0xKarinyash
|
; Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
bits 64
|
bits 64
|
||||||
|
|
||||||
@@ -27,9 +27,10 @@ stack_guard:
|
|||||||
global stack_bottom
|
global stack_bottom
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
resb 16384
|
resb 16384
|
||||||
|
global stack_top
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|
||||||
section .text
|
section .text.entry
|
||||||
global _start
|
global _start
|
||||||
global gdt_flush
|
global gdt_flush
|
||||||
extern kmain
|
extern kmain
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
// Copyright (c) 2025 0xKarinyash
|
|
||||||
|
|
||||||
// just fucking kill me already
|
|
||||||
|
|
||||||
#include <gdt.h>
|
|
||||||
|
|
||||||
GDTDescriptor gdt[5];
|
|
||||||
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) * 5) - 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 can't exec
|
|
||||||
|
|
||||||
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // hack. zeroifying tss struct
|
|
||||||
|
|
||||||
tss.iomap_base = sizeof(TSS);
|
|
||||||
tss.ist1 = (u64)double_fault_stack + sizeof(double_fault_stack);
|
|
||||||
write_tss(3);
|
|
||||||
|
|
||||||
gdt_flush((u64)&gdt_ptr);
|
|
||||||
|
|
||||||
// telling cpu that TSS info located at gdt[3]; offset = 3 * 8 = 24 = 0x18
|
|
||||||
__asm__ volatile ("ltr %%ax" :: "a" (0x18));
|
|
||||||
}
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user