full refactor in kernel/: now its apple-styled; im so fucking tired
This commit is contained in:
@@ -82,7 +82,7 @@ int main()
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
print_initramfs_warning(L"initramfs.cpio is missing");
|
||||
boot_info->initramfs.addr = nullptr;
|
||||
boot_info->initramfs.address = nullptr;
|
||||
boot_info->initramfs.size = 0;
|
||||
} else {
|
||||
status = initramfs_file->GetInfo(initramfs_file, &fi_guid, &iinfo_size, nullptr);
|
||||
@@ -105,14 +105,14 @@ int main()
|
||||
// just fucking kill me
|
||||
uintn_t initramfs_size_read = (uintn_t)initramfs_size;
|
||||
initramfs_file->Read(initramfs_file, &initramfs_size_read, (void*)initramfs_addr);
|
||||
boot_info->initramfs.addr = (void*)initramfs_addr;
|
||||
boot_info->initramfs.address = (void*)initramfs_addr;
|
||||
boot_info->initramfs.size = initramfs_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boot_info->framebuffer.base = (uint32_t*)gop->Mode->FrameBufferBase;
|
||||
boot_info->framebuffer.base_size = gop->Mode->FrameBufferSize;
|
||||
boot_info->framebuffer.baseSize = gop->Mode->FrameBufferSize;
|
||||
boot_info->framebuffer.height = gop->Mode->Information->VerticalResolution;
|
||||
boot_info->framebuffer.width = gop->Mode->Information->HorizontalResolution;
|
||||
boot_info->framebuffer.pitch = gop->Mode->Information->PixelsPerScanLine;
|
||||
@@ -139,11 +139,11 @@ int main()
|
||||
break;
|
||||
}
|
||||
|
||||
boot_info->mem.descriptor_size = desc_size;
|
||||
boot_info->mem.descriptor_version = desc_version;
|
||||
boot_info->mem.map_size = map_size;
|
||||
boot_info->mem.map_key = map_key;
|
||||
boot_info->mem.map = map;
|
||||
boot_info->memoryMap.descriptorSize = desc_size;
|
||||
boot_info->memoryMap.descriptorVersion = desc_version;
|
||||
boot_info->memoryMap.mapSize = map_size;
|
||||
boot_info->memoryMap.mapKey = map_key;
|
||||
boot_info->memoryMap.map = map;
|
||||
|
||||
status = gBS->ExitBootServices(IM, map_key);
|
||||
if (status == EFI_SUCCESS) {
|
||||
|
||||
+20
-20
@@ -3,35 +3,35 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef unsigned int bi_u32;
|
||||
typedef unsigned long long bi_u64;
|
||||
typedef unsigned int BIUInt32;
|
||||
typedef unsigned long long BIUInt64;
|
||||
|
||||
typedef struct {
|
||||
bi_u32* base;
|
||||
bi_u64 base_size;
|
||||
bi_u64 width;
|
||||
bi_u64 height;
|
||||
bi_u64 pitch;
|
||||
} BI_Framebuffer;
|
||||
BIUInt32* base;
|
||||
BIUInt64 baseSize;
|
||||
BIUInt64 width;
|
||||
BIUInt64 height;
|
||||
BIUInt64 pitch;
|
||||
} BIFramebuffer;
|
||||
|
||||
typedef struct {
|
||||
void* map;
|
||||
bi_u64 map_size;
|
||||
bi_u64 descriptor_size;
|
||||
bi_u32 map_key;
|
||||
bi_u32 descriptor_version;
|
||||
} BI_MemoryMap;
|
||||
BIUInt64 mapSize;
|
||||
BIUInt64 descriptorSize;
|
||||
BIUInt32 mapKey;
|
||||
BIUInt32 descriptorVersion;
|
||||
} BIMemoryMap;
|
||||
|
||||
typedef struct {
|
||||
void* addr;
|
||||
bi_u64 size;
|
||||
} BI_Initramfs;
|
||||
void* address;
|
||||
BIUInt64 size;
|
||||
} BIInitramfs;
|
||||
|
||||
typedef struct {
|
||||
bi_u64 magic;
|
||||
BI_Framebuffer framebuffer;
|
||||
BI_MemoryMap mem;
|
||||
BI_Initramfs initramfs;
|
||||
BIUInt64 magic;
|
||||
BIFramebuffer framebuffer;
|
||||
BIMemoryMap memoryMap;
|
||||
BIInitramfs initramfs;
|
||||
} Bootinfo;
|
||||
|
||||
#define BOOTINFO_MAGIC 0x7465726D // term
|
||||
+19
-19
@@ -1,23 +1,23 @@
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef unsigned char UInt8;
|
||||
typedef unsigned short UInt16;
|
||||
typedef unsigned int UInt32;
|
||||
typedef unsigned long long UInt64;
|
||||
|
||||
#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 HOTSegment {
|
||||
UInt64 type; // 1 = rx 2 = rw
|
||||
UInt64 vaddr;
|
||||
UInt64 offset;
|
||||
UInt64 filesz;
|
||||
UInt64 memsz;
|
||||
} HOTSegment;
|
||||
|
||||
typedef struct hot_header {
|
||||
u32 magic; // "HOT!"
|
||||
u8 version; // 1
|
||||
u8 reserved_pad[3];
|
||||
u64 entry_point;
|
||||
u64 segments_count;
|
||||
u64 reserved;
|
||||
} hot_header;
|
||||
typedef struct HOTHeader {
|
||||
UInt32 magic; // "HOT!"
|
||||
UInt8 version; // 1
|
||||
UInt8 reserved_pad[3];
|
||||
UInt64 entry_point;
|
||||
UInt64 segments_count;
|
||||
UInt64 reserved;
|
||||
} HOTHeader;
|
||||
|
||||
@@ -18,14 +18,16 @@ file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
|
||||
"src/arch/${ARCH}/*.c"
|
||||
"src/arch/${ARCH}/*.asm"
|
||||
|
||||
"src/core/*.c"
|
||||
"src/drivers/*.c"
|
||||
"src/mm/*.c"
|
||||
"src/OS/*.c"
|
||||
"src/OS/Exec/*.c"
|
||||
"src/OS/Services/*.c"
|
||||
"src/lib/*.c"
|
||||
"src/IO/*.c"
|
||||
"src/VM/*.c"
|
||||
"src/shell/*.c"
|
||||
"src/fs/*.c"
|
||||
"src/syscalls/*.c"
|
||||
"src/FS/*.c"
|
||||
|
||||
"data/*.c"
|
||||
"Data/*.c"
|
||||
)
|
||||
|
||||
add_executable(kernel ${KERNEL_SOURCES})
|
||||
@@ -34,7 +36,7 @@ target_include_directories(kernel PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../common"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/inc/arch/${ARCH}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/data"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Data"
|
||||
)
|
||||
|
||||
target_compile_options(kernel PRIVATE
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// font8x16 bitmap font
|
||||
// Source: https://github.com/hubenchang0515/font8x16
|
||||
// License: MIT
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
unsigned char font8x16[][16] = {
|
||||
|
||||
unsigned char VGAFont[][16] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, //0x00,
|
||||
{ 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x01,
|
||||
{ 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, }, //0x02,
|
||||
@@ -3,12 +3,12 @@
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <drivers/shitgui.h>
|
||||
#include <IO/IOGraphics.h>
|
||||
|
||||
#define LOGO_TRANSPARENCY_KEY 0xFF00FF
|
||||
|
||||
// Image: 100x100
|
||||
static const u32 logo_data[] = {
|
||||
static const UInt32 logo_data[] = {
|
||||
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
|
||||
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
|
||||
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
|
||||
@@ -1261,8 +1261,7 @@ static const u32 logo_data[] = {
|
||||
0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF,
|
||||
};
|
||||
|
||||
static SG_Image logo_img = {
|
||||
.width = 100,
|
||||
.height = 100,
|
||||
.buffer = (u32*)logo_data
|
||||
static IOGraphicsImage logoImage = {
|
||||
.size = {100, 100},
|
||||
.buffer = (UInt32*)logo_data
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
#include <FS/VFS.h>
|
||||
|
||||
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize);
|
||||
@@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef enum FSVNodeFlags {
|
||||
kFSVNodeFlagFile = 0x01,
|
||||
kFSVNodeFlagDirectory = 0x02,
|
||||
} FSVNodeFlags;
|
||||
|
||||
typedef struct FSVNode FSVNode;
|
||||
|
||||
typedef struct FSVNodeOperations {
|
||||
UInt64 (*read)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||
UInt64 (*write)(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||
void (*open)(FSVNode* node);
|
||||
void (*close)(FSVNode* node);
|
||||
FSVNode* (*findDirectory)(FSVNode* node, char* name);
|
||||
} FSVNodeOperations;
|
||||
|
||||
typedef struct FSVNode {
|
||||
char name[256];
|
||||
UInt32 protectionMask;
|
||||
UInt32 ownerIdentifier;
|
||||
UInt32 groupIdentifier;
|
||||
UInt32 flags;
|
||||
UInt32 inodeIdentifier;
|
||||
UInt64 dataLength;
|
||||
|
||||
FSVNodeOperations* operations;
|
||||
void* implementationData;
|
||||
|
||||
struct FSVNode* mountPoint;
|
||||
struct FSVNode* childNode;
|
||||
struct FSVNode* nextNode;
|
||||
} FSVNode;
|
||||
|
||||
void FSVirtualFileSystemInitialize(FSVNode* rootNode);
|
||||
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer);
|
||||
FSVNode* FSVirtualFileSystemOpenPath(const char* path);
|
||||
void FSVNodeClose(FSVNode* node);
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <IO/IOGraphics.h>
|
||||
|
||||
enum {
|
||||
kIOConsoleColorRed = 0xFF5555,
|
||||
kIOConsoleColorVeryRed = 0xFF0000,
|
||||
kIOConsoleColorGreen = 0x08bf39,
|
||||
kIOConsoleColorVeryGreen = 0x00FF00,
|
||||
kIOConsoleColorTurqoise = 0x5effaf,
|
||||
kIOConsoleColorBlue = 0x5555FF,
|
||||
kIOConsoleColorVeryBlue = 0x0000FF,
|
||||
kIOConsoleColorLightBlue = 0x3890e8,
|
||||
kIOConsoleColorYellow = 0xFFFF55,
|
||||
kIOConsoleColorCyan = 0x55FFFF,
|
||||
kIOConsoleColorMagneta = 0xFF55FF,
|
||||
kIOConsoleColorBlack = 0x000000,
|
||||
kIOConsoleColorWhite = 0xFFFFFF,
|
||||
kIOConsoleColorPink = 0xFFA3B1,
|
||||
};
|
||||
|
||||
void IOConsoleInit(IOGraphicsContext* context);
|
||||
UInt64 IOConsoleGetColors();
|
||||
void IOConsoleClear(IOGraphicsColor color);
|
||||
IOGraphicsContext* IOConsoleGetGraphicsContext();
|
||||
IOGraphicsSize IOConsoleGetDimensions();
|
||||
void IOConsoleSetForegroundColor(IOGraphicsColor color);
|
||||
void IOConsoleSetDefaultForegroundColor(UInt32 color);
|
||||
void IOConsoleSetCursorPosition(IOGraphicsPoint* point);
|
||||
char IOConsoleGetCharacter();
|
||||
void IOConsoleReadLine(char* buffer, UInt32 limit);
|
||||
void IOConsolePutcharacter(char character);
|
||||
void IOConsolePrint(const char *string);
|
||||
void IOConsoleLog(const char *fmt, ...);
|
||||
@@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
// RIP shitgui -- you started it all
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef UInt32 IOGraphicsColor;
|
||||
|
||||
typedef struct {
|
||||
UInt32 x;
|
||||
UInt32 y;
|
||||
} IOGraphicsPoint;
|
||||
|
||||
typedef struct {
|
||||
UInt32 width;
|
||||
UInt32 height;
|
||||
} IOGraphicsSize;
|
||||
|
||||
typedef struct {
|
||||
volatile UInt32* framebuffer;
|
||||
IOGraphicsSize dimensions;
|
||||
UInt32 pixelsPerScanLine;
|
||||
} IOGraphicsContext;
|
||||
|
||||
typedef struct {
|
||||
IOGraphicsColor* buffer;
|
||||
IOGraphicsSize size;
|
||||
} IOGraphicsImage;
|
||||
|
||||
typedef struct {
|
||||
IOGraphicsSize size;
|
||||
const unsigned char* baseAddress;
|
||||
} IOGraphicsFont;
|
||||
|
||||
|
||||
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point);
|
||||
|
||||
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image);
|
||||
|
||||
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point,
|
||||
IOGraphicsSize* size, IOGraphicsColor color);
|
||||
|
||||
void IOGraphicsDrawCharacter(
|
||||
IOGraphicsContext* context,
|
||||
IOGraphicsPoint* point,
|
||||
char character,
|
||||
IOGraphicsColor color,
|
||||
IOGraphicsFont* font
|
||||
);
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
enum {
|
||||
kIOKeyboardBufferSize = 256,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char buffer[kIOKeyboardBufferSize];
|
||||
UInt16 head;
|
||||
UInt16 tail;
|
||||
} IOKeyboardBuffer;
|
||||
|
||||
extern IOKeyboardBuffer gIOKeyboardInputBuffer;
|
||||
|
||||
void IOKeyboardInterruptsHandler();
|
||||
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
int IOSerialInit();
|
||||
void IOSerialWriteChar(char character);
|
||||
void IOSerialWrite(const char *string);
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
void IOTimerInitialize(UInt32 freq);
|
||||
UInt64 IOTimerInterruptsHandler(CPURegisters *regs);
|
||||
UInt64 IOTimerGetTicks();
|
||||
@@ -10,15 +10,15 @@
|
||||
|
||||
#define HEADER_MAGIC 0x1CE
|
||||
|
||||
typedef struct block_header {
|
||||
u64 magic;
|
||||
struct block_header* next;
|
||||
struct block_header* prev;
|
||||
u64 size;
|
||||
bool is_free;
|
||||
typedef struct VMHeapBlockHeader {
|
||||
UInt64 magic;
|
||||
struct VMHeapBlockHeader* next;
|
||||
struct VMHeapBlockHeader* previous;
|
||||
UInt64 size;
|
||||
bool isFree;
|
||||
} block_header;
|
||||
|
||||
void heap_init();
|
||||
void* malloc(u64 size);
|
||||
void VMHeapInitialize();
|
||||
void* malloc(UInt64 size);
|
||||
void free(void* ptr);
|
||||
void* realloc(void* ptr, u64 new_size);
|
||||
void* realloc(void* ptr, UInt64 new_size);
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
|
||||
u64 load_hot(process* proc, u8* data);
|
||||
UInt64 HOTLoad(OSProcess* process, UInt8* data);
|
||||
@@ -5,5 +5,5 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
i32 process_spawn(const char* path, const char* name);
|
||||
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName);
|
||||
void init_task_entry();
|
||||
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame);
|
||||
__attribute__((noreturn)) void OSPanic(const char* msg);
|
||||
@@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef enum OSProcessState {
|
||||
kOSProcessStateDead,
|
||||
kOSProcessStateRunning,
|
||||
kOSProcessStateReady,
|
||||
kOSProcessStateBlocked,
|
||||
kOSProcessStateSleeping,
|
||||
} OSProcessState;
|
||||
|
||||
typedef struct OSProcess {
|
||||
UInt64 processId;
|
||||
OSProcessState state;
|
||||
UInt64 physicalPML4;
|
||||
struct OSProcess* parent;
|
||||
char name[32];
|
||||
UInt64 heapStartPointer;
|
||||
UInt64 heapCurrentPointer;
|
||||
} OSProcess;
|
||||
|
||||
typedef struct OSTask {
|
||||
UInt64 stackPointer;
|
||||
struct OSTask* next;
|
||||
UInt32 id;
|
||||
UInt32 sleepTicks;
|
||||
OSProcessState taskState; // reusing process_state cuz wn
|
||||
UInt64 kernelStackTop;
|
||||
OSProcess* process;
|
||||
Int32 waitingForProcess;
|
||||
} OSTask;
|
||||
|
||||
void OSSchedulerInitialize();
|
||||
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer);
|
||||
UInt64 OSSchedulerNext(UInt64 currentStackPointer);
|
||||
void OSSchedulerYield(UInt64 ticks);
|
||||
void OSSchedulerBlock(UInt32 processID);
|
||||
void OSSchedulerWakeup(UInt32 processID);
|
||||
void OSSchedulerTerminate(); // suicide
|
||||
|
||||
extern OSTask* gOSSchedulerCurrentTask;
|
||||
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length);
|
||||
UInt64 OSServiceRead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count);
|
||||
@@ -4,4 +4,4 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u64 sys_mem(u64 size);
|
||||
UInt64 OSServiceMemoryGet(UInt64 size);
|
||||
@@ -0,0 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
Int32 OSServiceProcessExit(Int32 code);
|
||||
Int32 OSServiceProcessSpawn(const char* path);
|
||||
Int32 OSServiceProcessWait(UInt64 pid);
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
enum {
|
||||
kVMKernelHeapStart = 0xFFFFFFFFC0000000,
|
||||
kVMHeapSizePages = 1024
|
||||
};
|
||||
|
||||
#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START)
|
||||
#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START)
|
||||
|
||||
#define HEADER_MAGIC 0x1CE
|
||||
|
||||
typedef struct VMHeapBlockHeader {
|
||||
UInt64 magic;
|
||||
struct VMHeapBlockHeader* next;
|
||||
struct VMHeapBlockHeader* previous;
|
||||
UInt64 size;
|
||||
bool isFree;
|
||||
} VMHeapBlockHeader;
|
||||
|
||||
void VMHeapInitialize();
|
||||
void* malloc(UInt64 size);
|
||||
void free(void* ptr);
|
||||
void* realloc(void* ptr, UInt64 newSize);
|
||||
@@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include "bootinfo.h"
|
||||
#include <types.h>
|
||||
|
||||
#define kVMPageSize 4096
|
||||
#define kVMSafeSpaceStartAddress 0x100000
|
||||
#define kVMBlocksPerByte 8
|
||||
|
||||
#define BITMAP_BYTE_INDEX(address) ((address / kVMPageSize) / kVMBlocksPerByte)
|
||||
#define BITMAP_BIT_OFFSET(address) ((address / kVMPageSize) % kVMBlocksPerByte)
|
||||
#define BITMAP_TEST(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] & (1 << BITMAP_BIT_OFFSET(address)))
|
||||
#define BITMAP_SET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] |= (1 << BITMAP_BIT_OFFSET(address)))
|
||||
#define BITMAP_UNSET(bitmap, address) (bitmap[BITMAP_BYTE_INDEX(address)] &= ~(1 << BITMAP_BIT_OFFSET(address)))
|
||||
|
||||
typedef struct {
|
||||
UInt32 type;
|
||||
UInt32 padding;
|
||||
UInt64 physicalStart;
|
||||
UInt64 virtualStart;
|
||||
UInt64 pageCount;
|
||||
UInt64 attributes;
|
||||
} __attribute__((packed)) OSMemoryDescriptor;
|
||||
|
||||
typedef enum {
|
||||
kOSMemoryTypeReserved,
|
||||
kOSMemoryTypeLoaderCode,
|
||||
kOSMemoryTypeLoaderData,
|
||||
kOSMemoryTypeBootServicesCode,
|
||||
kOSMemoryTypeBootServicesData,
|
||||
kOSMemoryTypeRuntimeServicesCode,
|
||||
kOSMemoryTypeRuntimeServicesData,
|
||||
kOSMemoryTypeConventional,
|
||||
kOSMemoryTypeUnusable,
|
||||
kOSMemoryTypeACPIReclaim,
|
||||
kOSMemoryTypeACPINonVolatile,
|
||||
kOSMemoryTypeMappedIO,
|
||||
kOSMemoryTypeMappedIOPortSpace,
|
||||
kOSMemoryTypePalCode,
|
||||
kOSMemoryTypePersistent,
|
||||
kOSMemoryTypeMax
|
||||
} OSMemoryType;
|
||||
|
||||
UInt64 VMPhysicalMemoryGetTotalMemorySize();
|
||||
void VMPhysicalMemoryInitialize(BIMemoryMap* mmap);
|
||||
void* VMPhysicalMemoryAllocatePage();
|
||||
void VMPhysicalMemoryFreePage(void* addr);
|
||||
@@ -35,9 +35,9 @@
|
||||
#define HHDM_TO_PHYS(virt) ((virt) - HHDM_OFFSET)
|
||||
|
||||
|
||||
void vmm_init(Bootinfo* info);
|
||||
u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags);
|
||||
u64 vmm_create_address_space();
|
||||
u64 vmm_get_current_cr3();
|
||||
void load_cr3(u64 pml4_addr);
|
||||
void vmm_setup_user_stack(u64* pml4_phys);
|
||||
void VMVirtualMemoryInitialize(Bootinfo* info);
|
||||
UInt64* VMVirtualMemoryMapPage(UInt64* PML4, UInt64 physical, UInt64 virtual, UInt64 flags);
|
||||
UInt64 VMVirtualMemoryCreateAddressSpace();
|
||||
UInt64 VMGetCurrentCR3();
|
||||
void VMLoadCR3(UInt64 PML4Address);
|
||||
void VMVirtualMemorySetupUserStack(UInt64* physicalPML4);
|
||||
@@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define kHALGDTEntries 7
|
||||
|
||||
typedef struct {
|
||||
UInt16 limitLow;
|
||||
UInt16 baseLow;
|
||||
UInt8 baseMiddle;
|
||||
UInt8 access;
|
||||
UInt8 granularity;
|
||||
UInt8 baseHigh;
|
||||
} __attribute__((packed)) HALGlobalDescriptorTable;
|
||||
|
||||
|
||||
typedef struct {
|
||||
UInt16 limit;
|
||||
UInt64 base;
|
||||
} __attribute__((packed)) HALGlobalDescriptorTablePointer;
|
||||
|
||||
typedef struct {
|
||||
UInt32 reserved0;
|
||||
UInt64 rsp0;
|
||||
UInt64 rsp1;
|
||||
UInt64 rsp2;
|
||||
UInt64 reserved1;
|
||||
UInt64 ist1;
|
||||
UInt64 ist2;
|
||||
UInt64 ist3;
|
||||
UInt64 ist4;
|
||||
UInt64 ist5;
|
||||
UInt64 ist6;
|
||||
UInt64 ist7;
|
||||
UInt64 reserved2;
|
||||
UInt16 reserved3;
|
||||
UInt16 iomapBase;
|
||||
} __attribute__((packed)) HALTaskStateSegment;
|
||||
|
||||
|
||||
extern HALTaskStateSegment gHALTaskStateSegment;
|
||||
|
||||
void HALGlobalDescriptorTableInitialize();
|
||||
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
UInt16 offsetLow;
|
||||
UInt16 selector;
|
||||
UInt8 ist;
|
||||
UInt8 attributes;
|
||||
UInt16 offsetMid;
|
||||
UInt32 offsetHigh;
|
||||
UInt32 reserved;
|
||||
} __attribute__((packed)) HALInterruptsDescriptorTableEntry;
|
||||
|
||||
typedef struct {
|
||||
UInt16 limit;
|
||||
UInt64 base;
|
||||
} __attribute__((packed)) HALInterruptsDescriptorTablePointer;
|
||||
|
||||
void HALInterruptsDescriptorTableInitialize();
|
||||
@@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
enum {
|
||||
kIOMasterCommand = 0x20,
|
||||
kIOMasterData = 0x21,
|
||||
kIOSlaveCommand = 0xA0,
|
||||
kIOSlaveData = 0xA1,
|
||||
kIOPortWaitAddress = 0x80
|
||||
};
|
||||
|
||||
static inline void IOPortWrite8(UInt16 port, UInt8 val) {
|
||||
__asm__ volatile(
|
||||
"outb %0, %1"
|
||||
:
|
||||
: "a"(val),
|
||||
"Nd"(port) );
|
||||
}
|
||||
|
||||
static inline unsigned char IOPortRead8(UInt16 port) {
|
||||
unsigned char ret;
|
||||
__asm__ volatile(
|
||||
"inb %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(port)
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// sending junk to 0x80 (unused) to skip few tacts
|
||||
// not ideal i know
|
||||
static inline void IOSynchronizeBus() {
|
||||
IOPortWrite8(kIOPortWaitAddress, 0x0);
|
||||
}
|
||||
|
||||
static inline void IOPortWrite8WithWait(UInt16 port, UInt8 val) {
|
||||
IOPortWrite8(port, val);
|
||||
IOSynchronizeBus();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef enum {
|
||||
kCPUFeatureFPU = (1ULL << 0),
|
||||
kCPUFeatureTSC = (1ULL << 1),
|
||||
kCPUFeatureMSR = (1ULL << 2),
|
||||
kCPUFeatureAPIC = (1ULL << 3),
|
||||
kCPUFeatureMTRR = (1ULL << 4),
|
||||
kCPUFeaturePAE = (1ULL << 5),
|
||||
|
||||
kCPUFeatureSSE = (1ULL << 10),
|
||||
kCPUFeatureSSE2 = (1ULL << 11),
|
||||
kCPUFeatureSSE3 = (1ULL << 12),
|
||||
kCPUFeatureSSSE3 = (1ULL << 13),
|
||||
kCPUFeatureSSE4_1 = (1ULL << 14),
|
||||
kCPUFeatureSSE4_2 = (1ULL << 15),
|
||||
|
||||
kCPUFeatureAVX = (1ULL << 20),
|
||||
kCPUFeatureF16C = (1ULL << 21),
|
||||
kCPUFeatureRDRAND = (1ULL << 22),
|
||||
|
||||
kCPUFeatureHypervisor = (1ULL << 30)
|
||||
} OSCPUFeature;
|
||||
|
||||
typedef struct {
|
||||
UInt64 userStackPointer;
|
||||
UInt64 kernelStackPointer;
|
||||
UInt64 selfAddress;
|
||||
|
||||
UInt64 features;
|
||||
char vendorID[13];
|
||||
UInt32 family;
|
||||
UInt32 model;
|
||||
} OSCPUData;
|
||||
|
||||
extern OSCPUData gOSBootCPU;
|
||||
|
||||
void OSCPUInitialize(UInt64 kernelStackTop);
|
||||
Boolean OSCPUHasFeature(OSCPUFeature feature);
|
||||
@@ -3,4 +3,4 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u16 pic_remap();
|
||||
UInt16 HALLegacyInterruptControllerRemap();
|
||||
@@ -1,40 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define CPU_FEAT_FPU (1ULL << 0)
|
||||
#define CPU_FEAT_TSC (1ULL << 1)
|
||||
#define CPU_FEAT_MSR (1ULL << 2)
|
||||
#define CPU_FEAT_APIC (1ULL << 3)
|
||||
#define CPU_FEAT_MTRR (1ULL << 4)
|
||||
#define CPU_FEAT_PAE (1ULL << 5)
|
||||
|
||||
#define CPU_FEAT_SSE (1ULL << 10)
|
||||
#define CPU_FEAT_SSE2 (1ULL << 11)
|
||||
#define CPU_FEAT_SSE3 (1ULL << 12)
|
||||
#define CPU_FEAT_SSSE3 (1ULL << 13)
|
||||
#define CPU_FEAT_SSE4_1 (1ULL << 14)
|
||||
#define CPU_FEAT_SSE4_2 (1ULL << 15)
|
||||
|
||||
#define CPU_FEAT_AVX (1ULL << 20)
|
||||
#define CPU_FEAT_F16C (1ULL << 21)
|
||||
#define CPU_FEAT_RDRAND (1ULL << 22)
|
||||
|
||||
#define CPU_FEAT_HYPERVISOR (1ULL << 30)
|
||||
|
||||
typedef struct {
|
||||
u64 user_rsp;
|
||||
u64 kernel_rsp;
|
||||
u64 self;
|
||||
|
||||
u64 features;
|
||||
char vendor[13];
|
||||
u32 family;
|
||||
u32 model;
|
||||
} cpu_info;
|
||||
|
||||
extern cpu_info g_cpu;
|
||||
|
||||
void cpuinfo_init(u64 kernel_stack_top);
|
||||
bool cpu_has(u64 feature);
|
||||
@@ -1,42 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
u16 limit_low;
|
||||
u16 base_low;
|
||||
u8 base_middle;
|
||||
u8 access;
|
||||
u8 granularity;
|
||||
u8 base_high;
|
||||
} __attribute__((packed)) GDTDescriptor;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u16 limit;
|
||||
u64 base;
|
||||
} __attribute__((packed)) GDTPtr;
|
||||
|
||||
typedef struct {
|
||||
u32 reserved0;
|
||||
u64 rsp0;
|
||||
u64 rsp1;
|
||||
u64 rsp2;
|
||||
u64 reserved1;
|
||||
u64 ist1;
|
||||
u64 ist2;
|
||||
u64 ist3;
|
||||
u64 ist4;
|
||||
u64 ist5;
|
||||
u64 ist6;
|
||||
u64 ist7;
|
||||
u64 reserved2;
|
||||
u16 reserved3;
|
||||
u16 iomap_base;
|
||||
} __attribute__((packed)) TSS;
|
||||
|
||||
extern TSS tss;
|
||||
|
||||
void gdt_init();
|
||||
@@ -1,22 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
u16 offset_low;
|
||||
u16 selector;
|
||||
u8 ist;
|
||||
u8 attributes;
|
||||
u16 offset_mid;
|
||||
u32 offset_high;
|
||||
u32 reserved;
|
||||
} __attribute__((packed)) IDTEntry;
|
||||
|
||||
typedef struct {
|
||||
u16 limit;
|
||||
u64 base;
|
||||
} __attribute__((packed)) IDTPtr;
|
||||
|
||||
void idt_init();
|
||||
@@ -1,39 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MASTER_COMMAND 0x20
|
||||
#define MASTER_DATA 0x21
|
||||
#define SLAVE_COMMAND 0xA0
|
||||
#define SLAVE_DATA 0xA1
|
||||
|
||||
static inline void outb(unsigned short port, unsigned char val) {
|
||||
__asm__ volatile(
|
||||
"outb %0, %1"
|
||||
:
|
||||
: "a"(val),
|
||||
"Nd"(port) );
|
||||
}
|
||||
|
||||
static inline unsigned char inb(unsigned short port) {
|
||||
unsigned char ret;
|
||||
__asm__ volatile(
|
||||
"inb %1, %0"
|
||||
: "=a"(ret)
|
||||
: "Nd"(port)
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// sending junk to 0x80 (unused) to skip few tacts
|
||||
// not ideal i know
|
||||
static inline void io_wait() {
|
||||
outb(0x80, 0x0);
|
||||
}
|
||||
|
||||
static inline void outb_wait(unsigned short port, unsigned char val) {
|
||||
outb(port, val);
|
||||
io_wait();
|
||||
}
|
||||
@@ -3,14 +3,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MSR_EFER 0xC0000080
|
||||
#define MSR_STAR 0xC0000081
|
||||
#define MSR_LSTAR 0xC0000082
|
||||
#define MSR_FMASK 0xC0000084
|
||||
#define MSR_GS_BASE 0xC0000101
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
enum {
|
||||
kHALModelSpecificRegisterExtendedFeatureEnable = 0xC0000080, // EFER
|
||||
kHALModelSpecificRegisterSystemCallTarget = 0xC0000081, // STAR
|
||||
kHALModelSpecificRegisterLongSystemCallTarget = 0xC0000082, // LSTAR
|
||||
kHALModelSpecificRegisterSystemCallFlagMask = 0xC0000084, // FMASK
|
||||
kHALModelSpecificRegisterGSBase = 0xC0000101, // GS_BASE
|
||||
kHALModelSpecificRegisterKernelGSBase = 0xC0000102 // KERNEL_GS_BASE
|
||||
};
|
||||
|
||||
#define EFER_SCE 0x01 // System Call Enable
|
||||
enum {
|
||||
kHALEFERSystemCallExtensionsEnable = 0x01 // SCE
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SYS_EXIT,
|
||||
@@ -19,6 +23,6 @@ typedef enum {
|
||||
SYS_WRITE,
|
||||
SYS_READ,
|
||||
SYS_WAIT,
|
||||
} syscalls;
|
||||
} Services;
|
||||
|
||||
void syscall_init();
|
||||
void OSServicesInitialize();
|
||||
@@ -1,10 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
__attribute__((noreturn)) void panic_exception(Registers *regs);
|
||||
__attribute__((noreturn)) void panic(const char* msg);
|
||||
|
||||
extern const char* exception_messages[];
|
||||
@@ -1,42 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef enum process_state {
|
||||
DEAD,
|
||||
RUNNING,
|
||||
READY,
|
||||
BLOCKED,
|
||||
SLEEPING,
|
||||
} process_state;
|
||||
|
||||
typedef struct process {
|
||||
u64 pid;
|
||||
process_state state;
|
||||
u64 pml4_phys;
|
||||
struct process* parent;
|
||||
char name[32];
|
||||
u64 heap_start;
|
||||
u64 heap_cur;
|
||||
} process;
|
||||
|
||||
typedef struct task {
|
||||
u64 rsp;
|
||||
struct task* next;
|
||||
u32 id;
|
||||
u32 sleep_ticks;
|
||||
process_state task_state; // reusing process_state cuz wn
|
||||
u64 kernel_stack_top;
|
||||
process* proc;
|
||||
i32 waiting_on_pid;
|
||||
} task;
|
||||
|
||||
void sched_init();
|
||||
task* sched_spawn(void(*entry)(), process* owner, bool is_user, u64 fixed_user_stack);
|
||||
u64 sched_next(u64 curr_rsp);
|
||||
void yield(u64 ticks);
|
||||
void sched_block(u32 pid);
|
||||
void sched_wakeup(u32 pid);
|
||||
void sched_exit(); // suicide
|
||||
@@ -1,10 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
i32 strcmp(const char* s1, const char* s2);
|
||||
i32 strncmp(const char* s1, const char* s2, u64 n);
|
||||
char* strcpy(char* dest, const char* src);
|
||||
char* strncpy(char* dest, const char* src, u64 n);
|
||||
@@ -1,22 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <drivers/shitgui.h>
|
||||
|
||||
void console_init(SG_Context *ctx);
|
||||
u64 console_get_colors();
|
||||
void console_clear(u32 color);
|
||||
SG_Context* console_get_context();
|
||||
SG_Point console_get_dimensions();
|
||||
void console_set_color(u32 color);
|
||||
void console_set_default_color(u32 color);
|
||||
void console_set_cursor_pos(SG_Point *p);
|
||||
char console_getc();
|
||||
void console_putc(char c);
|
||||
void kprint(const char *str);
|
||||
void kprintf(const char *fmt, ...);
|
||||
void kgets(char* buff, u32 lim);
|
||||
void cursor_blink();
|
||||
void cursor_blinker_sched_task();
|
||||
void console_toggle_cursor_blink();
|
||||
@@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
extern u8 font8x16[128][16];
|
||||
@@ -1,16 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define KB_BUFF_SIZE 256
|
||||
typedef struct {
|
||||
char buffer[KB_BUFF_SIZE];
|
||||
u16 head;
|
||||
u16 tail;
|
||||
} kb_buffer;
|
||||
|
||||
extern kb_buffer kb_buf;
|
||||
|
||||
void kb_handler();
|
||||
@@ -1,8 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
int serial_init();
|
||||
void serial_writec(char chr);
|
||||
void serial_write(const char *str);
|
||||
@@ -1,33 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
typedef struct {
|
||||
volatile u32 *fb;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 pitch;
|
||||
} SG_Context;
|
||||
typedef struct {
|
||||
u32 x;
|
||||
u32 y;
|
||||
} SG_Point;
|
||||
typedef struct {
|
||||
u32 *buffer;
|
||||
u32 height;
|
||||
u32 width;
|
||||
} SG_Image;
|
||||
|
||||
typedef struct {
|
||||
u32 w;
|
||||
u32 h;
|
||||
const unsigned char* base;
|
||||
} SG_Font;
|
||||
|
||||
void sg_init(SG_Context *ctx);
|
||||
u32 sg_get_pixel(SG_Context *ctx, SG_Point *p);
|
||||
void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img);
|
||||
void sg_draw_rect(SG_Context *ctx, SG_Point *p, u32 w, u32 h, u32 color);
|
||||
void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font);
|
||||
@@ -1,10 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
void timer_init(u32 freq);
|
||||
u64 timer_handler(Registers *regs);
|
||||
void sleep(u64 ms);
|
||||
u64 get_uptime();
|
||||
@@ -1,8 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
#include <fs/vfs.h>
|
||||
|
||||
u64 cpio_read(fs_node* node, u64 offset, u64 size, u8* buff);
|
||||
fs_node* cpio_mount(void* base, u64 size);
|
||||
@@ -1,38 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
#define FS_FILE 0x01
|
||||
#define FS_DIR 0x02
|
||||
|
||||
struct fs_node;
|
||||
typedef struct fs_node fs_node;
|
||||
|
||||
typedef struct {
|
||||
u64 (*read)(struct fs_node* node, u64 offset, u64 size, u8* buff);
|
||||
u64 (*write)(struct fs_node* node, u64 offset, u64 size, u8* buff);
|
||||
void (*open)(struct fs_node* node);
|
||||
void (*close)(struct fs_node* node);
|
||||
|
||||
struct fs_node* (*finddir)(struct fs_node* node, char* name);
|
||||
} fs_ops;
|
||||
|
||||
struct fs_node {
|
||||
char name[256];
|
||||
u32 mask;
|
||||
u32 uid;
|
||||
u32 gid;
|
||||
u32 flags;
|
||||
u32 inode;
|
||||
u64 len;
|
||||
fs_ops* ops;
|
||||
void* impl_data;
|
||||
struct fs_node* ptr;
|
||||
struct fs_node* next;
|
||||
};
|
||||
|
||||
void vfs_init(fs_node* root_node);
|
||||
u64 vfs_read(fs_node* node, u64 offset, u64 size, u8* buff);
|
||||
fs_node* vfs_open(const char* path);
|
||||
void vfs_close(fs_node* node);
|
||||
@@ -13,7 +13,7 @@ static inline int abs(int n) {
|
||||
return (n < 0) ? -n : n;
|
||||
}
|
||||
|
||||
static inline i64 i64abs(i64 n) {
|
||||
static inline Int64 i64abs(Int64 n) {
|
||||
return (n < 0) ? -n : n;
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
void rng_init();
|
||||
u64 krand();
|
||||
void RandInitialize();
|
||||
UInt64 Rand();
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <drivers/shitgui.h>
|
||||
#include <IO/IOGraphics.h>
|
||||
|
||||
void show_splash(SG_Context *sg_ctx);
|
||||
void SplashShow(IOGraphicsContext* IOGraphicsContextPointer);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
Int32 strcmp(const char* s1, const char* s2);
|
||||
Int32 strncmp(const char* s1, const char* s2, UInt64 n);
|
||||
char* strcpy(char* dest, const char* src);
|
||||
char* strncpy(char* dest, const char* src, UInt64 n);
|
||||
void *memset(void *ptr, int value, Size num);
|
||||
void* memcpy(void* dest, const void* src, UInt64 n);
|
||||
@@ -1,8 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
void* memset(void* ptr, int value, usize num);
|
||||
void* memcpy(void* dest, const void* src, u64 n);
|
||||
@@ -1,22 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include "bootinfo.h"
|
||||
#include <types.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define BLOCKS_PER_BYTE 8
|
||||
|
||||
#define SAFE_SPACE_START_ADDR 0x100000
|
||||
|
||||
#define BITMAP_BYTE_INDEX(addr) ((addr / PAGE_SIZE) / BLOCKS_PER_BYTE)
|
||||
#define BITMAP_BIT_OFFSET(addr) ((addr / PAGE_SIZE) % BLOCKS_PER_BYTE)
|
||||
#define BITMAP_TEST(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] & (1 << BITMAP_BIT_OFFSET(addr)))
|
||||
#define BITMAP_SET(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] |= (1 << BITMAP_BIT_OFFSET(addr)))
|
||||
#define BITMAP_UNSET(bitmap, addr) (bitmap[BITMAP_BYTE_INDEX(addr)] &= ~(1 << BITMAP_BIT_OFFSET(addr)))
|
||||
|
||||
u64 pmm_get_total_mem();
|
||||
void pmm_init(BI_MemoryMap* mmap);
|
||||
void* pmm_alloc_page();
|
||||
void pmm_free_page(void* addr);
|
||||
@@ -3,13 +3,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
void cmd_kfetch();
|
||||
void cmd_meow();
|
||||
void cmd_help();
|
||||
void cmd_regs();
|
||||
void print_regs();
|
||||
void cmd_sleep();
|
||||
void cmd_debug();
|
||||
void cmd_rand();
|
||||
void cmd_ver();
|
||||
void cmd_userspace();
|
||||
void KSHCommandKernelFetch();
|
||||
void KSHCommandMeow();
|
||||
void KSHCommandHelp();
|
||||
void KSHCommandRegisters();
|
||||
void KSHCommandSleep();
|
||||
void KSHCommandDebug();
|
||||
void KSHCommandRand();
|
||||
void KSHCommandVer();
|
||||
@@ -4,4 +4,4 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u64 debug();
|
||||
UInt64 KSHDebug();
|
||||
|
||||
@@ -2,6 +2,5 @@
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <drivers/shitgui.h>
|
||||
|
||||
void ksh();
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
u64 sys_write(u64 fd, u64 buff, u64 len);
|
||||
u64 sys_read(u64 fd, u64 buff, u64 count);
|
||||
@@ -1,10 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
i32 sys_exit(i32 code);
|
||||
i32 sys_spawn(const char* path);
|
||||
i32 sys_wait(u64 pid);
|
||||
+15
-46
@@ -3,55 +3,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef unsigned char UInt8;
|
||||
typedef unsigned short UInt16;
|
||||
typedef unsigned int UInt32;
|
||||
typedef unsigned long long UInt64;
|
||||
|
||||
typedef signed char i8;
|
||||
typedef signed short i16;
|
||||
typedef signed int i32;
|
||||
typedef signed long long i64;
|
||||
typedef signed char Int8;
|
||||
typedef signed short Int16;
|
||||
typedef signed int Int32;
|
||||
typedef signed long long Int64;
|
||||
|
||||
typedef u64 usize;
|
||||
typedef u64 uintptr_t;
|
||||
typedef UInt64 Size;
|
||||
typedef UInt64 uintptr_t;
|
||||
|
||||
typedef struct {
|
||||
u64 rax, rbx, rcx, rdx, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; // Pushed by us
|
||||
u64 int_no, err_code; // Pushed by macro
|
||||
u64 rip, cs, rflags, rsp, ss; // Pushed by CPU
|
||||
} Registers;
|
||||
UInt64 rax, rbx, rcx, rdx, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; // Pushed by us
|
||||
UInt64 interruptNumber, errorCode; // Pushed by macro
|
||||
UInt64 rip, cs, rflags, rsp, ss; // Pushed by CPU
|
||||
} CPURegisters;
|
||||
|
||||
typedef struct {
|
||||
u32 type;
|
||||
u32 pad;
|
||||
u64 physical_start;
|
||||
u64 virtual_start;
|
||||
u64 number_of_pages;
|
||||
u64 attribute;
|
||||
} __attribute__((packed)) efi_memory_descriptor_k;
|
||||
|
||||
typedef enum {
|
||||
EfiReservedMemoryType,
|
||||
EfiLoaderCode,
|
||||
EfiLoaderData,
|
||||
EfiBootServicesCode,
|
||||
EfiBootServicesData,
|
||||
EfiRuntimeServicesCode,
|
||||
EfiRuntimeServicesData,
|
||||
EfiConventionalMemory,
|
||||
EfiUnusableMemory,
|
||||
EfiACPIReclaimMemory,
|
||||
EfiACPIMemoryNVS,
|
||||
EfiMemoryMappedIO,
|
||||
EfiMemoryMappedIOPortSpace,
|
||||
EfiPalCode,
|
||||
EfiPersistentMemory,
|
||||
EfiMaxMemoryType
|
||||
} EFI_MEMORY_TYPE;
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
#define Boolean _Bool
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <types.h>
|
||||
#include <FS/CPIO.h>
|
||||
#include <FS/VFS.h>
|
||||
#include <lib/String.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <VM/Heap.h>
|
||||
#include <IO/IOConsole.h>
|
||||
|
||||
#define FSCPIO_ALIGN4(x) (((x) + 3) & ~3)
|
||||
|
||||
typedef struct FSCPIOHeader {
|
||||
char magic[6];
|
||||
char inode[8];
|
||||
char mode[8];
|
||||
char userIdentifier[8];
|
||||
char groupIdentifier[8];
|
||||
char linkCount[8];
|
||||
char modificationTime[8];
|
||||
char fileLength[8];
|
||||
char deviceMajor[8];
|
||||
char deviceMinor[8];
|
||||
char remoteDeviceMajor[8];
|
||||
char remoteDeviceMinor[8];
|
||||
char nameLength[8];
|
||||
char checkSum[8];
|
||||
} FSCPIOHeader;
|
||||
|
||||
static FSVNodeOperations gFSCPIOOperations = {
|
||||
.read = FSCPIORead,
|
||||
.write = nullptr,
|
||||
.open = nullptr,
|
||||
.close = nullptr,
|
||||
};
|
||||
|
||||
static UInt64 sFSCPIOHexadecimalToUInt64(const char* string, Int32 length) {
|
||||
UInt64 result = 0;
|
||||
for (Int32 i = 0; i < length; i++) {
|
||||
char character = string[i];
|
||||
result <<= 4;
|
||||
if (character >= '0' && character <= '9') result += (character - '0');
|
||||
else if (character >= 'A' && character <= 'F') result += (character - 'A' + 10);
|
||||
else if (character >= 'a' && character <= 'f') result += (character - 'a' + 10);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UInt64 FSCPIORead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
|
||||
if (offset > node->dataLength) return 0;
|
||||
if ((offset + size) > node->dataLength) size = node->dataLength - offset;
|
||||
|
||||
memcpy(buffer, (char*)node->implementationData + offset, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize) {
|
||||
UInt8* currentPointer = (UInt8*)baseAddress;
|
||||
UInt8* endPointer = currentPointer + totalSize;
|
||||
|
||||
FSVNode* rootNode = (FSVNode*)malloc(sizeof(FSVNode));
|
||||
if (!rootNode) OSPanic("CPIO: Failed to allocate memory for root node");
|
||||
|
||||
memset(rootNode, 0, sizeof(FSVNode));
|
||||
strcpy(rootNode->name, "/");
|
||||
rootNode->flags = kFSVNodeFlagDirectory;
|
||||
rootNode->operations = &gFSCPIOOperations;
|
||||
|
||||
FSVNode* tailNode = nullptr;
|
||||
|
||||
while (currentPointer < endPointer) {
|
||||
FSCPIOHeader* header = (FSCPIOHeader*)currentPointer;
|
||||
|
||||
if (strncmp(header->magic, "070701", 6) != 0) {
|
||||
OSPanic("CPIO: Invalid magic detected in initramfs");
|
||||
}
|
||||
|
||||
UInt64 nameSize = sFSCPIOHexadecimalToUInt64(header->nameLength, 8);
|
||||
UInt64 fileSize = sFSCPIOHexadecimalToUInt64(header->fileLength, 8);
|
||||
|
||||
char* fileName = (char*)(currentPointer + sizeof(FSCPIOHeader));
|
||||
if (strcmp(fileName, "TRAILER!!!") == 0) break;
|
||||
|
||||
UInt64 headerAndNameLength = sizeof(FSCPIOHeader) + nameSize;
|
||||
UInt64 offsetToData = FSCPIO_ALIGN4(headerAndNameLength);
|
||||
void* fileContent = (void*)(currentPointer + offsetToData);
|
||||
|
||||
FSVNode* newNode = (FSVNode*)malloc(sizeof(FSVNode));
|
||||
if (!newNode) OSPanic("CPIO: Failed to allocate memory for new node");
|
||||
|
||||
memset(newNode, 0, sizeof(FSVNode));
|
||||
strncpy(newNode->name, fileName, sizeof(newNode->name) - 1);
|
||||
|
||||
newNode->dataLength = fileSize;
|
||||
newNode->inodeIdentifier = sFSCPIOHexadecimalToUInt64(header->inode, 8);
|
||||
newNode->operations = &gFSCPIOOperations;
|
||||
newNode->implementationData = fileContent;
|
||||
|
||||
UInt64 mode = sFSCPIOHexadecimalToUInt64(header->mode, 8);
|
||||
if ((mode & 0xF000) == 0x4000) {
|
||||
newNode->flags = kFSVNodeFlagDirectory;
|
||||
} else {
|
||||
newNode->flags = kFSVNodeFlagFile;
|
||||
}
|
||||
|
||||
if (rootNode->childNode == nullptr) {
|
||||
rootNode->childNode = newNode;
|
||||
} else if (tailNode) {
|
||||
tailNode->nextNode = newNode;
|
||||
}
|
||||
|
||||
tailNode = newNode;
|
||||
|
||||
IOConsoleLog("^bCPIO^!: Found object '^y%s^!' (size: ^y%d^!) at ^y0x%x^!\n", fileName, fileSize, fileContent);
|
||||
|
||||
UInt64 dataLengthAligned = FSCPIO_ALIGN4(fileSize);
|
||||
currentPointer += offsetToData + dataLengthAligned;
|
||||
}
|
||||
|
||||
return rootNode;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <FS/VFS.h>
|
||||
#include <lib/String.h>
|
||||
|
||||
FSVNode* gFSVirtualFileSystemRoot = nullptr;
|
||||
|
||||
void FSVirtualFileSystemInitialize(FSVNode* rootNode) {
|
||||
gFSVirtualFileSystemRoot = rootNode;
|
||||
}
|
||||
|
||||
UInt64 FSVNodeRead(FSVNode* node, UInt64 offset, UInt64 size, UInt8* buffer) {
|
||||
if (!node || !node->operations || !node->operations->read) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return node->operations->read(node, offset, size, buffer);
|
||||
}
|
||||
|
||||
FSVNode* FSVirtualFileSystemOpenPath(const char* path) {
|
||||
if (!gFSVirtualFileSystemRoot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (strcmp(path, "/") == 0) {
|
||||
return gFSVirtualFileSystemRoot;
|
||||
}
|
||||
|
||||
const char* searchName = path;
|
||||
if (path[0] == '/') {
|
||||
searchName++;
|
||||
}
|
||||
|
||||
FSVNode* nodeIterator = gFSVirtualFileSystemRoot->childNode;
|
||||
while (nodeIterator != nullptr) {
|
||||
if (strcmp(nodeIterator->name, searchName) == 0) {
|
||||
if (nodeIterator->operations && nodeIterator->operations->open) {
|
||||
nodeIterator->operations->open(nodeIterator);
|
||||
}
|
||||
return nodeIterator;
|
||||
}
|
||||
nodeIterator = nodeIterator->nextNode;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FSVNodeClose(FSVNode* node) {
|
||||
if (node && node->operations && node->operations->close) {
|
||||
node->operations->close(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <IO/IOConsole.h>
|
||||
#include <IO/IOSerial.h>
|
||||
#include <IO/IOGraphics.h>
|
||||
#include <IO/IOKeyboard.h>
|
||||
|
||||
#include <lib/Math.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <Data/VGAFont.h>
|
||||
|
||||
static IOGraphicsContext* sIOGraphicsContextPointer = nullptr;
|
||||
static IOGraphicsPoint sIOConsoleCursorPosition = {0};
|
||||
static IOGraphicsFont sIOConsoleFont = {0};
|
||||
static IOGraphicsColor sIOConsoleForegroundColor = kIOConsoleColorWhite;
|
||||
static IOGraphicsColor sIOConsoleDefaultForegroundColor = kIOConsoleColorWhite;
|
||||
static IOGraphicsColor sIOConsoleBackgroundColor = kIOConsoleColorBlack;
|
||||
|
||||
void IOConsoleInit(IOGraphicsContext *context) {
|
||||
sIOGraphicsContextPointer = context;
|
||||
sIOConsoleCursorPosition.x = 0;
|
||||
sIOConsoleCursorPosition.y = 0;
|
||||
|
||||
sIOConsoleFont.size.height = 16;
|
||||
sIOConsoleFont.size.width = 8;
|
||||
sIOConsoleFont.baseAddress = (const unsigned char*)VGAFont;
|
||||
}
|
||||
|
||||
UInt64 IOConsoleGetColors() {
|
||||
return ((UInt64) sIOConsoleForegroundColor << 32) | sIOConsoleBackgroundColor;
|
||||
}
|
||||
|
||||
void IOConsoleClear(IOGraphicsColor color) {
|
||||
if (!sIOGraphicsContextPointer) return;
|
||||
|
||||
IOGraphicsPoint point = {0, 0};
|
||||
IOGraphicsDrawRectangle(
|
||||
sIOGraphicsContextPointer,
|
||||
&point,
|
||||
&sIOGraphicsContextPointer->dimensions,
|
||||
color
|
||||
);
|
||||
|
||||
sIOConsoleCursorPosition.x = 0;
|
||||
sIOConsoleCursorPosition.y = 0;
|
||||
sIOConsoleBackgroundColor = color;
|
||||
}
|
||||
|
||||
IOGraphicsContext* IOConsoleGetGraphicsContext() {
|
||||
return sIOGraphicsContextPointer;
|
||||
}
|
||||
|
||||
IOGraphicsSize IOConsoleGetDimensions() {
|
||||
return sIOGraphicsContextPointer->dimensions;
|
||||
}
|
||||
|
||||
void IOConsoleSetCursorPosition(IOGraphicsPoint* point) {
|
||||
if (!point) return;
|
||||
sIOConsoleCursorPosition.x = point->x;
|
||||
sIOConsoleCursorPosition.y = point->y;
|
||||
}
|
||||
|
||||
void IOConsolePutcharacter(char character) {
|
||||
IOSerialWriteChar(character);
|
||||
if (!sIOGraphicsContextPointer) return;
|
||||
if (character == '\n') {
|
||||
sIOConsoleCursorPosition.x = 0;
|
||||
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
|
||||
} else if (character == '\t') {
|
||||
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width * 4;
|
||||
} else if (character == '\b') {
|
||||
sIOConsoleCursorPosition.x -= sIOConsoleFont.size.width;
|
||||
IOGraphicsDrawRectangle(
|
||||
sIOGraphicsContextPointer,
|
||||
&sIOConsoleCursorPosition,
|
||||
&sIOConsoleFont.size,
|
||||
sIOConsoleBackgroundColor
|
||||
);
|
||||
} else {
|
||||
IOGraphicsDrawCharacter(
|
||||
sIOGraphicsContextPointer,
|
||||
&sIOConsoleCursorPosition,
|
||||
character,
|
||||
sIOConsoleForegroundColor,
|
||||
&sIOConsoleFont
|
||||
);
|
||||
sIOConsoleCursorPosition.x += sIOConsoleFont.size.width;
|
||||
}
|
||||
|
||||
if (sIOConsoleCursorPosition.x >= sIOGraphicsContextPointer->dimensions.width) {
|
||||
sIOConsoleCursorPosition.x = 0;
|
||||
sIOConsoleCursorPosition.y += sIOConsoleFont.size.height;
|
||||
}
|
||||
if (sIOConsoleCursorPosition.y >= sIOGraphicsContextPointer->dimensions.height) {
|
||||
IOConsoleClear(sIOConsoleBackgroundColor); // TODO: do scrolling
|
||||
}
|
||||
}
|
||||
|
||||
void IOConsolePrint(const char *string) {
|
||||
for (Int32 i = 0; string[i] != '\0'; i++) IOConsolePutcharacter(string[i]);
|
||||
}
|
||||
|
||||
static void sIOConsolePrintDecimal(const Int64 number) {
|
||||
if (number < 0) IOConsolePutcharacter('-');
|
||||
UInt64 unsignedNumber = abs(number);
|
||||
char buffer[32];
|
||||
Int32 i = 0;
|
||||
|
||||
do {
|
||||
buffer[i] = (unsignedNumber % 10) + '0';
|
||||
unsignedNumber /= 10;
|
||||
i++;
|
||||
} while (unsignedNumber > 0);
|
||||
|
||||
while (--i >= 0) {
|
||||
IOConsolePutcharacter(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void sIOConsolePrintHexadecimal(UInt64 unsignedNumber, UInt8 padding) {
|
||||
IOConsolePutcharacter('0');
|
||||
IOConsolePutcharacter('x');
|
||||
|
||||
if (unsignedNumber == 0) {
|
||||
IOConsolePutcharacter('0');
|
||||
for (Int32 i = 1; i < padding; i++) IOConsolePutcharacter('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[16] = {0};
|
||||
Int32 i = 0;
|
||||
|
||||
do {
|
||||
Int32 digit = unsignedNumber % 16;
|
||||
if (digit < 10) buffer[i++] = digit + '0';
|
||||
else buffer[i++] = digit - 10 + 'A';
|
||||
unsignedNumber /= 16;
|
||||
} while (unsignedNumber > 0);
|
||||
|
||||
while(i < padding) {
|
||||
IOConsolePutcharacter('0');
|
||||
padding--;
|
||||
}
|
||||
|
||||
while (--i >= 0) {
|
||||
IOConsolePutcharacter(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IOConsoleLog(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
for (Int32 i = 0; fmt[i] != '\0'; i++) {
|
||||
if (fmt[i] == '%') {
|
||||
i++;
|
||||
switch (fmt[i]) {
|
||||
case 's': {
|
||||
const char *string = va_arg(args, const char*);
|
||||
if (!string) string = "undefined";
|
||||
IOConsolePrint(string);
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
char character = (char)va_arg(args, int);
|
||||
IOConsolePutcharacter(character);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
Int32 number = va_arg(args, Int32);
|
||||
sIOConsolePrintDecimal(number);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
UInt64 number = va_arg(args, UInt64);
|
||||
sIOConsolePrintHexadecimal(number, 0);
|
||||
break;
|
||||
}
|
||||
case 'X' : {
|
||||
UInt64 number = va_arg(args, UInt64);
|
||||
sIOConsolePrintHexadecimal(number, 16);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
IOConsolePutcharacter(fmt[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (fmt[i] == '^') {
|
||||
i++;
|
||||
switch (fmt[i]) {
|
||||
case 'r': IOConsoleSetForegroundColor(kIOConsoleColorRed); break;
|
||||
case 'R': IOConsoleSetForegroundColor(kIOConsoleColorVeryRed); break;
|
||||
case 'g': IOConsoleSetForegroundColor(kIOConsoleColorGreen); break;
|
||||
case 'G': IOConsoleSetForegroundColor(kIOConsoleColorVeryGreen); break;
|
||||
case 't': IOConsoleSetForegroundColor(kIOConsoleColorTurqoise); break;
|
||||
case 'b': IOConsoleSetForegroundColor(kIOConsoleColorBlue); break;
|
||||
case 'B': IOConsoleSetForegroundColor(kIOConsoleColorVeryBlue); break;
|
||||
case 'l': IOConsoleSetForegroundColor(kIOConsoleColorLightBlue); break;
|
||||
case 'y': IOConsoleSetForegroundColor(kIOConsoleColorYellow); break;
|
||||
case 'c': IOConsoleSetForegroundColor(kIOConsoleColorCyan); break;
|
||||
case 'm': IOConsoleSetForegroundColor(kIOConsoleColorMagneta); break;
|
||||
case 'p': IOConsoleSetForegroundColor(kIOConsoleColorPink); break;
|
||||
case '0': IOConsoleSetForegroundColor(kIOConsoleColorBlack); break;
|
||||
case 'w': IOConsoleSetForegroundColor(kIOConsoleColorWhite); break;
|
||||
|
||||
case '!': IOConsoleSetForegroundColor(sIOConsoleDefaultForegroundColor); break;
|
||||
case '~': IOConsoleSetForegroundColor(~sIOConsoleBackgroundColor); break;
|
||||
|
||||
case '^': IOConsolePutcharacter('^'); break;
|
||||
|
||||
default: {
|
||||
IOConsolePutcharacter('^');
|
||||
IOConsolePutcharacter(fmt[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IOConsolePutcharacter(fmt[i]);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void IOConsoleSetForegroundColor(UInt32 color) {
|
||||
sIOConsoleForegroundColor = color;
|
||||
}
|
||||
|
||||
void IOConsoleSetDefaultForegroundColor(UInt32 color) {
|
||||
sIOConsoleDefaultForegroundColor = color;
|
||||
}
|
||||
|
||||
char IOConsoleGetCharacter() {
|
||||
while (gIOKeyboardInputBuffer.head == gIOKeyboardInputBuffer.tail) { __asm__ volatile ("sti"); OSSchedulerYield(1); }
|
||||
__asm__ volatile ("cli");
|
||||
char temp = gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.tail];
|
||||
gIOKeyboardInputBuffer.tail = (gIOKeyboardInputBuffer.tail + 1) % kIOKeyboardBufferSize;
|
||||
__asm__ volatile ("sti");
|
||||
return temp;
|
||||
}
|
||||
|
||||
void IOConsoleReadLine(char* buffer, UInt32 limit) {
|
||||
UInt32 i = 0;
|
||||
while (true) {
|
||||
char character = IOConsoleGetCharacter();
|
||||
switch (character) {
|
||||
case '\n': {
|
||||
buffer[i] = '\0';
|
||||
IOConsoleLog("\n");
|
||||
return;
|
||||
}
|
||||
case '\b': {
|
||||
if (i > 0) {
|
||||
i--;
|
||||
IOConsoleLog("\b \b");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (i < limit - 1) {
|
||||
buffer[i] = character;
|
||||
IOConsoleLog("%c", character);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
// RIP shitgui -- you started it all
|
||||
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <IO/IOGraphics.h>
|
||||
#include <VM/Heap.h>
|
||||
#include <lib/String.h>
|
||||
|
||||
enum {
|
||||
kIOGraphicsTransparencyKey = 0xFF00FF
|
||||
};
|
||||
|
||||
UInt32 IOGraphicsGetPixel(IOGraphicsContext* context, IOGraphicsPoint* point) {
|
||||
if (!context->framebuffer || !point || point->x >= context->dimensions.width || point->y >= context->dimensions.height) return 0;
|
||||
return context->framebuffer[point->y * context->pixelsPerScanLine + point->x];
|
||||
}
|
||||
|
||||
void IOGraphicsDrawImage(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsImage* image) {
|
||||
if (!context->framebuffer || !image) return;
|
||||
|
||||
UInt32 startX = point->x;
|
||||
UInt32 startY = point->y;
|
||||
UInt32 drawW = image->size.width;
|
||||
UInt32 drawH = image->size.height;
|
||||
|
||||
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
|
||||
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
|
||||
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
|
||||
|
||||
for (UInt32 y = 0; y < drawH; y++) {
|
||||
volatile UInt32 *destinationPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
|
||||
UInt32 *sourcePointer = &image->buffer[y * image->size.width];
|
||||
for (UInt32 x = 0; x < drawW; x++) {
|
||||
UInt32 color = sourcePointer[x];
|
||||
if (color != kIOGraphicsTransparencyKey) destinationPointer[x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IOGraphicsDrawRectangle(IOGraphicsContext* context, IOGraphicsPoint* point, IOGraphicsSize* size, IOGraphicsColor color) {
|
||||
if (!context->framebuffer) return;
|
||||
|
||||
UInt32 startX = point->x;
|
||||
UInt32 startY = point->y;
|
||||
UInt32 drawW = size->width;
|
||||
UInt32 drawH = size->height;
|
||||
|
||||
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
|
||||
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
|
||||
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
|
||||
|
||||
|
||||
for (UInt32 y = 0; y < drawH; y++) {
|
||||
volatile UInt32* rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
|
||||
for (UInt32 x = 0; x < drawW; x++) rowPointer[x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void IOGraphicsDrawCharacter(IOGraphicsContext* context, IOGraphicsPoint* point, char c, IOGraphicsColor color, IOGraphicsFont* font) {
|
||||
if (!context->framebuffer) return;
|
||||
|
||||
UInt32 startX = point->x;
|
||||
UInt32 startY = point->y;
|
||||
UInt32 drawW = font->size.width;
|
||||
UInt32 drawH = font->size.height;
|
||||
|
||||
if (startX >= context->dimensions.width || startY >= context->dimensions.height) return;
|
||||
if (startX + drawW > context->dimensions.width) drawW = context->dimensions.width - startX;
|
||||
if (startY + drawH > context->dimensions.height) drawH = context->dimensions.height - startY;
|
||||
|
||||
for (UInt32 y = 0; y < drawH; y++) {
|
||||
UInt8 bitmapRow = font->baseAddress[(unsigned char)c * font->size.height + y];
|
||||
volatile UInt32 *rowPointer = &context->framebuffer[(startY + y) * context->pixelsPerScanLine + startX];
|
||||
for (UInt32 x = 0; x < drawW; x++) {
|
||||
if (bitmapRow & (1 << (7 - x))) {
|
||||
rowPointer[x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <drivers/keyboard.h>
|
||||
#include <drivers/console.h>
|
||||
#include <IO/IOKeyboard.h>
|
||||
#include <IO/IOConsole.h>
|
||||
|
||||
#include <io.h>
|
||||
#include <IO.h>
|
||||
#include <types.h>
|
||||
|
||||
unsigned char keyboard_map[128] = {
|
||||
static unsigned char sIOKeyboardMap[128] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 0x00 - 0x09 */
|
||||
'9', '0', '-', '=', '\b', /* Backspace */
|
||||
'\t', /* Tab */
|
||||
@@ -46,7 +46,7 @@ unsigned char keyboard_map[128] = {
|
||||
0, /* All other keys are undefined */
|
||||
};
|
||||
|
||||
unsigned char keyboard_map_shifted[128] = {
|
||||
static unsigned char sIOKeyboardMapShifted[128] = {
|
||||
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 0x00 - 0x09 */
|
||||
'(', ')', '_', '+', '\b', /* Backspace */
|
||||
'\t', /* Tab */
|
||||
@@ -85,29 +85,30 @@ unsigned char keyboard_map_shifted[128] = {
|
||||
0, /* All other keys */
|
||||
};
|
||||
|
||||
bool shift_pressed = false;
|
||||
kb_buffer kb_buf = {0};
|
||||
static Boolean sIOKeyboardIsShiftPressed = false;
|
||||
|
||||
void kb_handler() {
|
||||
u16 next_head = (kb_buf.head + 1) % KB_BUFF_SIZE;
|
||||
IOKeyboardBuffer gIOKeyboardInputBuffer = {0};
|
||||
|
||||
u8 scancode = inb(0x60);
|
||||
void IOKeyboardInterruptsHandler() {
|
||||
UInt16 nextHead = (gIOKeyboardInputBuffer.head + 1) % kIOKeyboardBufferSize;
|
||||
|
||||
UInt8 scancode = IOPortRead8(0x60);
|
||||
// make code 0x00 - 0x7F; break code = make code + 0x80
|
||||
if (scancode < 0x80) {
|
||||
unsigned char* arr = shift_pressed ? keyboard_map_shifted : keyboard_map;
|
||||
char ascii = arr[scancode];
|
||||
if (ascii && next_head != kb_buf.tail) {
|
||||
kb_buf.buffer[kb_buf.head] = ascii;
|
||||
kb_buf.head = next_head;
|
||||
unsigned char* keyMap = sIOKeyboardIsShiftPressed ? sIOKeyboardMapShifted : sIOKeyboardMap;
|
||||
char ascii = keyMap[scancode];
|
||||
if (ascii && nextHead != gIOKeyboardInputBuffer.tail) {
|
||||
gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.head] = ascii;
|
||||
gIOKeyboardInputBuffer.head = nextHead;
|
||||
} else {
|
||||
switch (scancode) {
|
||||
case 0x2A: shift_pressed = true; break;
|
||||
case 0x2A: sIOKeyboardIsShiftPressed = true; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (scancode) {
|
||||
case 0xAA: shift_pressed = false; break;
|
||||
case 0xAA: sIOKeyboardIsShiftPressed = false; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <IO/IOSerial.h>
|
||||
#include <IO.h>
|
||||
|
||||
enum {
|
||||
kIOCom1Port = 0x3F8,
|
||||
};
|
||||
|
||||
int IOSerialInit() {
|
||||
IOPortWrite8(kIOCom1Port + 1, 0x00); // interrupt enable register (+1) / disable interruptions
|
||||
IOPortWrite8(kIOCom1Port + 3, 0x80); // line control register (+3)
|
||||
IOPortWrite8(kIOCom1Port + 0, 0x03); // speed : low byte
|
||||
IOPortWrite8(kIOCom1Port + 1, 0x00); // speed : high byte
|
||||
IOPortWrite8(kIOCom1Port + 3, 0x03); // line control register (+3) / reset DLAB / no parity / 1 stop bit / (8N1)
|
||||
IOPortWrite8(kIOCom1Port + 2, 0xC7); // FIFO Control register (+2) / 1100 0111 / last ones are enable FIFO buff / first ones to clean noise
|
||||
IOPortWrite8(kIOCom1Port + 4, 0x0B); // ready :3
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int IOCheckIsTransmitEmpty() {
|
||||
return IOPortRead8(kIOCom1Port + 5) & 0x20; // checking 5th bit LSR
|
||||
}
|
||||
|
||||
void IOSerialWriteChar(char character) {
|
||||
while (IOCheckIsTransmitEmpty() == 0); // waiting for buffer to flush (spinlock)
|
||||
IOPortWrite8(kIOCom1Port, character);
|
||||
}
|
||||
|
||||
void IOSerialWrite(const char* string) {
|
||||
for (int i = 0; string[i] != '\0'; i++) IOSerialWriteChar(string[i]);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <IO/IOTimer.h>
|
||||
#include <IO.h>
|
||||
#include <types.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
|
||||
enum {
|
||||
kIOTimerPitBaseClock = 1193180,
|
||||
kIOTimerPitCommand = 0x43,
|
||||
kIOTimerPitData = 0x40,
|
||||
};
|
||||
|
||||
static volatile UInt64 sIOTimerTicks = 0;
|
||||
|
||||
void IOTimerInitialize(UInt32 frequency) {
|
||||
UInt32 divisor = kIOTimerPitBaseClock / frequency;
|
||||
|
||||
IOPortWrite8(kIOTimerPitCommand, 0x36); // 0x36 = 00110110 = channel 0, LOHI byte access, Mode 3, binary
|
||||
IOPortWrite8(kIOTimerPitData, divisor & 0xFF);
|
||||
IOPortWrite8(kIOTimerPitData, (divisor >> 8) & 0xFF);
|
||||
|
||||
UInt8 mask = IOPortRead8(0x21);
|
||||
mask &= ~(1 << 0);
|
||||
IOPortWrite8(0x21, mask);
|
||||
}
|
||||
|
||||
UInt64 IOTimerInterruptsHandler(CPURegisters *registers) {
|
||||
sIOTimerTicks++;
|
||||
return OSSchedulerNext((UInt64)registers);
|
||||
}
|
||||
|
||||
UInt64 IOTimerGetTicks() {
|
||||
return sIOTimerTicks;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/Exec/HOTLoader.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <lib/String.h>
|
||||
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <VM/Heap.h>
|
||||
|
||||
#include "../../common/hot_header.h"
|
||||
|
||||
UInt64 HOTLoad(OSProcess* process, UInt8* data) {
|
||||
HOTHeader* header = (HOTHeader*)data;
|
||||
if (header->magic != HOT_MAGIC) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
HOTSegment* segments = (HOTSegment*)(data + sizeof(HOTHeader));
|
||||
for (UInt64 i = 0; i < header->segments_count; i++) {
|
||||
HOTSegment* segment = &segments[i];
|
||||
if (segment->memsz == 0) continue;
|
||||
|
||||
UInt64 start = segment->vaddr & ~(0xFFFULL);
|
||||
UInt64 end = (segment->vaddr + segment->memsz + 0xFFF) & ~(0xFFFULL);
|
||||
|
||||
for (UInt64 address = start; address < end; address += kVMPageSize) {
|
||||
void* physicalPage = VMPhysicalMemoryAllocatePage();
|
||||
VMVirtualMemoryMapPage((UInt64*)process->physicalPML4, (UInt64)physicalPage, address, PTE_USER | PTE_RW | PTE_PRESENT);
|
||||
void* kernelVirtAddress = (void*)((UInt64)physicalPage + HHDM_OFFSET);
|
||||
memset(kernelVirtAddress, 0, kVMPageSize);
|
||||
UInt64 pageOverleapStart = (address > segment->vaddr) ? address : segment->vaddr;
|
||||
UInt64 pageOverleapEnd = (address + kVMPageSize < segment->vaddr + segment->filesz)
|
||||
? (address + kVMPageSize)
|
||||
: (segment->vaddr + segment->filesz);
|
||||
if (pageOverleapStart < pageOverleapEnd) {
|
||||
UInt64 copySize = pageOverleapEnd - pageOverleapStart;
|
||||
UInt64 sourceOffset = segment->offset + (pageOverleapStart - segment->vaddr);
|
||||
UInt64 destinationOffset = pageOverleapStart - address;
|
||||
|
||||
memcpy((UInt8*)kernelVirtAddress + destinationOffset, data + sourceOffset, copySize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return header->entry_point;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/Exec/HOTLoader.h>
|
||||
#include <OS/Exec/OSLoader.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <lib/String.h>
|
||||
|
||||
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <VM/Heap.h>
|
||||
|
||||
#include <FS/VFS.h>
|
||||
|
||||
#include <IO/IOConsole.h>
|
||||
#include <types.h>
|
||||
|
||||
extern UInt32 gOSSchedulerNextProcessID;
|
||||
|
||||
enum {
|
||||
kOSUserStackTop = 0x70000000,
|
||||
kOSHeapStart = 0x40000000
|
||||
};
|
||||
|
||||
|
||||
Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName) {
|
||||
FSVNode* executableFile = FSVirtualFileSystemOpenPath(executablePath);
|
||||
if (!executableFile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
OSProcess* newProcess = (OSProcess*)malloc(sizeof(OSProcess));
|
||||
if (!newProcess) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
memset(newProcess, 0, sizeof(OSProcess));
|
||||
newProcess->processId = gOSSchedulerNextProcessID++;
|
||||
newProcess->state = kOSProcessStateRunning;
|
||||
newProcess->physicalPML4 = VMVirtualMemoryCreateAddressSpace();
|
||||
newProcess->heapStartPointer = kOSHeapStart;
|
||||
newProcess->heapCurrentPointer = kOSHeapStart;
|
||||
strncpy(newProcess->name, processName, 31);
|
||||
|
||||
UInt8* imageBuffer = (UInt8*)malloc(executableFile->dataLength);
|
||||
if (!imageBuffer) {
|
||||
free(newProcess);
|
||||
return -3;
|
||||
}
|
||||
|
||||
FSVNodeRead(executableFile, 0, executableFile->dataLength, imageBuffer);
|
||||
|
||||
UInt64 entryPoint = HOTLoad(newProcess, imageBuffer);
|
||||
if (!entryPoint) {
|
||||
free(imageBuffer);
|
||||
free(newProcess);
|
||||
return -4;
|
||||
}
|
||||
|
||||
free(imageBuffer);
|
||||
|
||||
VMVirtualMemorySetupUserStack((UInt64*)newProcess->physicalPML4);
|
||||
|
||||
OSSchedulerSpawn((void(*)())entryPoint, newProcess, true, kOSUserStackTop);
|
||||
|
||||
return newProcess->processId;
|
||||
}
|
||||
|
||||
void init_task_entry() {
|
||||
Int32 pid = OSLoaderProcessSpawn("/bin/init", "init");
|
||||
if (pid < 0) {
|
||||
OSPanic("FATAL: Failed to spawn /bin/init");
|
||||
}
|
||||
|
||||
while (1) { __asm__("sti; hlt"); }
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <lib/Rand.h>
|
||||
|
||||
#include <IO/IOGraphics.h>
|
||||
#include <IO/IOConsole.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
static const char* sOSPanicFunMessages[] = {
|
||||
"Execution finished abnormally with code: 0x_x",
|
||||
"It's definitely your fault.",
|
||||
"No more Roblox!",
|
||||
"Call your mom 4 help!",
|
||||
"2bad4u",
|
||||
"Touch grass",
|
||||
"Skill issue",
|
||||
"You should just go outside actually",
|
||||
"Perfect opportunity to take a shower",
|
||||
"404 not found",
|
||||
"Windows is locked! Password:___ Time left: 5:45:41",
|
||||
"GOOOOOAL",
|
||||
"\"NAM PIZDA\": hackers dropped our registry",
|
||||
"geeked vs locked in",
|
||||
"HEEEELP!",
|
||||
"LET ME GO!",
|
||||
"You little asshole, make it better",
|
||||
"Go and read books for programming u idiot",
|
||||
"TIME TO BRAKE! :3 Take a tea and try again later cutie",
|
||||
"Code have been eaten by Aliens",
|
||||
"That's all, folks!",
|
||||
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
|
||||
"I'll be back",
|
||||
"Hastla la vista, baby",
|
||||
"Ti chego mne tut nagovoril...",
|
||||
"Your access has been denied because of your region.\n\t\t\t\tPlease, use Chultem VPN and try again later.",
|
||||
"Fatal error has been occurred. \n\t\t\t\tYour device will be transformed into Niva in a few seconds.",
|
||||
"Have you tried turning it off and on again?",
|
||||
"Put it in rice maybe?",
|
||||
"Just hit the monitor, it usually helps",
|
||||
"I think it needs a rest. Come back tomorrow",
|
||||
"You clicked something wrong, didn't you?",
|
||||
"You hacked it too hard, bro",
|
||||
"I think you deleted the internet",
|
||||
"Stop downloading RAM",
|
||||
"Pro tip: dont crash",
|
||||
"Stop ricing the kernel you loonixtard, TermOS is NOT Loonix",
|
||||
"Attaboy, Jack. He's good. Really good.",
|
||||
"Zhenih priehal",
|
||||
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
|
||||
"fuck off",
|
||||
"Your GPU is now mining Ethereum for me. Thanks.",
|
||||
"Your PC is locked!\n\t\t\t\tPay a fee of 0.019082006 bitcoins to a wallet 1KtoProchitalTotSosal to get decryption key!",
|
||||
};
|
||||
|
||||
|
||||
static const char* sOSPanicExceptionMessages[] = {
|
||||
"Division By Zero",
|
||||
"Debug",
|
||||
"Non Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Into Detected Overflow",
|
||||
"Out of Bounds",
|
||||
"Invalid Opcode",
|
||||
"Device Not Available",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Bad TSS",
|
||||
"Segment Not Present",
|
||||
"Stack Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"Reserved",
|
||||
"x87 Floating-Point Exception",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"SIMD Floating-Point Exception",
|
||||
"Virtualization Exception",
|
||||
"Control Protection Exception",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Hypervisor Injection Exception",
|
||||
"VMM Communication Exception",
|
||||
"Security Exception",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
__attribute__((noreturn)) static void die() {
|
||||
while (1) {
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
||||
static void sOSPanicDrawPanicBackground() {
|
||||
IOConsoleClear(0x000000);
|
||||
IOConsoleSetForegroundColor(0xFFFFFF);
|
||||
IOConsoleSetDefaultForegroundColor(0xFFFFFF);
|
||||
|
||||
UInt64 funMessagesCount = sizeof(sOSPanicFunMessages) / sizeof(sOSPanicFunMessages[0]);
|
||||
UInt8 randNum = Rand() % funMessagesCount;
|
||||
|
||||
IOConsoleLog("\n\n");
|
||||
IOConsoleLog("\t\t\t\t^bKERNEL PANIC^! :( \n");
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
IOConsoleLog("\t\t^y%s^!\n", sOSPanicFunMessages[randNum]);
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void OSPanicException(CPURegisters* frame) {
|
||||
sOSPanicDrawPanicBackground();
|
||||
|
||||
IOConsoleLog("\t\t^yCPU EXCEPTION^!: ^b%s^! (%d)\n", sOSPanicExceptionMessages[frame->interruptNumber], frame->interruptNumber);
|
||||
if (frame->errorCode) IOConsoleLog("\t\t^yError Code^!: %X\n", frame->errorCode);
|
||||
IOConsoleLog("\t\t^yInstruction Pointer^! (^yRIP^!): %X\n", frame->rip);
|
||||
IOConsoleLog("\t\t^yCode Segment^! (^yCS^!): %X\n", frame->cs);
|
||||
IOConsoleLog("\t\t^yFlags^! (^yRFLAGS^!): %X\n", frame->rflags);
|
||||
IOConsoleLog("\t\t^yStack Pointer^! (^yRSP^!): %X\n", frame->rsp);
|
||||
if (frame->interruptNumber == 14) {
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
IOConsoleLog("\t\t ^yPage Fault Helper^! \n");
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
UInt64 cr2;
|
||||
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
IOConsoleLog("\t\t^yFaulting Address^! (^yCR2^!): %X\n", cr2);
|
||||
IOConsoleLog("\t\t^yERRCode^!: %X\n", frame->errorCode);
|
||||
UInt64 present = (frame->errorCode & (1 << 0)) != 0;
|
||||
UInt64 write = (frame->errorCode & (1 << 1)) != 0;
|
||||
UInt64 user = (frame->errorCode & (1 << 2)) != 0;
|
||||
UInt64 reserved = (frame->errorCode & (1 << 3)) != 0;
|
||||
UInt64 instruction = (frame->errorCode & (1 << 4)) != 0;
|
||||
IOConsoleLog("\t\t\t[^bP^!] ^yReason^!: %s\n", present ? "Page Protection violation" : "Non-present page");
|
||||
IOConsoleLog("\t\t\t[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
|
||||
IOConsoleLog("\t\t\t[^bU^!] ^yRing^! %s\n", user ? "3" : "0");
|
||||
if (reserved) IOConsoleLog("\t\t\t[^bR^!] CPU Wrote 1 to a reserved field in page table entry. ^rCorrupt page table?^!\n");
|
||||
if (instruction) IOConsoleLog("\t\t\t[^bI^!] ^yTried to^! execute ^ycode from^! NX ^ymemory^!\n");
|
||||
}
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
IOConsoleLog("\t\t\t\t^yREGISTERS^!\n");
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
IOConsoleLog("\t\t^yRAX^!=%X, ^yRBX^!=%X\n", frame->rax, frame->rbx);
|
||||
IOConsoleLog("\t\t^yRCX^!=%X, ^yRDX^!=%X\n", frame->rcx, frame->rdx);
|
||||
IOConsoleLog("\t\t^yRSI^!=%X, ^yRDI^!=%X\n", frame->rsi, frame->rdi);
|
||||
IOConsoleLog("\t\t^yRBP^!=%X, ^yR8^! =%X\n", frame->rbp, frame->r8);
|
||||
IOConsoleLog("\t\t^yR9^! =%X, ^yR10^!=%X \n", frame->r9, frame->r10);
|
||||
IOConsoleLog("\t\t^yR11^!=%X, ^yR12^!=%X\n", frame->r11, frame->r12);
|
||||
IOConsoleLog("\t\t^yR13^!=%X, ^yR14^!=%X\n", frame->r13, frame->r14);
|
||||
IOConsoleLog("\t\t^yR15^!=%X\n",frame->r15);
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void OSPanic(const char* message) {
|
||||
sOSPanicDrawPanicBackground();
|
||||
|
||||
IOConsoleLog("\t\t^yReason^!: %s\n", message);
|
||||
IOConsoleLog("\t\t--------------------------------\n");
|
||||
IOConsoleLog("\t\t\t\t^bSystem halted.^!\n");
|
||||
|
||||
die();
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <lib/String.h>
|
||||
#include <VM/Heap.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <OSCPU.h>
|
||||
#include <GDT.h>
|
||||
|
||||
OSTask* gOSSchedulerCurrentTask = nullptr;
|
||||
UInt32 gOSSchedulerNextProcessID = 1;
|
||||
|
||||
extern void irq0_handler();
|
||||
extern UInt64 gVMKernelPML4Physical;
|
||||
|
||||
static OSProcess sOSSchedulerKernelProcess;
|
||||
|
||||
void idle_task() {
|
||||
while (1) {
|
||||
__asm__ volatile ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void OSSchedulerInitialize() {
|
||||
sOSSchedulerKernelProcess.processId = 0;
|
||||
sOSSchedulerKernelProcess.state = kOSProcessStateRunning;
|
||||
sOSSchedulerKernelProcess.physicalPML4 = gVMKernelPML4Physical;
|
||||
strcpy(sOSSchedulerKernelProcess.name, "kernel");
|
||||
|
||||
OSTask* kernelTask = (OSTask*)malloc(sizeof(OSTask));
|
||||
memset(kernelTask, 0, sizeof(OSTask));
|
||||
kernelTask->id = 0;
|
||||
kernelTask->process = &sOSSchedulerKernelProcess;
|
||||
kernelTask->sleepTicks = 0;
|
||||
kernelTask->next = kernelTask;
|
||||
kernelTask->taskState = kOSProcessStateRunning;
|
||||
kernelTask->waitingForProcess = -1;
|
||||
|
||||
gOSSchedulerCurrentTask = kernelTask;
|
||||
OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0);
|
||||
}
|
||||
|
||||
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) {
|
||||
OSTask* task = (OSTask*)malloc(sizeof(OSTask));
|
||||
if (!task) return nullptr;
|
||||
if (!owner) owner = &sOSSchedulerKernelProcess;
|
||||
|
||||
UInt64 stackSize = 16384;
|
||||
UInt8* stackBaseAddress = (UInt8*)malloc(stackSize);
|
||||
if (!stackBaseAddress) OSPanic("OOM for task stack");
|
||||
UInt64* rsp = (UInt64*)(stackBaseAddress + stackSize);
|
||||
|
||||
UInt64 cs = isUser ? 0x23 : 0x08;
|
||||
UInt64 ss = isUser ? 0x1b : 0x10;
|
||||
UInt64 rflags = 0x202;
|
||||
UInt64 targetStackPointer = 0;
|
||||
if (isUser) targetStackPointer = fixedUserStackPointer;
|
||||
else targetStackPointer = (UInt64)stackBaseAddress + stackSize;
|
||||
|
||||
*--rsp = ss; // SS -- Kernel data
|
||||
*--rsp = targetStackPointer; // rsp
|
||||
*--rsp = rflags; // RFLAGS -- Interrupts Enabled | Reserved bit;
|
||||
*--rsp = cs; // CS -- Kernel Code;
|
||||
*--rsp = (UInt64)entry; // RIP
|
||||
|
||||
*--rsp = 0; // int no
|
||||
*--rsp = 0; // err code
|
||||
|
||||
for (UInt8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
|
||||
|
||||
task->stackPointer = (UInt64)rsp;
|
||||
task->process = owner;
|
||||
task->id = owner->processId;
|
||||
task->sleepTicks = 0;
|
||||
task->next = gOSSchedulerCurrentTask->next;
|
||||
task->kernelStackTop = (UInt64)stackBaseAddress + stackSize;
|
||||
task->taskState = kOSProcessStateRunning;
|
||||
task->waitingForProcess = -1;
|
||||
gOSSchedulerCurrentTask->next = task;
|
||||
return task;
|
||||
}
|
||||
|
||||
UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
|
||||
if (!gOSSchedulerCurrentTask) return currentStackPointer;
|
||||
|
||||
gOSSchedulerCurrentTask->stackPointer = currentStackPointer;
|
||||
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
|
||||
|
||||
do {
|
||||
if (taskIterator->sleepTicks > 0) taskIterator->sleepTicks--;
|
||||
taskIterator = taskIterator->next;
|
||||
} while (taskIterator != gOSSchedulerCurrentTask->next);
|
||||
|
||||
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
|
||||
|
||||
OSTask* nextTask = gOSSchedulerCurrentTask;
|
||||
while (1) {
|
||||
// TODO: add gc here;
|
||||
nextTask = nextTask->next;
|
||||
if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning;
|
||||
if (nextTask->taskState == kOSProcessStateRunning) break;
|
||||
if (nextTask == gOSSchedulerCurrentTask) {
|
||||
if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break;
|
||||
OSPanic("no running tasks");
|
||||
}
|
||||
}
|
||||
|
||||
if (nextTask->process->physicalPML4 != gOSSchedulerCurrentTask->process->physicalPML4) VMLoadCR3(nextTask->process->physicalPML4);
|
||||
gOSSchedulerCurrentTask = nextTask;
|
||||
gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop;
|
||||
gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop;
|
||||
return gOSSchedulerCurrentTask->stackPointer;
|
||||
}
|
||||
|
||||
void OSSchedulerBlock(UInt32 processID) {
|
||||
gOSSchedulerCurrentTask->taskState = kOSProcessStateBlocked;
|
||||
gOSSchedulerCurrentTask->waitingForProcess = processID;
|
||||
__asm__ volatile("int $32");
|
||||
}
|
||||
|
||||
void OSSchedulerWakeup(UInt32 processID) {
|
||||
OSTask* iteratorTask = gOSSchedulerCurrentTask;
|
||||
do {
|
||||
if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) {
|
||||
iteratorTask->taskState = kOSProcessStateRunning;
|
||||
iteratorTask->waitingForProcess = -1;
|
||||
}
|
||||
iteratorTask = iteratorTask->next;
|
||||
} while (iteratorTask != gOSSchedulerCurrentTask);
|
||||
}
|
||||
|
||||
void OSSchedulerTerminate() {
|
||||
UInt32 processID = gOSSchedulerCurrentTask->id;
|
||||
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
|
||||
|
||||
OSSchedulerWakeup(processID);
|
||||
__asm__ volatile("int $32");
|
||||
}
|
||||
|
||||
void OSSchedulerYield(UInt64 ticks) {
|
||||
gOSSchedulerCurrentTask->sleepTicks = ticks;
|
||||
gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping;
|
||||
__asm__ volatile("hlt");
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/Services/OSServiceIO.h>
|
||||
#include <IO/IOConsole.h>
|
||||
|
||||
UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
|
||||
if (fileDescriptor == 1 || fileDescriptor == 2) {
|
||||
char* string = (char*)buffer;
|
||||
for (UInt64 i = 0; i < length; i++) {
|
||||
IOConsolePutcharacter(string[i]);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 OSServiceRead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
|
||||
char* readBuffer = (char*)buffer;
|
||||
if (fileDescriptor == 0) {
|
||||
for (UInt64 i = 0; i < count; i++) {
|
||||
readBuffer[i] = IOConsoleGetCharacter();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/Services/OSServiceMemory.h>
|
||||
|
||||
#include <OS/OSScheduler.h>
|
||||
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <lib/String.h>
|
||||
|
||||
UInt64 OSServiceMemoryGet(UInt64 size) {
|
||||
if (size == 0) return 0;
|
||||
OSProcess* currentProcess = gOSSchedulerCurrentTask->process;
|
||||
UInt64 addressToReturn = currentProcess->heapCurrentPointer;
|
||||
|
||||
UInt64 pages_needed = (size + (kVMPageSize-1)) / kVMPageSize;
|
||||
|
||||
for (UInt64 i = 0; i < pages_needed; i++) {
|
||||
void* phycialAddress = VMPhysicalMemoryAllocatePage();
|
||||
if (!phycialAddress) return 0;
|
||||
|
||||
VMVirtualMemoryMapPage((UInt64*)currentProcess->physicalPML4, (UInt64)phycialAddress, currentProcess->heapCurrentPointer, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
memset((void*)PHYS_TO_HHDM((UInt64)phycialAddress), 0, kVMPageSize);
|
||||
|
||||
currentProcess->heapCurrentPointer += kVMPageSize;
|
||||
}
|
||||
|
||||
return addressToReturn;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <OS/Services/OSServiceProcess.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/Exec/OSLoader.h>
|
||||
#include <IO/IOConsole.h>
|
||||
|
||||
Int32 OSServiceProcessExit(Int32 code) {
|
||||
IOConsoleLog("\n[Dewar] process \"%s\" exited with code %d\n", gOSSchedulerCurrentTask->process->name, code);
|
||||
OSSchedulerTerminate();
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Int32 OSServiceProcessSpawn(const char* path) {
|
||||
return OSLoaderProcessSpawn(path, path);
|
||||
}
|
||||
|
||||
Int32 OSServiceProcessWait(UInt64 processID) {
|
||||
OSSchedulerBlock(processID);
|
||||
return processID;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <VM/Heap.h>
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <lib/String.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <types.h>
|
||||
|
||||
extern UInt64* gVMKernelPML4;
|
||||
static VMHeapBlockHeader* sVMHeapListHead = nullptr;
|
||||
|
||||
void combine_forward(VMHeapBlockHeader* current) {
|
||||
if (!current->next || !current->next->isFree) return;
|
||||
current->size += sizeof(VMHeapBlockHeader) + current->next->size;
|
||||
current->next = current->next->next;
|
||||
if (current->next) current->next->previous = current; // what the fuck
|
||||
}
|
||||
|
||||
void VMHeapInitialize() {
|
||||
UInt64 heapStart = kVMKernelHeapStart;
|
||||
|
||||
for (UInt64 i = 0; i < kVMHeapSizePages; i++) {
|
||||
UInt64 physical = (UInt64)VMPhysicalMemoryAllocatePage();
|
||||
if (!physical) OSPanic("OOM during heap init");
|
||||
|
||||
UInt64 virtual = heapStart + (i * kVMPageSize);
|
||||
VMVirtualMemoryMapPage(gVMKernelPML4, physical, virtual, PTE_PRESENT | PTE_RW);
|
||||
}
|
||||
|
||||
sVMHeapListHead = (VMHeapBlockHeader*)heapStart;
|
||||
sVMHeapListHead->magic = HEADER_MAGIC;
|
||||
sVMHeapListHead->size = (kVMHeapSizePages * kVMPageSize) - sizeof(VMHeapBlockHeader);
|
||||
sVMHeapListHead->isFree = true;
|
||||
sVMHeapListHead->next = nullptr;
|
||||
sVMHeapListHead->previous = nullptr;
|
||||
}
|
||||
|
||||
void* malloc(UInt64 size) {
|
||||
if (size == 0) return nullptr;
|
||||
UInt64 alignedSize = (size + 15) & ~15;
|
||||
|
||||
VMHeapBlockHeader* current = sVMHeapListHead;
|
||||
while (current) {
|
||||
if (current->isFree && current->size >= alignedSize) {
|
||||
if (current->size > alignedSize + sizeof(VMHeapBlockHeader) + 16) {
|
||||
VMHeapBlockHeader* new_block = (VMHeapBlockHeader*)((UInt64)current + sizeof(VMHeapBlockHeader) + alignedSize);
|
||||
new_block->size = current->size - alignedSize - sizeof(VMHeapBlockHeader);
|
||||
new_block->isFree = true;
|
||||
new_block->next = current->next;
|
||||
new_block->previous = current;
|
||||
new_block->magic = HEADER_MAGIC;
|
||||
|
||||
if (current->next) current->next->previous = new_block;
|
||||
current->next = new_block;
|
||||
current->size = alignedSize;
|
||||
}
|
||||
current->isFree = false;
|
||||
return (void*)((UInt64)current + sizeof(VMHeapBlockHeader));
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void free(void* pointer) {
|
||||
if (!pointer) return;
|
||||
|
||||
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
|
||||
if (current->magic != HEADER_MAGIC) return;
|
||||
|
||||
current->isFree = true;
|
||||
if (current->next && current->next->isFree) combine_forward(current);
|
||||
if (current->previous && current->previous->isFree) combine_forward(current->previous);
|
||||
}
|
||||
|
||||
void* realloc(void* pointer, UInt64 newSize) {
|
||||
if (!pointer) return malloc(newSize);
|
||||
if (newSize == 0) {
|
||||
free(pointer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
|
||||
if (current->size >= newSize) return pointer;
|
||||
|
||||
if (current->next &&
|
||||
current->next->isFree &&
|
||||
(current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable
|
||||
combine_forward(current);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
void* newPointer = malloc(newSize);
|
||||
if (!newPointer) return nullptr;
|
||||
|
||||
memcpy(newPointer, pointer, current->size);
|
||||
free(pointer);
|
||||
|
||||
return newPointer;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <lib/String.h>
|
||||
#include <lib/Math.h>
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
#include <types.h>
|
||||
|
||||
#include "bootinfo.h"
|
||||
|
||||
|
||||
UInt8* gVMPhycalMemoryBitmap = nullptr;
|
||||
UInt64 gVMPhycalMemoryBitmapSize = 0;
|
||||
UInt64 gVMPhycalMemoryTotalMemorySize = 0;
|
||||
|
||||
extern UInt64 _kernel_start;
|
||||
extern UInt64 _kernel_end;
|
||||
|
||||
UInt64 VMPhysicalMemoryGetTotalMemorySize() {
|
||||
return gVMPhycalMemoryTotalMemorySize;
|
||||
}
|
||||
|
||||
void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
|
||||
UInt64 descriptorCount = memoryMap->mapSize / memoryMap->descriptorSize;
|
||||
UInt64 maxPhysicalAddress = 0;
|
||||
|
||||
for (UInt64 i = 0; i < descriptorCount; i++) {
|
||||
OSMemoryDescriptor* descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
|
||||
|
||||
if (descriptor->type == kOSMemoryTypeMappedIO ||
|
||||
descriptor->type == kOSMemoryTypeMappedIOPortSpace ||
|
||||
descriptor->type == kOSMemoryTypeUnusable ||
|
||||
descriptor->type == kOSMemoryTypeReserved ||
|
||||
descriptor->type == kOSMemoryTypePalCode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UInt64 nominee = descriptor->physicalStart + (descriptor->pageCount * kVMPageSize);
|
||||
if (nominee > maxPhysicalAddress) {
|
||||
maxPhysicalAddress = nominee;
|
||||
}
|
||||
}
|
||||
gVMPhycalMemoryTotalMemorySize = maxPhysicalAddress;
|
||||
|
||||
UInt64 totalPageCount = maxPhysicalAddress / kVMPageSize;
|
||||
UInt64 bitmapSize = (totalPageCount + 7) / 8;
|
||||
OSMemoryDescriptor *bitmapHostDescriptor = nullptr;
|
||||
|
||||
for (UInt64 i = 0; i < descriptorCount; i++) {
|
||||
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
|
||||
|
||||
if ((descriptor->type == kOSMemoryTypeConventional) &&
|
||||
((descriptor->pageCount * kVMPageSize) >= bitmapSize) &&
|
||||
(descriptor->physicalStart >= kVMSafeSpaceStartAddress)) {
|
||||
bitmapHostDescriptor = descriptor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bitmapHostDescriptor == nullptr) {
|
||||
OSPanic("PMM: Not enough RAM for memory bitmap!");
|
||||
}
|
||||
|
||||
gVMPhycalMemoryBitmap = (UInt8*)bitmapHostDescriptor->physicalStart;
|
||||
gVMPhycalMemoryBitmapSize = bitmapSize;
|
||||
|
||||
memset(gVMPhycalMemoryBitmap, 0xFF, bitmapSize);
|
||||
|
||||
for (UInt64 i = 0; i < descriptorCount; i++) {
|
||||
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
|
||||
|
||||
if (descriptor->type != kOSMemoryTypeConventional) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UInt64 startAddress = descriptor->physicalStart;
|
||||
UInt64 endAddress = startAddress + (descriptor->pageCount * kVMPageSize);
|
||||
|
||||
for (UInt64 addr = startAddress; addr < endAddress; addr += kVMPageSize) {
|
||||
BITMAP_UNSET(gVMPhycalMemoryBitmap, addr);
|
||||
}
|
||||
}
|
||||
|
||||
UInt64 kernelStart = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_start);
|
||||
UInt64 kernelEnd = KERNEL_VIRT_TO_PHYS((UInt64)&_kernel_end);
|
||||
|
||||
UInt64 bitmapStart = (UInt64)gVMPhycalMemoryBitmap;
|
||||
UInt64 bitmapEnd = bitmapStart + gVMPhycalMemoryBitmapSize;
|
||||
|
||||
for (UInt64 addr = 0; addr < kVMSafeSpaceStartAddress; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
|
||||
for (UInt64 addr = kernelStart; addr < kernelEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
|
||||
for (UInt64 addr = bitmapStart; addr < bitmapEnd; addr += kVMPageSize) BITMAP_SET(gVMPhycalMemoryBitmap, addr);
|
||||
}
|
||||
|
||||
void* VMPhysicalMemoryAllocatePage() {
|
||||
for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) {
|
||||
if (gVMPhycalMemoryBitmap[i] == 0xFF) continue;
|
||||
|
||||
for (UInt64 bit = 0; bit < 8; bit++) {
|
||||
if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) {
|
||||
UInt64 address = (i * 8 + bit) * kVMPageSize;
|
||||
BITMAP_SET(gVMPhycalMemoryBitmap, address);
|
||||
return (void*)address;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr; // Out of memory
|
||||
}
|
||||
|
||||
void VMPhysicalMemoryFreePage(void* address) {
|
||||
BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address);
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
#include <VM/VMM.h>
|
||||
#include <VM/PMM.h>
|
||||
|
||||
#include <OS/OSPanic.h>
|
||||
|
||||
#include <GDT.h>
|
||||
#include <IDT.h>
|
||||
|
||||
#include <lib/String.h>
|
||||
|
||||
#include <types.h>
|
||||
#include "bootinfo.h"
|
||||
|
||||
enum {
|
||||
kVMUserStackTop = 0x70000000,
|
||||
kVMUserStackSize = 0x4000
|
||||
};
|
||||
|
||||
UInt64* gVMKernelPML4 = nullptr;
|
||||
UInt64 gVMKernelPML4Physical = 0;
|
||||
static bool isInitialized = false;
|
||||
|
||||
extern UInt64 _kernel_start;
|
||||
extern UInt64 _kernel_end;
|
||||
extern UInt8* gVMPhycalMemoryBitmap;
|
||||
extern UInt64 gVMPhycalMemoryBitmapSize;
|
||||
extern HALGlobalDescriptorTable gHALGlobalDescriptorTable[];
|
||||
extern HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[];
|
||||
extern UInt8 gHALDoubleFaultStack[];
|
||||
extern UInt8 stack_guard;
|
||||
|
||||
static UInt64* sVMGetVirtualTable(UInt64 phys) {
|
||||
if (isInitialized) return (UInt64*)PHYS_TO_HHDM(phys);
|
||||
return (UInt64*)phys;
|
||||
}
|
||||
|
||||
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
|
||||
UInt64 pt_idx = VMM_PT_INDEX(virt);
|
||||
UInt64 pd_idx = VMM_PD_INDEX(virt);
|
||||
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||
|
||||
UInt64* pml4_virt = pml4;
|
||||
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
|
||||
|
||||
UInt64 table_flags = PTE_PRESENT | PTE_RW | (flags & PTE_USER);
|
||||
|
||||
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) {
|
||||
UInt64* addr = VMPhysicalMemoryAllocatePage();
|
||||
if (!addr) return nullptr;
|
||||
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
|
||||
memset(addr_virt, 0, kVMPageSize);
|
||||
pml4_virt[pml4_idx] = (UInt64)addr | table_flags;
|
||||
} else {
|
||||
pml4_virt[pml4_idx] |= (flags & PTE_USER);
|
||||
}
|
||||
|
||||
UInt64* pdpt = (UInt64*)PTE_GET_ADDR(pml4_virt[pml4_idx]);
|
||||
UInt64* pdpt_virt = sVMGetVirtualTable((UInt64)pdpt);
|
||||
|
||||
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) {
|
||||
UInt64* addr = VMPhysicalMemoryAllocatePage();
|
||||
if (!addr) return nullptr;
|
||||
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
|
||||
memset(addr_virt, 0, kVMPageSize);
|
||||
pdpt_virt[pdpt_idx] = (UInt64)addr | table_flags;
|
||||
} else {
|
||||
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
|
||||
}
|
||||
|
||||
UInt64* pd = (UInt64*)PTE_GET_ADDR(pdpt_virt[pdpt_idx]);
|
||||
UInt64* pd_virt = sVMGetVirtualTable((UInt64)pd);
|
||||
|
||||
if (!(pd_virt[pd_idx] & PTE_PRESENT)) {
|
||||
UInt64* addr = VMPhysicalMemoryAllocatePage();
|
||||
if (!addr) return nullptr;
|
||||
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
|
||||
memset(addr_virt, 0, kVMPageSize);
|
||||
pd_virt[pd_idx] = (UInt64)addr | table_flags;
|
||||
} else {
|
||||
pd_virt[pd_idx] |= (flags & PTE_USER);
|
||||
}
|
||||
|
||||
UInt64* pt = (UInt64*)PTE_GET_ADDR(pd_virt[pd_idx]);
|
||||
UInt64* pt_virt = sVMGetVirtualTable((UInt64)pt);
|
||||
pt_virt[pt_idx] = phys | flags;
|
||||
|
||||
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
|
||||
|
||||
return (UInt64*)virt;
|
||||
}
|
||||
|
||||
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
|
||||
UInt64 pt_idx = VMM_PT_INDEX(virt);
|
||||
UInt64 pd_idx = VMM_PD_INDEX(virt);
|
||||
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||
|
||||
UInt64* pml4_virt = pml4;
|
||||
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
|
||||
|
||||
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) return;
|
||||
UInt64* pdpt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pml4_virt[pml4_idx]));
|
||||
|
||||
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) return;
|
||||
UInt64* pd_virt = sVMGetVirtualTable(PTE_GET_ADDR(pdpt_virt[pdpt_idx]));
|
||||
|
||||
if (!(pd_virt[pd_idx] & PTE_PRESENT)) return;
|
||||
UInt64* pt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pd_virt[pd_idx]));
|
||||
|
||||
pt_virt[pt_idx] = 0;
|
||||
|
||||
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
|
||||
}
|
||||
|
||||
void VMLoadCR3(UInt64 pml4_addr) {
|
||||
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
|
||||
}
|
||||
|
||||
void VMVirtualMemoryInitialize(Bootinfo* info) {
|
||||
gVMKernelPML4Physical = (UInt64)VMPhysicalMemoryAllocatePage();
|
||||
gVMKernelPML4 = (UInt64*)gVMKernelPML4Physical;
|
||||
memset(gVMKernelPML4, 0, kVMPageSize);
|
||||
|
||||
UInt64 k_virt_start = (UInt64)&_kernel_start;
|
||||
UInt64 k_virt_end = (UInt64)&_kernel_end;
|
||||
|
||||
UInt64 fb_start = (UInt64)info->framebuffer.base;
|
||||
UInt64 fb_end = fb_start + info->framebuffer.baseSize;
|
||||
UInt64 fb_size = fb_end - fb_start;
|
||||
|
||||
UInt64 max_mem = VMPhysicalMemoryGetTotalMemorySize();
|
||||
for (UInt64 i = 0; i < max_mem; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, i, PHYS_TO_HHDM(i), PTE_PRESENT | PTE_RW);
|
||||
for (UInt64 i = k_virt_start; i < k_virt_end; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, KERNEL_VIRT_TO_PHYS(i), i, PTE_PRESENT | PTE_RW);
|
||||
for (UInt64 i = 0; i < fb_size; i += kVMPageSize) VMVirtualMemoryMapPage(gVMKernelPML4, fb_start + i, FB_VIRT_BASE + i, PTE_PRESENT | PTE_RW);
|
||||
VMVirtualMemoryUnmapPage(gVMKernelPML4, (UInt64)&stack_guard);
|
||||
|
||||
gVMPhycalMemoryBitmap = (UInt8*)PHYS_TO_HHDM((UInt64)gVMPhycalMemoryBitmap);
|
||||
info->framebuffer.base = (UInt32*)FB_VIRT_BASE;
|
||||
VMLoadCR3(gVMKernelPML4Physical);
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
UInt64 VMVirtualMemoryCreateAddressSpace() {
|
||||
UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage();
|
||||
if (!phys) return 0;
|
||||
|
||||
UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys);
|
||||
memset(virt, 0, kVMPageSize);
|
||||
|
||||
UInt64* kernel_pml4_virt = sVMGetVirtualTable((UInt64)gVMKernelPML4);
|
||||
|
||||
for (UInt32 i = 256; i < 512; i++) {
|
||||
virt[i] = kernel_pml4_virt[i];
|
||||
}
|
||||
|
||||
return phys;
|
||||
}
|
||||
|
||||
UInt64 VMGetCurrentCR3() {
|
||||
UInt64 cr3;
|
||||
__asm__ volatile("mov %%cr3, %0" : "=r"(cr3));
|
||||
return cr3;
|
||||
}
|
||||
|
||||
|
||||
void VMVirtualMemorySetupUserStack(UInt64* pml4_phys) {
|
||||
UInt64 stack_bottom = kVMUserStackTop - kVMUserStackSize;
|
||||
for (UInt64 addr = stack_bottom; addr < kVMUserStackTop; addr += 4096) {
|
||||
void* phys = VMPhysicalMemoryAllocatePage();
|
||||
if (!phys) OSPanic("OOM in user stack setup");
|
||||
memset((void*)PHYS_TO_HHDM((UInt64)phys), 0, 4096);
|
||||
VMVirtualMemoryMapPage((UInt64*)pml4_phys, (UInt64)phys, addr, PTE_PRESENT | PTE_RW | PTE_USER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
// just fucking kill me already
|
||||
|
||||
#include <GDT.h>
|
||||
|
||||
HALGlobalDescriptorTable gHALGlobalDescriptorTable[kHALGDTEntries];
|
||||
HALGlobalDescriptorTablePointer gHALGlobalDescriptorTablePointer;
|
||||
HALTaskStateSegment gHALTaskStateSegment;
|
||||
UInt8 gHALDoubleFaultStack[4096] = {0};
|
||||
|
||||
static void sHALGlobalDescriptorTableSetGate(int number, UInt64 base, UInt64 limit, UInt8 access, UInt8 granularity) {
|
||||
gHALGlobalDescriptorTable[number].baseLow = (base & 0xFFFF); // left only low 16bit
|
||||
gHALGlobalDescriptorTable[number].baseMiddle = (base >> 16) & 0xFF; // 3rd address byte
|
||||
gHALGlobalDescriptorTable[number].baseHigh = (base >> 24) & 0xFF; // 4th address byte
|
||||
|
||||
gHALGlobalDescriptorTable[number].limitLow = (limit & 0xFFFF);
|
||||
gHALGlobalDescriptorTable[number].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19)
|
||||
gHALGlobalDescriptorTable[number].granularity |= granularity & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags)
|
||||
gHALGlobalDescriptorTable[number].access = access;
|
||||
|
||||
// fuck intel
|
||||
}
|
||||
|
||||
|
||||
static void sHALTaskStateSegmentWrite(int number) {
|
||||
UInt64 base = (UInt64)&gHALTaskStateSegment;
|
||||
UInt64 limit = sizeof(gHALTaskStateSegment);
|
||||
UInt64 access = 0x89; // TSS_PRESENT | TSS_EXECUTABLE | TSS_ACCESSED;
|
||||
UInt64 granularity = 0;
|
||||
|
||||
sHALGlobalDescriptorTableSetGate(number, base, limit, access, granularity);
|
||||
*((UInt64*)&gHALGlobalDescriptorTable[number+1]) = (base >> 32); // really scary but not really hard
|
||||
// just direct write 8bytes to num+1
|
||||
// basically a hack but at this point i dont care
|
||||
}
|
||||
|
||||
|
||||
extern void gdt_flush(UInt64 gdt_ptr_addr); // entry.asm
|
||||
|
||||
void HALGlobalDescriptorTableInitialize() {
|
||||
gHALGlobalDescriptorTablePointer.limit = (sizeof(HALGlobalDescriptorTable) * kHALGDTEntries) - 1;
|
||||
gHALGlobalDescriptorTablePointer.base = (UInt64)&gHALGlobalDescriptorTable;
|
||||
|
||||
// 0: Null
|
||||
sHALGlobalDescriptorTableSetGate(0, 0, 0, 0, 0);
|
||||
|
||||
// 1: Kernel Code (Ring 0)
|
||||
// Access: 0x9A (Present, Ring0, Exec/Read)
|
||||
// Granularity: 0x20 (Long Mode bit) access ring 0 code exec code readable
|
||||
sHALGlobalDescriptorTableSetGate(1, 0, 0, 0x9A, 0x20); // 0x9A = 1 00 1 1 0 1
|
||||
// 0x20 = 0010 0000 bit 5 is "Long mode"
|
||||
// 2: Kernel Data (Ring 0)
|
||||
// Access: 0x92 (Present, Ring0, Read/Write)
|
||||
sHALGlobalDescriptorTableSetGate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
|
||||
|
||||
// 3: User Data (Ring 3)
|
||||
// Access: 0xF2 (Present, Ring3, Read/Write)
|
||||
sHALGlobalDescriptorTableSetGate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
|
||||
|
||||
// 4: User Code (Ring 3)
|
||||
// Access: 0xFA (Present, Ring3, RWX)
|
||||
sHALGlobalDescriptorTableSetGate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
|
||||
|
||||
for (UInt64 i = 0; i < sizeof(HALTaskStateSegment); i++) ((UInt8*)&gHALTaskStateSegment)[i] = 0; // zeroifying tss struct
|
||||
|
||||
gHALTaskStateSegment.iomapBase = sizeof(HALTaskStateSegment);
|
||||
gHALTaskStateSegment.ist1 = (UInt64)gHALDoubleFaultStack + sizeof(gHALDoubleFaultStack);
|
||||
sHALTaskStateSegmentWrite(5);
|
||||
|
||||
gdt_flush((UInt64)&gHALGlobalDescriptorTablePointer);
|
||||
|
||||
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
|
||||
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <IDT.h>
|
||||
#include <types.h>
|
||||
|
||||
HALInterruptsDescriptorTableEntry gHALInterruptsDescriptorTable[256];
|
||||
HALInterruptsDescriptorTablePointer gHALInterruptsDescriptorTablePointer;
|
||||
|
||||
extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3();
|
||||
extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7();
|
||||
extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11();
|
||||
extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15();
|
||||
extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19();
|
||||
extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23();
|
||||
extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27();
|
||||
extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31();
|
||||
extern void irq0(void); extern void irq1(void);
|
||||
|
||||
extern void idt_load(UInt64); // asm: lidt [rdi] / ret
|
||||
|
||||
static void sHALInterruptsDescriptorTableSetGate(int number, UInt64 handler, UInt16 selector, UInt8 flags) {
|
||||
gHALInterruptsDescriptorTable[number].offsetLow = handler & 0xFFFF;
|
||||
gHALInterruptsDescriptorTable[number].offsetMid = (handler >> 16) & 0xFFFF;
|
||||
gHALInterruptsDescriptorTable[number].offsetHigh = (handler >> 32) & 0xFFFFFFFF;
|
||||
|
||||
gHALInterruptsDescriptorTable[number].selector = selector; // 0x08 (Kernel Code)
|
||||
gHALInterruptsDescriptorTable[number].ist = 0;
|
||||
gHALInterruptsDescriptorTable[number].attributes = flags;
|
||||
gHALInterruptsDescriptorTable[number].reserved = 0;
|
||||
}
|
||||
|
||||
void HALInterruptsDescriptorTableInitialize() {
|
||||
gHALInterruptsDescriptorTablePointer.limit = (sizeof(HALInterruptsDescriptorTableEntry) * 256) - 1;
|
||||
gHALInterruptsDescriptorTablePointer.base = (UInt64)&gHALInterruptsDescriptorTable;
|
||||
|
||||
const UInt8 flags = 0x8E;
|
||||
const UInt8 selector = 0x08;
|
||||
|
||||
|
||||
sHALInterruptsDescriptorTableSetGate(0, (UInt64)isr0, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(1, (UInt64)isr1, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(2, (UInt64)isr2, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(3, (UInt64)isr3, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(4, (UInt64)isr4, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(5, (UInt64)isr5, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(6, (UInt64)isr6, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(7, (UInt64)isr7, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(8, (UInt64)isr8, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(9, (UInt64)isr9, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(10, (UInt64)isr10, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(11, (UInt64)isr11, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(12, (UInt64)isr12, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(13, (UInt64)isr13, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(14, (UInt64)isr14, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(15, (UInt64)isr15, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(16, (UInt64)isr16, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(17, (UInt64)isr17, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(18, (UInt64)isr18, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(19, (UInt64)isr19, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(20, (UInt64)isr20, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(21, (UInt64)isr21, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(22, (UInt64)isr22, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(23, (UInt64)isr23, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(24, (UInt64)isr24, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(25, (UInt64)isr25, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(26, (UInt64)isr26, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(27, (UInt64)isr27, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(28, (UInt64)isr28, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(29, (UInt64)isr29, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(30, (UInt64)isr30, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(31, (UInt64)isr31, selector, flags);
|
||||
|
||||
gHALInterruptsDescriptorTable[8].ist = 1; // TSS
|
||||
gHALInterruptsDescriptorTable[13].ist = 1;
|
||||
gHALInterruptsDescriptorTable[14].ist = 1;
|
||||
|
||||
sHALInterruptsDescriptorTableSetGate(32, (UInt64)irq0, selector, flags);
|
||||
sHALInterruptsDescriptorTableSetGate(33, (UInt64)irq1, selector, flags);
|
||||
|
||||
__asm__ volatile ("lidt %0" : : "m"(gHALInterruptsDescriptorTablePointer));
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <types.h>
|
||||
#include <OSCPU.h>
|
||||
|
||||
#define MSR_GS_BASE 0xC0000101
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
OSCPUData gOSBootCPU = {0};
|
||||
|
||||
static inline void CPUID(UInt32 leaf, UInt32 subleaf, UInt32 *eax, UInt32 *ebx, UInt32 *ecx, UInt32 *edx) {
|
||||
__asm__ volatile("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(leaf), "c"(subleaf)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void WRMSR(UInt32 msr, UInt64 val) {
|
||||
UInt32 low = (UInt32)val;
|
||||
UInt32 high = (UInt32)(val >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
void OSCPUInitialize(UInt64 kernelStackTop) {
|
||||
gOSBootCPU.kernelStackPointer = kernelStackTop;
|
||||
gOSBootCPU.selfAddress = (UInt64)&gOSBootCPU;
|
||||
WRMSR(MSR_KERNEL_GS_BASE, (UInt64)&gOSBootCPU);
|
||||
|
||||
|
||||
UInt32 eax, ebx, ecx, edx;
|
||||
|
||||
CPUID(0, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
UInt32* vendorPointer = (UInt32*)gOSBootCPU.vendorID;
|
||||
vendorPointer[0] = ebx;
|
||||
vendorPointer[1] = edx;
|
||||
vendorPointer[2] = ecx;
|
||||
gOSBootCPU.vendorID[12] = '\0';
|
||||
|
||||
CPUID(1, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
gOSBootCPU.family = (eax >> 8) & 0xF;
|
||||
gOSBootCPU.model = (eax >> 4) & 0xF;
|
||||
if (gOSBootCPU.family == 6 || gOSBootCPU.family == 15) {
|
||||
gOSBootCPU.model += ((eax >> 16) & 0xF) << 4;
|
||||
}
|
||||
|
||||
if (edx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureFPU;
|
||||
if (edx & (1 << 4)) gOSBootCPU.features |= kCPUFeatureTSC;
|
||||
if (edx & (1 << 5)) gOSBootCPU.features |= kCPUFeatureMSR;
|
||||
if (edx & (1 << 6)) gOSBootCPU.features |= kCPUFeaturePAE;
|
||||
if (edx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureAPIC;
|
||||
if (edx & (1 << 12)) gOSBootCPU.features |= kCPUFeatureMTRR;
|
||||
|
||||
if (edx & (1 << 25)) gOSBootCPU.features |= kCPUFeatureSSE;
|
||||
if (edx & (1 << 26)) gOSBootCPU.features |= kCPUFeatureSSE2;
|
||||
if (ecx & (1 << 0)) gOSBootCPU.features |= kCPUFeatureSSE3;
|
||||
if (ecx & (1 << 9)) gOSBootCPU.features |= kCPUFeatureSSSE3;
|
||||
if (ecx & (1 << 19)) gOSBootCPU.features |= kCPUFeatureSSE4_1;
|
||||
if (ecx & (1 << 20)) gOSBootCPU.features |= kCPUFeatureSSE4_2;
|
||||
|
||||
if (ecx & (1 << 28)) gOSBootCPU.features |= kCPUFeatureAVX;
|
||||
if (ecx & (1 << 29)) gOSBootCPU.features |= kCPUFeatureF16C;
|
||||
if (ecx & (1 << 30)) gOSBootCPU.features |= kCPUFeatureRDRAND;
|
||||
|
||||
if (ecx & (1 << 31)) gOSBootCPU.features |= kCPUFeatureHypervisor;
|
||||
}
|
||||
|
||||
Boolean OSCPUHasFeature(OSCPUFeature feature) {
|
||||
return (gOSBootCPU.features & feature) != 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <PIC.h>
|
||||
#include <IO.h>
|
||||
#include <types.h>
|
||||
|
||||
|
||||
UInt16 HALLegacyInterruptControllerRemap() {
|
||||
UInt8 currentMaster = IOPortRead8(kIOMasterData);
|
||||
UInt8 currentSlave = IOPortRead8(kIOSlaveData);
|
||||
|
||||
// initialization; icw1
|
||||
IOPortWrite8WithWait(kIOMasterCommand, 0x11);
|
||||
IOPortWrite8WithWait(kIOSlaveCommand, 0x11);
|
||||
|
||||
// icw2
|
||||
IOPortWrite8WithWait(kIOMasterData, 0x20); // master now controlling idt[32..39]
|
||||
IOPortWrite8WithWait(kIOSlaveData, 0x28); // idt[40..47]
|
||||
|
||||
// icw3
|
||||
IOPortWrite8WithWait(kIOMasterData, 0x04); // slave on irq2
|
||||
IOPortWrite8WithWait(kIOSlaveData, 0x02); // assign id = 2 to slave
|
||||
|
||||
// icw4; 0x01 -- 8086 mode
|
||||
IOPortWrite8WithWait(kIOMasterData, 0x01);
|
||||
IOPortWrite8WithWait(kIOSlaveData, 0x01);
|
||||
|
||||
IOPortWrite8WithWait(kIOMasterData, 0xFD); // 1111 1101
|
||||
// 0 -- means 'on'
|
||||
IOPortWrite8WithWait(kIOSlaveData, 0xFF); // Everything ON
|
||||
|
||||
return ((UInt16) currentMaster << 8) | currentSlave;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <types.h>
|
||||
#include <cpuinfo.h>
|
||||
|
||||
#define MSR_GS_BASE 0xC0000101
|
||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||
|
||||
cpu_info g_cpu = {0};
|
||||
|
||||
static inline void cpuid(u32 leaf, u32 subleaf, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) {
|
||||
__asm__ volatile("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(leaf), "c"(subleaf)
|
||||
);
|
||||
}
|
||||
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
void cpuinfo_init(u64 kernel_stack_top) {
|
||||
g_cpu.kernel_rsp = kernel_stack_top;
|
||||
g_cpu.self = (u64)&g_cpu;
|
||||
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
|
||||
|
||||
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(0, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
u32* vendor_ptr = (u32*)g_cpu.vendor;
|
||||
vendor_ptr[0] = ebx;
|
||||
vendor_ptr[1] = edx;
|
||||
vendor_ptr[2] = ecx;
|
||||
g_cpu.vendor[12] = '\0';
|
||||
|
||||
cpuid(1, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
g_cpu.family = (eax >> 8) & 0xF;
|
||||
g_cpu.model = (eax >> 4) & 0xF;
|
||||
if (g_cpu.family == 6 || g_cpu.family == 15) {
|
||||
g_cpu.model += ((eax >> 16) & 0xF) << 4;
|
||||
}
|
||||
|
||||
if (edx & (1 << 0)) g_cpu.features |= CPU_FEAT_FPU;
|
||||
if (edx & (1 << 4)) g_cpu.features |= CPU_FEAT_TSC;
|
||||
if (edx & (1 << 5)) g_cpu.features |= CPU_FEAT_MSR;
|
||||
if (edx & (1 << 6)) g_cpu.features |= CPU_FEAT_PAE;
|
||||
if (edx & (1 << 9)) g_cpu.features |= CPU_FEAT_APIC;
|
||||
if (edx & (1 << 12)) g_cpu.features |= CPU_FEAT_MTRR;
|
||||
if (edx & (1 << 25)) g_cpu.features |= CPU_FEAT_SSE;
|
||||
if (edx & (1 << 26)) g_cpu.features |= CPU_FEAT_SSE2;
|
||||
|
||||
if (ecx & (1 << 0)) g_cpu.features |= CPU_FEAT_SSE3;
|
||||
if (ecx & (1 << 9)) g_cpu.features |= CPU_FEAT_SSSE3;
|
||||
if (ecx & (1 << 19)) g_cpu.features |= CPU_FEAT_SSE4_1;
|
||||
if (ecx & (1 << 20)) g_cpu.features |= CPU_FEAT_SSE4_2;
|
||||
if (ecx & (1 << 28)) g_cpu.features |= CPU_FEAT_AVX;
|
||||
if (ecx & (1 << 29)) g_cpu.features |= CPU_FEAT_F16C;
|
||||
|
||||
if (ecx & (1 << 30)) g_cpu.features |= CPU_FEAT_RDRAND;
|
||||
|
||||
if (ecx & (1 << 31)) g_cpu.features |= CPU_FEAT_HYPERVISOR;
|
||||
}
|
||||
|
||||
bool cpu_has(u64 feature) {
|
||||
return (g_cpu.features & feature) != 0;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
// just fucking kill me already
|
||||
|
||||
#include <gdt.h>
|
||||
#define GDT_ENTIRES 7
|
||||
|
||||
GDTDescriptor gdt[GDT_ENTIRES];
|
||||
GDTPtr gdt_ptr;
|
||||
TSS tss;
|
||||
u8 double_fault_stack[4096] = {0};
|
||||
|
||||
void gdt_set_gate(int num, u64 base, u64 limit, u8 access, u8 gran) {
|
||||
gdt[num].base_low = (base & 0xFFFF); // left only low 16bit
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF; // 3rd address byte
|
||||
gdt[num].base_high = (base >> 24) & 0xFF; // 4th address byte
|
||||
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = (limit >> 16) & 0x0F; // leave only first 4 bits (limit's left 16-19)
|
||||
gdt[num].granularity |= gran & 0xF0; // get flags and concate two pieces so FFFFLLLL (L -- Limit; F -- flags)
|
||||
gdt[num].access = access;
|
||||
|
||||
// fuck intel
|
||||
}
|
||||
|
||||
|
||||
void write_tss(int num) {
|
||||
u64 base = (u64)&tss;
|
||||
u64 limit = sizeof(tss);
|
||||
u64 access = 0x89; // TSS_PRESENT | TSS_EXECUTABLE | TSS_ACCESSED;
|
||||
u64 gran = 0;
|
||||
|
||||
gdt_set_gate(num, base, limit, access, gran);
|
||||
*((u64*)&gdt[num+1]) = (base >> 32); // really scary but not really hard
|
||||
// just direct write 8bytes to num+1
|
||||
// basically a hack but at this point i dont care
|
||||
}
|
||||
|
||||
|
||||
extern void gdt_flush(u64 gdt_ptr_addr); // entry.asm
|
||||
|
||||
void gdt_init() {
|
||||
gdt_ptr.limit = (sizeof(GDTDescriptor) * GDT_ENTIRES) - 1;
|
||||
gdt_ptr.base = (u64)&gdt;
|
||||
|
||||
// 0: Null
|
||||
gdt_set_gate(0, 0, 0, 0, 0);
|
||||
|
||||
// 1: Kernel Code (Ring 0)
|
||||
// Access: 0x9A (Present, Ring0, Exec/Read)
|
||||
// Granularity: 0x20 (Long Mode bit) access ring 0 code exec code readable
|
||||
gdt_set_gate(1, 0, 0, 0x9A, 0x20); // 0x9A = 1 00 1 1 0 1
|
||||
// 0x20 = 0010 0000 bit 5 is "Long mode"
|
||||
// 2: Kernel Data (Ring 0)
|
||||
// Access: 0x92 (Present, Ring0, Read/Write)
|
||||
gdt_set_gate(2, 0, 0, 0x92, 0); // 0x92 = 1 00 1 0 0 1
|
||||
|
||||
// 3: User Data (Ring 3)
|
||||
// Access: 0xF2 (Present, Ring3, Read/Write)
|
||||
gdt_set_gate(3, 0, 0, 0xF2, 0); // 0xF2 = 1 11 1 0 0 1
|
||||
|
||||
// 4: User Code (Ring 3)
|
||||
// Access: 0xFA (Present, Ring3, RWX)
|
||||
gdt_set_gate(4, 0, 0, 0xFA, 0x20); // 0xFA = 1 11 1 1 0 1
|
||||
|
||||
for (u64 i = 0; i < sizeof(TSS); i++) ((u8*)&tss)[i] = 0; // zeroifying tss struct
|
||||
|
||||
tss.iomap_base = sizeof(TSS);
|
||||
tss.ist1 = (u64)double_fault_stack + sizeof(double_fault_stack);
|
||||
write_tss(5);
|
||||
|
||||
gdt_flush((u64)&gdt_ptr);
|
||||
|
||||
// telling cpu that TSS info located at gdt[5]; offset = 5 * 8 = 40 = 0x28
|
||||
__asm__ volatile ("ltr %%ax" :: "a" (0x28));
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <idt.h>
|
||||
#include <types.h>
|
||||
|
||||
IDTEntry idt[256];
|
||||
IDTPtr idt_ptr;
|
||||
|
||||
extern void isr0(); extern void isr1(); extern void isr2(); extern void isr3();
|
||||
extern void isr4(); extern void isr5(); extern void isr6(); extern void isr7();
|
||||
extern void isr8(); extern void isr9(); extern void isr10(); extern void isr11();
|
||||
extern void isr12(); extern void isr13(); extern void isr14(); extern void isr15();
|
||||
extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19();
|
||||
extern void isr20(); extern void isr21(); extern void isr22(); extern void isr23();
|
||||
extern void isr24(); extern void isr25(); extern void isr26(); extern void isr27();
|
||||
extern void isr28(); extern void isr29(); extern void isr30(); extern void isr31();
|
||||
extern void irq0(void); extern void irq1(void);
|
||||
|
||||
extern void idt_load(u64); // asm: lidt [rdi] / ret
|
||||
|
||||
void idt_set_gate(int num, u64 handler, u16 sel, u8 flags) {
|
||||
idt[num].offset_low = handler & 0xFFFF;
|
||||
idt[num].offset_mid = (handler >> 16) & 0xFFFF;
|
||||
idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF;
|
||||
|
||||
idt[num].selector = sel; // 0x08 (Kernel Code)
|
||||
idt[num].ist = 0;
|
||||
idt[num].attributes = flags;
|
||||
idt[num].reserved = 0;
|
||||
}
|
||||
|
||||
void idt_init() {
|
||||
idt_ptr.limit = (sizeof(IDTEntry) * 256) - 1;
|
||||
idt_ptr.base = (u64)&idt;
|
||||
|
||||
const u8 flags = 0x8E;
|
||||
const u8 selector = 0x08;
|
||||
|
||||
|
||||
idt_set_gate(0, (u64)isr0, selector, flags);
|
||||
idt_set_gate(1, (u64)isr1, selector, flags);
|
||||
idt_set_gate(2, (u64)isr2, selector, flags);
|
||||
idt_set_gate(3, (u64)isr3, selector, flags);
|
||||
idt_set_gate(4, (u64)isr4, selector, flags);
|
||||
idt_set_gate(5, (u64)isr5, selector, flags);
|
||||
idt_set_gate(6, (u64)isr6, selector, flags);
|
||||
idt_set_gate(7, (u64)isr7, selector, flags);
|
||||
idt_set_gate(8, (u64)isr8, selector, flags);
|
||||
idt_set_gate(9, (u64)isr9, selector, flags);
|
||||
idt_set_gate(10, (u64)isr10, selector, flags);
|
||||
idt_set_gate(11, (u64)isr11, selector, flags);
|
||||
idt_set_gate(12, (u64)isr12, selector, flags);
|
||||
idt_set_gate(13, (u64)isr13, selector, flags);
|
||||
idt_set_gate(14, (u64)isr14, selector, flags);
|
||||
idt_set_gate(15, (u64)isr15, selector, flags);
|
||||
idt_set_gate(16, (u64)isr16, selector, flags);
|
||||
idt_set_gate(17, (u64)isr17, selector, flags);
|
||||
idt_set_gate(18, (u64)isr18, selector, flags);
|
||||
idt_set_gate(19, (u64)isr19, selector, flags);
|
||||
idt_set_gate(20, (u64)isr20, selector, flags);
|
||||
idt_set_gate(21, (u64)isr21, selector, flags);
|
||||
idt_set_gate(22, (u64)isr22, selector, flags);
|
||||
idt_set_gate(23, (u64)isr23, selector, flags);
|
||||
idt_set_gate(24, (u64)isr24, selector, flags);
|
||||
idt_set_gate(25, (u64)isr25, selector, flags);
|
||||
idt_set_gate(26, (u64)isr26, selector, flags);
|
||||
idt_set_gate(27, (u64)isr27, selector, flags);
|
||||
idt_set_gate(28, (u64)isr28, selector, flags);
|
||||
idt_set_gate(29, (u64)isr29, selector, flags);
|
||||
idt_set_gate(30, (u64)isr30, selector, flags);
|
||||
idt_set_gate(31, (u64)isr31, selector, flags);
|
||||
|
||||
idt[8].ist = 1; // TSS
|
||||
idt[13].ist = 1;
|
||||
idt[14].ist = 1;
|
||||
|
||||
idt_set_gate(32, (u64)irq0, selector, flags);
|
||||
idt_set_gate(33, (u64)irq1, selector, flags);
|
||||
|
||||
__asm__ volatile ("lidt %0" : : "m"(idt_ptr));
|
||||
}
|
||||
@@ -1,41 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <io.h>
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <drivers/keyboard.h>
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/timer.h>
|
||||
#include <shell/builtins.h>
|
||||
#include <syscalls/proc.h>
|
||||
#include <IO.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <IO/IOKeyboard.h>
|
||||
#include <IO/IOConsole.h>
|
||||
#include <IO/IOTimer.h>
|
||||
#include <OS/Services/OSServiceProcess.h>
|
||||
#include <types.h>
|
||||
|
||||
extern task* curr_task;
|
||||
|
||||
void isr_handler_c(Registers *regs) {
|
||||
if (regs->int_no == 3) {
|
||||
return print_regs();
|
||||
void isr_handler_c(CPURegisters* frame) {
|
||||
if (frame->interruptNumber == 3) {
|
||||
IOConsoleLog("--------------------------------\n");
|
||||
IOConsoleLog("\t\t^gREGISTERS^!\n");
|
||||
IOConsoleLog("--------------------------------\n");
|
||||
IOConsoleLog("^gRAX^!=%X, ^gRBX^!=%X\n", frame->rax, frame->rbx);
|
||||
IOConsoleLog("^gRCX^!=%X, ^gRDX^!=%X\n", frame->rcx, frame->rdx);
|
||||
IOConsoleLog("^gRSI^!=%X, ^gRDI^!=%X\n", frame->rsi, frame->rdi);
|
||||
IOConsoleLog("^gRBP^!=%X, ^gR8^! =%X\n", frame->rbp, frame->r8);
|
||||
IOConsoleLog("^gR9^! =%X, ^gR10^!=%X \n", frame->r9, frame->r10);
|
||||
IOConsoleLog("^gR11^!=%X, ^gR12^!=%X\n", frame->r11, frame->r12);
|
||||
IOConsoleLog("^gR13^!=%X, ^gR14^!=%X\n", frame->r13, frame->r14);
|
||||
IOConsoleLog("^gR15^!=%X\n",frame->r15);
|
||||
IOConsoleLog("--------------------------------\n");
|
||||
}
|
||||
if ((regs->cs & 3) != 0) {
|
||||
kprintf("\n[Dewar] Process '%s' (PID %d) Segmentation Fault at %X\n",
|
||||
curr_task->proc->name, curr_task->proc->pid, regs->rip);
|
||||
curr_task->task_state = DEAD;
|
||||
sys_exit(-1);
|
||||
sched_next((u64)regs);
|
||||
if ((frame->cs & 3) != 0) {
|
||||
IOConsoleLog("\n[Dewar] Process '%s' (PID %d) Segmentation Fault at %X\n",
|
||||
gOSSchedulerCurrentTask->process->name, gOSSchedulerCurrentTask->process->processId, frame->rip);
|
||||
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
|
||||
OSServiceProcessExit(-1);
|
||||
OSSchedulerNext((UInt64)frame);
|
||||
return;
|
||||
}
|
||||
panic_exception(regs);
|
||||
OSPanicException(frame);
|
||||
}
|
||||
|
||||
u64 irq_handler_c(Registers *regs) {
|
||||
u64 curr_rsp = (u64)regs;
|
||||
switch (regs->int_no) {
|
||||
case 32: curr_rsp = timer_handler(regs); break;
|
||||
case 33: kb_handler(); break;
|
||||
UInt64 irq_handler_c(CPURegisters* regs) {
|
||||
UInt64 curr_rsp = (UInt64)regs;
|
||||
switch (regs->interruptNumber) {
|
||||
case 32: curr_rsp = IOTimerInterruptsHandler(regs); break;
|
||||
case 33: IOKeyboardInterruptsHandler(); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
outb(MASTER_COMMAND, 0x20);
|
||||
IOPortWrite8(kIOMasterCommand, 0x20);
|
||||
return curr_rsp;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <pic.h>
|
||||
#include <io.h>
|
||||
#include <types.h>
|
||||
|
||||
|
||||
u16 pic_remap() {
|
||||
u8 curr_master = inb(MASTER_DATA);
|
||||
u8 curr_slave = inb(SLAVE_DATA);
|
||||
|
||||
// initialization; icw1
|
||||
outb_wait(MASTER_COMMAND, 0x11);
|
||||
outb_wait(SLAVE_COMMAND, 0x11);
|
||||
|
||||
// icw2
|
||||
outb_wait(MASTER_DATA, 0x20); // master now controlling idt[32..39]
|
||||
outb_wait(SLAVE_DATA, 0x28); // idt[40..47]
|
||||
|
||||
// icw3
|
||||
outb_wait(MASTER_DATA, 0x04); // slave on irq2
|
||||
outb_wait(SLAVE_DATA, 0x02); // assign id = 2 to slave
|
||||
|
||||
// icw4; 0x01 -- 8086 mode
|
||||
outb_wait(MASTER_DATA, 0x01);
|
||||
outb_wait(SLAVE_DATA, 0x01);
|
||||
|
||||
outb_wait(MASTER_DATA, 0xFD); // 1111 1101
|
||||
// 0 -- means 'on'
|
||||
outb_wait(SLAVE_DATA, 0xFF); // Everything ON
|
||||
|
||||
return ((u16) curr_master << 8) | curr_slave;
|
||||
}
|
||||
@@ -1,66 +1,66 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <cpuinfo.h>
|
||||
#include <OSCPU.h>
|
||||
#include <syscall.h>
|
||||
#include <types.h>
|
||||
#include <drivers/console.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <IO/IOConsole.h>
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
|
||||
#include <syscalls/proc.h>
|
||||
#include <syscalls/mem.h>
|
||||
#include <syscalls/io.h>
|
||||
#include <OS/Services/OSServiceProcess.h>
|
||||
#include <OS/Services/OSServiceMemory.h>
|
||||
#include <OS/Services/OSServiceIO.h>
|
||||
|
||||
static inline void wrmsr(u32 msr, u64 val) {
|
||||
u32 low = (u32)val;
|
||||
u32 high = (u32)(val >> 32);
|
||||
static inline void WRMSR(UInt32 msr, UInt64 value) {
|
||||
UInt32 low = (UInt32)value;
|
||||
UInt32 high = (UInt32)(value >> 32);
|
||||
__asm__ volatile("wrmsr" :: "a"(low), "d"(high), "c"(msr));
|
||||
}
|
||||
|
||||
static inline u64 rdmsr(u32 msr) {
|
||||
u32 low, high;
|
||||
static inline UInt64 RDMSR(UInt32 msr) {
|
||||
UInt32 low, high;
|
||||
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||
return ((u64)high << 32) | low;
|
||||
return ((UInt64)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
|
||||
void OSServicesInitialize() {
|
||||
UInt64 efer = RDMSR(kHALModelSpecificRegisterExtendedFeatureEnable);
|
||||
WRMSR(kHALModelSpecificRegisterExtendedFeatureEnable, efer | 1); // Enabling SCE in EFER. Just enabling 0 bit
|
||||
|
||||
// setting up STAR
|
||||
// 32:47 kernel selector (0x08)
|
||||
// 48:64 user selector (0x01 cuz sysret adds +16 for CS and +8 for SS)
|
||||
u64 star = (0x13ULL << 48) | (0x08ULL << 32);
|
||||
wrmsr(MSR_STAR, star);
|
||||
UInt64 star = (0x13ULL << 48) | (0x08ULL << 32);
|
||||
WRMSR(kHALModelSpecificRegisterSystemCallTarget, star);
|
||||
|
||||
wrmsr(MSR_LSTAR, (u64)syscall_entry); // setting handler adress
|
||||
WRMSR(kHALModelSpecificRegisterLongSystemCallTarget, (UInt64)syscall_entry); // setting handler adress
|
||||
|
||||
// masking flags (IA32_FMASK)
|
||||
// 9 bit for finterrupts in syscall (IF) and few more necessary flags
|
||||
wrmsr(MSR_FMASK, 0x200); // masking only IF
|
||||
WRMSR(kHALModelSpecificRegisterSystemCallFlagMask, 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;
|
||||
if (gOSBootCPU.kernelStackPointer == 0) {
|
||||
void* physicalStackPointer = VMPhysicalMemoryAllocatePage();
|
||||
gOSBootCPU.kernelStackPointer = (UInt64)physicalStackPointer + HHDM_OFFSET + 4096;
|
||||
}
|
||||
|
||||
wrmsr(MSR_GS_BASE, (u64)&g_cpu);
|
||||
wrmsr(MSR_KERNEL_GS_BASE, (u64)&g_cpu);
|
||||
WRMSR(kHALModelSpecificRegisterGSBase, (UInt64)&gOSBootCPU);
|
||||
WRMSR(kHALModelSpecificRegisterKernelGSBase, (UInt64)&gOSBootCPU);
|
||||
}
|
||||
|
||||
u64 syscall_dispatch(u64 id, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5) {
|
||||
UInt64 syscall_dispatch(UInt64 id, UInt64 arg1, UInt64 arg2, UInt64 arg3, UInt64 arg4, UInt64 arg5) {
|
||||
switch (id) {
|
||||
case SYS_EXIT: return sys_exit(arg1);
|
||||
case SYS_SPAWN: return sys_spawn((const char*)arg1);
|
||||
case SYS_MEM: return sys_mem(arg1);
|
||||
case SYS_WRITE: return sys_write(arg1, arg2, arg3);
|
||||
case SYS_READ: return sys_read(arg1, arg2, arg3);
|
||||
case SYS_WAIT: return sys_wait(arg1);
|
||||
case SYS_EXIT: return OSServiceProcessExit(arg1);
|
||||
case SYS_SPAWN: return OSServiceProcessSpawn((const char*)arg1);
|
||||
case SYS_MEM: return OSServiceMemoryGet(arg1);
|
||||
case SYS_WRITE: return OSServiceWrite(arg1, arg2, arg3);
|
||||
case SYS_READ: return OSServiceRead(arg1, arg2, arg3);
|
||||
case SYS_WAIT: return OSServiceProcessWait(arg1);
|
||||
default:
|
||||
kprintf("[Dewar] Unknown syscall %d\n", id);
|
||||
IOConsoleLog("[Dewar] Unknown syscall %d\n", id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
// 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));
|
||||
for (u64 i = 0; i < header->segments_count; i++) {
|
||||
hot_segment* seg = &segments[i];
|
||||
if (seg->memsz == 0) continue;
|
||||
|
||||
u64 start = seg->vaddr & ~(0xFFFULL);
|
||||
u64 end = (seg->vaddr + seg->memsz + 0xFFF) & ~(0xFFFULL);
|
||||
|
||||
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);
|
||||
void* kernel_virt = (void*)((u64)phys + HHDM_OFFSET);
|
||||
memset(kernel_virt, 0, PAGE_SIZE);
|
||||
u64 page_overleap_start = (addr > seg->vaddr) ? addr : seg->vaddr;
|
||||
u64 page_overleap_end = (addr + PAGE_SIZE < seg->vaddr + seg->filesz)
|
||||
? (addr + PAGE_SIZE)
|
||||
: (seg->vaddr + seg->filesz);
|
||||
if (page_overleap_start < page_overleap_end) {
|
||||
u64 copy_size = page_overleap_end - page_overleap_start;
|
||||
u64 src_offset = seg->offset + (page_overleap_start - seg->vaddr);
|
||||
u64 dst_offset = page_overleap_start - addr;
|
||||
|
||||
memcpy((u8*)kernel_virt + dst_offset, data + src_offset, copy_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return header->entry_point;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// 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;
|
||||
extern u32 next_pid;
|
||||
|
||||
#define USER_STACK_TOP 0x70000000
|
||||
#define HEAP_START 0x40000000
|
||||
|
||||
i32 process_spawn(const char* path, const char* name) {
|
||||
fs_node* file = vfs_open(path);
|
||||
if (!file) return -1;
|
||||
|
||||
process* new_proc = (process*)malloc(sizeof(process));
|
||||
if (!new_proc) return -2;
|
||||
memset(new_proc, 0, sizeof(process));
|
||||
new_proc->pid = next_pid++;
|
||||
new_proc->state = RUNNING;
|
||||
new_proc->pml4_phys = vmm_create_address_space();
|
||||
new_proc->heap_start = HEAP_START;
|
||||
new_proc->heap_cur = HEAP_START;
|
||||
strncpy(new_proc->name, name, 31);
|
||||
|
||||
u8* file_buffer = (u8*)malloc(file->len);
|
||||
if (!file_buffer) {
|
||||
free(new_proc);
|
||||
return -3;
|
||||
}
|
||||
vfs_read(file, 0, file->len, file_buffer);
|
||||
|
||||
u64 entry = load_hot(new_proc, file_buffer);
|
||||
if (!entry) return -4;
|
||||
|
||||
free(file_buffer);
|
||||
|
||||
vmm_setup_user_stack((u64*)new_proc->pml4_phys);
|
||||
sched_spawn((void(*)())entry, new_proc, true, USER_STACK_TOP);
|
||||
|
||||
return new_proc->pid;
|
||||
}
|
||||
|
||||
void init_task_entry() {
|
||||
i32 pid = process_spawn("/bin/init", "init");
|
||||
if (pid < 0) {
|
||||
panic("FATAL: Failed to spawn /bin/init");
|
||||
}
|
||||
|
||||
while (1) { __asm__("sti; hlt"); }
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <core/panic.h>
|
||||
#include <core/rand.h>
|
||||
|
||||
#include <drivers/shitgui.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
const char* fun_messages[] = {
|
||||
"Execution finished abnormally with code: 0x_x",
|
||||
"It's definitely your fault.",
|
||||
"No more Roblox!",
|
||||
"Call your mom 4 help!",
|
||||
"2bad4u",
|
||||
"Touch grass",
|
||||
"Skill issue",
|
||||
"You should just go outside actually",
|
||||
"Perfect opportunity to take a shower",
|
||||
"404 not found",
|
||||
"Windows is locked! Password:___ Time left: 5:45:41",
|
||||
"GOOOOOAL",
|
||||
"\"NAM PIZDA\": hackers dropped our registry",
|
||||
"geeked vs locked in",
|
||||
"HEEEELP!",
|
||||
"LET ME GO!",
|
||||
"You little asshole, make it better",
|
||||
"Go and read books for programming u idiot",
|
||||
"TIME TO BRAKE! :3 Take a tea and try again later cutie",
|
||||
"Code have been eaten by Aliens",
|
||||
"That's all, folks!",
|
||||
"Raiden, answer me, Raiden, respond! Raiden?! RAIDEEEEEEEEEN!",
|
||||
"I'll be back",
|
||||
"Hastla la vista, baby",
|
||||
"Ti chego mne tut nagovoril...",
|
||||
"Your access has been denied because of your region.\n\t\t\t\tPlease, use Chultem VPN and try again later.",
|
||||
"Fatal error has been occurred. \n\t\t\t\tYour device will be transformed into Niva in a few seconds.",
|
||||
"Have you tried turning it off and on again?",
|
||||
"Put it in rice maybe?",
|
||||
"Just hit the monitor, it usually helps",
|
||||
"I think it needs a rest. Come back tomorrow",
|
||||
"You clicked something wrong, didn't you?",
|
||||
"You hacked it too hard, bro",
|
||||
"I think you deleted the internet",
|
||||
"Stop downloading RAM",
|
||||
"Pro tip: dont crash",
|
||||
"Stop ricing the kernel you loonixtard, TermOS is NOT Loonix",
|
||||
"Attaboy, Jack. He's good. Really good.",
|
||||
"Zhenih priehal",
|
||||
"YOUR PC WAS BLOCKED BY FBI FOR WATCHING PORNOGRAPHY SEND 20 US DOLLARS",
|
||||
"fuck off",
|
||||
"Your GPU is now mining Ethereum for me. Thanks.",
|
||||
"Your PC is locked!\n\t\t\t\tPay a fee of 0.019082006 bitcoins to a wallet 1KtoProchitalTotSosal to get decryption key!",
|
||||
};
|
||||
|
||||
|
||||
const char* exception_messages[] = {
|
||||
"Division By Zero",
|
||||
"Debug",
|
||||
"Non Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Into Detected Overflow",
|
||||
"Out of Bounds",
|
||||
"Invalid Opcode",
|
||||
"Device Not Available",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Bad TSS",
|
||||
"Segment Not Present",
|
||||
"Stack Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"Reserved",
|
||||
"x87 Floating-Point Exception",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"SIMD Floating-Point Exception",
|
||||
"Virtualization Exception",
|
||||
"Control Protection Exception",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Hypervisor Injection Exception",
|
||||
"VMM Communication Exception",
|
||||
"Security Exception",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
__attribute__((noreturn)) void die() {
|
||||
while (1) {
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void draw_panic_bg() {
|
||||
console_clear(0x000000);
|
||||
console_set_color(0xFFFFFF);
|
||||
console_set_default_color(0xFFFFFF);
|
||||
|
||||
u64 msg_count = sizeof(fun_messages) / sizeof(fun_messages[0]);
|
||||
u8 rand_num = krand() % msg_count;
|
||||
|
||||
kprintf("\n\n");
|
||||
kprintf("\t\t\t\t^bKERNEL PANIC^! :( \n");
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t^y%s^!\n", fun_messages[rand_num]);
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void panic_exception(Registers *regs) {
|
||||
draw_panic_bg();
|
||||
|
||||
kprintf("\t\t^yCPU EXCEPTION^!: ^b%s^! (%d)\n", exception_messages[regs->int_no], regs->int_no);
|
||||
if (regs->err_code) kprintf("\t\t^yError Code^!: %X\n", regs->err_code);
|
||||
kprintf("\t\t^yInstruction Pointer^! (^yRIP^!): %X\n", regs->rip);
|
||||
kprintf("\t\t^yCode Segment^! (^yCS^!): %X\n", regs->cs);
|
||||
kprintf("\t\t^yFlags^! (^yRFLAGS^!): %X\n", regs->rflags);
|
||||
kprintf("\t\t^yStack Pointer^! (^yRSP^!): %X\n", regs->rsp);
|
||||
if (regs->int_no == 14) {
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t ^yPage Fault Helper^! \n");
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
u64 cr2;
|
||||
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
kprintf("\t\t^yFaulting Address^! (^yCR2^!): %X\n", cr2);
|
||||
kprintf("\t\t^yERRCode^!: %X\n", regs->err_code);
|
||||
u64 present = (regs->err_code & (1 << 0)) != 0;
|
||||
u64 write = (regs->err_code & (1 << 1)) != 0;
|
||||
u64 user = (regs->err_code & (1 << 2)) != 0;
|
||||
u64 reserved = (regs->err_code & (1 << 3)) != 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[^bW^!] ^yCaused by^! %s\n", write ? "WRITE" : "READ");
|
||||
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 (instruction) kprintf("\t\t\t[^bI^!] ^yTried to^! execute ^ycode from^! NX ^ymemory^!\n");
|
||||
}
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\t^yREGISTERS^!\n");
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t^yRAX^!=%X, ^yRBX^!=%X\n", regs->rax, regs->rbx);
|
||||
kprintf("\t\t^yRCX^!=%X, ^yRDX^!=%X\n", regs->rcx, regs->rdx);
|
||||
kprintf("\t\t^yRSI^!=%X, ^yRDI^!=%X\n", regs->rsi, regs->rdi);
|
||||
kprintf("\t\t^yRBP^!=%X, ^yR8^! =%X\n", regs->rbp, regs->r8);
|
||||
kprintf("\t\t^yR9^! =%X, ^yR10^!=%X \n", regs->r9, regs->r10);
|
||||
kprintf("\t\t^yR11^!=%X, ^yR12^!=%X\n", regs->r11, regs->r12);
|
||||
kprintf("\t\t^yR13^!=%X, ^yR14^!=%X\n", regs->r13, regs->r14);
|
||||
kprintf("\t\t^yR15^!=%X\n",regs->r15);
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\t^bSystem halted.^!\n");
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void panic(const char* msg) {
|
||||
draw_panic_bg();
|
||||
|
||||
kprintf("\t\t^yReason^!: %s\n", msg);
|
||||
kprintf("\t\t--------------------------------\n");
|
||||
kprintf("\t\t\t\t^bSystem halted.^!\n");
|
||||
|
||||
die();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// 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>
|
||||
|
||||
static u64 prng_state = 0;
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/string.h>
|
||||
#include <mm/heap.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/memory.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 idle_task() {
|
||||
while (1) {
|
||||
__asm__ volatile ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void sched_init() {
|
||||
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));
|
||||
memset(kt, 0, sizeof(task));
|
||||
kt->id = 0;
|
||||
kt->proc = &kernel_process;
|
||||
kt->sleep_ticks = 0;
|
||||
kt->next = kt;
|
||||
kt->task_state = RUNNING;
|
||||
kt->waiting_on_pid = -1;
|
||||
|
||||
curr_task = kt;
|
||||
sched_spawn(idle_task, &kernel_process, false, 0);
|
||||
}
|
||||
|
||||
task* sched_spawn(void(*entry)(), process* owner, bool is_user, u64 fixed_user_stack) {
|
||||
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");
|
||||
u64* rsp = (u64*)(stack_base + stack_size);
|
||||
|
||||
u64 cs = is_user ? 0x23 : 0x08;
|
||||
u64 ss = is_user ? 0x1b : 0x10;
|
||||
u64 rflags = 0x202;
|
||||
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 = 0; // int no
|
||||
*--rsp = 0; // err code
|
||||
|
||||
for (u8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX
|
||||
|
||||
t->rsp = (u64)rsp;
|
||||
t->proc = owner;
|
||||
t->id = owner->pid;
|
||||
t->sleep_ticks = 0;
|
||||
t->next = curr_task->next;
|
||||
t->kernel_stack_top = (u64)stack_base + stack_size;
|
||||
t->task_state = RUNNING;
|
||||
t->waiting_on_pid = -1;
|
||||
curr_task->next = t;
|
||||
return t;
|
||||
}
|
||||
|
||||
u64 sched_next(u64 curr_rsp) {
|
||||
if (!curr_task) return curr_rsp;
|
||||
|
||||
curr_task->rsp = curr_rsp;
|
||||
task* it = curr_task->next;
|
||||
|
||||
do {
|
||||
if (it->sleep_ticks > 0) it->sleep_ticks--;
|
||||
it = it->next;
|
||||
} while (it != curr_task->next);
|
||||
|
||||
if (curr_task->sleep_ticks > 0) curr_task->sleep_ticks--;
|
||||
|
||||
task* next = curr_task;
|
||||
while (1) {
|
||||
// TODO: add gc here;
|
||||
next = next->next;
|
||||
if (next->task_state == SLEEPING && next->sleep_ticks == 0) next->task_state = RUNNING;
|
||||
if (next->task_state == RUNNING) break;
|
||||
if (next == curr_task) {
|
||||
if (curr_task->task_state == RUNNING) break;
|
||||
panic("no running tasks");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void sched_block(u32 pid) {
|
||||
curr_task->task_state = BLOCKED;
|
||||
curr_task->waiting_on_pid = pid;
|
||||
__asm__ volatile("int $32");
|
||||
}
|
||||
|
||||
void sched_wakeup(u32 pid) {
|
||||
task* it = curr_task;
|
||||
do {
|
||||
if (it->task_state == BLOCKED && it->waiting_on_pid == (i32)pid) {
|
||||
it->task_state = RUNNING;
|
||||
it->waiting_on_pid = -1;
|
||||
}
|
||||
it = it->next;
|
||||
} while (it != curr_task);
|
||||
}
|
||||
|
||||
void sched_exit() {
|
||||
u32 my_pid = curr_task->id;
|
||||
curr_task->task_state = DEAD;
|
||||
|
||||
sched_wakeup(my_pid);
|
||||
__asm__ volatile("int $32");
|
||||
}
|
||||
|
||||
void yield(u64 ticks) {
|
||||
curr_task->sleep_ticks = ticks;
|
||||
curr_task->task_state = SLEEPING;
|
||||
__asm__ volatile("hlt");
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
#include <drivers/shitgui.h>
|
||||
#include <drivers/console.h>
|
||||
#include "../data/logo.h"
|
||||
|
||||
void show_splash(SG_Context *sg_ctx) {
|
||||
SG_Point logo_point = {0, 10};
|
||||
sg_put_img(sg_ctx, &logo_point, &logo_img);
|
||||
SG_Point start_pos = {75, 55}; // greeting
|
||||
console_set_cursor_pos(&start_pos);
|
||||
kprintf("Welcome to ^ptermOS^!!!!\n");
|
||||
|
||||
SG_Point text_normal_point = {0, 120}; // not nice to hardcode nums like that but we have what we have
|
||||
console_set_cursor_pos(&text_normal_point);
|
||||
}
|
||||
@@ -1,305 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include "core/scheduler.h"
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/serial.h>
|
||||
#include <drivers/font.h>
|
||||
#include <drivers/shitgui.h>
|
||||
#include <drivers/keyboard.h>
|
||||
|
||||
#include <core/math.h>
|
||||
#include <types.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define COLOR_RED 0xFF5555
|
||||
#define COLOR_VERYRED 0xFF0000
|
||||
#define COLOR_GREEN 0x08bf39
|
||||
#define COLOR_VERYGREEN 0x00FF00
|
||||
#define COLOR_TURQUOISE 0x5effaf
|
||||
#define COLOR_BLUE 0x5555FF
|
||||
#define COLOR_VERYBLUE 0x0000FF
|
||||
#define COLOR_LIGHTBLUE 0x3890e8
|
||||
#define COLOR_YELLOW 0xFFFF55
|
||||
#define COLOR_CYAN 0x55FFFF
|
||||
#define COLOR_MAGENTA 0xFF55FF
|
||||
#define COLOR_BLACK 0x000000
|
||||
#define COLOR_WHITE 0xFFFFFF
|
||||
#define COLOR_PINK 0xFFA3B1
|
||||
|
||||
static SG_Context *ctx_ptr = nullptr;
|
||||
static SG_Point s_cursor_pos = {0};
|
||||
static SG_Font s_font = {0};
|
||||
static u32 s_color = COLOR_WHITE;
|
||||
static u32 s_def_color = COLOR_WHITE;
|
||||
static u32 s_bg_color = COLOR_BLACK;
|
||||
static bool s_are_we_blinkin = true;
|
||||
static bool s_waiting_for_input = false;
|
||||
static bool s_cursor_visible = false;
|
||||
|
||||
void console_init(SG_Context *ctx) {
|
||||
ctx_ptr = ctx;
|
||||
s_cursor_pos.x = 0;
|
||||
s_cursor_pos.y = 0;
|
||||
|
||||
s_font.h = 16;
|
||||
s_font.w = 8;
|
||||
s_font.base = (const unsigned char*)font8x16;
|
||||
}
|
||||
|
||||
u64 console_get_colors() {
|
||||
return ((u64) s_color << 32) | s_bg_color;
|
||||
}
|
||||
|
||||
void console_clear(u32 color) {
|
||||
if (!ctx_ptr) return;
|
||||
|
||||
SG_Point p = {0, 0};
|
||||
sg_draw_rect(ctx_ptr, &p, ctx_ptr->width, ctx_ptr->height, color);
|
||||
|
||||
s_cursor_pos.x = 0;
|
||||
s_cursor_pos.y = 0;
|
||||
s_bg_color = color;
|
||||
}
|
||||
|
||||
SG_Context* console_get_context() {
|
||||
return ctx_ptr;
|
||||
}
|
||||
|
||||
SG_Point console_get_dimensions() {
|
||||
SG_Point p = {0};
|
||||
p.x = ctx_ptr->width;
|
||||
p.y = ctx_ptr->height;
|
||||
return p;
|
||||
}
|
||||
|
||||
void console_set_cursor_pos(SG_Point *p) {
|
||||
if (!p) return;
|
||||
s_cursor_pos.x = p->x;
|
||||
s_cursor_pos.y = p->y;
|
||||
}
|
||||
|
||||
void console_putc(char c) {
|
||||
serial_writec(c);
|
||||
if (!ctx_ptr) return;
|
||||
if (c == '\n') {
|
||||
s_cursor_pos.x = 0;
|
||||
s_cursor_pos.y += s_font.h;
|
||||
} else if (c == '\t') {
|
||||
s_cursor_pos.x += s_font.w * 4;
|
||||
} else if (c == '\b') {
|
||||
s_cursor_pos.x -= s_font.w;
|
||||
sg_draw_rect(ctx_ptr, &s_cursor_pos, s_font.w, s_font.h, s_bg_color);
|
||||
} else {
|
||||
sg_draw_char_bitmap(ctx_ptr, &s_cursor_pos, c, s_color, &s_font);
|
||||
s_cursor_pos.x += s_font.w;
|
||||
}
|
||||
|
||||
if (s_cursor_pos.x >= ctx_ptr->width) {
|
||||
s_cursor_pos.x = 0;
|
||||
s_cursor_pos.y += s_font.h;
|
||||
}
|
||||
if (s_cursor_pos.y >= ctx_ptr->height) {
|
||||
console_clear(s_bg_color); // TODO: do scrolling
|
||||
}
|
||||
}
|
||||
|
||||
void kprint(const char *str) {
|
||||
for (i32 i = 0; str[i] != '\0'; i++) console_putc(str[i]);
|
||||
}
|
||||
|
||||
static void print_dec(const i64 n) {
|
||||
if (n < 0) console_putc('-');
|
||||
u64 u = abs(n);
|
||||
char buffer[32];
|
||||
i32 i = 0;
|
||||
|
||||
do {
|
||||
buffer[i] = (u % 10) + '0';
|
||||
u /= 10;
|
||||
i++;
|
||||
} while (u > 0);
|
||||
|
||||
while (--i >= 0) {
|
||||
console_putc(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_hex(u64 u, u8 padding) {
|
||||
console_putc('0');
|
||||
console_putc('x');
|
||||
|
||||
if (u == 0) {
|
||||
console_putc('0');
|
||||
for (i32 i = 1; i < padding; i++) console_putc('0');
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[16] = {0};
|
||||
i32 i = 0;
|
||||
|
||||
do {
|
||||
i32 digit = u % 16;
|
||||
if (digit < 10) buffer[i++] = digit + '0';
|
||||
else buffer[i++] = digit - 10 + 'A';
|
||||
u /= 16;
|
||||
} while (u > 0);
|
||||
|
||||
while(i < padding) {
|
||||
console_putc('0');
|
||||
padding--;
|
||||
}
|
||||
|
||||
while (--i >= 0) {
|
||||
console_putc(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void kprintf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
for (i32 i = 0; fmt[i] != '\0'; i++) {
|
||||
if (fmt[i] == '%') {
|
||||
i++;
|
||||
switch (fmt[i]) {
|
||||
case 's': {
|
||||
const char *str = va_arg(args, const char*);
|
||||
if (!str) str = "undefined";
|
||||
kprint(str);
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
char c = (char)va_arg(args, int);
|
||||
console_putc(c);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
i32 num = va_arg(args, i32);
|
||||
print_dec(num);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
u64 num = va_arg(args, u64);
|
||||
print_hex(num, 0);
|
||||
break;
|
||||
}
|
||||
case 'X' : {
|
||||
u64 num = va_arg(args, u64);
|
||||
print_hex(num, 16);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console_putc(fmt[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (fmt[i] == '^') {
|
||||
i++;
|
||||
switch (fmt[i]) {
|
||||
case 'r': console_set_color(COLOR_RED); break;
|
||||
case 'R': console_set_color(COLOR_VERYRED); break;
|
||||
case 'g': console_set_color(COLOR_GREEN); break;
|
||||
case 'G': console_set_color(COLOR_VERYGREEN); break;
|
||||
case 't': console_set_color(COLOR_TURQUOISE); break;
|
||||
case 'b': console_set_color(COLOR_BLUE); break;
|
||||
case 'B': console_set_color(COLOR_VERYBLUE); break;
|
||||
case 'l': console_set_color(COLOR_LIGHTBLUE); break;
|
||||
case 'y': console_set_color(COLOR_YELLOW); break;
|
||||
case 'c': console_set_color(COLOR_CYAN); break;
|
||||
case 'm': console_set_color(COLOR_MAGENTA); break;
|
||||
case 'p': console_set_color(COLOR_PINK); break;
|
||||
case '0': console_set_color(COLOR_BLACK); break;
|
||||
case 'w': console_set_color(COLOR_WHITE); break;
|
||||
case '!': console_set_color(s_def_color); break;
|
||||
case '~': console_set_color(~s_bg_color); break;
|
||||
case '^': console_putc('^'); break;
|
||||
default: {
|
||||
console_putc('^');
|
||||
console_putc(fmt[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console_putc(fmt[i]);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void console_set_color(u32 color) {
|
||||
s_color = color;
|
||||
}
|
||||
|
||||
void console_set_default_color(u32 color) {
|
||||
s_def_color = color;
|
||||
}
|
||||
|
||||
char console_getc() {
|
||||
s_waiting_for_input = true;
|
||||
while (kb_buf.head == kb_buf.tail) { __asm__ volatile ("sti"); yield(1); }
|
||||
__asm__ volatile ("cli");
|
||||
s_waiting_for_input = false;
|
||||
char temp = kb_buf.buffer[kb_buf.tail];
|
||||
kb_buf.tail = (kb_buf.tail + 1) % KB_BUFF_SIZE;
|
||||
__asm__ volatile ("sti");
|
||||
if (s_cursor_visible) {
|
||||
cursor_blink();
|
||||
s_cursor_visible = false;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
void kgets(char* buff, u32 lim) {
|
||||
u32 i = 0;
|
||||
while (true) {
|
||||
char c = console_getc();
|
||||
switch (c) {
|
||||
case '\n': {
|
||||
buff[i] = '\0';
|
||||
kprintf("\n");
|
||||
return;
|
||||
}
|
||||
case '\b': {
|
||||
if (i > 0) {
|
||||
i--;
|
||||
kprintf("\b \b");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (i < lim - 1) {
|
||||
buff[i] = c;
|
||||
kprintf("%c", c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cursor_blink() {
|
||||
sg_draw_rect(ctx_ptr, &s_cursor_pos, s_font.w, s_font.h, sg_get_pixel(ctx_ptr, &s_cursor_pos) ^ 0xFFFFFF);
|
||||
}
|
||||
|
||||
void cursor_blinker_sched_task() {
|
||||
while (true) {
|
||||
if (s_are_we_blinkin) {
|
||||
if (s_waiting_for_input) {
|
||||
cursor_blink();
|
||||
s_cursor_visible = !s_cursor_visible;
|
||||
}
|
||||
} else if (s_cursor_visible) {
|
||||
cursor_blink();
|
||||
s_cursor_visible = !s_cursor_visible;
|
||||
}
|
||||
yield(500);
|
||||
}
|
||||
}
|
||||
|
||||
void console_toggle_cursor_blink() {
|
||||
s_are_we_blinkin = !s_are_we_blinkin;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <drivers/serial.h>
|
||||
#include <io.h>
|
||||
|
||||
#define PORT 0x3F8 // com1
|
||||
|
||||
int serial_init() {
|
||||
outb(PORT + 1, 0x00); // interrupt enable register (+1) / disable interruptions
|
||||
outb(PORT + 3, 0x80); // line control register (+3)
|
||||
outb(PORT + 0, 0x03); // speed : low byte
|
||||
outb(PORT + 1, 0x00); // speed : high byte
|
||||
outb(PORT + 3, 0x03); // line control register (+3) / reset DLAB / no parity / 1 stop bit / (8N1)
|
||||
outb(PORT + 2, 0xC7); // FIFO Control register (+2) / 1100 0111 / last ones are enable FIFO buff / first ones to clean noise
|
||||
outb(PORT + 4, 0x0B); // ready :3
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_transmit_empty() {
|
||||
return inb(PORT + 5) & 0x20; // checking 5th bit LSR
|
||||
}
|
||||
|
||||
void serial_writec(char chr) {
|
||||
while (is_transmit_empty() == 0); // waiting for buffer to flush (spinlock)
|
||||
outb(PORT, chr);
|
||||
}
|
||||
|
||||
void serial_write(const char *str) {
|
||||
for (int i = 0; str[i] != '\0'; i++) serial_writec(str[i]);
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <core/scheduler.h>
|
||||
#include <core/panic.h>
|
||||
#include <drivers/shitgui.h>
|
||||
#include <mm/heap.h>
|
||||
#include <mm/memory.h>
|
||||
|
||||
#define SHITGUI_TRANSPARENCY_KEY 0xFF00FF
|
||||
|
||||
SG_Context* main_context;
|
||||
|
||||
void sg_init(SG_Context *ctx) {
|
||||
main_context = ctx;
|
||||
}
|
||||
|
||||
u32 sg_get_pixel(SG_Context *ctx, SG_Point *p) {
|
||||
if (!ctx->fb || !p || p->x >= ctx->width || p->y >= ctx->height) return 0;
|
||||
return ctx->fb[p->y * ctx->pitch + p->x];
|
||||
}
|
||||
|
||||
void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img) {
|
||||
if (!ctx->fb || !img) return;
|
||||
|
||||
u32 start_x = p->x;
|
||||
u32 start_y = p->y;
|
||||
u32 draw_w = img->width;
|
||||
u32 draw_h = img->height;
|
||||
|
||||
if (start_x >= ctx->width || start_y >= ctx->height) return;
|
||||
if (start_x + draw_w > ctx->width) draw_w = ctx->width - start_x;
|
||||
if (start_y + draw_h > ctx->height) draw_h = ctx->height - start_y;
|
||||
|
||||
for (u32 y = 0; y < draw_h; y++) {
|
||||
volatile u32 *dest_ptr = &ctx->fb[(start_y + y) * ctx->pitch + start_x];
|
||||
u32 *src_ptr = &img->buffer[y * img->width];
|
||||
for (u32 x = 0; x < draw_w; x++) {
|
||||
u32 color = src_ptr[x];
|
||||
if (color != SHITGUI_TRANSPARENCY_KEY) dest_ptr[x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sg_draw_rect(SG_Context *ctx, SG_Point *p, u32 w, u32 h, u32 color) {
|
||||
if (!ctx->fb) return;
|
||||
|
||||
u32 start_x = p->x;
|
||||
u32 start_y = p->y;
|
||||
u32 draw_w = w;
|
||||
u32 draw_h = h;
|
||||
|
||||
if (start_x >= ctx->width || start_y >= ctx->height) return;
|
||||
if (start_x + draw_w > ctx->width) draw_w = ctx->width - start_x;
|
||||
if (start_y + draw_h > ctx->height) draw_h = ctx->height - start_y;
|
||||
|
||||
|
||||
for (u32 y = 0; y < draw_h; y++) {
|
||||
volatile u32 *row_ptr = &ctx->fb[(start_y + y) * ctx->pitch + start_x];
|
||||
for (u32 x = 0; x < draw_w; x++) row_ptr[x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font) {
|
||||
if (!ctx->fb) return;
|
||||
|
||||
u32 start_x = p->x;
|
||||
u32 start_y = p->y;
|
||||
u32 draw_w = font->w;
|
||||
u32 draw_h = font->h;
|
||||
|
||||
if (start_x >= ctx->width || start_y >= ctx->height) return;
|
||||
if (start_x + draw_w > ctx->width) draw_w = ctx->width - start_x;
|
||||
if (start_y + draw_h > ctx->height) draw_h = ctx->height - start_y;
|
||||
|
||||
for (u32 y = 0; y < draw_h; y++) {
|
||||
u8 bitmap_row = font->base[(unsigned char)c * font->h + y];
|
||||
volatile u32 *row_ptr = &ctx->fb[(start_y + y) * ctx->pitch + start_x];
|
||||
for (u32 x = 0; x < draw_w; x++) {
|
||||
if (bitmap_row & (1 << (7 - x))) {
|
||||
row_ptr[x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <drivers/timer.h>
|
||||
#include <io.h>
|
||||
#include <types.h>
|
||||
#include <core/scheduler.h>
|
||||
|
||||
#define PIT_BASE_CLOCK 1193180
|
||||
#define PIT_CMD 0x43
|
||||
#define PIT_DATA 0x40
|
||||
|
||||
volatile u64 ticks = 0;
|
||||
|
||||
void timer_init(u32 freq) {
|
||||
u32 divisor = PIT_BASE_CLOCK / freq;
|
||||
|
||||
outb(PIT_CMD, 0x36); // 0x36 = 00110110 = channel 0, LOHI byte access, Mode 3, binary
|
||||
outb(PIT_DATA, divisor & 0xFF);
|
||||
outb(PIT_DATA, (divisor >> 8) & 0xFF);
|
||||
|
||||
u8 mask = inb(0x21);
|
||||
mask &= ~(1 << 0);
|
||||
outb(0x21, mask);
|
||||
}
|
||||
|
||||
u64 timer_handler(Registers *regs) {
|
||||
ticks++;
|
||||
return sched_next((u64)regs);
|
||||
}
|
||||
|
||||
|
||||
void sleep(u64 ms) {
|
||||
u64 start = ticks;
|
||||
while (ticks < start + ms) __asm__ volatile ("hlt");
|
||||
}
|
||||
|
||||
u64 get_uptime() {
|
||||
return ticks;
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <types.h>
|
||||
#include <fs/cpio.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <core/string.h>
|
||||
#include <core/panic.h>
|
||||
#include <mm/memory.h>
|
||||
#include <mm/heap.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
#define ALIGN4(x) (((x) + 3) & ~3)
|
||||
|
||||
typedef struct {
|
||||
char c_magic[6]; // "070701"
|
||||
char c_ino[8];
|
||||
char c_mode[8]; // type and flags
|
||||
char c_uid[8];
|
||||
char c_gid[8];
|
||||
char c_nlink[8];
|
||||
char c_mtime[8];
|
||||
char c_filesize[8];
|
||||
char c_devmajor[8];
|
||||
char c_devminor[8];
|
||||
char c_rdevmajor[8];
|
||||
char c_rdevminor[8];
|
||||
char c_namesize[8]; // including \0
|
||||
char c_check[8]; // checksum (usually 0)
|
||||
} cpio_header;
|
||||
|
||||
static fs_ops cpio_ops = {
|
||||
.read = cpio_read,
|
||||
.write = nullptr,
|
||||
.open = nullptr,
|
||||
.close = nullptr,
|
||||
};
|
||||
|
||||
u64 hex_to_u64(const char* s, i32 len) {
|
||||
u64 res = 0;
|
||||
for (i32 i = 0; i < len; i++) {
|
||||
char c = s[i];
|
||||
res <<= 4;
|
||||
if (c >= '0' && c <= '9') res += (c - '0');
|
||||
else if (c >= 'A' && c <= 'F') res += (c - 'A' + 10);
|
||||
else if (c >= 'a' && c <= 'f') res += (c - 'a' + 10);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
u64 cpio_read(fs_node* node, u64 offset, u64 size, u8* buff) {
|
||||
if (offset > node->len) return 0; // EOF
|
||||
if ((offset + size) > node->len) size = node->len - offset;
|
||||
|
||||
memcpy(buff, (char*)node->impl_data + offset, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
fs_node* cpio_mount(void* base, u64 size) {
|
||||
u8* ptr = (u8*)base;
|
||||
u8* end = ptr + size;
|
||||
|
||||
fs_node* root = malloc(sizeof(fs_node));
|
||||
if (!root) panic("CPIO: Failed to malloc for root node!");
|
||||
memset(root, 0, sizeof(fs_node));
|
||||
strcpy(root->name, "/");
|
||||
root->flags = FS_DIR;
|
||||
root->ops = &cpio_ops;
|
||||
|
||||
fs_node* tail = nullptr;
|
||||
|
||||
while (ptr < end) {
|
||||
cpio_header* header = (cpio_header*)ptr;
|
||||
|
||||
if (strncmp(header->c_magic, "070701", 6) != 0) panic("CPIO: Bad magic! Corrupted initramfs");
|
||||
u64 namesize = hex_to_u64(header->c_namesize, 8);
|
||||
u64 filesize = hex_to_u64(header->c_filesize, 8);
|
||||
|
||||
char* filename = (char*)(ptr + sizeof(cpio_header));
|
||||
if (strcmp(filename, "TRAILER!!!") == 0) break;
|
||||
|
||||
u64 header_and_name_len = sizeof(cpio_header) + namesize;
|
||||
u64 offset_to_data = ALIGN4(header_and_name_len);
|
||||
void* file_content = (void*)(ptr + offset_to_data);
|
||||
|
||||
fs_node* new_node = malloc(sizeof(fs_node));
|
||||
if (!new_node) panic("CPIO: Failed to malloc for new node!");
|
||||
memset(new_node, 0, sizeof(fs_node));
|
||||
strncpy(new_node->name, filename, sizeof(new_node->name) - 1);
|
||||
|
||||
new_node->len = filesize;
|
||||
new_node->inode = hex_to_u64(header->c_ino, 8);
|
||||
new_node->ops = &cpio_ops;
|
||||
new_node->impl_data = file_content;
|
||||
|
||||
u64 mode = hex_to_u64(header->c_mode, 8);
|
||||
if ((mode & 0xF000) == 0x4000) new_node->flags = FS_DIR;
|
||||
else new_node->flags = FS_FILE;
|
||||
|
||||
if (root->ptr == nullptr) root->ptr = new_node;
|
||||
else if (tail) tail->next = new_node;
|
||||
|
||||
tail = new_node;
|
||||
|
||||
kprintf("^bCPIO^!: Found file '^y%s^!' (size ^y%d^!) at ^y%x^!\n", filename, filesize, file_content);
|
||||
|
||||
u64 data_len = ALIGN4(filesize);
|
||||
ptr += offset_to_data + data_len;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#include <fs/vfs.h>
|
||||
#include <core/string.h>
|
||||
|
||||
fs_node* fs_root = nullptr;
|
||||
|
||||
void vfs_init(fs_node* root_node) {
|
||||
fs_root = root_node;
|
||||
}
|
||||
|
||||
u64 vfs_read(fs_node* node, u64 offset, u64 size, u8* buff) {
|
||||
if (!node) return 0;
|
||||
if (!node->ops->read) return 0;
|
||||
|
||||
return node->ops->read(node, offset, size, buff);
|
||||
}
|
||||
|
||||
fs_node* vfs_open(const char* path) {
|
||||
if (!fs_root) return nullptr;
|
||||
if (strcmp(path, "/") == 0) return fs_root;
|
||||
|
||||
const char* search_name = path;
|
||||
if (path[0] == '/') search_name++;
|
||||
|
||||
fs_node* curr = fs_root->ptr;
|
||||
while (curr != nullptr) {
|
||||
if (strcmp(curr->name, search_name) == 0) {
|
||||
if (curr->ops->open) curr->ops->open(curr);
|
||||
return curr;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void vfs_close(fs_node* node) {
|
||||
if (node && node->ops->close) node->ops->close(node);
|
||||
}
|
||||
+73
-70
@@ -7,107 +7,110 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <drivers/shitgui.h>
|
||||
#include <drivers/serial.h>
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/timer.h>
|
||||
#include <IO/IOGraphics.h>
|
||||
#include <IO/IOSerial.h>
|
||||
#include <IO/IOConsole.h>
|
||||
#include <IO/IOTimer.h>
|
||||
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <core/splash.h>
|
||||
#include <core/rand.h>
|
||||
#include <core/loader.h>
|
||||
#include <OS/OSPanic.h>
|
||||
#include <OS/OSScheduler.h>
|
||||
#include <OS/Exec/OSLoader.h>
|
||||
|
||||
#include <gdt.h>
|
||||
#include <idt.h>
|
||||
#include <pic.h>
|
||||
#include <cpuinfo.h>
|
||||
#include <lib/Splash.h>
|
||||
#include <lib/Rand.h>
|
||||
|
||||
#include <GDT.h>
|
||||
#include <IDT.h>
|
||||
#include <PIC.h>
|
||||
#include <OSCPU.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
#include <mm/vmm.h>
|
||||
#include <mm/heap.h>
|
||||
#include <VM/PMM.h>
|
||||
#include <VM/VMM.h>
|
||||
#include <VM/Heap.h>
|
||||
|
||||
#include <fs/cpio.h>
|
||||
#include <fs/vfs.h>
|
||||
#include <FS/CPIO.h>
|
||||
#include <FS/VFS.h>
|
||||
|
||||
#define FG_COLOR 0xffffff
|
||||
#define BG_COLOR 0x111111
|
||||
enum {
|
||||
kDefaultConsoleForegroundColor = 0xffffff,
|
||||
kDefaultConsoleBackgroundColor = 0x111111,
|
||||
};
|
||||
|
||||
extern u64 _kernel_end;
|
||||
extern UInt64 _kernel_end;
|
||||
extern void* stack_top;
|
||||
static SG_Context sg_ctx;
|
||||
static IOGraphicsContext sIOGraphicsContext;
|
||||
|
||||
void kmain(Bootinfo* info) {
|
||||
serial_init();
|
||||
serial_write("Kernel started\n");
|
||||
IOSerialInit();
|
||||
IOSerialWrite("Kernel started\n");
|
||||
|
||||
console_init(&sg_ctx);
|
||||
IOConsoleInit(&sIOGraphicsContext);
|
||||
|
||||
if (info->magic != BOOTINFO_MAGIC) panic("Corrupt bootinfo!");
|
||||
if (info->magic != BOOTINFO_MAGIC) OSPanic("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();
|
||||
kprintf("IDT initialized\n");
|
||||
pic_remap();
|
||||
kprintf("PIC remapped\n");
|
||||
pmm_init(&info->mem);
|
||||
kprintf("PMM initialized\n");
|
||||
vmm_init(info);
|
||||
kprintf("VMM initialized\n");
|
||||
timer_init(1000);
|
||||
kprintf("Timer initialized\n");
|
||||
heap_init();
|
||||
kprintf("Heap initialized\n");
|
||||
sched_init();
|
||||
kprintf("Scheduler initialized\n");
|
||||
sg_init(&sg_ctx);
|
||||
kprintf("Shitgui initialized\n");
|
||||
syscall_init();
|
||||
OSCPUInitialize((UInt64)&stack_top);
|
||||
IOConsoleLog("Got CPUINFO\n");
|
||||
RandInitialize();
|
||||
IOConsoleLog("Random initialized\n");
|
||||
HALGlobalDescriptorTableInitialize();
|
||||
IOConsoleLog("GDT initialized\n");
|
||||
HALInterruptsDescriptorTableInitialize();
|
||||
IOConsoleLog("IDT initialized\n");
|
||||
HALLegacyInterruptControllerRemap();
|
||||
IOConsoleLog("PIC remapped\n");
|
||||
VMPhysicalMemoryInitialize(&info->memoryMap);
|
||||
IOConsoleLog("PMM initialized\n");
|
||||
VMVirtualMemoryInitialize(info);
|
||||
IOConsoleLog("VMM initialized\n");
|
||||
IOTimerInitialize(1000);
|
||||
IOConsoleLog("Timer initialized\n");
|
||||
VMHeapInitialize();
|
||||
IOConsoleLog("Heap initialized\n");
|
||||
OSSchedulerInitialize();
|
||||
IOConsoleLog("Scheduler initialized\n");
|
||||
|
||||
info = (Bootinfo*)PHYS_TO_HHDM((u64)info);
|
||||
OSServicesInitialize();
|
||||
IOConsoleLog("Syscalls initialized");
|
||||
|
||||
fs_node* root = cpio_mount(PHYS_TO_HHDM(info->initramfs.addr), info->initramfs.size);
|
||||
vfs_init(root);
|
||||
kprintf("VFS initialized\n");
|
||||
info = (Bootinfo*)PHYS_TO_HHDM((UInt64)info);
|
||||
|
||||
u32 *fb = (u32*)info->framebuffer.base;
|
||||
if (!fb) return kprintf("No framebuffer found!!");
|
||||
FSVNode* root = FSCPIOMount(PHYS_TO_HHDM(info->initramfs.address), info->initramfs.size);
|
||||
FSVirtualFileSystemInitialize(root);
|
||||
IOConsoleLog("VFS initialized\n");
|
||||
|
||||
sg_ctx.fb = fb;
|
||||
sg_ctx.height = info->framebuffer.height;
|
||||
sg_ctx.width = info->framebuffer.width;
|
||||
sg_ctx.pitch = info->framebuffer.pitch;
|
||||
UInt32 *framebuffer = (UInt32*)info->framebuffer.base;
|
||||
if (!framebuffer) return IOConsoleLog("No framebuffer found!!");
|
||||
|
||||
console_clear(BG_COLOR);
|
||||
console_set_color(FG_COLOR);
|
||||
console_set_default_color(FG_COLOR);
|
||||
sIOGraphicsContext.framebuffer = framebuffer;
|
||||
sIOGraphicsContext.dimensions.height = info->framebuffer.height;
|
||||
sIOGraphicsContext.dimensions.width = info->framebuffer.width;
|
||||
sIOGraphicsContext.pixelsPerScanLine = info->framebuffer.pitch;
|
||||
|
||||
show_splash(&sg_ctx);
|
||||
IOConsoleClear(kDefaultConsoleBackgroundColor);
|
||||
IOConsoleSetForegroundColor(kDefaultConsoleForegroundColor);
|
||||
IOConsoleSetDefaultForegroundColor(kDefaultConsoleForegroundColor);
|
||||
|
||||
SplashShow(&sIOGraphicsContext);
|
||||
|
||||
bool staying_in_ksh = false;
|
||||
if (!info->initramfs.addr) {
|
||||
kprintf("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n");
|
||||
if (!info->initramfs.address) {
|
||||
IOConsoleLog("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n");
|
||||
staying_in_ksh = true;
|
||||
}
|
||||
|
||||
if (!staying_in_ksh) {
|
||||
kprintf("Press any key to continue booting. \nPress ^yq^! to stay in ^gksh^!\n");
|
||||
IOConsoleLog("Press any key to continue booting. \nPress ^yq^! to stay in ^gksh^!\n");
|
||||
char c = '\n';
|
||||
c = console_getc();
|
||||
c = IOConsoleGetCharacter();
|
||||
if (c == 'q') staying_in_ksh = true;
|
||||
}
|
||||
|
||||
if (staying_in_ksh) sched_spawn(ksh, nullptr, false, 0);
|
||||
else sched_spawn(init_task_entry, nullptr, false, 0);
|
||||
if (staying_in_ksh) OSSchedulerSpawn(ksh, nullptr, false, 0);
|
||||
else OSSchedulerSpawn(init_task_entry, nullptr, false, 0);
|
||||
|
||||
__asm__ volatile("sti");
|
||||
|
||||
while (true) __asm__ volatile("hlt");
|
||||
panic("How in the name of God you got here?");
|
||||
OSPanic("How in the name of God you got here?");
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include "bootinfo.h"
|
||||
#include <lib/Rand.h>
|
||||
#include <OSCPU.h>
|
||||
#include <types.h>
|
||||
|
||||
static UInt64 sPseudorandState = 0;
|
||||
|
||||
static inline UInt64 RDTSC() {
|
||||
UInt32 lo, hi;
|
||||
__asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
|
||||
return ((UInt64)hi << 32) | lo;
|
||||
}
|
||||
|
||||
void RandInitialize() {
|
||||
sPseudorandState = RDTSC();
|
||||
if (sPseudorandState == 0) sPseudorandState = BOOTINFO_MAGIC; // why not reuse "termOS"?
|
||||
}
|
||||
|
||||
static UInt64 RandXorshift() {
|
||||
UInt64 x = sPseudorandState;
|
||||
x ^= x << 13;
|
||||
x ^= x >> 7;
|
||||
x ^= x << 17;
|
||||
return sPseudorandState = x;
|
||||
}
|
||||
|
||||
static bool RandHardware(UInt64 *value) {
|
||||
UInt8 ok;
|
||||
__asm__ volatile ("rdrand %0; setc %1"
|
||||
: "=r" (*value), "=qm" (ok));
|
||||
return ok != 0;
|
||||
}
|
||||
|
||||
UInt64 Rand() {
|
||||
UInt64 result;
|
||||
if (OSCPUHasFeature(kCPUFeatureRDRAND)) {
|
||||
if (RandHardware(&result)) return result;
|
||||
}
|
||||
|
||||
return RandXorshift();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
#include <IO/IOGraphics.h>
|
||||
#include <IO/IOConsole.h>
|
||||
|
||||
#include <Data/logo.h>
|
||||
|
||||
void SplashShow(IOGraphicsContext* IOGraphicsContextPointer) {
|
||||
IOGraphicsPoint logoPoint = {0, 10};
|
||||
IOGraphicsPoint startPoint = {75, 55}; // greeting
|
||||
IOGraphicsPoint normalTextPoint = {0, 120}; // not nice to hardcode nums like that but we have what we have
|
||||
|
||||
IOGraphicsDrawImage(IOGraphicsContextPointer, &logoPoint, &logoImage);
|
||||
IOConsoleSetCursorPosition(&startPoint);
|
||||
IOConsoleLog("Welcome to ^ptermOS^!!!!\n");
|
||||
|
||||
IOConsoleSetCursorPosition(&normalTextPoint);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user