From b8f7ef086d1d1b1cd686fff04d0a587f8fd39d81 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 27 Mar 2025 17:24:21 +0100 Subject: add: new driver device kit API. (DDK) refactor: rename SCIKit -> user (then libuser.dylib) boot/modules/netboot: fixed compilation for amd64. Signed-off-by: Amlal El Mahrouss --- dev/ddk/ddk.h | 112 +++++++++++++++++++++++++++++++++ dev/ddk/ddk.json | 23 +++++++ dev/ddk/dev.h | 35 +++++++++++ dev/ddk/docs/SPECIFICATION_DDK.md | 18 ++++++ dev/ddk/io.h | 18 ++++++ dev/ddk/src/ddk_alloc.c | 36 +++++++++++ dev/ddk/src/ddk_dev.c | 30 +++++++++ dev/ddk/src/ddk_io.c | 37 +++++++++++ dev/ddk/src/ddk_kernel_call.c | 60 ++++++++++++++++++ dev/ddk/src/ddk_kernel_call_dispatch.S | 36 +++++++++++ dev/ddk/src/ddk_rt_cxx.cc | 29 +++++++++ dev/ddk/src/ddk_str.c | 40 ++++++++++++ dev/ddk/src/ddk_ver.c | 25 ++++++++ dev/ddk/str.h | 17 +++++ 14 files changed, 516 insertions(+) create mode 100644 dev/ddk/ddk.h create mode 100644 dev/ddk/ddk.json create mode 100644 dev/ddk/dev.h create mode 100644 dev/ddk/docs/SPECIFICATION_DDK.md create mode 100644 dev/ddk/io.h create mode 100644 dev/ddk/src/ddk_alloc.c create mode 100644 dev/ddk/src/ddk_dev.c create mode 100644 dev/ddk/src/ddk_io.c create mode 100644 dev/ddk/src/ddk_kernel_call.c create mode 100644 dev/ddk/src/ddk_kernel_call_dispatch.S create mode 100644 dev/ddk/src/ddk_rt_cxx.cc create mode 100644 dev/ddk/src/ddk_str.c create mode 100644 dev/ddk/src/ddk_ver.c create mode 100644 dev/ddk/str.h (limited to 'dev/ddk') diff --git a/dev/ddk/ddk.h b/dev/ddk/ddk.h new file mode 100644 index 00000000..f6f8d48e --- /dev/null +++ b/dev/ddk/ddk.h @@ -0,0 +1,112 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + FILE: ddk.h + PURPOSE: DDK Driver model base header. + +------------------------------------------- */ + +#pragma once + +#include +#include + +#if defined(__cplusplus) +#define BOOL bool +#define YES true +#define NO false +#define DDK_EXTERN extern "C" __declspec(dllexport) +#define nil nullptr +#undef NULL +#define NULL 0 +#define DDK_FINAL final +#else +#define BOOL char +#define YES 1 +#define NO 0 +#define DDK_EXTERN extern __declspec(dllexport) +#define nil ((void*)0) +#undef NULL +#define NULL ((void*)0) +#define DDK_FINAL +#endif // defined(__cplusplus) + +#ifndef __DDK__ +#undef DDK_EXTERN +#if defined(__cplusplus) +#define DDK_EXTERN extern "C" __declspec(dllimport) +#else +#define DDK_EXTERN __declspec(dllimport) +#endif +#endif + +#define ATTRIBUTE(X) __attribute__((X)) + +#ifndef __NEOSKRNL__ +#error !!! Do not include header in EL0/Ring 3 mode !!! +#endif // __MINOSKRNL__ + +struct DDK_STATUS_STRUCT; +struct DDK_OBJECT_MANIFEST; + +/// \brief Object handle manifest. +struct DDK_OBJECT_MANIFEST DDK_FINAL +{ + char* p_name; + int32_t p_kind; + void* p_object; +}; + +/// \brief DDK status ping structure. +struct DDK_STATUS_STRUCT DDK_FINAL +{ + int32_t s_action_id; + int32_t s_issuer_id; + int32_t s_group_id; + void* s_object; +}; + +/// @brief Call Kernel procedure. +/// @param name the procedure name. +/// @param cnt number of elements in **dat** +/// @param dat data argument pointer. +/// @param sz sz of whole data argument pointer. +/// @return result of call +DDK_EXTERN void* ke_call(const char* name, int32_t cnt, void* dat, size_t sz); + +/// @brief add a system call. +/// @param slot system call slot id. +/// @param slotFn, syscall slot. +DDK_EXTERN void ke_add_syscall(const int32_t slot, void (*slotFn)(void* a0)); + +/// @brief Allocates an heap ptr. +/// @param sz size of the allocated struct/type. +/// @return the pointer allocated or **nil**. +DDK_EXTERN void* kalloc(size_t sz); + +/// @brief Frees an heap ptr. +/// @param pointer kernel pointer to free. +DDK_EXTERN void kfree(void* the_ptr); + +/// @brief Gets a Kernel object. +/// @param slot object id (can be 0) +/// @param name the property's name. +/// @return DDK_OBJECT_MANIFEST. +DDK_EXTERN struct DDK_OBJECT_MANIFEST* ke_get_obj(const int slot, const char* name); + +/// @brief Set a Kernel object. +/// @param slot object id (can be 0) +/// @param name the property's name. +/// @param ddk_pr pointer to a object's DDK_OBJECT_MANIFEST. +/// @return returned object. +DDK_EXTERN void* ke_set_obj(const int32_t slot, const struct DDK_OBJECT_MANIFEST* ddk_pr); + +/// @brief The highest API version of the DDK. +DDK_EXTERN int32_t kApiVersionHighest; + +/// @brief The lowest API version of the DDK. +DDK_EXTERN int32_t kApiVersionLowest; + +/// @brief API version in BCD. +DDK_EXTERN int32_t kApiVersion; diff --git a/dev/ddk/ddk.json b/dev/ddk/ddk.json new file mode 100644 index 00000000..ffc05f5f --- /dev/null +++ b/dev/ddk/ddk.json @@ -0,0 +1,23 @@ +{ + "compiler_path": "x86_64-w64-mingw32-gcc", + "compiler_std": "c++20", + "headers_path": ["../", "./"], + "sources_path": ["src/*.c", "src/*.cc", "src/*.S"], + "output_name": "ddk.sys", + "compiler_flags": [ + "-ffreestanding", + "-shared", + "-std=c17", + "-fno-rtti", + "-fno-exceptions", + "-Wl,--subsystem=17" + ], + "cpp_macros": [ + "__NEOSKRNL__", + "__DDK_AMD64__", + "__DDK__", + "kDDKVersionHighest=0x0100", + "kDDKVersionLowest=0x0100", + "kDDKVersion=0x0100" + ] +} diff --git a/dev/ddk/dev.h b/dev/ddk/dev.h new file mode 100644 index 00000000..98979e52 --- /dev/null +++ b/dev/ddk/dev.h @@ -0,0 +1,35 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + File: dev.h + Purpose: DDK device support. + +------------------------------------------- */ + +#pragma once + +#include + +struct _DDK_DEVICE; + +#define DDK_DEVICE_NAME_LEN (255) + +/// @brief Kernel Device driver. +typedef struct _DDK_DEVICE DDK_FINAL +{ + char d_name[DDK_DEVICE_NAME_LEN]; // the device name. Could be /./DEVICE_NAME/ + void* (*d_read)(void* arg, int len); // read from device. + void (*d_write)(void* arg, int len); + void (*d_wait)(void); // write to device. + struct _DDK_DEVICE* (*d_open)(const char* path); // open device. + void (*d_close)(struct _DDK_DEVICE* dev); // close device. +} DDK_DEVICE, *DDK_DEVICE_PTR; + +/// @brief Open a new device from path. +/// @param path the device's path. +DDK_EXTERN DDK_DEVICE_PTR open(const char* path); + +/// @brief Close any device. +/// @param device valid device. +DDK_EXTERN BOOL close(DDK_DEVICE_PTR device); diff --git a/dev/ddk/docs/SPECIFICATION_DDK.md b/dev/ddk/docs/SPECIFICATION_DDK.md new file mode 100644 index 00000000..5fbff990 --- /dev/null +++ b/dev/ddk/docs/SPECIFICATION_DDK.md @@ -0,0 +1,18 @@ +=================================== + +# 0: General Information + +=================================== + +- Programming Language: C/C++ +- Build System: Make/BTB +- Purpose: Driver Tool Kit, which you link against libddk.sys + +=================================== + +# 1: How It works + +=================================== + +- Driver shall directly call the kernel at specific ports. (Or a kernel call) +- Kernel must respond according to kernel call, otherwise a panic will occur. \ No newline at end of file diff --git a/dev/ddk/io.h b/dev/ddk/io.h new file mode 100644 index 00000000..cfd6d2d2 --- /dev/null +++ b/dev/ddk/io.h @@ -0,0 +1,18 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK Text I/O. + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief print character into UART. +DDK_EXTERN void kputc(const char ch); + +/// @brief print string to UART. +/// @param message string to transmit to UART. +DDK_EXTERN void kprint(const char* message); diff --git a/dev/ddk/src/ddk_alloc.c b/dev/ddk/src/ddk_alloc.c new file mode 100644 index 00000000..9d0ac0db --- /dev/null +++ b/dev/ddk/src/ddk_alloc.c @@ -0,0 +1,36 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK allocator. + +------------------------------------------- */ + +#include + +/** + \brief Allocates a new heap on the Kernel's side. + \param sz the size of the heap block. + \return the newly allocated pointer. +*/ +DDK_EXTERN void* kalloc(size_t sz) +{ + if (!sz) + ++sz; + + void* ptr = ke_call("mm_new_heap", 1, &sz, sizeof(size_t)); + + return ptr; +} + +/** + \brief Frees a pointer from the heap. + \param ptr the pointer to free. +*/ +DDK_EXTERN void kfree(void* ptr) +{ + if (!ptr) + return; + + ke_call("mm_delete_heap", 1, ptr, 0); +} diff --git a/dev/ddk/src/ddk_dev.c b/dev/ddk/src/ddk_dev.c new file mode 100644 index 00000000..7514bf84 --- /dev/null +++ b/dev/ddk/src/ddk_dev.c @@ -0,0 +1,30 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK Text I/O. + +------------------------------------------- */ + +#include +#include + +/// @brief Open a new binary device from path. +DDK_EXTERN DDK_DEVICE_PTR open(const char* devicePath) +{ + if (!devicePath) + return nil; + + return ke_call("sk_open_dev", 1, (void*)devicePath, kstrlen(devicePath)); +} + +/// @brief Close any device. +/// @param device valid device. +DDK_EXTERN BOOL close(DDK_DEVICE_PTR device) +{ + if (!device) + return NO; + + ke_call("sk_close_dev", 1, device, sizeof(DDK_DEVICE)); + return YES; +} diff --git a/dev/ddk/src/ddk_io.c b/dev/ddk/src/ddk_io.c new file mode 100644 index 00000000..0e10a0ad --- /dev/null +++ b/dev/ddk/src/ddk_io.c @@ -0,0 +1,37 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK Text I/O. + +------------------------------------------- */ + +#include + +DDK_EXTERN void kputc(const char ch) +{ + char assembled[2] = {0}; + assembled[0] = ch; + assembled[1] = 0; + + ke_call("ke_put_string", 1, assembled, 1); +} + +/// @brief print string to UART. +/// @param message UART to transmit. +DDK_EXTERN void kprint(const char* message) +{ + if (!message) + return; + if (*message == 0) + return; + + size_t index = 0; + size_t len = kstrlen(message); + + while (index < len) + { + kputc(message[index]); + ++index; + } +} diff --git a/dev/ddk/src/ddk_kernel_call.c b/dev/ddk/src/ddk_kernel_call.c new file mode 100644 index 00000000..71dbebeb --- /dev/null +++ b/dev/ddk/src/ddk_kernel_call.c @@ -0,0 +1,60 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK Kernel call. + +------------------------------------------- */ + +#include +#include + +/// @brief this is an internal call, do not use it. +DDK_EXTERN ATTRIBUTE(naked) void* ke_call_dispatch(const char* name, int32_t cnt, void* data, size_t sz); + +/// @brief Interupt Kernel and call it's RPC. +/// @param KernelRpcName RPC name +/// @param cnt number of elements in **data** pointer. +/// @param data data pointer. +/// @param sz The size of the whole data pointer. +/// @retval void* Kernel call was successful. +/// @retval nil Kernel call failed, call KernelLastError(void) +DDK_EXTERN void* ke_call(const char* name, int32_t cnt, void* data, size_t sz) +{ + if (!name || *name == 0 || cnt == 0) + return nil; + + return ke_call_dispatch(name, cnt, data, sz); +} + +/// @brief Add system call. +/// @param slot system call slot +/// @param slotFn, syscall slot. +DDK_EXTERN void ke_add_syscall(const int slot, void (*slotFn)(void* a0)) +{ + ke_call("ke_add_syscall", slot, slotFn, 1); +} + +/// @brief Get a Kernel object. +/// @param slot property id (always 0) +/// @param name the object's name. +/// @return Object manifest. +DDK_EXTERN struct DDK_OBJECT_MANIFEST* ke_get_obj(const int slot, const char* name) +{ + struct DDK_OBJECT_MANIFEST* manifest = (struct DDK_OBJECT_MANIFEST*)ke_call("cf_get_kobj", slot, (void*)name, 1); + + if (!manifest) + return nil; + + return manifest; +} + +/// @brief Set a Kernel object. +/// @param slot property id (always 0) +/// @param name the object's name. +/// @param ddk_pr pointer to a object's DDK_OBJECT_MANIFEST. +/// @return property's object. +DDK_EXTERN void* ke_set_obj(const int slot, const struct DDK_OBJECT_MANIFEST* ddk_pr) +{ + return ke_call("cf_set_kobj", slot, (void*)ddk_pr, 1); +} diff --git a/dev/ddk/src/ddk_kernel_call_dispatch.S b/dev/ddk/src/ddk_kernel_call_dispatch.S new file mode 100644 index 00000000..9b32d0c2 --- /dev/null +++ b/dev/ddk/src/ddk_kernel_call_dispatch.S @@ -0,0 +1,36 @@ +/** + lang: asm + compiler: gnu + */ + +.globl ke_call_dispatch + +.text + +/* Really simple function, takes our va-list, + and brings it to the trap handler in the Kernel. */ + +#if defined(__DDK_AMD64__) + +/* args rcx, rdx, r8, r9 */ +ke_call_dispatch: + int $0x33 + ret + +#elif defined(__DDK_POWER64__) + +/* args r8, r9, r10, r11 */ +ke_call_dispatch: + /* There is no specific interrupt request id for a system call in POWER. */ + sc + blr + +#elif defined(__DDK_ARM64__) + +/* args x0, x8, x9, x10, x11 is kept to tell that this is a Kernel call */ +ke_call_dispatch: + /* There is no specific interrupt request id for a system call in ARM64 as well. */ + mov x9, #0x33 + svc #0 + +#endif diff --git a/dev/ddk/src/ddk_rt_cxx.cc b/dev/ddk/src/ddk_rt_cxx.cc new file mode 100644 index 00000000..1ac66457 --- /dev/null +++ b/dev/ddk/src/ddk_rt_cxx.cc @@ -0,0 +1,29 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK C++ runtime. + +------------------------------------------- */ + +#include + +void* operator new(size_t sz) +{ + return kalloc(sz); +} + +void operator delete(void* ptr) +{ + kfree(ptr); +} + +void* operator new[](size_t sz) +{ + return kalloc(sz); +} + +void operator delete[](void* ptr) +{ + kfree(ptr); +} diff --git a/dev/ddk/src/ddk_str.c b/dev/ddk/src/ddk_str.c new file mode 100644 index 00000000..1558e636 --- /dev/null +++ b/dev/ddk/src/ddk_str.c @@ -0,0 +1,40 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK Strings. + +------------------------------------------- */ + +#include + +DDK_EXTERN size_t kstrlen(const char* in) +{ + if (in == nil) + return 0; + + if (*in == 0) + return 0; + + size_t index = 0; + + while (in[index] != 0) + { + ++index; + } + + return index; +} + +DDK_EXTERN int kstrncpy(char* dst, const char* src, size_t len) +{ + size_t index = 0; + + while (index != len) + { + dst[index] = src[index]; + ++index; + } + + return index; +} diff --git a/dev/ddk/src/ddk_ver.c b/dev/ddk/src/ddk_ver.c new file mode 100644 index 00000000..9641fb34 --- /dev/null +++ b/dev/ddk/src/ddk_ver.c @@ -0,0 +1,25 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK version symbols. + +------------------------------------------- */ + +#include + +#ifndef kDDKVersionHighest +#define kDDKVersionHighest 1 +#endif // !kDDKVersionHighest + +#ifndef kDDKVersionLowest +#define kDDKVersionLowest 1 +#endif // !kDDKVersionLowest + +#ifndef kDDKVersion +#define kDDKVersion 1 +#endif // !kDDKVersion + +int32_t kApiVersionHighest = kDDKVersionHighest; +int32_t kApiVersionLowest = kDDKVersionLowest; +int32_t kApiVersion = kDDKVersion; diff --git a/dev/ddk/str.h b/dev/ddk/str.h new file mode 100644 index 00000000..e1e206a8 --- /dev/null +++ b/dev/ddk/str.h @@ -0,0 +1,17 @@ +/* ------------------------------------------- + + Copyright Amlal EL Mahrouss. + + Purpose: DDK Strings. + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief DDK equivalent of POSIX's string.h +/// @file str.h + +DDK_EXTERN size_t kstrlen(const char* in); +DDK_EXTERN int kstrncpy(char* dst, const char* src, size_t len); -- cgit v1.2.3