From 439479a3fa02f1fecc5a3a77e8ffa528e9616c42 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Thu, 23 Apr 2026 21:47:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=A8=8B=E5=BA=8F=E5=A5=97?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + README.zh-CN.md | 1 + kit/.gitignore | 3 + kit/CMakeLists.txt | 234 ++++++++++ kit/Makefile | 64 +++ kit/README.md | 97 ++++ kit/README.zh-CN.md | 97 ++++ kit/apps/hello/main.c | 6 + kit/include/cleonos_rust_bridge.h | 9 + kit/include/cleonos_stdio.h | 6 + kit/include/cleonos_syscall.h | 256 +++++++++++ kit/include/cleonos_version.h | 6 + kit/include/ctype.h | 16 + kit/include/dlfcn.h | 8 + kit/include/stdio.h | 27 ++ kit/include/stdlib.h | 36 ++ kit/include/string.h | 29 ++ kit/linker/user.ld | 29 ++ kit/runtime/dlfcn.c | 48 ++ kit/runtime/libc_ctype.c | 45 ++ kit/runtime/libc_stdlib.c | 254 +++++++++++ kit/runtime/libc_string.c | 445 +++++++++++++++++++ kit/runtime/main_adapter.c | 8 + kit/runtime/runtime.c | 53 +++ kit/runtime/stdio.c | 712 ++++++++++++++++++++++++++++++ kit/runtime/syscall.c | 413 +++++++++++++++++ wine/License | 51 +++ 27 files changed, 2954 insertions(+) create mode 100644 kit/.gitignore create mode 100644 kit/CMakeLists.txt create mode 100644 kit/Makefile create mode 100644 kit/README.md create mode 100644 kit/README.zh-CN.md create mode 100644 kit/apps/hello/main.c create mode 100644 kit/include/cleonos_rust_bridge.h create mode 100644 kit/include/cleonos_stdio.h create mode 100644 kit/include/cleonos_syscall.h create mode 100644 kit/include/cleonos_version.h create mode 100644 kit/include/ctype.h create mode 100644 kit/include/dlfcn.h create mode 100644 kit/include/stdio.h create mode 100644 kit/include/stdlib.h create mode 100644 kit/include/string.h create mode 100644 kit/linker/user.ld create mode 100644 kit/runtime/dlfcn.c create mode 100644 kit/runtime/libc_ctype.c create mode 100644 kit/runtime/libc_stdlib.c create mode 100644 kit/runtime/libc_string.c create mode 100644 kit/runtime/main_adapter.c create mode 100644 kit/runtime/runtime.c create mode 100644 kit/runtime/stdio.c create mode 100644 kit/runtime/syscall.c create mode 100644 wine/License diff --git a/README.md b/README.md index e76ff7c..617b072 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Experimental x86_64 operating system project with a C kernel, Rust-assisted runt . |- clks/ # CLKS kernel submodule (standalone kernel repository) |- cleonos/ # Userland runtime, libc-like layer, user apps, Rust user library +|- kit/ # Standalone user-app SDK (build ELF without kernel source tree) |- ramdisk/ # Static files copied into runtime ramdisk |- configs/ # Boot configuration (Limine) |- cmake/ # Shared CMake scripts (tool checks, logging, limine setup) diff --git a/README.zh-CN.md b/README.zh-CN.md index 9c4cb2c..9807686 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -22,6 +22,7 @@ . |- clks/ # CLKS 内核子模块(独立内核仓库) |- cleonos/ # 用户态运行时、基础库、用户应用、Rust 用户库 +|- kit/ # 独立用户态应用 SDK(无需内核源码树即可构建 ELF) |- ramdisk/ # 运行时 ramdisk 的静态文件 |- configs/ # 启动配置(Limine) |- cmake/ # CMake 公共脚本(工具检查、日志、limine 初始化) diff --git a/kit/.gitignore b/kit/.gitignore new file mode 100644 index 0000000..095e9d9 --- /dev/null +++ b/kit/.gitignore @@ -0,0 +1,3 @@ +build/ +build-cmake/ +build-cmake-*/ diff --git a/kit/CMakeLists.txt b/kit/CMakeLists.txt new file mode 100644 index 0000000..ec4a88b --- /dev/null +++ b/kit/CMakeLists.txt @@ -0,0 +1,234 @@ +cmake_minimum_required(VERSION 3.20) +project(CLeonOSKit NONE) + +set(CLEONOS_KIT_APPS_DIR "${CMAKE_SOURCE_DIR}/apps" CACHE PATH "Directory containing app subdirectories") +set(CLEONOS_KIT_RUNTIME_DIR "${CMAKE_SOURCE_DIR}/runtime" CACHE PATH "Directory containing user runtime sources") +set(CLEONOS_KIT_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include" CACHE PATH "Directory containing user runtime headers") +set(CLEONOS_KIT_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/linker/user.ld" CACHE FILEPATH "Linker script for user ELF") +set(CLEONOS_KIT_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/build/apps" CACHE PATH "Output directory for generated ELF files") +set(CLEONOS_KIT_OBJ_DIR "${CMAKE_SOURCE_DIR}/build/obj" CACHE PATH "Output directory for object files") +set(CLEONOS_KIT_APP_NAMES "" CACHE STRING "Optional app list, separated by comma/semicolon (empty means all apps)") +set(CLEONOS_KIT_USE_MAIN_ADAPTER ON CACHE BOOL "When ON, apps can provide plain main(int,char**)") +set(CLEONOS_KIT_ENABLE_WERROR ON CACHE BOOL "Treat warnings as errors") + +set(CLEONOS_KIT_CC "x86_64-elf-gcc" CACHE STRING "C compiler for user ELF objects") +set(CLEONOS_KIT_LD "x86_64-elf-ld" CACHE STRING "Linker for user ELF") + +function(resolve_tool_with_fallback VAR_NAME) + set(_fallbacks ${ARGN}) + set(_requested "${${VAR_NAME}}") + + if("${_requested}" STREQUAL "") + message(FATAL_ERROR "empty tool variable: ${VAR_NAME}") + endif() + + if(IS_ABSOLUTE "${_requested}") + if(NOT EXISTS "${_requested}") + message(FATAL_ERROR "${VAR_NAME} not found: ${_requested}") + endif() + set(_resolved "${_requested}") + else() + unset(_requested_path CACHE) + unset(_requested_path) + find_program(_requested_path NAMES "${_requested}") + if(_requested_path) + set(_resolved "${_requested_path}") + else() + set(_resolved "") + foreach(_cand IN LISTS _fallbacks) + unset(_cand_path CACHE) + unset(_cand_path) + find_program(_cand_path NAMES "${_cand}") + if(_cand_path) + message(STATUS "${VAR_NAME} '${_requested}' not found; fallback to '${_cand}'") + set(_resolved "${_cand_path}") + break() + endif() + endforeach() + if("${_resolved}" STREQUAL "") + message(FATAL_ERROR "${VAR_NAME} tool not found: '${_requested}', fallbacks='${_fallbacks}'") + endif() + endif() + endif() + + set(${VAR_NAME} "${_resolved}" CACHE STRING "resolved tool path" FORCE) + set(${VAR_NAME} "${_resolved}" PARENT_SCOPE) +endfunction() + +resolve_tool_with_fallback(CLEONOS_KIT_CC gcc clang cc) +resolve_tool_with_fallback(CLEONOS_KIT_LD ld ld.lld) + +execute_process( + COMMAND ${CLEONOS_KIT_LD} -V + RESULT_VARIABLE _ld_probe_rc + OUTPUT_VARIABLE _ld_probe_out + ERROR_VARIABLE _ld_probe_err +) + +execute_process( + COMMAND ${CLEONOS_KIT_LD} --help + RESULT_VARIABLE _ld_help_rc + OUTPUT_VARIABLE _ld_help_out + ERROR_VARIABLE _ld_help_err +) + +set(_ld_probe_text "${_ld_probe_out}\n${_ld_probe_err}\n${_ld_help_out}\n${_ld_help_err}") +string(TOLOWER "${_ld_probe_text}" _ld_probe_lower) + +if(_ld_probe_lower MATCHES "i386pep" + OR _ld_probe_lower MATCHES "pei-" + OR _ld_probe_lower MATCHES "pe-coff" + OR _ld_probe_lower MATCHES "appcontainer" + OR _ld_probe_lower MATCHES "auto-import") + message(FATAL_ERROR + "selected linker appears to target PE/COFF, not ELF. " + "Use an ELF toolchain, for example: " + "-DCLEONOS_KIT_CC=x86_64-elf-gcc -DCLEONOS_KIT_LD=x86_64-elf-ld") +endif() + +if(NOT EXISTS "${CLEONOS_KIT_LINKER_SCRIPT}") + message(FATAL_ERROR "missing linker script: ${CLEONOS_KIT_LINKER_SCRIPT}") +endif() + +if(NOT IS_DIRECTORY "${CLEONOS_KIT_APPS_DIR}") + message(FATAL_ERROR "missing apps directory: ${CLEONOS_KIT_APPS_DIR}") +endif() + +if(NOT IS_DIRECTORY "${CLEONOS_KIT_RUNTIME_DIR}") + message(FATAL_ERROR "missing runtime directory: ${CLEONOS_KIT_RUNTIME_DIR}") +endif() + +if(NOT IS_DIRECTORY "${CLEONOS_KIT_INCLUDE_DIR}") + message(FATAL_ERROR "missing include directory: ${CLEONOS_KIT_INCLUDE_DIR}") +endif() + +file(MAKE_DIRECTORY "${CLEONOS_KIT_OUTPUT_DIR}") +file(MAKE_DIRECTORY "${CLEONOS_KIT_OBJ_DIR}") + +set(_runtime_sources + "${CLEONOS_KIT_RUNTIME_DIR}/runtime.c" + "${CLEONOS_KIT_RUNTIME_DIR}/syscall.c" + "${CLEONOS_KIT_RUNTIME_DIR}/stdio.c" + "${CLEONOS_KIT_RUNTIME_DIR}/libc_string.c" + "${CLEONOS_KIT_RUNTIME_DIR}/libc_stdlib.c" + "${CLEONOS_KIT_RUNTIME_DIR}/libc_ctype.c" + "${CLEONOS_KIT_RUNTIME_DIR}/dlfcn.c" +) + +if(CLEONOS_KIT_USE_MAIN_ADAPTER) + list(APPEND _runtime_sources "${CLEONOS_KIT_RUNTIME_DIR}/main_adapter.c") +endif() + +foreach(_src IN LISTS _runtime_sources) + if(NOT EXISTS "${_src}") + message(FATAL_ERROR "missing runtime source: ${_src}") + endif() +endforeach() + +set(CLEONOS_KIT_CFLAGS + -std=c11 + -ffreestanding + -fno-stack-protector + -fno-builtin + -Wall + -Wextra + -m64 + -mno-red-zone + -fno-pic + -fno-pie + "-I${CLEONOS_KIT_INCLUDE_DIR}" +) + +if(CLEONOS_KIT_ENABLE_WERROR) + list(APPEND CLEONOS_KIT_CFLAGS -Werror) +endif() + +set(CLEONOS_KIT_LDFLAGS "" CACHE STRING "Extra linker flags (semicolon separated)") + +function(cleonos_compile_object SRC_PATH OUT_VAR) + file(RELATIVE_PATH _rel "${CMAKE_SOURCE_DIR}" "${SRC_PATH}") + string(REGEX REPLACE "\\.c$" ".o" _obj_rel "${_rel}") + set(_obj_path "${CLEONOS_KIT_OBJ_DIR}/${_obj_rel}") + get_filename_component(_obj_dir "${_obj_path}" DIRECTORY) + + add_custom_command( + OUTPUT "${_obj_path}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${_obj_dir}" + COMMAND ${CLEONOS_KIT_CC} ${CLEONOS_KIT_CFLAGS} -c "${SRC_PATH}" -o "${_obj_path}" + DEPENDS "${SRC_PATH}" + VERBATIM + ) + + set(${OUT_VAR} "${_obj_path}" PARENT_SCOPE) +endfunction() + +function(cleonos_kit_add_app APP_NAME) + set(_app_sources ${ARGN}) + + if(NOT _app_sources) + message(FATAL_ERROR "cleonos_kit_add_app(${APP_NAME}) requires at least one source") + endif() + + set(_obj_list) + foreach(_src IN LISTS _runtime_sources _app_sources) + cleonos_compile_object("${_src}" _obj) + list(APPEND _obj_list "${_obj}") + endforeach() + + set(_out_path "${CLEONOS_KIT_OUTPUT_DIR}/${APP_NAME}.elf") + add_custom_command( + OUTPUT "${_out_path}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CLEONOS_KIT_OUTPUT_DIR}" + COMMAND ${CLEONOS_KIT_LD} ${CLEONOS_KIT_LDFLAGS} -T "${CLEONOS_KIT_LINKER_SCRIPT}" -o "${_out_path}" ${_obj_list} + DEPENDS ${_obj_list} "${CLEONOS_KIT_LINKER_SCRIPT}" + VERBATIM + ) + + add_custom_target("app-${APP_NAME}" DEPENDS "${_out_path}") + set_property(GLOBAL APPEND PROPERTY CLEONOS_KIT_APP_TARGETS "app-${APP_NAME}") + set_property(GLOBAL APPEND PROPERTY CLEONOS_KIT_APP_OUTPUTS "${_out_path}") +endfunction() + +set(_app_names) +if("${CLEONOS_KIT_APP_NAMES}" STREQUAL "") + file(GLOB _app_entries RELATIVE "${CLEONOS_KIT_APPS_DIR}" "${CLEONOS_KIT_APPS_DIR}/*") + foreach(_entry IN LISTS _app_entries) + if(IS_DIRECTORY "${CLEONOS_KIT_APPS_DIR}/${_entry}") + list(APPEND _app_names "${_entry}") + endif() + endforeach() +else() + string(REPLACE "," ";" _app_names "${CLEONOS_KIT_APP_NAMES}") +endif() + +list(REMOVE_DUPLICATES _app_names) +list(SORT _app_names) + +if(NOT _app_names) + message(FATAL_ERROR "no apps selected/found under ${CLEONOS_KIT_APPS_DIR}") +endif() + +foreach(_app IN LISTS _app_names) + if(NOT IS_DIRECTORY "${CLEONOS_KIT_APPS_DIR}/${_app}") + message(FATAL_ERROR "app directory not found: ${CLEONOS_KIT_APPS_DIR}/${_app}") + endif() + + file(GLOB_RECURSE _app_sources CONFIGURE_DEPENDS "${CLEONOS_KIT_APPS_DIR}/${_app}/*.c") + if(NOT _app_sources) + message(FATAL_ERROR "no C sources found for app '${_app}' in ${CLEONOS_KIT_APPS_DIR}/${_app}") + endif() + + cleonos_kit_add_app("${_app}" ${_app_sources}) +endforeach() + +get_property(_kit_targets GLOBAL PROPERTY CLEONOS_KIT_APP_TARGETS) +get_property(_kit_outputs GLOBAL PROPERTY CLEONOS_KIT_APP_OUTPUTS) + +if(NOT _kit_targets) + message(FATAL_ERROR "no app targets were generated") +endif() + +add_custom_target(apps ALL DEPENDS ${_kit_targets}) + +message(STATUS "CLeonOS kit apps: ${_app_names}") +message(STATUS "CLeonOS kit output: ${CLEONOS_KIT_OUTPUT_DIR}") diff --git a/kit/Makefile b/kit/Makefile new file mode 100644 index 0000000..7aa5faa --- /dev/null +++ b/kit/Makefile @@ -0,0 +1,64 @@ +.RECIPEPREFIX := > +MAKEFLAGS += --no-print-directory + +CMAKE ?= cmake +CMAKE_BUILD_DIR ?= build-cmake +CMAKE_BUILD_TYPE ?= Release +CMAKE_GENERATOR ?= +CMAKE_EXTRA_ARGS ?= +APPS ?= +WERROR ?= ON +KIT_CC ?= +KIT_LD ?= + +ifeq ($(strip $(CMAKE_GENERATOR)),) +GEN_ARG := +else +GEN_ARG := -G "$(CMAKE_GENERATOR)" +endif + +APPS_ARG := +ifneq ($(strip $(APPS)),) +APPS_ARG := -DCLEONOS_KIT_APP_NAMES=$(APPS) +endif + +KIT_CC_ARG := +ifneq ($(strip $(KIT_CC)),) +KIT_CC_ARG := -DCLEONOS_KIT_CC=$(KIT_CC) +endif + +KIT_LD_ARG := +ifneq ($(strip $(KIT_LD)),) +KIT_LD_ARG := -DCLEONOS_KIT_LD=$(KIT_LD) +endif + +.PHONY: all configure reconfigure apps clean clean-all help + +all: apps + +configure: +> @$(CMAKE) -S . -B $(CMAKE_BUILD_DIR) $(GEN_ARG) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) -DCLEONOS_KIT_ENABLE_WERROR=$(WERROR) $(APPS_ARG) $(KIT_CC_ARG) $(KIT_LD_ARG) $(CMAKE_EXTRA_ARGS) + +reconfigure: +> @$(CMAKE) -E rm -rf $(CMAKE_BUILD_DIR) +> @$(MAKE) configure CMAKE_BUILD_TYPE="$(CMAKE_BUILD_TYPE)" CMAKE_GENERATOR="$(CMAKE_GENERATOR)" CMAKE_EXTRA_ARGS="$(CMAKE_EXTRA_ARGS)" APPS="$(APPS)" WERROR="$(WERROR)" KIT_CC="$(KIT_CC)" KIT_LD="$(KIT_LD)" + +apps: configure +> @$(CMAKE) --build $(CMAKE_BUILD_DIR) --target apps + +clean: +> @if [ -d "$(CMAKE_BUILD_DIR)" ]; then \ +> $(CMAKE) --build $(CMAKE_BUILD_DIR) --target clean; \ +> fi + +clean-all: +> @$(CMAKE) -E rm -rf $(CMAKE_BUILD_DIR) build + +help: +> @echo "CLeonOS kit build wrapper" +> @echo " make apps" +> @echo " make apps APPS=hello" +> @echo " make apps APPS=hello,foo" +> @echo " make apps KIT_CC=x86_64-elf-gcc KIT_LD=x86_64-elf-ld" +> @echo " make clean" +> @echo " make clean-all" diff --git a/kit/README.md b/kit/README.md new file mode 100644 index 0000000..e61a6a9 --- /dev/null +++ b/kit/README.md @@ -0,0 +1,97 @@ +# CLeonOS App Kit + +[English](README.md) | [简体中文](README.zh-CN.md) + +`kit/` is a standalone user-app SDK for CLeonOS. +It builds ring3 ELF apps **without** depending on CLKS kernel source. + +## Toolchain + +Use an **ELF** toolchain (not MinGW PE/COFF): + +- Recommended: `x86_64-elf-gcc` + `x86_64-elf-ld` +- Alternative: `clang` + ELF-mode `ld.lld` + +## What Is Included + +- User runtime (`runtime/`) copied from CLeonOS userland +- Syscall/libc-like headers (`include/`) +- User linker script (`linker/user.ld`) +- CMake project and Makefile wrapper +- Sample app: `apps/hello/main.c` + +Default sample behavior: +- prints `Hello world!` + +## Quick Start + +```bash +cd kit +make apps +``` + +Output ELF files are generated under: + +```text +kit/build/apps/*.elf +``` + +## Build Only Specific Apps + +Build one app: + +```bash +make apps APPS=hello +``` + +Build multiple apps: + +```bash +make apps APPS=hello,foo,bar +``` + +Each app must be a directory under `apps//` with one or more `.c` files. + +## App Entry + +By default, kit enables `runtime/main_adapter.c`, so your app can define standard: + +```c +int main(int argc, char **argv) +``` + +If you need raw CLeonOS entry (`cleonos_app_main(int,char**,char**)`), configure with: + +```bash +cmake -S . -B build-cmake -DCLEONOS_KIT_USE_MAIN_ADAPTER=OFF +``` + +## CMake Direct Usage + +```bash +cmake -S . -B build-cmake -DCMAKE_BUILD_TYPE=Release +cmake --build build-cmake --target apps +``` + +Explicit ELF toolchain example: + +```bash +cmake -S . -B build-cmake \ + -DCLEONOS_KIT_CC=x86_64-elf-gcc \ + -DCLEONOS_KIT_LD=x86_64-elf-ld +cmake --build build-cmake --target apps +``` + +Useful options: + +- `-DCLEONOS_KIT_APP_NAMES=hello,foo` +- `-DCLEONOS_KIT_ENABLE_WERROR=OFF` +- `-DCLEONOS_KIT_OUTPUT_DIR=` + +## Add New App + +1. Create directory: `apps/myapp/` +2. Add source file(s), for example `apps/myapp/main.c` +3. Rebuild with `make apps` + +Kit auto-discovers app directories. diff --git a/kit/README.zh-CN.md b/kit/README.zh-CN.md new file mode 100644 index 0000000..1cb913d --- /dev/null +++ b/kit/README.zh-CN.md @@ -0,0 +1,97 @@ +# CLeonOS 应用开发套件 + +[English](README.md) | [简体中文](README.zh-CN.md) + +`kit/` 是一个独立的 CLeonOS 用户态应用 SDK。 +它可以在**不依赖 CLKS 内核源码**的情况下构建 ring3 ELF 程序。 + +## 工具链要求 + +请使用 **ELF** 目标工具链(不要使用 MinGW 的 PE/COFF 目标): + +- 推荐:`x86_64-elf-gcc` + `x86_64-elf-ld` +- 备选:`clang` + ELF 模式 `ld.lld` + +## 套件内容 + +- 来自 CLeonOS 用户态的运行时实现(`runtime/`) +- syscall / libc 风格头文件(`include/`) +- 用户态链接脚本(`linker/user.ld`) +- 独立的 CMake 工程和 Makefile 包装 +- 示例程序:`apps/hello/main.c` + +默认示例行为: +- 输出 `Hello world!` + +## 快速开始 + +```bash +cd kit +make apps +``` + +生成的 ELF 位于: + +```text +kit/build/apps/*.elf +``` + +## 仅构建指定应用 + +只构建一个: + +```bash +make apps APPS=hello +``` + +构建多个: + +```bash +make apps APPS=hello,foo,bar +``` + +每个应用应放在 `apps//` 目录,并包含一个或多个 `.c` 文件。 + +## 程序入口 + +默认启用 `runtime/main_adapter.c`,因此应用可以直接写标准入口: + +```c +int main(int argc, char **argv) +``` + +如果你要使用原始入口 `cleonos_app_main(int,char**,char**)`,可关闭适配器: + +```bash +cmake -S . -B build-cmake -DCLEONOS_KIT_USE_MAIN_ADAPTER=OFF +``` + +## 直接使用 CMake + +```bash +cmake -S . -B build-cmake -DCMAKE_BUILD_TYPE=Release +cmake --build build-cmake --target apps +``` + +显式指定 ELF 工具链示例: + +```bash +cmake -S . -B build-cmake \ + -DCLEONOS_KIT_CC=x86_64-elf-gcc \ + -DCLEONOS_KIT_LD=x86_64-elf-ld +cmake --build build-cmake --target apps +``` + +常用选项: + +- `-DCLEONOS_KIT_APP_NAMES=hello,foo` +- `-DCLEONOS_KIT_ENABLE_WERROR=OFF` +- `-DCLEONOS_KIT_OUTPUT_DIR=` + +## 新增应用 + +1. 创建目录:`apps/myapp/` +2. 添加源码(例如 `apps/myapp/main.c`) +3. 执行 `make apps` + +kit 会自动扫描并构建应用目录。 diff --git a/kit/apps/hello/main.c b/kit/apps/hello/main.c new file mode 100644 index 0000000..5f60df6 --- /dev/null +++ b/kit/apps/hello/main.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("Hello world!\n"); + return 0; +} diff --git a/kit/include/cleonos_rust_bridge.h b/kit/include/cleonos_rust_bridge.h new file mode 100644 index 0000000..b363677 --- /dev/null +++ b/kit/include/cleonos_rust_bridge.h @@ -0,0 +1,9 @@ +#ifndef CLEONOS_RUST_BRIDGE_H +#define CLEONOS_RUST_BRIDGE_H + +typedef unsigned long long u64; +typedef unsigned long long usize; + +u64 cleonos_rust_guarded_len(const unsigned char *ptr, usize max_len); + +#endif diff --git a/kit/include/cleonos_stdio.h b/kit/include/cleonos_stdio.h new file mode 100644 index 0000000..be99024 --- /dev/null +++ b/kit/include/cleonos_stdio.h @@ -0,0 +1,6 @@ +#ifndef CLEONOS_STDIO_H +#define CLEONOS_STDIO_H + +#include + +#endif diff --git a/kit/include/cleonos_syscall.h b/kit/include/cleonos_syscall.h new file mode 100644 index 0000000..9320b97 --- /dev/null +++ b/kit/include/cleonos_syscall.h @@ -0,0 +1,256 @@ +#ifndef CLEONOS_SYSCALL_H +#define CLEONOS_SYSCALL_H + +typedef unsigned long long u64; +typedef unsigned long long usize; + +#define CLEONOS_FS_NAME_MAX 96ULL +#define CLEONOS_PROC_PATH_MAX 192ULL + +#define CLEONOS_PROC_STATE_UNUSED 0ULL +#define CLEONOS_PROC_STATE_PENDING 1ULL +#define CLEONOS_PROC_STATE_RUNNING 2ULL +#define CLEONOS_PROC_STATE_EXITED 3ULL +#define CLEONOS_PROC_STATE_STOPPED 4ULL + +#define CLEONOS_SIGKILL 9ULL +#define CLEONOS_SIGTERM 15ULL +#define CLEONOS_SIGCONT 18ULL +#define CLEONOS_SIGSTOP 19ULL + +#define CLEONOS_O_RDONLY 0x0000ULL +#define CLEONOS_O_WRONLY 0x0001ULL +#define CLEONOS_O_RDWR 0x0002ULL +#define CLEONOS_O_CREAT 0x0040ULL +#define CLEONOS_O_TRUNC 0x0200ULL +#define CLEONOS_O_APPEND 0x0400ULL +#define CLEONOS_FD_INHERIT ((u64) - 1) + +typedef struct cleonos_proc_snapshot { + u64 pid; + u64 ppid; + u64 state; + u64 started_tick; + u64 exited_tick; + u64 exit_status; + u64 runtime_ticks; + u64 mem_bytes; + u64 tty_index; + u64 last_signal; + u64 last_fault_vector; + u64 last_fault_error; + u64 last_fault_rip; + char path[CLEONOS_PROC_PATH_MAX]; +} cleonos_proc_snapshot; + +typedef struct cleonos_fb_info { + u64 width; + u64 height; + u64 pitch; + u64 bpp; +} cleonos_fb_info; + +typedef struct cleonos_fb_blit_req { + u64 pixels_ptr; + u64 src_width; + u64 src_height; + u64 src_pitch_bytes; + u64 dst_x; + u64 dst_y; + u64 scale; +} cleonos_fb_blit_req; + +#define CLEONOS_SYSCALL_LOG_WRITE 0ULL +#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL +#define CLEONOS_SYSCALL_TASK_COUNT 2ULL +#define CLEONOS_SYSCALL_CUR_TASK 3ULL +#define CLEONOS_SYSCALL_SERVICE_COUNT 4ULL +#define CLEONOS_SYSCALL_SERVICE_READY_COUNT 5ULL +#define CLEONOS_SYSCALL_CONTEXT_SWITCHES 6ULL +#define CLEONOS_SYSCALL_KELF_COUNT 7ULL +#define CLEONOS_SYSCALL_KELF_RUNS 8ULL +#define CLEONOS_SYSCALL_FS_NODE_COUNT 9ULL +#define CLEONOS_SYSCALL_FS_CHILD_COUNT 10ULL +#define CLEONOS_SYSCALL_FS_GET_CHILD_NAME 11ULL +#define CLEONOS_SYSCALL_FS_READ 12ULL +#define CLEONOS_SYSCALL_EXEC_PATH 13ULL +#define CLEONOS_SYSCALL_EXEC_REQUESTS 14ULL +#define CLEONOS_SYSCALL_EXEC_SUCCESS 15ULL +#define CLEONOS_SYSCALL_USER_SHELL_READY 16ULL +#define CLEONOS_SYSCALL_USER_EXEC_REQUESTED 17ULL +#define CLEONOS_SYSCALL_USER_LAUNCH_TRIES 18ULL +#define CLEONOS_SYSCALL_USER_LAUNCH_OK 19ULL +#define CLEONOS_SYSCALL_USER_LAUNCH_FAIL 20ULL +#define CLEONOS_SYSCALL_TTY_COUNT 21ULL +#define CLEONOS_SYSCALL_TTY_ACTIVE 22ULL +#define CLEONOS_SYSCALL_TTY_SWITCH 23ULL +#define CLEONOS_SYSCALL_TTY_WRITE 24ULL +#define CLEONOS_SYSCALL_TTY_WRITE_CHAR 25ULL +#define CLEONOS_SYSCALL_KBD_GET_CHAR 26ULL +#define CLEONOS_SYSCALL_FS_STAT_TYPE 27ULL +#define CLEONOS_SYSCALL_FS_STAT_SIZE 28ULL +#define CLEONOS_SYSCALL_FS_MKDIR 29ULL +#define CLEONOS_SYSCALL_FS_WRITE 30ULL +#define CLEONOS_SYSCALL_FS_APPEND 31ULL +#define CLEONOS_SYSCALL_FS_REMOVE 32ULL +#define CLEONOS_SYSCALL_LOG_JOURNAL_COUNT 33ULL +#define CLEONOS_SYSCALL_LOG_JOURNAL_READ 34ULL +#define CLEONOS_SYSCALL_KBD_BUFFERED 35ULL +#define CLEONOS_SYSCALL_KBD_PUSHED 36ULL +#define CLEONOS_SYSCALL_KBD_POPPED 37ULL +#define CLEONOS_SYSCALL_KBD_DROPPED 38ULL +#define CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES 39ULL +#define CLEONOS_SYSCALL_GETPID 40ULL +#define CLEONOS_SYSCALL_SPAWN_PATH 41ULL +#define CLEONOS_SYSCALL_WAITPID 42ULL +#define CLEONOS_SYSCALL_EXIT 43ULL +#define CLEONOS_SYSCALL_SLEEP_TICKS 44ULL +#define CLEONOS_SYSCALL_YIELD 45ULL +#define CLEONOS_SYSCALL_SHUTDOWN 46ULL +#define CLEONOS_SYSCALL_RESTART 47ULL +#define CLEONOS_SYSCALL_AUDIO_AVAILABLE 48ULL +#define CLEONOS_SYSCALL_AUDIO_PLAY_TONE 49ULL +#define CLEONOS_SYSCALL_AUDIO_STOP 50ULL +#define CLEONOS_SYSCALL_EXEC_PATHV 51ULL +#define CLEONOS_SYSCALL_SPAWN_PATHV 52ULL +#define CLEONOS_SYSCALL_PROC_ARGC 53ULL +#define CLEONOS_SYSCALL_PROC_ARGV 54ULL +#define CLEONOS_SYSCALL_PROC_ENVC 55ULL +#define CLEONOS_SYSCALL_PROC_ENV 56ULL +#define CLEONOS_SYSCALL_PROC_LAST_SIGNAL 57ULL +#define CLEONOS_SYSCALL_PROC_FAULT_VECTOR 58ULL +#define CLEONOS_SYSCALL_PROC_FAULT_ERROR 59ULL +#define CLEONOS_SYSCALL_PROC_FAULT_RIP 60ULL +#define CLEONOS_SYSCALL_PROC_COUNT 61ULL +#define CLEONOS_SYSCALL_PROC_PID_AT 62ULL +#define CLEONOS_SYSCALL_PROC_SNAPSHOT 63ULL +#define CLEONOS_SYSCALL_PROC_KILL 64ULL +#define CLEONOS_SYSCALL_KDBG_SYM 65ULL +#define CLEONOS_SYSCALL_KDBG_BT 66ULL +#define CLEONOS_SYSCALL_KDBG_REGS 67ULL +#define CLEONOS_SYSCALL_STATS_TOTAL 68ULL +#define CLEONOS_SYSCALL_STATS_ID_COUNT 69ULL +#define CLEONOS_SYSCALL_STATS_RECENT_WINDOW 70ULL +#define CLEONOS_SYSCALL_STATS_RECENT_ID 71ULL +#define CLEONOS_SYSCALL_FD_OPEN 72ULL +#define CLEONOS_SYSCALL_FD_READ 73ULL +#define CLEONOS_SYSCALL_FD_WRITE 74ULL +#define CLEONOS_SYSCALL_FD_CLOSE 75ULL +#define CLEONOS_SYSCALL_FD_DUP 76ULL +#define CLEONOS_SYSCALL_DL_OPEN 77ULL +#define CLEONOS_SYSCALL_DL_CLOSE 78ULL +#define CLEONOS_SYSCALL_DL_SYM 79ULL +#define CLEONOS_SYSCALL_EXEC_PATHV_IO 80ULL +#define CLEONOS_SYSCALL_FB_INFO 81ULL +#define CLEONOS_SYSCALL_FB_BLIT 82ULL +#define CLEONOS_SYSCALL_FB_CLEAR 83ULL +#define CLEONOS_SYSCALL_KERNEL_VERSION 84ULL +#define CLEONOS_SYSCALL_DISK_PRESENT 85ULL +#define CLEONOS_SYSCALL_DISK_SIZE_BYTES 86ULL +#define CLEONOS_SYSCALL_DISK_SECTOR_COUNT 87ULL +#define CLEONOS_SYSCALL_DISK_FORMATTED 88ULL +#define CLEONOS_SYSCALL_DISK_FORMAT_FAT32 89ULL +#define CLEONOS_SYSCALL_DISK_MOUNT 90ULL +#define CLEONOS_SYSCALL_DISK_MOUNTED 91ULL +#define CLEONOS_SYSCALL_DISK_MOUNT_PATH 92ULL +#define CLEONOS_SYSCALL_DISK_READ_SECTOR 93ULL +#define CLEONOS_SYSCALL_DISK_WRITE_SECTOR 94ULL + +u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); +u64 cleonos_sys_log_write(const char *message, u64 length); +u64 cleonos_sys_timer_ticks(void); +u64 cleonos_sys_task_count(void); +u64 cleonos_sys_service_count(void); +u64 cleonos_sys_service_ready_count(void); +u64 cleonos_sys_context_switches(void); +u64 cleonos_sys_kelf_count(void); +u64 cleonos_sys_kelf_runs(void); +u64 cleonos_sys_fs_node_count(void); +u64 cleonos_sys_fs_child_count(const char *dir_path); +u64 cleonos_sys_fs_get_child_name(const char *dir_path, u64 index, char *out_name); +u64 cleonos_sys_fs_read(const char *path, char *out_buffer, u64 buffer_size); +u64 cleonos_sys_exec_path(const char *path); +u64 cleonos_sys_exec_pathv(const char *path, const char *argv_line, const char *env_line); +u64 cleonos_sys_exec_pathv_io(const char *path, const char *argv_line, const char *env_line, u64 stdin_fd, + u64 stdout_fd, u64 stderr_fd); +u64 cleonos_sys_exec_request_count(void); +u64 cleonos_sys_exec_success_count(void); +u64 cleonos_sys_user_shell_ready(void); +u64 cleonos_sys_user_exec_requested(void); +u64 cleonos_sys_user_launch_tries(void); +u64 cleonos_sys_user_launch_ok(void); +u64 cleonos_sys_user_launch_fail(void); +u64 cleonos_sys_tty_count(void); +u64 cleonos_sys_tty_active(void); +u64 cleonos_sys_tty_switch(u64 tty_index); +u64 cleonos_sys_tty_write(const char *text, u64 length); +u64 cleonos_sys_tty_write_char(char ch); +u64 cleonos_sys_kbd_get_char(void); +u64 cleonos_sys_fs_stat_type(const char *path); +u64 cleonos_sys_fs_stat_size(const char *path); +u64 cleonos_sys_fs_mkdir(const char *path); +u64 cleonos_sys_fs_write(const char *path, const char *data, u64 size); +u64 cleonos_sys_fs_append(const char *path, const char *data, u64 size); +u64 cleonos_sys_fs_remove(const char *path); +u64 cleonos_sys_log_journal_count(void); +u64 cleonos_sys_log_journal_read(u64 index_from_oldest, char *out_line, u64 out_size); +u64 cleonos_sys_kbd_buffered(void); +u64 cleonos_sys_kbd_pushed(void); +u64 cleonos_sys_kbd_popped(void); +u64 cleonos_sys_kbd_dropped(void); +u64 cleonos_sys_kbd_hotkey_switches(void); +u64 cleonos_sys_getpid(void); +u64 cleonos_sys_spawn_path(const char *path); +u64 cleonos_sys_spawn_pathv(const char *path, const char *argv_line, const char *env_line); +u64 cleonos_sys_wait_pid(u64 pid, u64 *out_status); +u64 cleonos_sys_exit(u64 status); +u64 cleonos_sys_sleep_ticks(u64 ticks); +u64 cleonos_sys_yield(void); +u64 cleonos_sys_shutdown(void); +u64 cleonos_sys_restart(void); +u64 cleonos_sys_audio_available(void); +u64 cleonos_sys_audio_play_tone(u64 hz, u64 ticks); +u64 cleonos_sys_audio_stop(void); +u64 cleonos_sys_proc_argc(void); +u64 cleonos_sys_proc_argv(u64 index, char *out_value, u64 out_size); +u64 cleonos_sys_proc_envc(void); +u64 cleonos_sys_proc_env(u64 index, char *out_value, u64 out_size); +u64 cleonos_sys_proc_last_signal(void); +u64 cleonos_sys_proc_fault_vector(void); +u64 cleonos_sys_proc_fault_error(void); +u64 cleonos_sys_proc_fault_rip(void); +u64 cleonos_sys_proc_count(void); +u64 cleonos_sys_proc_pid_at(u64 index, u64 *out_pid); +u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64 out_size); +u64 cleonos_sys_proc_kill(u64 pid, u64 signal); +u64 cleonos_sys_kdbg_sym(u64 addr, char *out_line, u64 out_size); +u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size); +u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size); +u64 cleonos_sys_stats_total(void); +u64 cleonos_sys_stats_id_count(u64 id); +u64 cleonos_sys_stats_recent_window(void); +u64 cleonos_sys_stats_recent_id(u64 id); +u64 cleonos_sys_fd_open(const char *path, u64 flags, u64 mode); +u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size); +u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size); +u64 cleonos_sys_fd_close(u64 fd); +u64 cleonos_sys_fd_dup(u64 fd); +u64 cleonos_sys_dl_open(const char *path); +u64 cleonos_sys_dl_close(u64 handle); +u64 cleonos_sys_dl_sym(u64 handle, const char *symbol); +u64 cleonos_sys_fb_info(cleonos_fb_info *out_info); +u64 cleonos_sys_fb_blit(const cleonos_fb_blit_req *req); +u64 cleonos_sys_fb_clear(u64 rgb); +u64 cleonos_sys_kernel_version(char *out_version, u64 out_size); +u64 cleonos_sys_disk_present(void); +u64 cleonos_sys_disk_size_bytes(void); +u64 cleonos_sys_disk_sector_count(void); +u64 cleonos_sys_disk_formatted(void); +u64 cleonos_sys_disk_format_fat32(const char *label); +u64 cleonos_sys_disk_mount(const char *mount_path); +u64 cleonos_sys_disk_mounted(void); +u64 cleonos_sys_disk_mount_path(char *out_path, u64 out_size); +u64 cleonos_sys_disk_read_sector(u64 lba, void *out_sector); +u64 cleonos_sys_disk_write_sector(u64 lba, const void *sector_data); + +#endif diff --git a/kit/include/cleonos_version.h b/kit/include/cleonos_version.h new file mode 100644 index 0000000..4011f0e --- /dev/null +++ b/kit/include/cleonos_version.h @@ -0,0 +1,6 @@ +#ifndef CLEONOS_VERSION_H +#define CLEONOS_VERSION_H + +#define CLEONOS_VERSION_STRING "1.0.0-alpha" + +#endif diff --git a/kit/include/ctype.h b/kit/include/ctype.h new file mode 100644 index 0000000..93d9f74 --- /dev/null +++ b/kit/include/ctype.h @@ -0,0 +1,16 @@ +#ifndef CLEONOS_LIBC_CTYPE_H +#define CLEONOS_LIBC_CTYPE_H + +int isspace(int ch); +int isdigit(int ch); +int isalpha(int ch); +int isalnum(int ch); +int isxdigit(int ch); +int isupper(int ch); +int islower(int ch); +int isprint(int ch); +int iscntrl(int ch); +int tolower(int ch); +int toupper(int ch); + +#endif diff --git a/kit/include/dlfcn.h b/kit/include/dlfcn.h new file mode 100644 index 0000000..1ceb0d7 --- /dev/null +++ b/kit/include/dlfcn.h @@ -0,0 +1,8 @@ +#ifndef CLEONOS_LIBC_DLFCN_H +#define CLEONOS_LIBC_DLFCN_H + +void *dlopen(const char *path, int flags); +void *dlsym(void *handle, const char *symbol); +int dlclose(void *handle); + +#endif diff --git a/kit/include/stdio.h b/kit/include/stdio.h new file mode 100644 index 0000000..7738b8b --- /dev/null +++ b/kit/include/stdio.h @@ -0,0 +1,27 @@ +#ifndef CLEONOS_LIBC_STDIO_H +#define CLEONOS_LIBC_STDIO_H + +#include + +#ifndef EOF +#define EOF (-1) +#endif + +int putchar(int ch); +int getchar(void); +int fputc(int ch, int fd); +int fgetc(int fd); +int fputs(const char *text, int fd); +int puts(const char *text); + +int vsnprintf(char *out, unsigned long out_size, const char *fmt, va_list args); +int snprintf(char *out, unsigned long out_size, const char *fmt, ...); + +int vdprintf(int fd, const char *fmt, va_list args); +int dprintf(int fd, const char *fmt, ...); +int vfprintf(int fd, const char *fmt, va_list args); +int fprintf(int fd, const char *fmt, ...); +int vprintf(const char *fmt, va_list args); +int printf(const char *fmt, ...); + +#endif diff --git a/kit/include/stdlib.h b/kit/include/stdlib.h new file mode 100644 index 0000000..6c6d30e --- /dev/null +++ b/kit/include/stdlib.h @@ -0,0 +1,36 @@ +#ifndef CLEONOS_LIBC_STDLIB_H +#define CLEONOS_LIBC_STDLIB_H + +#include + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#ifndef RAND_MAX +#define RAND_MAX 32767 +#endif + +int abs(int value); +long labs(long value); +long long llabs(long long value); + +int atoi(const char *text); +long atol(const char *text); +long long atoll(const char *text); +long strtol(const char *text, char **out_end, int base); +unsigned long strtoul(const char *text, char **out_end, int base); +long long strtoll(const char *text, char **out_end, int base); +unsigned long long strtoull(const char *text, char **out_end, int base); + +void srand(unsigned int seed); +int rand(void); + +void exit(int status); +void abort(void); + +#endif diff --git a/kit/include/string.h b/kit/include/string.h new file mode 100644 index 0000000..fb4dc38 --- /dev/null +++ b/kit/include/string.h @@ -0,0 +1,29 @@ +#ifndef CLEONOS_LIBC_STRING_H +#define CLEONOS_LIBC_STRING_H + +#include + +void *memset(void *dst, int value, size_t size); +void *memcpy(void *dst, const void *src, size_t size); +void *memmove(void *dst, const void *src, size_t size); +int memcmp(const void *left, const void *right, size_t size); +void *memchr(const void *src, int value, size_t size); + +size_t strlen(const char *text); +size_t strnlen(const char *text, size_t max_size); +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t size); +int strcmp(const char *left, const char *right); +int strncmp(const char *left, const char *right, size_t size); +char *strchr(const char *text, int ch); +char *strrchr(const char *text, int ch); +char *strstr(const char *haystack, const char *needle); +size_t strspn(const char *text, const char *accept); +size_t strcspn(const char *text, const char *reject); +char *strpbrk(const char *text, const char *accept); +char *strtok_r(char *text, const char *delim, char **saveptr); +char *strtok(char *text, const char *delim); +char *strcat(char *dst, const char *src); +char *strncat(char *dst, const char *src, size_t size); + +#endif diff --git a/kit/linker/user.ld b/kit/linker/user.ld new file mode 100644 index 0000000..e1f0694 --- /dev/null +++ b/kit/linker/user.ld @@ -0,0 +1,29 @@ +OUTPUT_FORMAT(elf64-x86-64) +ENTRY(_start) + +PHDRS { + text PT_LOAD FLAGS(5); + rodata PT_LOAD FLAGS(4); + data PT_LOAD FLAGS(6); +} + +SECTIONS { + . = 0x00400000; + + .text : ALIGN(0x1000) { + *(.text .text.*) + } :text + + .rodata : ALIGN(0x1000) { + *(.rodata .rodata.*) + } :rodata + + .data : ALIGN(0x1000) { + *(.data .data.*) + } :data + + .bss : ALIGN(0x1000) { + *(COMMON) + *(.bss .bss.*) + } :data +} diff --git a/kit/runtime/dlfcn.c b/kit/runtime/dlfcn.c new file mode 100644 index 0000000..fffd616 --- /dev/null +++ b/kit/runtime/dlfcn.c @@ -0,0 +1,48 @@ +#include + +#include + +void *dlopen(const char *path, int flags) { + u64 handle; + + (void)flags; + + if (path == (const char *)0 || path[0] == '\0') { + return (void *)0; + } + + handle = cleonos_sys_dl_open(path); + + if (handle == 0ULL || handle == (u64)-1) { + return (void *)0; + } + + return (void *)handle; +} + +void *dlsym(void *handle, const char *symbol) { + u64 addr; + + if (handle == (void *)0 || symbol == (const char *)0 || symbol[0] == '\0') { + return (void *)0; + } + + addr = cleonos_sys_dl_sym((u64)handle, symbol); + + if (addr == 0ULL || addr == (u64)-1) { + return (void *)0; + } + + return (void *)addr; +} + +int dlclose(void *handle) { + u64 rc; + + if (handle == (void *)0) { + return -1; + } + + rc = cleonos_sys_dl_close((u64)handle); + return (rc == (u64)-1) ? -1 : 0; +} diff --git a/kit/runtime/libc_ctype.c b/kit/runtime/libc_ctype.c new file mode 100644 index 0000000..de5a8b7 --- /dev/null +++ b/kit/runtime/libc_ctype.c @@ -0,0 +1,45 @@ +#include + +int isspace(int ch) { + return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\v' || ch == '\f') ? 1 : 0; +} + +int isdigit(int ch) { + return (ch >= '0' && ch <= '9') ? 1 : 0; +} + +int isalpha(int ch) { + return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) ? 1 : 0; +} + +int isalnum(int ch) { + return (isalpha(ch) != 0 || isdigit(ch) != 0) ? 1 : 0; +} + +int isxdigit(int ch) { + return (isdigit(ch) != 0 || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) ? 1 : 0; +} + +int isupper(int ch) { + return (ch >= 'A' && ch <= 'Z') ? 1 : 0; +} + +int islower(int ch) { + return (ch >= 'a' && ch <= 'z') ? 1 : 0; +} + +int isprint(int ch) { + return (ch >= 0x20 && ch <= 0x7E) ? 1 : 0; +} + +int iscntrl(int ch) { + return (ch >= 0x00 && ch <= 0x1F) || ch == 0x7F ? 1 : 0; +} + +int tolower(int ch) { + return (isupper(ch) != 0) ? (ch - 'A' + 'a') : ch; +} + +int toupper(int ch) { + return (islower(ch) != 0) ? (ch - 'a' + 'A') : ch; +} diff --git a/kit/runtime/libc_stdlib.c b/kit/runtime/libc_stdlib.c new file mode 100644 index 0000000..1cc96cb --- /dev/null +++ b/kit/runtime/libc_stdlib.c @@ -0,0 +1,254 @@ +#include + +#include +#include + +#include + +static int clib_digit_value(int ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + + if (ch >= 'a' && ch <= 'z') { + return 10 + (ch - 'a'); + } + + if (ch >= 'A' && ch <= 'Z') { + return 10 + (ch - 'A'); + } + + return -1; +} + +static const char *clib_skip_space(const char *text) { + const char *p = text; + + if (p == (const char *)0) { + return (const char *)0; + } + + while (*p != '\0' && isspace((unsigned char)*p) != 0) { + p++; + } + + return p; +} + +int abs(int value) { + return (value < 0) ? -value : value; +} + +long labs(long value) { + return (value < 0L) ? -value : value; +} + +long long llabs(long long value) { + return (value < 0LL) ? -value : value; +} + +int atoi(const char *text) { + return (int)strtol(text, (char **)0, 10); +} + +long atol(const char *text) { + return strtol(text, (char **)0, 10); +} + +long long atoll(const char *text) { + return strtoll(text, (char **)0, 10); +} + +unsigned long strtoul(const char *text, char **out_end, int base) { + const char *p = clib_skip_space(text); + int negative = 0; + unsigned long value = 0UL; + int any = 0; + int overflow = 0; + + if (out_end != (char **)0) { + *out_end = (char *)text; + } + + if (p == (const char *)0) { + return 0UL; + } + + if (*p == '+' || *p == '-') { + negative = (*p == '-') ? 1 : 0; + p++; + } + + if (base == 0) { + if (p[0] == '0') { + if ((p[1] == 'x' || p[1] == 'X') && isxdigit((unsigned char)p[2]) != 0) { + base = 16; + p += 2; + } else { + base = 8; + } + } else { + base = 10; + } + } else if (base == 16) { + if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + p += 2; + } + } + + if (base < 2 || base > 36) { + return 0UL; + } + + while (*p != '\0') { + int digit = clib_digit_value((unsigned char)*p); + + if (digit < 0 || digit >= base) { + break; + } + + any = 1; + + if (value > (ULONG_MAX - (unsigned long)digit) / (unsigned long)base) { + overflow = 1; + value = ULONG_MAX; + } else if (overflow == 0) { + value = value * (unsigned long)base + (unsigned long)digit; + } + + p++; + } + + if (any == 0) { + return 0UL; + } + + if (out_end != (char **)0) { + *out_end = (char *)p; + } + + if (negative != 0) { + return (unsigned long)(0UL - value); + } + + return value; +} + +long strtol(const char *text, char **out_end, int base) { + const char *p = clib_skip_space(text); + int negative = 0; + unsigned long long value = 0ULL; + unsigned long long limit; + int any = 0; + int overflow = 0; + + if (out_end != (char **)0) { + *out_end = (char *)text; + } + + if (p == (const char *)0) { + return 0L; + } + + if (*p == '+' || *p == '-') { + negative = (*p == '-') ? 1 : 0; + p++; + } + + if (base == 0) { + if (p[0] == '0') { + if ((p[1] == 'x' || p[1] == 'X') && isxdigit((unsigned char)p[2]) != 0) { + base = 16; + p += 2; + } else { + base = 8; + } + } else { + base = 10; + } + } else if (base == 16) { + if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + p += 2; + } + } + + if (base < 2 || base > 36) { + return 0L; + } + + limit = (negative != 0) ? ((unsigned long long)LONG_MAX + 1ULL) : (unsigned long long)LONG_MAX; + + while (*p != '\0') { + int digit = clib_digit_value((unsigned char)*p); + + if (digit < 0 || digit >= base) { + break; + } + + any = 1; + + if (value > (limit - (unsigned long long)digit) / (unsigned long long)base) { + overflow = 1; + value = limit; + } else if (overflow == 0) { + value = value * (unsigned long long)base + (unsigned long long)digit; + } + + p++; + } + + if (any == 0) { + return 0L; + } + + if (out_end != (char **)0) { + *out_end = (char *)p; + } + + if (overflow != 0) { + return (negative != 0) ? LONG_MIN : LONG_MAX; + } + + if (negative != 0) { + if (value == ((unsigned long long)LONG_MAX + 1ULL)) { + return LONG_MIN; + } + return -(long)value; + } + + return (long)value; +} + +long long strtoll(const char *text, char **out_end, int base) { + return (long long)strtol(text, out_end, base); +} + +unsigned long long strtoull(const char *text, char **out_end, int base) { + return (unsigned long long)strtoul(text, out_end, base); +} + +static unsigned long clib_rand_state = 1UL; + +void srand(unsigned int seed) { + clib_rand_state = (unsigned long)seed; + if (clib_rand_state == 0UL) { + clib_rand_state = 1UL; + } +} + +int rand(void) { + clib_rand_state = (1103515245UL * clib_rand_state) + 12345UL; + return (int)((clib_rand_state >> 16) & (unsigned long)RAND_MAX); +} + +void exit(int status) { + (void)cleonos_sys_exit((u64)(unsigned long long)status); + + for (;;) { + (void)cleonos_sys_yield(); + } +} + +void abort(void) { + exit(EXIT_FAILURE); +} diff --git a/kit/runtime/libc_string.c b/kit/runtime/libc_string.c new file mode 100644 index 0000000..bbb1bd7 --- /dev/null +++ b/kit/runtime/libc_string.c @@ -0,0 +1,445 @@ +#include + +void *memset(void *dst, int value, size_t size) { + unsigned char *d = (unsigned char *)dst; + unsigned char byte = (unsigned char)value; + size_t i; + + if (d == (unsigned char *)0) { + return dst; + } + + for (i = 0U; i < size; i++) { + d[i] = byte; + } + + return dst; +} + +void *memcpy(void *dst, const void *src, size_t size) { + unsigned char *d = (unsigned char *)dst; + const unsigned char *s = (const unsigned char *)src; + size_t i; + + if (d == (unsigned char *)0 || s == (const unsigned char *)0) { + return dst; + } + + for (i = 0U; i < size; i++) { + d[i] = s[i]; + } + + return dst; +} + +void *memmove(void *dst, const void *src, size_t size) { + unsigned char *d = (unsigned char *)dst; + const unsigned char *s = (const unsigned char *)src; + size_t i; + + if (d == (unsigned char *)0 || s == (const unsigned char *)0 || d == s || size == 0U) { + return dst; + } + + if (d < s || d >= s + size) { + for (i = 0U; i < size; i++) { + d[i] = s[i]; + } + } else { + for (i = size; i > 0U; i--) { + d[i - 1U] = s[i - 1U]; + } + } + + return dst; +} + +int memcmp(const void *left, const void *right, size_t size) { + const unsigned char *a = (const unsigned char *)left; + const unsigned char *b = (const unsigned char *)right; + size_t i; + + if (a == b || size == 0U) { + return 0; + } + + if (a == (const unsigned char *)0) { + return -1; + } + + if (b == (const unsigned char *)0) { + return 1; + } + + for (i = 0U; i < size; i++) { + if (a[i] != b[i]) { + return (a[i] < b[i]) ? -1 : 1; + } + } + + return 0; +} + +void *memchr(const void *src, int value, size_t size) { + const unsigned char *s = (const unsigned char *)src; + unsigned char needle = (unsigned char)value; + size_t i; + + if (s == (const unsigned char *)0) { + return (void *)0; + } + + for (i = 0U; i < size; i++) { + if (s[i] == needle) { + return (void *)(s + i); + } + } + + return (void *)0; +} + +size_t strlen(const char *text) { + size_t len = 0U; + + if (text == (const char *)0) { + return 0U; + } + + while (text[len] != '\0') { + len++; + } + + return len; +} + +size_t strnlen(const char *text, size_t max_size) { + size_t len = 0U; + + if (text == (const char *)0) { + return 0U; + } + + while (len < max_size && text[len] != '\0') { + len++; + } + + return len; +} + +char *strcpy(char *dst, const char *src) { + size_t i = 0U; + + if (dst == (char *)0 || src == (const char *)0) { + return dst; + } + + while (src[i] != '\0') { + dst[i] = src[i]; + i++; + } + + dst[i] = '\0'; + return dst; +} + +char *strncpy(char *dst, const char *src, size_t size) { + size_t i = 0U; + + if (dst == (char *)0 || src == (const char *)0) { + return dst; + } + + while (i < size && src[i] != '\0') { + dst[i] = src[i]; + i++; + } + + while (i < size) { + dst[i++] = '\0'; + } + + return dst; +} + +int strcmp(const char *left, const char *right) { + size_t i = 0U; + + if (left == right) { + return 0; + } + + if (left == (const char *)0) { + return -1; + } + + if (right == (const char *)0) { + return 1; + } + + while (left[i] != '\0' && right[i] != '\0') { + if (left[i] != right[i]) { + return (left[i] < right[i]) ? -1 : 1; + } + i++; + } + + if (left[i] == right[i]) { + return 0; + } + + return (left[i] < right[i]) ? -1 : 1; +} + +int strncmp(const char *left, const char *right, size_t size) { + size_t i = 0U; + + if (size == 0U || left == right) { + return 0; + } + + if (left == (const char *)0) { + return -1; + } + + if (right == (const char *)0) { + return 1; + } + + while (i < size && left[i] != '\0' && right[i] != '\0') { + if (left[i] != right[i]) { + return (left[i] < right[i]) ? -1 : 1; + } + i++; + } + + if (i == size) { + return 0; + } + + if (left[i] == right[i]) { + return 0; + } + + return (left[i] < right[i]) ? -1 : 1; +} + +char *strchr(const char *text, int ch) { + char needle = (char)ch; + size_t i = 0U; + + if (text == (const char *)0) { + return (char *)0; + } + + while (text[i] != '\0') { + if (text[i] == needle) { + return (char *)(text + i); + } + i++; + } + + if (needle == '\0') { + return (char *)(text + i); + } + + return (char *)0; +} + +char *strrchr(const char *text, int ch) { + char needle = (char)ch; + const char *last = (const char *)0; + size_t i = 0U; + + if (text == (const char *)0) { + return (char *)0; + } + + while (text[i] != '\0') { + if (text[i] == needle) { + last = text + i; + } + i++; + } + + if (needle == '\0') { + return (char *)(text + i); + } + + return (char *)last; +} + +char *strstr(const char *haystack, const char *needle) { + size_t i; + size_t j; + size_t nlen; + + if (haystack == (const char *)0 || needle == (const char *)0) { + return (char *)0; + } + + nlen = strlen(needle); + if (nlen == 0U) { + return (char *)haystack; + } + + for (i = 0U; haystack[i] != '\0'; i++) { + if (haystack[i] != needle[0]) { + continue; + } + + for (j = 1U; j < nlen; j++) { + if (haystack[i + j] == '\0' || haystack[i + j] != needle[j]) { + break; + } + } + + if (j == nlen) { + return (char *)(haystack + i); + } + } + + return (char *)0; +} + +static int clib_delim_contains(const char *delim, char ch) { + size_t i = 0U; + + if (delim == (const char *)0) { + return 0; + } + + while (delim[i] != '\0') { + if (delim[i] == ch) { + return 1; + } + i++; + } + + return 0; +} + +size_t strspn(const char *text, const char *accept) { + size_t n = 0U; + + if (text == (const char *)0 || accept == (const char *)0) { + return 0U; + } + + while (text[n] != '\0' && clib_delim_contains(accept, text[n]) != 0) { + n++; + } + + return n; +} + +size_t strcspn(const char *text, const char *reject) { + size_t n = 0U; + + if (text == (const char *)0 || reject == (const char *)0) { + return 0U; + } + + while (text[n] != '\0' && clib_delim_contains(reject, text[n]) == 0) { + n++; + } + + return n; +} + +char *strpbrk(const char *text, const char *accept) { + size_t i = 0U; + + if (text == (const char *)0 || accept == (const char *)0) { + return (char *)0; + } + + while (text[i] != '\0') { + if (clib_delim_contains(accept, text[i]) != 0) { + return (char *)(text + i); + } + i++; + } + + return (char *)0; +} + +char *strtok_r(char *text, const char *delim, char **saveptr) { + char *start; + char *cursor; + + if (delim == (const char *)0 || saveptr == (char **)0) { + return (char *)0; + } + + if (text != (char *)0) { + cursor = text; + } else { + cursor = *saveptr; + } + + if (cursor == (char *)0) { + return (char *)0; + } + + while (*cursor != '\0' && clib_delim_contains(delim, *cursor) != 0) { + cursor++; + } + + if (*cursor == '\0') { + *saveptr = cursor; + return (char *)0; + } + + start = cursor; + while (*cursor != '\0' && clib_delim_contains(delim, *cursor) == 0) { + cursor++; + } + + if (*cursor == '\0') { + *saveptr = cursor; + } else { + *cursor = '\0'; + *saveptr = cursor + 1; + } + + return start; +} + +char *strtok(char *text, const char *delim) { + static char *state = (char *)0; + return strtok_r(text, delim, &state); +} + +char *strcat(char *dst, const char *src) { + size_t dlen = strlen(dst); + size_t i = 0U; + + if (dst == (char *)0 || src == (const char *)0) { + return dst; + } + + while (src[i] != '\0') { + dst[dlen + i] = src[i]; + i++; + } + + dst[dlen + i] = '\0'; + return dst; +} + +char *strncat(char *dst, const char *src, size_t size) { + size_t dlen = strlen(dst); + size_t i = 0U; + + if (dst == (char *)0 || src == (const char *)0) { + return dst; + } + + while (i < size && src[i] != '\0') { + dst[dlen + i] = src[i]; + i++; + } + + dst[dlen + i] = '\0'; + return dst; +} diff --git a/kit/runtime/main_adapter.c b/kit/runtime/main_adapter.c new file mode 100644 index 0000000..2e1a9d1 --- /dev/null +++ b/kit/runtime/main_adapter.c @@ -0,0 +1,8 @@ +#include + +extern int main(int argc, char **argv); + +int cleonos_app_main(int argc, char **argv, char **envp) { + (void)envp; + return main(argc, argv); +} diff --git a/kit/runtime/runtime.c b/kit/runtime/runtime.c new file mode 100644 index 0000000..a6f9e2c --- /dev/null +++ b/kit/runtime/runtime.c @@ -0,0 +1,53 @@ +#include + +#define CLEONOS_RUNTIME_ARGV_MAX 24ULL +#define CLEONOS_RUNTIME_ENVP_MAX 24ULL +#define CLEONOS_RUNTIME_ITEM_MAX 128ULL + +extern int cleonos_app_main(int argc, char **argv, char **envp); +extern void cleonos_cmd_runtime_pre_main(char **envp) __attribute__((weak)); + +u64 _start(void) { + static char argv_items[CLEONOS_RUNTIME_ARGV_MAX][CLEONOS_RUNTIME_ITEM_MAX]; + static char env_items[CLEONOS_RUNTIME_ENVP_MAX][CLEONOS_RUNTIME_ITEM_MAX]; + static char *argv_ptrs[CLEONOS_RUNTIME_ARGV_MAX + 1ULL]; + static char *env_ptrs[CLEONOS_RUNTIME_ENVP_MAX + 1ULL]; + u64 argc = 0ULL; + u64 envc = 0ULL; + u64 i; + int code; + + argc = cleonos_sys_proc_argc(); + envc = cleonos_sys_proc_envc(); + + if (argc > CLEONOS_RUNTIME_ARGV_MAX) { + argc = CLEONOS_RUNTIME_ARGV_MAX; + } + + if (envc > CLEONOS_RUNTIME_ENVP_MAX) { + envc = CLEONOS_RUNTIME_ENVP_MAX; + } + + for (i = 0ULL; i < argc; i++) { + argv_items[i][0] = '\0'; + (void)cleonos_sys_proc_argv(i, argv_items[i], CLEONOS_RUNTIME_ITEM_MAX); + argv_ptrs[i] = argv_items[i]; + } + + argv_ptrs[argc] = (char *)0; + + for (i = 0ULL; i < envc; i++) { + env_items[i][0] = '\0'; + (void)cleonos_sys_proc_env(i, env_items[i], CLEONOS_RUNTIME_ITEM_MAX); + env_ptrs[i] = env_items[i]; + } + + env_ptrs[envc] = (char *)0; + + if (cleonos_cmd_runtime_pre_main != (void (*)(char **))0) { + cleonos_cmd_runtime_pre_main(env_ptrs); + } + + code = cleonos_app_main((int)argc, argv_ptrs, env_ptrs); + return (u64)code; +} diff --git a/kit/runtime/stdio.c b/kit/runtime/stdio.c new file mode 100644 index 0000000..367b810 --- /dev/null +++ b/kit/runtime/stdio.c @@ -0,0 +1,712 @@ +#include + +#include + +typedef unsigned long clio_size_t; + +#define CLIO_SINK_FD 1 +#define CLIO_SINK_BUF 2 + +struct clio_sink { + int mode; + int fd; + char *buffer; + clio_size_t capacity; + clio_size_t count; + int failed; +}; + +static clio_size_t clio_strlen(const char *text) { + clio_size_t len = 0UL; + + if (text == (const char *)0) { + return 0UL; + } + + while (text[len] != '\0') { + len++; + } + + return len; +} + +static int clio_write_all_fd(int fd, const char *text, clio_size_t len) { + const char *cursor = text; + clio_size_t left = len; + + if (fd < 0 || (text == (const char *)0 && len != 0UL)) { + return EOF; + } + + while (left > 0UL) { + u64 wrote = cleonos_sys_fd_write((u64)fd, cursor, (u64)left); + clio_size_t progressed; + + if (wrote == 0ULL || wrote == (u64)-1) { + return EOF; + } + + progressed = (wrote > (u64)left) ? left : (clio_size_t)wrote; + cursor += progressed; + left -= progressed; + } + + if (len > 0x7FFFFFFFUL) { + return 0x7FFFFFFF; + } + + return (int)len; +} + +static void clio_sink_init_fd(struct clio_sink *sink, int fd) { + sink->mode = CLIO_SINK_FD; + sink->fd = fd; + sink->buffer = (char *)0; + sink->capacity = 0UL; + sink->count = 0UL; + sink->failed = 0; +} + +static void clio_sink_init_buffer(struct clio_sink *sink, char *out, clio_size_t out_size) { + sink->mode = CLIO_SINK_BUF; + sink->fd = -1; + sink->buffer = out; + sink->capacity = out_size; + sink->count = 0UL; + sink->failed = 0; + + if (out != (char *)0 && out_size > 0UL) { + out[0] = '\0'; + } +} + +static void clio_sink_finalize_buffer(struct clio_sink *sink) { + if (sink->mode != CLIO_SINK_BUF || sink->buffer == (char *)0 || sink->capacity == 0UL) { + return; + } + + if (sink->count < sink->capacity) { + sink->buffer[sink->count] = '\0'; + } else { + sink->buffer[sink->capacity - 1UL] = '\0'; + } +} + +static int clio_sink_emit(struct clio_sink *sink, const char *text, clio_size_t len) { + if (sink == (struct clio_sink *)0 || text == (const char *)0 || len == 0UL) { + return 1; + } + + if (sink->mode == CLIO_SINK_FD) { + if (clio_write_all_fd(sink->fd, text, len) == EOF) { + sink->failed = 1; + return 0; + } + } else { + if (sink->buffer != (char *)0 && sink->capacity > 0UL) { + clio_size_t i; + clio_size_t start = sink->count; + clio_size_t writable = 0UL; + + if (start + 1UL < sink->capacity) { + writable = (sink->capacity - 1UL) - start; + } + + if (len < writable) { + writable = len; + } + + for (i = 0UL; i < writable; i++) { + sink->buffer[start + i] = text[i]; + } + } + } + + sink->count += len; + return 1; +} + +static clio_size_t clio_u64_to_base(unsigned long long value, unsigned int base, int uppercase, char *out, + clio_size_t out_size) { + char tmp[64]; + clio_size_t pos = 0UL; + clio_size_t i = 0UL; + + if (out == (char *)0 || out_size < 2UL || base < 2U || base > 16U) { + return 0UL; + } + + if (value == 0ULL) { + out[0] = '0'; + out[1] = '\0'; + return 1UL; + } + + while (value != 0ULL && pos < (clio_size_t)sizeof(tmp)) { + unsigned long long digit = value % (unsigned long long)base; + + if (digit < 10ULL) { + tmp[pos++] = (char)('0' + digit); + } else { + char alpha = (uppercase != 0) ? 'A' : 'a'; + tmp[pos++] = (char)(alpha + (char)(digit - 10ULL)); + } + + value /= (unsigned long long)base; + } + + if (pos + 1UL > out_size) { + return 0UL; + } + + while (pos > 0UL) { + pos--; + out[i++] = tmp[pos]; + } + + out[i] = '\0'; + return i; +} + +static clio_size_t clio_i64_to_dec(long long value, char *out, clio_size_t out_size) { + unsigned long long magnitude; + clio_size_t offset = 0UL; + clio_size_t len; + + if (out == (char *)0 || out_size < 2UL) { + return 0UL; + } + + if (value < 0LL) { + out[offset++] = '-'; + if (offset + 2UL > out_size) { + return 0UL; + } + magnitude = (unsigned long long)(-(value + 1LL)) + 1ULL; + } else { + magnitude = (unsigned long long)value; + } + + len = clio_u64_to_base(magnitude, 10U, 0, out + offset, out_size - offset); + + if (len == 0UL) { + return 0UL; + } + + return offset + len; +} + +static int clio_is_digit(char ch) { + return (ch >= '0' && ch <= '9') ? 1 : 0; +} + +static int clio_emit_repeat(struct clio_sink *sink, char ch, clio_size_t count) { + while (count > 0UL) { + if (clio_sink_emit(sink, &ch, 1UL) == 0) { + return 0; + } + count--; + } + + return 1; +} + +static int clio_emit_with_width(struct clio_sink *sink, const char *text, clio_size_t text_len, int left_align, + char pad_char, clio_size_t width) { + if (left_align == 0 && width > text_len) { + if (clio_emit_repeat(sink, pad_char, width - text_len) == 0) { + return 0; + } + } + + if (text_len > 0UL && clio_sink_emit(sink, text, text_len) == 0) { + return 0; + } + + if (left_align != 0 && width > text_len) { + if (clio_emit_repeat(sink, ' ', width - text_len) == 0) { + return 0; + } + } + + return 1; +} + +static int clio_vformat(struct clio_sink *sink, const char *fmt, va_list args) { + const char *cursor = fmt; + + if (sink == (struct clio_sink *)0 || fmt == (const char *)0) { + return EOF; + } + + while (*cursor != '\0') { + if (*cursor != '%') { + if (clio_sink_emit(sink, cursor, 1UL) == 0) { + return EOF; + } + cursor++; + continue; + } + + cursor++; + + if (*cursor == '%') { + if (clio_sink_emit(sink, "%", 1UL) == 0) { + return EOF; + } + cursor++; + continue; + } + + { + int left_align = 0; + int zero_pad = 0; + clio_size_t width = 0UL; + int has_precision = 0; + clio_size_t precision = 0UL; + int length_mode = 0; /* 0: default, 1: l, 2: ll, 3: z */ + char spec = *cursor; + char number_buf[96]; + + while (spec == '-' || spec == '0') { + if (spec == '-') { + left_align = 1; + } else if (spec == '0') { + zero_pad = 1; + } + cursor++; + spec = *cursor; + } + + while (clio_is_digit(spec) != 0) { + width = (width * 10UL) + (clio_size_t)(unsigned long)(spec - '0'); + cursor++; + spec = *cursor; + } + + if (spec == '.') { + has_precision = 1; + precision = 0UL; + cursor++; + spec = *cursor; + + while (clio_is_digit(spec) != 0) { + precision = (precision * 10UL) + (clio_size_t)(unsigned long)(spec - '0'); + cursor++; + spec = *cursor; + } + } + + if (spec == 'l') { + cursor++; + spec = *cursor; + length_mode = 1; + + if (spec == 'l') { + cursor++; + spec = *cursor; + length_mode = 2; + } + } else if (spec == 'z') { + cursor++; + spec = *cursor; + length_mode = 3; + } + + if (spec == '\0') { + break; + } + + if (spec == 's') { + const char *text = va_arg(args, const char *); + clio_size_t text_len; + + if (text == (const char *)0) { + text = "(null)"; + } + + text_len = clio_strlen(text); + if (has_precision != 0 && precision < text_len) { + text_len = precision; + } + + if (clio_emit_with_width(sink, text, text_len, left_align, ' ', width) == 0) { + return EOF; + } + } else if (spec == 'c') { + char out = (char)va_arg(args, int); + char out_buf[1]; + + out_buf[0] = out; + if (clio_emit_with_width(sink, out_buf, 1UL, left_align, ' ', width) == 0) { + return EOF; + } + } else if (spec == 'd' || spec == 'i') { + long long value; + char sign_char = '\0'; + const char *digits = number_buf; + clio_size_t digits_len; + clio_size_t leading_zeros = 0UL; + clio_size_t core_len; + int sign_emitted = 0; + + if (length_mode == 2) { + value = va_arg(args, long long); + } else if (length_mode == 1) { + value = (long long)va_arg(args, long); + } else if (length_mode == 3) { + value = (long long)va_arg(args, long long); + } else { + value = (long long)va_arg(args, int); + } + + digits_len = clio_i64_to_dec(value, number_buf, (clio_size_t)sizeof(number_buf)); + if (digits_len == 0UL) { + return EOF; + } + + if (number_buf[0] == '-') { + sign_char = '-'; + digits = number_buf + 1; + digits_len--; + } + + if (has_precision != 0 && precision == 0UL && value == 0LL) { + digits_len = 0UL; + } + + if (has_precision != 0 && precision > digits_len) { + leading_zeros = precision - digits_len; + } + + core_len = digits_len + leading_zeros + ((sign_char != '\0') ? 1UL : 0UL); + + if (left_align == 0 && width > core_len) { + if (zero_pad != 0 && has_precision == 0) { + if (sign_char != '\0') { + if (clio_sink_emit(sink, &sign_char, 1UL) == 0) { + return EOF; + } + sign_emitted = 1; + } + if (clio_emit_repeat(sink, '0', width - core_len) == 0) { + return EOF; + } + } else { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + } + + if (sign_char != '\0' && sign_emitted == 0) { + if (clio_sink_emit(sink, &sign_char, 1UL) == 0) { + return EOF; + } + } + + if (clio_emit_repeat(sink, '0', leading_zeros) == 0) { + return EOF; + } + + if (digits_len > 0UL && clio_sink_emit(sink, digits, digits_len) == 0) { + return EOF; + } + + if (left_align != 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + } else if (spec == 'u' || spec == 'x' || spec == 'X') { + unsigned long long value; + unsigned int base = (spec == 'u') ? 10U : 16U; + int upper = (spec == 'X') ? 1 : 0; + clio_size_t digits_len; + clio_size_t leading_zeros = 0UL; + clio_size_t core_len; + char pad_char = ' '; + + if (length_mode == 2) { + value = va_arg(args, unsigned long long); + } else if (length_mode == 1) { + value = (unsigned long long)va_arg(args, unsigned long); + } else if (length_mode == 3) { + value = (unsigned long long)va_arg(args, unsigned long long); + } else { + value = (unsigned long long)va_arg(args, unsigned int); + } + + digits_len = clio_u64_to_base(value, base, upper, number_buf, (clio_size_t)sizeof(number_buf)); + if (digits_len == 0UL) { + return EOF; + } + + if (has_precision != 0 && precision == 0UL && value == 0ULL) { + digits_len = 0UL; + } + + if (has_precision != 0 && precision > digits_len) { + leading_zeros = precision - digits_len; + } + + core_len = digits_len + leading_zeros; + + if (zero_pad != 0 && has_precision == 0 && left_align == 0) { + pad_char = '0'; + } + + if (left_align == 0 && width > core_len) { + if (clio_emit_repeat(sink, pad_char, width - core_len) == 0) { + return EOF; + } + } + + if (clio_emit_repeat(sink, '0', leading_zeros) == 0) { + return EOF; + } + + if (digits_len > 0UL && clio_sink_emit(sink, number_buf, digits_len) == 0) { + return EOF; + } + + if (left_align != 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + } else if (spec == 'p') { + const void *ptr = va_arg(args, const void *); + unsigned long long value = (unsigned long long)(usize)ptr; + clio_size_t digits_len; + clio_size_t leading_zeros = 0UL; + clio_size_t core_len; + + digits_len = clio_u64_to_base(value, 16U, 0, number_buf, (clio_size_t)sizeof(number_buf)); + if (digits_len == 0UL) { + return EOF; + } + + if (has_precision != 0 && precision == 0UL && value == 0ULL) { + digits_len = 0UL; + } + + if (has_precision != 0 && precision > digits_len) { + leading_zeros = precision - digits_len; + } + + core_len = 2UL + leading_zeros + digits_len; + + if (left_align == 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + + if (clio_sink_emit(sink, "0x", 2UL) == 0) { + return EOF; + } + + if (clio_emit_repeat(sink, '0', leading_zeros) == 0) { + return EOF; + } + + if (digits_len > 0UL && clio_sink_emit(sink, number_buf, digits_len) == 0) { + return EOF; + } + + if (left_align != 0 && width > core_len) { + if (clio_emit_repeat(sink, ' ', width - core_len) == 0) { + return EOF; + } + } + } else if (spec == 'n') { + int *out_count = va_arg(args, int *); + if (out_count != (int *)0) { + if (sink->count > 0x7FFFFFFFUL) { + *out_count = 0x7FFFFFFF; + } else { + *out_count = (int)sink->count; + } + } + } else { + char fallback[2]; + fallback[0] = spec; + fallback[1] = '\0'; + + if (clio_sink_emit(sink, "%", 1UL) == 0 || clio_sink_emit(sink, fallback, 1UL) == 0) { + return EOF; + } + } + + cursor++; + } + } + + if (sink->mode == CLIO_SINK_BUF) { + clio_sink_finalize_buffer(sink); + } + + if (sink->failed != 0) { + return EOF; + } + + if (sink->count > 0x7FFFFFFFUL) { + return 0x7FFFFFFF; + } + + return (int)sink->count; +} + +int putchar(int ch) { + char out = (char)(ch & 0xFF); + return (clio_write_all_fd(1, &out, 1UL) == EOF) ? EOF : (int)(unsigned char)out; +} + +int getchar(void) { + char ch = '\0'; + + for (;;) { + u64 got = cleonos_sys_fd_read(0ULL, &ch, 1ULL); + + if (got == 1ULL) { + return (int)(unsigned char)ch; + } + + if (got == (u64)-1) { + return EOF; + } + + (void)cleonos_sys_yield(); + } +} + +int fputc(int ch, int fd) { + char out = (char)(ch & 0xFF); + return (clio_write_all_fd(fd, &out, 1UL) == EOF) ? EOF : (int)(unsigned char)out; +} + +int fgetc(int fd) { + char ch = '\0'; + + if (fd < 0) { + return EOF; + } + + for (;;) { + u64 got = cleonos_sys_fd_read((u64)fd, &ch, 1ULL); + + if (got == 1ULL) { + return (int)(unsigned char)ch; + } + + if (got == (u64)-1) { + return EOF; + } + + (void)cleonos_sys_yield(); + } +} + +int fputs(const char *text, int fd) { + clio_size_t len; + + if (text == (const char *)0) { + return EOF; + } + + len = clio_strlen(text); + return clio_write_all_fd(fd, text, len); +} + +int puts(const char *text) { + int wrote = fputs(text, 1); + + if (wrote == EOF) { + return EOF; + } + + if (putchar('\n') == EOF) { + return EOF; + } + + return wrote + 1; +} + +int vsnprintf(char *out, unsigned long out_size, const char *fmt, va_list args) { + struct clio_sink sink; + va_list args_copy; + int rc; + + clio_sink_init_buffer(&sink, out, out_size); + va_copy(args_copy, args); + rc = clio_vformat(&sink, fmt, args_copy); + va_end(args_copy); + + return rc; +} + +int snprintf(char *out, unsigned long out_size, const char *fmt, ...) { + va_list args; + int rc; + + va_start(args, fmt); + rc = vsnprintf(out, out_size, fmt, args); + va_end(args); + + return rc; +} + +int vdprintf(int fd, const char *fmt, va_list args) { + struct clio_sink sink; + va_list args_copy; + int rc; + + clio_sink_init_fd(&sink, fd); + va_copy(args_copy, args); + rc = clio_vformat(&sink, fmt, args_copy); + va_end(args_copy); + + return rc; +} + +int dprintf(int fd, const char *fmt, ...) { + va_list args; + int rc; + + va_start(args, fmt); + rc = vdprintf(fd, fmt, args); + va_end(args); + + return rc; +} + +int vfprintf(int fd, const char *fmt, va_list args) { + return vdprintf(fd, fmt, args); +} + +int fprintf(int fd, const char *fmt, ...) { + va_list args; + int rc; + + va_start(args, fmt); + rc = vdprintf(fd, fmt, args); + va_end(args); + + return rc; +} + +int vprintf(const char *fmt, va_list args) { + return vdprintf(1, fmt, args); +} + +int printf(const char *fmt, ...) { + va_list args; + int rc; + + va_start(args, fmt); + rc = vdprintf(1, fmt, args); + va_end(args); + + return rc; +} diff --git a/kit/runtime/syscall.c b/kit/runtime/syscall.c new file mode 100644 index 0000000..d4ddcec --- /dev/null +++ b/kit/runtime/syscall.c @@ -0,0 +1,413 @@ +#include + +u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2) { + u64 ret; + + __asm__ volatile("int $0x80" : "=a"(ret) : "a"(id), "b"(arg0), "c"(arg1), "d"(arg2) : "memory"); + + return ret; +} + +u64 cleonos_sys_log_write(const char *message, u64 length) { + return cleonos_syscall(CLEONOS_SYSCALL_LOG_WRITE, (u64)message, length, 0ULL); +} + +u64 cleonos_sys_timer_ticks(void) { + return cleonos_syscall(CLEONOS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_task_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_TASK_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_service_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_SERVICE_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_service_ready_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_SERVICE_READY_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_context_switches(void) { + return cleonos_syscall(CLEONOS_SYSCALL_CONTEXT_SWITCHES, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_kelf_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KELF_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_kelf_runs(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KELF_RUNS, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_node_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_NODE_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_child_count(const char *dir_path) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_CHILD_COUNT, (u64)dir_path, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_get_child_name(const char *dir_path, u64 index, char *out_name) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_GET_CHILD_NAME, (u64)dir_path, index, (u64)out_name); +} + +u64 cleonos_sys_fs_read(const char *path, char *out_buffer, u64 buffer_size) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_READ, (u64)path, (u64)out_buffer, buffer_size); +} + +u64 cleonos_sys_exec_path(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_EXEC_PATH, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_exec_pathv(const char *path, const char *argv_line, const char *env_line) { + return cleonos_syscall(CLEONOS_SYSCALL_EXEC_PATHV, (u64)path, (u64)argv_line, (u64)env_line); +} + +struct cleonos_exec_pathv_io_req { + u64 env_line_ptr; + u64 stdin_fd; + u64 stdout_fd; + u64 stderr_fd; +}; + +u64 cleonos_sys_exec_pathv_io(const char *path, const char *argv_line, const char *env_line, u64 stdin_fd, + u64 stdout_fd, u64 stderr_fd) { + struct cleonos_exec_pathv_io_req req; + + req.env_line_ptr = (u64)env_line; + req.stdin_fd = stdin_fd; + req.stdout_fd = stdout_fd; + req.stderr_fd = stderr_fd; + + return cleonos_syscall(CLEONOS_SYSCALL_EXEC_PATHV_IO, (u64)path, (u64)argv_line, (u64)&req); +} + +u64 cleonos_sys_exec_request_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_EXEC_REQUESTS, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_exec_success_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_EXEC_SUCCESS, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_user_shell_ready(void) { + return cleonos_syscall(CLEONOS_SYSCALL_USER_SHELL_READY, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_user_exec_requested(void) { + return cleonos_syscall(CLEONOS_SYSCALL_USER_EXEC_REQUESTED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_user_launch_tries(void) { + return cleonos_syscall(CLEONOS_SYSCALL_USER_LAUNCH_TRIES, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_user_launch_ok(void) { + return cleonos_syscall(CLEONOS_SYSCALL_USER_LAUNCH_OK, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_user_launch_fail(void) { + return cleonos_syscall(CLEONOS_SYSCALL_USER_LAUNCH_FAIL, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_tty_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_TTY_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_tty_active(void) { + return cleonos_syscall(CLEONOS_SYSCALL_TTY_ACTIVE, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_tty_switch(u64 tty_index) { + return cleonos_syscall(CLEONOS_SYSCALL_TTY_SWITCH, tty_index, 0ULL, 0ULL); +} + +u64 cleonos_sys_tty_write(const char *text, u64 length) { + return cleonos_syscall(CLEONOS_SYSCALL_TTY_WRITE, (u64)text, length, 0ULL); +} + +u64 cleonos_sys_tty_write_char(char ch) { + return cleonos_syscall(CLEONOS_SYSCALL_TTY_WRITE_CHAR, (u64)(unsigned char)ch, 0ULL, 0ULL); +} + +u64 cleonos_sys_kbd_get_char(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KBD_GET_CHAR, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_stat_type(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_STAT_TYPE, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_stat_size(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_STAT_SIZE, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_mkdir(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_MKDIR, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_fs_write(const char *path, const char *data, u64 size) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_WRITE, (u64)path, (u64)data, size); +} + +u64 cleonos_sys_fs_append(const char *path, const char *data, u64 size) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_APPEND, (u64)path, (u64)data, size); +} + +u64 cleonos_sys_fs_remove(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_FS_REMOVE, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_log_journal_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_LOG_JOURNAL_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_log_journal_read(u64 index_from_oldest, char *out_line, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_LOG_JOURNAL_READ, index_from_oldest, (u64)out_line, out_size); +} + +u64 cleonos_sys_kbd_buffered(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KBD_BUFFERED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_kbd_pushed(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KBD_PUSHED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_kbd_popped(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KBD_POPPED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_kbd_dropped(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KBD_DROPPED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_kbd_hotkey_switches(void) { + return cleonos_syscall(CLEONOS_SYSCALL_KBD_HOTKEY_SWITCHES, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_getpid(void) { + return cleonos_syscall(CLEONOS_SYSCALL_GETPID, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_spawn_path(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_SPAWN_PATH, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_spawn_pathv(const char *path, const char *argv_line, const char *env_line) { + return cleonos_syscall(CLEONOS_SYSCALL_SPAWN_PATHV, (u64)path, (u64)argv_line, (u64)env_line); +} + +u64 cleonos_sys_wait_pid(u64 pid, u64 *out_status) { + return cleonos_syscall(CLEONOS_SYSCALL_WAITPID, pid, (u64)out_status, 0ULL); +} + +u64 cleonos_sys_exit(u64 status) { + return cleonos_syscall(CLEONOS_SYSCALL_EXIT, status, 0ULL, 0ULL); +} + +u64 cleonos_sys_sleep_ticks(u64 ticks) { + return cleonos_syscall(CLEONOS_SYSCALL_SLEEP_TICKS, ticks, 0ULL, 0ULL); +} + +u64 cleonos_sys_yield(void) { + return cleonos_syscall(CLEONOS_SYSCALL_YIELD, 0ULL, 0ULL, 0ULL); +} +u64 cleonos_sys_shutdown(void) { + return cleonos_syscall(CLEONOS_SYSCALL_SHUTDOWN, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_restart(void) { + return cleonos_syscall(CLEONOS_SYSCALL_RESTART, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_audio_available(void) { + return cleonos_syscall(CLEONOS_SYSCALL_AUDIO_AVAILABLE, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_audio_play_tone(u64 hz, u64 ticks) { + return cleonos_syscall(CLEONOS_SYSCALL_AUDIO_PLAY_TONE, hz, ticks, 0ULL); +} + +u64 cleonos_sys_audio_stop(void) { + return cleonos_syscall(CLEONOS_SYSCALL_AUDIO_STOP, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_argc(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_ARGC, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_argv(u64 index, char *out_value, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_ARGV, index, (u64)out_value, out_size); +} + +u64 cleonos_sys_proc_envc(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_ENVC, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_env(u64 index, char *out_value, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_ENV, index, (u64)out_value, out_size); +} + +u64 cleonos_sys_proc_last_signal(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_LAST_SIGNAL, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_fault_vector(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_FAULT_VECTOR, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_fault_error(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_FAULT_ERROR, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_fault_rip(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_FAULT_RIP, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_proc_pid_at(u64 index, u64 *out_pid) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_PID_AT, index, (u64)out_pid, 0ULL); +} + +u64 cleonos_sys_proc_snapshot(u64 pid, cleonos_proc_snapshot *out_snapshot, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_SNAPSHOT, pid, (u64)out_snapshot, out_size); +} + +u64 cleonos_sys_proc_kill(u64 pid, u64 signal) { + return cleonos_syscall(CLEONOS_SYSCALL_PROC_KILL, pid, signal, 0ULL); +} + +struct cleonos_kdbg_bt_req { + u64 rbp; + u64 rip; + u64 out_ptr; + u64 out_size; +}; + +u64 cleonos_sys_kdbg_sym(u64 addr, char *out_line, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_KDBG_SYM, addr, (u64)out_line, out_size); +} + +u64 cleonos_sys_kdbg_bt(u64 rbp, u64 rip, char *out_text, u64 out_size) { + struct cleonos_kdbg_bt_req req; + + req.rbp = rbp; + req.rip = rip; + req.out_ptr = (u64)out_text; + req.out_size = out_size; + + return cleonos_syscall(CLEONOS_SYSCALL_KDBG_BT, (u64)&req, 0ULL, 0ULL); +} + +u64 cleonos_sys_kdbg_regs(char *out_text, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_KDBG_REGS, (u64)out_text, out_size, 0ULL); +} + +u64 cleonos_sys_stats_total(void) { + return cleonos_syscall(CLEONOS_SYSCALL_STATS_TOTAL, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_stats_id_count(u64 id) { + return cleonos_syscall(CLEONOS_SYSCALL_STATS_ID_COUNT, id, 0ULL, 0ULL); +} + +u64 cleonos_sys_stats_recent_window(void) { + return cleonos_syscall(CLEONOS_SYSCALL_STATS_RECENT_WINDOW, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_stats_recent_id(u64 id) { + return cleonos_syscall(CLEONOS_SYSCALL_STATS_RECENT_ID, id, 0ULL, 0ULL); +} + +u64 cleonos_sys_fd_open(const char *path, u64 flags, u64 mode) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_OPEN, (u64)path, flags, mode); +} + +u64 cleonos_sys_fd_read(u64 fd, void *out_buffer, u64 size) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_READ, fd, (u64)out_buffer, size); +} + +u64 cleonos_sys_fd_write(u64 fd, const void *buffer, u64 size) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_WRITE, fd, (u64)buffer, size); +} + +u64 cleonos_sys_fd_close(u64 fd) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_CLOSE, fd, 0ULL, 0ULL); +} + +u64 cleonos_sys_fd_dup(u64 fd) { + return cleonos_syscall(CLEONOS_SYSCALL_FD_DUP, fd, 0ULL, 0ULL); +} + +u64 cleonos_sys_dl_open(const char *path) { + return cleonos_syscall(CLEONOS_SYSCALL_DL_OPEN, (u64)path, 0ULL, 0ULL); +} + +u64 cleonos_sys_dl_close(u64 handle) { + return cleonos_syscall(CLEONOS_SYSCALL_DL_CLOSE, handle, 0ULL, 0ULL); +} + +u64 cleonos_sys_dl_sym(u64 handle, const char *symbol) { + return cleonos_syscall(CLEONOS_SYSCALL_DL_SYM, handle, (u64)symbol, 0ULL); +} + +u64 cleonos_sys_fb_info(cleonos_fb_info *out_info) { + return cleonos_syscall(CLEONOS_SYSCALL_FB_INFO, (u64)out_info, 0ULL, 0ULL); +} + +u64 cleonos_sys_fb_blit(const cleonos_fb_blit_req *req) { + return cleonos_syscall(CLEONOS_SYSCALL_FB_BLIT, (u64)req, 0ULL, 0ULL); +} + +u64 cleonos_sys_fb_clear(u64 rgb) { + return cleonos_syscall(CLEONOS_SYSCALL_FB_CLEAR, rgb, 0ULL, 0ULL); +} + +u64 cleonos_sys_kernel_version(char *out_version, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_KERNEL_VERSION, (u64)out_version, out_size, 0ULL); +} + +u64 cleonos_sys_disk_present(void) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_PRESENT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_size_bytes(void) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_SIZE_BYTES, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_sector_count(void) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_SECTOR_COUNT, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_formatted(void) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_FORMATTED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_format_fat32(const char *label) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_FORMAT_FAT32, (u64)label, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_mount(const char *mount_path) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_MOUNT, (u64)mount_path, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_mounted(void) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_MOUNTED, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_disk_mount_path(char *out_path, u64 out_size) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_MOUNT_PATH, (u64)out_path, out_size, 0ULL); +} + +u64 cleonos_sys_disk_read_sector(u64 lba, void *out_sector) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_READ_SECTOR, lba, (u64)out_sector, 0ULL); +} + +u64 cleonos_sys_disk_write_sector(u64 lba, const void *sector_data) { + return cleonos_syscall(CLEONOS_SYSCALL_DISK_WRITE_SECTOR, lba, (u64)sector_data, 0ULL); +} diff --git a/wine/License b/wine/License new file mode 100644 index 0000000..59711bc --- /dev/null +++ b/wine/License @@ -0,0 +1,51 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and +You must cause any modified files to carry prominent notices stating that You changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file