Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa6b7924e2 | |||
| 4e10985909 | |||
| c72dbc763c | |||
| 02b36283a5 | |||
| e21f5ef52f | |||
| 2be7d3bd46 | |||
| 02dc35f0df | |||
| ee67cef4f8 | |||
| c30d57d06e | |||
| 4e6794a6c2 |
+2
-1
@@ -5,4 +5,5 @@ kernel/data
|
||||
*.md
|
||||
bootloader/
|
||||
bootloader/src/uefi
|
||||
initramfs/
|
||||
initramfs/
|
||||
kernel/inc/Data
|
||||
+18
-13
@@ -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}"
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -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,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,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,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,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
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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();
|
||||
@@ -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,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
|
||||
#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;
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -4,4 +4,4 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
UInt64 OSServiceMemoryGet(UInt64 size);
|
||||
UInt64 OSServiceMemoryAllocate(UInt64 size);
|
||||
@@ -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
@@ -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
@@ -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,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
|
||||
#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>
|
||||
|
||||
|
||||
@@ -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
|
||||
#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
|
||||
#include <IO/IOGraphics.h>
|
||||
|
||||
@@ -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);
|
||||
@@ -1,6 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
void ksh();
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Copyright (c) 2025 0xKarinyash */
|
||||
Copyright (c) 2026 0xKarinyash */
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
|
||||
+10
-10
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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,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,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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,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,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,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,5 +1,5 @@
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright (c) 2025 0xKarinyash
|
||||
; Copyright (c) 2026 0xKarinyash
|
||||
|
||||
bits 64
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||
; Copyright (c) 2025 0xKarinyash
|
||||
; Copyright (c) 2026 0xKarinyash
|
||||
|
||||
bits 64
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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,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,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
@@ -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,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2026 0xKarinyash
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <Console.h>
|
||||
#include <Memory.h>
|
||||
#include <Process.h>
|
||||
#include <String.h>
|
||||
#include <Varargs.h>
|
||||
#include <Types.h>
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user