10 Commits

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

* Added Garbage Collector for tasks

* Moved Getchar to IOKeyboard with locking

* Cleanup panic messages
2026-01-31 20:50:27 +04:00
Karina ee67cef4f8 ref: initramfs -> StartupVolume; /bin -> /System/CoreServices;
ref(Kernel/VM/Heap): malloc -> VMHeapAllocate; free -> VMHeapFree; realloc -> VMHeapResize
2026-01-31 16:11:45 +04:00
Karina c30d57d06e fix(ksh/regs): now it doesnt panic when typing regs in ksh
fix(kmain): Now Dewar correctly OSPanic()'s instead of returnin IOConsoleLog when no framebuffer found
2026-01-31 02:49:34 +04:00
Karina 4e6794a6c2 chore: update copyrights 2026-01-31 01:57:28 +04:00
113 changed files with 1398 additions and 915 deletions
+4
View File
@@ -0,0 +1,4 @@
If:
PathMatch: .*\.h
CompileFlags:
Add: [-x, objective-c]
+2 -1
View File
@@ -5,4 +5,5 @@ kernel/data
*.md
bootloader/
bootloader/src/uefi
initramfs/
initramfs/
kernel/inc/Data
+18 -13
View File
@@ -30,23 +30,28 @@ add_subdirectory(bootloader)
add_subdirectory(kernel)
add_subdirectory(userspace)
set(SYSTEM_SERVICES
init
debug
termosh
testOBJC
)
set(VOLUME_ROOT "${CMAKE_BINARY_DIR}/StartupVolume")
set(INITRAMFS_CPIO_FILE "${CMAKE_BINARY_DIR}/StartupVolume.cpio")
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
set(IMG_FILE "${CMAKE_BINARY_DIR}/termOS.img")
set(INITRAMFS_SRC_DIR "${CMAKE_SOURCE_DIR}/initramfs")
set(INITRAMFS_CPIO_FILE "${CMAKE_BINARY_DIR}/initramfs.cpio")
file(GLOB_RECURSE INIT_FILES "${INITRAMFS_SRC_DIR}/*")
add_custom_command(
add_custom_command(
OUTPUT ${INITRAMFS_CPIO_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${VOLUME_ROOT}
COMMAND sh -c "find . -mindepth 1 ! -name '*.cpio' -print0 | ${CPIO_EXE} --null -ov -H newc > \"${INITRAMFS_CPIO_FILE}\""
WORKING_DIRECTORY ${INITRAMFS_SRC_DIR}
DEPENDS ${INIT_FILES} init debug termosh
WORKING_DIRECTORY ${VOLUME_ROOT}
DEPENDS ${SYSTEM_SERVICES}
VERBATIM
COMMENT "Packing initramfs to cpio..."
COMMENT "Packing StartupVolume to cpio..."
)
add_custom_command(
OUTPUT ${IMG_FILE}
COMMAND dd if=/dev/zero of=${IMG_FILE} bs=1M count=64 status=none
@@ -54,7 +59,7 @@ if(MCOPY_EXE AND MKFS_EXE AND CPIO_EXE)
COMMAND mmd -i ${IMG_FILE} ::/EFI ::/EFI/BOOT
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} $<TARGET_FILE:BOOTX64> ::/EFI/BOOT/BOOTX64.EFI
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} ${CMAKE_BINARY_DIR}/bin/kernel.bin ::/kernel.bin
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} ${INITRAMFS_CPIO_FILE} ::/initramfs.cpio
COMMAND ${MCOPY_EXE} -i ${IMG_FILE} ${INITRAMFS_CPIO_FILE} ::/StartupVolume.cpio
DEPENDS BOOTX64 kernel ${INITRAMFS_CPIO_FILE}
VERBATIM
COMMENT "Generating bootable image: ${IMG_FILE}"
+3 -3
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include "uefi.h" // IWYU pragma: keep
#include "../../common/bootinfo.h"
@@ -78,10 +78,10 @@ int main()
efi_file_handle_t* initramfs_file;
uintn_t iinfo_size = 0;
efi_file_info_t* ifile_info = nullptr;
status = root->Open(root, &initramfs_file, L"initramfs.cpio", EFI_FILE_MODE_READ, 0);
status = root->Open(root, &initramfs_file, L"StartupVolume.cpio", EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(status)) {
print_initramfs_warning(L"initramfs.cpio is missing");
print_initramfs_warning(L"StartupVolume.cpio is missing");
boot_info->initramfs.address = nullptr;
boot_info->initramfs.size = 0;
} else {
+11 -11
View File
@@ -46,7 +46,7 @@ void __stdio_cleanup(void)
BS->FreePool(__argvutf8);
#endif
if(__blk_devs) {
free(__blk_devs);
MemoryFree(__blk_devs);
__blk_devs = NULL;
__blk_ndevs = 0;
}
@@ -127,7 +127,7 @@ int fclose (FILE *__stream)
if(__stream == (FILE*)__blk_devs[i].bio)
return 1;
status = __stream->Close(__stream);
free(__stream);
MemoryFree(__stream);
return !EFI_ERROR(status);
}
@@ -188,7 +188,7 @@ err: __stdio_seterrno(status);
return -1;
}
/* no need for fclose(f); */
free(f);
MemoryFree(f);
return 0;
}
@@ -250,7 +250,7 @@ FILE *fopen (const char_t *__filename, const char_t *__modes)
/* workaround a bug in TianoCore, it reports zero size even though the data is in the buffer */
if(handle_size < 1)
handle_size = (uintn_t)sizeof(handles) / sizeof(efi_handle_t);
__blk_devs = (block_file_t*)malloc(handle_size * sizeof(block_file_t));
__blk_devs = (block_file_t*)MemoryAllocate(handle_size * sizeof(block_file_t));
if(__blk_devs) {
memset(__blk_devs, 0, handle_size * sizeof(block_file_t));
for(i = __blk_ndevs = 0; i < handle_size; i++)
@@ -276,7 +276,7 @@ FILE *fopen (const char_t *__filename, const char_t *__modes)
errno = ENODEV;
return NULL;
}
ret = (FILE*)malloc(sizeof(FILE));
ret = (FILE*)MemoryAllocate(sizeof(FILE));
if(!ret) return NULL;
/* normally write means read,write,create. But for remove (internal '*' mode), we need read,write without create
* also mode 'w' in POSIX means write-only (without read), but that's not working on certain firmware, we must
@@ -292,16 +292,16 @@ FILE *fopen (const char_t *__filename, const char_t *__modes)
__modes[1] == CL('d') ? EFI_FILE_DIRECTORY : 0);
if(EFI_ERROR(status)) {
err: __stdio_seterrno(status);
free(ret); return NULL;
MemoryFree(ret); return NULL;
}
if(__modes[0] == CL('*')) return ret;
status = ret->GetInfo(ret, &infGuid, &fsiz, &info);
if(EFI_ERROR(status)) goto err;
if(__modes[1] == CL('d') && !(info.Attribute & EFI_FILE_DIRECTORY)) {
ret->Close(ret); free(ret); errno = ENOTDIR; return NULL;
ret->Close(ret); MemoryFree(ret); errno = ENOTDIR; return NULL;
}
if(__modes[1] != CL('d') && (info.Attribute & EFI_FILE_DIRECTORY)) {
ret->Close(ret); free(ret); errno = EISDIR; return NULL;
ret->Close(ret); MemoryFree(ret); errno = EISDIR; return NULL;
}
if(__modes[0] == CL('a')) fseek(ret, 0, SEEK_END);
if(__modes[0] == CL('w')) {
@@ -713,7 +713,7 @@ int sprintf(char_t *dst, const char_t* fmt, ...)
return ret;
}
int snprintf(char_t *dst, size_t maxlen, const char_t* fmt, ...)
int StringFormat(char_t *dst, size_t maxlen, const char_t* fmt, ...)
{
int ret;
__builtin_va_list args;
@@ -738,7 +738,7 @@ int vprintf(const char_t* fmt, __builtin_va_list args)
return ret;
}
int printf(const char_t* fmt, ...)
int ConsolePrint(const char_t* fmt, ...)
{
int ret;
__builtin_va_list args;
@@ -800,7 +800,7 @@ int getchar_ifany (void)
return EFI_ERROR(status) ? 0 : key.UnicodeChar;
}
int getchar (void)
int ConsoleGetCharacter (void)
{
uintn_t idx;
BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &idx);
+7 -7
View File
@@ -77,7 +77,7 @@ int64_t strtol (const char_t *s, char_t **__endptr, int __base)
return v * sign;
}
void *malloc (size_t __size)
void *MemoryAllocate (size_t __size)
{
void *ret = NULL;
efi_status_t status;
@@ -106,20 +106,20 @@ void *malloc (size_t __size)
void *calloc (size_t __nmemb, size_t __size)
{
void *ret = malloc(__nmemb * __size);
void *ret = MemoryAllocate(__nmemb * __size);
if(ret) memset(ret, 0, __nmemb * __size);
return ret;
}
void *realloc (void *__ptr, size_t __size)
void *MemoryReallocate (void *__ptr, size_t __size)
{
void *ret = NULL;
efi_status_t status;
#ifndef UEFI_NO_TRACK_ALLOC
uintn_t i;
#endif
if(!__ptr) return malloc(__size);
if(!__size) { free(__ptr); return NULL; }
if(!__ptr) return MemoryAllocate(__size);
if(!__size) { MemoryFree(__ptr); return NULL; }
#ifndef UEFI_NO_TRACK_ALLOC
/* get the slot which stores the old size for this buffer */
for(i = 0; i < __stdlib_numallocs && __stdlib_allocs[i] != (uintptr_t)__ptr; i += 2);
@@ -145,7 +145,7 @@ void *realloc (void *__ptr, size_t __size)
return ret;
}
void free (void *__ptr)
void MemoryFree (void *__ptr)
{
efi_status_t status;
#ifndef UEFI_NO_TRACK_ALLOC
@@ -341,7 +341,7 @@ uint8_t *getenv(char_t *name, uintn_t *len)
#else
status = RT->GetVariable(name, &globGuid, &attr, len, &tmp);
#endif
if(EFI_ERROR(status) || *len < 1 || !(ret = malloc((*len) + 1))) {
if(EFI_ERROR(status) || *len < 1 || !(ret = MemoryAllocate((*len) + 1))) {
*len = 0;
return NULL;
}
+2 -2
View File
@@ -116,7 +116,7 @@ void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl)
return NULL;
}
char_t *strcpy(char_t *dst, const char_t *src)
char_t *StringCopy(char_t *dst, const char_t *src)
{
char_t *s = dst;
if(src && dst && src != dst) {
@@ -178,7 +178,7 @@ int strncmp(const char_t *s1, const char_t *s2, size_t n)
char_t *strdup(const char_t *s)
{
size_t i = (strlen(s)+1) * sizeof(char_t);
char_t *s2 = (char_t *)malloc(i);
char_t *s2 = (char_t *)MemoryAllocate(i);
if(s2 != NULL) memcpy(s2, (const void*)s, i);
return s2;
}
+7 -7
View File
@@ -1314,10 +1314,10 @@ typedef int (*__compar_fn_t) (const void *, const void *);
extern int atoi (const char_t *__nptr);
extern int64_t atol (const char_t *__nptr);
extern int64_t strtol (const char_t *__nptr, char_t **__endptr, int __base);
extern void *malloc (size_t __size);
extern void *MemoryAllocate (size_t __size);
extern void *calloc (size_t __nmemb, size_t __size);
extern void *realloc (void *__ptr, size_t __size);
extern void free (void *__ptr);
extern void *MemoryReallocate (void *__ptr, size_t __size);
extern void MemoryFree (void *__ptr);
extern void abort (void);
extern void exit (int __status);
/* exit Boot Services function. Returns 0 on success. */
@@ -1355,14 +1355,14 @@ extern int fseek (FILE *__stream, long int __off, int __whence);
extern long int ftell (FILE *__stream);
extern int feof (FILE *__stream);
extern int fprintf (FILE *__stream, const char_t *__format, ...);
extern int printf (const char_t *__format, ...);
extern int ConsolePrint (const char_t *__format, ...);
extern int sprintf (char_t *__s, const char_t *__format, ...);
extern int vfprintf (FILE *__s, const char_t *__format, __builtin_va_list __arg);
extern int vprintf (const char_t *__format, __builtin_va_list __arg);
extern int vsprintf (char_t *__s, const char_t *__format, __builtin_va_list __arg);
extern int snprintf (char_t *__s, size_t __maxlen, const char_t *__format, ...);
extern int StringFormat (char_t *__s, size_t __maxlen, const char_t *__format, ...);
extern int vsnprintf (char_t *__s, size_t __maxlen, const char_t *__format, __builtin_va_list __arg);
extern int getchar (void);
extern int ConsoleGetCharacter (void);
/* non-blocking, only returns UNICODE if there's any key pressed, 0 otherwise */
extern int getchar_ifany (void);
extern int putchar (int __c);
@@ -1376,7 +1376,7 @@ extern void *memchr(const void *__s, int __c, size_t __n);
extern void *memrchr(const void *__s, int __c, size_t __n);
void *memmem(const void *haystack, size_t hl, const void *needle, size_t nl);
void *memrmem(const void *haystack, size_t hl, const void *needle, size_t nl);
extern char_t *strcpy (char_t *__dest, const char_t *__src);
extern char_t *StringCopy (char_t *__dest, const char_t *__src);
extern char_t *strncpy (char_t *__dest, const char_t *__src, size_t __n);
extern char_t *strcat (char_t *__dest, const char_t *__src);
extern char_t *strncat (char_t *__dest, const char_t *__src, size_t __n);
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
+1 -1
View File
@@ -24,7 +24,7 @@ file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
"src/lib/*.c"
"src/IO/*.c"
"src/VM/*.c"
"src/shell/*.c"
"src/KSH/*.c"
"src/FS/*.c"
"Data/*.c"
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
// cats licensed to their authors
// i took it from https://www.asciiart.eu/animals/cats
+1 -1
View File
@@ -1,6 +1,6 @@
// Huge thanks to https://t.me/kinolenta2004 for this amazing logo
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
+1 -2
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
@@ -29,7 +29,6 @@ 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);
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
// RIP shitgui -- you started it all
#pragma once
+8 -5
View File
@@ -1,19 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#include <OS/OSSpinlock.h>
enum {
kIOKeyboardBufferSize = 256,
};
typedef struct {
OSSpinlock lock;
char buffer[kIOKeyboardBufferSize];
UInt16 head;
UInt16 tail;
} IOKeyboardBuffer;
volatile UInt16 head;
volatile UInt16 tail;
} IOKeyboardController;
extern IOKeyboardBuffer gIOKeyboardInputBuffer;
extern IOKeyboardController gIOKeyboardController;
void IOKeyboardInterruptsHandler();
char IOKeyboardGetCharacter();
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
@@ -2,7 +2,5 @@
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
Int32 spawn(const char* path);
Int32 wait(UInt64 pid);
void KSHEntry();
-24
View File
@@ -1,24 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
#include <types.h>
#define KERNEL_HEAP_START 0xFFFFFFFFC0000000
#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START)
#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START)
#define HEADER_MAGIC 0x1CE
typedef struct VMHeapBlockHeader {
UInt64 magic;
struct VMHeapBlockHeader* next;
struct VMHeapBlockHeader* previous;
UInt64 size;
bool isFree;
} block_header;
void VMHeapInitialize();
void* malloc(UInt64 size);
void free(void* ptr);
void* realloc(void* ptr, UInt64 new_size);
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
+2 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
@@ -29,6 +29,7 @@ typedef struct OSTask {
UInt32 sleepTicks;
OSProcessState taskState; // reusing process_state cuz wn
UInt64 kernelStackTop;
void* kernelStackBase;
OSProcess* process;
Int32 waitingForProcess;
} OSTask;
+19
View File
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef struct OSSpinlock {
volatile UInt32 lockValue;
} OSSpinlock;
typedef struct OSSpinlockState {
Boolean interruptsEnabled;
} OSSpinlockState;
void OSSpinlockLock(OSSpinlock* lock);
void OSSpinlockUnlock(OSSpinlock* lock);
void OSSpinlockLockIRQ(OSSpinlock* lock, OSSpinlockState* state);
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState* state);
+2 -2
View File
@@ -4,5 +4,5 @@
#pragma once
#include <types.h>
UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length);
UInt64 OSServiceRead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count);
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length);
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count);
+1 -1
View File
@@ -4,4 +4,4 @@
#pragma once
#include <types.h>
UInt64 OSServiceMemoryGet(UInt64 size);
UInt64 OSServiceMemoryAllocate(UInt64 size);
+6 -8
View File
@@ -1,19 +1,17 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
enum {
kVMKernelHeapStart = 0xFFFFFFFFC0000000,
kVMHeapSizePages = 1024
kVMHeapSizePages = 1024,
kVMHeapBlockHeaderMagic = 0x1CE
};
#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;
@@ -23,6 +21,6 @@ typedef struct VMHeapBlockHeader {
} VMHeapBlockHeader;
void VMHeapInitialize();
void* malloc(UInt64 size);
void free(void* ptr);
void* realloc(void* ptr, UInt64 newSize);
void* VMHeapAllocate(UInt64 size);
void VMHeapFree(void* ptr);
void* VMHeapResize(void* ptr, UInt64 newSize);
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include "bootinfo.h"
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include "bootinfo.h"
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <IO/IOGraphics.h>
+8 -7
View File
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 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);
void* MemorySet(void* destination, UInt8 value, UInt64 count);
void* MemoryCopy(void* destination, const void* source, UInt64 count);
Int32 StringCompare(const char* firstString, const char* secondString);
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit);
char* StringCopy(char* destination, const char* source);
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit);
UInt64 StringGetLength(const char* string);
-6
View File
@@ -1,6 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
#pragma once
void ksh();
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
+1 -1
View File
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
Copyright (c) 2025 0xKarinyash */
Copyright (c) 2026 0xKarinyash */
ENTRY(_start)
+10 -10
View File
@@ -51,7 +51,7 @@ 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);
MemoryCopy(buffer, (char*)node->implementationData + offset, size);
return size;
}
@@ -59,11 +59,11 @@ FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize) {
UInt8* currentPointer = (UInt8*)baseAddress;
UInt8* endPointer = currentPointer + totalSize;
FSVNode* rootNode = (FSVNode*)malloc(sizeof(FSVNode));
FSVNode* rootNode = (FSVNode*)VMHeapAllocate(sizeof(FSVNode));
if (!rootNode) OSPanic("CPIO: Failed to allocate memory for root node");
memset(rootNode, 0, sizeof(FSVNode));
strcpy(rootNode->name, "/");
MemorySet(rootNode, 0, sizeof(FSVNode));
StringCopy(rootNode->name, "/");
rootNode->flags = kFSVNodeFlagDirectory;
rootNode->operations = &gFSCPIOOperations;
@@ -72,25 +72,25 @@ FSVNode* FSCPIOMount(void* baseAddress, UInt64 totalSize) {
while (currentPointer < endPointer) {
FSCPIOHeader* header = (FSCPIOHeader*)currentPointer;
if (strncmp(header->magic, "070701", 6) != 0) {
OSPanic("CPIO: Invalid magic detected in initramfs");
if (StringCompareWithLimit(header->magic, "070701", 6) != 0) {
OSPanic("CPIO: Invalid magic detected in StartupVolume");
}
UInt64 nameSize = sFSCPIOHexadecimalToUInt64(header->nameLength, 8);
UInt64 fileSize = sFSCPIOHexadecimalToUInt64(header->fileLength, 8);
char* fileName = (char*)(currentPointer + sizeof(FSCPIOHeader));
if (strcmp(fileName, "TRAILER!!!") == 0) break;
if (StringCompare(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));
FSVNode* newNode = (FSVNode*)VMHeapAllocate(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);
MemorySet(newNode, 0, sizeof(FSVNode));
StringCopyWithLimit(newNode->name, fileName, sizeof(newNode->name) - 1);
newNode->dataLength = fileSize;
newNode->inodeIdentifier = sFSCPIOHexadecimalToUInt64(header->inode, 8);
+2 -2
View File
@@ -23,7 +23,7 @@ FSVNode* FSVirtualFileSystemOpenPath(const char* path) {
return nullptr;
}
if (strcmp(path, "/") == 0) {
if (StringCompare(path, "/") == 0) {
return gFSVirtualFileSystemRoot;
}
@@ -34,7 +34,7 @@ FSVNode* FSVirtualFileSystemOpenPath(const char* path) {
FSVNode* nodeIterator = gFSVirtualFileSystemRoot->childNode;
while (nodeIterator != nullptr) {
if (strcmp(nodeIterator->name, searchName) == 0) {
if (StringCompare(nodeIterator->name, searchName) == 0) {
if (nodeIterator->operations && nodeIterator->operations->open) {
nodeIterator->operations->open(nodeIterator);
}
+2 -11
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IO/IOConsole.h>
#include <IO/IOSerial.h>
@@ -238,19 +238,10 @@ 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();
char character = IOKeyboardGetCharacter();
switch (character) {
case '\n': {
buffer[i] = '\0';
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
// RIP shitgui -- you started it all
#include <OS/OSScheduler.h>
+32 -6
View File
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IO/IOKeyboard.h>
#include <IO/IOConsole.h>
#include <OS/OSSpinlock.h>
#include <OS/OSScheduler.h>
#include <IO.h>
#include <types.h>
@@ -87,19 +89,20 @@ static unsigned char sIOKeyboardMapShifted[128] = {
static Boolean sIOKeyboardIsShiftPressed = false;
IOKeyboardBuffer gIOKeyboardInputBuffer = {0};
IOKeyboardController gIOKeyboardController = {0};
void IOKeyboardInterruptsHandler() {
UInt16 nextHead = (gIOKeyboardInputBuffer.head + 1) % kIOKeyboardBufferSize;
OSSpinlockLock(&gIOKeyboardController.lock);
UInt16 nextHead = (gIOKeyboardController.head + 1) % kIOKeyboardBufferSize;
UInt8 scancode = IOPortRead8(0x60);
// make code 0x00 - 0x7F; break code = make code + 0x80
if (scancode < 0x80) {
unsigned char* keyMap = sIOKeyboardIsShiftPressed ? sIOKeyboardMapShifted : sIOKeyboardMap;
char ascii = keyMap[scancode];
if (ascii && nextHead != gIOKeyboardInputBuffer.tail) {
gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.head] = ascii;
gIOKeyboardInputBuffer.head = nextHead;
if (ascii && nextHead != gIOKeyboardController.tail) {
gIOKeyboardController.buffer[gIOKeyboardController.head] = ascii;
gIOKeyboardController.head = nextHead;
} else {
switch (scancode) {
case 0x2A: sIOKeyboardIsShiftPressed = true; break;
@@ -112,4 +115,27 @@ void IOKeyboardInterruptsHandler() {
default: break;
}
}
OSSpinlockUnlock(&gIOKeyboardController.lock);
}
char IOKeyboardGetCharacter() {
char ascii = 0;
OSSpinlockState state;
while (true) {
OSSpinlockLockIRQ(&gIOKeyboardController.lock, &state);
if (gIOKeyboardController.head != gIOKeyboardController.tail) {
ascii = gIOKeyboardController.buffer[gIOKeyboardController.tail];
gIOKeyboardController.tail = (gIOKeyboardController.tail + 1) % kIOKeyboardBufferSize;
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
return ascii;
}
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
__asm__ volatile ("sti");
OSSchedulerYield(1);
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IO/IOSerial.h>
#include <IO.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IO/IOTimer.h>
#include <IO.h>
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <types.h>
#include <OSCPU.h>
@@ -15,7 +15,7 @@
#include <VM/VMM.h>
#include <VM/Heap.h>
#include <shell/dbgcmd.h>
#include <KSH/KSHDebug.h>
#include <Data/cats.h>
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <shell/dbgcmd.h>
#include <KSH/KSHDebug.h>
#include <IO/IOConsole.h>
UInt64 KSHDebug() {
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <shell/ksh.h>
#include <shell/builtins.h>
#include <KSH/KSHEntry.h>
#include <KSH/KSHBuiltins.h>
#include <IO/IOConsole.h>
#include <IO/IOGraphics.h>
@@ -72,19 +72,19 @@ static const KSHCommandMap CommandMap[] = {
{nullptr, TOKEN_NULL}
};
KSHToken char2token(char* token) {
KSHToken KSHCharacter2Token(char* token) {
for (Int32 i = 0; CommandMap[i].str != nullptr; i++) {
if (strcmp(token, CommandMap[i].str) == 0) return CommandMap[i].token;
if (StringCompare(token, CommandMap[i].str) == 0) return CommandMap[i].token;
}
return TOKEN_ILLEGAL;
}
void ksh() {
void KSHEntry() {
while (true) {
IOConsoleLog("ksh_> ");
char cmdbuff[256];
IOConsoleReadLine(cmdbuff, 256);
switch(char2token(cmdbuff)) {
switch(KSHCharacter2Token(cmdbuff)) {
case TOKEN_EMPTY: continue;
case TOKEN_CLEAR: IOConsoleClear((UInt32) IOConsoleGetColors() & 0xFFFFFFFF); break;
+2 -2
View File
@@ -29,7 +29,7 @@ UInt64 HOTLoad(OSProcess* process, UInt8* data) {
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);
MemorySet(kernelVirtAddress, 0, kVMPageSize);
UInt64 pageOverleapStart = (address > segment->vaddr) ? address : segment->vaddr;
UInt64 pageOverleapEnd = (address + kVMPageSize < segment->vaddr + segment->filesz)
? (address + kVMPageSize)
@@ -39,7 +39,7 @@ UInt64 HOTLoad(OSProcess* process, UInt8* data) {
UInt64 sourceOffset = segment->offset + (pageOverleapStart - segment->vaddr);
UInt64 destinationOffset = pageOverleapStart - address;
memcpy((UInt8*)kernelVirtAddress + destinationOffset, data + sourceOffset, copySize);
MemoryCopy((UInt8*)kernelVirtAddress + destinationOffset, data + sourceOffset, copySize);
}
}
}
+14 -11
View File
@@ -31,22 +31,22 @@ Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName)
return -1;
}
OSProcess* newProcess = (OSProcess*)malloc(sizeof(OSProcess));
OSProcess* newProcess = (OSProcess*)VMHeapAllocate(sizeof(OSProcess));
if (!newProcess) {
return -2;
}
memset(newProcess, 0, sizeof(OSProcess));
MemorySet(newProcess, 0, sizeof(OSProcess));
newProcess->processId = gOSSchedulerNextProcessID++;
newProcess->state = kOSProcessStateRunning;
newProcess->physicalPML4 = VMVirtualMemoryCreateAddressSpace();
newProcess->heapStartPointer = kOSHeapStart;
newProcess->heapCurrentPointer = kOSHeapStart;
strncpy(newProcess->name, processName, 31);
StringCopyWithLimit(newProcess->name, processName, 31);
UInt8* imageBuffer = (UInt8*)malloc(executableFile->dataLength);
UInt8* imageBuffer = (UInt8*)VMHeapAllocate(executableFile->dataLength);
if (!imageBuffer) {
free(newProcess);
VMHeapFree(newProcess);
return -3;
}
@@ -54,24 +54,27 @@ Int32 OSLoaderProcessSpawn(const char* executablePath, const char* processName)
UInt64 entryPoint = HOTLoad(newProcess, imageBuffer);
if (!entryPoint) {
free(imageBuffer);
free(newProcess);
VMHeapFree(imageBuffer);
VMHeapFree(newProcess);
return -4;
}
free(imageBuffer);
VMHeapFree(imageBuffer);
VMVirtualMemorySetupUserStack((UInt64*)newProcess->physicalPML4);
OSSchedulerSpawn((void(*)())entryPoint, newProcess, true, kOSUserStackTop);
if (!OSSchedulerSpawn((void(*)())entryPoint, newProcess, true, kOSUserStackTop)) {
VMHeapFree(newProcess);
return -5;
}
return newProcess->processId;
}
void init_task_entry() {
Int32 pid = OSLoaderProcessSpawn("/bin/init", "init");
Int32 pid = OSLoaderProcessSpawn("/System/CoreServices/init", "init");
if (pid < 0) {
OSPanic("FATAL: Failed to spawn /bin/init");
OSPanic("FATAL: Failed to spawn /System/CoreServices/init");
}
while (1) { __asm__("sti; hlt"); }
+1 -3
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <OS/OSPanic.h>
#include <lib/Rand.h>
@@ -35,8 +35,6 @@ static const char* sOSPanicFunMessages[] = {
"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",
+94 -14
View File
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <OS/OSSpinlock.h>
#include <OS/OSPanic.h>
#include <lib/String.h>
#include <VM/Heap.h>
#include <VM/VMM.h>
@@ -16,6 +17,9 @@ extern void irq0_handler();
extern UInt64 gVMKernelPML4Physical;
static OSProcess sOSSchedulerKernelProcess;
static OSSpinlock sOSSchedulerLock;
static OSTask* sOSSchedulerGarbageCollectorTask = nullptr;
void idle_task() {
while (1) {
@@ -23,14 +27,61 @@ void idle_task() {
}
}
void OSSchedulerGarbageCollector() {
OSTask* self = gOSSchedulerCurrentTask;
while (true) {
OSTask* previousTask = self;
OSTask* nextTask = previousTask->next;
while (nextTask != self) {
if (nextTask->taskState == kOSProcessStateDead) {
OSSpinlockState lockState;
OSSpinlockLockIRQ(&sOSSchedulerLock, &lockState);
previousTask->next = nextTask->next;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &lockState);
if (nextTask->kernelStackBase) {
VMHeapFree(nextTask->kernelStackBase);
}
VMHeapFree(nextTask);
nextTask = previousTask->next;
} else {
previousTask = nextTask;
nextTask = nextTask->next;
}
}
OSSchedulerYield(200);
}
}
static void sOSSchedulerPostGarbageCollectorSignal() {
if (!sOSSchedulerGarbageCollectorTask) return;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
sOSSchedulerGarbageCollectorTask->taskState = kOSProcessStateRunning;
sOSSchedulerGarbageCollectorTask->sleepTicks = 0;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerInitialize() {
sOSSchedulerKernelProcess.processId = 0;
sOSSchedulerKernelProcess.state = kOSProcessStateRunning;
sOSSchedulerKernelProcess.physicalPML4 = gVMKernelPML4Physical;
strcpy(sOSSchedulerKernelProcess.name, "kernel");
StringCopy(sOSSchedulerKernelProcess.name, "kernel");
OSTask* kernelTask = (OSTask*)VMHeapAllocate(sizeof(OSTask));
if (!kernelTask) OSPanic("Failed to initialize scheduler: OOm");
MemorySet(kernelTask, 0, sizeof(OSTask));
OSTask* kernelTask = (OSTask*)malloc(sizeof(OSTask));
memset(kernelTask, 0, sizeof(OSTask));
kernelTask->id = 0;
kernelTask->process = &sOSSchedulerKernelProcess;
kernelTask->sleepTicks = 0;
@@ -40,16 +91,26 @@ void OSSchedulerInitialize() {
gOSSchedulerCurrentTask = kernelTask;
OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0);
sOSSchedulerGarbageCollectorTask = OSSchedulerSpawn(OSSchedulerGarbageCollector, &sOSSchedulerKernelProcess, false, 0);
return;
}
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) {
OSTask* task = (OSTask*)malloc(sizeof(OSTask));
OSTask* task = (OSTask*)VMHeapAllocate(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");
UInt8* stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
if (!stackBaseAddress) {
sOSSchedulerPostGarbageCollectorSignal();
OSSchedulerYield(0);
stackBaseAddress = (UInt8*)VMHeapAllocate(stackSize);
if (!stackBaseAddress) {
VMHeapFree(task);
return nullptr;
}
}
UInt64* rsp = (UInt64*)(stackBaseAddress + stackSize);
UInt64 cs = isUser ? 0x23 : 0x08;
@@ -74,17 +135,27 @@ OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt6
task->process = owner;
task->id = owner->processId;
task->sleepTicks = 0;
task->next = gOSSchedulerCurrentTask->next;
task->kernelStackTop = (UInt64)stackBaseAddress + stackSize;
task->kernelStackBase = stackBaseAddress;
task->taskState = kOSProcessStateRunning;
task->waitingForProcess = -1;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
task->next = gOSSchedulerCurrentTask->next;
gOSSchedulerCurrentTask->next = task;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
return task;
}
UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
if (!gOSSchedulerCurrentTask) return currentStackPointer;
OSSpinlockLock(&sOSSchedulerLock);
gOSSchedulerCurrentTask->stackPointer = currentStackPointer;
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
@@ -95,12 +166,12 @@ UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
OSTask* nextTask = gOSSchedulerCurrentTask;
OSTask* nextTask = gOSSchedulerCurrentTask->next;
while (1) {
// TODO: add gc here;
nextTask = nextTask->next;
if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning;
if (nextTask->taskState == kOSProcessStateRunning) break;
nextTask = nextTask->next;
if (nextTask == gOSSchedulerCurrentTask) {
if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break;
OSPanic("no running tasks");
@@ -111,6 +182,8 @@ UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
gOSSchedulerCurrentTask = nextTask;
gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop;
gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop;
OSSpinlockUnlock(&sOSSchedulerLock);
return gOSSchedulerCurrentTask->stackPointer;
}
@@ -121,6 +194,9 @@ void OSSchedulerBlock(UInt32 processID) {
}
void OSSchedulerWakeup(UInt32 processID) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
OSTask* iteratorTask = gOSSchedulerCurrentTask;
do {
if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) {
@@ -129,18 +205,22 @@ void OSSchedulerWakeup(UInt32 processID) {
}
iteratorTask = iteratorTask->next;
} while (iteratorTask != gOSSchedulerCurrentTask);
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerTerminate() {
UInt32 processID = gOSSchedulerCurrentTask->id;
gOSSchedulerCurrentTask->taskState = kOSProcessStateDead;
OSSchedulerWakeup(processID);
sOSSchedulerPostGarbageCollectorSignal();
__asm__ volatile("int $32");
}
void OSSchedulerYield(UInt64 ticks) {
gOSSchedulerCurrentTask->sleepTicks = ticks;
gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping;
__asm__ volatile("hlt");
}
__asm__ volatile("int $32");
}
+29
View File
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSSpinlock.h>
void OSSpinlockLock(OSSpinlock* lock) {
while (__atomic_exchange_n(&lock->lockValue, 1, __ATOMIC_ACQUIRE)) {
while (lock->lockValue) {
__builtin_ia32_pause();
}
}
}
void OSSpinlockUnlock(OSSpinlock *lock) {
__atomic_store_n(&lock->lockValue, 0, __ATOMIC_RELEASE);
}
void OSSpinlockLockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
UInt64 rflags;
__asm__ volatile("pushfq; pop %0; cli" : "=r"(rflags) :: "memory"); // read flags and cli
state->interruptsEnabled = (rflags & (1 << 9)) != 0; // IF bit
OSSpinlockLock(lock);
}
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
OSSpinlockUnlock(lock);
if (state->interruptsEnabled) __asm__ volatile("sti" ::: "memory");
}
+4 -3
View File
@@ -3,8 +3,9 @@
#include <OS/Services/OSServiceIO.h>
#include <IO/IOConsole.h>
#include <IO/IOKeyboard.h>
UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
UInt64 OSServiceIOWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
if (fileDescriptor == 1 || fileDescriptor == 2) {
char* string = (char*)buffer;
for (UInt64 i = 0; i < length; i++) {
@@ -15,11 +16,11 @@ UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
return 0;
}
UInt64 OSServiceRead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
UInt64 OSServiceIORead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
char* readBuffer = (char*)buffer;
if (fileDescriptor == 0) {
for (UInt64 i = 0; i < count; i++) {
readBuffer[i] = IOConsoleGetCharacter();
readBuffer[i] = IOKeyboardGetCharacter();
}
return count;
}
+2 -2
View File
@@ -9,7 +9,7 @@
#include <VM/VMM.h>
#include <lib/String.h>
UInt64 OSServiceMemoryGet(UInt64 size) {
UInt64 OSServiceMemoryAllocate(UInt64 size) {
if (size == 0) return 0;
OSProcess* currentProcess = gOSSchedulerCurrentTask->process;
UInt64 addressToReturn = currentProcess->heapCurrentPointer;
@@ -21,7 +21,7 @@ UInt64 OSServiceMemoryGet(UInt64 size) {
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);
MemorySet((void*)PHYS_TO_HHDM((UInt64)phycialAddress), 0, kVMPageSize);
currentProcess->heapCurrentPointer += kVMPageSize;
}
+50 -22
View File
@@ -1,17 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <VM/Heap.h>
#include <VM/PMM.h>
#include <VM/VMM.h>
#include <lib/String.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
extern UInt64* gVMKernelPML4;
static VMHeapBlockHeader* sVMHeapListHead = nullptr;
static OSSpinlock sVMHeapLock = {0};
void combine_forward(VMHeapBlockHeader* current) {
static void sVMHeapCombineForward(VMHeapBlockHeader* current) {
if (!current->next || !current->next->isFree) return;
current->size += sizeof(VMHeapBlockHeader) + current->next->size;
current->next = current->next->next;
@@ -30,14 +32,14 @@ void VMHeapInitialize() {
}
sVMHeapListHead = (VMHeapBlockHeader*)heapStart;
sVMHeapListHead->magic = HEADER_MAGIC;
sVMHeapListHead->magic = kVMHeapBlockHeaderMagic;
sVMHeapListHead->size = (kVMHeapSizePages * kVMPageSize) - sizeof(VMHeapBlockHeader);
sVMHeapListHead->isFree = true;
sVMHeapListHead->next = nullptr;
sVMHeapListHead->previous = nullptr;
}
void* malloc(UInt64 size) {
static void* sVMHeapAllocateInternal(UInt64 size) {
if (size == 0) return nullptr;
UInt64 alignedSize = (size + 15) & ~15;
@@ -50,7 +52,7 @@ void* malloc(UInt64 size) {
new_block->isFree = true;
new_block->next = current->next;
new_block->previous = current;
new_block->magic = HEADER_MAGIC;
new_block->magic = kVMHeapBlockHeaderMagic;
if (current->next) current->next->previous = new_block;
current->next = new_block;
@@ -65,39 +67,65 @@ void* malloc(UInt64 size) {
return nullptr;
}
void free(void* pointer) {
static void sVMHeapFreeInternal(void* pointer) {
if (!pointer) return;
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->magic != HEADER_MAGIC) return;
if (current->magic != kVMHeapBlockHeaderMagic) return;
current->isFree = true;
if (current->next && current->next->isFree) combine_forward(current);
if (current->previous && current->previous->isFree) combine_forward(current->previous);
if (current->next && current->next->isFree) sVMHeapCombineForward(current);
if (current->previous && current->previous->isFree) sVMHeapCombineForward(current->previous);
}
void* realloc(void* pointer, UInt64 newSize) {
if (!pointer) return malloc(newSize);
void* VMHeapAllocate(UInt64 size) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
void* result = sVMHeapAllocateInternal(size);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return result;
}
void VMHeapFree(void* pointer) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
sVMHeapFreeInternal(pointer);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
}
void* VMHeapResize(void* pointer, UInt64 newSize) {
if (!pointer) return VMHeapAllocate(newSize);
if (newSize == 0) {
free(pointer);
VMHeapFree(pointer);
return nullptr;
}
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->size >= newSize) return pointer;
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
if (current->next &&
current->next->isFree &&
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->size >= newSize) {
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
if (current->next && current->next->isFree &&
(current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable
combine_forward(current);
sVMHeapCombineForward(current);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
void* newPointer = malloc(newSize);
if (!newPointer) return nullptr;
memcpy(newPointer, pointer, current->size);
free(pointer);
void* newPointer = sVMHeapAllocateInternal(newSize);
if (newPointer) {
MemoryCopy(newPointer, pointer, current->size);
sVMHeapFreeInternal(pointer);
}
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return newPointer;
}
+18 -2
View File
@@ -6,7 +6,9 @@
#include <lib/String.h>
#include <lib/Math.h>
#include <OS/OSPanic.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
#include "bootinfo.h"
@@ -16,6 +18,8 @@ UInt8* gVMPhycalMemoryBitmap = nullptr;
UInt64 gVMPhycalMemoryBitmapSize = 0;
UInt64 gVMPhycalMemoryTotalMemorySize = 0;
static OSSpinlock sVMPMMLock = {0};
extern UInt64 _kernel_start;
extern UInt64 _kernel_end;
@@ -67,7 +71,7 @@ void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
gVMPhycalMemoryBitmap = (UInt8*)bitmapHostDescriptor->physicalStart;
gVMPhycalMemoryBitmapSize = bitmapSize;
memset(gVMPhycalMemoryBitmap, 0xFF, bitmapSize);
MemorySet(gVMPhycalMemoryBitmap, 0xFF, bitmapSize);
for (UInt64 i = 0; i < descriptorCount; i++) {
OSMemoryDescriptor *descriptor = (OSMemoryDescriptor*)((UInt8*)memoryMap->map + (i * memoryMap->descriptorSize));
@@ -96,6 +100,9 @@ void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
}
void* VMPhysicalMemoryAllocatePage() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) {
if (gVMPhycalMemoryBitmap[i] == 0xFF) continue;
@@ -103,13 +110,22 @@ void* VMPhysicalMemoryAllocatePage() {
if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) {
UInt64 address = (i * 8 + bit) * kVMPageSize;
BITMAP_SET(gVMPhycalMemoryBitmap, address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return (void*)address;
}
}
}
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return nullptr; // Out of memory
}
void VMPhysicalMemoryFreePage(void* address) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
}
+40 -10
View File
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <VM/VMM.h>
#include <VM/PMM.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <GDT.h>
#include <IDT.h>
@@ -20,6 +21,7 @@ enum {
UInt64* gVMKernelPML4 = nullptr;
UInt64 gVMKernelPML4Physical = 0;
static OSSpinlock sVMVMMlock = {0};
static bool isInitialized = false;
extern UInt64 _kernel_start;
@@ -36,7 +38,7 @@ static UInt64* sVMGetVirtualTable(UInt64 phys) {
return (UInt64*)phys;
}
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
@@ -51,7 +53,7 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
memset(addr_virt, 0, kVMPageSize);
MemorySet(addr_virt, 0, kVMPageSize);
pml4_virt[pml4_idx] = (UInt64)addr | table_flags;
} else {
pml4_virt[pml4_idx] |= (flags & PTE_USER);
@@ -64,7 +66,7 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
memset(addr_virt, 0, kVMPageSize);
MemorySet(addr_virt, 0, kVMPageSize);
pdpt_virt[pdpt_idx] = (UInt64)addr | table_flags;
} else {
pdpt_virt[pdpt_idx] |= (flags & PTE_USER);
@@ -77,7 +79,7 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl
UInt64* addr = VMPhysicalMemoryAllocatePage();
if (!addr) return nullptr;
UInt64* addr_virt = sVMGetVirtualTable((UInt64)addr);
memset(addr_virt, 0, kVMPageSize);
MemorySet(addr_virt, 0, kVMPageSize);
pd_virt[pd_idx] = (UInt64)addr | table_flags;
} else {
pd_virt[pd_idx] |= (flags & PTE_USER);
@@ -92,7 +94,7 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl
return (UInt64*)virt;
}
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
@@ -115,6 +117,27 @@ void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
}
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, phys, virt, flags);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return result;
}
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
sVMVirtualMemoryUnmapPageInternal(pml4, virt);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
}
void VMLoadCR3(UInt64 pml4_addr) {
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
}
@@ -122,7 +145,7 @@ void VMLoadCR3(UInt64 pml4_addr) {
void VMVirtualMemoryInitialize(Bootinfo* info) {
gVMKernelPML4Physical = (UInt64)VMPhysicalMemoryAllocatePage();
gVMKernelPML4 = (UInt64*)gVMKernelPML4Physical;
memset(gVMKernelPML4, 0, kVMPageSize);
MemorySet(gVMKernelPML4, 0, kVMPageSize);
UInt64 k_virt_start = (UInt64)&_kernel_start;
UInt64 k_virt_end = (UInt64)&_kernel_end;
@@ -144,11 +167,17 @@ void VMVirtualMemoryInitialize(Bootinfo* info) {
}
UInt64 VMVirtualMemoryCreateAddressSpace() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage();
if (!phys) return 0;
if (!phys) {
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return 0;
};
UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys);
memset(virt, 0, kVMPageSize);
MemorySet(virt, 0, kVMPageSize);
UInt64* kernel_pml4_virt = sVMGetVirtualTable((UInt64)gVMKernelPML4);
@@ -156,6 +185,7 @@ UInt64 VMVirtualMemoryCreateAddressSpace() {
virt[i] = kernel_pml4_virt[i];
}
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return phys;
}
@@ -171,7 +201,7 @@ void VMVirtualMemorySetupUserStack(UInt64* pml4_phys) {
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);
MemorySet((void*)PHYS_TO_HHDM((UInt64)phys), 0, 4096);
VMVirtualMemoryMapPage((UInt64*)pml4_phys, (UInt64)phys, addr, PTE_PRESENT | PTE_RW | PTE_USER);
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
// just fucking kill me already
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IDT.h>
#include <types.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <PIC.h>
#include <IO.h>
+1 -1
View File
@@ -1,5 +1,5 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2025 0xKarinyash
; Copyright (c) 2026 0xKarinyash
bits 64
+1 -1
View File
@@ -1,5 +1,5 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2025 0xKarinyash
; Copyright (c) 2026 0xKarinyash
bits 64
+2 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IO.h>
#include <OS/OSPanic.h>
@@ -24,6 +24,7 @@ void isr_handler_c(CPURegisters* frame) {
IOConsoleLog("^gR13^!=%X, ^gR14^!=%X\n", frame->r13, frame->r14);
IOConsoleLog("^gR15^!=%X\n",frame->r15);
IOConsoleLog("--------------------------------\n");
return;
}
if ((frame->cs & 3) != 0) {
IOConsoleLog("\n[Dewar] Process '%s' (PID %d) Segmentation Fault at %X\n",
+3 -3
View File
@@ -55,9 +55,9 @@ UInt64 syscall_dispatch(UInt64 id, UInt64 arg1, UInt64 arg2, UInt64 arg3, UInt64
switch (id) {
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_MEM: return OSServiceMemoryAllocate(arg1);
case SYS_WRITE: return OSServiceIOWrite(arg1, arg2, arg3);
case SYS_READ: return OSServiceIORead(arg1, arg2, arg3);
case SYS_WAIT: return OSServiceProcessWait(arg1);
default:
IOConsoleLog("[Dewar] Unknown syscall %d\n", id);
+11 -10
View File
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include "bootinfo.h"
#include <shell/ksh.h>
#include <KSH/KSHEntry.h>
#include <types.h>
@@ -11,6 +11,7 @@
#include <IO/IOSerial.h>
#include <IO/IOConsole.h>
#include <IO/IOTimer.h>
#include <IO/IOKeyboard.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
@@ -80,7 +81,7 @@ void kmain(Bootinfo* info) {
IOConsoleLog("VFS initialized\n");
UInt32 *framebuffer = (UInt32*)info->framebuffer.base;
if (!framebuffer) return IOConsoleLog("No framebuffer found!!");
if (!framebuffer) return OSPanic("No framebuffer found!!");
sIOGraphicsContext.framebuffer = framebuffer;
sIOGraphicsContext.dimensions.height = info->framebuffer.height;
@@ -93,20 +94,20 @@ void kmain(Bootinfo* info) {
SplashShow(&sIOGraphicsContext);
bool staying_in_ksh = false;
bool rescueMode = false;
if (!info->initramfs.address) {
IOConsoleLog("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n");
staying_in_ksh = true;
IOConsoleLog("^rWARNING^!: Failed to load ^yStartupVolume^!! Staying in kernel rescue shell!\n\n");
rescueMode = true;
}
if (!staying_in_ksh) {
if (!rescueMode) {
IOConsoleLog("Press any key to continue booting. \nPress ^yq^! to stay in ^gksh^!\n");
char c = '\n';
c = IOConsoleGetCharacter();
if (c == 'q') staying_in_ksh = true;
c = IOKeyboardGetCharacter();
if (c == 'q') rescueMode = true;
}
if (staying_in_ksh) OSSchedulerSpawn(ksh, nullptr, false, 0);
if (rescueMode) OSSchedulerSpawn(KSHEntry, nullptr, false, 0);
else OSSchedulerSpawn(init_task_entry, nullptr, false, 0);
__asm__ volatile("sti");
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include "bootinfo.h"
#include <lib/Rand.h>
+1 -1
View File
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <IO/IOGraphics.h>
#include <IO/IOConsole.h>
+56 -50
View File
@@ -1,71 +1,77 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#include <lib/String.h>
Int32 strcmp(const char *s1, const char *s2) {
while (*s1 && (*s1 == *s2)) {
s1++;
s2++;
void* MemorySet(void* destination, UInt8 value, UInt64 count) {
UInt8* bytePointer = (UInt8*) destination;
while (count--) {
*bytePointer++ = (UInt8)value;
}
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
return destination;
}
Int32 strncmp(const char* s1, const char* s2, UInt64 n) {
while (n > 0) {
if (*s1 != *s2) return *(unsigned char*)s1 - *(unsigned char*)s2;
if (*s1 == '\0') return 0;
s1++;
s2++;
n--;
void* MemoryCopy(void* destination, const void* source, UInt64 count) {
UInt8* destinationBuffer = (UInt8*)destination;
const UInt8* sourceBuffer = (const UInt8*)source;
while (count >= 8) {
*(UInt64*)destinationBuffer = *(const UInt64*)sourceBuffer;
destinationBuffer += 8;
sourceBuffer += 8;
count -= 8;
}
while (count > 0) {
*destinationBuffer++ = *sourceBuffer++;
count--;
}
return destination;
}
Int32 StringCompare(const char* firstString, const char* secondString) {
while (*firstString && (*firstString == *secondString)) {
firstString++;
secondString++;
}
return *(const unsigned char*)firstString - *(const unsigned char*)secondString;
}
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit) {
while (limit > 0) {
if (*firstString != *secondString) return *(unsigned char*)firstString - *(unsigned char*)secondString;
if (*firstString == '\0') return 0;
firstString++;
secondString++;
limit--;
}
return 0;
}
char* strcpy(char* dest, const char* src) {
char* saved = dest;
while (*src) *dest++ = *src++;
*dest = 0;
char* StringCopy(char* destination, const char* source) {
char* saved = destination;
while (*source) *destination++ = *source++;
*destination = 0;
return saved;
}
char* strncpy(char* dest, const char* src, UInt64 n) {
char* saved = dest;
while (*src && n > 0) {
*dest++ = *src++;
n--;
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit) {
char* saved = destination;
while (*source && limit > 0) {
*destination++ = *source++;
limit--;
}
while (n > 0) {
*dest++ = 0;
n--;
while (limit > 0) {
*destination++ = 0;
limit--;
}
return saved;
}
void *memset(void *ptr, int value, Size num) {
UInt8 *p = (UInt8 *)ptr;
while (num--) {
*p++ = (UInt8)value;
}
return ptr;
}
void* memcpy(void* dest, const void* src, UInt64 n) {
UInt8* d = (UInt8*)dest;
const UInt8* s = (const UInt8*)src;
while (n >= 8) {
*(UInt64*)d = *(const UInt64*)s;
d += 8;
s += 8;
n -= 8;
}
while (n > 0) {
*d++ = *s++;
n--;
}
return dest;
UInt64 StringGetLength(const char* string) {
UInt64 result = 0;
for (result = 0; string[result]; result++);
return result;
}
+1 -1
View File
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (c) 2025 0xKarinyash
# Copyright (c) 2026 0xKarinyash
import sys
from PIL import Image
+3 -1
View File
@@ -7,7 +7,9 @@ set(CMAKE_C_EXTENSIONS OFF)
message(STATUS "Building termOS's userspace")
add_subdirectory(libobjc)
add_subdirectory(libterm)
add_subdirectory(init)
add_subdirectory(debug)
add_subdirectory(termosh)
add_subdirectory(testOBJC)
add_subdirectory(termosh)
+8 -81
View File
@@ -1,85 +1,12 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <stdio.h>
#include <malloc.h>
#define VECTOR_BUFFER_SIZE 8
typedef struct {
Int32* data;
UInt64 size;
UInt64 capacity;
} Vector;
void vector_init(Vector* vec) {
vec->data = nullptr;
vec->size = 0;
vec->capacity = 0;
}
UInt8 vector_append(Vector* vec, const Int32 num) {
if (vec->size >= vec->capacity) {
UInt64 new_cap = (vec->capacity == 0) ? VECTOR_BUFFER_SIZE : vec->capacity * 2;
Int32* new_data = realloc(vec->data, new_cap * sizeof(Int32));
if (!new_data) return 2; // Out of memory
vec->data = new_data;
vec->capacity = new_cap;
}
vec->data[vec->size] = num;
vec->size++;
return 0;
}
void vector_reset(Vector* vec) {
vec->size = 0;
}
UInt8 vector_reserve(Vector* vec, UInt64 new_cap) {
if (new_cap <= vec->capacity) return 0;
Int32* new_data = realloc(vec->data, new_cap * sizeof(Int32));
if (!new_data) return 2;
vec->data = new_data;
vec->capacity = new_cap;
return 0;
}
void vector_free(Vector* vec) {
free(vec->data);
vec->data = nullptr;
vec->size = vec->capacity = 0;
}
void render_list(Vector* numbers) {
printf("\nNumbers [%d/%d]: [", numbers->size, numbers->capacity);
if (numbers->size == 0) printf("]");
for (UInt64 i = 0; i < numbers->size; i++) {
printf("%d", numbers->data[i]);
if (i + 1 >= numbers->size) {
printf("]");
break;
}
printf(", ");
}
}
#include <termOS.h>
int main() {
Vector nums;
vector_init(&nums);
printf("Heap test\n");
printf("press any key to add 1 number press 'q' to exit\n");
char c = 'd';
UInt64 i = 0;
while (c != 'q') {
render_list(&nums);
vector_append(&nums, i);
i++;
c = getchar();
for (int i = 0; i < 100; i++) {
UInt64 pid = ProcessSpawn("/System/CoreServices/debug");
if (pid < 0) {
ConsolePrint("[PIDSPAMMER] Error %d\n", pid);
} else {
ConsolePrint("[PIDSPAMMER] %d spawned\n", pid);
}
}
vector_free(&nums);
}
+3 -4
View File
@@ -1,14 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <process.h>
#include <malloc.h>
#include <termOS.h>
// TODO: read .cfg and spawn what stated there
int main() {
while (1) {
Int32 pid = spawn("/bin/termosh");
Int32 pid = ProcessSpawn("/System/CoreServices/termosh");
if (pid < 0) return pid;
wait(pid);
ProcessWait(pid);
}
}
+31
View File
@@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.16)
project(libobjc LANGUAGES C ASM_NASM OBJC)
set(USER_C_FLAGS
-ffreestanding
-fno-builtin
-nostdlib
-nostdinc
-fno-stack-protector
-fno-pic
-fno-pie
-m64
-mno-red-zone
-mcmodel=small
-O2
)
set(LIBOBJC_SOURCES
src/runtime.c
src/lookup.c
src/msgSend.asm
src/exceptions.c
src/HOTObject.m
)
add_library(objc STATIC ${LIBOBJC_SOURCES})
target_compile_options(objc PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
target_include_directories(objc PUBLIC inc)
target_link_libraries(objc PRIVATE term)
+21
View File
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <Types.h>
typedef struct OBJCClass OBJCClass;
typedef struct OBJCObject OBJCObject;
typedef OBJCObject* id;
typedef OBJCClass* Class;
@interface HOTObject {
Class classPointer;
}
+ (id)alloc;
- (id)init;
- (id)free;
@end
+20
View File
@@ -0,0 +1,20 @@
#import <HOTObject.h>
extern id OBJCAllocateInstance(Class class);
extern void MemoryFree(void* pointer);
@implementation HOTObject
+ (id)alloc {
return OBJCAllocateInstance((Class)self);
}
- (id)init {
return self;
}
- (id)free {
MemoryFree(self);
return (id)0;
}
@end
+3
View File
@@ -0,0 +1,3 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
+3
View File
@@ -0,0 +1,3 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
+59
View File
@@ -0,0 +1,59 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2026 0xKarinyash
[bits 64]
section .text
global objc_msgSend
; id objc_msgSend(id self, SEL _cmd, ...)
; RDI = self, RSI = _cmd (pointer on OBJCSelector)
objc_msgSend:
test rdi, rdi
jz .return_nil
mov rax, [rdi]
.search_class:
; OBJClass:
; 0: metaClass, 8: parentClass, 16: name, 24: version, 32: info, 40: instanceSize, 48: methods
mov r10, [rax + 48] ; R10 = OBJCMethodList*
.search_method_list:
test r10, r10
jz .go_to_parent
; OBJCMethodList:
; 0: next, 8: methodCount, 12: padding, 16: methods[]
mov ecx, [r10 + 8] ; ECX = methodCount
test ecx, ecx
jz .next_list
lea r11, [r10 + 16] ; R11 start of methods[]
.loop_methods:
; OBJCMethod:
; 0: selector, 8: types, 16: functionPointer
mov r8, [r11]
cmp r8, rsi
je .found
add r11, 24
loop .loop_methods
.next_list:
mov r10, [r10] ; r10 = list->next
jmp .search_method_list
.go_to_parent:
mov rax, [rax + 8]
test rax, rax
jnz .search_class
jmp .return_nil
.found:
mov rax, [r11 + 16]
jmp rax
.return_nil:
xor rax, rax
xor rdx, rdx
ret
+121
View File
@@ -0,0 +1,121 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <termOS.h>
typedef struct OBJCSelector OBJCSelector;
typedef struct OBJCMethod OBJCMethod;
typedef struct OBJCMethodList OBJCMethodList;
typedef struct OBJCClass OBJCClass;
typedef struct OBJCObject OBJCObject;
typedef struct OBJCSymbolTable OBJCSymbolTable;
typedef struct OBJCModule OBJCModule;
struct OBJCSelector {
const char* name;
const char* types;
};
struct OBJCMethod {
struct OBJCSelector* selector;
const char* types;
void* functionPointer; // pointer to function
};
struct OBJCMethodList {
struct OBJCMethodList* next;
Int32 methodCount;
struct OBJCMethod methods[];
};
struct OBJCClass {
OBJCClass* metaClass; // pointer to metaclass
OBJCClass* parentClass; // parent
const char* name;
Int64 version;
Int64 info;
Int64 instanceSize;
OBJCMethodList* methods;
};
struct OBJCObject {
OBJCClass* classPointer;
};
struct OBJCSymbolTable {
UInt32 selectorReferencesCount;
OBJCSelector* selectorReferences;
UInt16 classDefinitionCount;
UInt16 categoryDefinitionCount;
void* definitions[];
};
struct OBJCModule {
UInt64 version;
UInt64 size;
const char* name;
OBJCSymbolTable* symbolTable;
};
enum {
kOBJCRuntimeMaxClasses = 256
};
static OBJCClass* _classTable[kOBJCRuntimeMaxClasses];
static UInt32 _classCount = 0;
static OBJCClass* sOBJCGetClass(const char* name) {
for (UInt32 i = 0; i < _classCount; i++) {
if (StringCompare(_classTable[i]->name, name) == 0) return _classTable[i];
}
return nullptr;
}
static void sOBJCRegisterModule(OBJCModule* module) {
if (!module || !module->symbolTable) return;
OBJCSymbolTable* symbolTable = module->symbolTable;
for (UInt16 i = 0; i < symbolTable->classDefinitionCount; i++) {
OBJCClass* class = (OBJCClass*)symbolTable->definitions[i];
if (_classCount < kOBJCRuntimeMaxClasses) {
_classTable[_classCount++] = class;
}
}
}
// real
extern void* __objc_module_list_start;
extern void* __objc_module_list_end;
OBJCClass* objc_getClass(const char* name) {
return sOBJCGetClass(name);
}
void __objc_exec_class(OBJCModule* module) {
sOBJCRegisterModule(module);
}
OBJCClass* objc_lookup_class(const char* name) {
return sOBJCGetClass(name);
}
void _objc_init_runtime() {
void** currentModule = &__objc_module_list_start;
while (currentModule < &__objc_module_list_end) {
if (*currentModule) __objc_exec_class((OBJCModule*)*currentModule);
currentModule++;
}
}
OBJCObject* OBJCAllocateInstance(OBJCClass* class) {
if (!class) return nullptr;
OBJCObject* instance = (OBJCObject*)MemoryAllocate(class->instanceSize);
if (instance) {
MemorySet(instance, 0, class->instanceSize);
instance->classPointer = class;
}
return instance;
}
+34 -14
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(libterm LANGUAGES C ASM_NASM)
project(libterm LANGUAGES C ASM_NASM OBJC)
set(USER_C_FLAGS
-ffreestanding
@@ -22,12 +22,12 @@ set(USER_C_FLAGS
set(CMAKE_ASM_NASM_FLAGS "-f elf64")
set(LIBTERM_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls.asm
${CMAKE_CURRENT_SOURCE_DIR}/src/stdio.c
${CMAKE_CURRENT_SOURCE_DIR}/src/malloc.c
${CMAKE_CURRENT_SOURCE_DIR}/src/string.c
${CMAKE_CURRENT_SOURCE_DIR}/src/ctype.c
${CMAKE_CURRENT_SOURCE_DIR}/src/process.c
${CMAKE_CURRENT_SOURCE_DIR}/src/OSServices.asm
${CMAKE_CURRENT_SOURCE_DIR}/src/Console.c
${CMAKE_CURRENT_SOURCE_DIR}/src/Memory.c
${CMAKE_CURRENT_SOURCE_DIR}/src/String.c
${CMAKE_CURRENT_SOURCE_DIR}/src/Character.c
${CMAKE_CURRENT_SOURCE_DIR}/src/Process.c
)
add_library(term STATIC ${LIBTERM_SOURCES})
@@ -36,25 +36,45 @@ target_compile_options(term PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
target_include_directories(term PUBLIC inc)
add_library(crt0_obj OBJECT src/crt0.asm)
target_compile_options(crt0_obj PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
add_library(RuntimeEntryObject OBJECT src/RuntimeEntry.asm)
add_library(ObjCRuntimeEntryObject OBJECT src/ObjCRuntimeEntry.asm)
function(add_termos_executable NAME SOURCES)
set(HAS_OBJC FALSE)
foreach(SRC ${SOURCES})
get_filename_component(EXT ${SRC} EXT)
if(EXT STREQUAL ".m")
set(HAS_OBJC TRUE)
break()
endif()
endforeach()
add_executable(${NAME} ${SOURCES})
target_sources(${NAME} PRIVATE $<TARGET_OBJECTS:crt0_obj>)
if(HAS_OBJC)
target_sources(${NAME} PRIVATE $<TARGET_OBJECTS:ObjCRuntimeEntryObject>)
target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:OBJC>:-fobjc-runtime=gnustep -fblocks>)
target_link_options(${NAME} PRIVATE -T ${libterm_SOURCE_DIR}/linker/objc.ld)
target_link_libraries(${NAME} PRIVATE objc)
else()
target_sources(${NAME} PRIVATE $<TARGET_OBJECTS:RuntimeEntryObject>)
endif()
target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:C>:${USER_C_FLAGS}>)
target_compile_options(${NAME} PRIVATE
$<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:OBJC>>:${USER_C_FLAGS}>
)
target_link_libraries(${NAME} PRIVATE term)
target_link_options(${NAME} PRIVATE
-T ${libterm_SOURCE_DIR}/linker.ld
-T ${libterm_SOURCE_DIR}/linker/common.ld
-nostdlib
-static
)
set(ELF2HOT_DIR "${CMAKE_SOURCE_DIR}/tools/elf2hot")
set(FINAL_HOT_PATH "${CMAKE_SOURCE_DIR}/initramfs/bin/${NAME}")
set(STARTUP_VOLUME_DIR "${CMAKE_BINARY_DIR}/StartupVolume/System/CoreServices")
file(MAKE_DIRECTORY "${STARTUP_VOLUME_DIR}")
set(FINAL_HOT_PATH "${STARTUP_VOLUME_DIR}/${NAME}")
add_custom_command(TARGET ${NAME} POST_BUILD
COMMAND cargo run --release --quiet -- $<TARGET_FILE:${NAME}> ${FINAL_HOT_PATH}
+15
View File
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <Types.h>
enum {
kConsoleEOF = -1,
kConsoleDefaultBufferSize = 1024
};
Int32 ConsolePrint(const char* format, ...);
Int32 StringFormat(char* destination, UInt64 size, const char* format, ...);
Int32 ConsoleGetCharacter();
char* ConsoleReadLine(char* string, UInt64 size);
+23
View File
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <Types.h>
enum {
kMemoryBlockMagic = 0x1CE1CE,
kMemoryAlignment = 16,
kMemoryPageSize = 4096
};
typedef struct MemoryBlockHeader {
UInt64 magic;
struct MemoryBlockHeader* next;
struct MemoryBlockHeader* previous;
UInt64 size;
bool isFree;
} MemoryBlockHeader;
void* MemoryAllocate(UInt64 size);
void MemoryFree(void* pointer);
void* MemoryReallocate(void* pointer, UInt64 newSize);
+8
View File
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <Types.h>
Int32 ProcessSpawn(const char* path);
Int32 ProcessWait(UInt64 pid);
+16
View File
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <Types.h>
void* MemorySet(void* destination, UInt8 value, UInt64 count);
void* MemoryCopy(void* destination, const void* source, UInt64 count);
Int32 StringCompare(const char* firstString, const char* secondString);
Int32 StringCompareWithLimit(const char* firstString, const char* secondString, UInt64 limit);
char* StringCopy(char* destination, const char* source);
char* StringCopyWithLimit(char* destination, const char* source, UInt64 limit);
UInt64 StringGetLength(const char* string);
UInt64 StringGetInitialSpan(const char* string, const char* characterSet);
char* StringFindFirstCharacterFromSet(const char* string, const char* accept);
char* StringTokenize(char *s, const char* delim);
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 0xKarinyash
// Copyright (c) 2026 0xKarinyash
#pragma once
-19
View File
@@ -1,19 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
#define HEADER_MAGIC 0x1CE1CE
typedef struct block_header {
UInt64 magic;
struct block_header* next;
struct block_header* prev;
UInt64 size;
bool is_free;
} block_header;
void* malloc(UInt64 size);
void free(void* ptr);
void* realloc(void* ptr, UInt64 new_size);
-11
View File
@@ -1,11 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
int printf(const char *fmt, ...);
int snprintf(char* str, UInt64 size, const char* fmt, ...);
int getchar();
char* gets(char* str);
char* gets_s(char* str, UInt64 size);
-16
View File
@@ -1,16 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
void *memset(void *ptr, int value, usize num);
void* memcpy(void* dest, const void* src, UInt64 n);
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);
UInt64 strlen(const char* str);
UInt64 strspn(const char* s, const char* accept);
char* strpbrk(const char* s, const char* accept);
char* strtok(char *s, const char* delim);
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <Console.h>
#include <Memory.h>
#include <Process.h>
#include <String.h>
#include <Varargs.h>
#include <Types.h>
+28
View File
@@ -0,0 +1,28 @@
SECTIONS
{
.objc_metadata :
{
. = ALIGN(8);
__objc_runtime_start = .;
KEEP(*(.objc_info))
__objc_module_list_start = .;
KEEP(*(.objc_module_info))
__objc_module_list_end = .;
KEEP(*(.objc_selectors))
KEEP(*(.objc_classes))
KEEP(*(.objc_category))
KEEP(*(.objc_class_refs))
KEEP(*(.objc_class_names))
KEEP(*(.objc_method_names))
KEEP(*(.objc_method_types))
KEEP(*(.objc_protocol_list))
KEEP(*(.objc_string_object))
KEEP(*(.objc_constant_string))
KEEP(*(.objc_data))
KEEP(*(.objc_list.*))
__objc_runtime_end = .;
}
}
INSERT AFTER .data;
+156
View File
@@ -0,0 +1,156 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <Console.h>
#include <Varargs.h>
#include <String.h>
extern UInt64 OSServiceIORead(UInt64 fileDescriptor, void* buffer, UInt64 length);
extern UInt64 OSServiceIOWrite(UInt64 fileDescriptor, const void* buffer, UInt64 length);
static void sConsoleWriteCharacter(char character) {
OSServiceIOWrite(1, &character, 1);
}
static inline void sConsoleBufferAdd(char* string, UInt64 size, UInt64* written, char character) {
if (*written < size - 1 && size > 0) {
string[*written] = character;
}
(*written)++;
}
static Int32 sStringFormatVariadic(char* string, UInt64 size, const char* format, va_list args) {
UInt64 written = 0;
for (UInt32 i = 0; format[i] != '\0'; i++) {
if (format[i] == '%') {
i++;
if (format[i] == '\0') break;
switch (format[i]) {
case 's': {
const char* vaArgString = va_arg(args, const char*);
if (!vaArgString) vaArgString = "(null)";
while (*vaArgString) sConsoleBufferAdd(string, size, &written, *vaArgString++);
break;
}
case 'c': {
char character = (char)va_arg(args, int);
sConsoleBufferAdd(string, size, &written, character);
break;
}
case 'd': {
Int64 number = va_arg(args, int);
if (number < 0) {
sConsoleBufferAdd(string, size, &written, '-');
number = -number;
}
UInt64 unsignedNumber = (UInt64)number;
char tempBuffer[32];
Int32 position = 0;
if (unsignedNumber == 0) tempBuffer[position++] = '0';
while (unsignedNumber > 0) {
tempBuffer[position++] = (unsignedNumber % 10) + '0';
unsignedNumber /= 10;
}
while (position > 0) sConsoleBufferAdd(string, size, &written, tempBuffer[--position]);
break;
}
case 'x':
case 'X': {
UInt64 unsignedNumber = va_arg(args, unsigned long long);
UInt8 padding = (format[i] == 'X') ? 16 : 0;
char tempBuffer[32];
int position = 0;
const char* hex = "0123456789ABCDEF";
if (unsignedNumber == 0 && padding == 0) tempBuffer[position++] = '0';
while (unsignedNumber > 0) {
tempBuffer[position++] = hex[unsignedNumber % 16];
unsignedNumber /= 16;
}
while (position < padding) tempBuffer[position++] = '0';
while (position > 0) sConsoleBufferAdd(string, size, &written, tempBuffer[--position]);
break;
}
case '%': {
sConsoleBufferAdd(string, size, &written, '%');
break;
}
default: {
sConsoleBufferAdd(string, size, &written, '%');
sConsoleBufferAdd(string, size, &written, format[i]);
break;
}
}
} else {
sConsoleBufferAdd(string, size, &written, format[i]);
}
}
if (size > 0) {
if (written < size) string[written] = '\0';
else string[size - 1] = '\0';
}
return (int)written;
}
Int32 StringFormat(char* destination, usize size, const char* format, ...) {
va_list args;
va_start(args, format);
int returnValue = sStringFormatVariadic(destination, size, format, args);
va_end(args);
return returnValue;
}
Int32 ConsolePrint(const char *format, ...) {
char buffer[kConsoleDefaultBufferSize];
va_list args;
va_start(args, format);
int length = sStringFormatVariadic(buffer, sizeof(buffer), format, args);
va_end(args);
UInt64 writeLength = ((UInt64)length < sizeof(buffer)) ? length : (sizeof(buffer) - 1);
OSServiceIOWrite(1, buffer, writeLength);
return (int)writeLength;
}
Int32 ConsoleGetCharacter() {
char character;
UInt64 serviceCallResult = OSServiceIORead(0, &character, 1);
if (serviceCallResult <= 0) return kConsoleEOF;
return (int)(unsigned char)character;
}
char* ConsoleReadLine(char* string, UInt64 size) {
if (size == 0) return string;
UInt64 i = 0;
int character;
while (i < size - 1) {
character = ConsoleGetCharacter();
if (character == kConsoleEOF || character == '\n' || character == '\r') break;
if (character == '\b') {
if (i > 0) {
i--;
ConsolePrint("\b \b");
}
continue;
}
string[i++] = (char)character;
sConsoleWriteCharacter(character);
}
string[i] = '\0';
sConsoleWriteCharacter('\n');
return string;
}
+104
View File
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
// brutally copypasting from kernel/mm/heap.c
#include <Memory.h>
#include <String.h>
static MemoryBlockHeader* sMemoryHeapListHead = nullptr;
extern UInt64 OSServiceMemoryAllocate(UInt64 size);
static void sMemoryCombineForward(MemoryBlockHeader* current) {
if (!current->next || !current->next->isFree) return;
current->size += sizeof(MemoryBlockHeader) + current->next->size;
current->next = current->next->next;
if (current->next) current->next->previous = current;
}
void* MemoryAllocate(UInt64 size) {
if (size == 0) return nullptr;
UInt64 alignedSize = (size + (kMemoryAlignment-1)) & ~(kMemoryAlignment - 1);
MemoryBlockHeader* current = sMemoryHeapListHead;
MemoryBlockHeader* lastBlock = nullptr;
while (current) {
if (current->isFree && current->size >= alignedSize) {
if (current->size > alignedSize + sizeof(MemoryBlockHeader) + kMemoryAlignment) {
MemoryBlockHeader* newBlock = (MemoryBlockHeader*)((UInt64)current + sizeof(MemoryBlockHeader) + alignedSize);
newBlock->size = current->size - alignedSize - sizeof(MemoryBlockHeader);
newBlock->isFree = true;
newBlock->next = current->next;
newBlock->previous = current;
newBlock->magic = kMemoryBlockMagic;
if (current->next) current->next->previous = newBlock;
current->next = newBlock;
current->size = alignedSize;
}
current->isFree = false;
return (void*)((UInt64)current + sizeof(MemoryBlockHeader));
}
lastBlock = current;
current = current->next;
}
UInt64 sizeNeededToAllocate = alignedSize + sizeof(MemoryBlockHeader);
UInt64 pageAlignedSize = (sizeNeededToAllocate + (kMemoryPageSize-1)) & ~(kMemoryPageSize-1);
UInt64 newMemoryAddress = OSServiceMemoryAllocate(pageAlignedSize);
if (newMemoryAddress == 0) return nullptr;
MemoryBlockHeader* newBlock = (MemoryBlockHeader*)newMemoryAddress;
newBlock->size = pageAlignedSize - sizeof(MemoryBlockHeader);
newBlock->isFree = true;
newBlock->magic = kMemoryBlockMagic;
newBlock->next = nullptr;
newBlock->previous = lastBlock;
if (lastBlock) {
lastBlock->next = newBlock;
} else {
sMemoryHeapListHead = newBlock;
}
return MemoryAllocate(size);
}
void MemoryFree(void* pointer) {
if (!pointer) return;
MemoryBlockHeader* current = (MemoryBlockHeader*)((UInt64)pointer - sizeof(MemoryBlockHeader));
if (current->magic != kMemoryBlockMagic) return;
current->isFree = true;
if (current->next && current->next->isFree) sMemoryCombineForward(current);
if (current->previous && current->previous->isFree) sMemoryCombineForward(current->previous);
}
void* MemoryReallocate(void* pointer, UInt64 newSize) {
if (!pointer) return MemoryAllocate(newSize);
if (newSize == 0) {
MemoryFree(pointer);
return nullptr;
}
MemoryBlockHeader* current = (MemoryBlockHeader*)((UInt64)pointer - sizeof(MemoryBlockHeader));
if (current->size >= newSize) return pointer;
if (current->next &&
current->next->isFree &&
(current->size + sizeof(MemoryBlockHeader) + current->next->size) >= newSize) {
sMemoryCombineForward(current);
return pointer;
}
void* newPointer = MemoryAllocate(newSize);
if (!newPointer) return nullptr;
MemoryCopy(newPointer, pointer, current->size);
MemoryFree(pointer);
return newPointer;
}
@@ -5,39 +5,39 @@ bits 64
section .text
global sys_exit
global sys_spawn
global sys_mem
global sys_write
global sys_read
global sys_wait
global OSServiceProcessExit
global OSServiceProcessSpawn
global OSServiceMemoryAllocate
global OSServiceIOWrite
global OSServiceIORead
global OSServiceProcessWait
sys_exit:
OSServiceProcessExit:
mov rax, 0
syscall
ret
sys_spawn:
OSServiceProcessSpawn:
mov rax, 1
syscall
ret
sys_mem:
OSServiceMemoryAllocate:
mov rax, 2
syscall
ret
sys_write:
OSServiceIOWrite:
mov rax, 3
syscall
ret
sys_read:
OSServiceIORead:
mov rax, 4
syscall
ret
sys_wait:
OSServiceProcessWait:
mov rax, 5
syscall
ret
@@ -0,0 +1,18 @@
; SPDX-License-Identifier: GPL-3.0-or-later
; Copyright (c) 2026 0xKarinyash
[bits 64]
section .text
global _start
extern main
extern OSServiceProcessExit
extern _objc_init_runtime
_start:
call _objc_init_runtime
call main
mov rdi, rax
call OSServiceProcessExit

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