Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d32444da2 | |||
| 55ea8fc533 | |||
| 3f3a026432 | |||
| 8a6994ebd8 | |||
| 3525c81d9e |
+2
-1
@@ -1,4 +1,5 @@
|
||||
.cache
|
||||
build*
|
||||
.venv
|
||||
initrd/image.cpio
|
||||
initrd/image.cpio
|
||||
initramfs/*
|
||||
+19
-4
@@ -6,15 +6,30 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||
|
||||
add_subdirectory(bootloader)
|
||||
add_subdirectory(kernel)
|
||||
|
||||
find_program(MCOPY_EXE mcopy)
|
||||
find_program(MKFS_EXE mkfs.fat)
|
||||
find_program(CPIO_EXE cpio)
|
||||
find_program(QEMU_EXE qemu-system-x86_64)
|
||||
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)
|
||||
|
||||
if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
|
||||
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
|
||||
|
||||
@@ -27,7 +42,7 @@ if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}
|
||||
COMMAND sh -c "find . -mindepth 1 ! -name '*.cpio' -print0 | ${CPIO_EXE} --null -ov -H newc > \"${INITRAMFS_CPIO_FILE}\""
|
||||
WORKING_DIRECTORY ${INITRAMFS_SRC_DIR}
|
||||
DEPENDS ${INIT_FILES}
|
||||
DEPENDS ${INIT_FILES} init
|
||||
VERBATIM
|
||||
COMMENT "Packing initramfs to cpio..."
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ set(UEFI_COMPILE_OPTIONS
|
||||
-std=c23
|
||||
-target x86_64-unknown-windows-msvc
|
||||
-Wall -Wextra
|
||||
-fno-builtin
|
||||
$<$<CONFIG:Release>:-Werror>
|
||||
)
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Meow!!
|
||||
@@ -1 +0,0 @@
|
||||
Nyaaa
|
||||
@@ -1,5 +1,5 @@
|
||||
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_REQUIRED ON)
|
||||
@@ -9,7 +9,7 @@ if (NOT DEFINED ARCH)
|
||||
set(ARCH "x86_64")
|
||||
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
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define CPU_FEAT_FPU (1ULL << 0)
|
||||
#define CPU_FEAT_TSC (1ULL << 1)
|
||||
#define CPU_FEAT_MSR (1ULL << 2)
|
||||
#define CPU_FEAT_APIC (1ULL << 3)
|
||||
#define CPU_FEAT_MTRR (1ULL << 4)
|
||||
#define CPU_FEAT_PAE (1ULL << 5)
|
||||
|
||||
#define CPU_FEAT_SSE (1ULL << 10)
|
||||
#define CPU_FEAT_SSE2 (1ULL << 11)
|
||||
#define CPU_FEAT_SSE3 (1ULL << 12)
|
||||
#define CPU_FEAT_SSSE3 (1ULL << 13)
|
||||
#define CPU_FEAT_SSE4_1 (1ULL << 14)
|
||||
#define CPU_FEAT_SSE4_2 (1ULL << 15)
|
||||
|
||||
#define CPU_FEAT_AVX (1ULL << 20)
|
||||
#define CPU_FEAT_F16C (1ULL << 21)
|
||||
#define CPU_FEAT_RDRAND (1ULL << 22)
|
||||
|
||||
#define CPU_FEAT_HYPERVISOR (1ULL << 30)
|
||||
|
||||
typedef struct {
|
||||
u64 user_rsp;
|
||||
u64 kernel_rsp;
|
||||
u64 self;
|
||||
|
||||
u64 features;
|
||||
char vendor[13];
|
||||
u32 family;
|
||||
u32 model;
|
||||
} cpu_info;
|
||||
|
||||
extern cpu_info g_cpu;
|
||||
|
||||
void cpuinfo_init(u64 kernel_stack_top);
|
||||
bool cpu_has(u64 feature);
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MSR_EFER 0xC0000080
|
||||
#define MSR_STAR 0xC0000081
|
||||
#define MSR_LSTAR 0xC0000082
|
||||
#define MSR_FMASK 0xC0000084
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
#define EFER_SCE 0x01 // System Call Enable
|
||||
|
||||
typedef enum {
|
||||
SYS_EXIT,
|
||||
SYS_EXEC,
|
||||
SYS_WRITE,
|
||||
} syscalls;
|
||||
|
||||
void syscall_init();
|
||||
@@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
#include <core/scheduler.h>
|
||||
|
||||
bool exec_init(process* p, const char* path);
|
||||
void init_task_entry();
|
||||
@@ -4,4 +4,5 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u64 shitrand();
|
||||
void rng_init();
|
||||
u64 krand();
|
||||
@@ -3,15 +3,30 @@
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef enum process_state {
|
||||
DEAD,
|
||||
RUNNING,
|
||||
} process_state;
|
||||
|
||||
typedef struct process {
|
||||
u64 pid;
|
||||
process_state state;
|
||||
u64 pml4_phys;
|
||||
struct process* parent;
|
||||
char name[32];
|
||||
} process;
|
||||
|
||||
typedef struct task {
|
||||
u64 rsp;
|
||||
struct task* next;
|
||||
u32 id;
|
||||
u32 sleep_ticks;
|
||||
u64 kernel_stack_top;
|
||||
process* proc;
|
||||
} task;
|
||||
|
||||
void sched_init();
|
||||
task* sched_spawn(void(*entry)());
|
||||
task* sched_spawn(void(*entry)(), process* owner);
|
||||
u64 sched_next(u64 curr_rsp);
|
||||
void yield(u64 ticks);
|
||||
@@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
void jump_to_userspace(void* entry, void* user_stack_top);
|
||||
@@ -26,16 +26,8 @@ typedef struct {
|
||||
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();
|
||||
void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font);
|
||||
@@ -37,3 +37,6 @@
|
||||
|
||||
void vmm_init(Bootinfo* info);
|
||||
u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags);
|
||||
u64 vmm_create_address_space();
|
||||
u64 vmm_get_current_cr3();
|
||||
void load_cr3(u64 pml4_addr);
|
||||
@@ -10,4 +10,6 @@ void cmd_regs();
|
||||
void print_regs();
|
||||
void cmd_sleep();
|
||||
void cmd_debug();
|
||||
int rectest(int a);
|
||||
void cmd_rand();
|
||||
void cmd_ver();
|
||||
void cmd_userspace();
|
||||
@@ -0,0 +1,72 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include "types.h"
|
||||
#include <cpuinfo.h>
|
||||
|
||||
#define MSR_GS_BASE 0xC0000101
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
cpu_info g_cpu = {0};
|
||||
|
||||
static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) {
|
||||
__asm__ volatile("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(leaf), "c"(subleaf)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
void cpuinfo_init(u64 kernel_stack_top) {
|
||||
g_cpu.kernel_rsp = kernel_stack_top;
|
||||
g_cpu.self = (u64)&g_cpu;
|
||||
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
|
||||
|
||||
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(0, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
u32* vendor_ptr = (u32*)g_cpu.vendor;
|
||||
vendor_ptr[0] = ebx;
|
||||
vendor_ptr[1] = edx;
|
||||
vendor_ptr[2] = ecx;
|
||||
g_cpu.vendor[12] = '\0';
|
||||
|
||||
cpuid(1, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
g_cpu.family = (eax >> 8) & 0xF;
|
||||
g_cpu.model = (eax >> 4) & 0xF;
|
||||
if (g_cpu.family == 6 || g_cpu.family == 15) {
|
||||
g_cpu.model += ((eax >> 16) & 0xF) << 4;
|
||||
}
|
||||
|
||||
if (edx & (1 << 0)) g_cpu.features |= CPU_FEAT_FPU;
|
||||
if (edx & (1 << 4)) g_cpu.features |= CPU_FEAT_TSC;
|
||||
if (edx & (1 << 5)) g_cpu.features |= CPU_FEAT_MSR;
|
||||
if (edx & (1 << 6)) g_cpu.features |= CPU_FEAT_PAE;
|
||||
if (edx & (1 << 9)) g_cpu.features |= CPU_FEAT_APIC;
|
||||
if (edx & (1 << 12)) g_cpu.features |= CPU_FEAT_MTRR;
|
||||
if (edx & (1 << 25)) g_cpu.features |= CPU_FEAT_SSE;
|
||||
if (edx & (1 << 26)) g_cpu.features |= CPU_FEAT_SSE2;
|
||||
|
||||
if (ecx & (1 << 0)) g_cpu.features |= CPU_FEAT_SSE3;
|
||||
if (ecx & (1 << 9)) g_cpu.features |= CPU_FEAT_SSSE3;
|
||||
if (ecx & (1 << 19)) g_cpu.features |= CPU_FEAT_SSE4_1;
|
||||
if (ecx & (1 << 20)) g_cpu.features |= CPU_FEAT_SSE4_2;
|
||||
if (ecx & (1 << 28)) g_cpu.features |= CPU_FEAT_AVX;
|
||||
if (ecx & (1 << 29)) g_cpu.features |= CPU_FEAT_F16C;
|
||||
|
||||
if (ecx & (1 << 30)) g_cpu.features |= CPU_FEAT_RDRAND;
|
||||
|
||||
if (ecx & (1 << 31)) g_cpu.features |= CPU_FEAT_HYPERVISOR;
|
||||
}
|
||||
|
||||
bool cpu_has(u64 feature) {
|
||||
return (g_cpu.features & feature) != 0;
|
||||
}
|
||||
@@ -27,9 +27,10 @@ stack_guard:
|
||||
global stack_bottom
|
||||
stack_bottom:
|
||||
resb 16384
|
||||
global stack_top
|
||||
stack_top:
|
||||
|
||||
section .text
|
||||
section .text.entry
|
||||
global _start
|
||||
global gdt_flush
|
||||
extern kmain
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright (c) 2026 0xKarinyash
|
||||
|
||||
bits 64
|
||||
|
||||
extern syscall_dispatch
|
||||
global syscall_entry
|
||||
|
||||
section .text
|
||||
|
||||
syscall_entry:
|
||||
swapgs
|
||||
mov [gs:0], rsp ; saving users rsp in g_cpu.user_rsp
|
||||
mov rsp, [gs:8] ; load kernel rsp from g_cpu.kernel_rsp
|
||||
|
||||
push qword [gs:0]
|
||||
push r11 ; rflags
|
||||
push rcx ; rip
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
push r10
|
||||
push r8
|
||||
push r9
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
; preparing c code
|
||||
; c waits rdi, rsi, rdx, rcx, r8, r9
|
||||
; user sent rax, rdi, rsi, rdx, r10, r8 (rax=id)
|
||||
|
||||
mov r9, r8 ; 6th arg
|
||||
mov r8, r10 ; 5th arg
|
||||
mov rcx, rdx ; 4th arg
|
||||
mov rdx, rsi ; 3rd arg
|
||||
mov rsi, rdi ; 2nd arg
|
||||
mov rdi, rax ; 1st arg (id)
|
||||
|
||||
call syscall_dispatch
|
||||
|
||||
; restoring context except RAX (result there)
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r9
|
||||
pop r8
|
||||
pop r10
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbx
|
||||
pop rbp
|
||||
pop rcx ; rip
|
||||
pop r11 ; rflags
|
||||
add rsp, 8 ; skip rsp
|
||||
|
||||
mov [gs:8], rsp
|
||||
mov rsp, [gs:0]
|
||||
swapgs
|
||||
|
||||
o64 sysret
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <cpuinfo.h>
|
||||
#include <syscall.h>
|
||||
#include <types.h>
|
||||
#include <drivers/console.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
static inline u64 rdmsr(u32 msr) {
|
||||
u32 low, high;
|
||||
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||
return ((u64)high << 32) | low;
|
||||
}
|
||||
|
||||
extern void syscall_entry();
|
||||
|
||||
void syscall_init() {
|
||||
u64 efer = rdmsr(MSR_EFER);
|
||||
wrmsr(MSR_EFER, efer | 1); // Enabling SCE in EFER. Just enabling 0 bit
|
||||
|
||||
// setting up STAR
|
||||
// 32:47 kernel selector (0x08)
|
||||
// 48:64 user selector (0x01 cuz sysret adds +16 for CS and +8 for SS)
|
||||
u64 star = (0x13ULL << 48) | (0x08ULL << 32);
|
||||
wrmsr(MSR_STAR, star);
|
||||
|
||||
wrmsr(MSR_LSTAR, (u64)syscall_entry); // setting handler adress
|
||||
|
||||
// masking flags (IA32_FMASK)
|
||||
// 9 bit for finterrupts in syscall (IF) and few more necessary flags
|
||||
wrmsr(MSR_FMASK, 0x200); // masking only IF
|
||||
|
||||
if (g_cpu.kernel_rsp == 0) {
|
||||
void* stack_phys = pmm_alloc_page();
|
||||
g_cpu.kernel_rsp = (u64)stack_phys + HHDM_OFFSET + 4096;
|
||||
}
|
||||
|
||||
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
|
||||
}
|
||||
|
||||
u64 syscall_dispatch(u64 id, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) {
|
||||
switch (id) {
|
||||
case SYS_EXIT: {
|
||||
kprintf("\n[Dewar] process exited with code %d", arg1);
|
||||
while(1) __asm__ ("hlt"); // stub
|
||||
return 0;
|
||||
}
|
||||
case SYS_EXEC: {
|
||||
kprintf("\n[Dewar] process called exec syscall");
|
||||
return 0; // stub as well
|
||||
}
|
||||
case SYS_WRITE: {
|
||||
kprintf("%s", (char*)arg1);
|
||||
return 0;
|
||||
}
|
||||
default: kprintf("[Dewar] Unknown syscall %d\n", id); return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <core/loader.h>
|
||||
#include <core/userspace.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/string.h>
|
||||
|
||||
#include <shell/ksh.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/heap.h>
|
||||
#include <mm/memory.h>
|
||||
|
||||
#include <fs/vfs.h>
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <types.h>
|
||||
|
||||
extern task* curr_task;
|
||||
|
||||
bool exec_init(process* p, const char* path) {
|
||||
kprintf("[Loader] loading %s...\n", path);
|
||||
fs_node* file = vfs_open(path);
|
||||
if (!file) {
|
||||
kprintf("[Loader] Error: %s not found in initramfs!\n", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 virt_code = 0x400000;
|
||||
u64 virt_stack = 0x800000;
|
||||
u64 stack_size = 8192;
|
||||
|
||||
u64 bytes_left = file->len;
|
||||
u64 offset = 0;
|
||||
u64 page_idx = 0;
|
||||
|
||||
while (bytes_left > 0) {
|
||||
void* phys = pmm_alloc_page();
|
||||
if (!phys) {
|
||||
kprintf("Loader: OOM!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
vmm_map_page((u64*)p->pml4_phys, (u64)phys, virt_code + (page_idx * 4096), PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
|
||||
void* k_ptr = (void*)(HHDM_OFFSET + (u64)phys);
|
||||
memset(k_ptr, 0, 4096);
|
||||
|
||||
u64 chunk = (bytes_left > 4096) ? 4096 : bytes_left;
|
||||
vfs_read(file, offset, chunk, (u8*)k_ptr);
|
||||
|
||||
bytes_left -= chunk;
|
||||
offset += chunk;
|
||||
page_idx++;
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < (stack_size / 4096); i++) {
|
||||
void* phys = pmm_alloc_page();
|
||||
vmm_map_page((u64*)p->pml4_phys, (u64)phys, virt_stack + (i * 4096), PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
memset((void*)(HHDM_OFFSET + (u64)phys), 0, 4096);
|
||||
}
|
||||
|
||||
load_cr3(p->pml4_phys);
|
||||
|
||||
// __asm__ volatile(
|
||||
// "mov %%cr3, %%rax\n\t"
|
||||
// "mov %%rax, %%cr3\n\t"
|
||||
// ::: "rax", "memory"
|
||||
// );
|
||||
|
||||
kprintf("[Loader] Transferring control to userspace...\n");
|
||||
jump_to_userspace((void*)virt_code, (void*)(virt_stack + stack_size));
|
||||
|
||||
return true; // unreachable
|
||||
}
|
||||
|
||||
void init_task_entry() {
|
||||
process* init_proc = (process*)malloc(sizeof(process));
|
||||
init_proc->pid = 1;
|
||||
init_proc->state = RUNNING;
|
||||
init_proc->pml4_phys = vmm_create_address_space();
|
||||
strcpy(init_proc->name, "init");
|
||||
|
||||
curr_task->proc = init_proc;
|
||||
|
||||
if (!exec_init(init_proc, "/init")) {
|
||||
kprintf("FATAL: Could not load /init\n");
|
||||
sched_spawn(ksh, nullptr);
|
||||
|
||||
while(1) __asm__("hlt");
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,9 @@ const char* fun_messages[] = {
|
||||
"Attaboy, Jack. He's good. Really good.",
|
||||
"Zhenih priehal",
|
||||
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
|
||||
"fuck off"
|
||||
"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!",
|
||||
};
|
||||
|
||||
|
||||
@@ -102,7 +104,7 @@ void draw_panic_bg() {
|
||||
console_set_default_color(0xFFFFFF);
|
||||
|
||||
u64 msg_count = sizeof(fun_messages) / sizeof(fun_messages[0]);
|
||||
u8 rand_num = shitrand() % msg_count;
|
||||
u8 rand_num = krand() % msg_count;
|
||||
|
||||
kprintf("\n\n");
|
||||
kprintf("\t\t\t\t^bKERNEL PANIC^! :( \n");
|
||||
|
||||
+34
-4
@@ -1,15 +1,45 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include "bootinfo.h"
|
||||
#include <core/rand.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <types.h>
|
||||
|
||||
// really shiity rand lol.
|
||||
// not shitty.. basic.
|
||||
static u64 prng_state = 0;
|
||||
|
||||
u64 shitrand() {
|
||||
int lo, hi;
|
||||
static inline u64 rdtsc() {
|
||||
u32 lo, hi;
|
||||
__asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
|
||||
void rng_init() {
|
||||
prng_state = rdtsc();
|
||||
if (prng_state == 0) prng_state = BOOTINFO_MAGIC; // why not reuse "termOS"?
|
||||
}
|
||||
|
||||
static u64 xorshift_rand() {
|
||||
u64 x = prng_state;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 7;
|
||||
x ^= x << 17;
|
||||
return prng_state = x;
|
||||
}
|
||||
|
||||
static bool hw_rand(u64 *val) {
|
||||
u8 ok;
|
||||
__asm__ volatile ("rdrand %0; setc %1"
|
||||
: "=r" (*val), "=qm" (ok));
|
||||
return ok != 0;
|
||||
}
|
||||
|
||||
u64 krand() {
|
||||
u64 res;
|
||||
if (cpu_has(CPU_FEAT_RDRAND)) {
|
||||
if (hw_rand(&res)) return res;
|
||||
}
|
||||
|
||||
return xorshift_rand();
|
||||
}
|
||||
@@ -3,28 +3,41 @@
|
||||
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/string.h>
|
||||
#include <mm/heap.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <gdt.h>
|
||||
|
||||
task* curr_task = nullptr;
|
||||
u32 next_pid = 1;
|
||||
|
||||
|
||||
extern void irq0_handler();
|
||||
extern u64 pml4_kernel_phys;
|
||||
|
||||
static process kernel_process;
|
||||
|
||||
void sched_init() {
|
||||
task* kt = (task*)malloc(sizeof(task));
|
||||
kernel_process.pid = 0;
|
||||
kernel_process.state = RUNNING;
|
||||
kernel_process.pml4_phys = pml4_kernel_phys;
|
||||
strcpy(kernel_process.name, "kernel");
|
||||
|
||||
task* kt = (task*)malloc(sizeof(task));
|
||||
kt->id = 0;
|
||||
kt->proc = &kernel_process;
|
||||
kt->sleep_ticks = 0;
|
||||
kt->next = kt;
|
||||
|
||||
curr_task = kt;
|
||||
}
|
||||
|
||||
task* sched_spawn(void(*entry)()) {
|
||||
task* sched_spawn(void(*entry)(), process* owner) {
|
||||
task* t = (task*)malloc(sizeof(task));
|
||||
if (!t) return nullptr;
|
||||
|
||||
if (!owner) owner = &kernel_process;
|
||||
|
||||
u64 stack_size = 16384;
|
||||
u8* stack_base = (u8*)malloc(stack_size);
|
||||
if (!stack_base) panic("OOM for task stack");
|
||||
@@ -42,6 +55,7 @@ task* sched_spawn(void(*entry)()) {
|
||||
for (u8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
|
||||
|
||||
t->rsp = (u64)rsp;
|
||||
t->proc = owner;
|
||||
t->id = next_pid++;
|
||||
t->sleep_ticks = 0;
|
||||
t->next = curr_task->next;
|
||||
@@ -66,8 +80,11 @@ u64 sched_next(u64 curr_rsp) {
|
||||
task* next = curr_task->next;
|
||||
while (next != curr_task && next->sleep_ticks > 0) next = next->next; // what the fuck i just wrote
|
||||
|
||||
if (next->proc->pml4_phys != curr_task->proc->pml4_phys) load_cr3(next->proc->pml4_phys);
|
||||
|
||||
curr_task = next;
|
||||
tss.rsp0 = curr_task->kernel_stack_top;
|
||||
g_cpu.kernel_rsp = curr_task->kernel_stack_top;
|
||||
return curr_task->rsp;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <core/userspace.h>
|
||||
#include <types.h>
|
||||
|
||||
#define USER_DS (0x18 | 3)
|
||||
#define USER_CS (0x20 | 3)
|
||||
#define RFLAGS_IF 0x202
|
||||
|
||||
void jump_to_userspace(void* entry, void* user_stack_top) {
|
||||
__asm__ volatile (
|
||||
"mov %0, %%ds\n"
|
||||
"mov %0, %%es\n"
|
||||
"mov %0, %%fs\n"
|
||||
:: "r" ((u64)USER_DS) : "memory"
|
||||
);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushq %0\n" // SS (User Data Selector)
|
||||
"pushq %1\n" // RSP (User Stack Pointer)
|
||||
"pushq %2\n" // RFLAGS
|
||||
"pushq %3\n" // CS (User Code Selector)
|
||||
"pushq %4\n" // RIP (Entry Point)
|
||||
"iretq\n"
|
||||
:
|
||||
: "r" ((u64)USER_DS),
|
||||
"r" ((u64)user_stack_top),
|
||||
"r" ((u64)RFLAGS_IF),
|
||||
"r" ((u64)USER_CS),
|
||||
"r" ((u64)entry)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
@@ -8,11 +8,8 @@
|
||||
#include <mm/memory.h>
|
||||
|
||||
#define SHITGUI_TRANSPARENCY_KEY 0xFF00FF
|
||||
#define SHITGUI_MAX_WINDOWS_AMOUNT 64
|
||||
|
||||
SG_Context* main_context;
|
||||
SG_Window* windows[SHITGUI_MAX_WINDOWS_AMOUNT]; // нет блять линукс
|
||||
u64 windows_amount = 0;
|
||||
|
||||
void sg_init(SG_Context *ctx) {
|
||||
main_context = ctx;
|
||||
@@ -85,64 +82,4 @@ void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Fon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position) {
|
||||
if (windows_amount >= SHITGUI_MAX_WINDOWS_AMOUNT) return nullptr;
|
||||
SG_Context* ctx = nullptr;
|
||||
u32* fb = nullptr;
|
||||
SG_Window* window = nullptr;
|
||||
|
||||
ctx = (SG_Context*)malloc(sizeof(SG_Context));
|
||||
if (!ctx) goto fail; // goto is GOOD for cleaning up in C stfu.
|
||||
// Mainline linux kernel contains 100k gotos
|
||||
|
||||
fb = malloc(size->x * size->y * sizeof(u32));
|
||||
if (!fb) goto fail;
|
||||
memset(fb, 0, size->x * size->y * sizeof(u32));
|
||||
|
||||
window = (SG_Window*)malloc(sizeof(SG_Window));
|
||||
if (!window) goto fail;
|
||||
|
||||
ctx->fb = fb;
|
||||
ctx->height = size->y;
|
||||
ctx->width = size->x;
|
||||
ctx->pitch = size->x;
|
||||
|
||||
|
||||
window->ctx = ctx;
|
||||
window->title = title;
|
||||
window->pos.x = position->x;
|
||||
window->pos.y = position->y;
|
||||
|
||||
windows[windows_amount] = window;
|
||||
windows_amount++;
|
||||
|
||||
return window;
|
||||
|
||||
fail:
|
||||
if (ctx) free(ctx);
|
||||
if (fb) free(fb);
|
||||
if (window) free(window);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void render_window(SG_Context *ctx, SG_Window *window) {
|
||||
SG_Image img = {0};
|
||||
img.buffer = window->ctx->fb;
|
||||
if (!img.buffer) panic("No img buffer found");
|
||||
img.height = window->ctx->height;
|
||||
img.width = window->ctx->width;
|
||||
|
||||
sg_put_img(ctx, &window->pos, &img);
|
||||
}
|
||||
|
||||
void composer_task() {
|
||||
while (true) {
|
||||
for (u64 i = 0; i < windows_amount; i++) {
|
||||
render_window(main_context, windows[i]);
|
||||
}
|
||||
yield(1);
|
||||
}
|
||||
}
|
||||
+25
-3
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include "bootinfo.h"
|
||||
|
||||
#include <shell/ksh.h>
|
||||
|
||||
#include <types.h>
|
||||
@@ -14,10 +15,14 @@
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/splash.h>
|
||||
#include <core/rand.h>
|
||||
#include <core/loader.h>
|
||||
|
||||
#include <gdt.h>
|
||||
#include <idt.h>
|
||||
#include <pic.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
@@ -30,6 +35,7 @@
|
||||
#define BG_COLOR 0x111111
|
||||
|
||||
extern u64 _kernel_end;
|
||||
extern void* stack_top;
|
||||
static SG_Context sg_ctx;
|
||||
|
||||
void kmain(Bootinfo* info) {
|
||||
@@ -40,6 +46,10 @@ void kmain(Bootinfo* info) {
|
||||
|
||||
if (info->magic != BOOTINFO_MAGIC) panic("Corrupt bootinfo!");
|
||||
|
||||
cpuinfo_init((u64)&stack_top);
|
||||
kprintf("Got CPUINFO\n");
|
||||
rng_init();
|
||||
kprintf("RNG initialized\n");
|
||||
gdt_init();
|
||||
kprintf("GDT initialized\n");
|
||||
idt_init();
|
||||
@@ -58,6 +68,7 @@ void kmain(Bootinfo* info) {
|
||||
kprintf("Scheduler initialized\n");
|
||||
sg_init(&sg_ctx);
|
||||
kprintf("Shitgui initialized\n");
|
||||
syscall_init();
|
||||
|
||||
info = (Bootinfo*)PHYS_TO_HHDM((u64)info);
|
||||
|
||||
@@ -79,9 +90,20 @@ void kmain(Bootinfo* info) {
|
||||
|
||||
show_splash(&sg_ctx);
|
||||
|
||||
sched_spawn(composer_task);
|
||||
sched_spawn(ksh);
|
||||
if (!info->initramfs.addr) kprintf("^rWARNING^!: Failed to load ^yinitramfs^!, VFS is empty.\n\n");
|
||||
bool staying_in_ksh = false;
|
||||
if (!info->initramfs.addr) {
|
||||
kprintf("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n");
|
||||
staying_in_ksh = true;
|
||||
}
|
||||
|
||||
kprintf("Press any key to stay in ^gksh^!. \nPress ^yenter^! to continue booting in ring 3\n");
|
||||
char c = '\n';
|
||||
c = console_getc();
|
||||
if (c != '\n') staying_in_ksh = true;
|
||||
|
||||
if (staying_in_ksh) sched_spawn(ksh, nullptr);
|
||||
else sched_spawn(init_task_entry, nullptr);
|
||||
|
||||
__asm__ volatile("sti");
|
||||
|
||||
while (true) __asm__ volatile("hlt");
|
||||
|
||||
+39
-12
@@ -11,6 +11,7 @@
|
||||
#include "bootinfo.h"
|
||||
|
||||
u64* pml4_kernel = nullptr;
|
||||
u64 pml4_kernel_phys = 0;
|
||||
static bool is_initialized = false;
|
||||
|
||||
extern u64 _kernel_start;
|
||||
@@ -89,26 +90,30 @@ void vmm_unmap_page(u64* pml4, u64 virt) {
|
||||
u64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||
u64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||
|
||||
if (!(pml4[pml4_idx] & PTE_PRESENT)) return;
|
||||
u64* pdpt = get_table_virt(PTE_GET_ADDR(pml4[pml4_idx]));
|
||||
|
||||
if (!(pdpt[pdpt_idx] & PTE_PRESENT)) return;
|
||||
u64* pd = get_table_virt(PTE_GET_ADDR(pdpt[pdpt_idx]));
|
||||
|
||||
if (!(pd[pd_idx] & PTE_PRESENT)) return;
|
||||
u64* pt = get_table_virt(PTE_GET_ADDR(pd[pd_idx]));
|
||||
u64* pml4_virt = pml4;
|
||||
if (is_initialized) pml4_virt = (u64*)PHYS_TO_HHDM((u64)pml4);
|
||||
|
||||
pt[pt_idx] = 0;
|
||||
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) return;
|
||||
u64* pdpt_virt = get_table_virt(PTE_GET_ADDR(pml4_virt[pml4_idx]));
|
||||
|
||||
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) return;
|
||||
u64* pd_virt = get_table_virt(PTE_GET_ADDR(pdpt_virt[pdpt_idx]));
|
||||
|
||||
if (!(pd_virt[pd_idx] & PTE_PRESENT)) return;
|
||||
u64* pt_virt = get_table_virt(PTE_GET_ADDR(pd_virt[pd_idx]));
|
||||
|
||||
pt_virt[pt_idx] = 0;
|
||||
|
||||
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
|
||||
}
|
||||
|
||||
static inline void load_cr3(u64 pml4_addr) {
|
||||
void load_cr3(u64 pml4_addr) {
|
||||
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
|
||||
}
|
||||
|
||||
void vmm_init(Bootinfo* info) {
|
||||
pml4_kernel = pmm_alloc_page();
|
||||
pml4_kernel_phys = (u64)pmm_alloc_page();
|
||||
pml4_kernel = (u64*)pml4_kernel_phys;
|
||||
memset(pml4_kernel, 0, PAGE_SIZE);
|
||||
|
||||
u64 k_virt_start = (u64)&_kernel_start;
|
||||
@@ -126,6 +131,28 @@ void vmm_init(Bootinfo* info) {
|
||||
|
||||
bitmap = (u8*)PHYS_TO_HHDM((u64)bitmap);
|
||||
info->framebuffer.base = (u32*)FB_VIRT_BASE;
|
||||
load_cr3((u64)pml4_kernel);
|
||||
load_cr3(pml4_kernel_phys);
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
u64 vmm_create_address_space() {
|
||||
u64 phys = (u64)pmm_alloc_page();
|
||||
if (!phys) return 0;
|
||||
|
||||
u64* virt = (u64*)PHYS_TO_HHDM(phys);
|
||||
memset(virt, 0, PAGE_SIZE);
|
||||
|
||||
u64* kernel_pml4_virt = get_table_virt((u64)pml4_kernel);
|
||||
|
||||
for (u32 i = 256; i < 512; i++) {
|
||||
virt[i] = kernel_pml4_virt[i];
|
||||
}
|
||||
|
||||
return phys;
|
||||
}
|
||||
|
||||
u64 vmm_get_current_cr3() {
|
||||
u64 cr3;
|
||||
__asm__ volatile("mov %%cr3, %0" : "=r"(cr3));
|
||||
return cr3;
|
||||
}
|
||||
+47
-18
@@ -1,14 +1,26 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <core/rand.h>
|
||||
|
||||
#include <drivers/timer.h>
|
||||
#include <types.h>
|
||||
#include <cpuinfo.h>
|
||||
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/timer.h>
|
||||
|
||||
#include <core/rand.h>
|
||||
#include <core/loader.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/string.h>
|
||||
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/heap.h>
|
||||
|
||||
#include <shell/dbgcmd.h>
|
||||
|
||||
#include "../data/cats.h"
|
||||
#include "shell/dbgcmd.h"
|
||||
|
||||
extern task* curr_task;
|
||||
|
||||
const char* ascii_logo[] = {
|
||||
" /\\___/\\ ",
|
||||
@@ -21,47 +33,40 @@ const char* ascii_logo[] = {
|
||||
" |_______| "
|
||||
};
|
||||
|
||||
int rectest(int a) {
|
||||
volatile int b = a + 1;
|
||||
kprintf("%d", b);
|
||||
return rectest(b * 2);
|
||||
}
|
||||
|
||||
void cmd_kfetch() {
|
||||
u64 uptime_s = get_uptime() / 1000;
|
||||
|
||||
kprintf("\n\n");
|
||||
kprintf("^p %s ^!\t\t^g kernel^!@^gtermos\n^0", ascii_logo[0]);
|
||||
kprintf("^p %s ^!\t\t^!-------------\n^!", ascii_logo[1]);
|
||||
kprintf("^p %s ^!\t\t^gOS^!: termOS 0.0.1\n^!", ascii_logo[2]);
|
||||
kprintf("^p %s ^!\t\t^gKernel^!: sucks\n^!", ascii_logo[3]);
|
||||
kprintf("^p %s ^!\t\t^!-------------\n^!", ascii_logo[1]);
|
||||
kprintf("^p %s ^!\t\t^gOS^!: termOS %s\n^!", ascii_logo[2], TERMOS_VERSION);
|
||||
kprintf("^p %s ^!\t\t^gKernel^!: Dewar (x86_64), build: %s %s\n^!", ascii_logo[3], __DATE__, __TIME__);
|
||||
kprintf("^p %s ^!\t\t^gUptime^!: %d seconds\n^!", ascii_logo[4], uptime_s);
|
||||
kprintf("^p %s ^!\t\t^gShell^!: ksh\n^!", ascii_logo[5]);
|
||||
kprintf("^p %s ^p\t\t^gDE^!: shitgui\n^!", ascii_logo[6]);
|
||||
kprintf("^p %s ^p\t\t^gCPU^!: %s\n^!", ascii_logo[7], "cool one");
|
||||
kprintf("^p %s ^!\t\t^gDE^!: shitgui\n^!", ascii_logo[6]);
|
||||
kprintf("^p %s ^!\t\t^gCPU^!: %s (^yFamily^!: %d; ^yModel^!: %d)\n^!", ascii_logo[7], g_cpu.vendor, g_cpu.family, g_cpu.model);
|
||||
kprintf("\n\n");
|
||||
}
|
||||
|
||||
void cmd_meow() {
|
||||
u64 cats_count = sizeof(cats) / sizeof(cats[0]);
|
||||
u8 rand_num = shitrand() % cats_count;
|
||||
u8 rand_num = krand() % cats_count;
|
||||
kprintf("Nyaaa!!\n\n%s\n\n", cats[rand_num]);
|
||||
}
|
||||
|
||||
void cmd_help() {
|
||||
kprintf("Welcome to ^ptermOS^!'s ^gk^!ernel ^gsh^!ell!\n");
|
||||
kprintf("It loads when userspace is failed to load and acts as a basic rescue environment\n");
|
||||
kprintf("At this moment i dont have userspace so it loads always\n");
|
||||
kprintf("Available commands:\n");
|
||||
|
||||
kprintf("\t^rDebug^!:\n");
|
||||
kprintf("\t\t^ysleep^! \t\tSleep for 3seconds\n");
|
||||
kprintf("\t\t^ydbg^! \t\tTest new stuff\n");
|
||||
kprintf("\t\t^yregs^! \t\tPrint current regs\n");
|
||||
kprintf("\t\t^yrectest^! \t\tTSS test\n");
|
||||
kprintf("\t\t^ypanic^! \t\tPanics (lol)\n");
|
||||
kprintf("\t\t^yud2^! \t\tPanics with #UD\n");
|
||||
kprintf("\t\t^ypf^! \t\tPanics with #PF\n");
|
||||
kprintf("\t\t^yuserspace^! \t\tAttempt to jump in ring 3\n");
|
||||
|
||||
kprintf("\t^pFun^!:\n");
|
||||
kprintf("\t\t^ysplash^! \t\tShows splash (works kinda unstable)\n");
|
||||
@@ -74,6 +79,8 @@ void cmd_help() {
|
||||
kprintf("\t^bMisc^!:\n");
|
||||
kprintf("\t\t^yclear^! \t\tClear console\n");
|
||||
kprintf("\t\t^yhelp^! \t\tShow this menu\n");
|
||||
kprintf("\t\t^yrand^! \t\tGet a random number\n");
|
||||
kprintf("\t\t^yver^! \t\tDisplays termOS's version\n");
|
||||
}
|
||||
|
||||
void cmd_regs() {
|
||||
@@ -100,8 +107,30 @@ void cmd_sleep() {
|
||||
sleep(3000);
|
||||
}
|
||||
|
||||
void cmd_rand() {
|
||||
kprintf("Your rand number (0..100) is ... ^y%d^!!\n", krand() % 100);
|
||||
}
|
||||
|
||||
void cmd_debug() {
|
||||
u64 status = debug();
|
||||
kprintf("\nDebug ended with code %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
void cmd_ver() {
|
||||
kprintf("termOS version %s\n", TERMOS_VERSION);
|
||||
kprintf("Dewar Kernel (x86_64), build: %s %s\n", __DATE__, __TIME__);
|
||||
kprintf("License: GPL-3.0-or-later\n");
|
||||
}
|
||||
|
||||
void cmd_userspace() {
|
||||
process* init_proc = (process*)malloc(sizeof(process));
|
||||
init_proc->pid = 1;
|
||||
init_proc->state = RUNNING;
|
||||
init_proc->pml4_phys = vmm_create_address_space();
|
||||
strcpy(init_proc->name, "init");
|
||||
|
||||
curr_task->proc = init_proc;
|
||||
kprintf("Trying to jump in ring 3...\n");
|
||||
if (!exec_init(init_proc, "/init")) kprintf("Failed to jump.\n");
|
||||
}
|
||||
@@ -1,57 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
// contents of this file will be changed CONSTANTLY
|
||||
// im just testing new stuff here
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include "mm/vmm.h"
|
||||
#include <mm/pmm.h>
|
||||
#include <shell/dbgcmd.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
extern u64* pml4_kernel;
|
||||
|
||||
#define USER_DS (0x18 | 3)
|
||||
#define USER_CS (0x20 | 3)
|
||||
#define RFLAGS_IF 0x202
|
||||
|
||||
void jump_to_userspace(void* entry, void* user_stack_top) {
|
||||
__asm__ volatile (
|
||||
"mov %0, %%ds\n"
|
||||
"mov %0, %%es\n"
|
||||
"mov %0, %%fs\n"
|
||||
"mov %0, %%gs\n"
|
||||
:: "r" ((u64)USER_DS) : "memory"
|
||||
);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushq %0\n" // SS (User Data Selector)
|
||||
"pushq %1\n" // RSP (User Stack Pointer)
|
||||
"pushq %2\n" // RFLAGS
|
||||
"pushq %3\n" // CS (User Code Selector)
|
||||
"pushq %4\n" // RIP (Entry Point)
|
||||
"iretq\n" // jump
|
||||
:
|
||||
: "r" ((u64)USER_DS),
|
||||
"r" ((u64)user_stack_top),
|
||||
"r" ((u64)RFLAGS_IF),
|
||||
"r" ((u64)USER_CS),
|
||||
"r" ((u64)entry)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
u64 debug() {
|
||||
void* phys_code = pmm_alloc_page();
|
||||
void* phys_stack = pmm_alloc_page();
|
||||
u64 virt_code = 0x400000;
|
||||
u64 virt_stack = 0x800000;
|
||||
|
||||
vmm_map_page(pml4_kernel, (u64)phys_code, virt_code, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
vmm_map_page(pml4_kernel, (u64)phys_stack, virt_stack, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
u8* kernel_view = (u8*)(HHDM_OFFSET + phys_code);
|
||||
kernel_view[0] = 0xEB; // jmp
|
||||
kernel_view[1] = 0xFE; // to self
|
||||
kprintf("Jumping to userspace. Goodbye.");
|
||||
jump_to_userspace((void*)virt_code, (void*)(virt_stack + 4096));
|
||||
return 0;
|
||||
}
|
||||
+12
-4
@@ -33,9 +33,12 @@ typedef enum {
|
||||
TOKEN_PANIC,
|
||||
TOKEN_PANIC_UD2,
|
||||
TOKEN_PANIC_PF,
|
||||
TOKEN_USERSPACE,
|
||||
|
||||
TOKEN_CLEAR,
|
||||
TOKEN_BLINKING,
|
||||
TOKEN_RAND,
|
||||
TOKEN_VER,
|
||||
|
||||
TOKEN_BACK,
|
||||
TOKEN_FORWARD,
|
||||
@@ -56,10 +59,10 @@ static const ksh_command_map token_map[] = {
|
||||
{"sleep", TOKEN_SLEEP},
|
||||
{"dbg", TOKEN_DEBUG},
|
||||
{"regs", TOKEN_REGS},
|
||||
{"rectest", TOKEN_RECTEST},
|
||||
{"panic", TOKEN_PANIC},
|
||||
{"ud2", TOKEN_PANIC_UD2},
|
||||
{"pf", TOKEN_PANIC_PF},
|
||||
{"userspace", TOKEN_USERSPACE},
|
||||
|
||||
// fun
|
||||
{"meow", TOKEN_MEOW},
|
||||
@@ -69,6 +72,9 @@ static const ksh_command_map token_map[] = {
|
||||
// misc
|
||||
{"help", TOKEN_HELP},
|
||||
{"clear", TOKEN_CLEAR},
|
||||
{"rand", TOKEN_RAND},
|
||||
{"ver", TOKEN_VER},
|
||||
|
||||
{nullptr, TOKEN_NULL}
|
||||
};
|
||||
|
||||
@@ -80,7 +86,7 @@ ksh_token char2token(char* token) {
|
||||
}
|
||||
|
||||
void ksh() {
|
||||
sched_spawn(cursor_blinker_sched_task);
|
||||
sched_spawn(cursor_blinker_sched_task, nullptr);
|
||||
while (true) {
|
||||
kprintf("ksh_> ");
|
||||
char cmdbuff[256];
|
||||
@@ -90,15 +96,17 @@ void ksh() {
|
||||
|
||||
case TOKEN_CLEAR: console_clear((u32) console_get_colors() & 0xFFFFFFFF); break;
|
||||
case TOKEN_BLINKING: console_toggle_cursor_blink(); break;
|
||||
case TOKEN_RAND: cmd_rand(); break;
|
||||
case TOKEN_VER: cmd_ver(); break;
|
||||
|
||||
case TOKEN_SLEEP: cmd_sleep(); break;
|
||||
case TOKEN_DEBUG: cmd_debug(); break;
|
||||
case TOKEN_REGS: cmd_regs(); break;
|
||||
case TOKEN_RECTEST: rectest(0); break;
|
||||
case TOKEN_PANIC: panic("Manually initiated panic");
|
||||
case TOKEN_PANIC_UD2: __asm__ volatile ("ud2");
|
||||
case TOKEN_PANIC_PF: u64* bad_ptr = (u64*)0xDEADBEEF; *bad_ptr = 666;
|
||||
|
||||
case TOKEN_USERSPACE: cmd_userspace(); break;
|
||||
|
||||
case TOKEN_SPLASH: show_splash(console_get_context()); break;
|
||||
case TOKEN_KFETCH: cmd_kfetch(); break;
|
||||
case TOKEN_MEOW: cmd_meow(); break;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(termOSuserspace LANGUAGES C ASM_NASM)
|
||||
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
message(STATUS "Building termOS's userspace")
|
||||
|
||||
add_subdirectory(init)
|
||||
@@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(termOSinit LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
message(STATUS "Building termOS's init")
|
||||
|
||||
file(GLOB_RECURSE INIT_SOURCES CMAKE_CONFIGURE_DEPENDS
|
||||
"src/*.asm"
|
||||
"src/*.c"
|
||||
)
|
||||
|
||||
add_executable(init ${INIT_SOURCES})
|
||||
set_target_properties(init PROPERTIES
|
||||
SUFFIX ""
|
||||
LINKER_LANGUAGE C
|
||||
)
|
||||
|
||||
target_link_options(init PRIVATE
|
||||
-nostdlib
|
||||
-static
|
||||
-Wl,--oformat=binary
|
||||
-Wl,-Ttext=0x400000
|
||||
-Wl,-e,start
|
||||
)
|
||||
|
||||
add_custom_command(TARGET init POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:init> ${CMAKE_SOURCE_DIR}/initramfs/init
|
||||
COMMENT "Installing init binary to initramfs"
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
[bits 64]
|
||||
|
||||
section .text
|
||||
global start
|
||||
extern main
|
||||
|
||||
start:
|
||||
call main
|
||||
.hang:
|
||||
jmp .hang
|
||||
@@ -0,0 +1,16 @@
|
||||
static inline void sys_write(const char* str) {
|
||||
__asm__ volatile (
|
||||
"mov $2, %%rax\n\t"
|
||||
"mov %0, %%rdi\n\t"
|
||||
"syscall"
|
||||
:
|
||||
: "r"(str)
|
||||
: "rax", "rdi", "rcx", "r11", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
int main() {
|
||||
sys_write("Meowww!!!\n");
|
||||
sys_write("Nyaaaaa");
|
||||
for (int i = 0; i < 100; i++) sys_write("a");
|
||||
}
|
||||
Reference in New Issue
Block a user