Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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
|
||||||
+2
-1
@@ -5,4 +5,5 @@ kernel/data
|
|||||||
*.md
|
*.md
|
||||||
tools/
|
tools/
|
||||||
bootloader/
|
bootloader/
|
||||||
bootloader/src/uefi
|
bootloader/src/uefi
|
||||||
|
initramfs/
|
||||||
+20
-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_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)
|
||||||
|
|
||||||
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")
|
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 ${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}\""
|
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 ${INITRAMFS_SRC_DIR}
|
||||||
DEPENDS ${INIT_FILES}
|
DEPENDS ${INIT_FILES} init_elf
|
||||||
VERBATIM
|
VERBATIM
|
||||||
COMMENT "Packing initramfs to cpio..."
|
COMMENT "Packing initramfs to cpio..."
|
||||||
)
|
)
|
||||||
@@ -58,6 +73,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,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>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
|
||||||
|
#define HOT_MAGIC 0x21544F48
|
||||||
|
|
||||||
|
typedef struct hot_segment {
|
||||||
|
u64 type; // 1 = rx 2 = rw
|
||||||
|
u64 vaddr;
|
||||||
|
u64 offset;
|
||||||
|
u64 filesz;
|
||||||
|
u64 memsz;
|
||||||
|
} hot_segment;
|
||||||
|
|
||||||
|
typedef struct hot_header {
|
||||||
|
u32 magic; // "HOT!"
|
||||||
|
u8 version; // 1
|
||||||
|
u8 reserved_pad[3];
|
||||||
|
u64 entry_point;
|
||||||
|
u64 segments_count;
|
||||||
|
u64 reserved;
|
||||||
|
} hot_header;
|
||||||
@@ -1 +0,0 @@
|
|||||||
Meow!!
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Nyaaa
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -37,4 +37,6 @@ typedef struct {
|
|||||||
u16 iomap_base;
|
u16 iomap_base;
|
||||||
} __attribute__((packed)) TSS;
|
} __attribute__((packed)) TSS;
|
||||||
|
|
||||||
|
extern TSS tss;
|
||||||
|
|
||||||
void gdt_init();
|
void gdt_init();
|
||||||
|
|||||||
@@ -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,8 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <types.h>
|
||||||
|
#include <core/scheduler.h>
|
||||||
|
|
||||||
|
u64 load_hot(process* proc, u8* data);
|
||||||
@@ -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
|
#pragma once
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
u64 shitrand();
|
void rng_init();
|
||||||
|
u64 krand();
|
||||||
@@ -3,14 +3,30 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <types.h>
|
#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 {
|
typedef struct task {
|
||||||
u64 rsp;
|
u64 rsp;
|
||||||
struct task* next;
|
struct task* next;
|
||||||
u32 id;
|
u32 id;
|
||||||
u32 sleep_ticks;
|
u32 sleep_ticks;
|
||||||
} task_t;
|
u64 kernel_stack_top;
|
||||||
|
process* proc;
|
||||||
|
} task;
|
||||||
|
|
||||||
void sched_init();
|
void sched_init();
|
||||||
task_t* sched_spawn(void(*entry)());
|
task* sched_spawn(void(*entry)(), process* owner, bool is_user, u64 fixed_user_stack);
|
||||||
u64 sched_next(u64 curr_rsp);
|
u64 sched_next(u64 curr_rsp);
|
||||||
void yield(u64 ticks);
|
void yield(u64 ticks);
|
||||||
@@ -26,16 +26,8 @@ typedef struct {
|
|||||||
const unsigned char* base;
|
const unsigned char* base;
|
||||||
} SG_Font;
|
} SG_Font;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SG_Context *ctx;
|
|
||||||
SG_Point pos;
|
|
||||||
const char *title;
|
|
||||||
} SG_Window;
|
|
||||||
|
|
||||||
void sg_init(SG_Context *ctx);
|
void sg_init(SG_Context *ctx);
|
||||||
u32 sg_get_pixel(SG_Context *ctx, SG_Point *p);
|
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_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_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);
|
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();
|
|
||||||
@@ -37,3 +37,7 @@
|
|||||||
|
|
||||||
void vmm_init(Bootinfo* info);
|
void vmm_init(Bootinfo* info);
|
||||||
u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags);
|
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);
|
||||||
|
void vmm_setup_user_stack(u64* pml4_phys);
|
||||||
@@ -10,4 +10,6 @@ void cmd_regs();
|
|||||||
void print_regs();
|
void print_regs();
|
||||||
void cmd_sleep();
|
void cmd_sleep();
|
||||||
void cmd_debug();
|
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
|
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
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
// just fucking kill me already
|
// just fucking kill me already
|
||||||
|
|
||||||
#include <gdt.h>
|
#include <gdt.h>
|
||||||
|
#define GDT_ENTIRES 7
|
||||||
|
|
||||||
GDTDescriptor gdt[5];
|
GDTDescriptor gdt[GDT_ENTIRES];
|
||||||
GDTPtr gdt_ptr;
|
GDTPtr gdt_ptr;
|
||||||
TSS tss;
|
TSS tss;
|
||||||
u8 double_fault_stack[4096] = {0};
|
u8 double_fault_stack[4096] = {0};
|
||||||
@@ -40,7 +41,7 @@ void write_tss(int num) {
|
|||||||
extern void gdt_flush(u64 gdt_ptr_addr); // entry.asm
|
extern void gdt_flush(u64 gdt_ptr_addr); // entry.asm
|
||||||
|
|
||||||
void gdt_init() {
|
void gdt_init() {
|
||||||
gdt_ptr.limit = (sizeof(GDTDescriptor) * 5) - 1;
|
gdt_ptr.limit = (sizeof(GDTDescriptor) * GDT_ENTIRES) - 1;
|
||||||
gdt_ptr.base = (u64)&gdt;
|
gdt_ptr.base = (u64)&gdt;
|
||||||
|
|
||||||
// 0: Null
|
// 0: Null
|
||||||
@@ -53,17 +54,25 @@ void gdt_init() {
|
|||||||
// 0x20 = 0010 0000 bit 5 is "Long mode"
|
// 0x20 = 0010 0000 bit 5 is "Long mode"
|
||||||
// 2: Kernel Data (Ring 0)
|
// 2: Kernel Data (Ring 0)
|
||||||
// Access: 0x92 (Present, Ring0, Read/Write)
|
// Access: 0x92 (Present, Ring0, Read/Write)
|
||||||
gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 can't exec
|
gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
|
||||||
|
|
||||||
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // hack. zeroifying tss struct
|
// 3: User Data (Ring 3)
|
||||||
|
// Access: 0xF2 (Present, Ring3, Read/Write)
|
||||||
|
gdt_set_gate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
|
||||||
|
|
||||||
|
// 4: User Code (Ring 3)
|
||||||
|
// Access: 0xFA (Present, Ring3, RWX)
|
||||||
|
gdt_set_gate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
|
||||||
|
|
||||||
|
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // zeroifying tss struct
|
||||||
|
|
||||||
tss.iomap_base = sizeof(TSS);
|
tss.iomap_base = sizeof(TSS);
|
||||||
tss.ist1 = (u64)double_fault_stack + sizeof(double_fault_stack);
|
tss.ist1 = (u64)double_fault_stack + sizeof(double_fault_stack);
|
||||||
write_tss(3);
|
write_tss(5);
|
||||||
|
|
||||||
gdt_flush((u64)&gdt_ptr);
|
gdt_flush((u64)&gdt_ptr);
|
||||||
|
|
||||||
// telling cpu that TSS info located at gdt[3]; offset = 3 * 8 = 24 = 0x18
|
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
|
||||||
__asm__ volatile ("ltr %%ax" :: "a" (0x18));
|
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,46 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <core/hot.h>
|
||||||
|
#include <core/scheduler.h>
|
||||||
|
#include <core/string.h>
|
||||||
|
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include <mm/vmm.h>
|
||||||
|
#include <mm/heap.h>
|
||||||
|
#include <mm/memory.h>
|
||||||
|
|
||||||
|
#include "../../common/hot_header.h"
|
||||||
|
|
||||||
|
u64 load_hot(process* proc, u8* data) {
|
||||||
|
hot_header* header = (hot_header*)data;
|
||||||
|
if (header->magic != HOT_MAGIC) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hot_segment* segments = (hot_segment*)(data + sizeof(hot_header));
|
||||||
|
u64 kernel_cr3 = vmm_get_current_cr3();
|
||||||
|
for (u64 i = 0; i < header->segments_count; i++) {
|
||||||
|
hot_segment* seg = &segments[i];
|
||||||
|
if (seg->memsz == 0) continue;
|
||||||
|
|
||||||
|
u64 start = seg->vaddr & ~(0xFFF);
|
||||||
|
u64 end = (seg->vaddr + seg->memsz + 0xFFF) & ~(0xFFF);
|
||||||
|
for (u64 addr = start; addr < end; addr += PAGE_SIZE) {
|
||||||
|
void* phys = pmm_alloc_page();
|
||||||
|
vmm_map_page((u64*)proc->pml4_phys, (u64)phys, addr, PTE_USER | PTE_RW | PTE_PRESENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
load_cr3(proc->pml4_phys);
|
||||||
|
if (seg->filesz > 0) memcpy((void*)seg->vaddr, data + seg->offset, seg->filesz);
|
||||||
|
if (seg->memsz > seg->filesz) {
|
||||||
|
u64 bss_start = seg->vaddr + seg->filesz;
|
||||||
|
u64 bss_len = seg->memsz - seg->filesz;
|
||||||
|
memset((void*)bss_start, 0, bss_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
load_cr3(kernel_cr3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return header->entry_point;
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
// Copyright (c) 2026 0xKarinyash
|
||||||
|
|
||||||
|
#include <core/panic.h>
|
||||||
|
#include <core/hot.h>
|
||||||
|
#include <core/loader.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;
|
||||||
|
|
||||||
|
#define USER_STACK_TOP 0x70000000
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
fs_node* file = vfs_open("/init");
|
||||||
|
if (!file) panic("FATAL: /init not found!");
|
||||||
|
|
||||||
|
u8* file_buffer = (u8*)malloc(file->len);
|
||||||
|
vfs_read(file, 0, file->len, file_buffer);
|
||||||
|
|
||||||
|
u64 entry = load_hot(init_proc, file_buffer);
|
||||||
|
if (!entry) panic("Invalid HOT executable");
|
||||||
|
|
||||||
|
free(file_buffer);
|
||||||
|
vmm_setup_user_stack((u64*)init_proc->pml4_phys);
|
||||||
|
sched_spawn((void(*)())entry, init_proc, true, USER_STACK_TOP);
|
||||||
|
|
||||||
|
while(1) { __asm__("sti; hlt"); }
|
||||||
|
}
|
||||||
@@ -51,7 +51,9 @@ const char* fun_messages[] = {
|
|||||||
"Attaboy, Jack. He's good. Really good.",
|
"Attaboy, Jack. He's good. Really good.",
|
||||||
"Zhenih priehal",
|
"Zhenih priehal",
|
||||||
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
|
"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);
|
console_set_default_color(0xFFFFFF);
|
||||||
|
|
||||||
u64 msg_count = sizeof(fun_messages) / sizeof(fun_messages[0]);
|
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("\n\n");
|
||||||
kprintf("\t\t\t\t^bKERNEL PANIC^! :( \n");
|
kprintf("\t\t\t\t^bKERNEL PANIC^! :( \n");
|
||||||
@@ -133,7 +135,7 @@ __attribute__((noreturn)) void panic_exception(Registers *regs) {
|
|||||||
u64 user = (regs->err_code & (1 << 2)) != 0;
|
u64 user = (regs->err_code & (1 << 2)) != 0;
|
||||||
u64 reserved = (regs->err_code & (1 << 3)) != 0;
|
u64 reserved = (regs->err_code & (1 << 3)) != 0;
|
||||||
u64 instruction = (regs->err_code & (1 << 4)) != 0;
|
u64 instruction = (regs->err_code & (1 << 4)) != 0;
|
||||||
kprintf("\t\t\t[^bP^!] ^yReason^! %s\n", present ? "Page Protection violation" : "Non-present page");
|
kprintf("\t\t\t[^bP^!] ^yReason^!: %s\n", present ? "Page Protection violation" : "Non-present page");
|
||||||
kprintf("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
|
kprintf("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
|
||||||
kprintf("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
|
kprintf("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
|
||||||
if (reserved) kprintf("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
|
if (reserved) kprintf("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
|
||||||
|
|||||||
+34
-4
@@ -1,15 +1,45 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2025 0xKarinyash
|
||||||
|
|
||||||
|
#include "bootinfo.h"
|
||||||
#include <core/rand.h>
|
#include <core/rand.h>
|
||||||
|
#include <cpuinfo.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
// really shiity rand lol.
|
static u64 prng_state = 0;
|
||||||
// not shitty.. basic.
|
|
||||||
|
|
||||||
u64 shitrand() {
|
static inline u64 rdtsc() {
|
||||||
int lo, hi;
|
u32 lo, hi;
|
||||||
__asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi));
|
__asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi));
|
||||||
|
|
||||||
return ((u64)hi << 32) | lo;
|
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();
|
||||||
}
|
}
|
||||||
+37
-12
@@ -3,36 +3,56 @@
|
|||||||
|
|
||||||
#include <core/panic.h>
|
#include <core/panic.h>
|
||||||
#include <core/scheduler.h>
|
#include <core/scheduler.h>
|
||||||
|
#include <core/string.h>
|
||||||
#include <mm/heap.h>
|
#include <mm/heap.h>
|
||||||
|
#include <mm/vmm.h>
|
||||||
|
#include <cpuinfo.h>
|
||||||
|
#include <gdt.h>
|
||||||
|
|
||||||
task_t* curr_task = nullptr;
|
task* curr_task = nullptr;
|
||||||
u32 next_pid = 1;
|
u32 next_pid = 1;
|
||||||
|
|
||||||
extern void irq0_handler();
|
extern void irq0_handler();
|
||||||
|
extern u64 pml4_kernel_phys;
|
||||||
|
|
||||||
|
static process kernel_process;
|
||||||
|
|
||||||
void sched_init() {
|
void sched_init() {
|
||||||
task_t* kt = (task_t*)malloc(sizeof(task_t));
|
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->id = 0;
|
||||||
|
kt->proc = &kernel_process;
|
||||||
kt->sleep_ticks = 0;
|
kt->sleep_ticks = 0;
|
||||||
kt->next = kt;
|
kt->next = kt;
|
||||||
|
|
||||||
curr_task = kt;
|
curr_task = kt;
|
||||||
}
|
}
|
||||||
|
|
||||||
task_t* sched_spawn(void(*entry)()) {
|
task* sched_spawn(void(*entry)(), process* owner, bool is_user, u64 fixed_user_stack) {
|
||||||
task_t* t = (task_t*)malloc(sizeof(task_t));
|
task* t = (task*)malloc(sizeof(task));
|
||||||
if (!t) return nullptr;
|
if (!t) return nullptr;
|
||||||
|
if (!owner) owner = &kernel_process;
|
||||||
|
|
||||||
u64 stack_size = 16384;
|
u64 stack_size = 16384;
|
||||||
u8* stack_base = (u8*)malloc(stack_size);
|
u8* stack_base = (u8*)malloc(stack_size);
|
||||||
if (!stack_base) panic("OOM for task stack");
|
if (!stack_base) panic("OOM for task stack");
|
||||||
u64* rsp = (u64*)(stack_base + stack_size);
|
u64* rsp = (u64*)(stack_base + stack_size);
|
||||||
|
|
||||||
*--rsp = 0x10; // SS -- Kernel data
|
u64 cs = is_user ? 0x23 : 0x08;
|
||||||
*--rsp = (u64)stack_base + stack_size; // rsp
|
u64 ss = is_user ? 0x1b : 0x10;
|
||||||
*--rsp = 0x202; // RFLAGS -- Interrupts Enabled | Reserved bit;
|
u64 rflags = 0x202;
|
||||||
*--rsp = 0x08; // CS -- Kernel Code;
|
u64 target_rsp = 0;
|
||||||
|
if (is_user) target_rsp = fixed_user_stack;
|
||||||
|
else target_rsp = (u64)stack_base + stack_size;
|
||||||
|
|
||||||
|
*--rsp = ss; // SS -- Kernel data
|
||||||
|
*--rsp = target_rsp; // rsp
|
||||||
|
*--rsp = rflags; // RFLAGS -- Interrupts Enabled | Reserved bit;
|
||||||
|
*--rsp = cs; // CS -- Kernel Code;
|
||||||
*--rsp = (u64)entry; // RIP
|
*--rsp = (u64)entry; // RIP
|
||||||
|
|
||||||
*--rsp = 0; // int no
|
*--rsp = 0; // int no
|
||||||
@@ -41,11 +61,12 @@ task_t* sched_spawn(void(*entry)()) {
|
|||||||
for (u8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
|
for (u8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
|
||||||
|
|
||||||
t->rsp = (u64)rsp;
|
t->rsp = (u64)rsp;
|
||||||
|
t->proc = owner;
|
||||||
t->id = next_pid++;
|
t->id = next_pid++;
|
||||||
t->sleep_ticks = 0;
|
t->sleep_ticks = 0;
|
||||||
t->next = curr_task->next;
|
t->next = curr_task->next;
|
||||||
|
t->kernel_stack_top = (u64)stack_base + stack_size;
|
||||||
curr_task->next = t;
|
curr_task->next = t;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +74,7 @@ u64 sched_next(u64 curr_rsp) {
|
|||||||
if (!curr_task) return curr_rsp;
|
if (!curr_task) return curr_rsp;
|
||||||
|
|
||||||
curr_task->rsp = curr_rsp;
|
curr_task->rsp = curr_rsp;
|
||||||
task_t* it = curr_task->next;
|
task* it = curr_task->next;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (it->sleep_ticks > 0) it->sleep_ticks--;
|
if (it->sleep_ticks > 0) it->sleep_ticks--;
|
||||||
@@ -62,10 +83,14 @@ u64 sched_next(u64 curr_rsp) {
|
|||||||
|
|
||||||
if (curr_task->sleep_ticks > 0) curr_task->sleep_ticks--;
|
if (curr_task->sleep_ticks > 0) curr_task->sleep_ticks--;
|
||||||
|
|
||||||
task_t* next = curr_task->next;
|
task* next = curr_task->next;
|
||||||
while (next != curr_task && next->sleep_ticks > 0) next = next->next; // what the fuck i just wrote
|
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;
|
curr_task = next;
|
||||||
|
tss.rsp0 = curr_task->kernel_stack_top;
|
||||||
|
g_cpu.kernel_rsp = curr_task->kernel_stack_top;
|
||||||
return curr_task->rsp;
|
return curr_task->rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,8 @@
|
|||||||
#include <mm/memory.h>
|
#include <mm/memory.h>
|
||||||
|
|
||||||
#define SHITGUI_TRANSPARENCY_KEY 0xFF00FF
|
#define SHITGUI_TRANSPARENCY_KEY 0xFF00FF
|
||||||
#define SHITGUI_MAX_WINDOWS_AMOUNT 64
|
|
||||||
|
|
||||||
SG_Context* main_context;
|
SG_Context* main_context;
|
||||||
SG_Window* windows[SHITGUI_MAX_WINDOWS_AMOUNT]; // нет блять линукс
|
|
||||||
u64 windows_amount = 0;
|
|
||||||
|
|
||||||
void sg_init(SG_Context *ctx) {
|
void sg_init(SG_Context *ctx) {
|
||||||
main_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+27
-5
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2025 0xKarinyash
|
||||||
|
|
||||||
#include "bootinfo.h"
|
#include "bootinfo.h"
|
||||||
|
|
||||||
#include <shell/ksh.h>
|
#include <shell/ksh.h>
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
@@ -14,10 +15,14 @@
|
|||||||
#include <core/panic.h>
|
#include <core/panic.h>
|
||||||
#include <core/scheduler.h>
|
#include <core/scheduler.h>
|
||||||
#include <core/splash.h>
|
#include <core/splash.h>
|
||||||
|
#include <core/rand.h>
|
||||||
|
#include <core/loader.h>
|
||||||
|
|
||||||
#include <gdt.h>
|
#include <gdt.h>
|
||||||
#include <idt.h>
|
#include <idt.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
|
#include <cpuinfo.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <mm/vmm.h>
|
#include <mm/vmm.h>
|
||||||
@@ -30,6 +35,7 @@
|
|||||||
#define BG_COLOR 0x111111
|
#define BG_COLOR 0x111111
|
||||||
|
|
||||||
extern u64 _kernel_end;
|
extern u64 _kernel_end;
|
||||||
|
extern void* stack_top;
|
||||||
static SG_Context sg_ctx;
|
static SG_Context sg_ctx;
|
||||||
|
|
||||||
void kmain(Bootinfo* info) {
|
void kmain(Bootinfo* info) {
|
||||||
@@ -40,6 +46,10 @@ void kmain(Bootinfo* info) {
|
|||||||
|
|
||||||
if (info->magic != BOOTINFO_MAGIC) panic("Corrupt bootinfo!");
|
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();
|
gdt_init();
|
||||||
kprintf("GDT initialized\n");
|
kprintf("GDT initialized\n");
|
||||||
idt_init();
|
idt_init();
|
||||||
@@ -58,15 +68,16 @@ void kmain(Bootinfo* info) {
|
|||||||
kprintf("Scheduler initialized\n");
|
kprintf("Scheduler initialized\n");
|
||||||
sg_init(&sg_ctx);
|
sg_init(&sg_ctx);
|
||||||
kprintf("Shitgui initialized\n");
|
kprintf("Shitgui initialized\n");
|
||||||
|
syscall_init();
|
||||||
|
|
||||||
info = (Bootinfo*)PHYS_TO_HHDM((u64)info);
|
info = (Bootinfo*)PHYS_TO_HHDM((u64)info);
|
||||||
|
|
||||||
fs_node* root = cpio_mount(PHYS_TO_HHDM(info->initramfs.addr), info->initramfs.size);
|
fs_node* root = cpio_mount(PHYS_TO_HHDM(info->initramfs.addr), info->initramfs.size);
|
||||||
vfs_init(root);
|
vfs_init(root);
|
||||||
kprintf("VFS initialized");
|
kprintf("VFS initialized\n");
|
||||||
|
|
||||||
u32 *fb = (u32*)info->framebuffer.base;
|
u32 *fb = (u32*)info->framebuffer.base;
|
||||||
if (!fb) return serial_write("No framebuffer found!!");
|
if (!fb) return kprintf("No framebuffer found!!");
|
||||||
|
|
||||||
sg_ctx.fb = fb;
|
sg_ctx.fb = fb;
|
||||||
sg_ctx.height = info->framebuffer.height;
|
sg_ctx.height = info->framebuffer.height;
|
||||||
@@ -79,9 +90,20 @@ void kmain(Bootinfo* info) {
|
|||||||
|
|
||||||
show_splash(&sg_ctx);
|
show_splash(&sg_ctx);
|
||||||
|
|
||||||
sched_spawn(composer_task);
|
bool staying_in_ksh = false;
|
||||||
sched_spawn(ksh);
|
if (!info->initramfs.addr) {
|
||||||
if (!info->initramfs.addr) kprintf("^rWARNING^!: Failed to load ^yinitramfs^!, VFS is empty.\n\n");
|
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, false, 0);
|
||||||
|
else sched_spawn(init_task_entry, nullptr, false, 0);
|
||||||
|
|
||||||
__asm__ volatile("sti");
|
__asm__ volatile("sti");
|
||||||
|
|
||||||
while (true) __asm__ volatile("hlt");
|
while (true) __asm__ volatile("hlt");
|
||||||
|
|||||||
+67
-17
@@ -4,13 +4,19 @@
|
|||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <mm/memory.h>
|
#include <mm/memory.h>
|
||||||
|
|
||||||
|
#include <core/panic.h>
|
||||||
|
|
||||||
#include <gdt.h>
|
#include <gdt.h>
|
||||||
#include <idt.h>
|
#include <idt.h>
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include "bootinfo.h"
|
#include "bootinfo.h"
|
||||||
|
|
||||||
|
#define USER_STACK_TOP 0x70000000
|
||||||
|
#define USER_STACK_SIZE 0x4000
|
||||||
|
|
||||||
u64* pml4_kernel = nullptr;
|
u64* pml4_kernel = nullptr;
|
||||||
|
u64 pml4_kernel_phys = 0;
|
||||||
static bool is_initialized = false;
|
static bool is_initialized = false;
|
||||||
|
|
||||||
extern u64 _kernel_start;
|
extern u64 _kernel_start;
|
||||||
@@ -18,7 +24,6 @@ extern u64 _kernel_end;
|
|||||||
extern u8* bitmap;
|
extern u8* bitmap;
|
||||||
extern u64 bitmap_size_g;
|
extern u64 bitmap_size_g;
|
||||||
extern GDTDescriptor gdt[];
|
extern GDTDescriptor gdt[];
|
||||||
extern TSS tss[];
|
|
||||||
extern IDTEntry idt[];
|
extern IDTEntry idt[];
|
||||||
extern u8 double_fault_stack[];
|
extern u8 double_fault_stack[];
|
||||||
extern u8 stack_guard;
|
extern u8 stack_guard;
|
||||||
@@ -37,12 +42,16 @@ u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) {
|
|||||||
u64* pml4_virt = pml4;
|
u64* pml4_virt = pml4;
|
||||||
if (is_initialized) pml4_virt = (u64*)PHYS_TO_HHDM((u64)pml4);
|
if (is_initialized) pml4_virt = (u64*)PHYS_TO_HHDM((u64)pml4);
|
||||||
|
|
||||||
|
u64 table_flags = PTE_PRESENT | PTE_RW | (flags & PTE_USER);
|
||||||
|
|
||||||
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
|
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
|
||||||
u64* addr = pmm_alloc_page();
|
u64* addr = pmm_alloc_page();
|
||||||
if (!addr) return nullptr;
|
if (!addr) return nullptr;
|
||||||
u64* addr_virt = get_table_virt((u64)addr);
|
u64* addr_virt = get_table_virt((u64)addr);
|
||||||
memset(addr_virt, 0, PAGE_SIZE);
|
memset(addr_virt, 0, PAGE_SIZE);
|
||||||
pml4_virt[pml4_idx] = (u64)addr | PTE_PRESENT | PTE_RW;
|
pml4_virt[pml4_idx] = (u64)addr | table_flags;
|
||||||
|
} else {
|
||||||
|
pml4_virt[pml4_idx] |= (flags & PTE_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64* pdpt = (u64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
|
u64* pdpt = (u64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
|
||||||
@@ -53,7 +62,9 @@ u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) {
|
|||||||
if (!addr) return nullptr;
|
if (!addr) return nullptr;
|
||||||
u64* addr_virt = get_table_virt((u64)addr);
|
u64* addr_virt = get_table_virt((u64)addr);
|
||||||
memset(addr_virt, 0, PAGE_SIZE);
|
memset(addr_virt, 0, PAGE_SIZE);
|
||||||
pdpt_virt[pdpt_idx] = (u64)addr | PTE_PRESENT | PTE_RW;
|
pdpt_virt[pdpt_idx] = (u64)addr | table_flags;
|
||||||
|
} else {
|
||||||
|
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64* pd = (u64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
|
u64* pd = (u64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
|
||||||
@@ -64,7 +75,9 @@ u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) {
|
|||||||
if (!addr) return nullptr;
|
if (!addr) return nullptr;
|
||||||
u64* addr_virt = get_table_virt((u64)addr);
|
u64* addr_virt = get_table_virt((u64)addr);
|
||||||
memset(addr_virt, 0, PAGE_SIZE);
|
memset(addr_virt, 0, PAGE_SIZE);
|
||||||
pd_virt[pd_idx] = (u64)addr | PTE_PRESENT | PTE_RW;
|
pd_virt[pd_idx] = (u64)addr | table_flags;
|
||||||
|
} else {
|
||||||
|
pd_virt[pd_idx] |= (flags & PTE_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64* pt = (u64*)PTE_GET_ADDR(pd_virt[pd_idx]);
|
u64* pt = (u64*)PTE_GET_ADDR(pd_virt[pd_idx]);
|
||||||
@@ -82,26 +95,30 @@ void vmm_unmap_page(u64* pml4, u64 virt) {
|
|||||||
u64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
u64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||||
u64 pml4_idx = VMM_PML4_INDEX(virt);
|
u64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||||
|
|
||||||
if (!(pml4[pml4_idx] & PTE_PRESENT)) return;
|
u64* pml4_virt = pml4;
|
||||||
u64* pdpt = get_table_virt(PTE_GET_ADDR(pml4[pml4_idx]));
|
if (is_initialized) pml4_virt = (u64*)PHYS_TO_HHDM((u64)pml4);
|
||||||
|
|
||||||
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]));
|
|
||||||
|
|
||||||
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");
|
__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");
|
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void vmm_init(Bootinfo* info) {
|
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);
|
memset(pml4_kernel, 0, PAGE_SIZE);
|
||||||
|
|
||||||
u64 k_virt_start = (u64)&_kernel_start;
|
u64 k_virt_start = (u64)&_kernel_start;
|
||||||
@@ -119,6 +136,39 @@ void vmm_init(Bootinfo* info) {
|
|||||||
|
|
||||||
bitmap = (u8*)PHYS_TO_HHDM((u64)bitmap);
|
bitmap = (u8*)PHYS_TO_HHDM((u64)bitmap);
|
||||||
info->framebuffer.base = (u32*)FB_VIRT_BASE;
|
info->framebuffer.base = (u32*)FB_VIRT_BASE;
|
||||||
load_cr3((u64)pml4_kernel);
|
load_cr3(pml4_kernel_phys);
|
||||||
is_initialized = true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vmm_setup_user_stack(u64* pml4_phys) {
|
||||||
|
u64 stack_bottom = USER_STACK_TOP - USER_STACK_SIZE;
|
||||||
|
for (u64 addr = stack_bottom; addr < USER_STACK_TOP; addr += 4096) {
|
||||||
|
void* phys = pmm_alloc_page();
|
||||||
|
if (!phys) panic("OOM in user stack setup");
|
||||||
|
memset((void*)PHYS_TO_HHDM((u64)phys), 0, 4096);
|
||||||
|
vmm_map_page((u64*)pml4_phys, (u64)phys, addr, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+39
-18
@@ -1,14 +1,26 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2025 0xKarinyash
|
||||||
|
|
||||||
#include <drivers/console.h>
|
|
||||||
#include <core/rand.h>
|
|
||||||
|
|
||||||
#include <drivers/timer.h>
|
|
||||||
#include <types.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 "../data/cats.h"
|
||||||
#include "shell/dbgcmd.h"
|
|
||||||
|
extern task* curr_task;
|
||||||
|
|
||||||
const char* ascii_logo[] = {
|
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() {
|
void cmd_kfetch() {
|
||||||
u64 uptime_s = get_uptime() / 1000;
|
u64 uptime_s = get_uptime() / 1000;
|
||||||
|
|
||||||
kprintf("\n\n");
|
kprintf("\n\n");
|
||||||
kprintf("^p %s ^!\t\t^g kernel^!@^gtermos\n^0", ascii_logo[0]);
|
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^!-------------\n^!", ascii_logo[1]);
|
||||||
kprintf("^p %s ^!\t\t^gOS^!: termOS 0.0.1\n^!", ascii_logo[2]);
|
kprintf("^p %s ^!\t\t^gOS^!: termOS %s\n^!", ascii_logo[2], TERMOS_VERSION);
|
||||||
kprintf("^p %s ^!\t\t^gKernel^!: sucks\n^!", ascii_logo[3]);
|
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^gUptime^!: %d seconds\n^!", ascii_logo[4], uptime_s);
|
||||||
kprintf("^p %s ^!\t\t^gShell^!: ksh\n^!", ascii_logo[5]);
|
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 ^!\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^gCPU^!: %s (^yFamily^!: %d; ^yModel^!: %d)\n^!", ascii_logo[7], g_cpu.vendor, g_cpu.family, g_cpu.model);
|
||||||
kprintf("\n\n");
|
kprintf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_meow() {
|
void cmd_meow() {
|
||||||
u64 cats_count = sizeof(cats) / sizeof(cats[0]);
|
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]);
|
kprintf("Nyaaa!!\n\n%s\n\n", cats[rand_num]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_help() {
|
void cmd_help() {
|
||||||
kprintf("Welcome to ^ptermOS^!'s ^gk^!ernel ^gsh^!ell!\n");
|
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("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("Available commands:\n");
|
||||||
|
|
||||||
kprintf("\t^rDebug^!:\n");
|
kprintf("\t^rDebug^!:\n");
|
||||||
kprintf("\t\t^ysleep^! \t\tSleep for 3seconds\n");
|
kprintf("\t\t^ysleep^! \t\tSleep for 3seconds\n");
|
||||||
kprintf("\t\t^ydbg^! \t\tTest new stuff\n");
|
kprintf("\t\t^ydbg^! \t\tTest new stuff\n");
|
||||||
kprintf("\t\t^yregs^! \t\tPrint current regs\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^ypanic^! \t\tPanics (lol)\n");
|
||||||
kprintf("\t\t^yud2^! \t\tPanics with #UD\n");
|
kprintf("\t\t^yud2^! \t\tPanics with #UD\n");
|
||||||
kprintf("\t\t^ypf^! \t\tPanics with #PF\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^pFun^!:\n");
|
||||||
kprintf("\t\t^ysplash^! \t\tShows splash (works kinda unstable)\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^bMisc^!:\n");
|
||||||
kprintf("\t\t^yclear^! \t\tClear console\n");
|
kprintf("\t\t^yclear^! \t\tClear console\n");
|
||||||
kprintf("\t\t^yhelp^! \t\tShow this menu\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() {
|
void cmd_regs() {
|
||||||
@@ -100,8 +107,22 @@ void cmd_sleep() {
|
|||||||
sleep(3000);
|
sleep(3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmd_rand() {
|
||||||
|
kprintf("Your rand number (0..100) is ... ^y%d^!!\n", krand() % 100);
|
||||||
|
}
|
||||||
|
|
||||||
void cmd_debug() {
|
void cmd_debug() {
|
||||||
u64 status = debug();
|
u64 status = debug();
|
||||||
kprintf("\nDebug ended with code %d\n", status);
|
kprintf("\nDebug ended with code %d\n", status);
|
||||||
return;
|
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() {
|
||||||
|
sched_spawn(init_task_entry, nullptr, false, 0);
|
||||||
|
}
|
||||||
@@ -1,31 +1,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// Copyright (c) 2025 0xKarinyash
|
// Copyright (c) 2026 0xKarinyash
|
||||||
// contents of this file will be changed CONSTANTLY
|
|
||||||
// im just testing new stuff here
|
|
||||||
|
|
||||||
#include <drivers/console.h>
|
|
||||||
#include <shell/dbgcmd.h>
|
#include <shell/dbgcmd.h>
|
||||||
#include <fs/vfs.h>
|
#include <drivers/console.h>
|
||||||
#include <mm/memory.h>
|
|
||||||
|
|
||||||
u64 debug() {
|
u64 debug() {
|
||||||
kprintf("Debug: Trying to open /test1.txt...\n");
|
|
||||||
|
|
||||||
fs_node* file = vfs_open("/test1.txt");
|
|
||||||
|
|
||||||
if (file == nullptr) {
|
|
||||||
kprintf("Error: File not found! Check initrd or filename.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
kprintf("Success!\n");
|
|
||||||
kprintf("\tFilename: %s\n", file->name);
|
|
||||||
kprintf("\tSize: %d bytes\n", file->len);
|
|
||||||
|
|
||||||
char buf[64];
|
|
||||||
memset(buf, 0, 64);
|
|
||||||
vfs_read(file, 0, 63, (u8*)buf);
|
|
||||||
kprintf("\tContent: %s\n", buf);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
+12
-4
@@ -33,9 +33,12 @@ typedef enum {
|
|||||||
TOKEN_PANIC,
|
TOKEN_PANIC,
|
||||||
TOKEN_PANIC_UD2,
|
TOKEN_PANIC_UD2,
|
||||||
TOKEN_PANIC_PF,
|
TOKEN_PANIC_PF,
|
||||||
|
TOKEN_USERSPACE,
|
||||||
|
|
||||||
TOKEN_CLEAR,
|
TOKEN_CLEAR,
|
||||||
TOKEN_BLINKING,
|
TOKEN_BLINKING,
|
||||||
|
TOKEN_RAND,
|
||||||
|
TOKEN_VER,
|
||||||
|
|
||||||
TOKEN_BACK,
|
TOKEN_BACK,
|
||||||
TOKEN_FORWARD,
|
TOKEN_FORWARD,
|
||||||
@@ -56,10 +59,10 @@ static const ksh_command_map token_map[] = {
|
|||||||
{"sleep", TOKEN_SLEEP},
|
{"sleep", TOKEN_SLEEP},
|
||||||
{"dbg", TOKEN_DEBUG},
|
{"dbg", TOKEN_DEBUG},
|
||||||
{"regs", TOKEN_REGS},
|
{"regs", TOKEN_REGS},
|
||||||
{"rectest", TOKEN_RECTEST},
|
|
||||||
{"panic", TOKEN_PANIC},
|
{"panic", TOKEN_PANIC},
|
||||||
{"ud2", TOKEN_PANIC_UD2},
|
{"ud2", TOKEN_PANIC_UD2},
|
||||||
{"pf", TOKEN_PANIC_PF},
|
{"pf", TOKEN_PANIC_PF},
|
||||||
|
{"userspace", TOKEN_USERSPACE},
|
||||||
|
|
||||||
// fun
|
// fun
|
||||||
{"meow", TOKEN_MEOW},
|
{"meow", TOKEN_MEOW},
|
||||||
@@ -69,6 +72,9 @@ static const ksh_command_map token_map[] = {
|
|||||||
// misc
|
// misc
|
||||||
{"help", TOKEN_HELP},
|
{"help", TOKEN_HELP},
|
||||||
{"clear", TOKEN_CLEAR},
|
{"clear", TOKEN_CLEAR},
|
||||||
|
{"rand", TOKEN_RAND},
|
||||||
|
{"ver", TOKEN_VER},
|
||||||
|
|
||||||
{nullptr, TOKEN_NULL}
|
{nullptr, TOKEN_NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +86,7 @@ ksh_token char2token(char* token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ksh() {
|
void ksh() {
|
||||||
sched_spawn(cursor_blinker_sched_task);
|
sched_spawn(cursor_blinker_sched_task, nullptr, false, 0);
|
||||||
while (true) {
|
while (true) {
|
||||||
kprintf("ksh_> ");
|
kprintf("ksh_> ");
|
||||||
char cmdbuff[256];
|
char cmdbuff[256];
|
||||||
@@ -90,15 +96,17 @@ void ksh() {
|
|||||||
|
|
||||||
case TOKEN_CLEAR: console_clear((u32) console_get_colors() & 0xFFFFFFFF); break;
|
case TOKEN_CLEAR: console_clear((u32) console_get_colors() & 0xFFFFFFFF); break;
|
||||||
case TOKEN_BLINKING: console_toggle_cursor_blink(); 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_SLEEP: cmd_sleep(); break;
|
||||||
case TOKEN_DEBUG: cmd_debug(); break;
|
case TOKEN_DEBUG: cmd_debug(); break;
|
||||||
case TOKEN_REGS: cmd_regs(); break;
|
case TOKEN_REGS: cmd_regs(); break;
|
||||||
case TOKEN_RECTEST: rectest(0); break;
|
|
||||||
case TOKEN_PANIC: panic("Manually initiated panic");
|
case TOKEN_PANIC: panic("Manually initiated panic");
|
||||||
case TOKEN_PANIC_UD2: __asm__ volatile ("ud2");
|
case TOKEN_PANIC_UD2: __asm__ volatile ("ud2");
|
||||||
case TOKEN_PANIC_PF: u64* bad_ptr = (u64*)0xDEADBEEF; *bad_ptr = 666;
|
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_SPLASH: show_splash(console_get_context()); break;
|
||||||
case TOKEN_KFETCH: cmd_kfetch(); break;
|
case TOKEN_KFETCH: cmd_kfetch(); break;
|
||||||
case TOKEN_MEOW: cmd_meow(); break;
|
case TOKEN_MEOW: cmd_meow(); break;
|
||||||
|
|||||||
Generated
+88
@@ -0,0 +1,88 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "elf2hot"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"goblin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "goblin"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4db6758c546e6f81f265638c980e5e84dfbda80cfd8e89e02f83454c8e8124bd"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"plain",
|
||||||
|
"scroll",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plain"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scroll"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add"
|
||||||
|
dependencies = [
|
||||||
|
"scroll_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scroll_derive"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed76efe62313ab6610570951494bdaa81568026e0318eaa55f167de70eeea67d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.114"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "elf2hot"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
goblin = "0.10.4"
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
use goblin::elf::program_header::PT_LOAD;
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct HotHeader {
|
||||||
|
magic: u32,
|
||||||
|
version: u8,
|
||||||
|
reserved_pad: [u8; 3],
|
||||||
|
entry_point: u64,
|
||||||
|
segments_count: u64,
|
||||||
|
reserved: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Default, Debug, Clone, Copy)]
|
||||||
|
struct HotSegment {
|
||||||
|
stype: u64,
|
||||||
|
vaddr: u64,
|
||||||
|
offset: u64,
|
||||||
|
filesz: u64,
|
||||||
|
memsz: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
const HOT_MAGIC: u32 = 0x21544F48; // "HOT!"
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() < 3 {
|
||||||
|
println!("Usage: elf2hot <input_elf> <output_hot>");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let input_path = &args[1];
|
||||||
|
let output_path = &args[2];
|
||||||
|
|
||||||
|
let mut f = File::open(input_path)?;
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
f.read_to_end(&mut buffer)?;
|
||||||
|
|
||||||
|
let elf = goblin::elf::Elf::parse(&buffer)?;
|
||||||
|
|
||||||
|
let mut hot_segments = Vec::new();
|
||||||
|
let mut segment_data = Vec::new();
|
||||||
|
|
||||||
|
let mut current_offset = std::mem::size_of::<HotHeader>() as u64;
|
||||||
|
|
||||||
|
let load_segments: Vec<_> = elf.program_headers.iter()
|
||||||
|
.filter(|ph| ph.p_type == PT_LOAD)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
current_offset += (load_segments.len() * std::mem::size_of::<HotSegment>()) as u64;
|
||||||
|
|
||||||
|
for ph in load_segments {
|
||||||
|
let is_code = ph.is_executable();
|
||||||
|
|
||||||
|
let data = &buffer[ph.p_offset as usize..(ph.p_offset + ph.p_filesz) as usize];
|
||||||
|
segment_data.push(data);
|
||||||
|
|
||||||
|
hot_segments.push(HotSegment {
|
||||||
|
stype: if is_code { 1 } else { 2 },
|
||||||
|
vaddr: ph.p_vaddr,
|
||||||
|
offset: current_offset,
|
||||||
|
filesz: ph.p_filesz,
|
||||||
|
memsz: ph.p_memsz,
|
||||||
|
});
|
||||||
|
|
||||||
|
current_offset += ph.p_filesz;
|
||||||
|
}
|
||||||
|
|
||||||
|
let header = HotHeader {
|
||||||
|
magic: HOT_MAGIC,
|
||||||
|
version: 1,
|
||||||
|
entry_point: elf.entry,
|
||||||
|
segments_count: hot_segments.len() as u64,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut out = File::create(output_path)?;
|
||||||
|
|
||||||
|
let header_bytes: [u8; std::mem::size_of::<HotHeader>()] = unsafe { std::mem::transmute(header) };
|
||||||
|
out.write_all(&header_bytes)?;
|
||||||
|
|
||||||
|
for seg in hot_segments {
|
||||||
|
let seg_bytes: [u8; std::mem::size_of::<HotSegment>()] = unsafe { std::mem::transmute(seg) };
|
||||||
|
out.write_all(&seg_bytes)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for data in segment_data {
|
||||||
|
out.write_all(data)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Successfully converted {} to {}!", input_path, output_path);
|
||||||
|
println!("Entry point: 0x{:X}", elf.entry);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -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,33 @@
|
|||||||
|
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)
|
||||||
|
|
||||||
|
get_filename_component(TOOLS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../tools/elf2hot" ABSOLUTE)
|
||||||
|
set(FINAL_INIT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../initramfs/init")
|
||||||
|
|
||||||
|
file(GLOB_RECURSE INIT_SOURCES "src/*.asm" "src/*.c")
|
||||||
|
|
||||||
|
add_executable(init_elf ${INIT_SOURCES})
|
||||||
|
|
||||||
|
set_target_properties(init_elf PROPERTIES
|
||||||
|
OUTPUT_NAME "init"
|
||||||
|
LINKER_LANGUAGE C
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_options(init_elf PRIVATE
|
||||||
|
-nostdlib
|
||||||
|
-static
|
||||||
|
-T "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(TARGET init_elf POST_BUILD
|
||||||
|
COMMAND cargo run --release --quiet -- $<TARGET_FILE:init_elf> ${FINAL_INIT_PATH}
|
||||||
|
|
||||||
|
WORKING_DIRECTORY ${TOOLS_DIR}
|
||||||
|
|
||||||
|
COMMENT "Cargo is converting ELF to HOT! format..."
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
ENTRY(start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x400000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.gnu.build-id)
|
||||||
|
*(.note.GNU-stack)
|
||||||
|
*(.note.gnu.property)
|
||||||
|
*(.comment)
|
||||||
|
*(.interp)
|
||||||
|
*(.dynsym)
|
||||||
|
*(.dynstr)
|
||||||
|
*(.hash)
|
||||||
|
*(.gnu.hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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