From 83d870e58457a1d335a1d9b9966a6a1887cc297b Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Mon, 24 Nov 2025 03:02:43 +0100 Subject: feat! breaking changes on kernel sources. Signed-off-by: Amlal El Mahrouss --- src/libSystem/SystemKit/Err.h | 58 ++++ src/libSystem/SystemKit/Jail.h | 36 +++ src/libSystem/SystemKit/Macros.h | 126 +++++++++ src/libSystem/SystemKit/Syscall.h | 21 ++ src/libSystem/SystemKit/System.h | 389 +++++++++++++++++++++++++++ src/libSystem/SystemKit/Verify.h | 40 +++ src/libSystem/docs/SPECIFICATION_SYSCALLS.md | 25 ++ src/libSystem/libSystem.json | 20 ++ src/libSystem/obj/.keep | 0 src/libSystem/src/JailCalls.cc | 17 ++ src/libSystem/src/Makefile | 16 ++ src/libSystem/src/SystemCalls.cc | 169 ++++++++++++ src/libSystem/src/SystemCallsABI+AMD64.asm | 81 ++++++ src/libSystem/src/Utils.cc | 29 ++ src/libSystem/src/VerifyCalls.cc | 18 ++ 15 files changed, 1045 insertions(+) create mode 100644 src/libSystem/SystemKit/Err.h create mode 100644 src/libSystem/SystemKit/Jail.h create mode 100644 src/libSystem/SystemKit/Macros.h create mode 100644 src/libSystem/SystemKit/Syscall.h create mode 100644 src/libSystem/SystemKit/System.h create mode 100644 src/libSystem/SystemKit/Verify.h create mode 100644 src/libSystem/docs/SPECIFICATION_SYSCALLS.md create mode 100644 src/libSystem/libSystem.json create mode 100644 src/libSystem/obj/.keep create mode 100644 src/libSystem/src/JailCalls.cc create mode 100644 src/libSystem/src/Makefile create mode 100644 src/libSystem/src/SystemCalls.cc create mode 100644 src/libSystem/src/SystemCallsABI+AMD64.asm create mode 100644 src/libSystem/src/Utils.cc create mode 100644 src/libSystem/src/VerifyCalls.cc (limited to 'src/libSystem') diff --git a/src/libSystem/SystemKit/Err.h b/src/libSystem/SystemKit/Err.h new file mode 100644 index 00000000..ea36abde --- /dev/null +++ b/src/libSystem/SystemKit/Err.h @@ -0,0 +1,58 @@ +/* ======================================== + + Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#pragma once + +#include + +/// @file Err.h +/// @brief Process Codes type and values. +/// @author Amlal El Mahrouss (amlal@nekernel.org) + +#define err_local_ok() (kLastError == kErrorSuccess) +#define err_local_fail() (kLastError != kErrorSuccess) +#define err_local_get() (kLastError) + +typedef SInt32 ErrRef; + +inline constexpr ErrRef kErrorSuccess = 0; +inline constexpr ErrRef kErrorExecutable = 33; +inline constexpr ErrRef kErrorExecutableLib = 34; +inline constexpr ErrRef kErrorFileNotFound = 35; +inline constexpr ErrRef kErrorDirectoryNotFound = 36; +inline constexpr ErrRef kErrorDiskReadOnly = 37; +inline constexpr ErrRef kErrorDiskIsFull = 38; +inline constexpr ErrRef kErrorProcessFault = 39; +inline constexpr ErrRef kErrorSocketHangUp = 40; +inline constexpr ErrRef kErrorThreadLocalStorage = 41; +inline constexpr ErrRef kErrorMath = 42; +inline constexpr ErrRef kErrorNoNetwork = 43; +inline constexpr ErrRef kErrorHeapOutOfMemory = 44; +inline constexpr ErrRef kErrorNoSuchDisk = 45; +inline constexpr ErrRef kErrorFileExists = 46; +inline constexpr ErrRef kErrorFormatFailed = 47; +inline constexpr ErrRef kErrorNetworkTimeout = 48; +inline constexpr ErrRef kErrorInternal = 49; +inline constexpr ErrRef kErrorForkAlreadyExists = 50; +inline constexpr ErrRef kErrorOutOfTeamSlot = 51; +inline constexpr ErrRef kErrorHeapNotPresent = 52; +inline constexpr ErrRef kErrorNoEntrypoint = 53; +inline constexpr ErrRef kErrorDiskIsCorrupted = 54; +inline constexpr ErrRef kErrorDisk = 55; +inline constexpr ErrRef kErrorInvalidData = 56; +inline constexpr ErrRef kErrorAsync = 57; +inline constexpr ErrRef kErrorNonBlocking = 58; +inline constexpr ErrRef kErrorIPC = 59; +inline constexpr ErrRef kErrorSign = 60; +inline constexpr ErrRef kErrorInvalidCreds = 61; +inline constexpr ErrRef kErrorCDTrayBroken = 62; +inline constexpr ErrRef kErrorUnrecoverableDisk = 63; +inline constexpr ErrRef kErrorFileLocked = 64; +inline constexpr ErrRef kErrorDiskIsTooTiny = 65; +inline constexpr ErrRef kErrorUnimplemented = -1; + +/// @brief The last error reported by the system to the process. +IMPORT_C ErrRef kLastError; diff --git a/src/libSystem/SystemKit/Jail.h b/src/libSystem/SystemKit/Jail.h new file mode 100644 index 00000000..f28968b4 --- /dev/null +++ b/src/libSystem/SystemKit/Jail.h @@ -0,0 +1,36 @@ +/* ======================================== + + Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#pragma once + +#include + +/// @file Jail.h +/// @author Amlal El Mahrouss +/// @brief NeKernel Jail System, part of OpenEnclave. + +struct JAIL_INFO; +struct JAIL; + +/// @brief Jail information (client side struct) +struct JAIL_INFO { + SInt32 fParentID; + SInt32 fJailHash; + SInt64 fACL; +}; + +/// @brief Jail information (we grab a JAIL from JailGetCurrent()) +struct JAIL { + struct JAIL_INFO* fServer; + struct JAIL_INFO* fClient; + SInt32 fJailHash; + SInt32 fParentID; + SInt64 fACL; +}; + +/// @brief Get the current jail +/// @return Pointer to the current jail structure, or NULL if not in a jail +IMPORT_C struct JAIL* JailGetCurrent(Void); diff --git a/src/libSystem/SystemKit/Macros.h b/src/libSystem/SystemKit/Macros.h new file mode 100644 index 00000000..aac2bf1b --- /dev/null +++ b/src/libSystem/SystemKit/Macros.h @@ -0,0 +1,126 @@ +/* ======================================== + +Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +File: Macros.h +Purpose: libsci Macros header. + +======================================== */ + +#pragma once + +/***********************************************************************************/ +/// @file libSystem/Macros.h +/// @brief Macros and Core types of the SCI (System Call Interface). +/***********************************************************************************/ + +#include + +#define ATTRIBUTE(X) __attribute__((X)) + +#define IMPORT_CXX extern "C++" +#define IMPORT_C extern "C" + +#define DEPRECATED ATTRIBUTE(deprecated) + +#define EXIT_SUCCESS (0) +#define EXIT_FAILURE (1) + +#define FILE_MAX_LEN (256) + +#ifndef BOOL +#define BOOL bool +#endif + +typedef bool Bool; +typedef bool Boolean; +typedef void Void; + +#ifndef __cplusplus +#define true (1) +#define false (0) +#endif + +#define YES true +#define NO false + +typedef __UINT64_TYPE__ UInt64; +typedef __UINT32_TYPE__ UInt32; +typedef __UINT16_TYPE__ UInt16; +typedef __UINT8_TYPE__ UInt8; + +typedef __SIZE_TYPE__ SizeT; + +typedef __INT64_TYPE__ SInt64; +typedef __INT32_TYPE__ SInt32; +typedef __INT16_TYPE__ SInt16; +typedef __INT8_TYPE__ SInt8; + +typedef void* VoidPtr; +typedef __UINTPTR_TYPE__ UIntPtr; +typedef char Char; + +#ifdef __cplusplus +typedef decltype(nullptr) nullPtr; +typedef nullPtr NullPtr; + +#define LIBSYS_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define LIBSYS_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define LIBSYS_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define LIBSYS_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +#endif + +#define MUST_PASS(X) _rtl_assert(X, __FILE__) + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(X) \ + (((sizeof(X) / sizeof(*(X))) / (static_cast(!(sizeof(X) % sizeof(*(X))))))) +#endif + +#ifndef KIB +#define KIB(X) (UInt64)((X) / 1024) +#endif + +#ifndef kib_cast +#define kib_cast(X) (UInt64)((X) *1024) +#endif + +#ifndef MIB +#define MIB(X) (UInt64)((UInt64) KIB(X) / 1024) +#endif + +#ifndef mib_cast +#define mib_cast(X) (UInt64)((UInt64) kib_cast(X) * 1024) +#endif + +#ifndef GIB +#define GIB(X) (UInt64)((UInt64) MIB(X) / 1024) +#endif + +#ifndef gib_cast +#define gib_cast(X) (UInt64)((UInt64) mib_cast(X) * 1024) +#endif + +#ifndef TIB +#define TIB(X) (UInt64)((UInt64) GIB(X) / 1024) +#endif + +#ifndef tib_cast +#define tib_cast(X) ((UInt64) gib_cast(X) * 1024) +#endif + +#define LIBSYS_UNUSED(X) ((void) X) + +IMPORT_C void _rtl_assert(Bool expr, const Char* origin); diff --git a/src/libSystem/SystemKit/Syscall.h b/src/libSystem/SystemKit/Syscall.h new file mode 100644 index 00000000..58d7d7f1 --- /dev/null +++ b/src/libSystem/SystemKit/Syscall.h @@ -0,0 +1,21 @@ +/* ======================================== + + Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#pragma once + +#include +#include + +IMPORT_C VoidPtr libsys_syscall_arg_1(SizeT id); +IMPORT_C VoidPtr libsys_syscall_arg_2(SizeT id, VoidPtr arg1); +IMPORT_C VoidPtr libsys_syscall_arg_3(SizeT id, VoidPtr arg1, VoidPtr arg3); +IMPORT_C VoidPtr libsys_syscall_arg_4(SizeT id, VoidPtr arg1, VoidPtr arg3, VoidPtr arg4); + +IMPORT_C UInt64 libsys_hash_64(const Char* path); + +#ifndef SYSCALL_HASH +#define SYSCALL_HASH(str) libsys_hash_64(str) +#endif // !SYSCALL_HASH diff --git a/src/libSystem/SystemKit/System.h b/src/libSystem/SystemKit/System.h new file mode 100644 index 00000000..544b7ee3 --- /dev/null +++ b/src/libSystem/SystemKit/System.h @@ -0,0 +1,389 @@ +/* ======================================== + +Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +File: System.h +Purpose: System Call Interface. + +======================================== */ + +#ifndef LIBSYS_SYSTEM_CALLS_H +#define LIBSYS_SYSTEM_CALLS_H + +#include + +/// @brief TTY device path. +#define kPrintDevicePath "/devices/tty{}" +#define kCDDevicePath "/devices/dvd{}" + +// ------------------------------------------------------------------------------------------ // +/// @brief Types API. +// ------------------------------------------------------------------------------------------ // + +struct REF_TYPE { + UInt64 __hash; /// @brief Hash of the syscall + VoidPtr __self; /// @brief Syscall self value. +}; + +typedef REF_TYPE* Ref; + +typedef Ref IORef; +typedef Ref FSRef; +typedef Ref DylibRef; +typedef Ref ThreadRef; +typedef Ref SocketRef; +typedef Ref NetworkRef; +typedef Ref MutexRef; +typedef Ref EventRef; +typedef Ref SemaphoreRef; + +// ------------------------------------------------------------------------------------------ // +/// @brief Dynamic Loader API. +// ------------------------------------------------------------------------------------------ // + +/// @brief Get function which is part of the Dylib. +/// @param symbol the symbol to look for +/// @param dll_handle the Dylib handle. +/// @return the proc pointer. +IMPORT_C Ref LdrGetDylibSymbolFromHandle(_Input const Char* symbol, _Input Ref dll_handle); + +/// @brief Open Dylib handle. +/// @param path dll path. +/// @param drv driver letter. +/// @return a dylib ref. +IMPORT_C Ref LdrOpenDylibHandle(_Input const Char* path, _Input const Char* drive_letter); + +/// @brief Close Dylib handle +/// @param dll_handle the dylib ref. +/// @return whether it closed or not. +IMPORT_C UInt32 LdrCloseDylibHandle(_Input Ref* dll_handle); + +// ------------------------------------------------------------------------------------------ // +// File API. +// ------------------------------------------------------------------------------------------ // + +/// @brief Opens a file from a drive. +/// @param fs_path the filesystem path. +/// @param drive_letter drive name, use NULL to use default drive location. +/// @return the file descriptor of the file. +IMPORT_C Ref IoOpenFile(const Char* fs_path, const Char* drive_letter); + +/// @brief Closes a file and flushes its content. +/// @param file_desc the file descriptor. +/// @return Function doesn't return a type. +IMPORT_C Void IoCloseFile(_Input Ref file_desc); + +/// @brief I/O control (ioctl) on a file. +/// @param file_desc the file descriptor. +/// @param ioctl_code the ioctl code. +/// @param in_data the input data. +/// @param out_data the output data. +/// @return the number of bytes written. +/// @note This function is used to control the file descriptor, introduced for OpenHeFS. +IMPORT_C SInt32 IoCtrlFile(_Input Ref file_desc, _Input UInt32 ioctl_code, _Input VoidPtr in_data, + _Output VoidPtr out_data); + +/// @brief Gets the file mime (if any) +/// @param file_desc the file descriptor. +IMPORT_C const Char* IoMimeFile(_Input Ref file_desc); + +/// @brief Gets the dir DIM. +/// @param dir_desc directory descriptor. +/// @note only works in OpenHeFS, will return nil-x/nil if used on any other filesystem. +IMPORT_C const Char* IoDimFile(_Input Ref dir_desc); + +/// @brief Write data to a file ref +/// @param file_desc the file descriptor. +/// @param out_data the data to write. +/// @param sz_data the size of the data to write. +/// @return the number of bytes written. +IMPORT_C UInt32 IoWriteFile(_Input Ref file_desc, _Output VoidPtr out_data, SizeT sz_data); + +/// @brief Read data from a file. +/// @param file_desc the file descriptor. +/// @param out_data the data to read. +/// @param sz_data the size of the data to read. +IMPORT_C UInt32 IoReadFile(_Input Ref file_desc, _Output VoidPtr* out_data, SizeT sz_data); + +/// @brief Rewind the file pointer to the beginning of the file. +/// @param file_desc the file descriptor. +/// @return the number of bytes read. +IMPORT_C UInt64 IoRewindFile(_Input Ref file_desc); + +/// @brief Tell the current position of the file pointer. +/// @param file_desc the file descriptor. +/// @return the current position of the file pointer. +IMPORT_C UInt64 IoTellFile(_Input Ref file_desc); + +/// @brief Seek file offset from file descriptor. +IMPORT_C UInt64 IoSeekFile(_Input Ref file_desc, UInt64 file_offset); + +// ------------------------------------------------------------------------ +// Process API. +// ------------------------------------------------------------------------ + +/// @brief Spawns a Thread Information Block and Global Information Block inside the current +/// process. +/// @param process_id Target Process ID, must be valid. +/// @return > 0 error occurred or already present, = 0 success. +IMPORT_C UInt32 RtlSpawnIB(UIntPtr process_id); + +/// @brief Spawns a process with a unique pid (stored as UIntPtr). +/// @param process_path process filesystem path. +/// @return > 0 process was created. +IMPORT_C UIntPtr RtlSpawnProcess(const Char* process_path, SizeT argc, Char** argv, Char** envp, + SizeT envp_len); + +/// @brief Exits a process with an exit_code. +/// @return if it has succeeded true, otherwise false. +IMPORT_C Bool RtlExitProcess(UIntPtr handle, UIntPtr exit_code); + +// ------------------------------------------------------------------------ +// Memory Manager API. +// ------------------------------------------------------------------------ + +/// @brief Creates a new heap from the process's address space. +/// @param len the length of it. +/// @param flags the flags of it. +/// @return heap pointer. +IMPORT_C VoidPtr MmCreateHeap(_Input SizeT len, _Input UInt32 flags); + +/// @brief Destroys the pointer +/// @param heap the heap itself. +/// @return void. +IMPORT_C SInt32 MmDestroyHeap(_Input VoidPtr heap); + +/// @brief Change protection flags of a memory region. +IMPORT_C SInt32 MmSetHeapFlags(_Input VoidPtr heap, _Input UInt32 flags); + +/// @brief Change protection flags of a memory region. +IMPORT_C UInt32 MmGetHeapFlags(_Input VoidPtr heap); + +/// @brief Fill memory region with CRC32. +IMPORT_C UInt32 MmFillCRC32Heap(_Input VoidPtr heap); + +/// @brief Copy memory region. +IMPORT_C VoidPtr MmCopyMemory(_Input VoidPtr dest, _Input VoidPtr src, _Input SizeT len); + +/// @brief Compare memory regions. +IMPORT_C SInt64 MmCmpMemory(_Input VoidPtr dest, _Input VoidPtr src, _Input SizeT len); + +/// @brief Fill memory region. +IMPORT_C VoidPtr MmFillMemory(_Input VoidPtr dest, _Input SizeT len, _Input UInt8 value); + +/// @brief Compare string regions. +IMPORT_C SInt64 MmStrCmp(_Input const Char* dest, _Input const Char* src); + +/// @brief Get length of string. +IMPORT_C SInt64 MmStrLen(const Char* str); + +// ------------------------------------------------------------------------ +// @brief Error API. +// ------------------------------------------------------------------------ + +IMPORT_C SInt32 ErrGetLastError(Void); + +// ------------------------------------------------------------------------ +// @brief Threading API. +// ------------------------------------------------------------------------ + +/// @brief Exit the current thread. +/// @param exit_code the exit code. +IMPORT_C SInt32 ThrExitCurrentThread(_Input SInt32 exit_code); + +/// @brief Exit the main thread. +/// @param exit_code the exit code. +IMPORT_C SInt32 ThrExitMainThread(_Input SInt32 exit_code); + +/// @brief Exit a thread. +/// @param thread the thread to exit. +/// @param exit_code the exit code. +IMPORT_C SInt32 ThrExitThread(_Input ThreadRef thread, _Input SInt32 exit_code); + +/// @brief Thread procedure function type. +typedef SInt32 (*ThrProcKind)(SInt32 argc, Char** argv); + +/// @brief Creates a thread. +/// @param procedure the thread procedure. +/// @param argument_count number of arguments inside that thread. +/// @param flags Thread flags. +/// @return the thread object. +IMPORT_C ThreadRef ThrCreateThread(const Char* thread_name, ThrProcKind procedure, + SInt32 argument_count, SInt32 flags); + +/// @brief Yields the current thread. +/// @param thread the thread to yield. +IMPORT_C SInt32 ThrYieldThread(ThreadRef thrd); + +/// @brief Joins a thread. +/// @param thread the thread to join. +IMPORT_C SInt32 ThrJoinThread(ThreadRef thrd); + +/// @brief Detach a thread. +/// @param thread the thread to detach. +IMPORT_C SInt32 ThrDetachThread(ThreadRef thrd); + +// ------------------------------------------------------------------------ +// @brief Drive Management API. +// ------------------------------------------------------------------------ + +// ------------------------------------------------------------------------------------------ // +/// @brief Get the default drive letter. +/// @param void. +/// @return the drive letter. +// ------------------------------------------------------------------------------------------ // +IMPORT_C Char* DrvGetDefaultDriveLetter(Void); + +// ------------------------------------------------------------------------------------------ // +/// @brief Get the drive letter from a path. +/// @param path the path. +/// @return the drive letter. +// ------------------------------------------------------------------------------------------ // +IMPORT_C Char* DrvGetDriveLetterFromPath(_Input const Char* path); + +// ------------------------------------------------------------------------------------------ // +/// @brief Get a mounted drive from a letter. +/// @param letter the letter (A..Z). +/// @return the drive object. +// ------------------------------------------------------------------------------------------ // +IMPORT_C Ref DrvGetMountedDrive(_Input Char letter); + +// ------------------------------------------------------------------------------------------ // +/// @brief Mount a drive. +/// @param path the path to mount. +/// @param letter the letter to mount. +// ------------------------------------------------------------------------------------------ // +IMPORT_C Void DrvMountDrive(_Input const Char* path, _Input const Char* letter); + +// ------------------------------------------------------------------------------------------ // +/// @brief Unmount a drive. +/// @param letter the letter to unmount. +// ------------------------------------------------------------------------------------------ // +IMPORT_C Void DrvUnmountDrive(_Input Char letter); + +// ------------------------------------------------------------------------ +// Event handling API, use to listen to OS specific events. +// ------------------------------------------------------------------------ + +// ------------------------------------------------------------------------------------------ // +/// @brief Add an event listener. +/// @param event_name the event name. +/// @param listener the listener to add. +/// @return the event listener. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C Void EvtAddListener(_Input const Char* event_name, _Input Ref listener); + +// ------------------------------------------------------------------------------------------ // +/// @brief Remove an event listener. +/// @param event_name the event name. +/// @param listener the listener to remove. +/// @return the event listener. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C Void EvtRemoveListener(_Input const Char* event_name, _Input Ref listener); + +// ------------------------------------------------------------------------------------------ // +/// @brief Dispatch an event. +/// @param event_name the event name. +/// @param event_data the event data. +/// @return the event data. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C VoidPtr EvtDispatchEvent(_Input const Char* event_name, _Input VoidPtr event_data); + +// ------------------------------------------------------------------------------------------ // +// Power API. +// ------------------------------------------------------------------------------------------ // + +enum { + kPowerCodeInvalid = 0, + kPowerCodeShutdown = 12, + kPowerCodeReboot, + kPowerCodeSleep, + kPowerCodeWake, + kPowerCodeCount, +}; + +IMPORT_C SInt32 PwrReadCode(_Output SInt32& code); + +IMPORT_C SInt32 PwrSendCode(_Output SInt32& code); + +// ------------------------------------------------------------------------------------------ // +// CD-ROM API. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C IORef CdOpenTray(Void); + +IMPORT_C SInt32 CdEjectDrive(_Input IORef cdrom); + +IMPORT_C SInt32 CdCloseTray(Void); + +// ------------------------------------------------------------------------------------------ // +// TTY API. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C SInt32 PrintOut(IORef file /* nullptr to direct to stdout */, const Char* fmt, ...); + +IMPORT_C SInt32 PrintIn(IORef file /* nullptr to direct to stdout */, const Char* fmt, ...); + +IMPORT_C IORef PrintCreate(Void); + +IMPORT_C SInt32 PrintRelease(IORef); + +IMPORT_C IORef PrintGet(const Char* path); + +// ------------------------------------------------------------------------------------------ // +// @brief Scheduler/Debug API. +// ------------------------------------------------------------------------------------------ // + +typedef SInt32 AffinityRef; +typedef UInt64 ProcessRef; + +IMPORT_C SInt32 SchedSetAffinity(_Input ProcessRef, SInt32 req, _Input AffinityRef*); + +IMPORT_C SInt32 SchedGetAffinity(_Input ProcessRef, _InOut AffinityRef*); + +IMPORT_C SInt32 SchedFireSignal(_Input ProcessRef, SInt32); + +IMPORT_C SInt32 SchedReadMemory(_Input ProcessRef, SInt32, SInt32); + +IMPORT_C SInt32 SchedWriteMemory(_Input ProcessRef, SInt32, SInt32); + +IMPORT_C UIntPtr SchedGetCurrentProcessID(Void); + +// ------------------------------------------------------------------------------------------ // +// @brief Filesystem API. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C BOOL FsCopy(const Char* path, const Char* dst); + +IMPORT_C BOOL FsMove(const Char* path, const Char* dst); + +IMPORT_C BOOL FsExists(const Char* path); + +IMPORT_C BOOL FsCreateDir(const Char* path); + +IMPORT_C BOOL FsCreateFile(const Char* path); + +IMPORT_C BOOL FsCreateAlias(const Char* path, const Char* from); + +// ------------------------------------------------------------------------------------------ // +// @brief Installable Filesystem API. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C BOOL IfsMount(const Char* path, const Char* drive_letter); + +IMPORT_C BOOL IfsUnmount(const Char* drive_letter); + +IMPORT_C BOOL IfsIsMounted(const Char* drive_letter); + +// ------------------------------------------------------------------------------------------ // +// @brief String Manip API. +// ------------------------------------------------------------------------------------------ // + +IMPORT_C Char* StrFmt(const Char* fmt, ...); + +IMPORT_C UInt64 StrMathToNumber(const Char* in, const Char** endp, const SInt16 base); + +#endif // ifndef LIBSYS_SYSTEM_CALLS_H diff --git a/src/libSystem/SystemKit/Verify.h b/src/libSystem/SystemKit/Verify.h new file mode 100644 index 00000000..7d15435a --- /dev/null +++ b/src/libSystem/SystemKit/Verify.h @@ -0,0 +1,40 @@ +/* ======================================== + + Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + + File: Verify.h + Purpose: System Call Interface Verification Layer. + + ======================================== */ + +#pragma once + +#include + +namespace LibSystem::Verify { +/// @author 0xf00sec, and Amlal El Mahrouss +/// @brief safe cast operator. +template +inline R sys_safe_cast(const T* ptr) { + _rtl_assert(ptr, "safe cast failed!"); + return static_cast(const_cast(ptr)); +} + +template +struct must_cast_traits { + constexpr static BOOL value = false; +}; + +template +struct must_cast_traits { + constexpr static BOOL value = true; +}; + +/// @author Amlal El Mahrouss +/// @brief Safe constexpr cast. +template +inline constexpr R* sys_constexpr_cast(T* ptr) { + static_assert(must_cast_traits::value, "constexpr cast failed! types are mismatching!"); + return static_cast(ptr); +} +} // namespace LibSystem::Verify diff --git a/src/libSystem/docs/SPECIFICATION_SYSCALLS.md b/src/libSystem/docs/SPECIFICATION_SYSCALLS.md new file mode 100644 index 00000000..89f61498 --- /dev/null +++ b/src/libSystem/docs/SPECIFICATION_SYSCALLS.md @@ -0,0 +1,25 @@ +=================================== +# 0: General Information +=================================== + +- **Programming Language**: C / C++ +- **Build System**: Make / NeBuild +- **Purpose**: System Call Interface (SCI) for NeKernel + +=================================== +# 1: How It Works +=================================== + +- This header provides the raw API surface for accessing NeKernel's system calls. + +- It is **not** directly used by applications. + - Instead, it is abstracted by the **SystemSDK**, which presents a stable, high-level interface. + +- At runtime: + - System calls are routed from user-space code to the **kernel syscall manager**. + - The syscall manager executes the requested operation and returns control to `libSystem`. + - Finally, the result is delivered back to the originating process. + +- This separation ensures that: + - The SCI remains low-level and close to the ABI. + - `SystemSDK` provides portability and shielding from changes in syscall internals. \ No newline at end of file diff --git a/src/libSystem/libSystem.json b/src/libSystem/libSystem.json new file mode 100644 index 00000000..9df1b8f0 --- /dev/null +++ b/src/libSystem/libSystem.json @@ -0,0 +1,20 @@ +{ + "compiler_path": "x86_64-w64-mingw32-g++", + "compiler_std": "c++20", + "headers_path": ["../", "./"], + "sources_path": ["src/*.cc", "src/*.stub.obj"], + "output_name": "libSystem.dll", + "compiler_flags": [ + "-ffreestanding", + "-shared", + "-fPIC", + "-fno-rtti", + "-fno-exceptions", + "-Wl,--subsystem=17" + ], + "cpp_macros": [ + "kLibSystemVersion=0x0100", + "kLibSystemVersionHighest=0x0100", + "kLibSystemVersionLowest=0x0100" + ] +} diff --git a/src/libSystem/obj/.keep b/src/libSystem/obj/.keep new file mode 100644 index 00000000..e69de29b diff --git a/src/libSystem/src/JailCalls.cc b/src/libSystem/src/JailCalls.cc new file mode 100644 index 00000000..f7ca5bec --- /dev/null +++ b/src/libSystem/src/JailCalls.cc @@ -0,0 +1,17 @@ +/* ======================================== + + Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#include +#include +#include +#include +#include + +using namespace LibSystem; + +IMPORT_C struct JAIL* JailGetCurrent(Void) { + return (struct JAIL*) libsys_syscall_arg_1(SYSCALL_HASH("JailGetCurrent")); +} \ No newline at end of file diff --git a/src/libSystem/src/Makefile b/src/libSystem/src/Makefile new file mode 100644 index 00000000..622223b4 --- /dev/null +++ b/src/libSystem/src/Makefile @@ -0,0 +1,16 @@ +################################################## +# (c) Amlal El Mahrouss and NeKernel contributors, licensed under the Apache 2.0 license. +# This file is for libSystem.dll's syscall stubs. +################################################## + +ASM=nasm +FLAGS=-f win64 + +.PHONY: error +error: + @echo "==> Invalid recipe." + @echo "==> Use libsys_asm_io_ instead." + +.PHONY: libsys_asm_io_x64 +libsys_asm_io_x64: + $(ASM) $(FLAGS) SystemCallsABI+AMD64.asm -o SystemCallsABI+AMD64.stub.obj diff --git a/src/libSystem/src/SystemCalls.cc b/src/libSystem/src/SystemCalls.cc new file mode 100644 index 00000000..7409c9b7 --- /dev/null +++ b/src/libSystem/src/SystemCalls.cc @@ -0,0 +1,169 @@ +/* ======================================== + + Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#include +#include +#include +#include + +using namespace LibSystem; + +IMPORT_C Char* StrFmt(const Char* fmt, ...) { + if (!fmt || *fmt == 0) return const_cast("(null)"); + + return const_cast(""); +} + +// memmove-style copy +IMPORT_C VoidPtr MmCopyMemory(_Input VoidPtr dest, _Input VoidPtr src, _Input SizeT len) { + // handles overlap, prefers 64-bit word copies when aligned + if (!len || !dest || !src) return nullptr; + + auto s = static_cast(src); + auto d = static_cast(dest); + + if (d == s) return dest; + + // decide direction + if (d > s && d < s + len) { + const UInt8* rs = s + len; + UInt8* rd = d + len; + + // try 64-bit aligned backward copy + if (len >= sizeof(UInt64) && (reinterpret_cast(rs) % sizeof(UInt64) == 0) && + (reinterpret_cast(rd) % sizeof(UInt64) == 0)) { + auto rsw = reinterpret_cast(rs); + auto rdw = reinterpret_cast(rd); + + SizeT words = len / sizeof(UInt64); + + for (SizeT i = 0; i < words; ++i) { + rdw[-1 - static_cast(i)] = rsw[-1 - static_cast(i)]; + } + + SizeT rem = len % sizeof(UInt64); + for (SizeT i = 0; i < rem; ++i) { + rd[-1 - i] = rs[-1 - i]; + } + } else { + // byte-wise backward + for (SizeT i = 0; i < len; ++i) { + rd[-1 - i] = rs[-1 - i]; + } + } + } else { + // try 64-bit aligned forward copy + if (len >= sizeof(UInt64) && (reinterpret_cast(s) % sizeof(UInt64) == 0) && + (reinterpret_cast(d) % sizeof(UInt64) == 0)) { + auto sw = reinterpret_cast(s); + auto dw = reinterpret_cast(d); + SizeT words = len / sizeof(UInt64); + + for (SizeT i = 0; i < words; ++i) { + dw[i] = sw[i]; + } + + SizeT rem = len % sizeof(UInt64); + const SizeT offset = words * sizeof(UInt64); + for (SizeT i = 0; i < rem; ++i) { + d[offset + i] = s[offset + i]; + } + } else { + for (SizeT i = 0; i < len; ++i) { + d[i] = s[i]; + } + } + } + + return dest; +} + +IMPORT_C SInt64 MmStrLen(const Char* in) { + // strlen via pointer walk + if (!in) return -kErrorInvalidData; + + const Char* p = in; + while (*p) ++p; + + return static_cast(p - in); +} + +IMPORT_C VoidPtr MmFillMemory(_Input VoidPtr dest, _Input SizeT len, _Input UInt8 value) { + if (!len || !dest) return nullptr; + + auto d = static_cast(dest); + + if (len >= sizeof(UInt64) && (reinterpret_cast(d) % sizeof(UInt64)) == 0) { + UInt64 pattern = static_cast(value); + pattern |= (pattern << 8); + pattern |= (pattern << 16); + pattern |= (pattern << 32); + + auto dw = reinterpret_cast(d); + SizeT words = len / sizeof(UInt64); + + for (SizeT i = 0; i < words; ++i) { + dw[i] = pattern; + } + + SizeT rem = len % sizeof(UInt64); + const SizeT offset = words * sizeof(UInt64); + for (SizeT i = 0; i < rem; ++i) { + d[offset + i] = value; + } + } else { + for (SizeT i = 0; i < len; ++i) d[i] = value; + } + + return dest; +} + +IMPORT_C Ref IoOpenFile(_Input const Char* path, _Input const Char* drv_letter) { + return static_cast(libsys_syscall_arg_3( + SYSCALL_HASH("IoOpenFile"), Verify::sys_safe_cast(path), Verify::sys_safe_cast(drv_letter))); +} + +IMPORT_C Void IoCloseFile(_Input Ref desc) { + libsys_syscall_arg_2(SYSCALL_HASH("IoCloseFile"), static_cast(desc)); +} + +IMPORT_C UInt64 IoSeekFile(_Input Ref desc, _Input UInt64 off) { + auto ret_ptr = libsys_syscall_arg_3(SYSCALL_HASH("IoSeekFile"), static_cast(desc), + reinterpret_cast(&off)); + + if (!ret_ptr) return ~0UL; + + auto ret = static_cast(ret_ptr); + UInt64 result = *ret; + MUST_PASS(result != ~0UL); + return result; +} + +IMPORT_C UInt64 IoTellFile(_Input Ref desc) { + auto ret_ptr = libsys_syscall_arg_2(SYSCALL_HASH("IoTellFile"), static_cast(desc)); + if (!ret_ptr) return ~0UL; + auto ret = static_cast(ret_ptr); + return *ret; +} + +IMPORT_C SInt32 PrintOut(_Input IORef desc, const Char* fmt, ...) { + va_list args; + va_start(args, fmt); + + auto buf = StrFmt(fmt, args); + + va_end(args); + + // if truncated, `needed` >= kBufferSz; we still send truncated buffer + auto ret_ptr = libsys_syscall_arg_3(SYSCALL_HASH("PrintOut"), static_cast(desc), + Verify::sys_safe_cast(buf)); + + if (!ret_ptr) return -kErrorInvalidData; + + auto ret = static_cast(ret_ptr); + + return *ret; +} diff --git a/src/libSystem/src/SystemCallsABI+AMD64.asm b/src/libSystem/src/SystemCallsABI+AMD64.asm new file mode 100644 index 00000000..dd8fc9e8 --- /dev/null +++ b/src/libSystem/src/SystemCallsABI+AMD64.asm @@ -0,0 +1,81 @@ +;; /* +;; * ======================================================== +;; * +;; * libSystem/src/SystemCallsABI+AMD64.asm +;; * Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. +;; * +;; * ======================================================== +;; */ + +[bits 64] + +section .text + +global libsys_syscall_arg_1 +global libsys_syscall_arg_2 +global libsys_syscall_arg_3 +global libsys_syscall_arg_4 + +libsys_syscall_arg_1: + push rbp + mov rbp, rsp + + mov r8, rcx + + xor rax, rax + + syscall + + pop rbp + + ret + +libsys_syscall_arg_2: + push rbp + mov rbp, rsp + + mov r8, rcx + mov r9, rdx + + xor rax, rax + + syscall + + pop rbp + + ret + +libsys_syscall_arg_3: + push rbp + mov rbp, rsp + + mov r8, rcx + mov r9, rdx + mov r10, rbx + + xor rax, rax + + syscall + + pop rbp + + ret + +libsys_syscall_arg_4: + push rbp + mov rbp, rsp + + mov rax, r8 + + mov r8, rcx + mov r9, rdx + mov r10, rbx + mov r11, rax + + xor rax, rax + + syscall + + pop rbp + + ret diff --git a/src/libSystem/src/Utils.cc b/src/libSystem/src/Utils.cc new file mode 100644 index 00000000..9d0920e0 --- /dev/null +++ b/src/libSystem/src/Utils.cc @@ -0,0 +1,29 @@ +/* ======================================== + + Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#include +#include +#include +#include + +using namespace LibSystem; + +/// @note This uses the FNV 64-bit variant. +IMPORT_C UInt64 libsys_hash_64(const Char* path) { + if (!path || *path == 0) return 0; + + const UInt64 kFNVSeed = 0xcbf29ce484222325ULL; + const UInt64 kFNVPrime = 0x100000001b3ULL; + + UInt64 hash = kFNVSeed; + + while (*path) { + hash ^= (Char) (*path++); + hash *= kFNVPrime; + } + + return hash; +} diff --git a/src/libSystem/src/VerifyCalls.cc b/src/libSystem/src/VerifyCalls.cc new file mode 100644 index 00000000..1c00612f --- /dev/null +++ b/src/libSystem/src/VerifyCalls.cc @@ -0,0 +1,18 @@ +/* ======================================== + + Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#include +#include +#include + +using namespace LibSystem; + +IMPORT_C Void _rtl_assert(Bool expr, const Char* origin) { + if (!expr) { + PrintOut(nullptr, "Assertion failed: %s\r", origin); + libsys_syscall_arg_1(SYSCALL_HASH("_rtl_debug_break")); + } +} \ No newline at end of file -- cgit v1.2.3