diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-07 13:22:53 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-11 00:08:15 +0100 |
| commit | 7861a52adf92a083bb2aed4c35f98d8035dce032 (patch) | |
| tree | 28cd3c40e4c878f730f5df3c1d93bdf91af490c3 | |
| parent | 7fc48e9216ff809da5f8055a50b0be17628ef1df (diff) | |
Setup project skeleton
589 files changed, 28919 insertions, 362 deletions
@@ -1 +1,2 @@ /build*/ +/src/ps1/*.dat diff --git a/CMakeLists.txt b/CMakeLists.txt index 9820c84..bb3c826 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# wanix, a Unix-like operating system for WebAssembly +# wnix, a Unix-like operating system for WebAssembly applications. # Copyright (C) 2025 Xavier Del Campo Romero # # This program is free software: you can redistribute it and/or modify @@ -21,16 +21,20 @@ set(TOOLS_PREFIX ${CMAKE_BINARY_DIR}/tools) include(ExternalProject) ExternalProject_Add(tools SOURCE_DIR ${CMAKE_SOURCE_DIR}/tools + BUILD_ALWAYS ON CMAKE_ARGS + -D CMAKE_EXPORT_COMPILE_COMMANDS=ON -D CMAKE_INSTALL_PREFIX=${TOOLS_PREFIX}) -project(wanix C) +project(wnix C ASM) +option(WNIX_BUILD_PROGRAMS "Build userspace programs" ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) -add_compile_options(-mno-gpopt) +add_compile_options(-mno-gpopt -ffunction-sections -fdata-sections) if(CMAKE_TOOLCHAIN_FILE MATCHES "ps1") set(PS1_BUILD 1) + option(WNIX_VIRT_CD "Virtualise CD driver through SIO") elseif(CMAKE_TOOLCHAIN_FILE MATCHES "win9x") set(WIN9X_BUILD 1) set(SDL1_2_BUILD 1) @@ -40,7 +44,7 @@ else() set(SDL1_2_BUILD 1) endif() -add_executable(${PROJECT_NAME} ${exec_flags} "src/main.c") +add_executable(${PROJECT_NAME} ${exec_flags} src/main.c) if(SDL1_2_BUILD) find_package(SDL 1.2 REQUIRED) @@ -58,16 +62,19 @@ if(NOT PS1_BUILD) find_package(ENET 1.3 REQUIRED) endif() -set(cdroot ${CMAKE_BINARY_DIR}/cdimg) -file(MAKE_DIRECTORY ${cdroot}) +set(cdroot ${CMAKE_BINARY_DIR}) if(PS1_BUILD) - include("cmake/ps1.cmake") + include(cmake/ps1.cmake) elseif(WIN9X_BUILD) - include("cmake/win9x.cmake") + include(cmake/win9x.cmake) elseif(HOST_BUILD) - include("cmake/host.cmake") + include(cmake/host.cmake) endif() -add_subdirectory("res") -add_subdirectory("src") +add_subdirectory(res) +add_subdirectory(src) + +if(WNIX_BUILD_PROGRAMS) + add_subdirectory(programs) +endif() diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe66a7a --- /dev/null +++ b/README.md @@ -0,0 +1,133 @@ +# Wnix + +**DISCLAIMER: this project is in early stage development, and therefore** +**not suitable for production environments.** + +Wnix (pronounced _woo-nix_ or _double u-nix_) is a small, Unix-like operating +system aimed towards resource-constrained devices without a [MMU]. +Virtual memory semantics are instead achieved by *exclusively* running +[WebAssembly] applications on its userspace, using the small and flexible +interpreter [NanoWasm] as its backend. + +For the sake of simplicity, and as opposed to most operating systems, +Wnix only requires one execution thread to perform all tasks. In other words, +Wnix is highly concurrent, but not parallel, and relies entirely on +co-operative execution of asynchronous (i.e., fast) tasks to achieve +[concurrency]. + +**Note:** while designed to remain portable, Wnix currently only targets the +original [PlayStation]. + +## Dependencies + +- A `mipsel-unknown-elf` cross-toolchain (i.e., GNU `binutils` and GCC). +Here are [some notes](https://www.psxdev.net/forum/viewtopic.php?t=40) +to build it from source. +- `clang-18` +- `libclang-18-dev` +- Copy `libclang_rt.builtins-wasm32.a` (get from WASI-SDK) to +`/usr/lib/llvm-18/lib/clang/18/lib`. +- C and C++ compilers for the host platform. + +## How to build + +Configure with: + +``` +cmake -B build -DCMAKE_TOOLCHAIN_FILE=cmake/ps1-toolchain.cmake -DVIDEO_MODE=VMODE_PAL +``` + +Build with: + +``` +cmake --build build/ # Optionally, add -j$(nproc) +``` + +## FAQ + +### Why not a fully-fledged operating system like GNU/Linux or BSDs? + +While all these projects truly deserve uttermost respect, these are very +complex projects that target a diverse range of highly sophisticated hardware. + +More specifically, regarding the original PlayStation there have been +[several unsuccessful attempts](https://www.psxdev.net/forum/viewtopic.php?t=152&start=40) +at running ancient versions of the Linux kernel (circa `2.4`), with +[concerns](https://www.psxdev.net/forum/viewtopic.php?p=19405#p19405) +about newer versions not being able to fit into the console's 2 MiB RAM. + +On the other hand, kernels like Linux are focused on running native +executables (i.e., ELF files), where the semantics provided by MMUs would not +be available on limited hardware like the original PlayStation. +While it might still be possible to configure Linux to exclusively +run WebAssembly applications somehow, Linux is still a very large and complex +project that would require a big effort to port to a PlayStation. + +Since binary compatibility with existing Linux software is not a requirement, +a simple operating system with Unix-like semantics is enough to allow +WebAssembly applications to interact with the system via [WASI]. + +Moreover, not having a MMU available would typically mean executables +would be dumped to RAM before execution, with a non-negligible footprint. +On the other hand, NanoWasm is designed to allow direct execution from any +source, including read-only media like CD-ROMs. + +Similarly, NanoWasm allows to allocate and manipulate WebAssembly memories +(linear memory, stack, etc.) from any source, including but not limited to +memory cards or any other external mass storage, therefore allowing the system +to outgrow its RAM size limitations, similarly to how fully-fledged operating +systems like GNU/Linux implement virtual memory. + +More importantly, running userspace applications without a MMU would allow a +malicious application to read/write memory from/to other processes, or even +the kernel itself. Confining userspace applications into a sandbox can be +achieved via WebAssembly, a bytecode representation that can be easily compiled +down to from popular programming languages, such as C or C++, via [`wasi-sdk`]. + +Of course, the design decisions above were made with memory efficiency and +security in mind, at the cost of execution speed. Wnix is meant to provide +similar tools compared to fully-fledged operating systems, at a fraction of +their size. + +And last, but not least, Wnix was written as an attempt to learn about +operating systems in general, and a way to have fun while implementing +interesting ways to achieve virtual memory semantics and concurrency by +software. + +## License + +``` +wnix, a Unix-like operating system for WebAssembly applications. +Copyright (C) 2025 Xavier Del Campo Romero + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +``` + +Wnix includes source code from other projects under various free software +licenses. Unless explicitly noted otherwise, Wnix is licensed according to +[`LICENSE`](LICENSE). + +## Disclaimer + +- Linux is a registered trademark of Linus Torvalds. +- PlayStation is a registered trademark of its respective owners. +- Unix is a registered trademark of its respective owners. + +[MMU]: https://en.wikipedia.org/wiki/Memory_management_unit +[WebAssembly]: https://en.wikipedia.org/wiki/Webassembly +[NanoWasm]: https://gitea.privatedns.org/xavi/nanowasm +[PlayStation]: https://en.wikipedia.org/wiki/PlayStation_(console) +[concurrency]: https://en.wikipedia.org/wiki/Concurrent_computing +[WASI]: https://wasi.dev/ +[`wasi-sdk`]: https://github.com/WebAssembly/wasi-sdk diff --git a/cmake/FindPSXSDK.cmake b/cmake/FindPSXSDK.cmake deleted file mode 100644 index 2d1982d..0000000 --- a/cmake/FindPSXSDK.cmake +++ /dev/null @@ -1,94 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindPSXSDK ------------ - -Find PSXSDK (an open source software development kit for the original -Sony PlayStation) libraries and header files. - -Imported targets -^^^^^^^^^^^^^^^^ - -This module defines the following :prop_tgt:`IMPORTED` targets: - - ``PSXSDK::PSXSDK``, - The PSXSDK `psx` library, if found. - -Result variables -^^^^^^^^^^^^^^^^ - -This module will set the following variables in your project: - -``PSXSDK_FOUND`` - true if PSXSDK libraries and header files were found. -``PSXSDK_VERSION`` - PSXSDK release version -``PSXSDK_INCLUDE_DIRS`` - the directory containing the PSXSDK headers; note - ``PSXSDK_INCLUDE_DIRS`` is also required -``PSXSDK_LIBRARIES`` - PSXSDK libraries to be linked; note ``PSXSDK_LIBRARIES`` is also - required - -#]=======================================================================] - -find_path(PSXSDK_INCLUDE_DIRS - NAMES - huff.h - meidogte.h - meidogte_inline.h - memcard.h - modplay.h - psxbios.h - psxcdrom.h - psxgpu.h - psxgte.h - psx.h - psxpad.h - psxsio.h - psxspu.h - psxutil.h - runexe.h - search.h - HINTS - ENV PSXSDK_PATH - PATH_SUFFIXES - include -) - -find_library(PSXSDK_LIBRARIES - NAMES psx - HINTS - ENV PSXSDK_PATH - PATH_SUFFIXES - lib -) - -if(PSXSDK_INCLUDE_DIRS AND EXISTS "${PSXSDK_INCLUDE_DIRS}/psx.h") - set(version_regex "^#define[ \t]+PSXSDK_VERSION_STRING[ \t]+\"([0-9\.]+)\"$") - file(STRINGS "${PSXSDK_INCLUDE_DIRS}/psx.h" PSXSDK_VERSION_LINE REGEX ${version_regex}) - string(REGEX REPLACE ${version_regex} "\\1" PSXSDK_VERSION "${PSXSDK_VERSION_LINE}") - unset(PSXSDK_VERSION_LINE) - unset(version_regex) -endif() - -include(FindPackageHandleStandardArgs) - -find_package_handle_standard_args(PSXSDK - REQUIRED_VARS - PSXSDK_LIBRARIES PSXSDK_INCLUDE_DIRS - VERSION_VAR - PSXSDK_VERSION -) - -if(PSXSDK_FOUND) - if(NOT TARGET PSXSDK::PSXSDK) - add_library(PSXSDK::PSXSDK INTERFACE IMPORTED) - target_include_directories(PSXSDK::PSXSDK - INTERFACE "${PSXSDK_INCLUDE_DIRS}") - set_target_properties(PSXSDK::PSXSDK PROPERTIES - IMPORTED_LOCATION "${PSXSDK_LIBRARIES}") - endif() -endif() diff --git a/cmake/FindWASI_SDK.cmake b/cmake/FindWASI_SDK.cmake new file mode 100644 index 0000000..28c7993 --- /dev/null +++ b/cmake/FindWASI_SDK.cmake @@ -0,0 +1,39 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +find_program(WASI_SDK_CLANG + clang + PATHS + /opt/wasi-sdk/bin + ENV WASI_SDK_PATH + NO_DEFAULT_PATH +) + +find_program(WASI_SDK_STRIP + strip + PATHS + /opt/wasi-sdk/bin + ENV WASI_SDK_PATH + NO_DEFAULT_PATH +) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WASI_SDK + REQUIRED_VARS + WASI_SDK_CLANG + WASI_SDK_STRIP +) diff --git a/cmake/ps1.cmake b/cmake/ps1.cmake index 21d77fa..14b6937 100644 --- a/cmake/ps1.cmake +++ b/cmake/ps1.cmake @@ -1,13 +1,8 @@ -find_package(PSXSDK 0.7.1 REQUIRED) - -target_compile_definitions(${PROJECT_NAME} PUBLIC FIXMATH_FAST_SIN PSXSDK_DEBUG) -add_custom_target(exe ALL elf2exe ${PROJECT_NAME} - ${cdroot}/${PROJECT_NAME}.exe -mark="A homebrew game created with PSXSDK" +add_custom_target(exe ALL ${TOOLS_PREFIX}/bin/elf2exe ${PROJECT_NAME} + ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.exe + -mark="wnix, a Unix-like operating system for WebAssembly applications" DEPENDS ${PROJECT_NAME}) -add_custom_target(iso ALL mkisofs -o ${PROJECT_NAME}.iso -V ${PROJECT_NAME} - -sysid PLAYSTATION ${cdroot} DEPENDS exe) - -set(license_prefix $ENV{PSXSDK_PATH}/share/licenses) +add_dependencies(exe tools) if(VIDEO_MODE STREQUAL "VMODE_PAL") set(region eur) @@ -24,20 +19,16 @@ elseif(VIDEO_MODE STREQUAL "VMODE_NTSC") set(region ${NTSC_REGION}) endif() -set(license $ENV{PSXSDK_PATH}/share/licenses/info${region}.dat) +add_custom_target(bin_cue ALL + ${TOOLS_PREFIX}/bin/mkpsxiso -q ${CMAKE_BINARY_DIR}/wnix.xml + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_custom_target(bin_cue ALL mkpsxiso ${PROJECT_NAME}.iso ${PROJECT_NAME}.bin - ${license} -s DEPENDS iso) +add_dependencies(bin_cue exe tools) -if(NOT EXISTS "${cdroot}/system.cnf") - file(COPY "src/ps1/system.cnf" DESTINATION "${cdroot}") -endif() +set(cflags ${cflags}) if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(cflags ${cflags} -Og) else() - set(cflags ${cflags} -Os) + set(cflags ${cflags} -O3 -g) endif() - -set(cflags ${cflags} -fshort-enums) -# libfixmath is already bundled with PSXSDK. diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt new file mode 100644 index 0000000..6d1cc25 --- /dev/null +++ b/programs/CMakeLists.txt @@ -0,0 +1,55 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +set(programs + initd + yes +) + +include(ExternalProject) +find_package(Clang REQUIRED) +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +foreach(p ${programs}) + set(cflags " \ + -g \ + ") + + set(ldflags " \ + ") + + ExternalProject_Add(${p}_wnix + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/${p} + BUILD_ALWAYS ON + CMAKE_ARGS + -D CMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_LIST_DIR}/wasm-clang-toolchain.cmake + -D CMAKE_C_FLAGS=${cflags} + -D CMAKE_EXE_LINKER_FLAGS=${ldflags} + -D CMAKE_BUILD_TYPE=Release + -D CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH} + -D CMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR} + ) + + add_custom_target(${p}_nwc ALL + ${TOOLS_PREFIX}/bin/nwc + ${CMAKE_CURRENT_BINARY_DIR}/bin/${p} ${CMAKE_BINARY_DIR}/bin/${p} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + BYPRODUCTS ${CMAKE_BINARY_DIR}/bin/${p} + ) + + add_dependencies(${p}_nwc ${p}_wnix tools) + add_dependencies(mkpsxiso_xml ${p}_nwc) +endforeach() diff --git a/programs/initd/CMakeLists.txt b/programs/initd/CMakeLists.txt new file mode 100644 index 0000000..500782a --- /dev/null +++ b/programs/initd/CMakeLists.txt @@ -0,0 +1,31 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +cmake_minimum_required(VERSION 3.13) +include(GNUInstallDirs) +project(initd C) +add_executable(${PROJECT_NAME} initd.c) +add_subdirectory(../wnix ${CMAKE_CURRENT_BINARY_DIR}/wnix) +target_link_libraries(${PROJECT_NAME} PRIVATE wnix) +# TODO: Debugging symbols could still be there, but nwc still has issues. +add_custom_target(${PROJECT_NAME}_strip ALL + ${CMAKE_STRIP} ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} +) +add_dependencies(${PROJECT_NAME}_strip ${PROJECT_NAME}) +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/programs/initd/initd.c b/programs/initd/initd.c new file mode 100644 index 0000000..67ac4d4 --- /dev/null +++ b/programs/initd/initd.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <sys/mount.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) +{ + if (mount("/dev/mc0", "/home", "ps1mcfs", 0, NULL)) + return errno; + + return 1; +} diff --git a/programs/wasm-clang-toolchain.cmake b/programs/wasm-clang-toolchain.cmake new file mode 100644 index 0000000..450b0f9 --- /dev/null +++ b/programs/wasm-clang-toolchain.cmake @@ -0,0 +1,37 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +find_package(Clang REQUIRED) +set(expr "^([0-9]+)\.([0-9]+)\.([0-9]+)$") +string(REGEX REPLACE ${expr} "\\1" LLVM_VERSION_MAJOR "${LLVM_VERSION}") +find_program(clang_exec clang-${LLVM_VERSION_MAJOR} REQUIRED) +set(CMAKE_C_COMPILER ${clang_exec}) +set(CMAKE_C_COMPILER_WORKS 1) +set(CMAKE_C_FLAGS " \ + ${CMAKE_C_FLAGS} \ + --target=wasm32-unknown-unknown-wasm \ + -fno-exceptions \ + -nostdinc \ + -nostdlib \ +") +set(CMAKE_EXE_LINKER_FLAGS "\ + -Wl,--threads=1 \ + --target=wasm32-unknown-unknown-wasm \ + -fno-exceptions \ + -nostdinc \ + -nostdlib \ +") +set(CMAKE_STRIP ${WASI_SDK_STRIP}) diff --git a/programs/wnix/CMakeLists.txt b/programs/wnix/CMakeLists.txt new file mode 100644 index 0000000..a118bd0 --- /dev/null +++ b/programs/wnix/CMakeLists.txt @@ -0,0 +1,26 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(wnix + mkdir.c + mount.c + sbrk.c + start.c +) +set(LIBC_FREESTANDING ON) +add_subdirectory(../../src/libc ${CMAKE_CURRENT_BINARY_DIR}/libc) +target_compile_definitions(c PRIVATE PRINTF_DISABLE_SUPPORT_FLOAT) +target_link_libraries(wnix PUBLIC c) diff --git a/programs/wnix/mkdir.c b/programs/wnix/mkdir.c new file mode 100644 index 0000000..5547616 --- /dev/null +++ b/programs/wnix/mkdir.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <sys/stat.h> +#include <errno.h> + +int mkdir(const char *const pathname, mode_t flags) +{ + int __wnix_mkdir(const char *, mode_t, int *) __attribute__(( + __import_module__("wnix"), + __import_name__("mkdir") + )); + + return __wnix_mkdir(pathname, flags, &errno); +} diff --git a/programs/wnix/mount.c b/programs/wnix/mount.c new file mode 100644 index 0000000..2512f73 --- /dev/null +++ b/programs/wnix/mount.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <sys/mount.h> +#include <errno.h> + +int mount(const char *const src, const char *const tgt, const char *const type, + const unsigned long flags, const void *const args) +{ + int __wnix_mount(const char *, const char *, const char *, + unsigned long, const void *, int *) __attribute__(( + __import_module__("wnix"), + __import_name__("mount") + )); + + return __wnix_mount(src, tgt, type, flags, args, &errno); +} diff --git a/programs/wnix/sbrk.c b/programs/wnix/sbrk.c new file mode 100644 index 0000000..7e32118 --- /dev/null +++ b/programs/wnix/sbrk.c @@ -0,0 +1,56 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <unistd.h> +#include <stddef.h> +#include <stdint.h> + +void *sbrk(const intptr_t increment) +{ + const unsigned pagesize = 64 << 10; + extern char __heap_base[]; + static char *cur = __heap_base, *end; + + if (increment < 0) + { + errno = EINVAL; + return NULL; + } + else if (!end) + end = cur + __builtin_wasm_memory_size(0) * pagesize; + + if (increment >= (intptr_t)end || cur >= end - increment) + { + const unsigned long pages = (uintptr_t)increment / pagesize, + new_end = __builtin_wasm_memory_grow(0, pages); + + if (!new_end) + { + errno = ENOMEM; + return NULL; + } + + end = (void *)new_end; + } + + void *ret = cur; + + cur += increment; + return ret; +} diff --git a/programs/wnix/start.c b/programs/wnix/start.c new file mode 100644 index 0000000..06dc4d5 --- /dev/null +++ b/programs/wnix/start.c @@ -0,0 +1,64 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> + +void _start(void) +{ + int main(int, char *[]); + int __wnix_argc(void) __attribute__(( + __import_module__("wnix"), + __import_name__("argc") + )); + _Noreturn void __wnix_exit(int) __attribute__(( + __import_module__("wnix"), + __import_name__("exit") + )); + + const int argc = __wnix_argc(); + char **argv = malloc((argc + 1) * sizeof *argv); + + if (!argv) + __wnix_exit(EXIT_FAILURE); + + for (int i = 0; i < argc; i++) + { + size_t __wnix_arglen(int) __attribute__(( + __import_module__("wnix"), + __import_name__("arglen") + )); + + int __wnix_argcopy(int, char *, int *) __attribute__(( + __import_module__("wnix"), + __import_name__("argcopy") + )); + + char *const arg = malloc(__wnix_arglen(i)); + + if (!arg) + __wnix_exit(EXIT_FAILURE); + + __wnix_argcopy(i, arg, &errno); + argv[i] = arg; + } + + argv[argc] = NULL; + __wnix_exit(main(argc, argv)); +} diff --git a/programs/yes/CMakeLists.txt b/programs/yes/CMakeLists.txt new file mode 100644 index 0000000..59abf8f --- /dev/null +++ b/programs/yes/CMakeLists.txt @@ -0,0 +1,31 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +cmake_minimum_required(VERSION 3.13) +include(GNUInstallDirs) +project(yes C) +add_executable(${PROJECT_NAME} yes.c) +add_subdirectory(../wnix ${CMAKE_CURRENT_BINARY_DIR}/wnix) +target_link_libraries(${PROJECT_NAME} PRIVATE wnix) +# TODO: Debugging symbols could still be there, but nwc still has issues. +add_custom_target(${PROJECT_NAME}_strip ALL + ${CMAKE_STRIP} ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} +) +add_dependencies(${PROJECT_NAME}_strip ${PROJECT_NAME}) +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/programs/yes/yes.c b/programs/yes/yes.c new file mode 100644 index 0000000..bdc9d9d --- /dev/null +++ b/programs/yes/yes.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#if 0 +#include <stdio.h> +#include <stdlib.h> +#endif + +int main(int argc, char *argv[]) +{ +#if 0 + for (;;) + puts("y"); + + return EXIT_SUCCESS; +#else +return 0; +#endif +} diff --git a/res/CMakeLists.txt b/res/CMakeLists.txt index 8fb119e..92baf7a 100644 --- a/res/CMakeLists.txt +++ b/res/CMakeLists.txt @@ -1,11 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake) -sprite(NAME font - X 472 +sprite(NAME pixfont + X 640 Y 0 BPP 4 - CX 368 + CX 640 CY 498 TRANSPARENT TRUE) - -container(NAME ${PROJECT_NAME} SPRITES font) diff --git a/res/LICENSE b/res/LICENSE index 14474c2..0991335 100644 --- a/res/LICENSE +++ b/res/LICENSE @@ -1,6 +1,6 @@ All assets on this folder are either original or have originated from subfolder "orig". Read LICENSE file in "orig" for further reference. -font.bmp: -font_24.bmp: - Derived work from sprFont.png +pixfont.bmp: +pixfont_24.bmp: + Derived work from pixfont.png diff --git a/res/font.bmp b/res/font.bmp Binary files differdeleted file mode 100644 index 7fc1c36..0000000 --- a/res/font.bmp +++ /dev/null diff --git a/res/font_24.bmp b/res/font_24.bmp Binary files differdeleted file mode 100644 index b12a8ce..0000000 --- a/res/font_24.bmp +++ /dev/null diff --git a/res/functions.cmake b/res/functions.cmake index a0de87d..57119ce 100644 --- a/res/functions.cmake +++ b/res/functions.cmake @@ -20,7 +20,7 @@ function(sprite) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${SPRITE_NAME}.bmp BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SPRITE_NAME}) - add_dependencies(iso ${SPRITE_NAME}_img) + add_dependencies(bin_cue ${SPRITE_NAME}_img) elseif(SDL1_2_BUILD) if(${SPRITE_TRANSPARENT}) set(trans "transparent=1") @@ -57,7 +57,7 @@ function(sound) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${SOUND_NAME}.wav BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${SOUND_NAME}) - add_dependencies(iso ${SOUND_NAME}_snd) + add_dependencies(bin_cue ${SOUND_NAME}_snd) elseif(SDL1_2_BUILD) if(${SOUND_LOOP}) set(loop "loop=1") diff --git a/res/orig/LICENSE b/res/orig/LICENSE index bfab4ed..8860bc8 100644 --- a/res/orig/LICENSE +++ b/res/orig/LICENSE @@ -1,3 +1,4 @@ -sprFont.png: - https://opengameart.org/content/kl-font +pixfont.png: + https://opengameart.org/content/16x12-terminal-bitmap-font + Author: CruzR License(s): CC0 diff --git a/res/orig/pixfont.png b/res/orig/pixfont.png Binary files differnew file mode 100644 index 0000000..418b41d --- /dev/null +++ b/res/orig/pixfont.png diff --git a/res/orig/sprFont.png b/res/orig/sprFont.png Binary files differdeleted file mode 100644 index 78a9d78..0000000 --- a/res/orig/sprFont.png +++ /dev/null diff --git a/res/pixfont.bmp b/res/pixfont.bmp Binary files differnew file mode 100644 index 0000000..addee36 --- /dev/null +++ b/res/pixfont.bmp diff --git a/res/pixfont_24.bmp b/res/pixfont_24.bmp Binary files differnew file mode 100644 index 0000000..e0682ee --- /dev/null +++ b/res/pixfont_24.bmp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f28e58..05c73c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# wanix, a Unix-like operating system for WebAssembly +# wnix, a Unix-like operating system for WebAssembly applications. # Copyright (C) 2025 Xavier Del Campo Romero # # This program is free software: you can redistribute it and/or modify @@ -14,17 +14,33 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. +set(NW_LOG_CUSTOM ON) add_subdirectory(nanowasm) -target_link_libraries(${PROJECT_NAME} PRIVATE nanowasm) +set(WIP_LOG_CUSTOM ON) +add_subdirectory(wip) +add_subdirectory(dynstr) # Avoid C11 since it is not supported by the i386-mingw32 toolchain. -set(cflags ${cflags} -Wall -ffunction-sections -fdata-sections -pedantic) +set(cflags ${cflags} -Wall -pedantic) set(components aio + bin + caio + drv + endian + fs + gfx + init + io + kprintf + loop + net + page ) set(interfaces + state ) if(PS1_BUILD) @@ -35,24 +51,24 @@ endif() target_compile_options(${PROJECT_NAME} PUBLIC ${cflags}) target_compile_options(nanowasm PUBLIC ${cflags}) # Dependencies for main.c -# target_link_libraries(${PROJECT_NAME} PRIVATE) +target_link_libraries(${PROJECT_NAME} PRIVATE gfx init loop) foreach(c ${components}) - add_subdirectory("${c}") + add_subdirectory(${c}) target_compile_options(${c} PUBLIC ${cflags}) target_compile_features(${c} PUBLIC c_std_99) set_target_properties(${c} PROPERTIES C_STANDARD 99 C_EXTENSIONS OFF) target_link_libraries(${PROJECT_NAME} PRIVATE ${c}) if(PS1_BUILD) - target_link_libraries(${c} PRIVATE c) + target_link_libraries(${c} PUBLIC c) endif() endforeach() foreach(i ${interfaces}) - add_subdirectory("${i}") + add_subdirectory(${i}) target_compile_options(${i} INTERFACE ${cflags}) - target_link_libraries(${PROJECT_NAME} PRIVATE ${c}) + target_link_libraries(${i} INTERFACE ${c}) endforeach() target_link_options(${PROJECT_NAME} PRIVATE -Wl,--gc-sections) diff --git a/src/aio/CMakeLists.txt b/src/aio/CMakeLists.txt index 3f4561a..278192b 100644 --- a/src/aio/CMakeLists.txt +++ b/src/aio/CMakeLists.txt @@ -1,6 +1,20 @@ -set(src - "src/close.c" - "src/open.c" -) -add_library(aio ${src}) -target_include_directories(aio PUBLIC "include" PRIVATE "private_include") +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(aio) +add_subdirectory(src) +target_include_directories(aio PUBLIC include PRIVATE private_include) +target_link_libraries(aio PUBLIC fs INTERFACE state) diff --git a/src/aio/include/aio.h b/src/aio/include/aio.h index f9f76cb..9486f3f 100644 --- a/src/aio/include/aio.h +++ b/src/aio/include/aio.h @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -19,17 +19,41 @@ #ifndef AIO_H #define AIO_H +#include <fs/fs.h> +#include <sys/types.h> +#include <state.h> +#include <stdbool.h> #include <stddef.h> -enum +struct aio_poll { - AIO_POLLIN = 1, - AIO_POLLOUT = 1 << 1 + const struct aio *aio; + bool done; + int error; + struct aio_poll *prev, *next; }; -struct aio *aio_open(const char *path, const char *mode); -int aio_poll(struct aio **io, size_t n); -int aio_event(const struct aio *io, int ev); -int aio_close(struct aio *io); +struct aio_done +{ + int (*f)(enum state state, void *args); + void *args; +}; + +struct aio_mount +{ + struct fs_mount mount; + const char *type; +}; + +struct aio *aio_mount(const struct aio_mount *m, const struct aio_done *d); +struct aio *aio_mkdir(const struct fs_mkdir *m, const struct aio_done *d); +struct aio *aio_open(const struct fs_open *o, const struct aio_done *d); +struct aio *aio_read(const struct fs_read *r, const struct aio_done *d); +struct aio *aio_write(const struct fs_write *w, const struct aio_done *d); +struct aio *aio_stat(const struct fs_stat *s, const struct aio_done *d); +int aio_read_nb(const struct fs_read *r); +int aio_poll(struct aio_poll *p, int ms); +int aio_close(struct fs_fd *fd); +void aio_free(struct aio *io); #endif diff --git a/src/aio/private_include/aio/types.h b/src/aio/private_include/aio/types.h index 31ee414..1fee8c1 100644 --- a/src/aio/private_include/aio/types.h +++ b/src/aio/private_include/aio/types.h @@ -1,16 +1,32 @@ -#ifndef AIO_PRV_OPEN_H -#define AIO_PRV_OPEN_H +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ -enum aio_state -{ - AIO_OK, - AIO_AGAIN, - AIO_FATAL -}; +#ifndef AIO_TYPES_H +#define AIO_TYPES_H + +#include <aio.h> +#include <fs/fs.h> struct aio { - enum aio_state (*next)(struct aio *); + int error; + struct fs_ret r; + struct aio_done done; }; #endif diff --git a/src/aio/src/CMakeLists.txt b/src/aio/src/CMakeLists.txt new file mode 100644 index 0000000..ba4af9c --- /dev/null +++ b/src/aio/src/CMakeLists.txt @@ -0,0 +1,28 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(aio PRIVATE + close.c + free.c + mkdir.c + mount.c + open.c + poll.c + read.c + read_nb.c + stat.c + write.c +) diff --git a/src/aio/src/close.c b/src/aio/src/close.c index a6067a8..68c5dd7 100644 --- a/src/aio/src/close.c +++ b/src/aio/src/close.c @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -17,18 +17,13 @@ */ #include <aio.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> +#include <aio/types.h> +#include <fs/fs.h> -int aio_close(struct aio *const aio) +int aio_close(struct fs_fd *const fd) { - if (!aio) - { - errno = EINVAL; - return EOF; - } + if (fd->mp && fd->mp->fs) + return fd->mp->fs->close(fd); - free(aio); - return 0; + return -1; } diff --git a/src/aio/src/free.c b/src/aio/src/free.c new file mode 100644 index 0000000..cfefb1c --- /dev/null +++ b/src/aio/src/free.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <stdlib.h> + +void aio_free(struct aio *const aio) +{ + free(aio); +} diff --git a/src/aio/src/mkdir.c b/src/aio/src/mkdir.c new file mode 100644 index 0000000..40b09b6 --- /dev/null +++ b/src/aio/src/mkdir.c @@ -0,0 +1,137 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <aio/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <sys/stat.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +struct mkdir +{ + struct fs_mkdir mkdir; + struct aio_done done; + char *path, *parent; + struct aio *aio; +}; + +static void free_mkdir(struct mkdir *const mk) +{ + if (mk) + { + free(mk->path); + free(mk->parent); + } + + free(mk); +} + +static int done(const enum state state, void *const args) +{ + int ret = 0; + struct mkdir *const mk = args; + const struct aio_done *const d = &mk->done; + + if (d->f) + ret = d->f(state, d->args); + + free_mkdir(mk); + return ret; +} + +static int search_done(const enum state state, + const char *const relpath, const struct fs_mp *const mp, + const union inode_result *const inode, void *const args) +{ + struct mkdir *const mk = args; + struct aio *const aio = mk->aio; + const struct fs *const fs = mp->fs; + const char *path = mk->path; + struct fs_ret r; + + path += strlen(mp->tgt) + strlen(relpath); + mk->mkdir.path = path; + + if (fs->mkdir(&mk->mkdir, mp, inode, &r)) + goto failure; + + aio->r = r; + return 0; + +failure: + aio->error = errno; + aio->done = mk->done; + free_mkdir(mk); + return -1; +} + +struct aio *aio_mkdir(const struct fs_mkdir *const m, + const struct aio_done *const d) +{ + struct aio *aio = NULL; + struct mkdir *mk = NULL; + char *const pathdup = strdup(m->path), *parent = NULL; + + if (!pathdup + || !(parent = fs_parent(m->path)) + || !(mk = malloc(sizeof *mk)) + || !(aio = malloc(sizeof *aio))) + goto failure; + + *mk = (const struct mkdir) + { + .path = pathdup, + .parent = parent, + .aio = aio, + .mkdir = *m + }; + + *aio = (const struct aio) + { + .done = + { + .args = mk, + .f = done + } + }; + + const struct inode_search s = + { + .path = parent, + .done = search_done, + .args = mk + }; + + if (d) + mk->done = *d; + else if (inode_search(&s, &aio->r)) + goto failure; + + return aio; + +failure: + free(mk); + free(aio); + free(parent); + free(pathdup); + return NULL; +} diff --git a/src/aio/src/mount.c b/src/aio/src/mount.c new file mode 100644 index 0000000..418fb69 --- /dev/null +++ b/src/aio/src/mount.c @@ -0,0 +1,174 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <aio/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <sys/types.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +struct mount +{ + char *src, *tgt; + struct aio *aio; + const struct fs *fs; + struct fs_mount mount; + struct aio_done done; +}; + +static void free_mount(struct mount *const m) +{ + if (m) + { + free(m->src); + free(m->tgt); + } + + free(m); +} + +static int done(const enum state state, void *const args) +{ + int ret = 0; + struct mount *const m = args; + const struct aio_done *const d = &m->done; + + if (d->f) + ret = d->f(state, d->args); + + free_mount(m); + return ret; +} + +static int search_done(const enum state s, const char *const relpath, + const struct fs_mp *const mp, const union inode_result *const inode, + void *const args) +{ + struct mount *const m = args; + struct aio *const aio = m->aio; + const struct fs *const fs = m->fs; + + if (strcmp(m->tgt, "/")) + { + if (!inode) + { + aio->error = ENOENT; + goto failure; + } + else if (mp->fs->iops.flags(inode) & INODE_MOUNTPOINT) + { + aio->error = EBUSY; + goto failure; + } + } + + if (fs->mount(&m->mount, &aio->r)) + { + aio->error = errno; + goto failure; + } + + return 0; + +failure: + aio->done = m->done; + free_mount(m); + return -1; +} + +struct aio *aio_mount(const struct aio_mount *const am, + const struct aio_done *const d) +{ + struct aio *aio = NULL; + const struct fs_mount *const m = &am->mount; + const struct fs *const fs = fs_from_type(am->type); + char *srcdup = NULL, *tgtdup = NULL; + struct mount *pm = NULL; + struct fs_mp mp; + + if (!fs) + { + errno = ENODEV; + goto failure; + } + else if (!m->src && fs->flags & FS_DEV_REQUIRED) + { + errno = ENOTBLK; + goto failure; + } + else if (!fs_mp_from_path(m->tgt, &mp) + && m->src && !strcmp(mp.src, m->src)) + { + errno = EBUSY; + goto failure; + } + else if ((m->src && !(srcdup = strdup(m->src))) + || !(tgtdup = strdup(m->tgt)) + || !(pm = malloc(sizeof *pm)) + || !(aio = malloc(sizeof *aio))) + goto failure; + + const struct inode_search s = + { + .path = m->tgt, + .done = search_done, + .args = pm + }; + + *pm = (const struct mount) + { + .aio = aio, + .src = srcdup, + .tgt = tgtdup, + .fs = fs, + .mount = + { + .src = srcdup, + .tgt = tgtdup, + .mode = m->mode, + .gid = m->gid, + .uid = m->uid + } + }; + + *aio = (const struct aio) + { + .done = + { + .f = done, + .args = pm + } + }; + + if (inode_search(&s, &aio->r)) + goto failure; + else if (d) + pm->done = *d; + + return aio; + +failure: + free(tgtdup); + free(srcdup); + free(pm); + free(aio); + return NULL; +} diff --git a/src/aio/src/open.c b/src/aio/src/open.c index 89fbbba..4ee94a9 100644 --- a/src/aio/src/open.c +++ b/src/aio/src/open.c @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -16,18 +16,111 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#include <aio.h> +#include <fs/fs.h> #include <aio/types.h> +#include <state.h> +#include <errno.h> #include <stddef.h> #include <stdlib.h> -struct aio *aio_open(const char *const path, const char *const mode) +struct open { - struct aio *const ret = malloc(sizeof *ret); + struct aio *aio; + struct fs_open open; + struct aio_done done; +}; - if (!ret) +static int done(const enum state s, void *const args) +{ + struct open *const o = args; + const struct aio_done *const d = &o->done; + + if (d->f) + d->f(s, d->args); + + free(o); + return 0; +} + +static enum state opened(void *const args) +{ + return STATE_OK; +} + +static int search_done(const enum state state, const char *const relpath, + const struct fs_mp *const mp, const union inode_result *const inode, + void *const args) +{ + struct open *const o = args; + struct aio *const aio = o->aio; + const struct fs *const fs = mp->fs; + + if (!inode) + { + aio->error = ENOENT; goto failure; + } + + aio->r = (const struct fs_ret) + { + .f = opened, + .args = o + }; + + if (fs->open(&o->open, mp, inode, &aio->r)) + { + aio->error = errno; + goto failure; + } + + return 0; + +failure: + aio->done = o->done; + free(o); + return -1; +} + +struct aio *aio_open(const struct fs_open *const op, + const struct aio_done *const d) +{ + struct aio *aio = NULL; + struct open *const o = malloc(sizeof *o); + + if (!o || !(aio = malloc(sizeof *aio))) + goto failure; + + *o = (const struct open) + { + .aio = aio, + .open = *op + }; + + *aio = (const struct aio) + { + .done = + { + .f = done, + .args = o + } + }; + + const struct inode_search s = + { + .path = op->path, + .done = search_done, + .args = o + }; + + if (inode_search(&s, &aio->r)) + goto failure; + else if (d) + o->done = *d; + + return aio; failure: - free(ret); + free(aio); return NULL; } diff --git a/src/aio/src/poll.c b/src/aio/src/poll.c new file mode 100644 index 0000000..9a792a8 --- /dev/null +++ b/src/aio/src/poll.c @@ -0,0 +1,77 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <aio/types.h> +#include <state.h> +#include <stdbool.h> +#include <stddef.h> +#include <time.h> + +int aio_poll(struct aio_poll *const poll, int ms) +{ + struct timespec init; + + if (ms > 0 && clock_gettime(CLOCK_REALTIME, &init)) + return -1; + + do + { + for (struct aio_poll *p = poll; p;) + { + struct aio_poll *const next = p->next; + const struct aio *const aio = p->aio; + const struct fs_ret *const r = &aio->r; + const enum state s = r->f(r->args); + + switch (s) + { + case STATE_AGAIN: + break; + + case STATE_FATAL: + p->error = aio->error; + /* Fall through */ + case STATE_OK: + { + const struct aio_done *const d = &aio->done; + + if (d->f) + return d->f(s, d->args) ? -1 : 1; + + p->done = true; + return 1; + } + } + + p = next; + } + + if (ms > 0) + { + struct timespec after; + + if (clock_gettime(CLOCK_REALTIME, &after)) + return -1; + + /* TODO */ + } + } while (ms); + + return 0; +} diff --git a/src/aio/src/read.c b/src/aio/src/read.c new file mode 100644 index 0000000..f57c3b0 --- /dev/null +++ b/src/aio/src/read.c @@ -0,0 +1,82 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <fs/fs.h> +#include <aio/types.h> +#include <state.h> +#include <stddef.h> +#include <stdlib.h> + +struct read +{ + struct aio_done done; +}; + +static int done(const enum state s, void *const args) +{ + int ret = 0; + struct read *const r = args; + const struct aio_done *const d = &r->done; + + if (d->f) + ret = d->f(s, d->args); + + free(r); + return ret; +} + +static enum state read_done(void *const args) +{ + return STATE_OK; +} + +struct aio *aio_read(const struct fs_read *const fr, + const struct aio_done *const d) +{ + struct aio *aio = NULL; + struct read *const r = malloc(sizeof *r); + struct fs_fd *const fd = fr->fd; + const struct fs *const fs = fd->mp->fs; + + if (!r || !(aio = malloc(sizeof *aio))) + goto failure; + + *r = (const struct read){0}; + *aio = (const struct aio) + { + .r.f = read_done, + .done = + { + .f = done, + .args = r + } + }; + + if (fs->read(fr, &aio->r)) + goto failure; + else if (d) + r->done = *d; + + return aio; + +failure: + free(r); + free(aio); + return NULL; +} diff --git a/src/aio/src/read_nb.c b/src/aio/src/read_nb.c new file mode 100644 index 0000000..133a75a --- /dev/null +++ b/src/aio/src/read_nb.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <aio/types.h> +#include <fs/fs.h> + +int aio_read_nb(const struct fs_read *const fr) +{ + const struct fs_fd *const fd = fr->fd; + const struct fs *const fs = fd->mp->fs; + + return fs->read_nb(fr); +} diff --git a/src/aio/src/stat.c b/src/aio/src/stat.c new file mode 100644 index 0000000..4c8ae35 --- /dev/null +++ b/src/aio/src/stat.c @@ -0,0 +1,117 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <aio/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <sys/types.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +struct stat_prv +{ + struct fs_stat stat; + struct aio_done done; + struct aio *aio; +}; + +static int done(const enum state state, void *const args) +{ + int ret = 0; + struct stat_prv *const p = args; + const struct aio_done *const d = &p->done; + + if (d->f) + ret = d->f(state, d->args); + + free(p); + return ret; +} + +static int search_done(const enum state s, const char *const relpath, + const struct fs_mp *const mp, const union inode_result *const inode, + void *const args) +{ + struct stat_prv *const p = args; + struct aio *const aio = p->aio; + const struct fs *const fs = mp->fs; + + if (!inode) + { + aio->error = ENOENT; + goto failure; + } + else if (fs->stat(&p->stat, mp, inode, &aio->r)) + { + aio->error = errno; + goto failure; + } + + return 0; + +failure: + aio->done = p->done; + free(p); + return -1; +} + +struct aio *aio_stat(const struct fs_stat *const as, + const struct aio_done *const d) +{ + struct aio *const aio = malloc(sizeof *aio); + struct stat_prv *const p = malloc(sizeof *p); + + if (!p || !aio) + goto failure; + + const struct inode_search s = + { + .path = as->path, + .done = search_done, + .args = p + }; + + *p = (const struct stat_prv) + { + .aio = aio, + .stat = *as + }; + + *aio = (const struct aio) + { + .done = + { + .f = done, + .args = p + } + }; + + if (inode_search(&s, &aio->r)) + goto failure; + else if (d) + p->done = *d; + + return aio; + +failure: + free(p); + free(aio); + return NULL; +} diff --git a/src/aio/src/write.c b/src/aio/src/write.c new file mode 100644 index 0000000..75f167f --- /dev/null +++ b/src/aio/src/write.c @@ -0,0 +1,82 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <aio.h> +#include <fs/fs.h> +#include <aio/types.h> +#include <state.h> +#include <stddef.h> +#include <stdlib.h> + +struct write +{ + struct aio_done done; +}; + +static int done(const enum state s, void *const args) +{ + int ret = 0; + struct write *const w = args; + const struct aio_done *const d = &w->done; + + if (d->f) + ret = d->f(s, d->args); + + free(w); + return ret; +} + +static enum state write_done(void *const args) +{ + return STATE_OK; +} + +struct aio *aio_write(const struct fs_write *const fw, + const struct aio_done *const d) +{ + struct aio *aio = NULL; + struct write *const w = malloc(sizeof *w); + struct fs_fd *const fd = fw->fd; + const struct fs *const fs = fd->mp->fs; + + if (!w || !(aio = malloc(sizeof *aio))) + goto failure; + + *w = (const struct write){0}; + *aio = (const struct aio) + { + .r.f = write_done, + .done = + { + .f = done, + .args = w + } + }; + + if (fs->write(fw, &aio->r)) + goto failure; + else if (d) + w->done = *d; + + return aio; + +failure: + free(w); + free(aio); + return NULL; +} diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt new file mode 100644 index 0000000..c0031b3 --- /dev/null +++ b/src/bin/CMakeLists.txt @@ -0,0 +1,35 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(bin) +add_subdirectory(src) +target_include_directories(bin PUBLIC include PRIVATE private_include) +target_link_libraries(bin PRIVATE + aio + caio + dynstr + endian + fs + kprintf + loop + nanowasm + page + state + + + + drv_ps1_bios +) diff --git a/src/bin/include/bin.h b/src/bin/include/bin.h new file mode 100644 index 0000000..a5528c5 --- /dev/null +++ b/src/bin/include/bin.h @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_H +#define BIN_H + +#include <sys/types.h> + +int bin_exec(const char *path, const char *const *argv, uid_t uid, gid_t gid); +int bin_update(void); + +#endif diff --git a/src/bin/private_include/bin/mod.h b/src/bin/private_include/bin/mod.h new file mode 100644 index 0000000..13ef55c --- /dev/null +++ b/src/bin/private_include/bin/mod.h @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_MOD_H +#define BIN_MOD_H + +#include <bin/types.h> +#include <nanowasm/nw.h> +#include <stddef.h> + +const struct bin_mod *bin_mod(const char *path); +int bin_mod_lock(struct bin_mod *m); +int bin_mod_unlock(struct bin_mod *m); +int bin_mod_move(struct bin_mod *m, struct bin *from, struct bin *to); +void bin_mod_free(struct bin_mod *m); +int bin_mod_read(void *buf, size_t n, void *user); +int bin_mod_eof(void *user); +enum nw_state bin_mod_pc(long offset, struct nw_next *next, void *user); +enum nw_state bin_mod_seek(long offset, void *user); +enum nw_state bin_mod_tell(long *offset, void *user); + +extern const struct nw_mod_cfg bin_mod_cfg; + +#endif diff --git a/src/bin/private_include/bin/proc.h b/src/bin/private_include/bin/proc.h new file mode 100644 index 0000000..cf0c04e --- /dev/null +++ b/src/bin/private_include/bin/proc.h @@ -0,0 +1,49 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_PROC_H +#define BIN_PROC_H + +#include <bin/types.h> +#include <nanowasm/nw.h> +#include <stddef.h> + +int bin_proc_init(struct bin_proc *p); +int bin_proc_add(struct bin_proc *p); +void bin_proc_free(struct bin_proc *p); +int bin_proc_read(void *buf, size_t n, void *user); +int bin_proc_eof(void *user); +enum nw_state bin_proc_pc(long offset, struct nw_next *next, void *user); +enum nw_state bin_proc_seek(long offset, void *user); +enum nw_state bin_proc_tell(long *offset, void *user); +int bin_proc_lock(struct bin_proc *p); +int bin_proc_unlock(struct bin_proc *p); +int bin_proc_move(struct bin_proc *p, struct bin *from, struct bin *to); +int bin_proc_l_load(unsigned long pos, void *dst, size_t n, void *user); +int bin_proc_l_store(unsigned long pos, const void *src, size_t n, void *user); +int bin_proc_g_load(unsigned long pos, void *dst, size_t n, void *user); +int bin_proc_g_store(unsigned long pos, const void *src, size_t n, void *user); +int bin_proc_s_push(const void *src, size_t n, void *user); +int bin_proc_s_pop(void *dst, size_t n, void *user); +int bin_proc_s_read(size_t offset, void *dst, size_t n, void *user); +int bin_proc_s_write(size_t offset, const void *dst, size_t n, void *user); +size_t bin_proc_s_ptr(void *user); + +extern const struct nw_inst_cfg bin_proc_cfg; + +#endif diff --git a/src/bin/private_include/bin/routines.h b/src/bin/private_include/bin/routines.h new file mode 100644 index 0000000..c78ad18 --- /dev/null +++ b/src/bin/private_include/bin/routines.h @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_ROUTINES_H +#define BIN_ROUTINES_H + +#include <bin/types.h> +#include <sys/types.h> +#include <stdbool.h> + +pid_t bin_pid(void); +int bin_start(struct bin_mod *m); +int bin_stop(struct bin_proc *p); +int bin_load(struct bin_mod *m); +int bin_unload(struct bin_mod *m); + +#endif diff --git a/src/bin/private_include/bin/types.h b/src/bin/private_include/bin/types.h new file mode 100644 index 0000000..2a498ed --- /dev/null +++ b/src/bin/private_include/bin/types.h @@ -0,0 +1,99 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_TYPES_H +#define BIN_TYPES_H + +#include <bin/wasi.h> +#include <caio.h> +#include <fs/fs.h> +#include <dynstr.h> +#include <nanowasm/nw.h> +#include <nanowasm/dbg.h> +#include <sys/types.h> +#include <stdbool.h> + +enum {BIN_IMPORTS = 9}; + +struct bin_dbg +{ + char b; + bool running, step; + struct nw_dbg dbg; + struct dynstr dstr; + struct aio *aio; + struct fs_fd fd; + long *bkpt, offset; + size_t n_bkpt; +}; + +struct bin_stack +{ + struct page *page; + size_t sz, pi, n; +}; + +struct bin_global +{ + void *buf; + size_t sz; +}; + +struct bin_proc +{ + const struct bin_mod *mod; + struct nw_inst instance; + union nw_value args[7]; + struct bin_dbg dbg; + struct caio *caio; + char *path, **argv; + size_t argc; + pid_t pid; + uid_t uid; + gid_t gid; + char header[sizeof "asm"]; + size_t i; + long retval; + struct bin_stack stack; + struct bin_global global; + void *import; + struct page *linear; + int *fds; + size_t n_fds; + struct bin_proc *prev, *next; +}; + +struct bin_mod +{ + char *path; + struct caio *caio; + struct nw_mod mod; + struct nw_mod_out mod_out; + struct nw_import_index import_indexes[BIN_IMPORTS]; + struct bin_mod *prev, *next; +}; + +struct bin +{ + struct bin_mod *mod_head, *mod_tail; + struct bin_proc *proc_head, *proc_tail; +}; + +extern struct bin bin_active, bin_pending, bin_locked, bin_zombie; + +#endif diff --git a/src/bin/private_include/bin/wasi.h b/src/bin/private_include/bin/wasi.h new file mode 100644 index 0000000..c22c777 --- /dev/null +++ b/src/bin/private_include/bin/wasi.h @@ -0,0 +1,41 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_WASI_H +#define BIN_WASI_H + +#include <nanowasm/nw.h> + +enum nw_state bin_wasi_proc_exit(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_fd_prestat_get(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_fd_prestat_dir_name(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_path_create_directory(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_fd_close(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_fd_fdstat_get(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_fd_seek(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wasi_fd_write(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); + +#endif diff --git a/src/bin/private_include/bin/wasi/errno.h b/src/bin/private_include/bin/wasi/errno.h new file mode 100644 index 0000000..442e877 --- /dev/null +++ b/src/bin/private_include/bin/wasi/errno.h @@ -0,0 +1,105 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef WASI_ERRNO_H +#define WASI_ERRNO_H + +enum wasi_errno +{ + WASI_SUCCESS, + WASI_2BIG, + WASI_ACCES, + WASI_ADDRINUSE, + WASI_ADDRNOTAVAIL, + WASI_AFNOSUPPORT, + WASI_AGAIN, + WASI_ALREADY, + WASI_BADF, + WASI_BADMSG, + WASI_BUSY, + WASI_CANCELED, + WASI_CHILD, + WASI_CONNABORTED, + WASI_CONNREFUSED, + WASI_CONNRESET, + WASI_DEADLK, + WASI_DESTADDRREQ, + WASI_DOM, + WASI_DQUOT, + WASI_EXIST, + WASI_FAULT, + WASI_FBIG, + WASI_HOSTUNREACH, + WASI_IDRM, + WASI_ILSEQ, + WASI_INPROGRESS, + WASI_INTR, + WASI_INVAL, + WASI_IO, + WASI_ISCONN, + WASI_ISDIR, + WASI_LOOP, + WASI_MFILE, + WASI_MLINK, + WASI_MSGSIZE, + WASI_MULTIHOP, + WASI_NAMETOOLONG, + WASI_NETDOWN, + WASI_NETRESET, + WASI_NETUNREACH, + WASI_NFILE, + WASI_NOBUFS, + WASI_NODEV, + WASI_NOENT, + WASI_NOEXEC, + WASI_NOLCK, + WASI_NOLINK, + WASI_NOMEM, + WASI_NOMSG, + WASI_NOPROTOOPT, + WASI_NOSPC, + WASI_NOSYS, + WASI_NOTCONN, + WASI_NOTDIR, + WASI_NOTEMPTY, + WASI_NOTRECOVERABLE, + WASI_NOTSOCK, + WASI_NOTSUP, + WASI_NOTTY, + WASI_NXIO, + WASI_OVERFLOW, + WASI_OWNERDEAD, + WASI_PERM, + WASI_PIPE, + WASI_PROTO, + WASI_PROTONOSUPPORT, + WASI_PROTOTYPE, + WASI_RANGE, + WASI_ROFS, + WASI_SPIPE, + WASI_SRCH, + WASI_STALE, + WASI_TIMEDOUT, + WASI_TXTBSY, + WASI_XDEV, + WASI_NOTCAPABLE +}; + +int wasi_errno(int error, enum wasi_errno *out); + +#endif diff --git a/src/bin/private_include/bin/wnix.h b/src/bin/private_include/bin/wnix.h new file mode 100644 index 0000000..07e7131 --- /dev/null +++ b/src/bin/private_include/bin/wnix.h @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_WNIX_H +#define BIN_WNIX_H + +#include <nanowasm/nw.h> + +enum nw_state bin_wnix_exit(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wnix_argc(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wnix_arglen(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wnix_argcopy(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wnix_mkdir(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); +enum nw_state bin_wnix_mount(const union nw_value *params, + union nw_value *ret, void *user, struct nw_next *next); + +#endif diff --git a/src/bin/private_include/bin/wnix/routines.h b/src/bin/private_include/bin/wnix/routines.h new file mode 100644 index 0000000..aa488fb --- /dev/null +++ b/src/bin/private_include/bin/wnix/routines.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef BIN_WNIX_ROUTINES_H +#define BIN_WNIX_ROUTINES_H + +#include <bin.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +int bin_wnix_set_errno(struct bin_proc *p, int error, unsigned long addr, + struct nw_next *next); + +#endif diff --git a/src/bin/src/CMakeLists.txt b/src/bin/src/CMakeLists.txt new file mode 100644 index 0000000..0057f11 --- /dev/null +++ b/src/bin/src/CMakeLists.txt @@ -0,0 +1,30 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + exec.c + globals.c + load.c + loaded.c + pid.c + start.c + stop.c + update.c +) + +add_subdirectory(wnix) +add_subdirectory(mod) +add_subdirectory(proc) diff --git a/src/bin/src/exec.c b/src/bin/src/exec.c new file mode 100644 index 0000000..83c0e5f --- /dev/null +++ b/src/bin/src/exec.c @@ -0,0 +1,372 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/proc.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <aio.h> +#include <caio.h> +#include <fs/fs.h> +#include <loop.h> +#include <kprintf.h> +#include <dynstr.h> +#include <nanowasm/nw.h> +#include <nanowasm/dbg.h> +#include <fcntl.h> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> + +struct exec +{ + struct bin_mod *m; + struct bin_proc *p; +}; + +static int announced(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + struct bin_dbg *const d = &p->dbg; + const struct nw_dbg_cfg cfg = {.inst = &p->instance}; + + dynstr_free(&d->dstr); + + if (loop_rm_aio(d->aio)) + goto failure; + + aio_free(d->aio); + + if (state) + kprintf("failed to announce process to debugger: %s\n", p->path); + else + nw_dbg_init(&d->dbg, &cfg); + + return 0; + +failure: + bin_proc_free(p); + return -1; +} + +static int announce(struct bin_proc *const p) +{ + struct aio *aio = NULL; + struct bin_dbg *const dbg = &p->dbg; + struct dynstr *const s = &dbg->dstr; + const struct aio_done d = + { + .f = announced, + .args = p + }; + + dynstr_init(s); + + if (dynstr_append(s, ";hi:%s:%u\n", p->path, (unsigned)p->pid)) + goto failure; + + const struct fs_write w = + { + .buf = s->str, + .n = s->len + 1, + .fd = &dbg->fd + }; + + if (!(aio = aio_write(&w, &d)) || loop_add_aio(aio)) + goto failure; + + dbg->aio = aio; + return 0; + +failure: + aio_free(aio); + return -1; +} + +static int mod_opened(const enum state state, void *const args) +{ + struct exec *const e = args; + struct bin_mod *const m = e->m; + struct bin_proc *const p = e->p; + struct nw_mod_cfg cfg = bin_mod_cfg; + + cfg.io.user = m; + cfg.imp_indexes = m->import_indexes; + nw_init(&m->mod, &cfg); + + if (state) + goto failure; + else if (bin_load(m) + || bin_proc_init(p) + || announce(p)) + goto failure; + + return 0; + +failure: + bin_mod_free(m); + return -1; +} + +static int init_mod(struct bin_proc *const p) +{ + struct caio *caio = NULL; + char *const pathdup = strdup(p->path); + struct exec *const e = malloc(sizeof *e); + struct bin_mod *const m = malloc(sizeof *m); + const struct caio_open op = + { + .flags = O_RDONLY, + .path = p->path, + .gid = p->gid, + .uid = p->uid + }; + + const struct aio_done d = + { + .f = mod_opened, + .args = e, + }; + + if (!pathdup || !e || !m || !(caio = caio_open(&op, &d))) + goto failure; + + *m = (const struct bin_mod) + { + .path = pathdup, + .caio = caio + }; + + *e = (const struct exec) + { + .m = m, + .p = p + }; + + p->mod = m; + return 0; + +failure: + caio_close(caio); + free(pathdup); + free(m); + free(e); + return -1; +} + +static int header_read(struct bin_proc *const p) +{ + static const char shebang[] = "#! ", wasm[] = {'\0', 'a', 's', 'm'}; + const char *const h = p->header; + + if (!strncmp(h, shebang, strlen(shebang))) + { + /* TODO: interpret shebang */ + } + else if (!memcmp(h, wasm, sizeof wasm)) + { + if (init_mod(p)) + goto failure; + } + else + { + kprintf("Invalid file signature: {%hhx, %hhx, %hhx, %hhx}\n", + h[0], h[1], h[2], h[3]); + goto failure; + } + + if (caio_seek(p->caio, 0)) + goto failure; + + return 0; + +failure: + bin_proc_free(p); + return -1; +} + +static int read_header(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + + if (state) + goto failure; + + const size_t rem = sizeof p->header - p->i; + const struct aio_done d = {.f = read_header, .args = p}; + const int n = caio_read(p->caio, p->header + p->i, rem, &d); + + if (n < 0) + goto failure; + else if ((p->i += n) >= sizeof p->header) + return header_read(p); + + return 0; + +failure: + bin_proc_free(p); + return -1; +} + +static int opened(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + + if (state) + goto failure; + else if ((p->mod = bin_mod(p->path))) + return bin_proc_init(p); + + p->i = 0; + return read_header(STATE_OK, p); + +failure: + bin_proc_free(p); + return -1; +} + +static int serial_opened(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + struct bin_dbg *const dbg = &p->dbg; + struct caio *caio = NULL; + const struct aio_done d = + { + .f = opened, + .args = p + }; + + const struct caio_open op = + { + .flags = O_RDONLY, + .path = p->path, + .uid = p->uid, + .gid = p->gid + }; + + if (loop_rm_aio(dbg->aio)) + goto failure; + + aio_free(dbg->aio); + dbg->aio = NULL; + + if (state + || !(caio = caio_open(&op, &d)) + || caio_set_caches(caio, 3)) + goto failure; + + p->caio = caio; + return 0; + +failure: + caio_close(caio); + bin_proc_free(p); + return -1; +} + +static int copy_args(struct bin_proc *const p, const char *const path, + const char *const *const argv) +{ + int nargs = 2; + const char *const *parg = argv; + char **args = NULL; + + while (*parg++) + nargs++; + + if (!(args = malloc(nargs * sizeof *args))) + goto failure; + + for (int i = 0; i < nargs; i++) + args[i] = NULL; + + if (!(*args = strdup(path))) + goto failure; + + for (int i = 1; i < nargs - 1; i++) + if (!(args[i] = strdup(*(argv - 1)))) + goto failure; + + p->argc = nargs - 1; + p->argv = args; + return 0; + +failure: + + if (args) + for (int i = 0; i < nargs; i++) + free(args[i]); + + free(args); + return -1; +} + +int bin_exec(const char *const path, const char *const *const argv, + const uid_t uid, const gid_t gid) +{ + const pid_t pid = bin_pid(); + char *pathdup = NULL; + struct aio *serial = NULL; + struct bin_proc *const p = malloc(sizeof *p); + + if (!p) + goto failure; + + struct bin_dbg *const dbg = &p->dbg; + + const struct aio_done d = + { + .f = serial_opened, + .args = p + }; + + const struct fs_open op = + { + .path = "/dev/ttyS0", + .flags = O_RDWR, + .fd = &dbg->fd, + .uid = uid, + .gid = gid + }; + + if (!(pathdup = strdup(path)) + || !(serial = aio_open(&op, &d))) + goto failure; + + *p = (const struct bin_proc) + { + .path = pathdup, + .dbg.aio = serial, + .pid = pid, + .uid = uid, + .gid = gid + }; + + if (copy_args(p, path, argv) + || loop_add_aio(serial)) + goto failure; + + return 0; + +failure: + aio_free(serial); + free(pathdup); + free(p); + return -1; +} diff --git a/src/bin/src/globals.c b/src/bin/src/globals.c new file mode 100644 index 0000000..ffab850 --- /dev/null +++ b/src/bin/src/globals.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/types.h> + +struct bin bin_active, bin_pending, bin_locked, bin_zombie; diff --git a/src/bin/src/load.c b/src/bin/src/load.c new file mode 100644 index 0000000..4a2ab95 --- /dev/null +++ b/src/bin/src/load.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <stddef.h> + +int bin_load(struct bin_mod *const m) +{ + return bin_mod_move(m, NULL, &bin_pending); +} diff --git a/src/bin/src/loaded.c b/src/bin/src/loaded.c new file mode 100644 index 0000000..931807b --- /dev/null +++ b/src/bin/src/loaded.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <stddef.h> +#include <string.h> + +const struct bin_mod *bin_mod(const char *const path) +{ + for (const struct bin_mod *m = bin_active.mod_head; m; m = m->next) + if (!strcmp(m->path, path)) + return m; + + return NULL; +} diff --git a/src/bin/src/mod/CMakeLists.txt b/src/bin/src/mod/CMakeLists.txt new file mode 100644 index 0000000..0976111 --- /dev/null +++ b/src/bin/src/mod/CMakeLists.txt @@ -0,0 +1,29 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + cfg.c + eof.c + free.c + lock.c + move.c + pc.c + read.c + seek.c + tell.c + unload.c + unlock.c +) diff --git a/src/bin/src/mod/cfg.c b/src/bin/src/mod/cfg.c new file mode 100644 index 0000000..8c78a32 --- /dev/null +++ b/src/bin/src/mod/cfg.c @@ -0,0 +1,106 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +static const struct nw_import imports[BIN_IMPORTS] = +{ + { + .kind = NW_KIND_FUNCTION, + .module = "wnix", + .field = "exit", + .u.function = + { + .fn = bin_wnix_exit, + .signature = "(i)" + } + }, + + { + .kind = NW_KIND_FUNCTION, + .module = "wnix", + .field = "argc", + .u.function = + { + .fn = bin_wnix_argc, + .signature = "i()" + } + }, + + { + .kind = NW_KIND_FUNCTION, + .module = "wnix", + .field = "arglen", + .u.function = + { + .fn = bin_wnix_arglen, + .signature = "i(i)" + } + }, + + { + .kind = NW_KIND_FUNCTION, + .module = "wnix", + .field = "argcopy", + .u.function = + { + .fn = bin_wnix_argcopy, + .signature = "i(iii)" + } + }, + + { + .kind = NW_KIND_FUNCTION, + .module = "wnix", + .field = "mkdir", + .u.function = + { + .fn = bin_wnix_mkdir, + .signature = "i(iii)" + } + }, + + { + .kind = NW_KIND_FUNCTION, + .module = "wnix", + .field = "mount", + .u.function = + { + .fn = bin_wnix_mount, + .signature = "i(iiiiii)" + } + } +}; + +const struct nw_mod_cfg bin_mod_cfg = +{ + .imports = imports, + .n_imports = sizeof imports / sizeof *imports, + .io = + { + .read = bin_mod_read, + .eof = bin_mod_eof, + .pc = bin_mod_pc, + .seek = bin_mod_seek, + .tell = bin_mod_tell, + } +}; diff --git a/src/bin/src/mod/eof.c b/src/bin/src/mod/eof.c new file mode 100644 index 0000000..291d400 --- /dev/null +++ b/src/bin/src/mod/eof.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> + +int bin_mod_eof(void *const user) +{ + const struct bin_mod *const m = user; + + return caio_eof(m->caio); +} diff --git a/src/bin/src/mod/free.c b/src/bin/src/mod/free.c new file mode 100644 index 0000000..8b790bb --- /dev/null +++ b/src/bin/src/mod/free.c @@ -0,0 +1,33 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <caio.h> +#include <stdlib.h> + +void bin_mod_free(struct bin_mod *const p) +{ + if (!p) + return; + + caio_close(p->caio); + free(p->path); + free(p); +} diff --git a/src/bin/src/mod/lock.c b/src/bin/src/mod/lock.c new file mode 100644 index 0000000..89ab732 --- /dev/null +++ b/src/bin/src/mod/lock.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> + +int bin_mod_lock(struct bin_mod *const m) +{ + return bin_mod_move(m, &bin_pending, &bin_locked); +} diff --git a/src/bin/src/mod/move.c b/src/bin/src/mod/move.c new file mode 100644 index 0000000..84c6cb4 --- /dev/null +++ b/src/bin/src/mod/move.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <stddef.h> + +int bin_mod_move(struct bin_mod *const m, struct bin *const from, + struct bin *const to) +{ + if (from) + { + if (from->mod_head == m) + from->mod_head = m->next; + + if (from->mod_tail == m) + from->mod_tail = m->prev; + } + + if (m->next) + m->next->prev = m->prev; + + if (m->prev) + m->prev->next = m->next; + + if (to) + { + if (!to->mod_head) + { + to->mod_head = m; + m->prev = m->next = NULL; + } + else + { + struct bin_mod *const t = to->mod_tail; + + t->next = m; + m->prev = t; + m->next = NULL; + } + + to->mod_tail = m; + } + + return 0; +} diff --git a/src/bin/src/mod/pc.c b/src/bin/src/mod/pc.c new file mode 100644 index 0000000..bb9f84e --- /dev/null +++ b/src/bin/src/mod/pc.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_mod_pc(const long offset, struct nw_next *const next, + void *const user) +{ + /* TODO: will this be ever used? */ + return NW_OK; +} diff --git a/src/bin/src/mod/read.c b/src/bin/src/mod/read.c new file mode 100644 index 0000000..7e0919f --- /dev/null +++ b/src/bin/src/mod/read.c @@ -0,0 +1,53 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <caio.h> +#include <stdbool.h> +#include <stddef.h> + +static int done(const enum state state, void *const args) +{ + struct bin_mod *const m = args; + + if (state) + return -1; + + return bin_mod_unlock(m); +} + +int bin_mod_read(void *const buf, const size_t n, void *const user) +{ + struct bin_mod *const m = user; + const struct aio_done d = + { + .f = done, + .args = m + }; + + const int r = caio_read(m->caio, buf, n, &d); + + if (r < 0) + return -1; + else if (!r && !caio_eof(m->caio)) + return bin_mod_lock(m); + + return r; +} diff --git a/src/bin/src/mod/seek.c b/src/bin/src/mod/seek.c new file mode 100644 index 0000000..6d51049 --- /dev/null +++ b/src/bin/src/mod/seek.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_mod_seek(const long offset, void *const user) +{ + struct bin_mod *const m = user; + + return caio_seek(m->caio, offset) ? NW_FATAL : NW_OK; +} diff --git a/src/bin/src/mod/tell.c b/src/bin/src/mod/tell.c new file mode 100644 index 0000000..c027c8c --- /dev/null +++ b/src/bin/src/mod/tell.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_mod_tell(long *const offset, void *const user) +{ + const struct bin_mod *const m = user; + off_t off; + + if (caio_tell(m->caio, &off)) + return NW_FATAL; + + *offset = off; + return NW_OK; +} diff --git a/src/bin/src/mod/unload.c b/src/bin/src/mod/unload.c new file mode 100644 index 0000000..3f0b80b --- /dev/null +++ b/src/bin/src/mod/unload.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/routines.h> +#include <bin/types.h> + +int bin_unload(struct bin_mod *const m) +{ + struct bin *const b = &bin_pending; + + if (b->mod_head == m) + b->mod_head = m->next; + + if (b->mod_tail == m) + b->mod_tail = m->prev; + + if (m->next) + m->next->prev = m->prev; + + if (m->prev) + m->prev->next = m->next; + + return 0; +} diff --git a/src/bin/src/mod/unlock.c b/src/bin/src/mod/unlock.c new file mode 100644 index 0000000..61a3002 --- /dev/null +++ b/src/bin/src/mod/unlock.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/types.h> +#include <stddef.h> + +int bin_mod_unlock(struct bin_mod *const m) +{ + return bin_mod_move(m, &bin_locked, &bin_pending); +} diff --git a/src/bin/src/pid.c b/src/bin/src/pid.c new file mode 100644 index 0000000..bbbca78 --- /dev/null +++ b/src/bin/src/pid.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/types.h> +#include <bin/routines.h> +#include <sys/types.h> + +pid_t bin_pid(void) +{ + static pid_t pid; + + return ++pid; +} diff --git a/src/bin/src/proc/CMakeLists.txt b/src/bin/src/proc/CMakeLists.txt new file mode 100644 index 0000000..47df502 --- /dev/null +++ b/src/bin/src/proc/CMakeLists.txt @@ -0,0 +1,33 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + cfg.c + eof.c + free.c + init.c + lock.c + move.c + pc.c + read.c + seek.c + tell.c + unlock.c +) + +add_subdirectory(global) +add_subdirectory(linear) +add_subdirectory(stack) diff --git a/src/bin/src/proc/cfg.c b/src/bin/src/proc/cfg.c new file mode 100644 index 0000000..efe6333 --- /dev/null +++ b/src/bin/src/proc/cfg.c @@ -0,0 +1,59 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +const struct nw_inst_cfg bin_proc_cfg = +{ + .entry = "_start", + .interp_cfg = + { + .io = + { + .read = bin_proc_read, + .eof = bin_proc_eof, + .seek = bin_proc_seek, + .tell = bin_proc_tell, + .pc = bin_proc_pc + }, + + .global = + { + .load = bin_proc_g_load, + .store = bin_proc_g_store + }, + + .linear = + { + .load = bin_proc_l_load, + .store = bin_proc_l_store + }, + + .stack = + { + .push = bin_proc_s_push, + .pop = bin_proc_s_pop, + .read = bin_proc_s_read, + .write = bin_proc_s_write, + .ptr = bin_proc_s_ptr + } + } +}; diff --git a/src/bin/src/proc/eof.c b/src/bin/src/proc/eof.c new file mode 100644 index 0000000..c1d75e5 --- /dev/null +++ b/src/bin/src/proc/eof.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> + +int bin_proc_eof(void *const user) +{ + const struct bin_proc *const p = user; + + return caio_eof(p->caio); +} diff --git a/src/bin/src/proc/free.c b/src/bin/src/proc/free.c new file mode 100644 index 0000000..a5bdea1 --- /dev/null +++ b/src/bin/src/proc/free.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <aio.h> +#include <caio.h> +#include <stdlib.h> + +void bin_proc_free(struct bin_proc *const p) +{ + if (!p) + return; + + struct bin_dbg *const d = &p->dbg; + + dynstr_free(&d->dstr); + free(d->bkpt); + aio_free(d->aio); + caio_close(p->caio); + free(p->global.buf); + free(p->path); + free(p); +} diff --git a/src/bin/src/proc/global/CMakeLists.txt b/src/bin/src/proc/global/CMakeLists.txt new file mode 100644 index 0000000..bd445a4 --- /dev/null +++ b/src/bin/src/proc/global/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + load.c + store.c +) diff --git a/src/bin/src/proc/global/load.c b/src/bin/src/proc/global/load.c new file mode 100644 index 0000000..172ab14 --- /dev/null +++ b/src/bin/src/proc/global/load.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <kprintf.h> +#include <stddef.h> +#include <string.h> + +int bin_proc_g_load(const unsigned long pos, void *const dst, const size_t n, + void *const user) +{ + struct bin_proc *const p = user; + struct bin_global *const g = &p->global; + + if (n > g->sz || pos > g->sz - n) + { + kprintf("%s: out-of-bounds access to global memory\n", p->path); + return -1; + } + + memcpy(dst, (const char *)g->buf + pos, n); + return n; +} diff --git a/src/bin/src/proc/global/store.c b/src/bin/src/proc/global/store.c new file mode 100644 index 0000000..da7657e --- /dev/null +++ b/src/bin/src/proc/global/store.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <kprintf.h> +#include <stddef.h> +#include <string.h> + +int bin_proc_g_store(const unsigned long pos, const void *const src, + const size_t n, void *const user) +{ + struct bin_proc *const p = user; + struct bin_global *const g = &p->global; + + if (n > g->sz || pos > g->sz - n) + { + kprintf("%s: out-of-bounds access to global memory\n", p->path); + return -1; + } + + memcpy((char *)g->buf + pos, src, n); + return n; +} diff --git a/src/bin/src/proc/init.c b/src/bin/src/proc/init.c new file mode 100644 index 0000000..9a39c73 --- /dev/null +++ b/src/bin/src/proc/init.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +int bin_proc_init(struct bin_proc *const p) +{ + struct nw_inst_cfg icfg = bin_proc_cfg; + struct nw_interp_cfg *const i = &icfg.interp_cfg; + + i->user = i->io.user = p; + i->m = &p->mod->mod; + i->args = p->args; + i->n_args = sizeof p->args / sizeof *p->args; + + if (nw_start(&p->instance, &icfg)) + return -1; + + return bin_proc_move(p, NULL, &bin_pending); +} diff --git a/src/bin/src/proc/linear/CMakeLists.txt b/src/bin/src/proc/linear/CMakeLists.txt new file mode 100644 index 0000000..bd445a4 --- /dev/null +++ b/src/bin/src/proc/linear/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + load.c + store.c +) diff --git a/src/bin/src/proc/linear/load.c b/src/bin/src/proc/linear/load.c new file mode 100644 index 0000000..5881c69 --- /dev/null +++ b/src/bin/src/proc/linear/load.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <page.h> +#include <stddef.h> + +int bin_proc_l_load(const unsigned long pos, void *const dst, const size_t n, + void *const user) +{ + /* TODO: make nanowasm check linear memory accesses. */ + struct bin_proc *const p = user; + const int w = page_read(&p->linear, pos, dst, n); + + if (w < 0) + return -1; +#if 0 + else if (!w) + /* TODO: how to unlock? */ + return bin_proc_lock(p); +#endif + + return w; +} diff --git a/src/bin/src/proc/linear/store.c b/src/bin/src/proc/linear/store.c new file mode 100644 index 0000000..22f9891 --- /dev/null +++ b/src/bin/src/proc/linear/store.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <page.h> +#include <stddef.h> + +int bin_proc_l_store(const unsigned long pos, const void *const src, + const size_t n, void *const user) +{ + /* TODO: make nanowasm check linear memory accesses. */ + struct bin_proc *const p = user; + const int w = page_write(&p->linear, pos, src, n); + + if (w < 0) + return -1; +#if 0 + else if (!w) + /* TODO: how to unlock? */ + return bin_proc_lock(p); +#endif + + return w; +} diff --git a/src/bin/src/proc/lock.c b/src/bin/src/proc/lock.c new file mode 100644 index 0000000..479e902 --- /dev/null +++ b/src/bin/src/proc/lock.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <stddef.h> + +int bin_proc_lock(struct bin_proc *const p) +{ + return bin_proc_move(p, &bin_active, &bin_locked); +} diff --git a/src/bin/src/proc/move.c b/src/bin/src/proc/move.c new file mode 100644 index 0000000..7192457 --- /dev/null +++ b/src/bin/src/proc/move.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <stddef.h> + +int bin_proc_move(struct bin_proc *const p, struct bin *const from, + struct bin *const to) +{ + if (from) + { + if (from->proc_head == p) + from->proc_head = p->next; + + if (from->proc_tail == p) + from->proc_tail = p->prev; + } + + if (p->next) + p->next->prev = p->prev; + + if (p->prev) + p->prev->next = p->next; + + if (to) + { + if (!to->proc_head) + { + to->proc_head = p; + p->prev = p->next = NULL; + } + else + { + struct bin_proc *const t = to->proc_tail; + + t->next = p; + p->prev = t; + p->next = NULL; + } + + to->proc_tail = p; + } + + return 0; +} diff --git a/src/bin/src/proc/pc.c b/src/bin/src/proc/pc.c new file mode 100644 index 0000000..746e418 --- /dev/null +++ b/src/bin/src/proc/pc.c @@ -0,0 +1,666 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <aio.h> +#include <kprintf.h> +#include <loop.h> +#include <state.h> +#include <dynstr.h> +#include <nanowasm/nw.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +static enum nw_state check_start(void *, struct nw_next *); +static int read_string(struct bin_proc *, struct nw_next *); + +static int read_done(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + struct bin_dbg *const d = &p->dbg; + + if (loop_rm_aio(d->aio) || bin_proc_unlock(p)) + return -1; + + aio_free(d->aio); + d->aio = NULL; + return 0; +} + +static int read_byte(struct bin_proc *const p) +{ + struct bin_dbg *const d = &p->dbg; + + const struct fs_read r = + { + .fd = &d->fd, + .buf = &d->b, + .n = sizeof d->b + }; + + const struct aio_done done = + { + .f = read_done, + .args = p + }; + + struct aio *const aio = aio_read(&r, &done); + + if (!aio + || loop_add_aio(aio) + || bin_proc_lock(p)) + goto failure; + + d->aio = aio; + return 0; + +failure: + aio_free(aio); + return -1; +} + +static const char *token(const char *s, size_t *const n, + const char **const next) +{ + const char *const sep = strchr(s, ':'); + + if (sep) + { + *n = sep - s; + *next = sep + 1; + } + else + { + *n = sep ? sep - s : strlen(s); + *next = NULL; + } + + return s; +} + +static int parse_num(const char *const s, unsigned long *const out) +{ + char *end; + unsigned long v; + + errno = 0; + v = strtoul(s, &end, 0); + + if (errno || *end) + return -1; + + *out = v; + return 0; +} + +static int replied(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + struct bin_dbg *const d = &p->dbg; + + if (loop_rm_aio(d->aio) || bin_proc_unlock(p)) + return -1; + + aio_free(d->aio); + d->aio = NULL; + return 0; +} + +static enum nw_state finished(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct bin_dbg *const d = &p->dbg; + + dynstr_free(&d->dstr); + + if (d->running) + return NW_OK; + + *next = (const struct nw_next){.fn = check_start, .user = p}; + return NW_AGAIN; +} + +static enum nw_state reply(struct bin_proc *const p, struct nw_next *const next, + const char *const s) +{ + struct aio *aio = NULL; + struct bin_dbg *const d = &p->dbg; + const struct fs_write w = + { + .fd = &d->fd, + .buf = s, + .n = strlen(s) + }; + + const struct aio_done done = + { + .f = replied, + .args = p + }; + + if (!(aio = aio_write(&w, &done)) + || loop_add_aio(aio) + || bin_proc_lock(p)) + goto failure; + + d->aio = aio; + *next = (const struct nw_next){.fn = finished, .user = p}; + return NW_AGAIN; + +failure: + aio_free(aio); + return NW_FATAL; +} + +static int append_value(struct dynstr *const d, + const struct nw_dbg_value *const v) +{ + /* TODO: is %f valid for both float and double? */ + static const char *const fmt[] = + { + [NW_TYPE_I32] = "%lu", + [NW_TYPE_I64] = "%llu", + [NW_TYPE_F32] = "%f", + [NW_TYPE_F64] = "%f" + }; + + return dynstr_append(d, fmt[v->type], v->value); +} + +#include <drv/ps1/bios.h> +static enum nw_state write_value(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct bin_dbg *const db = &p->dbg; + struct dynstr *const d = &db->dstr; + struct nw_dbg_value v; + + dynstr_init(d); + + if (nw_dbg_value(&db->dbg, &v) + || dynstr_append(d, ";ok:") + || append_value(d, &v) + || dynstr_append(d, "\n")) + return NW_FATAL; + + Printf(">> %s", d->str); + return reply(user, next, d->str); +} + +static enum nw_state trap(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct bin_dbg *const db = &p->dbg; + struct dynstr *const d = &db->dstr; + + dynstr_init(d); + + if (dynstr_append(d, ";trap:%#lx\n", db->offset)) + return NW_FATAL; + + return reply(user, next, d->str); +} + +static enum nw_state ok(void *const user, struct nw_next *const next) +{ + return reply(user, next, ";ok\n"); +} + +static enum nw_state nok(void *const user, struct nw_next *const next) +{ + return reply(user, next, ";nok\n"); +} + +static int add_bkpt(struct bin_dbg *const d, const long addr) +{ + const size_t n = d->n_bkpt + 1; + long *const b = realloc(d->bkpt, n * sizeof *d->bkpt); + + if (!b) + return -1; + + b[d->n_bkpt] = addr; + d->bkpt = b; + d->n_bkpt = n; + return 0; +} + +static int cmd_b(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + size_t tklen; + unsigned long addr; + struct bin_dbg *const d = &p->dbg; + const size_t n = d->n_bkpt; + const char *ntok, *const tk = token(s, &tklen, &ntok); + + if (!tk || ntok) + { + kprintf("Syntax: b:<pc>\n"); + return 1; + } + else if (parse_num(tk, &addr) || addr > LONG_MAX) + { + kprintf("Invalid value: %s\n", tk); + return 1; + } + else if (add_bkpt(d, addr)) + return -1; + else + kprintf("Set breakpoint %zu at address %#lx\n", n, addr); + + *next = (const struct nw_next){.fn = ok, .user = p}; + return 0; +} + +static int cmd_bt(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + /* TODO */ + kprintf("%s: TODO\n", __func__); + return 1; +} + +static int cmd_c(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + struct bin_dbg *const d = &p->dbg; + + if (s) + { + kprintf("Syntax: c\n"); + return 1; + } + + d->running = true; + *next = (const struct nw_next){.fn = ok, .user = p}; + return 0; +} + +static int resize_bkpt(struct bin_dbg *const d, const unsigned long index) +{ + const size_t n = d->n_bkpt - 1; + long *const dst = &d->bkpt[index]; + + if (index < n) + memcpy(dst, dst + 1, (d->n_bkpt - index) * sizeof *dst); + + if (n) + { + long *const b = realloc(d->bkpt, n * sizeof *d->bkpt); + + if (!b) + return -1; + + d->bkpt = b; + } + else + { + free(d->bkpt); + d->bkpt = NULL; + } + + d->n_bkpt = n; + return 0; +} + +static void delete_bkpt(struct bin_dbg *const d) +{ + free(d->bkpt); + d->bkpt = NULL; + d->n_bkpt = 0; +} + +static int cmd_d(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + size_t tklen; + unsigned long index; + struct bin_dbg *const d = &p->dbg; + const char *ntok, *const tk = token(s, &tklen, &ntok); + + if (!tk) + { + if (d->n_bkpt) + { + delete_bkpt(d); + kprintf("Deleted all breakpoints\n"); + } + else + kprintf("No breakpoints to delete\n"); + } + else if (ntok) + { + kprintf("Syntax: d[:<b-index>]\n"); + return 1; + } + else if (parse_num(tk, &index) || index >= d->n_bkpt) + { + kprintf("Invalid breakpoint index: %s\n", tk); + return 1; + } + else if (resize_bkpt(d, index)) + return -1; + else + kprintf("Deleted breakpoint index %lu\n", index); + + *next = (const struct nw_next){.fn = ok, .user = p}; + return 0; +} + +static int cmd_g(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + size_t tklen; + unsigned long index; + struct bin_dbg *const d = &p->dbg; + const char *ntok, *const tk = token(s, &tklen, &ntok); + + if (!tk || ntok) + { + kprintf("Syntax: g:<index>\n"); + return 1; + } + else if (parse_num(tk, &index)) + { + kprintf("Invalid value: %s\n", tk); + return 1; + } + + nw_dbg_global(&d->dbg, index); + *next = (const struct nw_next){.fn = write_value, .user = p}; + return 0; + return 1; +} + +static int cmd_l(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + size_t tklen; + unsigned long index; + struct bin_dbg *const d = &p->dbg; + const char *ntok, *const tk = token(s, &tklen, &ntok); + + if (!tk || ntok) + { + kprintf("Syntax: l:<index>\n"); + return 1; + } + else if (parse_num(tk, &index)) + { + kprintf("Invalid value: %s\n", tk); + return 1; + } + + nw_dbg_local(&d->dbg, index); + *next = (const struct nw_next){.fn = write_value, .user = p}; + return 0; +} + +static int cmd_p(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + size_t tklen; + unsigned long index; + struct bin_dbg *const d = &p->dbg; + const char *ntok, *const tk = token(s, &tklen, &ntok); + + if (!tk || ntok) + { + kprintf("Syntax: p:<index>\n"); + return 1; + } + else if (parse_num(tk, &index)) + { + kprintf("Invalid value: %s\n", tk); + return 1; + } + + nw_dbg_param(&d->dbg, index); + *next = (const struct nw_next){.fn = write_value, .user = p}; + return 0; +} + +static int parse_type(const char *const s, enum nw_type *const out) +{ + switch (*s) + { + case 'i': + *out = NW_TYPE_I32; + break; + + case 'I': + *out = NW_TYPE_I64; + break; + + case 'f': + *out = NW_TYPE_F32; + break; + + case 'F': + *out = NW_TYPE_F64; + break; + + default: + return -1; + } + + return 0; +} + +static int cmd_m(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + size_t tklen; + struct bin_dbg *const d = &p->dbg; + static const char exc[] = "Syntax: m:<i|I|f|F>:<addr>\n"; + const char *ntok, *tk = token(s, &tklen, &ntok); + enum nw_type type; + unsigned long addr; + + if (!tk || tklen != 1 || !ntok) + { + kprintf(exc); + return 1; + } + else if (parse_type(tk, &type)) + { + kprintf("Invalid type specifier: %.*s\n", (int)tklen, tk); + return 1; + } + else if (!token(tk = ntok, &tklen, &ntok) || ntok) + { + kprintf(exc); + return 1; + } + else if (parse_num(tk, &addr)) + { + kprintf("Invalid address: %s\n", tk); + return 1; + } + + *next = (const struct nw_next){.fn = write_value, .user = p}; + nw_dbg_mem_load(&d->dbg, type, addr); + return 0; +} + +static int cmd_s(struct bin_proc *const p, const char *const s, + struct nw_next *const next) +{ + struct bin_dbg *const d = &p->dbg; + + if (s) + { + kprintf("Syntax: s\n"); + return 1; + } + + d->running = d->step = true; + *next = (const struct nw_next){.fn = ok, .user = p}; + return 0; +} + +static int parse_cmd(struct bin_proc *const p, const char *const tk, + const size_t tklen, const char *const ntk, struct nw_next *const next) +{ + static const struct cmd + { + const char *cmd; + int (*f)(struct bin_proc *, const char *, struct nw_next *); + } cmds[] = + { + {.cmd = "b", .f = cmd_b}, + {.cmd = "bt", .f = cmd_bt}, + {.cmd = "c", .f = cmd_c}, + {.cmd = "d", .f = cmd_d}, + {.cmd = "g", .f = cmd_g}, + {.cmd = "l", .f = cmd_l}, + {.cmd = "m", .f = cmd_m}, + {.cmd = "p", .f = cmd_p}, + {.cmd = "s", .f = cmd_s} + }; + + for (size_t i = 0; i < sizeof cmds / sizeof *cmds; i++) + { + const struct cmd *const c = &cmds[i]; + + if (!strncmp(c->cmd, tk, tklen)) + return c->f(p, ntk, next); + } + + kprintf("Unknown command %.*s\n", (int)tklen, tk); + return 1; +} + +static int parse(struct bin_proc *const p, struct nw_next *const next) +{ + struct bin_dbg *const dbg = &p->dbg; + struct dynstr *const d = &dbg->dstr; + const char *const s = d->str, *tk, *ntk; + size_t tklen; + + if (!s || !(tk = token(s, &tklen, &ntk)) || !tklen) + return 1; + + return parse_cmd(p, tk, tklen, ntk, next); +} + +static enum nw_state check_lf(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct bin_dbg *const dbg = &p->dbg; + struct dynstr *const d = &dbg->dstr; + const char b = dbg->b; + const size_t max = 128; + + Printf("%c", b); + + if (b == ';') + { + dynstr_free(d); + + if (read_string(p, next)) + return NW_FATAL; + } + else if (b == '\n') + { + const int n = parse(p, next); + + if (n < 0) + goto failure; + else if (n) + { + dynstr_free(d); + *next = (const struct nw_next){.fn = nok, .user = p}; + } + } + else if (d->len < max) + if (dynstr_append(d, "%c", b) || read_byte(p)) + goto failure; + + return NW_AGAIN; + +failure: + dynstr_free(d); + return NW_FATAL; +} + +static int read_string(struct bin_proc *const p, struct nw_next *const next) +{ + struct bin_dbg *const d = &p->dbg; + + dynstr_init(&d->dstr); + + if (read_byte(p)) + return -1; + + *next = (const struct nw_next){.fn = check_lf, .user = p}; + return 0; +} + +static enum nw_state check_start(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct bin_dbg *const d = &p->dbg; + + Printf("<< %c", d->b); + + if (d->b == ';') + { + if (read_string(p, next)) + return NW_FATAL; + } + else if (read_byte(p)) + return NW_FATAL; + else + Printf("(%#hhx)\n", d->b); + + return NW_AGAIN; +} + +enum nw_state bin_proc_pc(const long offset, struct nw_next *const next, + void *const user) +{ + struct bin_proc *const p = user; + struct bin_dbg *const d = &p->dbg; + + if (!d->running || d->step) + { + d->step = d->running = false; + d->offset = offset; + *next = (const struct nw_next){.fn = trap, .user = p}; + return NW_AGAIN; + } + else + for (size_t i = 0; i < d->n_bkpt; i++) + if (offset == d->bkpt[i]) + { + kprintf("Reached breakpoint %zu at offset %#lx\n", i, offset); + d->running = d->step = false; + d->offset = offset; + *next = (const struct nw_next){.fn = trap, .user = p}; + return NW_AGAIN; + } + + return NW_OK; +} diff --git a/src/bin/src/proc/read.c b/src/bin/src/proc/read.c new file mode 100644 index 0000000..f24a6ca --- /dev/null +++ b/src/bin/src/proc/read.c @@ -0,0 +1,51 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <stddef.h> + +static int done(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + + if (state) + return -1; + + return bin_proc_unlock(p); +} + +int bin_proc_read(void *const buf, const size_t n, void *const user) +{ + struct bin_proc *const p = user; + const struct aio_done d = + { + .f = done, + .args = p + }; + + const int r = caio_read(p->caio, buf, n, &d); + + if (r < 0) + return -1; + else if (!r && !caio_eof(p->caio)) + return bin_proc_lock(p); + + return r; +} diff --git a/src/bin/src/proc/seek.c b/src/bin/src/proc/seek.c new file mode 100644 index 0000000..24b1a2f --- /dev/null +++ b/src/bin/src/proc/seek.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_proc_seek(const long offset, void *const user) +{ + struct bin_proc *const p = user; + + return caio_seek(p->caio, offset) ? NW_FATAL : NW_OK; +} diff --git a/src/bin/src/proc/stack/CMakeLists.txt b/src/bin/src/proc/stack/CMakeLists.txt new file mode 100644 index 0000000..3e50879 --- /dev/null +++ b/src/bin/src/proc/stack/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + pop.c + ptr.c + push.c + read.c + write.c +) diff --git a/src/bin/src/proc/stack/pop.c b/src/bin/src/proc/stack/pop.c new file mode 100644 index 0000000..d6ec9e4 --- /dev/null +++ b/src/bin/src/proc/stack/pop.c @@ -0,0 +1,64 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <page.h> +#include <kprintf.h> +#include <stddef.h> + +int bin_proc_s_pop(void *const dst, size_t n, void *const user) +{ + struct bin_proc *const p = user; + struct bin_stack *const s = &p->stack; + unsigned long addr; + + if (!s->page || n > s->sz) + { + kprintf("%s: stack underflow\n", p->path); + return -1; + } + else if (s->pi) + { + const size_t rem = s->n - s->pi; + + if (n > rem) + n = rem; + + addr = s->sz - rem; + } + else + addr = s->sz - n; + + const int r = page_read(&s->page, addr, dst, n); + + if (r < 0) + return -1; + else if (r != n) + { + s->pi += r; + s->n = n; + return r; + } + else if (page_shrink(&s->page, addr)) + return -1; + + s->sz -= s->n ? s->n : n; + s->n = s->pi = 0; + return r; +} diff --git a/src/bin/src/proc/stack/ptr.c b/src/bin/src/proc/stack/ptr.c new file mode 100644 index 0000000..b0a8763 --- /dev/null +++ b/src/bin/src/proc/stack/ptr.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <stddef.h> + +size_t bin_proc_s_ptr(void *const user) +{ + const struct bin_proc *const p = user; + + return p->stack.sz; +} diff --git a/src/bin/src/proc/stack/push.c b/src/bin/src/proc/stack/push.c new file mode 100644 index 0000000..bc68180 --- /dev/null +++ b/src/bin/src/proc/stack/push.c @@ -0,0 +1,49 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <page.h> +#include <kprintf.h> +#include <stddef.h> + +int bin_proc_s_push(const void *const src, const size_t n, void *const user) +{ + struct bin_proc *const p = user; + struct bin_stack *const s = &p->stack; + const size_t max = 8192; + + if (n > max || s->sz > max - n) + { + kprintf("%s: stack overflow\n", p->path); + return -1; + } + + const int w = page_write(&s->page, s->sz, src, n); + + if (w < 0) + return -1; +#if 0 + else if (!w) + /* TODO: how to unlock? */ + return bin_proc_lock(p); +#endif + + s->sz += w; + return w; +} diff --git a/src/bin/src/proc/stack/read.c b/src/bin/src/proc/stack/read.c new file mode 100644 index 0000000..5f4a7ac --- /dev/null +++ b/src/bin/src/proc/stack/read.c @@ -0,0 +1,48 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <kprintf.h> +#include <page.h> +#include <stddef.h> + +int bin_proc_s_read(const size_t offset, void *const dst, const size_t n, + void *const user) +{ + struct bin_proc *const p = user; + struct bin_stack *const s = &p->stack; + + if (n > s->sz || offset > s->sz - n) + { + kprintf("%s: out-of-bounds stack access\n", p->path); + return -1; + } + + const int w = page_read(&s->page, offset, dst, n); + + if (w < 0) + return -1; +#if 0 + else if (!w) + /* TODO: how to unlock? */ + return bin_proc_lock(p); +#endif + + return w; +} diff --git a/src/bin/src/proc/stack/write.c b/src/bin/src/proc/stack/write.c new file mode 100644 index 0000000..0df017a --- /dev/null +++ b/src/bin/src/proc/stack/write.c @@ -0,0 +1,48 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin/proc.h> +#include <bin/types.h> +#include <kprintf.h> +#include <page.h> +#include <stddef.h> + +int bin_proc_s_write(const size_t offset, const void *const dst, + const size_t n, void *const user) +{ + struct bin_proc *const p = user; + struct bin_stack *const s = &p->stack; + + if (n > s->sz || offset > s->sz - n) + { + kprintf("%s: out-of-bounds stack access\n", p->path); + return -1; + } + + const int w = page_write(&s->page, offset, dst, n); + + if (w < 0) + return -1; +#if 0 + else if (!w) + /* TODO: how to unlock? */ + return bin_proc_lock(p); +#endif + + return w; +} diff --git a/src/bin/src/proc/tell.c b/src/bin/src/proc/tell.c new file mode 100644 index 0000000..ed12896 --- /dev/null +++ b/src/bin/src/proc/tell.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_proc_tell(long *const offset, void *const user) +{ + const struct bin_proc *const p = user; + off_t off; + + if (caio_tell(p->caio, &off)) + return NW_FATAL; + + *offset = off; + return NW_OK; +} diff --git a/src/bin/src/proc/unlock.c b/src/bin/src/proc/unlock.c new file mode 100644 index 0000000..101b093 --- /dev/null +++ b/src/bin/src/proc/unlock.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <stddef.h> + +int bin_proc_unlock(struct bin_proc *const p) +{ + return bin_proc_move(p, &bin_locked, &bin_active); +} diff --git a/src/bin/src/start.c b/src/bin/src/start.c new file mode 100644 index 0000000..dc98e7f --- /dev/null +++ b/src/bin/src/start.c @@ -0,0 +1,127 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <stdlib.h> + +static void add_proc(struct bin_proc *const pr) +{ + struct bin *const p = &bin_pending, *const a = &bin_active; + + if (p->proc_head == pr) + p->proc_head = pr->next; + + if (p->proc_tail == pr) + p->proc_tail = pr->prev; + + if (pr->next) + pr->next->prev = pr->prev; + + if (pr->prev) + pr->prev->next = pr->next; + + if (!a->proc_head) + a->proc_head = pr; + else + { + struct bin_proc *const t = a->proc_tail; + + t->next = pr; + pr->prev = t; + pr->next = NULL; + } + + a->proc_tail = pr; +} + +static void move_mod(struct bin_mod *const m) +{ + struct bin *const p = &bin_pending, *const a = &bin_active; + + if (p->mod_head == m) + p->mod_head = m->next; + + if (p->mod_tail == m) + p->mod_tail = m->prev; + + if (m->next) + m->next->prev = m->prev; + + if (m->prev) + m->prev->next = m->next; + + if (!a->mod_head) + a->mod_head = m; + else + { + struct bin_mod *const t = a->mod_tail; + + t->next = m; + m->prev = t; + m->next = NULL; + } + + a->mod_tail = m; +} + +static int setup_mems(struct bin_proc *const p) +{ + const struct nw_mod_out *const mout = &p->mod->mod_out; + const size_t n = mout->global; + void *const gl = malloc(n); + + if (!gl) + return -1; + + p->global = (const struct bin_global) + { + .buf = gl, + .sz = n + }; + + return 0; +} + +int bin_start(struct bin_mod *const m) +{ + int ret = -1; + struct bin *const b = &bin_pending; + + for (struct bin_proc *p = b->proc_head; p;) + { + struct bin_proc *const next = p->next; + + if (p->mod == m) + { + if (setup_mems(p)) + return -1; + + add_proc(p); + ret = 0; + } + + p = next; + } + + if (!ret) + move_mod(m); + + return ret; +} diff --git a/src/bin/src/stop.c b/src/bin/src/stop.c new file mode 100644 index 0000000..978da81 --- /dev/null +++ b/src/bin/src/stop.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/proc.h> +#include <bin/routines.h> +#include <bin/types.h> + +int bin_stop(struct bin_proc *const p) +{ + return bin_proc_move(p, &bin_active, &bin_zombie); +} diff --git a/src/bin/src/update.c b/src/bin/src/update.c new file mode 100644 index 0000000..3f03ae7 --- /dev/null +++ b/src/bin/src/update.c @@ -0,0 +1,145 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/mod.h> +#include <bin/proc.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <kprintf.h> +#include <nanowasm/nw.h> +#include <stdbool.h> + +static int load(void) +{ + struct bin *const b = &bin_pending; + + for (struct bin_mod *m = b->mod_head; m;) + { + struct bin_mod *const next = m->next; + + switch (nw_load(&m->mod, &m->mod_out)) + { + case STATE_AGAIN: + break; + + case STATE_FATAL: + /* TODO: call nw_loadexc. */ + kprintf("Module %s failed to load\n", m->path); + + if (bin_unload(m)) + kprintf("Failed to unload module %s\n", m->path); + + bin_mod_free(m); + break; + + case STATE_OK: + kprintf("Module %s loaded successfully\n", m->path); + + if (bin_start(m)) + return -1; + + break; + } + + m = next; + } + + return 0; +} + +static int run(void) +{ + for (struct bin_proc *p = bin_active.proc_head; p;) + { + struct bin_proc *const next = p->next; + struct nw_inst *const i = &p->instance; + + switch (nw_run(i)) + { + case STATE_AGAIN: + break; + + case STATE_FATAL: + kprintf("Instance %s failed to run: %s\n", p->path, nw_rexc(i)); + + if (bin_stop(p)) + kprintf("Failed to stop instance %s\n", p->path); + + break; + + case STATE_OK: + /* TODO: remove from queue. */ + break; + } + + p = next; + } + + return 0; +} + +static int prune(const struct bin_mod *const mod) +{ + for (struct bin_mod *m = bin_active.mod_head; m;) + { + struct bin_mod *const next = m->next; + + if (m == mod) + { + if (bin_mod_move(m, &bin_active, NULL)) + return -1; + + bin_mod_free(m); + break; + } + + m = next; + } + + return 0; +} + +static int kill(void) +{ + for (struct bin_proc *p = bin_zombie.proc_head; p;) + { + struct bin_proc *const next = p->next; + const struct bin_mod *const mod = p->mod; + bool used = false; + + kprintf("%s exited with status %ld\n", p->path, p->retval); + + if (bin_proc_move(p, &bin_zombie, NULL)) + return -1; + + bin_proc_free(p); + + if (!used && prune(mod)) + return -1; + + p = next; + } + + return 0; +} + +int bin_update(void) +{ + return load() || run() || kill(); +} diff --git a/src/bin/src/wnix/CMakeLists.txt b/src/bin/src/wnix/CMakeLists.txt new file mode 100644 index 0000000..b4868f2 --- /dev/null +++ b/src/bin/src/wnix/CMakeLists.txt @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(bin PRIVATE + argc.c + argcopy.c + arglen.c + exit.c + mkdir.c + mount.c + set_errno.c +) diff --git a/src/bin/src/wnix/argc.c b/src/bin/src/wnix/argc.c new file mode 100644 index 0000000..f6d4217 --- /dev/null +++ b/src/bin/src/wnix/argc.c @@ -0,0 +1,33 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_wnix_argc(const union nw_value *const params, + union nw_value *const ret, void *const user, + struct nw_next *const next) +{ + const struct bin_proc *const p = user; + + ret->i32 = p->argc; + return NW_OK; +} diff --git a/src/bin/src/wnix/argcopy.c b/src/bin/src/wnix/argcopy.c new file mode 100644 index 0000000..cedb26e --- /dev/null +++ b/src/bin/src/wnix/argcopy.c @@ -0,0 +1,143 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/wnix/routines.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <endian.h> +#include <nanowasm/nw.h> +#include <nanowasm/linear.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +struct argcopy +{ + long arg; + unsigned long addr, errno_addr; + union nw_value *ret; + size_t read; +}; + +static void free_argcopy(struct argcopy *const c) +{ + if (!c) + return; + + free(c); +} + +static enum nw_state errno_set(void *const user, + struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct argcopy *const c = p->import; + + c->ret->i32 = -1; + free_argcopy(c); + return NW_OK; +} + +static int set_errno(struct bin_proc *const p, const int error, + struct nw_next *const next) +{ + struct argcopy *const c = p->import; + + *next = (const struct nw_next) + { + .fn = errno_set, + .user = p + }; + + return bin_wnix_set_errno(p, error, c->errno_addr, next); +} + +static enum nw_state read_arg(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct argcopy *const c = p->import; + const char *const arg = p->argv[c->arg]; + const unsigned long addr = c->addr + c->read; + char b = arg[c->read]; + struct nw_sm_io io = {.buf = &b, .n = sizeof b}; + const enum nw_state n = nw_linear_store(&p->instance, &io, addr); + + if (n) + return n; + else if (++c->read >= strlen(arg) + 1) + { + c->ret->i32 = 0; + free_argcopy(c); + return NW_OK; + } + + return NW_AGAIN; +} + +static enum nw_state check(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct argcopy *const c = p->import; + + if (c->arg < 0 || c->arg >= p->argc || !c->addr || !c->errno_addr) + { + if (c->errno_addr) + { + if (set_errno(p, EINVAL, next)) + goto failure; + } + else + { + c->ret->i32 = -1; + return NW_OK; + } + } + else + *next = (const struct nw_next){.fn = read_arg, .user = user}; + +failure: + free_argcopy(c); + return NW_FATAL; +} + +enum nw_state bin_wnix_argcopy(const union nw_value *const params, + union nw_value *const ret, void *const user, + struct nw_next *const next) +{ + enum {ARG, ADDR, ERRNO}; + struct argcopy *const c = malloc(sizeof *c); + + if (!c) + return NW_FATAL; + + *c = (const struct argcopy) + { + .arg = params[ARG].i32, + .addr = params[ADDR].i32, + .errno_addr = params[ERRNO].i32, + .ret = ret + }; + + struct bin_proc *const p = user; + + *next = (const struct nw_next){.fn = check, .user = user}; + p->import = c; + return NW_AGAIN; +} diff --git a/src/bin/src/wnix/arglen.c b/src/bin/src/wnix/arglen.c new file mode 100644 index 0000000..b16c4eb --- /dev/null +++ b/src/bin/src/wnix/arglen.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <nanowasm/nw.h> +#include <string.h> + +enum nw_state bin_wnix_arglen(const union nw_value *const params, + union nw_value *const ret, void *const user, + struct nw_next *const next) +{ + const struct bin_proc *const p = user; + const long arg = params->i32; + + if (arg < 0 || arg >= p->argc) + ret->i32 = 0; + else + ret->i32 = strlen(p->argv[arg]); + + return NW_OK; +} diff --git a/src/bin/src/wnix/exit.c b/src/bin/src/wnix/exit.c new file mode 100644 index 0000000..8540250 --- /dev/null +++ b/src/bin/src/wnix/exit.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/proc.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <nanowasm/nw.h> + +enum nw_state bin_wnix_exit(const union nw_value *const params, + union nw_value *const ret, void *const user, + struct nw_next *const next) +{ + struct bin_proc *const p = user; + + if (bin_stop(p)) + return NW_FATAL; + + p->retval = params->i32; + return NW_OK; +} diff --git a/src/bin/src/wnix/mkdir.c b/src/bin/src/wnix/mkdir.c new file mode 100644 index 0000000..30a274a --- /dev/null +++ b/src/bin/src/wnix/mkdir.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/wnix/routines.h> +#include <bin/proc.h> +#include <bin/types.h> +#include <endian.h> +#include <nanowasm/nw.h> +#include <nanowasm/linear.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +enum nw_state bin_wnix_mkdir(const union nw_value *const params, + union nw_value *const ret, void *const user, + struct nw_next *const next) +{ + /* TODO */ + ret->i32 = -1; + return NW_OK; +} diff --git a/src/bin/src/wnix/mount.c b/src/bin/src/wnix/mount.c new file mode 100644 index 0000000..562f7d9 --- /dev/null +++ b/src/bin/src/wnix/mount.c @@ -0,0 +1,298 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/wnix.h> +#include <bin/proc.h> +#include <bin/routines.h> +#include <bin/types.h> +#include <bin/wnix/routines.h> +#include <aio.h> +#include <endian.h> +#include <state.h> +#include <nanowasm/nw.h> +#include <nanowasm/linear.h> +#include <errno.h> +#include <stdlib.h> + +struct mount +{ + struct mountstr + { + unsigned long addr; + char *str; + } src, tgt, type; + + unsigned long flags, args, errno_addr; + struct endian_le32 le32; + union nw_value *ret; + struct nw_sm_io io; + enum state state; + struct aio *aio; + int error; + size_t i; +}; + +static void free_mount(struct mount *const m) +{ + aio_free(m->aio); + free(m->src.str); + free(m->tgt.str); + free(m->type.str); + free(m); +} + +static enum nw_state errno_set(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct mount *const m = p->import; + + m->ret->i32 = -1; + free_mount(m); + return NW_OK; +} + +static int set_errno(struct bin_proc *const p, const int error, + struct nw_next *const next) +{ + struct mount *const m = p->import; + + *next = (const struct nw_next) + { + .fn = errno_set, + .user = p + }; + + return bin_wnix_set_errno(p, error, m->errno_addr, next); +} + +static enum nw_state mounted(void *const user, struct nw_next *const next) +{ + enum nw_state ret = NW_FATAL; + struct bin_proc *const p = user; + struct mount *const m = p->import; + + if (m->state) + { + if (set_errno(p, m->error, next)) + goto end; + + return NW_AGAIN; + } + + m->ret->i32 = 0; + ret = NW_OK; +end: + free_mount(m); + return ret; +} + +static int done(const enum state state, void *const args) +{ + struct bin_proc *const p = args; + struct mount *const m = p->import; + + if (bin_proc_unlock(p)) + { + free_mount(m); + return -1; + } + else if (state) + m->error = errno; + + m->state = state; + return 0; +} + +static enum nw_state do_mount(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct mount *const m = p->import; + const struct aio_mount am = + { + .type = m->type.str, + .mount = + { + .src = m->src.str, + .tgt = m->tgt.str, + .mode = m->flags, + .gid = p->gid, + .uid = p->uid + } + }; + + const struct aio_done d = + { + .f = done, + .args = p + }; + + if (!(m->aio = aio_mount(&am, &d))) + { + if (set_errno(p, errno, next)) + goto failure; + + return NW_AGAIN; + } + else if (bin_proc_lock(p)) + goto failure; + + *next = (const struct nw_next){.fn = mounted, .user = p}; + return NW_OK; + +failure: + free_mount(m); + return NW_FATAL; +} + +static enum nw_state read_str(struct bin_proc *const p, + struct mountstr *const ms) +{ + char b; + struct mount *const m = p->import; + struct nw_sm_io io = {.buf = &b, .n = sizeof b}; + const enum nw_state n = nw_linear_load(&p->instance, &io, ms->addr + m->i); + + if (n) + return n; + + char *const s = realloc(ms->str, m->i + 1); + + if (!s) + return NW_FATAL; + + s[m->i++] = b; + ms->str = s; + return b ? NW_AGAIN : NW_OK; +} + +static enum nw_state check_read_str(struct bin_proc *const p, + struct mountstr *const ms, const struct nw_next *const innext, + struct nw_next *const outnext) +{ + struct mount *const m = p->import; + enum {PATHMAX = 128}; + + if (m->i >= PATHMAX) + { + free_mount(m); + /* TODO: assign errno. */ + m->ret->i32 = -1; + return NW_OK; + } + + switch (read_str(p, ms)) + { + case NW_FATAL: + free_mount(m); + return NW_FATAL; + + case NW_OK: + m->i = 0; + *outnext = *innext; + break; + + case NW_AGAIN: + break; + } + + return NW_AGAIN; +} + +static enum nw_state read_type(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct mount *const m = p->import; + const struct nw_next rnext = {.fn = do_mount, .user = p}; + + return check_read_str(p, &m->type, &rnext, next); +} + +static enum nw_state read_tgt(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct mount *const m = p->import; + const struct nw_next rnext = {.fn = read_type, .user = p}; + + return check_read_str(p, &m->tgt, &rnext, next); +} + +static enum nw_state read_src(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct mount *const m = p->import; + const struct nw_next rnext = {.fn = read_tgt, .user = p}; + + return check_read_str(p, &m->src, &rnext, next); +} + +static enum nw_state check(void *const user, struct nw_next *const next) +{ + struct bin_proc *const p = user; + struct mount *const m = p->import; + + if (!m->src.addr || !m->tgt.addr || !m->type.addr || !m->errno_addr) + { + if (m->errno_addr) + { + if (set_errno(p, EINVAL, next)) + goto failure; + } + else + { + m->ret->i32 = -1; + return NW_OK; + } + } + else + *next = (const struct nw_next){.fn = read_src, .user = user}; + + return NW_AGAIN; + +failure: + free_mount(m); + return NW_FATAL; +} + +enum nw_state bin_wnix_mount(const union nw_value *const params, + union nw_value *const ret, void *const user, + struct nw_next *const next) +{ + enum {SRC, TGT, TYPE, FLAGS, ARGS, ERRNO}; + struct mount *const m = malloc(sizeof *m); + + if (!m) + return NW_FATAL; + + *m = (const struct mount) + { + .args = params[ARGS].i32, + .flags = params[FLAGS].i32, + .type.addr = params[TYPE].i32, + .tgt.addr = params[TGT].i32, + .src.addr = params[SRC].i32, + .errno_addr = params[ERRNO].i32, + .ret = ret + }; + + struct bin_proc *const p = user; + + *next = (const struct nw_next){.fn = check, .user = user}; + p->import = m; + return NW_AGAIN; +} diff --git a/src/bin/src/wnix/set_errno.c b/src/bin/src/wnix/set_errno.c new file mode 100644 index 0000000..cc04420 --- /dev/null +++ b/src/bin/src/wnix/set_errno.c @@ -0,0 +1,73 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <bin.h> +#include <bin/types.h> +#include <bin/wnix/routines.h> +#include <endian.h> +#include <nanowasm/nw.h> +#include <stdlib.h> + +struct set_errno +{ + struct bin_proc *p; + struct nw_next next; + struct nw_sm_io io; + struct endian_le32 error; + unsigned long addr; +}; + +static enum nw_state store_errno(void *const user, + struct nw_next *const next) +{ + struct set_errno *const e = user; + struct bin_proc *const p = e->p; + const enum nw_state n = nw_linear_store(&p->instance, &e->io, e->addr); + + if (n) + return n; + + *next = e->next; + free(e); + return NW_AGAIN; +} + +int bin_wnix_set_errno(struct bin_proc *const p, const int error, + const unsigned long addr, struct nw_next *const next) +{ + struct set_errno *const e = malloc(sizeof *e); + + if (!e) + return -1; + + *e = (const struct set_errno) + { + .error = endian_to_le32(error), + .next = *next, + .addr = addr, + .p = p, + .io = + { + .buf = &e->error, + .n = sizeof e->error + } + }; + + *next = (const struct nw_next){.fn = store_errno, .user = e}; + return 0; +} diff --git a/src/caio/CMakeLists.txt b/src/caio/CMakeLists.txt new file mode 100644 index 0000000..980d21b --- /dev/null +++ b/src/caio/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(caio) +add_subdirectory(src) +target_include_directories(caio PUBLIC include PRIVATE private_include) +target_link_libraries(caio PUBLIC aio fs state PRIVATE loop) +# Even if PRIVATE, there are cyclical dependencies among libraries that +# make LINK_INTERFACE_MULTIPLICITY to exceed its default value (2). +set_target_properties(caio PROPERTIES LINK_INTERFACE_MULTIPLICITY 3) diff --git a/src/caio/include/caio.h b/src/caio/include/caio.h new file mode 100644 index 0000000..284224a --- /dev/null +++ b/src/caio/include/caio.h @@ -0,0 +1,43 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef CAIO_H +#define CAIO_H + +#include <aio.h> +#include <stddef.h> + +struct caio_open +{ + const char *path; + int flags; + uid_t uid; + gid_t gid; +}; + +struct caio *caio_open(const struct caio_open *op, const struct aio_done *d); +int caio_set_caches(struct caio *a, size_t n); +int caio_read(struct caio *a, void *buf, size_t n, const struct aio_done *d); +int caio_write(struct caio *a, const void *buf, size_t n, + const struct aio_done *d); +int caio_seek(struct caio *a, off_t offset); +int caio_tell(const struct caio *a, off_t *offset); +int caio_eof(const struct caio *a); +int caio_close(struct caio *a); + +#endif diff --git a/src/caio/private_include/caio/routines.h b/src/caio/private_include/caio/routines.h new file mode 100644 index 0000000..a83043a --- /dev/null +++ b/src/caio/private_include/caio/routines.h @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef CAIO_ROUTINES_H +#define CAIO_ROUTINES_H + +#include <caio/types.h> +#include <sys/types.h> + +struct caio_cache *caio_cache(struct caio *a); + +#endif diff --git a/src/caio/private_include/caio/types.h b/src/caio/private_include/caio/types.h new file mode 100644 index 0000000..001a4d3 --- /dev/null +++ b/src/caio/private_include/caio/types.h @@ -0,0 +1,46 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef CAIO_TYPES_H +#define CAIO_TYPES_H + +#include <caio.h> +#include <aio.h> +#include <fs/fs.h> +#include <sys/types.h> +#include <stdbool.h> +#include <stddef.h> + +struct caio_cache +{ + off_t offset; + size_t available; + char buf[2048]; + struct caio_cache *prev, *next; +}; + +struct caio +{ + struct aio_done done; + struct aio *aio; + struct fs_fd fd; + struct caio_cache *caches; + off_t offset; +}; + +#endif diff --git a/src/caio/src/CMakeLists.txt b/src/caio/src/CMakeLists.txt new file mode 100644 index 0000000..91b95d4 --- /dev/null +++ b/src/caio/src/CMakeLists.txt @@ -0,0 +1,27 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(caio PRIVATE + cache.c + close.c + eof.c + open.c + read.c + seek.c + set_caches.c + tell.c + write.c +) diff --git a/src/caio/src/cache.c b/src/caio/src/cache.c new file mode 100644 index 0000000..edd462c --- /dev/null +++ b/src/caio/src/cache.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/routines.h> +#include <caio/types.h> +#include <sys/types.h> +#include <stddef.h> + +struct caio_cache *caio_cache(struct caio *const a) +{ + for (struct caio_cache *c = a->caches; c; c = c->next) + { + const off_t offset = a->offset; + + if (c->available + && offset >= c->offset + && offset < c->offset + sizeof c->buf) + return c; + } + + return NULL; +} diff --git a/src/caio/src/close.c b/src/caio/src/close.c new file mode 100644 index 0000000..253aaa7 --- /dev/null +++ b/src/caio/src/close.c @@ -0,0 +1,44 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/types.h> +#include <aio.h> +#include <fs/fs.h> +#include <stdlib.h> + +int caio_close(struct caio *const caio) +{ + if (!caio) + return 0; + else + aio_free(caio->aio); + + for (struct caio_cache *c = caio->caches; c;) + { + struct caio_cache *const next = c->next; + + free(c); + c = next; + } + + aio_close(&caio->fd); + free(caio); + /* TODO */ + return -1; +} diff --git a/src/caio/src/eof.c b/src/caio/src/eof.c new file mode 100644 index 0000000..a631546 --- /dev/null +++ b/src/caio/src/eof.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/types.h> + +int caio_eof(const struct caio *const a) +{ + return a->offset >= a->fd.size; +} diff --git a/src/caio/src/open.c b/src/caio/src/open.c new file mode 100644 index 0000000..c12432c --- /dev/null +++ b/src/caio/src/open.c @@ -0,0 +1,79 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/types.h> +#include <aio.h> +#include <loop.h> +#include <fs/fs.h> +#include <stdlib.h> + +static int done(const enum state state, void *const args) +{ + struct caio *const a = args; + const struct aio_done *const d = &a->done; + + if (loop_rm_aio(a->aio)) + return -1; + + aio_free(a->aio); + a->aio = NULL; + return d->f ? d->f(state, d->args) : 0; +} + +struct caio *caio_open(const struct caio_open *op, + const struct aio_done *const d) +{ + struct aio *aio = NULL; + struct caio *const ret = malloc(sizeof *ret); + + if (!ret) + goto failure; + + const struct fs_open aio_op = + { + .flags = op->flags, + .path = op->path, + .uid = op->uid, + .gid = op->gid, + .fd = &ret->fd, + }; + + const struct aio_done dd = + { + .f = done, + .args = ret + }; + + *ret = (const struct caio){0}; + + if (caio_set_caches(ret, 1) + || !(aio = aio_open(&aio_op, &dd)) + || loop_add_aio(aio)) + goto failure; + else if (d) + ret->done = *d; + + ret->aio = aio; + return ret; + +failure: + aio_free(aio); + free(ret); + return NULL; +} diff --git a/src/caio/src/read.c b/src/caio/src/read.c new file mode 100644 index 0000000..e1e85b6 --- /dev/null +++ b/src/caio/src/read.c @@ -0,0 +1,154 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/routines.h> +#include <caio/types.h> +#include <aio.h> +#include <fs/fs.h> +#include <loop.h> +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +static int done(const enum state s, void *const args) +{ + struct caio *const a = args; + const struct aio_done *const d = &a->done; + + if (loop_rm_aio(a->aio)) + return -1; + + aio_free(a->aio); + a->aio = NULL; + return d->f ? d->f(s, d->args) : 0; +} + +static size_t read_cache(struct caio *const a, struct caio_cache *const c, + void *const buf, size_t n) +{ + char *p = buf; + size_t i = a->offset % sizeof c->buf; + + while (i < c->available && n) + { + *p++ = c->buf[i++]; + n--; + } + + const size_t ret = p - (const char *)buf; + + a->offset += ret; + return ret; +} + +static size_t getrem(const struct caio *const a) +{ + const struct fs_fd *const fd = &a->fd; + const off_t n = fd->size - fd->offset; + const size_t sz = sizeof a->caches->buf / sizeof *a->caches->buf; + + return n < sz ? n : sz; +} + +static struct caio_cache *rotate(struct caio *const a) +{ + const struct fs_fd *const fd = &a->fd; + long long maxdiff = LLONG_MAX; + struct caio_cache *ret = a->caches; + + for (struct caio_cache *c = a->caches; c; c = c->next) + { + if (!c->available) + return c; + + const long long diff = (long long)c->offset - (long long)fd->offset, + adiff = llabs(diff); + + if (adiff < maxdiff) + { + maxdiff = adiff; + ret = c; + } + } + + return ret; +} + +static int setup_cache(struct caio *const a, const struct aio_done *const d) +{ + const size_t rem = getrem(a); + + if (!rem) + return 0; + + struct aio *aio = NULL; + struct caio_cache *const c = rotate(a); + const struct fs_read r = + { + .fd = &a->fd, + .buf = c->buf, + .n = rem + }; + + const struct aio_done dd = + { + .f = done, + .args = a + }; + + const off_t offset = (a->offset / sizeof c->buf) * sizeof c->buf; + + a->fd.offset = offset; + + if (!(aio = aio_read(&r, &dd)) || loop_add_aio(aio)) + goto failure; + else if (d) + a->done = *d; + else + a->done = (const struct aio_done){0}; + + a->aio = aio; + c->offset = offset; + c->available = rem; + return 0; + +failure: + aio_free(aio); + return -1; +} + +int caio_read(struct caio *const a, void *const buf, const size_t n, + const struct aio_done *const d) +{ + if (a->offset >= a->fd.size) + return 0; + + struct caio_cache *const c = caio_cache(a); + + if (c) + { + const size_t cr = read_cache(a, c, buf, n); + + if (cr) + return cr; + } + + return setup_cache(a, d); +} diff --git a/src/caio/src/readdebugmsg.c b/src/caio/src/readdebugmsg.c new file mode 100644 index 0000000..11493ba --- /dev/null +++ b/src/caio/src/readdebugmsg.c @@ -0,0 +1,170 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/routines.h> +#include <caio/types.h> +#include <aio.h> +#include <fs/fs.h> +#include <loop.h> +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + + +#include <drv/ps1/bios.h> +static int done(const enum state s, void *const args) +{ + struct caio *const a = args; + const struct aio_done *const d = &a->done; + + if (loop_rm_aio(a->aio)) + return -1; + + aio_free(a->aio); + a->aio = NULL; + Printf("finished preparing cache\n"); + return d->f ? d->f(s, d->args) : 0; +} + +static size_t read_cache(struct caio *const a, struct caio_cache *const c, + void *const buf, size_t n) +{ + char *p = buf; + size_t i = a->offset % sizeof c->buf, start = i; + unsigned char checksum = 0; + + while (i < c->available && n) + { + const unsigned char b = c->buf[i++]; + + *p++ = b; + checksum += b; + n--; + } + + const size_t ret = p - (const char *)buf; + + if (ret) + Printf("%s: read %lu bytes from cache %p (offset=%lu, bytes [%lu-%lu], chk=%#x)\n", + __func__, (unsigned long)ret, (void *)c, + (unsigned long)a->offset, (unsigned long)start, (unsigned long)i - 1, + (unsigned)checksum); + + a->offset += ret; + return ret; +} + +static size_t getrem(const struct caio *const a) +{ + const struct fs_fd *const fd = &a->fd; + const off_t n = fd->size - fd->offset; + const size_t sz = sizeof a->caches->buf / sizeof *a->caches->buf; + + return n < sz ? n : sz; +} + +static struct caio_cache *rotate(struct caio *const a) +{ + const struct fs_fd *const fd = &a->fd; + long long maxdiff = LLONG_MAX; + struct caio_cache *ret = a->caches; + + for (struct caio_cache *c = a->caches; c; c = c->next) + { + if (!c->available) + return c; + + const long long diff = (long long)c->offset - (long long)fd->offset, + adiff = llabs(diff); + + if (adiff < maxdiff) + { + maxdiff = adiff; + ret = c; + } + } + + return ret; +} + +static int setup_cache(struct caio *const a, const struct aio_done *const d) +{ + const size_t rem = getrem(a); + + if (!rem) + return 0; + + struct aio *aio = NULL; + struct caio_cache *const c = rotate(a); + const struct fs_read r = + { + .fd = &a->fd, + .buf = c->buf, + .n = rem + }; + + const struct aio_done dd = + { + .f = done, + .args = a + }; + + const off_t offset = (a->offset / sizeof c->buf) * sizeof c->buf; + + a->fd.offset = offset; + + if (!(aio = aio_read(&r, &dd)) || loop_add_aio(aio)) + goto failure; + else if (d) + a->done = *d; + else + a->done = (const struct aio_done){0}; + + a->aio = aio; + c->offset = offset; + c->available = rem; + Printf("%s: setting up cache %p with offset %lu, fd->offset=%lu and %lu bytes\n", + __func__, (void *)c, (unsigned long)c->offset, (unsigned long)a->fd.offset, + (unsigned long)c->available); + return 0; + +failure: + aio_free(aio); + return -1; +} + +int caio_read(struct caio *const a, void *const buf, const size_t n, + const struct aio_done *const d) +{ + if (a->offset >= a->fd.size) + return 0; + + struct caio_cache *const c = caio_cache(a); + + if (c) + { + const size_t cr = read_cache(a, c, buf, n); + + if (cr) + return cr; + } + + return setup_cache(a, d); +} diff --git a/src/caio/src/readnodebug.c b/src/caio/src/readnodebug.c new file mode 100644 index 0000000..ed8187e --- /dev/null +++ b/src/caio/src/readnodebug.c @@ -0,0 +1,152 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/routines.h> +#include <caio/types.h> +#include <aio.h> +#include <fs/fs.h> +#include <loop.h> +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +static int done(const enum state s, void *const args) +{ + struct caio *const a = args; + const struct aio_done *const d = &a->done; + + if (loop_rm_aio(a->aio)) + return -1; + + aio_free(a->aio); + a->aio = NULL; + return d->f ? d->f(s, d->args) : 0; +} + +static size_t read_cache(struct caio *const a, struct caio_cache *const c, + void *const buf, size_t n) +{ + char *p = buf; + size_t i = a->offset % sizeof c->buf; + + while (i < c->available && n) + { + *p++ = c->buf[i++]; + n--; + } + + const size_t ret = p - (const char *)buf; + + a->offset += ret; + return ret; +} + +static size_t getrem(const struct caio *const a) +{ + const struct fs_fd *const fd = &a->fd; + const off_t n = fd->size - fd->offset; + const size_t sz = sizeof a->caches->buf / sizeof *a->caches->buf; + + return n < sz ? n : sz; +} + +static struct caio_cache *rotate(struct caio *const a) +{ + const struct fs_fd *const fd = &a->fd; + long long maxdiff = LLONG_MAX; + struct caio_cache *ret = a->caches; + + for (struct caio_cache *c = a->caches; c; c = c->next) + { + const long long diff = c->available ? + (long long)c->offset - (long long)fd->offset : 0, + adiff = llabs(diff); + + if (adiff < maxdiff) + { + maxdiff = adiff; + ret = c; + } + } + + return ret; +} + +static int setup_cache(struct caio *const a, const struct aio_done *const d) +{ + const size_t rem = getrem(a); + + if (!rem) + return 0; + + struct aio *aio = NULL; + struct caio_cache *const c = rotate(a); + const struct fs_read r = + { + .fd = &a->fd, + .buf = c->buf, + .n = rem + }; + + const struct aio_done dd = + { + .f = done, + .args = a + }; + + const off_t offset = (a->offset / sizeof c->buf) * sizeof c->buf; + + a->fd.offset = offset; + + if (!(aio = aio_read(&r, &dd)) || loop_add_aio(aio)) + goto failure; + else if (d) + a->done = *d; + else + a->done = (const struct aio_done){0}; + + a->aio = aio; + c->offset = offset; + c->available = rem; + return 0; + +failure: + aio_free(aio); + return -1; +} + +int caio_read(struct caio *const a, void *const buf, const size_t n, + const struct aio_done *const d) +{ + if (a->offset >= a->fd.size) + return 0; + + struct caio_cache *const c = caio_cache(a); + + if (c) + { + const size_t cr = read_cache(a, c, buf, n); + + if (cr) + return cr; + } + + return setup_cache(a, d); +} diff --git a/src/caio/src/seek.c b/src/caio/src/seek.c new file mode 100644 index 0000000..1c0848d --- /dev/null +++ b/src/caio/src/seek.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/routines.h> +#include <caio/types.h> +#include <sys/types.h> + +int caio_seek(struct caio *const a, const off_t offset) +{ + struct fs_fd *const fd = &a->fd; + const off_t page = offset / sizeof a->caches->buf; + + a->offset = offset; + + if (!caio_cache(a)) + fd->offset = page * sizeof a->caches->buf; + + return 0; +} diff --git a/src/caio/src/set_caches.c b/src/caio/src/set_caches.c new file mode 100644 index 0000000..dfdd562 --- /dev/null +++ b/src/caio/src/set_caches.c @@ -0,0 +1,78 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/types.h> +#include <errno.h> +#include <stdlib.h> + +int caio_set_caches(struct caio *const a, const size_t n) +{ + struct caio_cache *c, *prev = NULL; + size_t i; + + if (!n) + { + errno = EINVAL; + return -1; + } + + for (i = 0, c = a->caches; i < n; i++) + { + if (!c) + { + struct caio_cache *const nc = malloc(sizeof *nc); + + if (!nc) + return -1; + + *nc = (const struct caio_cache){0}; + + if (!a->caches) + a->caches = nc; + else if (prev) + { + prev->next = nc; + nc->prev = prev; + } + + prev = nc; + } + else + { + prev = c; + c = c->next; + } + } + + for (i = 0, c = a->caches; c; i++) + { + struct caio_cache *const next = c->next; + + if (i >= n) + { + c->prev = c->next; + c->next = c->prev; + free(c); + } + + c = next; + } + + return 0; +} diff --git a/src/caio/src/tell.c b/src/caio/src/tell.c new file mode 100644 index 0000000..7bfb63a --- /dev/null +++ b/src/caio/src/tell.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/types.h> + +int caio_tell(const struct caio *const a, off_t *const offset) +{ + *offset = a->offset; + return 0; +} diff --git a/src/caio/src/write.c b/src/caio/src/write.c new file mode 100644 index 0000000..55ac558 --- /dev/null +++ b/src/caio/src/write.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <caio.h> +#include <caio/types.h> +#include <aio.h> +#include <fs/fs.h> + +int caio_write(struct caio *const caio, const void *const buf, const size_t n, + const struct aio_done *d) +{ + /* TODO */ + return -1; +} diff --git a/src/drv/CMakeLists.txt b/src/drv/CMakeLists.txt new file mode 100644 index 0000000..3306d93 --- /dev/null +++ b/src/drv/CMakeLists.txt @@ -0,0 +1,28 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv) +add_subdirectory(event) +add_subdirectory(tty) +add_subdirectory(src) +target_include_directories(drv PUBLIC include PRIVATE private_include) +target_link_libraries(drv PUBLIC drv_event PRIVATE drv_tty) + +if(PS1_BUILD) + add_subdirectory(ps1) + target_compile_definitions(drv PRIVATE DRV_PS1) + target_link_libraries(drv PUBLIC drv_ps1_time PRIVATE drv_ps1) +endif() diff --git a/src/drv/event/CMakeLists.txt b/src/drv/event/CMakeLists.txt new file mode 100644 index 0000000..7d52511 --- /dev/null +++ b/src/drv/event/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_event INTERFACE) +target_include_directories(drv_event INTERFACE include) diff --git a/src/drv/event/include/drv/event.h b/src/drv/event/include/drv/event.h new file mode 100644 index 0000000..5707242 --- /dev/null +++ b/src/drv/event/include/drv/event.h @@ -0,0 +1,49 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_EVENT_H +#define DRV_EVENT_H + +#include <sys/types.h> +#include <stdbool.h> +#include <stddef.h> + +struct drv_event_done +{ + int (*f)(int error, void *args); + void *args; +}; + +struct drv_event_ops +{ + int (*read)(void *buf, size_t n, off_t offset, + const struct drv_event_done *done, void *args); + int (*read_nb)(void *buf, size_t n, void *args); + int (*write)(const void *buf, size_t n, const struct drv_event_done *done, + void *args); + void *args; +}; + +struct drv_event +{ + int (*status)(const char *node, const struct drv_event_ops *ops, + bool available, mode_t mode, void *args); + void *args; +}; + +#endif diff --git a/src/drv/include/drv/drv.h b/src/drv/include/drv/drv.h new file mode 100644 index 0000000..eb8bee0 --- /dev/null +++ b/src/drv/include/drv/drv.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_H +#define DRV_H + +#include <drv/event.h> + +struct drv *drv_init(const struct drv_event *ev); +int drv_update(struct drv *d); +void drv_free(struct drv *d); + +#endif diff --git a/src/drv/include/drv/time.h b/src/drv/include/drv/time.h new file mode 100644 index 0000000..12b213d --- /dev/null +++ b/src/drv/include/drv/time.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TIME_H +#define DRV_TIME_H + +#include <time.h> + +int drv_time_getres(clockid_t id, struct timespec *ts); +int drv_time_gettime(clockid_t id, struct timespec *ts); +int drv_time_settime(clockid_t id, const struct timespec *ts); + +#endif diff --git a/src/drv/private_include/drv/port.h b/src/drv/private_include/drv/port.h new file mode 100644 index 0000000..cdf30ab --- /dev/null +++ b/src/drv/private_include/drv/port.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PORT_H +#define DRV_PORT_H + +struct drv_port; + +#ifdef DRV_PS1 +#include <drv/ps1.h> +#endif + +#endif diff --git a/src/drv/private_include/drv/tree.h b/src/drv/private_include/drv/tree.h new file mode 100644 index 0000000..da4b7e9 --- /dev/null +++ b/src/drv/private_include/drv/tree.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TREE_H +#define DRV_TREE_H + +#include <drv/drv.h> +#include <drv/port.h> +#include <stddef.h> + +extern struct drv_port *(*const drv_tree_init[])(const struct drv_event *); +extern int (*const drv_tree_update[])(struct drv_port *); +extern void (*const drv_tree_free[])(struct drv_port *); +extern const size_t drv_tree_n; + +#endif diff --git a/src/drv/private_include/drv/types.h b/src/drv/private_include/drv/types.h new file mode 100644 index 0000000..959e12d --- /dev/null +++ b/src/drv/private_include/drv/types.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TYPES_H +#define DRV_TYPES_H + +#include <stddef.h> + +struct drv +{ + struct drv_port **ports; + size_t n; +}; + +#endif diff --git a/src/drv/ps1/CMakeLists.txt b/src/drv/ps1/CMakeLists.txt new file mode 100644 index 0000000..08d97c2 --- /dev/null +++ b/src/drv/ps1/CMakeLists.txt @@ -0,0 +1,37 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_subdirectory(bios) +add_subdirectory(cd) +add_subdirectory(cpu) +add_subdirectory(dma) +add_subdirectory(event) +add_subdirectory(gpu) +add_subdirectory(irq) +add_subdirectory(mc) +add_subdirectory(pad) +add_subdirectory(rcnt) +add_subdirectory(sio) +add_subdirectory(time) +add_library(drv_ps1) +add_subdirectory(src) +target_include_directories(drv_ps1 PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1 PUBLIC c drv_event PRIVATE + drv_ps1_cd + drv_ps1_mc + drv_ps1_pad + drv_ps1_sio +) diff --git a/src/drv/ps1/bios/CMakeLists.txt b/src/drv/ps1/bios/CMakeLists.txt new file mode 100644 index 0000000..ebc0937 --- /dev/null +++ b/src/drv/ps1/bios/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_bios) +add_subdirectory(src) +target_include_directories(drv_ps1_bios INTERFACE include) diff --git a/src/drv/ps1/bios/include/drv/ps1/bios.h b/src/drv/ps1/bios/include/drv/ps1/bios.h new file mode 100644 index 0000000..ca53194 --- /dev/null +++ b/src/drv/ps1/bios/include/drv/ps1/bios.h @@ -0,0 +1,128 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PS1_BIOS_H +#define PS1_BIOS_H + +#include <stdint.h> +#include <setjmp.h> + +#if __GNUC__ +#define PRINTF_ATTR __attribute__ ((format (__printf__, 1, 2))) +#else +#define PRINTF_ATTR +#endif + +enum +{ + CLASS_IRQ0 = (long)0xf0000001, + CLASS_GPU, + CLASS_CDROM, + CLASS_DMA, + CLASS_RTC0 = (long)0xf2000000, + CLASS_RTC1, + CLASS_RTC2, + CLASS_VBLANK, + CLASS_CONTROLLER = (long)0xf0000008, + CLASS_SPU, + CLASS_PIO, + CLASS_SIO +}; + +enum +{ + MODE_EXECUTE = 0x1000, + MODE_READY = 0x2000 +}; + +enum +{ + SPEC_COUNTER_ZERO = 1, + SPEC_INTERRUPTED = 1 << 1, + SPEC_EOF = 1 << 2, + SPEC_FILE_CLOSED = 1 << 3, + SPEC_COMMAND_ACK = 1 << 4, + SPEC_COMMAND_COMPLETE = 1 << 5, + SPEC_DATA_READY = 1 << 6, + SPEC_DATA_END = 1 << 7, + SPEC_TIMEOUT = 1 << 8, + SPEC_UNKNOWN_CMD = 1 << 9, + SPEC_END_READ_BUF = 1 << 10, + SPEC_END_WRITE_BUF = 1 << 11, + SPEC_GENERAL_INTERRUPT = 1 << 12, + SPEC_NEW_DEVICE = 1 << 13, + SPEC_SYSCALL = 1 << 14, + SPEC_ERROR = 1 << 15, + SPEC_WRITE_ERROR, + SPEC_DOMAIN_ERROR = 0x301, + SPEC_RANGE_RNG +}; + +struct CdAsyncSeekL +{ + uint8_t minutes, seconds, frames; +}; + +union SetMode +{ + struct + { + uint8_t cdda :1, autopause :1, report :1, xa_filter :1, ignore :1, + whole_sector :1, xa_adpcm :1, speed :1; + } bits; + + uint8_t mask; +}; + +struct CdAsyncReadSector_mode +{ + union SetMode mode; + union + { + struct + { + uint8_t reads :1, :7; + } bits; + } read; + + uint16_t reserved; +}; + +int EnterCriticalSection(void); +void ExitCriticalSection(void); +void GetConf(uint32_t *events, uint32_t *tcb, void **stacktop); +void SetConf(uint32_t events, uint32_t tcb, void *stacktop); +int OpenEvent(int class, int spec, int mode, int (*f)(void)); +int EnableEvent(int event); +int DisableEvent(int event); +int CloseEvent(int event); +int TestEvent(int event); +int WaitEvent(int event); +int CdAsyncGetStatus(uint8_t *response); +int CdAsyncReadSector(unsigned count, void *dst, + struct CdAsyncReadSector_mode mode); +int CdAsyncSeekL(const struct CdAsyncSeekL *seekl); +int Printf(const char *fmt, ...) PRINTF_ATTR; +void SetCustomExitFromException(jmp_buf jmp); +void CdInit(void); +void CdRemove(void); +int SaveState(jmp_buf buf); +void RestoreState(jmp_buf buf, int value); +void ReturnFromException(void); + +#endif diff --git a/src/drv/ps1/bios/src/CMakeLists.txt b/src/drv/ps1/bios/src/CMakeLists.txt new file mode 100644 index 0000000..67ea62b --- /dev/null +++ b/src/drv/ps1/bios/src/CMakeLists.txt @@ -0,0 +1,38 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_bios PRIVATE + CdAsyncGetStatus.s + CdAsyncReadSector.s + CdAsyncSeekL.s + CdInit.s + CdRemove.s + CloseEvent.s + DisableEvent.s + EnableEvent.s + EnterCriticalSection.s + ExitCriticalSection.s + GetConf.s + OpenEvent.s + Printf.s + RestoreState.s + ReturnFromException.s + SaveState.s + SetConf.s + SetCustomExitFromException.s + TestEvent.s + WaitEvent.s +) diff --git a/src/drv/ps1/bios/src/CdAsyncGetStatus.s b/src/drv/ps1/bios/src/CdAsyncGetStatus.s new file mode 100644 index 0000000..18922da --- /dev/null +++ b/src/drv/ps1/bios/src/CdAsyncGetStatus.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global CdAsyncGetStatus + +CdAsyncGetStatus: + li $9, 0x7c + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/CdAsyncReadSector.s b/src/drv/ps1/bios/src/CdAsyncReadSector.s new file mode 100644 index 0000000..6411e12 --- /dev/null +++ b/src/drv/ps1/bios/src/CdAsyncReadSector.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global CdAsyncReadSector + +CdAsyncReadSector: + li $9, 0x7e + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/CdAsyncSeekL.s b/src/drv/ps1/bios/src/CdAsyncSeekL.s new file mode 100644 index 0000000..529d116 --- /dev/null +++ b/src/drv/ps1/bios/src/CdAsyncSeekL.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global CdAsyncSeekL + +CdAsyncSeekL: + li $9, 0x78 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/CdInit.s b/src/drv/ps1/bios/src/CdInit.s new file mode 100644 index 0000000..dcf3474 --- /dev/null +++ b/src/drv/ps1/bios/src/CdInit.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global CdInit + +CdInit: + li $9, 0x54 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/CdRemove.s b/src/drv/ps1/bios/src/CdRemove.s new file mode 100644 index 0000000..e3bb34d --- /dev/null +++ b/src/drv/ps1/bios/src/CdRemove.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global CdRemove + +CdRemove: + li $9, 0x56 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/CloseEvent.s b/src/drv/ps1/bios/src/CloseEvent.s new file mode 100644 index 0000000..7dd47e3 --- /dev/null +++ b/src/drv/ps1/bios/src/CloseEvent.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global CloseEvent + +CloseEvent: + li $9, 0x9 + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/DisableEvent.s b/src/drv/ps1/bios/src/DisableEvent.s new file mode 100644 index 0000000..f32dcf8 --- /dev/null +++ b/src/drv/ps1/bios/src/DisableEvent.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global DisableEvent + +DisableEvent: + li $9, 0xd + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/EnableEvent.s b/src/drv/ps1/bios/src/EnableEvent.s new file mode 100644 index 0000000..f6da29d --- /dev/null +++ b/src/drv/ps1/bios/src/EnableEvent.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.text + +.global EnableEvent + +EnableEvent: + li $9, 0xc + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/EnterCriticalSection.s b/src/drv/ps1/bios/src/EnterCriticalSection.s new file mode 100644 index 0000000..c8302e0 --- /dev/null +++ b/src/drv/ps1/bios/src/EnterCriticalSection.s @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.text + +.global EnterCriticalSection + +EnterCriticalSection: + li $a0, 1 + syscall + nop + jr $ra + nop diff --git a/src/drv/ps1/bios/src/ExitCriticalSection.s b/src/drv/ps1/bios/src/ExitCriticalSection.s new file mode 100644 index 0000000..198b040 --- /dev/null +++ b/src/drv/ps1/bios/src/ExitCriticalSection.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global ExitCriticalSection + +ExitCriticalSection: + li $a0, 2 + syscall + nop + jr $ra + nop diff --git a/src/drv/ps1/bios/src/GetConf.s b/src/drv/ps1/bios/src/GetConf.s new file mode 100644 index 0000000..927b950 --- /dev/null +++ b/src/drv/ps1/bios/src/GetConf.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global GetConf + +GetConf: + li $9, 0x9d + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/OpenEvent.s b/src/drv/ps1/bios/src/OpenEvent.s new file mode 100644 index 0000000..dca7141 --- /dev/null +++ b/src/drv/ps1/bios/src/OpenEvent.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global OpenEvent + +OpenEvent: + li $9, 0x8 + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/Printf.s b/src/drv/ps1/bios/src/Printf.s new file mode 100644 index 0000000..9e0a77f --- /dev/null +++ b/src/drv/ps1/bios/src/Printf.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global Printf + +Printf: + li $9, 0x3f + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/RestoreState.s b/src/drv/ps1/bios/src/RestoreState.s new file mode 100644 index 0000000..c830296 --- /dev/null +++ b/src/drv/ps1/bios/src/RestoreState.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global RestoreState + +RestoreState: + li $9, 0x14 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/ReturnFromException.s b/src/drv/ps1/bios/src/ReturnFromException.s new file mode 100644 index 0000000..6af3bb3 --- /dev/null +++ b/src/drv/ps1/bios/src/ReturnFromException.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global ReturnFromException + +ReturnFromException: + li $9, 0x17 + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/SaveState.s b/src/drv/ps1/bios/src/SaveState.s new file mode 100644 index 0000000..eb72ea3 --- /dev/null +++ b/src/drv/ps1/bios/src/SaveState.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global SaveState + +SaveState: + li $9, 0x13 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/SetConf.s b/src/drv/ps1/bios/src/SetConf.s new file mode 100644 index 0000000..5063667 --- /dev/null +++ b/src/drv/ps1/bios/src/SetConf.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global SetConf + +SetConf: + li $9, 0x9c + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/SetCustomExitFromException.s b/src/drv/ps1/bios/src/SetCustomExitFromException.s new file mode 100644 index 0000000..75cf8cc --- /dev/null +++ b/src/drv/ps1/bios/src/SetCustomExitFromException.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.global SetCustomExitFromException + +SetCustomExitFromException: + li $9, 0x19 + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/TestEvent.s b/src/drv/ps1/bios/src/TestEvent.s new file mode 100644 index 0000000..af0edab --- /dev/null +++ b/src/drv/ps1/bios/src/TestEvent.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.text + +.global TestEvent + +TestEvent: + li $9, 0xb + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/WaitEvent.s b/src/drv/ps1/bios/src/WaitEvent.s new file mode 100644 index 0000000..8f58d52 --- /dev/null +++ b/src/drv/ps1/bios/src/WaitEvent.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +.text + +.global WaitEvent + +WaitEvent: + li $9, 0xa + j 0xb0 + nop diff --git a/src/drv/ps1/cd/CMakeLists.txt b/src/drv/ps1/cd/CMakeLists.txt new file mode 100644 index 0000000..9b84541 --- /dev/null +++ b/src/drv/ps1/cd/CMakeLists.txt @@ -0,0 +1,27 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_cd) +add_subdirectory(src) +target_include_directories(drv_ps1_cd PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_cd + PUBLIC + c + drv_event + PRIVATE + drv_ps1_bios + drv_ps1_event +) diff --git a/src/drv/ps1/cd/include/drv/ps1/cd.h b/src/drv/ps1/cd/include/drv/ps1/cd.h new file mode 100644 index 0000000..ff57622 --- /dev/null +++ b/src/drv/ps1/cd/include/drv/ps1/cd.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_H +#define DRV_PS1_CD_H + +#include <drv/event.h> + +struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *ev); +int drv_ps1_cd_update(struct drv_ps1_cd *cd); +void drv_ps1_cd_free(struct drv_ps1_cd *cd); + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h new file mode 100644 index 0000000..37b2d03 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h @@ -0,0 +1,66 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_REGS_H +#define DRV_PS1_CD_REGS_H + +#include <stdint.h> + +struct cd_reg_status +{ + uint8_t index :2; + const uint8_t ADPBUSY :1, PRMEMPT :1, PRMWRDY :1, RSLRRDY :1, DRQSTS :1, + BUSYSTS :1; +}; + +struct cd_reg_cmd +{ + uint8_t cmd; +}; + +struct cd_reg_rsp +{ + uint8_t rsp; +}; + +struct cd_reg_param +{ + uint8_t param; +}; + +union cd_reg_if +{ + const struct + { + uint8_t response :3, :1, cmd_start :1, :3; + } r; + + struct + { + uint8_t ack: 5, :1, CLRPRM :1, :1; + } w; +}; + +#define CD_REG(x) (0x1f801800 + (x)) +#define CD_REG_STATUS ((volatile struct cd_reg_status *)CD_REG(0)) +#define CD_REG_CMD ((volatile struct cd_reg_cmd *)CD_REG(1)) +#define CD_REG_RSP ((const volatile struct cd_reg_rsp *)CD_REG(1)) +#define CD_REG_PARAM ((volatile struct cd_reg_param *)CD_REG(2)) +#define CD_REG_IF ((volatile union cd_reg_if *)CD_REG(3)) + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h new file mode 100644 index 0000000..0b756de --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_ROUTINES_H +#define DRV_PS1_CD_ROUTINES_H + +#include <drv/event.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/bios.h> +#include <sys/types.h> +#include <stddef.h> + +int drv_ps1_cd_send(const struct cmd *cmd); +int drv_ps1_cd_getstat(void); +int drv_ps1_cd_read(void *buf, size_t n, off_t offset, + const struct drv_event_done *done, void *args); +int drv_ps1_cd_write(const void *buf, size_t n, + const struct drv_event_done *done, void *args); +int drv_ps1_cd_next(void); +struct CdAsyncSeekL drv_ps1_cd_toseekl(unsigned i); + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h new file mode 100644 index 0000000..2d4ae51 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h @@ -0,0 +1,111 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_TYPES_H +#define DRV_PS1_CD_TYPES_H + +#include <drv/event.h> +#include <sys/types.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +struct drv_ps1_cd +{ + bool available; + struct drv_event ev; +}; + +struct cmd +{ + enum + { + CMD_SYNC, + CMD_GETSTAT, + CMD_SETLOC, + } cmd; + + union cmd_param + { + struct cmd_setloc + { + uint8_t min, sec, sect; + } setloc; + } params; +}; + +struct cd_prv_getstat +{ + union + { + struct + { + uint8_t invalid :1, motor :1, seek_error :1, id_error :1, + shell_open :1, reading :1, seeking :1, playing_cdda :1; + } bits; + + uint8_t byte; + } status; +}; + +struct cd_prv_read +{ + int endevent, errevent; +}; + +struct cd_req_read +{ + void *buf; + size_t n; + off_t offset; +}; + +struct cd_req +{ + union + { + struct cd_req_read read; + } u; + + int (*f)(void); + struct drv_event_done done; + struct cd_req *next; +}; + +enum {CD_SECTOR_SZ = 2048}; + +struct cd_prv +{ + bool available, sector_read; + int (*next)(void); + int event; + struct cmd cmd; + struct cd_req *head, *tail; + char sector[CD_SECTOR_SZ]; + off_t offset; + + union + { + struct cd_prv_getstat getstat; + struct cd_prv_read read; + } u; +}; + +extern struct cd_prv drv_ps1_cd_prv; + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/virt/types.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/virt/types.h new file mode 100644 index 0000000..59437c0 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/virt/types.h @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_VIRT_TYPES_H +#define DRV_PS1_CD_VIRT_TYPES_H + +#include <drv/event.h> + +struct drv_ps1_cd +{ + struct drv_event ev; +}; + +struct cd_prv +{ + int (*next)(void); +}; + +extern struct cd_prv drv_ps1_cd_prv; + +#endif diff --git a/src/drv/ps1/cd/src/CMakeLists.txt b/src/drv/ps1/cd/src/CMakeLists.txt new file mode 100644 index 0000000..df5ecca --- /dev/null +++ b/src/drv/ps1/cd/src/CMakeLists.txt @@ -0,0 +1,33 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +if(WNIX_VIRT_CD) + add_subdirectory(virt) +else() + target_sources(drv_ps1_cd PRIVATE + free.c + getstat.c + init.c + next.c + prv.c + read.c + toseekl.c + update.c + write.c + ) +endif() + +target_link_libraries(drv_ps1_cd PRIVATE kprintf) diff --git a/src/drv/ps1/cd/src/ensure_event.c b/src/drv/ps1/cd/src/ensure_event.c new file mode 100644 index 0000000..592184a --- /dev/null +++ b/src/drv/ps1/cd/src/ensure_event.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/bios.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/event.h> +#include <stddef.h> + +int drv_ps1_cd_ensure_event(struct cd_prv *const p) +{ + if (p->event) + return 0; + + const int event = drv_ps1_event_open(CLASS_CDROM, SPEC_COMMAND_COMPLETE, + MODE_READY, NULL); + + if (event == -1) + return -1; + + drv_ps1_event_enable(p->event = event); + return 0; +} diff --git a/src/drv/ps1/cd/src/free.c b/src/drv/ps1/cd/src/free.c new file mode 100644 index 0000000..ed6f347 --- /dev/null +++ b/src/drv/ps1/cd/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> + +void drv_ps1_cd_free(struct drv_ps1_cd *const cd) +{ +} diff --git a/src/drv/ps1/cd/src/getstat.c b/src/drv/ps1/cd/src/getstat.c new file mode 100644 index 0000000..34bdaf5 --- /dev/null +++ b/src/drv/ps1/cd/src/getstat.c @@ -0,0 +1,70 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/event.h> +#include <kprintf.h> + +static int wait_event(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_getstat *const g = &p->u.getstat; + + if (drv_ps1_event_test(p->event)) + { + p->available = !g->status.bits.shell_open; + + if (!p->head) + return drv_ps1_cd_getstat(); + + return p->head->f(); + } + + return 0; +} + +static int ensure_event(struct cd_prv *const p) +{ + if (p->event) + return 0; + else if ((p->event = drv_ps1_event_open(CLASS_CDROM, SPEC_COMMAND_COMPLETE, + MODE_READY, NULL)) == -1) + return -1; + + drv_ps1_event_enable(p->event); + return 0; +} + +int drv_ps1_cd_getstat(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_getstat *const g = &p->u.getstat; + + /* TODO: CdAsyncGetStatus is *very* slow (~2.5 seconds / 10k calls) */ + if (ensure_event(p)) + return -1; + else if (!CdAsyncGetStatus(&g->status.byte)) + { + kprintf("%s: CdAsyncGetStatus failed\n", __func__); + return -1; + } + + p->next = wait_event; + return 0; +} diff --git a/src/drv/ps1/cd/src/init.c b/src/drv/ps1/cd/src/init.c new file mode 100644 index 0000000..b452e82 --- /dev/null +++ b/src/drv/ps1/cd/src/init.c @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/event.h> +#include <stddef.h> +#include <stdlib.h> + +struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *const ev) +{ + struct drv_ps1_cd *const ret = malloc(sizeof *ret); + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (!ret) + return NULL; + else if (!p->next && drv_ps1_cd_getstat()) + goto failure; + + *ret = (const struct drv_ps1_cd){.ev = *ev}; + return ret; + +failure: + free(ret); + return NULL; +} diff --git a/src/drv/ps1/cd/src/next.c b/src/drv/ps1/cd/src/next.c new file mode 100644 index 0000000..b26633a --- /dev/null +++ b/src/drv/ps1/cd/src/next.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <stdlib.h> + +int drv_ps1_cd_next(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const next = p->head->next; + + free(p->head); + + if (next && next->f()) + return -1; + else if (!(p->head = next)) + return drv_ps1_cd_getstat(); + + return 0; +} diff --git a/src/drv/ps1/cd/src/prv.c b/src/drv/ps1/cd/src/prv.c new file mode 100644 index 0000000..61ed4b4 --- /dev/null +++ b/src/drv/ps1/cd/src/prv.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/types.h> + +struct cd_prv drv_ps1_cd_prv; diff --git a/src/drv/ps1/cd/src/read.c b/src/drv/ps1/cd/src/read.c new file mode 100644 index 0000000..d21cbae --- /dev/null +++ b/src/drv/ps1/cd/src/read.c @@ -0,0 +1,239 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/event.h> +#include <drv/event.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +static int seek(void); + +static int deliver_event(struct cd_prv *const p, const int error) +{ + const struct cd_prv_read *const read = &p->u.read; + const struct cd_req *const req = p->head; + const struct drv_event_done *const d = &req->done; + + drv_ps1_event_disable(read->endevent); + drv_ps1_event_close(read->endevent); + drv_ps1_event_disable(read->errevent); + drv_ps1_event_close(read->errevent); + + if (!error) + { + const struct cd_req_read *const rr = &req->u.read; + const long offset = rr->offset % CD_SECTOR_SZ; + + memcpy(rr->buf, p->sector + offset, rr->n); + + if (!((p->offset += rr->n) % CD_SECTOR_SZ)) + p->sector_read = false; + } + + if (d->f(error, d->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_read(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_prv_read *const read = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + p->sector_read = true; + return deliver_event(p, SUCCESS); + } + else if (drv_ps1_event_test(read->errevent) + || drv_ps1_event_test(read->endevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int uncached_read(struct cd_prv *const p) +{ + int endevent, errevent; + struct cd_prv_read *const r = &p->u.read; + const struct CdAsyncReadSector_mode mode = + { + .mode.bits.speed = 1, + }; + + endevent = drv_ps1_event_open(CLASS_CDROM, SPEC_DATA_END, MODE_READY, NULL); + errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL); + + if (endevent == -1 || errevent == -1) + goto failure; + + *r = (const struct cd_prv_read) + { + .endevent = endevent, + .errevent = errevent + }; + + drv_ps1_event_enable(endevent); + drv_ps1_event_enable(errevent); + + if (!CdAsyncReadSector(1, p->sector, mode)) + goto failure; + + p->next = wait_read; + return 0; + +failure: + + if (endevent != -1) + { + drv_ps1_event_disable(endevent); + drv_ps1_event_close(endevent); + } + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int cached_read(struct cd_prv *const p) +{ + struct cd_req *const req = p->head; + struct cd_req_read *const rr = &req->u.read; + const struct drv_event_done *const done = &req->done; + const off_t offset = rr->offset % CD_SECTOR_SZ, + rem = CD_SECTOR_SZ - offset, + n = rr->n > rem ? rem : rr->n; + + memcpy(rr->buf, p->sector + offset, n); + + if (!((p->offset += n) % CD_SECTOR_SZ)) + p->sector_read = false; + + if (done->f(SUCCESS, done->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_req *const req = p->head; + const struct cd_req_read *const rr = &req->u.read; + const struct cd_prv_read *const r = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + drv_ps1_event_disable(r->errevent); + drv_ps1_event_close(r->errevent); + p->offset = rr->offset; + return uncached_read(p); + } + else if (drv_ps1_event_test(r->errevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_read *const r = &p->u.read; + const struct cd_req_read *rr = &p->head->u.read; + const unsigned sector = rr->offset / CD_SECTOR_SZ; + const struct CdAsyncSeekL seekl = drv_ps1_cd_toseekl(sector); + const int errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, + MODE_READY, NULL); + + if (errevent == -1) + goto failure; + + *r = (const struct cd_prv_read){.errevent = errevent}; + p->sector_read = false; + drv_ps1_event_enable(errevent); + + if (!CdAsyncSeekL(&seekl)) + goto failure; + + p->next = wait_seek; + return 0; + +failure: + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int start(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_req *const req = p->head; + const struct cd_req_read *const rr = &req->u.read; + const off_t cursect = p->offset / CD_SECTOR_SZ, + tgtsect = rr->offset / CD_SECTOR_SZ; + + if (cursect != tgtsect || !p->sector_read) + return seek(); + + /* TODO: multi-sector reads, make sure cache can really be used */ + return cached_read(p); +} + +int drv_ps1_cd_read(void *const buf, const size_t n, const off_t offset, + const struct drv_event_done *const done, void *const args) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const r = malloc(sizeof *r); + + if (!r) + return -1; + + *r = (const struct cd_req) + { + .f = start, + .done = *done, + .u.read = + { + .offset = offset, + .buf = buf, + .n = n + } + }; + + if (!p->head) + p->head = r; + else + p->tail->next = r; + + p->tail = r; + return 0; +} diff --git a/src/drv/ps1/cd/src/readdebug b/src/drv/ps1/cd/src/readdebug new file mode 100644 index 0000000..b2c09a7 --- /dev/null +++ b/src/drv/ps1/cd/src/readdebug @@ -0,0 +1,253 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/event.h> +#include <drv/event.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + + +#include <drv/ps1/bios.h> + +static int seek(void); + +static int deliver_event(struct cd_prv *const p, const int error) +{ + const struct cd_prv_read *const read = &p->u.read; + const struct cd_req *const req = p->head; + const struct drv_event_done *const d = &req->done; + + drv_ps1_event_disable(read->endevent); + drv_ps1_event_close(read->endevent); + drv_ps1_event_disable(read->errevent); + drv_ps1_event_close(read->errevent); + + if (!error) + { + const struct cd_req_read *const rr = &req->u.read; + const long offset = rr->offset % CD_SECTOR_SZ; + + memcpy(rr->buf, p->sector + offset, rr->n); + + if (!((p->offset += rr->n) % CD_SECTOR_SZ)) + p->sector_read = false; + } + + if (d->f(error, d->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_read(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_prv_read *const read = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + p->sector_read = true; + return deliver_event(p, SUCCESS); + } + else if (drv_ps1_event_test(read->errevent) + || drv_ps1_event_test(read->endevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int uncached_read(struct cd_prv *const p) +{ + int endevent, errevent; + struct cd_prv_read *const r = &p->u.read; + const struct CdAsyncReadSector_mode mode = + { + .mode.bits.speed = 1, + }; + + endevent = drv_ps1_event_open(CLASS_CDROM, SPEC_DATA_END, MODE_READY, NULL); + errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL); + + if (endevent == -1 || errevent == -1) + goto failure; + + *r = (const struct cd_prv_read) + { + .endevent = endevent, + .errevent = errevent + }; + + drv_ps1_event_enable(endevent); + drv_ps1_event_enable(errevent); + + Printf("preparing async read\n"); + if (!CdAsyncReadSector(1, p->sector, mode)) + goto failure; + + p->next = wait_read; + return 0; + +failure: + + if (endevent != -1) + { + drv_ps1_event_disable(endevent); + drv_ps1_event_close(endevent); + } + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int cached_read(struct cd_prv *const p) +{ + struct cd_req *const req = p->head; + struct cd_req_read *const rr = &req->u.read; + const struct drv_event_done *const done = &req->done; + const off_t offset = rr->offset % CD_SECTOR_SZ, + rem = CD_SECTOR_SZ - offset, + n = rr->n > rem ? rem : rr->n; + + Printf("Doing %lu-byte cached read from offset %lu to %p\n", + (unsigned long) n, (unsigned long) offset, (void *)rr->buf); + memcpy(rr->buf, p->sector + offset, n); + + if (!((p->offset += n) % CD_SECTOR_SZ)) + p->sector_read = false; + + if (done->f(SUCCESS, done->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_req *const req = p->head; + const struct cd_req_read *const rr = &req->u.read; + const struct cd_prv_read *const r = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + Printf("finished seeking\n"); + drv_ps1_event_disable(r->errevent); + drv_ps1_event_close(r->errevent); + p->offset = rr->offset; + return uncached_read(p); + } + else if (drv_ps1_event_test(r->errevent)) + { + Printf("failed to seek\n"); + return deliver_event(p, EIO); + } + + return 0; +} + +static int seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_read *const r = &p->u.read; + const struct cd_req_read *rr = &p->head->u.read; + const unsigned sector = rr->offset / CD_SECTOR_SZ; + const struct CdAsyncSeekL seekl = drv_ps1_cd_toseekl(sector); + const int errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, + MODE_READY, NULL); + + if (errevent == -1) + goto failure; + + *r = (const struct cd_prv_read){.errevent = errevent}; + p->sector_read = false; + drv_ps1_event_enable(errevent); + + Printf("Seeking to offset %lu\n", (unsigned long)rr->offset); + + if (!CdAsyncSeekL(&seekl)) + goto failure; + + p->next = wait_seek; + return 0; + +failure: + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int start(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_req *const req = p->head; + const struct cd_req_read *const rr = &req->u.read; + const off_t cursect = p->offset / CD_SECTOR_SZ, + tgtsect = rr->offset / CD_SECTOR_SZ; + + if (cursect != tgtsect || !p->sector_read) + return seek(); + + /* TODO: multi-sector reads, make sure cache can really be used */ + return cached_read(p); +} + +int drv_ps1_cd_read(void *const buf, const size_t n, const off_t offset, + const struct drv_event_done *const done, void *const args) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const r = malloc(sizeof *r); + + if (!r) + return -1; + + *r = (const struct cd_req) + { + .f = start, + .done = *done, + .u.read = + { + .offset = offset, + .buf = buf, + .n = n + } + }; + + if (!p->head) + p->head = r; + else + p->tail->next = r; + + p->tail = r; + Printf("Added %p {.buf=%p, .n=%lu} to read reqs\n", (void *)p->tail, buf, + (unsigned long)n); + return 0; +} diff --git a/src/drv/ps1/cd/src/send.c b/src/drv/ps1/cd/src/send.c new file mode 100644 index 0000000..01aa5cb --- /dev/null +++ b/src/drv/ps1/cd/src/send.c @@ -0,0 +1,101 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cd/regs.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/event.h> +#include <stdint.h> + +static int wait_event(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (drv_ps1_event_test(p->event)) + { + const union cd_prv_getstat g = {.status = CD_REG_RSP->rsp}; + + p->available = !g.bits.shell_open; + } + + return 0; +} + +static void send_params(const struct cd_prv *const p) +{ + static const size_t n[] = + { + [CMD_SETLOC] = sizeof (struct cmd_setloc) + }; + + const uint8_t cmd = p->cmd.cmd, index = CD_REG_STATUS->index; + + if (cmd < sizeof n / sizeof *n) + { + const void *const vbuf = &p->cmd.params; + const uint8_t *buf = vbuf; + + CD_REG_STATUS->index = 0; + + for (size_t i = 0; i < n[cmd]; i++) + CD_REG_PARAM->param = *buf++; + + CD_REG_STATUS->index = index; + } +} + +static int send_data(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (CD_REG_STATUS->BUSYSTS) + return 0; + + send_params(p); + CD_REG_CMD->cmd = p->cmd.cmd; + p->next = wait_event; + return 0; +} + +static int reset_param_fifo(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (CD_REG_STATUS->BUSYSTS) + return 0; + + CD_REG_IF->w.ack = 0x1f; + CD_REG_STATUS->index = 1; + CD_REG_IF->w.CLRPRM = 1; + p->next = send_data; + return 0; +} + +int drv_ps1_cd_send(const struct cmd *const cmd) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (drv_ps1_cd_ensure_event(p)) + return -1; + + p->cmd = *cmd; + p->next = reset_param_fifo; + return 0; +} diff --git a/src/drv/ps1/cd/src/toseekl.c b/src/drv/ps1/cd/src/toseekl.c new file mode 100644 index 0000000..ee776c9 --- /dev/null +++ b/src/drv/ps1/cd/src/toseekl.c @@ -0,0 +1,54 @@ +/* Original functions from psn00bsdk, commit 5d9aa2d3 + * + * itob extracted from libpsn00b/include/psxcd.h + * CdIntToPos (here renamed to drv_ps1_cd_toseekl) extracted from + * libpsn00b/psxcd/misc.c + * + * Original copyright notice: + * + * PSn00bSDK CD-ROM library + * (C) 2020-2023 Lameguy64, spicyjpeg - MPL licensed + */ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/bios.h> + +/** + * @brief Translates a decimal value to BCD. + * + * @details Translates a decimal integer in 0-99 range into a BCD format value. + */ +static unsigned itob(const unsigned i) +{ + return ((i / 10) * 16) | (i % 10); +} + +struct CdAsyncSeekL drv_ps1_cd_toseekl(unsigned i) +{ + i += 150; + + return (const struct CdAsyncSeekL) + { + .minutes = itob(i / (75 * 60)), + .seconds = itob((i / 75) % 60), + .frames = itob(i % 75) + }; +} diff --git a/src/drv/ps1/cd/src/update.c b/src/drv/ps1/cd/src/update.c new file mode 100644 index 0000000..148dd87 --- /dev/null +++ b/src/drv/ps1/cd/src/update.c @@ -0,0 +1,47 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/cd/routines.h> +#include <drv/event.h> +#include <stdbool.h> + +int drv_ps1_cd_update(struct drv_ps1_cd *const cd) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (p->next()) + return -1; + else if (p->available ^ cd->available) + { + const struct drv_event *const ev = &cd->ev; + static const struct drv_event_ops ops = + { + .read = drv_ps1_cd_read, + .write = drv_ps1_cd_write + }; + + if (ev->status("cd0", &ops, p->available, 0440, ev->args)) + return -1; + + cd->available = p->available; + } + + return 0; +} diff --git a/src/drv/ps1/cd/src/virt/CMakeLists.txt b/src/drv/ps1/cd/src/virt/CMakeLists.txt new file mode 100644 index 0000000..0e5bd1b --- /dev/null +++ b/src/drv/ps1/cd/src/virt/CMakeLists.txt @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_cd PRIVATE + # free.c + init.c + # next.c + # prv.c + # read.c + # update.c + # write.c +) diff --git a/src/drv/ps1/cd/src/virt/init.c b/src/drv/ps1/cd/src/virt/init.c new file mode 100644 index 0000000..204f7fa --- /dev/null +++ b/src/drv/ps1/cd/src/virt/init.c @@ -0,0 +1,41 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/virt/types.h> +#include <drv/event.h> +#include <stddef.h> +#include <stdlib.h> + +struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *const ev) +{ + struct drv_ps1_cd *const ret = malloc(sizeof *ret); + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (!ret) + return NULL; + else if (!p->next && drv_ps1_cd_getstat()) + goto failure; + + *ret = (const struct drv_ps1_cd){.ev = *ev}; + return ret; + +failure: + free(ret); + return NULL; +} diff --git a/src/drv/ps1/cd/src/write.c b/src/drv/ps1/cd/src/write.c new file mode 100644 index 0000000..ba47993 --- /dev/null +++ b/src/drv/ps1/cd/src/write.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/event.h> +#include <errno.h> + +int drv_ps1_cd_write(const void *const buf, const size_t n, + const struct drv_event_done *const done, void *const args) +{ + /* TODO: write event callback returning EROFS */ + errno = EROFS; + return -1; +} diff --git a/src/drv/ps1/cpu/CMakeLists.txt b/src/drv/ps1/cpu/CMakeLists.txt new file mode 100644 index 0000000..dafb0cd --- /dev/null +++ b/src/drv/ps1/cpu/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_cpu INTERFACE) +target_include_directories(drv_ps1_cpu INTERFACE include) diff --git a/src/drv/ps1/cpu/include/drv/ps1/cpu.h b/src/drv/ps1/cpu/include/drv/ps1/cpu.h new file mode 100644 index 0000000..d951f48 --- /dev/null +++ b/src/drv/ps1/cpu/include/drv/ps1/cpu.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CPU_H +#define DRV_PS1_CPU_H + +#define DRV_PS1_CPU_F 33868800ul + +#endif diff --git a/src/drv/ps1/dma/CMakeLists.txt b/src/drv/ps1/dma/CMakeLists.txt new file mode 100644 index 0000000..0daeee9 --- /dev/null +++ b/src/drv/ps1/dma/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_dma INTERFACE) +target_include_directories(drv_ps1_dma INTERFACE include) diff --git a/src/drv/ps1/dma/include/drv/ps1/dma.h b/src/drv/ps1/dma/include/drv/ps1/dma.h new file mode 100644 index 0000000..9538c3b --- /dev/null +++ b/src/drv/ps1/dma/include/drv/ps1/dma.h @@ -0,0 +1,97 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_DMA_H +#define DRV_PS1_DMA_H + +#include <stdint.h> + +union dpcr +{ + struct + { + uint32_t mdecin_prio :3, mdecin_en :1, mdecout_prio :3, mdecout_en :1, + gpu_prio :3, gpu_en :1, cdrom_prio :3, cdrom_en :1, spu_prio :3, + spu_en :1, pio_prio :3, pio_en :1, otc_prio :3, otc_en :1, :4; + } bits; + + uint32_t mask; +}; + +union madr +{ + struct + { + uint32_t addr :24, :8; + } bits; + + uint32_t mask; +}; + +union bcr +{ + struct + { + uint16_t nwords, reserved; + } syncmode_0; + + struct + { + uint16_t blocksz, nblocks; + } syncmode_1; + + struct + { + uint32_t reserved; + } syncmode_2; + + uint32_t mask; +}; + +enum +{ + CHCR_DIR_TO_RAM, + CHCR_DIR_FROM_RAM +}; + +enum +{ + CHCR_SYNC_MODE_ALL, + CHCR_SYNC_MODE_BLOCKS, + CHCR_SYNC_MODE_LINKED_LIST +}; + +union chcr +{ + struct + { + uint32_t dir :1, memstep :1, :6, chopping :1, sync_mode :2, :5, + chopping_dma_window_sz :3, :1, chopping_cpu_window_sz :3, :1, + start_busy :1, :3, start_trigger :1, :3; + } bits; + + uint32_t mask; +}; + +#define DMA_BASE(dma, off) ((dma) * 0x10 + 0x1f801080 + (off)) +#define D2_MADR ((volatile union madr *)DMA_BASE(2, 0)) +#define D2_BCR ((volatile union bcr *)DMA_BASE(2, 4)) +#define D2_CHCR ((volatile union chcr *)DMA_BASE(2, 8)) +#define DPCR ((volatile union dpcr *)0x1f8010f0) + +#endif diff --git a/src/drv/ps1/event/CMakeLists.txt b/src/drv/ps1/event/CMakeLists.txt new file mode 100644 index 0000000..2b00aaa --- /dev/null +++ b/src/drv/ps1/event/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_event) +add_subdirectory(src) +target_include_directories(drv_ps1_event PUBLIC include) +target_link_libraries(drv_ps1_event PUBLIC c drv_ps1_bios) diff --git a/src/drv/ps1/event/include/drv/ps1/event.h b/src/drv/ps1/event/include/drv/ps1/event.h new file mode 100644 index 0000000..2c34b02 --- /dev/null +++ b/src/drv/ps1/event/include/drv/ps1/event.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_EVENT_H +#define DRV_PS1_EVENT_H + +#include <drv/ps1/bios.h> + +int drv_ps1_event_open(int class, int spec, int mode, int (*f)(void)); +int drv_ps1_event_test(int event); +int drv_ps1_event_wait(int event); +int drv_ps1_event_enable(int event); +int drv_ps1_event_disable(int event); +int drv_ps1_event_close(int event); + +#endif diff --git a/src/drv/ps1/event/src/CMakeLists.txt b/src/drv/ps1/event/src/CMakeLists.txt new file mode 100644 index 0000000..e741edc --- /dev/null +++ b/src/drv/ps1/event/src/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_event PRIVATE + close.c + disable.c + enable.c + open.c + test.c +) diff --git a/src/drv/ps1/event/src/close.c b/src/drv/ps1/event/src/close.c new file mode 100644 index 0000000..01c9a33 --- /dev/null +++ b/src/drv/ps1/event/src/close.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_close(const int event) +{ + return CloseEvent(event); +} diff --git a/src/drv/ps1/event/src/disable.c b/src/drv/ps1/event/src/disable.c new file mode 100644 index 0000000..6d32b2b --- /dev/null +++ b/src/drv/ps1/event/src/disable.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_disable(const int event) +{ + return DisableEvent(event); +} diff --git a/src/drv/ps1/event/src/enable.c b/src/drv/ps1/event/src/enable.c new file mode 100644 index 0000000..3368ac4 --- /dev/null +++ b/src/drv/ps1/event/src/enable.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_enable(const int event) +{ + return EnableEvent(event); +} diff --git a/src/drv/ps1/event/src/open.c b/src/drv/ps1/event/src/open.c new file mode 100644 index 0000000..6bb55f1 --- /dev/null +++ b/src/drv/ps1/event/src/open.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_open(const int class, const int spec, const int mode, + int (*const f)(void)) +{ + int ret; + + EnterCriticalSection(); + ret = OpenEvent(class, spec, mode, f); + ExitCriticalSection(); + return ret; +} diff --git a/src/drv/ps1/event/src/test.c b/src/drv/ps1/event/src/test.c new file mode 100644 index 0000000..358bd8e --- /dev/null +++ b/src/drv/ps1/event/src/test.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_test(const int event) +{ + int ret; + + ret = TestEvent(event); + return ret; +} diff --git a/src/drv/ps1/gpu/CMakeLists.txt b/src/drv/ps1/gpu/CMakeLists.txt new file mode 100644 index 0000000..a86ab92 --- /dev/null +++ b/src/drv/ps1/gpu/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_gpu INTERFACE) +target_include_directories(drv_ps1_gpu INTERFACE include) diff --git a/src/drv/ps1/gpu/include/drv/ps1/gpu.h b/src/drv/ps1/gpu/include/drv/ps1/gpu.h new file mode 100644 index 0000000..1afc5f6 --- /dev/null +++ b/src/drv/ps1/gpu/include/drv/ps1/gpu.h @@ -0,0 +1,173 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_GPU_H +#define DRV_PS1_GPU_H + +#include <stdint.h> + +enum +{ + GP0_FILL_VRAM = 0x02, + GP0_TEXTRECT_VARSZ_OPAQ_RAW = 0x65, + GP0_COPY_RECT_CPU_VRAM = 0xa0, + GP0_COPY_RECT_VRAM_CPU = 0xc0, + GP0_DRAW_MODE = 0xe1, + GP0_TEX_WINDOW, + GP0_DRAW_AREA_TOP_LEFT, + GP0_DRAW_AREA_BOTTOM_RIGHT, + GP0_DRAW_OFFSET, + GP0_DRAW_MASK_BIT +}; + +enum +{ + GP1_RESET_GPU, + GP1_RESET_CMDBUF, + GP1_ACK_IRQ, + GP1_DISPLAY_ENABLE, + GP1_DMA_DIR, + GP1_START_DISPLAY_AREA, + GP1_H_DISPLAY_RANGE, + GP1_V_DISPLAY_RANGE, + GP1_DISPLAY_MODE +}; + +enum +{ + GP1_DMA_DIR_OFF, + GP1_DMA_DIR_FIFO, + GP1_DMA_DIR_CPU_TO_GP0, + GP1_DMA_DIR_GPUREAD_TO_CPU +}; + +union drv_ps1_gpu_gp0 +{ + uint32_t mask; + + struct + { + uint32_t w :16, h :16, x :16, y :16, r :8, g :8, b :8, cmd :8; + } fill_vram; + + struct + { + uint32_t :24, cmd :8; + } copy_rect; + + struct + { + uint16_t x, y; + } coord; + + struct + { + uint16_t w, h; + } size; + + struct + { + uint32_t page_x :4, page_y :1, stp :2, bpp :2, dither :1, + draw_to_display :1, tex_disable :1, xflip :1, yflip :1, :10, + cmd :8; + } draw_mode; + + struct + { + uint32_t mask_x :5, mask_y :5, off_x :5, off_y :5, :4, cmd :8; + } tex_window; + + struct + { + uint32_t x :10, y :9, :5, cmd :8; + } draw_area_tl, draw_area_br; + + struct + { + int32_t x :11, y :11, :2, cmd :8; + } offset; + + struct + { + uint32_t set :1, check :1, :22, cmd :8; + } mask_bit; +}; + +union drv_ps1_gpu_gp1 +{ + uint32_t mask; + + struct + { + uint32_t :24, cmd:8; + } reset_gpu, reset_cmdbuf, ack_irq; + + struct + { + uint32_t disable :1, :23, cmd :8; + } display; + + struct + { + uint32_t dir :2, :22, cmd :8; + } dma; + + struct + { + uint32_t x :10, y :9, :5, cmd :8; + } disparea; + + struct + { + uint32_t x1 :12, x2 :12, cmd :8; + } h_display_range; + + struct + { + uint32_t y1 :10, y2 :10, :4, cmd :8; + } v_display_range; + + struct + { + uint32_t hres :2, vres :1, vmode :1, coldepth :1, vinterlace :1, + hres2 :1, reverse :1, :16, cmd :8; + } display_mode; +}; + +union drv_ps1_gpu_stat +{ + struct + { + uint32_t x_base :4, y_base :1, stp :2, bpp :2, dither :1, + draw_to_display :1, set_mask :1, draw_pix :1, interlace :1, + reverse :1, disable :1, xres2 :1, xres1 :2, yres :1, vmode :1, + coldepth :1, vinterlace :1, display_enable :1, irq_req :1, + dma_req :1, ready_cmd :1, ready_send :1, ready_dma :1, dma_dir :2, + draw_odd :1; + } bits; + + uint32_t mask; +}; + +#define GPU_BASE 0x1f801810 +#define GPU_REG(x) (GPU_BASE + (x)) +#define GP0 ((volatile union drv_ps1_gpu_gp0 *)GPU_REG(0)) +#define GP1 ((volatile union drv_ps1_gpu_gp1 *)GPU_REG(4)) +#define GPUSTAT ((volatile const union drv_ps1_gpu_stat *)GPU_REG(4)) + +#endif diff --git a/src/drv/ps1/include/drv/ps1.h b/src/drv/ps1/include/drv/ps1.h new file mode 100644 index 0000000..7d92878 --- /dev/null +++ b/src/drv/ps1/include/drv/ps1.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_H +#define DRV_PS1_H + +#include <drv/event.h> + +struct drv_port *drv_ps1_init(const struct drv_event *ev); +int drv_ps1_update(struct drv_port *p); +void drv_ps1_free(struct drv_port *p); + +#endif diff --git a/src/drv/ps1/irq/CMakeLists.txt b/src/drv/ps1/irq/CMakeLists.txt new file mode 100644 index 0000000..8327cd5 --- /dev/null +++ b/src/drv/ps1/irq/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_irq) +add_subdirectory(src) +target_include_directories(drv_ps1_irq PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_irq PUBLIC c PRIVATE drv_ps1_bios) diff --git a/src/drv/ps1/irq/include/drv/ps1/irq.h b/src/drv/ps1/irq/include/drv/ps1/irq.h new file mode 100644 index 0000000..0d40c7f --- /dev/null +++ b/src/drv/ps1/irq/include/drv/ps1/irq.h @@ -0,0 +1,64 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_IRQ_H +#define DRV_PS1_IRQ_H + +#include <stdint.h> + +union drv_ps1_statmask +{ + struct + { + uint32_t vblank :1, gpu :1, cdrom :1, dma :1, tmr0 :1, tmr1 :1, tmr2 :1, + controller :1, sio :1, spu :1, lightpen :1, :21; + } bits; + + uint32_t mask; +}; + +#define I_BASE(x) (0x1f801070 + (x)) +#define I_STAT ((volatile union drv_ps1_statmask *)I_BASE(0)) +#define I_MASK ((volatile union drv_ps1_statmask *)I_BASE(4)) + +enum drv_ps1_irq +{ + IRQ_VBLANK, + IRQ_GPU, + IRQ_CDROM, + IRQ_DMA, + IRQ_TMR0, + IRQ_TMR1, + IRQ_TMR2, + IRQ_JOYPAD_MEMCARD, + IRQ_SIO, + IRQ_SPU, + IRQ_JOYPAD_IO +}; + +struct drv_ps1_irq_src +{ + int mask; + int (*fn)(void); + struct drv_ps1_irq_src *next; +}; + +int drv_ps1_irq_init(void); +int drv_ps1_irq_set(struct drv_ps1_irq_src *src); + +#endif diff --git a/src/drv/ps1/irq/private_include/drv/ps1/irq/routines.h b/src/drv/ps1/irq/private_include/drv/ps1/irq/routines.h new file mode 100644 index 0000000..39b7448 --- /dev/null +++ b/src/drv/ps1/irq/private_include/drv/ps1/irq/routines.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_IRQ_ROUTINES_H +#define DRV_PS1_IRQ_ROUTINES_H + +void drv_ps1_irq_handler(void); + +#endif diff --git a/src/drv/ps1/irq/private_include/drv/ps1/irq/types.h b/src/drv/ps1/irq/private_include/drv/ps1/irq/types.h new file mode 100644 index 0000000..6c5a185 --- /dev/null +++ b/src/drv/ps1/irq/private_include/drv/ps1/irq/types.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_IRQ_TYPES_H +#define DRV_PS1_IRQ_TYPES_H + +#include <drv/ps1/irq.h> + +extern struct drv_ps1_irq_src *drv_ps1_irq_head; + +#endif diff --git a/src/drv/ps1/irq/src/CMakeLists.txt b/src/drv/ps1/irq/src/CMakeLists.txt new file mode 100644 index 0000000..3823f4e --- /dev/null +++ b/src/drv/ps1/irq/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_irq PRIVATE + handler.c + head.c + init.c + set.c +) diff --git a/src/drv/ps1/irq/src/handler.c b/src/drv/ps1/irq/src/handler.c new file mode 100644 index 0000000..0861852 --- /dev/null +++ b/src/drv/ps1/irq/src/handler.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/irq.h> +#include <drv/ps1/irq/routines.h> +#include <drv/ps1/irq/types.h> +#include <drv/ps1/bios.h> +#include <stddef.h> + +void drv_ps1_irq_handler(void) +{ + for (struct drv_ps1_irq_src *s = drv_ps1_irq_head; s; s = s->next) + if (I_STAT->mask & s->mask) + s->fn(); + + ReturnFromException(); +} diff --git a/src/drv/ps1/irq/src/head.c b/src/drv/ps1/irq/src/head.c new file mode 100644 index 0000000..cde1fd8 --- /dev/null +++ b/src/drv/ps1/irq/src/head.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/irq.h> +#include <drv/ps1/irq/types.h> + +struct drv_ps1_irq_src *drv_ps1_irq_head; diff --git a/src/drv/ps1/irq/src/init.c b/src/drv/ps1/irq/src/init.c new file mode 100644 index 0000000..9e92b01 --- /dev/null +++ b/src/drv/ps1/irq/src/init.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/irq.h> +#include <drv/ps1/irq/routines.h> +#include <drv/ps1/bios.h> +#include <setjmp.h> + +int drv_ps1_irq_init(void) +{ + static jmp_buf jmp; + static char stack[128]; + const int critical = EnterCriticalSection(); + + if (SaveState(jmp)) + drv_ps1_irq_handler(); + + jmp->sp = (unsigned)stack + sizeof stack - 4; + SetCustomExitFromException(jmp); + + if (critical) + ExitCriticalSection(); + + return 0; +} diff --git a/src/drv/ps1/irq/src/set.c b/src/drv/ps1/irq/src/set.c new file mode 100644 index 0000000..35c5ed0 --- /dev/null +++ b/src/drv/ps1/irq/src/set.c @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/irq.h> +#include <drv/ps1/irq/types.h> +#include <drv/ps1/bios.h> + +int drv_ps1_irq_set(struct drv_ps1_irq_src *const src) +{ + if (!drv_ps1_irq_head) + drv_ps1_irq_head = src; + else + for (struct drv_ps1_irq_src *s = drv_ps1_irq_head; s; s = s->next) + if (!s->next) + { + s->next = src; + break; + } + + return 0; +} diff --git a/src/drv/ps1/mc/CMakeLists.txt b/src/drv/ps1/mc/CMakeLists.txt new file mode 100644 index 0000000..ef232ef --- /dev/null +++ b/src/drv/ps1/mc/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_mc) +add_subdirectory(src) +target_include_directories(drv_ps1_mc PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_mc PUBLIC c drv_event) diff --git a/src/drv/ps1/mc/include/drv/ps1/mc.h b/src/drv/ps1/mc/include/drv/ps1/mc.h new file mode 100644 index 0000000..2e90776 --- /dev/null +++ b/src/drv/ps1/mc/include/drv/ps1/mc.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_MC_H +#define DRV_PS1_MC_H + +#include <drv/event.h> + +struct drv_ps1_mc *drv_ps1_mc_init(const struct drv_event *ev); +int drv_ps1_mc_update(struct drv_ps1_mc *mc); +void drv_ps1_mc_free(struct drv_ps1_mc *mc); + +#endif diff --git a/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h b/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h new file mode 100644 index 0000000..14606e5 --- /dev/null +++ b/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_MC_TYPES_H +#define DRV_PS1_MC_TYPES_H + +#include <drv/event.h> + +struct drv_ps1_mc +{ + const struct drv_event *ev; +}; + +enum +{ + MC_0, + MC_1, + + N_MC +}; + +#endif diff --git a/src/drv/ps1/mc/src/CMakeLists.txt b/src/drv/ps1/mc/src/CMakeLists.txt new file mode 100644 index 0000000..ae1378c --- /dev/null +++ b/src/drv/ps1/mc/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_mc PRIVATE + free.c + init.c + update.c +) diff --git a/src/drv/ps1/mc/src/free.c b/src/drv/ps1/mc/src/free.c new file mode 100644 index 0000000..bdf54ff --- /dev/null +++ b/src/drv/ps1/mc/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/mc.h> + +void drv_ps1_mc_free(struct drv_ps1_mc *const mc) +{ +} diff --git a/src/drv/ps1/mc/src/init.c b/src/drv/ps1/mc/src/init.c new file mode 100644 index 0000000..88be46a --- /dev/null +++ b/src/drv/ps1/mc/src/init.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/mc.h> +#include <drv/ps1/mc/types.h> +#include <drv/event.h> +#include <stddef.h> +#include <stdlib.h> + +struct drv_ps1_mc *drv_ps1_mc_init(const struct drv_event *const ev) +{ + struct drv_ps1_mc *const ret = malloc(sizeof *ret); + + if (!ret) + return NULL; + + *ret = (const struct drv_ps1_mc){.ev = ev}; + return ret; +} diff --git a/src/drv/ps1/mc/src/update.c b/src/drv/ps1/mc/src/update.c new file mode 100644 index 0000000..866bf94 --- /dev/null +++ b/src/drv/ps1/mc/src/update.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/mc.h> +#include <drv/event.h> + +int drv_ps1_mc_update(struct drv_ps1_mc *const mc) +{ + /* TODO */ + return 0; +} diff --git a/src/drv/ps1/pad/CMakeLists.txt b/src/drv/ps1/pad/CMakeLists.txt new file mode 100644 index 0000000..eb74091 --- /dev/null +++ b/src/drv/ps1/pad/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_pad) +add_subdirectory(src) +target_include_directories(drv_ps1_pad PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_pad PUBLIC c drv_event) diff --git a/src/drv/ps1/pad/include/drv/ps1/pad.h b/src/drv/ps1/pad/include/drv/ps1/pad.h new file mode 100644 index 0000000..9cc2fc6 --- /dev/null +++ b/src/drv/ps1/pad/include/drv/ps1/pad.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_PAD_H +#define DRV_PS1_PAD_H + +#include <drv/event.h> + +struct drv_ps1_pad *drv_ps1_pad_init(const struct drv_event *ev); +int drv_ps1_pad_update(struct drv_ps1_pad *pad); +void drv_ps1_pad_free(struct drv_ps1_pad *pad); + +#endif diff --git a/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h b/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h new file mode 100644 index 0000000..c164a30 --- /dev/null +++ b/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_PAD_TYPES_H +#define DRV_PS1_PAD_TYPES_H + +#include <drv/event.h> + +struct drv_ps1_pad +{ + const struct drv_event *ev; +}; + +#endif diff --git a/src/drv/ps1/pad/src/CMakeLists.txt b/src/drv/ps1/pad/src/CMakeLists.txt new file mode 100644 index 0000000..bfae1a1 --- /dev/null +++ b/src/drv/ps1/pad/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_pad PRIVATE + free.c + init.c + update.c +) diff --git a/src/drv/ps1/pad/src/free.c b/src/drv/ps1/pad/src/free.c new file mode 100644 index 0000000..1498f2d --- /dev/null +++ b/src/drv/ps1/pad/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/pad.h> + +void drv_ps1_pad_free(struct drv_ps1_pad *const pad) +{ +} diff --git a/src/drv/ps1/pad/src/init.c b/src/drv/ps1/pad/src/init.c new file mode 100644 index 0000000..8fe3ccb --- /dev/null +++ b/src/drv/ps1/pad/src/init.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/pad.h> +#include <drv/ps1/pad/types.h> +#include <drv/event.h> +#include <stddef.h> +#include <stdlib.h> + +struct drv_ps1_pad *drv_ps1_pad_init(const struct drv_event *const ev) +{ + struct drv_ps1_pad *const ret = malloc(sizeof *ret); + + if (!ret) + return NULL; + + *ret = (const struct drv_ps1_pad){.ev = ev}; + return ret; +} diff --git a/src/drv/ps1/pad/src/update.c b/src/drv/ps1/pad/src/update.c new file mode 100644 index 0000000..9c9acfe --- /dev/null +++ b/src/drv/ps1/pad/src/update.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/pad.h> +#include <drv/event.h> + +int drv_ps1_pad_update(struct drv_ps1_pad *const pad) +{ + /* TODO */ + return 0; +} diff --git a/src/drv/ps1/private_include/drv/ps1/types.h b/src/drv/ps1/private_include/drv/ps1/types.h new file mode 100644 index 0000000..35cb14e --- /dev/null +++ b/src/drv/ps1/private_include/drv/ps1/types.h @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_TYPES_H +#define DRV_PS1_TYPES_H + +#include <drv/ps1/cd.h> +#include <drv/ps1/mc.h> +#include <drv/ps1/pad.h> +#include <drv/ps1/sio.h> + +struct drv_port +{ + struct drv_ps1_mc *mc; + struct drv_ps1_cd *cd; + struct drv_ps1_pad *pad; + struct drv_ps1_sio *sio; +}; + +#endif diff --git a/src/drv/ps1/rcnt/CMakeLists.txt b/src/drv/ps1/rcnt/CMakeLists.txt new file mode 100644 index 0000000..f5b5171 --- /dev/null +++ b/src/drv/ps1/rcnt/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_rcnt) +add_subdirectory(src) +target_include_directories(drv_ps1_rcnt PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_rcnt + PUBLIC c + PRIVATE drv_ps1_bios drv_ps1_irq drv_ps1_event) diff --git a/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h b/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h new file mode 100644 index 0000000..831012c --- /dev/null +++ b/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h @@ -0,0 +1,45 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_RCNT_H +#define DRV_PS1_RCNT_H + +#include <stdint.h> + +union drv_ps1_rcnt_cfg +{ + struct + { + uint32_t sync_enable :1, sync_mode :2, reset :1, irq_tgt :1, + irq_max :1, repeat :1, pulse_toggle :1, clocksrc :2, intreq :1; + } bits; + + uint32_t word; +}; + +enum drv_ps1_rcnt +{ + DRV_PS1_RCNT0, + DRV_PS1_RCNT1, + DRV_PS1_RCNT2 +}; + +int drv_ps1_rcnt_init(enum drv_ps1_rcnt rcnt, uint16_t target, + const union drv_ps1_rcnt_cfg *cfg, int (*f)(void)); + +#endif diff --git a/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h b/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h new file mode 100644 index 0000000..a6c9750 --- /dev/null +++ b/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_RCNT_REGS_H +#define DRV_PS1_RCNT_REGS_H + +#include <drv/ps1/rcnt.h> +#include <stdint.h> + +struct rcnt_value +{ + uint32_t value :16, :16; +}; + +#define RCNT_BASE(n) (0x1f801100 + (n << 4)) +#define RCNT_REG(n, m) (RCNT_BASE(n) + m) +#define RCNT_VALUE(n) ((volatile struct rcnt_value *)RCNT_REG(n, 0)) +#define RCNT_MODE(n) ((volatile union drv_ps1_rcnt_cfg *)RCNT_REG(n, 4)) +#define RCNT_TARGET(n) ((volatile struct rcnt_value *)RCNT_REG(n, 8)) + +#endif diff --git a/src/drv/ps1/rcnt/src/CMakeLists.txt b/src/drv/ps1/rcnt/src/CMakeLists.txt new file mode 100644 index 0000000..4e8eb88 --- /dev/null +++ b/src/drv/ps1/rcnt/src/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_rcnt PRIVATE + init.c +) diff --git a/src/drv/ps1/rcnt/src/init.c b/src/drv/ps1/rcnt/src/init.c new file mode 100644 index 0000000..0c4327c --- /dev/null +++ b/src/drv/ps1/rcnt/src/init.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/rcnt.h> +#include <drv/ps1/rcnt/regs.h> +#include <drv/ps1/event.h> +#include <drv/ps1/irq.h> +#include <drv/ps1/bios.h> +#include <stddef.h> +#include <stdint.h> + +int drv_ps1_rcnt_init(const enum drv_ps1_rcnt rcnt, const uint16_t target, + const union drv_ps1_rcnt_cfg *const cfg, int (*const f)(void)) +{ + int class; + + EnterCriticalSection(); + RCNT_TARGET(rcnt)->value = target; + *RCNT_MODE(rcnt) = *cfg; + + switch (rcnt) + { + case DRV_PS1_RCNT0: + I_MASK->bits.tmr0 = 1; + class = CLASS_RTC0; + break; + case DRV_PS1_RCNT1: + I_MASK->bits.tmr1 = 1; + class = CLASS_RTC1; + break; + case DRV_PS1_RCNT2: + I_MASK->bits.tmr2 = 1; + class = CLASS_RTC2; + break; + } + + ExitCriticalSection(); + + const int event = drv_ps1_event_open(class, SPEC_INTERRUPTED, + MODE_EXECUTE, f); + + if (event == -1) + return -1; + + drv_ps1_event_enable(event); + return 0; +} diff --git a/src/drv/ps1/sio/CMakeLists.txt b/src/drv/ps1/sio/CMakeLists.txt new file mode 100644 index 0000000..f382e08 --- /dev/null +++ b/src/drv/ps1/sio/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_sio) +add_subdirectory(src) +target_include_directories(drv_ps1_sio PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_sio + PUBLIC c + PRIVATE drv drv_ps1_bios drv_ps1_cpu drv_ps1_irq) diff --git a/src/drv/ps1/sio/include/drv/ps1/sio.h b/src/drv/ps1/sio/include/drv/ps1/sio.h new file mode 100644 index 0000000..3fabadd --- /dev/null +++ b/src/drv/ps1/sio/include/drv/ps1/sio.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_SIO_H +#define DRV_PS1_SIO_H + +#include <drv/event.h> + +struct drv_ps1_sio *drv_ps1_sio_init(const struct drv_event *ev); +int drv_ps1_sio_update(struct drv_ps1_sio *sio); +void drv_ps1_sio_free(struct drv_ps1_sio *sio); + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/ops.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/ops.h new file mode 100644 index 0000000..a481fa9 --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/ops.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_SIO_OPS_H +#define DRV_PS1_SIO_OPS_H + +#include <drv/event.h> +#include <sys/types.h> + +int drv_ps1_sio_read(void *buf, size_t n, off_t offset, + const struct drv_event_done *done, void *args); +int drv_ps1_sio_read_nb(void *buf, size_t n, void *args); +int drv_ps1_sio_write(const void *buf, size_t n, + const struct drv_event_done *done, void *args); + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/regs.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/regs.h new file mode 100644 index 0000000..16b2bca --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/regs.h @@ -0,0 +1,136 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_SIO_REGS_H +#define DRV_PS1_SIO_REGS_H + +#include <stdint.h> + +struct sio_tx_data +{ + uint32_t value :8, :24; +}; + +struct sio_rx_data +{ + uint8_t values[4]; +}; + +union sio_stat +{ + struct + { + uint32_t + tx_ready_started :1, + rx_fifo_not_empty :1, + tx_ready_finished :1, + rx_parity_error :1, + rx_fifo_overrun :1, + rx_bad_stp :1, + rx_inverted :1, + dsr :1, + cts :1, + irqreq :1, + :1, + baudrate :15, :6; + } bits; + + uint32_t mask; +}; + +union sio_mode +{ + struct + { + uint16_t + baudrate_mul :2, + len :2, + parity_en :1, + parity_odd :1, + stplen :2, + :8; + } bits; + + uint16_t mask; +}; + +union sio_ctrl +{ + struct + { + uint16_t + tx_en :1, + dtr :1, + rx_en :1, + tx_invert :1, + ack :1, + rts :1, + reset :1, + :1, + rx_int_mode :2, + tx_int_en :1, + rx_int_en :1, + dsr_int_en :1, + :3; + } bits; + + uint16_t mask; +}; + +enum +{ + SIO_CTRL_RX_INT_1, + SIO_CTRL_RX_INT_2, + SIO_CTRL_RX_INT_3, + SIO_CTRL_RX_INT_4 +}; + +enum +{ + SIO_MODE_FACTOR_STOP, + SIO_MODE_FACTOR_MUL1, + SIO_MODE_FACTOR_MUL16, + SIO_MODE_FACTOR_MUL64 +}; + +enum +{ + SIO_MODE_LEN_5, + SIO_MODE_LEN_6, + SIO_MODE_LEN_7, + SIO_MODE_LEN_8 +}; + +enum +{ + SIO_MODE_STP_RESERVED, + SIO_MODE_STP_1, + SIO_MODE_STP_1_5, + SIO_MODE_STP_2, +}; + +#define SIO_BASE 0x1f801050 +#define SIO_REG(n) (SIO_BASE + n) +#define SIO_TX_DATA ((volatile struct sio_tx_data *)SIO_REG(0)) +#define SIO_RX_DATA ((const volatile struct sio_rx_data *)SIO_REG(0)) +#define SIO_STAT ((const volatile union sio_stat *)SIO_REG(4)) +#define SIO_MODE ((volatile union sio_mode *)SIO_REG(8)) +#define SIO_CTRL ((volatile union sio_ctrl *)SIO_REG(10)) +#define SIO_BAUD (*(volatile uint16_t *)SIO_REG(14)) + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/routines.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/routines.h new file mode 100644 index 0000000..f5b97da --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/routines.h @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_SIO_ROUTINES_H +#define DRV_PS1_SIO_ROUTINES_H + +#include <drv/ps1/sio/types.h> + +int drv_ps1_sio_irq(void); +int drv_ps1_sio_next(struct sio_fifo *f); + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/types.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/types.h new file mode 100644 index 0000000..87dd412 --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/types.h @@ -0,0 +1,65 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_SIO_TYPES_H +#define DRV_PS1_SIO_TYPES_H + +#include <drv/event.h> +#include <stdbool.h> + +struct sio_req +{ + union + { + struct sio_req_r + { + void *buf; + size_t n; + } r; + + struct sio_req_w + { + const void *buf; + size_t n; + } w; + } u; + + int (*f)(void); + struct drv_event_done done; + struct sio_req *next; +}; + +struct sio_fifo +{ + char buf[192]; + size_t proc, pend; + struct sio_req *head, *tail; + int (*next)(void); +}; + +struct drv_ps1_sio +{ + bool init; + int event; + struct sio_fifo rx, tx; + struct drv_event ev; +}; + +extern struct drv_ps1_sio drv_ps1_sio; + +#endif diff --git a/src/drv/ps1/sio/src/CMakeLists.txt b/src/drv/ps1/sio/src/CMakeLists.txt new file mode 100644 index 0000000..1bcf5cf --- /dev/null +++ b/src/drv/ps1/sio/src/CMakeLists.txt @@ -0,0 +1,29 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_sio PRIVATE + free.c + globals.c + init.c + irq.c + next.c + read.c + read_nb.c + update.c + write.c +) + +target_link_libraries(drv_ps1_sio PRIVATE kprintf) diff --git a/src/drv/ps1/sio/src/free.c b/src/drv/ps1/sio/src/free.c new file mode 100644 index 0000000..5c506d0 --- /dev/null +++ b/src/drv/ps1/sio/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio.h> + +void drv_ps1_sio_free(struct drv_ps1_sio *const sio) +{ +} diff --git a/src/drv/ps1/sio/src/globals.c b/src/drv/ps1/sio/src/globals.c new file mode 100644 index 0000000..35c72b8 --- /dev/null +++ b/src/drv/ps1/sio/src/globals.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio/types.h> + +struct drv_ps1_sio drv_ps1_sio; diff --git a/src/drv/ps1/sio/src/init.c b/src/drv/ps1/sio/src/init.c new file mode 100644 index 0000000..6bf44fc --- /dev/null +++ b/src/drv/ps1/sio/src/init.c @@ -0,0 +1,70 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio.h> +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cpu.h> +#include <drv/ps1/irq.h> +#include <drv/event.h> + +struct drv_ps1_sio *drv_ps1_sio_init(const struct drv_event *const ev) +{ + const unsigned long baudrate = 115200ul; + + SIO_CTRL->bits.reset = 1; + SIO_BAUD = DRV_PS1_CPU_F / (16 * baudrate); + SIO_MODE->mask = (const union sio_mode) + { + .bits = + { + .baudrate_mul = SIO_MODE_FACTOR_MUL16, + .stplen = SIO_MODE_STP_1, + .len = SIO_MODE_LEN_8 + } + }.mask; + + SIO_CTRL->mask = (const union sio_ctrl) + { + .bits = + { + .rx_int_mode = SIO_CTRL_RX_INT_1, + .rx_int_en = 1, + .tx_en = 1, + .rx_en = 1, + .rts = 1, + .dtr = 1 + } + }.mask; + + static struct drv_ps1_irq_src src = + { + .mask = 1 << IRQ_SIO, + .fn = drv_ps1_sio_irq + }; + + if (drv_ps1_irq_set(&src)) + return NULL; + + I_MASK->bits.sio = 1; + drv_ps1_sio.ev = *ev; + return &drv_ps1_sio; +} diff --git a/src/drv/ps1/sio/src/irq.c b/src/drv/ps1/sio/src/irq.c new file mode 100644 index 0000000..5a19d83 --- /dev/null +++ b/src/drv/ps1/sio/src/irq.c @@ -0,0 +1,71 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio.h> +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cpu.h> +#include <drv/ps1/irq.h> +#include <drv/event.h> + +int irq_sio_overrun; + +static int read_rx(struct sio_fifo *const f) +{ + const unsigned char v = *SIO_RX_DATA->values; + size_t n = f->pend + 1; + + if (n >= sizeof f->buf) + n = 0; + + if (n == f->proc) + { + irq_sio_overrun = 1; + return -1; + } + + f->buf[f->pend = n] = v; + return 0; +} + +volatile unsigned sio_read; +volatile int sw_overrun; + +int drv_ps1_sio_irq(void) +{ + SIO_CTRL->bits.rts = 0; + + while (SIO_STAT->bits.rx_fifo_not_empty) + { + if (read_rx(&drv_ps1_sio.rx)) + { + sw_overrun = 1; + break; + } + + sio_read++; + } + + SIO_CTRL->bits.rts = 1; + I_STAT->bits.sio = 0; + SIO_CTRL->bits.ack = 1; + return 0; +} diff --git a/src/drv/ps1/sio/src/next.c b/src/drv/ps1/sio/src/next.c new file mode 100644 index 0000000..4c330ab --- /dev/null +++ b/src/drv/ps1/sio/src/next.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <stddef.h> +#include <stdlib.h> + +int drv_ps1_sio_next(struct sio_fifo *const f) +{ + struct sio_req *const next = f->head->next; + + free(f->head); + + f->next = next ? next->f : NULL; + f->head = next; + return 0; +} diff --git a/src/drv/ps1/sio/src/read.c b/src/drv/ps1/sio/src/read.c new file mode 100644 index 0000000..e13ad29 --- /dev/null +++ b/src/drv/ps1/sio/src/read.c @@ -0,0 +1,125 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/irq.h> +#include <drv/event.h> +#include <kprintf.h> +#include <sys/types.h> +#include <errno.h> +#include <stdlib.h> + +static int load(void); + +static int check(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + struct sio_req *const req = f->head; + struct sio_req_r *const r = &req->u.r; + + if (!r->n) + { + const struct drv_event_done *const d = &req->done; + + if (d->f && d->f(SUCCESS, d->args)) + return -1; + + return drv_ps1_sio_next(f); + } + + f->next = load; + return 0; +} + +static void read_fifo(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->rx; + struct sio_req *const req = f->head; + struct sio_req_r *const r = &req->u.r; + char *p = r->buf; + + I_MASK->bits.sio = 0; + SIO_CTRL->bits.rts = 0; + + while (r->n) + { + if (f->pend == f->proc) + break; + + size_t n = f->proc + 1; + + if (n >= sizeof f->buf) + n = 0; + + *p++ = f->buf[f->proc = n]; + r->buf = p; + r->n--; + } + + SIO_CTRL->bits.rts = 1; + I_MASK->bits.sio = 1; +} + +static int load(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + struct sio_req_r *const r = &f->head->u.r; + + read_fifo(s); + + if (!r->n) + f->next = check; + + return 0; +} + +int drv_ps1_sio_read(void *const buf, const size_t n, const off_t offset, + const struct drv_event_done *const done, void *const args) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + struct sio_req *const req = malloc(sizeof *req); + + if (!req) + return -1; + + *req = (const struct sio_req) + { + .f = load, + .done = *done, + .u.r = + { + .buf = buf, + .n = n + } + }; + + if (!f->head) + f->head = req; + else + f->tail->next = req; + + f->tail = req; + return 0; +} diff --git a/src/drv/ps1/sio/src/read_nb.c b/src/drv/ps1/sio/src/read_nb.c new file mode 100644 index 0000000..755c5cf --- /dev/null +++ b/src/drv/ps1/sio/src/read_nb.c @@ -0,0 +1,61 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/irq.h> +#include <drv/ps1/bios.h> +#include <drv/event.h> +#include <kprintf.h> +#include <sys/types.h> + +static int read_fifo(char *buf, size_t n) +{ + int ret = 0; + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + + I_MASK->bits.sio = 0; + SIO_CTRL->bits.rts = 0; + + while (n) + { + if (f->pend == f->proc) + break; + + size_t m = f->proc + 1; + + if (m >= sizeof f->buf) + m = 0; + + *buf++ = f->buf[f->proc = m]; + n--; + ret++; + } + + SIO_CTRL->bits.rts = 1; + I_MASK->bits.sio = 1; + return ret; +} + +int drv_ps1_sio_read_nb(void *const buf, const size_t n, void *const args) +{ + return read_fifo(buf, n); +} diff --git a/src/drv/ps1/sio/src/update.c b/src/drv/ps1/sio/src/update.c new file mode 100644 index 0000000..eac875c --- /dev/null +++ b/src/drv/ps1/sio/src/update.c @@ -0,0 +1,98 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio.h> +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/event.h> +#include <kprintf.h> +#include <stddef.h> +#include <stdbool.h> + +static int init(struct drv_ps1_sio *const s) +{ + if (s->init) + return 0; + + const struct drv_event *const ev = &s->ev; + static const struct drv_event_ops ops = + { + .read = drv_ps1_sio_read, + .read_nb = drv_ps1_sio_read_nb, + .write = drv_ps1_sio_write + }; + + if (ev->status("ttyS0", &ops, true, 0660, ev->args)) + return -1; + + s->init = true; + return 0; +} + +static int rx(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->rx; + + if (f->next) + return f->next(); + else if (f->head) + f->next = f->head->f; + + return 0; +} + +static void write_tx(struct sio_fifo *const f) +{ + if (f->proc == f->pend) + return; + + size_t n = f->proc + 1; + + if (n >= sizeof f->buf) + n = 0; + + SIO_TX_DATA->value = f->buf[f->proc = n]; +} + +static int tx(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->tx; + + if (SIO_STAT->bits.tx_ready_started) + write_tx(f); + + if (f->next) + return f->next(); + else if (f->head) + f->next = f->head->f; + + return 0; +} + +int drv_ps1_sio_update(struct drv_ps1_sio *const s) +{ + if (SIO_STAT->bits.rx_fifo_overrun) + SIO_CTRL->bits.ack = 1; + + if (init(s) || rx(s) || tx(s)) + return -1; + + return 0; +} diff --git a/src/drv/ps1/sio/src/write.c b/src/drv/ps1/sio/src/write.c new file mode 100644 index 0000000..942456f --- /dev/null +++ b/src/drv/ps1/sio/src/write.c @@ -0,0 +1,117 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/event.h> +#include <kprintf.h> +#include <sys/types.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> + +static int store(void); + +static void write_fifo(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->tx; + struct sio_req *const r = f->head; + struct sio_req_w *const w = &r->u.w; + const char *p = w->buf; + + while (w->n) + { + size_t n = f->pend + 1; + + if (n >= sizeof f->buf) + n = 0; + else if (n == f->proc) + break; + + f->buf[f->pend = n] = *p++; + w->buf = p; + w->n--; + } +} + +static int check(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->tx; + struct sio_req *const r = f->head; + struct sio_req_w *const w = &r->u.w; + + if (!w->n) + { + const struct drv_event_done *const d = &r->done; + + if (d->f && d->f(SUCCESS, d->args)) + return -1; + + return drv_ps1_sio_next(f); + } + + f->next = store; + return 0; +} + +static int store(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->tx; + struct sio_req_w *const w = &f->head->u.w; + + write_fifo(s); + + if (!w->n) + f->next = check; + + return 0; +} + +int drv_ps1_sio_write(const void *const buf, const size_t n, + const struct drv_event_done *const done, void *const args) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->tx; + struct sio_req *const req = malloc(sizeof *req); + + if (!req) + return -1; + + *req = (const struct sio_req) + { + .f = store, + .done = *done, + .u.w = + { + .buf = buf, + .n = n + } + }; + + if (!f->head) + f->head = req; + else + f->tail->next = req; + + f->tail = req; + return 0; +} diff --git a/src/drv/ps1/src/CMakeLists.txt b/src/drv/ps1/src/CMakeLists.txt new file mode 100644 index 0000000..34042e3 --- /dev/null +++ b/src/drv/ps1/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1 PRIVATE + free.c + init.c + update.c +) diff --git a/src/drv/ps1/src/free.c b/src/drv/ps1/src/free.c new file mode 100644 index 0000000..62be1b1 --- /dev/null +++ b/src/drv/ps1/src/free.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1.h> +#include <drv/ps1/types.h> +#include <drv/ps1/cd.h> +#include <drv/ps1/mc.h> +#include <drv/ps1/pad.h> +#include <drv/ps1/sio.h> + +void drv_ps1_free(struct drv_port *const p) +{ + drv_ps1_mc_free(p->mc); + drv_ps1_cd_free(p->cd); + drv_ps1_pad_free(p->pad); + drv_ps1_sio_free(p->sio); +} diff --git a/src/drv/ps1/src/init.c b/src/drv/ps1/src/init.c new file mode 100644 index 0000000..8ee92a6 --- /dev/null +++ b/src/drv/ps1/src/init.c @@ -0,0 +1,59 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1.h> +#include <drv/ps1/types.h> +#include <drv/ps1/cd.h> +#include <drv/ps1/mc.h> +#include <drv/ps1/pad.h> +#include <drv/ps1/sio.h> +#include <stdlib.h> + +struct drv_port *drv_ps1_init(const struct drv_event *const ev) +{ + struct drv_port *ret = NULL; + struct drv_ps1_mc *mc = NULL; + struct drv_ps1_cd *cd = NULL; + struct drv_ps1_pad *pad = NULL; + struct drv_ps1_sio *sio = NULL; + + if (!(mc = drv_ps1_mc_init(ev)) + || !(cd = drv_ps1_cd_init(ev)) + || !(pad = drv_ps1_pad_init(ev)) + || !(sio = drv_ps1_sio_init(ev)) + || !(ret = malloc(sizeof *ret))) + goto failure; + + *ret = (const struct drv_port) + { + .mc = mc, + .cd = cd, + .pad = pad, + .sio = sio + }; + + return ret; + +failure: + drv_ps1_mc_free(mc); + drv_ps1_cd_free(cd); + drv_ps1_pad_free(pad); + drv_ps1_sio_free(sio); + free(mc); + return NULL; +} diff --git a/src/drv/ps1/src/update.c b/src/drv/ps1/src/update.c new file mode 100644 index 0000000..49b22bb --- /dev/null +++ b/src/drv/ps1/src/update.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1.h> +#include <drv/ps1/types.h> +#include <drv/ps1/cd.h> +#include <drv/ps1/mc.h> +#include <drv/ps1/pad.h> +#include <drv/ps1/sio.h> + +int drv_ps1_update(struct drv_port *const p) +{ + if (drv_ps1_mc_update(p->mc) + || drv_ps1_cd_update(p->cd) + || drv_ps1_pad_update(p->pad) + || drv_ps1_sio_update(p->sio)) + return -1; + + return 0; +} diff --git a/src/drv/ps1/time/CMakeLists.txt b/src/drv/ps1/time/CMakeLists.txt new file mode 100644 index 0000000..93c0143 --- /dev/null +++ b/src/drv/ps1/time/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_time) +add_subdirectory(src) +target_include_directories(drv_ps1_time PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_time + PUBLIC c + PRIVATE drv drv_ps1_bios drv_ps1_irq drv_ps1_rcnt) diff --git a/src/drv/ps1/time/include/drv/ps1/time.h b/src/drv/ps1/time/include/drv/ps1/time.h new file mode 100644 index 0000000..f644b59 --- /dev/null +++ b/src/drv/ps1/time/include/drv/ps1/time.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_TIME_H +#define DRV_PS1_TIME_H + +int drv_ps1_time_tick(void); + +#endif diff --git a/src/drv/ps1/time/private_include/drv/ps1/time/types.h b/src/drv/ps1/time/private_include/drv/ps1/time/types.h new file mode 100644 index 0000000..2e673fb --- /dev/null +++ b/src/drv/ps1/time/private_include/drv/ps1/time/types.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_TIME_TYPES_H +#define DRV_PS1_TIME_TYPES_H + +#include <time.h> + +extern volatile struct timespec drv_ps1_time; + +#endif diff --git a/src/drv/ps1/time/src/CMakeLists.txt b/src/drv/ps1/time/src/CMakeLists.txt new file mode 100644 index 0000000..d8ebf38 --- /dev/null +++ b/src/drv/ps1/time/src/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_time PRIVATE + gettime.c + getres.c + globals.c + settime.c + tick.c +) diff --git a/src/drv/ps1/time/src/getres.c b/src/drv/ps1/time/src/getres.c new file mode 100644 index 0000000..de69ff5 --- /dev/null +++ b/src/drv/ps1/time/src/getres.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/time.h> +#include <errno.h> +#include <time.h> + +int drv_time_getres(const clockid_t id, struct timespec *const ts) +{ + if (id != CLOCK_REALTIME) + { + errno = EINVAL; + return -1; + } + else if (ts) + *ts = (const struct timespec){.tv_nsec = 1000000}; + + return 0; +} diff --git a/src/drv/ps1/time/src/gettime.c b/src/drv/ps1/time/src/gettime.c new file mode 100644 index 0000000..0fdbfea --- /dev/null +++ b/src/drv/ps1/time/src/gettime.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/time.h> +#include <drv/ps1/time/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/irq.h> +#include <errno.h> +#include <time.h> + +int drv_time_gettime(const clockid_t id, struct timespec *const ts) +{ + if (id != CLOCK_REALTIME) + { + errno = EINVAL; + return -1; + } + + I_MASK->bits.tmr2 = 0; + *ts = drv_ps1_time; + I_MASK->bits.tmr2 = 1; + return 0; +} diff --git a/src/drv/ps1/time/src/globals.c b/src/drv/ps1/time/src/globals.c new file mode 100644 index 0000000..2f53665 --- /dev/null +++ b/src/drv/ps1/time/src/globals.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/time/types.h> +#include <time.h> + +volatile struct timespec drv_ps1_time; diff --git a/src/drv/ps1/time/src/settime.c b/src/drv/ps1/time/src/settime.c new file mode 100644 index 0000000..f2ac5fe --- /dev/null +++ b/src/drv/ps1/time/src/settime.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/time.h> +#include <drv/ps1/time/types.h> +#include <drv/ps1/bios.h> +#include <errno.h> +#include <time.h> + +int drv_time_settime(const clockid_t id, const struct timespec *const ts) +{ + if (id != CLOCK_REALTIME) + { + errno = EINVAL; + return -1; + } + + EnterCriticalSection(); + drv_ps1_time = *ts; + ExitCriticalSection(); + return 0; +} diff --git a/src/drv/ps1/time/src/tick.c b/src/drv/ps1/time/src/tick.c new file mode 100644 index 0000000..494d8ed --- /dev/null +++ b/src/drv/ps1/time/src/tick.c @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/time.h> +#include <drv/ps1/time/types.h> +#include <drv/ps1/irq.h> +#include <time.h> + +int drv_ps1_time_tick(void) +{ + int ret = 0; + struct timespec ts; + volatile struct timespec *const t = &drv_ps1_time; + + if (clock_getres(CLOCK_REALTIME, &ts)) + ret = -1; + else if (t->tv_nsec >= 1000000000 - ts.tv_nsec) + { + t->tv_sec++; + t->tv_nsec = 0; + } + else + t->tv_nsec += ts.tv_nsec; + + I_STAT->bits.tmr2 = 0; + return ret; +} diff --git a/src/drv/src/CMakeLists.txt b/src/drv/src/CMakeLists.txt new file mode 100644 index 0000000..e567c1c --- /dev/null +++ b/src/drv/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv PRIVATE + free.c + init.c + tree.c + update.c +) diff --git a/src/drv/src/free.c b/src/drv/src/free.c new file mode 100644 index 0000000..2c324c0 --- /dev/null +++ b/src/drv/src/free.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/drv.h> +#include <drv/tree.h> +#include <drv/types.h> +#include <stdlib.h> + +void drv_free(struct drv *const d) +{ + if (d) + for (size_t i = 0; i < d->n; i++) + drv_tree_free[i](d->ports[i]); + + free(d); +} diff --git a/src/drv/src/init.c b/src/drv/src/init.c new file mode 100644 index 0000000..4b89f15 --- /dev/null +++ b/src/drv/src/init.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/drv.h> +#include <drv/types.h> +#include <drv/tree.h> +#include <drv/port.h> +#include <stddef.h> +#include <stdlib.h> + +struct drv *drv_init(const struct drv_event *const ev) +{ + size_t init = 0; + struct drv *const ret = malloc(sizeof *ret); + struct drv_port **const ports = malloc(drv_tree_n * sizeof *ports); + + if (!ports || !ret) + goto failure; + + for (size_t i = 0; i < drv_tree_n; i++, init++) + { + struct drv_port *const p = drv_tree_init[i](ev); + + if (!p) + goto failure; + + ports[i] = p; + } + + *ret = (const struct drv) + { + .ports = ports, + .n = drv_tree_n + }; + + return ret; + +failure: + + if (ports) + for (size_t i = 0; i < init; i++) + drv_tree_free[i](ports[i]); + + free(ports); + free(ret); + return NULL; +} diff --git a/src/drv/src/tree.c b/src/drv/src/tree.c new file mode 100644 index 0000000..d52df3d --- /dev/null +++ b/src/drv/src/tree.c @@ -0,0 +1,51 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/drv.h> +#include <drv/tree.h> +#include <drv/tty.h> +#include <drv/port.h> +#include <stddef.h> + +struct drv_port *(*const drv_tree_init[])(const struct drv_event *) = +{ +#if DRV_PS1 + drv_ps1_init, +#endif + drv_tty_init +}; + +enum {N = sizeof drv_tree_init / sizeof *drv_tree_init}; + +int (*const drv_tree_update[N])(struct drv_port *) = +{ +#if DRV_PS1 + drv_ps1_update, +#endif + drv_tty_update +}; + +void (*const drv_tree_free[N])(struct drv_port *) = +{ +#if DRV_PS1 + drv_ps1_free, +#endif + drv_tty_free +}; + +const size_t drv_tree_n = N; diff --git a/src/drv/src/update.c b/src/drv/src/update.c new file mode 100644 index 0000000..268c2b6 --- /dev/null +++ b/src/drv/src/update.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/drv.h> +#include <drv/tree.h> +#include <drv/types.h> +#include <drv/port.h> +#include <stddef.h> + +int drv_update(struct drv *const d) +{ + for (size_t i = 0; i < drv_tree_n; i++) + if (drv_tree_update[i](d->ports[i])) + return -1; + + return 0; +} diff --git a/src/drv/tty/CMakeLists.txt b/src/drv/tty/CMakeLists.txt new file mode 100644 index 0000000..ee14015 --- /dev/null +++ b/src/drv/tty/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_tty) +add_subdirectory(src) +target_include_directories(drv_tty PUBLIC include PRIVATE private_include) +target_link_libraries(drv_tty PUBLIC c PRIVATE gfx drv_event) diff --git a/src/drv/tty/include/drv/tty.h b/src/drv/tty/include/drv/tty.h new file mode 100644 index 0000000..27804bf --- /dev/null +++ b/src/drv/tty/include/drv/tty.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TTY_H +#define DRV_TTY_H + +#include <drv/event.h> + +struct drv_port *drv_tty_init(const struct drv_event *ev); +int drv_tty_update(struct drv_port *p); +void drv_tty_free(struct drv_port *p); + +#endif diff --git a/src/drv/tty/private_include/drv/tty/font.h b/src/drv/tty/private_include/drv/tty/font.h new file mode 100644 index 0000000..a36d68e --- /dev/null +++ b/src/drv/tty/private_include/drv/tty/font.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TTY_FONT_H +#define DRV_TTY_FONT_H + +#include <gfx/sprite.h> +#include <stddef.h> + +struct gfx_sprite ttyfont_spr; +extern const unsigned char ttyfont[]; +extern const size_t ttyfont_size; + +#endif diff --git a/src/drv/tty/private_include/drv/tty/ops.h b/src/drv/tty/private_include/drv/tty/ops.h new file mode 100644 index 0000000..b50b00a --- /dev/null +++ b/src/drv/tty/private_include/drv/tty/ops.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TTY_OPS_H +#define DRV_TTY_OPS_H + +#include <drv/event.h> +#include <drv/tty/types.h> +#include <stddef.h> + +int drv_tty_write(const void *buf, size_t n, const struct drv_event_done *done, + void *args); +int drv_tty_setdim(struct drv_port *p, unsigned x, unsigned y); + +#endif diff --git a/src/drv/tty/private_include/drv/tty/types.h b/src/drv/tty/private_include/drv/tty/types.h new file mode 100644 index 0000000..38a1108 --- /dev/null +++ b/src/drv/tty/private_include/drv/tty/types.h @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_TTY_TYPES_H +#define DRV_TTY_TYPES_H + +#include <drv/event.h> +#include <stdbool.h> +#include <stddef.h> + +struct row +{ + char *columns; + size_t len; +}; + +struct drv_port +{ + bool init; + struct row *rows, *first_row, *last_row, *proc_row; + size_t nrows, ncolumns, last_column, last_proc_column; + struct drv_event ev; +}; + +#endif diff --git a/src/drv/tty/src/CMakeLists.txt b/src/drv/tty/src/CMakeLists.txt new file mode 100644 index 0000000..096b685 --- /dev/null +++ b/src/drv/tty/src/CMakeLists.txt @@ -0,0 +1,27 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_tty PRIVATE + free.c + init.c + setdim.c + update.c + write.c +) + +if(PS1_BUILD) + add_subdirectory(ps1) +endif() diff --git a/src/drv/tty/src/free.c b/src/drv/tty/src/free.c new file mode 100644 index 0000000..66d5cb4 --- /dev/null +++ b/src/drv/tty/src/free.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/event.h> +#include <drv/tty.h> +#include <drv/tty/font.h> +#include <drv/tty/ops.h> +#include <drv/tty/types.h> +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <stddef.h> +#include <stdlib.h> + +void drv_tty_free(struct drv_port *const p) +{ + if (!p) + return; + + for (size_t i = 0; i < p->nrows; i++) + free(p->rows[i].columns); + + free(p->rows); + free(p); +} diff --git a/src/drv/tty/src/init.c b/src/drv/tty/src/init.c new file mode 100644 index 0000000..53299f4 --- /dev/null +++ b/src/drv/tty/src/init.c @@ -0,0 +1,58 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/event.h> +#include <drv/tty.h> +#include <drv/tty/font.h> +#include <drv/tty/ops.h> +#include <drv/tty/types.h> +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +static int load(void *const buf, const size_t n, void *const args) +{ + size_t *const off = args; + + memcpy(buf, ttyfont + *off, n); + *off += n; + return 0; +} + +struct drv_port *drv_tty_init(const struct drv_event *const ev) +{ + size_t off = 0; + struct drv_port *ret = NULL; + + if (!(ret = malloc(sizeof *ret))) + goto failure; + + *ret = (const struct drv_port){.ev = *ev}; + gfx_sprite_load(&ttyfont_spr, load, &off); + + if (drv_tty_setdim(ret, screen_w, screen_h)) + goto failure; + + return ret; + +failure: + drv_tty_free(ret); + return NULL; +} diff --git a/src/drv/tty/src/ps1/CMakeLists.txt b/src/drv/tty/src/ps1/CMakeLists.txt new file mode 100644 index 0000000..c07a45f --- /dev/null +++ b/src/drv/tty/src/ps1/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_tty PRIVATE + ttyfont_tim.c +) diff --git a/src/drv/tty/src/ps1/ttyfont_tim.c b/src/drv/tty/src/ps1/ttyfont_tim.c new file mode 100644 index 0000000..b7dd03b --- /dev/null +++ b/src/drv/tty/src/ps1/ttyfont_tim.c @@ -0,0 +1,801 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +/* Derived from res/font.bmp. See res/orig/LICENSE for details. */ + +#include <drv/tty/font.h> +#include <stddef.h> + +const unsigned char ttyfont[] = { + 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, + 0x80, 0x02, 0xf2, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x7f, + 0x2c, 0x34, 0x3e, 0x26, 0xdc, 0x01, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x40, 0x5f, 0x1f, 0x36, 0x9c, 0x03, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x0c, 0x24, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, + 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x10, 0x11, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, + 0x11, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x10, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x01, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x10, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +const size_t ttyfont_size = sizeof ttyfont; diff --git a/src/drv/tty/src/setdim.c b/src/drv/tty/src/setdim.c new file mode 100644 index 0000000..d1f835a --- /dev/null +++ b/src/drv/tty/src/setdim.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/event.h> +#include <drv/tty.h> +#include <drv/tty/font.h> +#include <drv/tty/ops.h> +#include <drv/tty/types.h> +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <stddef.h> +#include <stdlib.h> + +int drv_tty_setdim(struct drv_port *const p, const unsigned w, const unsigned h) +{ + const unsigned columns = w / 10, rows = h / 16; + struct row *const prs = malloc(rows * sizeof *prs); + + if (!prs) + goto failure; + + for (unsigned i = 0; i < rows; i++) + *(prs + i) = (const struct row){0}; + + for (unsigned i = 0; i < rows; i++) + { + struct row *const p = &prs[i]; + char *const c = malloc(columns); + + if (!c) + goto failure; + + p->columns = c; + } + + p->first_row = p->last_row = p->proc_row = p->rows = prs; + p->nrows = rows; + p->ncolumns = columns; + return 0; + +failure: + for (unsigned i = 0; i < rows; i++) + free(prs[i].columns); + + free(prs); + return -1; +} diff --git a/src/drv/tty/src/update.backup.c b/src/drv/tty/src/update.backup.c new file mode 100644 index 0000000..d072977 --- /dev/null +++ b/src/drv/tty/src/update.backup.c @@ -0,0 +1,125 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/event.h> +#include <drv/tty.h> +#include <drv/tty/font.h> +#include <drv/tty/ops.h> +#include <drv/tty/types.h> +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <stdbool.h> + +static int init(struct drv_port *const p) +{ + if (p->init) + return 0; + + const struct drv_event *const ev = &p->ev; + const struct drv_event_ops ops = + { + .write = drv_tty_write, + .args = p + }; + + if (ev->status("tty", &ops, true, 0666, ev->args)) + return -1; + + p->init = true; + return 0; +} + +static short get_y(const struct drv_port *const p) +{ + const ptrdiff_t r = p->proc_row - p->first_row; + + if (r >= 0) + return r * 16; + + return (((p->rows + p->nrows) - p->first_row) + + (p->proc_row - p->rows)) * 16; +} + +static int prepare(struct drv_port *const p) +{ + struct row *r = p->proc_row; + + if (r == p->last_row) + return 0; + else if (!p->last_proc_column) + { + struct gfx_rect *const rect = gfx_rect_get(); + const short y = get_y(p); + + if (!rect) + return 0; + + gfx_rect_init(rect); + rect->y = y; + rect->w = screen_w; + rect->h = 16; + + if (gfx_rect_sort(rect)) + return -1; + } + + const char c = r->columns[p->last_proc_column]; + + if (c != ' ') + { + struct gfx_sprite *const s = gfx_sprite_get(); + + if (!s || gfx_sprite_clone(&ttyfont_spr, s)) + return 0; + + const short x = p->last_proc_column * 10, y = get_y(p); + const char ch = c - ' '; + const short u = (12 * ch) % ttyfont_spr.w; + const short v = 16 * ((12 * ch) / ttyfont_spr.w); + + /* TODO: replace hardcoded values */ + s->x = x; + s->y = y; + s->w = 12; + s->h = 16; + s->u += u; + s->v += v; + + if (gfx_sprite_sort(s)) + return -1; + } + + if (++p->last_proc_column >= r->len) + { + if (++r - p->rows >= p->nrows) + r = p->rows; + + p->last_proc_column = 0; + } + + p->proc_row = r; + return 0; +} + +int drv_tty_update(struct drv_port *const p) +{ + if (init(p) || prepare(p)) + return -1; + + return 0; +} diff --git a/src/drv/tty/src/update.c b/src/drv/tty/src/update.c new file mode 100644 index 0000000..7c01678 --- /dev/null +++ b/src/drv/tty/src/update.c @@ -0,0 +1,126 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/event.h> +#include <drv/tty.h> +#include <drv/tty/font.h> +#include <drv/tty/ops.h> +#include <drv/tty/types.h> +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <stdbool.h> + +static int init(struct drv_port *const p) +{ + if (p->init) + return 0; + + const struct drv_event *const ev = &p->ev; + const struct drv_event_ops ops = + { + .write = drv_tty_write, + .args = p + }; + + if (ev->status("tty", &ops, true, 0666, ev->args)) + return -1; + + p->init = true; + return 0; +} + +static short get_y(const struct drv_port *const p) +{ + const ptrdiff_t r = p->proc_row - p->first_row; + + if (r >= 0) + return r * 16; + + return (((p->rows + p->nrows) - p->first_row) + + (p->proc_row - p->rows)) * 16; +} + +static int prepare(struct drv_port *const p) +{ + struct row *r = p->proc_row; + + if (r == p->last_row) + return 0; + + struct gfx_rect *const rect = gfx_rect_get(); + const short y = get_y(p); + short x = 0; + + if (!rect) + return 0; + + gfx_rect_init(rect); + rect->y = y; + rect->w = screen_w; + rect->h = 16; + + if (gfx_rect_sort(rect)) + return -1; + + /* TODO: this is a trick to avoid having half-rendered lines. */ + struct gfx_sprite *sprites[64]; + + for (size_t i = 0; i < sizeof sprites / sizeof *sprites; i++) + sprites[i] = gfx_sprite_get(); + + for (const char *c = r->columns; + *c && c - r->columns < p->ncolumns; c++, x += 10) + { + struct gfx_sprite *const s = sprites[c - r->columns]; + + if (*c == ' ') + continue; + + const char ch = *c - ' '; + const short u = (12 * ch) % ttyfont_spr.w; + const short v = 16 * ((12 * ch) / ttyfont_spr.w); + + if (!s || gfx_sprite_clone(&ttyfont_spr, s)) + return 0; + + /* TODO: replace hardcoded values */ + s->x = x; + s->y = y; + s->w = 12; + s->h = 16; + s->u += u; + s->v += v; + + if (gfx_sprite_sort(s)) + return -1; + } + + if (++r - p->rows >= p->nrows) + r = p->rows; + + p->proc_row = r; + return 0; +} + +int drv_tty_update(struct drv_port *const p) +{ + if (init(p) || prepare(p)) + return -1; + + return 0; +} diff --git a/src/drv/tty/src/write.c b/src/drv/tty/src/write.c new file mode 100644 index 0000000..d4a988d --- /dev/null +++ b/src/drv/tty/src/write.c @@ -0,0 +1,70 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/event.h> +#include <drv/tty.h> +#include <drv/tty/types.h> +#include <drv/tty/ops.h> +#include <errno.h> +#include <stddef.h> + +int drv_tty_write(const void *const buf, const size_t n, + const struct drv_event_done *const d, void *const args) +{ + struct drv_port *const p = args; + + for (const char *s = buf; s - (const char *)buf < n; s++) + { + struct row *const r = p->last_row; + char *const col = &r->columns[p->last_column]; + + if (*s == '\r') + { + *col = '\0'; + p->last_column = r->len = 0; + } + else + { + if (*s != '\n') + { + *col = *s; + r->len++; + } + else + *col = '\0'; + + if (*s == '\n' || ++p->last_column >= p->ncolumns) + { + if (++p->last_row - p->rows >= p->nrows) + p->last_row = p->rows; + + if (p->last_row == p->first_row) + { + if (++p->first_row - p->rows >= p->nrows) + p->first_row = p->rows; + + p->proc_row = p->first_row; + } + + p->last_column = 0; + } + } + } + + return d->f(SUCCESS, d->args); +} diff --git a/src/endian/CMakeLists.txt b/src/endian/CMakeLists.txt new file mode 100644 index 0000000..01a7e98 --- /dev/null +++ b/src/endian/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(endian) +add_subdirectory(src) +target_include_directories(endian PUBLIC include PRIVATE private_include) diff --git a/src/endian/include/endian.h b/src/endian/include/endian.h new file mode 100644 index 0000000..7cd0aae --- /dev/null +++ b/src/endian/include/endian.h @@ -0,0 +1,46 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ENDIAN_H +#define ENDIAN_H + +#include <stdint.h> + +struct endian_le16 +{ + uint8_t v[sizeof (uint16_t)]; +}; + +struct endian_le32 +{ + uint8_t v[sizeof (uint32_t)]; +}; + +struct endian_le64 +{ + uint8_t v[sizeof (uint64_t)]; +}; + +uint16_t endian_from_le16(const struct endian_le16 *v); +uint32_t endian_from_le32(const struct endian_le32 *v); +uint64_t endian_from_le64(const struct endian_le64 *v); +struct endian_le16 endian_to_le16(uint16_t v); +struct endian_le32 endian_to_le32(uint32_t v); +struct endian_le64 endian_to_le64(uint64_t v); + +#endif diff --git a/src/endian/src/CMakeLists.txt b/src/endian/src/CMakeLists.txt new file mode 100644 index 0000000..962291a --- /dev/null +++ b/src/endian/src/CMakeLists.txt @@ -0,0 +1,24 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(endian PRIVATE + from_le16.c + from_le32.c + from_le64.c + to_le16.c + to_le32.c + to_le64.c +) diff --git a/src/endian/src/from_le16.c b/src/endian/src/from_le16.c new file mode 100644 index 0000000..30685fe --- /dev/null +++ b/src/endian/src/from_le16.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <endian.h> +#include <stdint.h> + +uint16_t endian_from_le16(const struct endian_le16 *const v) +{ + return v->v[0] | (v->v[1] << 8); +} diff --git a/src/endian/src/from_le32.c b/src/endian/src/from_le32.c new file mode 100644 index 0000000..f56ee7b --- /dev/null +++ b/src/endian/src/from_le32.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <endian.h> +#include <stdint.h> + +uint32_t endian_from_le32(const struct endian_le32 *const v) +{ + return v->v[0] | (v->v[1] << 8) | ((unsigned long)v->v[2] << 16) + | ((unsigned long)v->v[3] << 24); +} diff --git a/src/endian/src/from_le64.c b/src/endian/src/from_le64.c new file mode 100644 index 0000000..37b5f1a --- /dev/null +++ b/src/endian/src/from_le64.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <endian.h> +#include <stdint.h> + +uint64_t endian_from_le64(const struct endian_le64 *const v) +{ + return v->v[0] + | (v->v[1] << 8) + | ((uint64_t)v->v[2] << 16ul) + | ((uint64_t)v->v[3] << 24ul) + | ((uint64_t)v->v[4] << 32ul) + | ((uint64_t)v->v[5] << 40ul) + | ((uint64_t)v->v[6] << 48ul) + | ((uint64_t)v->v[7] << 56ul); +} diff --git a/src/endian/src/to_le16.c b/src/endian/src/to_le16.c new file mode 100644 index 0000000..ddf8faf --- /dev/null +++ b/src/endian/src/to_le16.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <endian.h> +#include <stdint.h> + +struct endian_le16 endian_to_le16(const uint16_t v) +{ + return (const struct endian_le16) + { + .v = + { + [0] = v, + [1] = v >> 8 + } + }; +} diff --git a/src/endian/src/to_le32.c b/src/endian/src/to_le32.c new file mode 100644 index 0000000..b16dd69 --- /dev/null +++ b/src/endian/src/to_le32.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <endian.h> +#include <stdint.h> + +struct endian_le32 endian_to_le32(const uint32_t v) +{ + return (const struct endian_le32) + { + .v = + { + [0] = v, + [1] = v >> 8, + [2] = v >> 16, + [3] = v >> 24 + } + }; +} diff --git a/src/endian/src/to_le64.c b/src/endian/src/to_le64.c new file mode 100644 index 0000000..4d1ef1e --- /dev/null +++ b/src/endian/src/to_le64.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <endian.h> +#include <stdint.h> + +struct endian_le64 endian_to_le64(const uint64_t v) +{ + return (const struct endian_le64) + { + .v = + { + [0] = v, + [1] = v >> 8, + [2] = v >> 16, + [3] = v >> 24, + [4] = v >> 32, + [5] = v >> 40, + [6] = v >> 48, + [7] = v >> 56, + } + }; +} diff --git a/src/fs/CMakeLists.txt b/src/fs/CMakeLists.txt new file mode 100644 index 0000000..6f4aaea --- /dev/null +++ b/src/fs/CMakeLists.txt @@ -0,0 +1,24 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(fs) +add_subdirectory(src) +target_include_directories(fs PUBLIC include PRIVATE private_include) +target_link_libraries(fs PUBLIC state) +add_subdirectory(devfs) +add_subdirectory(iso9660) +add_subdirectory(ramfs) +add_subdirectory(rootfs) diff --git a/src/fs/devfs/CMakeLists.txt b/src/fs/devfs/CMakeLists.txt new file mode 100644 index 0000000..c3bbcf8 --- /dev/null +++ b/src/fs/devfs/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(devfs) +add_subdirectory(src) +target_include_directories(devfs PUBLIC include PRIVATE private_include) +target_link_libraries(devfs PUBLIC state c PRIVATE fs drv ramfs) diff --git a/src/fs/devfs/include/devfs.h b/src/fs/devfs/include/devfs.h new file mode 100644 index 0000000..ccc82ac --- /dev/null +++ b/src/fs/devfs/include/devfs.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DEVFS_H +#define DEVFS_H + +int devfs_register(void); + +#endif diff --git a/src/fs/devfs/private_include/devfs/ops.h b/src/fs/devfs/private_include/devfs/ops.h new file mode 100644 index 0000000..0c09776 --- /dev/null +++ b/src/fs/devfs/private_include/devfs/ops.h @@ -0,0 +1,49 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DEVFS_OPS_H +#define DEVFS_OPS_H + +#include <fs/fs.h> +#include <drv/event.h> +#include <sys/types.h> +#include <stdbool.h> + +int devfs_mount(const struct fs_mount *m, struct fs_ret *r); +int devfs_mkdir(const struct fs_mkdir *m, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int devfs_open(const struct fs_open *o, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int devfs_read(const struct fs_read *r, struct fs_ret *ret); +int devfs_read_nb(const struct fs_read *r); +int devfs_write(const struct fs_write *w, struct fs_ret *r); +int devfs_stat(const struct fs_stat *s, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int devfs_close(struct fs_fd *fd); +int devfs_search(const char *path, const struct fs_mp *mp, + union inode_result *inode, struct fs_ret *r); +int devfs_status(const char *node, const struct drv_event_ops *const ops, + bool available, mode_t mode, void *args); +int devfs_flags(const union inode_result *i); +int devfs_update(struct fs_mp_prv *pr); +int devfs_mknod(const char *path, mode_t mode, dev_t dev, + const struct drv_event_ops *const ops, struct fs_mp_prv *mp); +int devfs_unlink(const char *path, struct fs_mp_prv *mp); +const struct devfs_ops *devfs_ops(const struct fs_mp_prv *pr, const char *node); + +#endif diff --git a/src/fs/devfs/private_include/devfs/types.h b/src/fs/devfs/private_include/devfs/types.h new file mode 100644 index 0000000..da6b50b --- /dev/null +++ b/src/fs/devfs/private_include/devfs/types.h @@ -0,0 +1,44 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DEVFS_TYPES_H +#define DEVFS_TYPES_H + +#include <fs/fs.h> +#include <fs/inode.h> +#include <drv/drv.h> +#include <drv/event.h> +#include <ramfs.h> + +struct devfs_ops +{ + char *node; + struct drv_event_ops ops; + struct devfs_ops *prev, *next; +}; + +struct fs_mp_prv +{ + struct ramfs *rfs; + struct drv *drv; + struct devfs_ops *head, *tail; +}; + +extern const struct fs devfs; + +#endif diff --git a/src/fs/devfs/src/CMakeLists.txt b/src/fs/devfs/src/CMakeLists.txt new file mode 100644 index 0000000..2a12700 --- /dev/null +++ b/src/fs/devfs/src/CMakeLists.txt @@ -0,0 +1,34 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(devfs PRIVATE + close.c + flags.c + mount.c + mkdir.c + mknod.c + open.c + ops.c + stat.c + read.c + read_nb.c + register.c + search.c + status.c + unlink.c + update.c + write.c +) diff --git a/src/fs/devfs/src/close.c b/src/fs/devfs/src/close.c new file mode 100644 index 0000000..db236d1 --- /dev/null +++ b/src/fs/devfs/src/close.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <fs/fs.h> + +int devfs_close(struct fs_fd *const fd) +{ + return -1; +} diff --git a/src/fs/devfs/src/flags.c b/src/fs/devfs/src/flags.c new file mode 100644 index 0000000..082c5ad --- /dev/null +++ b/src/fs/devfs/src/flags.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> + +int devfs_flags(const union inode_result *const i) +{ + return i->memi->flags; +} diff --git a/src/fs/devfs/src/mkdir.c b/src/fs/devfs/src/mkdir.c new file mode 100644 index 0000000..cc091e0 --- /dev/null +++ b/src/fs/devfs/src/mkdir.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <fs/fs.h> +#include <fs/inode.h> + +int devfs_mkdir(const struct fs_mkdir *m, const struct fs_mp *const mp, + const union inode_result *const i, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/devfs/src/mknod.c b/src/fs/devfs/src/mknod.c new file mode 100644 index 0000000..f9a369e --- /dev/null +++ b/src/fs/devfs/src/mknod.c @@ -0,0 +1,54 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs/ops.h> +#include <devfs/types.h> +#include <fs/inode.h> +#include <ramfs.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +int devfs_mknod(const char *const node, const mode_t mode, const dev_t dev, + const struct drv_event_ops *const ops, struct fs_mp_prv *const pr) +{ + struct devfs_ops *dops = NULL; + char *const nodedup = strdup(node); + + if (!nodedup + || !(dops = malloc(sizeof *dops)) + || ramfs_mknod(node, mode, dev, pr->rfs)) + goto failure; + + *dops = (const struct devfs_ops){.node = nodedup, .ops = *ops}; + + if (!pr->head) + pr->head = dops; + else + { + dops->prev = pr->tail; + pr->tail->next = dops; + } + + pr->tail = dops; + return 0; + +failure: + free(dops); + return -1; +} diff --git a/src/fs/devfs/src/mount.c b/src/fs/devfs/src/mount.c new file mode 100644 index 0000000..2165971 --- /dev/null +++ b/src/fs/devfs/src/mount.c @@ -0,0 +1,59 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <drv/drv.h> +#include <fs/fs.h> +#include <ramfs.h> +#include <stdlib.h> + +int devfs_mount(const struct fs_mount *const m, struct fs_ret *const r) +{ + struct drv *drv = NULL; + struct fs_mp_prv *p = NULL; + struct ramfs *const rfs = ramfs_mount(m, r); + + if (!rfs || !(p = malloc(sizeof *p))) + goto failure; + + const struct drv_event ev = + { + .status = devfs_status, + .args = p + }; + + if (!(drv = drv_init(&ev)) + || fs_mountpoint(m->src, m->tgt, &devfs, devfs_update, p)) + goto failure; + + *p = (const struct fs_mp_prv) + { + .drv = drv, + .rfs = rfs + }; + + return 0; + +failure: + drv_free(drv); + free(p); + ramfs_free(rfs); + return -1; +} diff --git a/src/fs/devfs/src/open.c b/src/fs/devfs/src/open.c new file mode 100644 index 0000000..551061f --- /dev/null +++ b/src/fs/devfs/src/open.c @@ -0,0 +1,57 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/types.h> +#include <devfs/ops.h> +#include <fs/fs.h> +#include <state.h> +#include <stdlib.h> + +struct open +{ + struct fs_ret *pr, r; +}; + +static enum state done(void *const args) +{ + struct open *const op = args; + + *op->pr = op->r; + free(op); + return STATE_AGAIN; +} + +int devfs_open(const struct fs_open *const o, const struct fs_mp *const mp, + const union inode_result *const inode, struct fs_ret *const r) +{ + struct open *const op = malloc(sizeof *op); + + if (!op) + return -1; + + *op = (const struct open){.pr = r, .r = *r}; + *o->fd = (const struct fs_fd) + { + .inode = *inode, + .mp = mp + }; + + *r = (const struct fs_ret){.f = done, .args = op}; + return 0; +} diff --git a/src/fs/devfs/src/ops.c b/src/fs/devfs/src/ops.c new file mode 100644 index 0000000..c51cfa7 --- /dev/null +++ b/src/fs/devfs/src/ops.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <string.h> + +const struct devfs_ops *devfs_ops(const struct fs_mp_prv *const pr, + const char *const node) +{ + for (struct devfs_ops *o = pr->head; o; o = o->next) + if (!strcmp(o->node, node)) + return o; + + return NULL; +} diff --git a/src/fs/devfs/src/read.c b/src/fs/devfs/src/read.c new file mode 100644 index 0000000..e968eb2 --- /dev/null +++ b/src/fs/devfs/src/read.c @@ -0,0 +1,98 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <fs/fs.h> +#include <state.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> + +struct read +{ + bool done; + size_t n; + struct fs_fd *fd; + struct fs_ret *pr, r; +}; + +static int done(const int error, void *const args) +{ + struct read *const re = args; + + re->done = true; + return 0; +} + +static enum state wait(void *const args) +{ + struct read *const re = args; + + if (!re->done) + return STATE_AGAIN; + + re->fd->offset += re->n; + *re->pr = re->r; + free(re); + return STATE_AGAIN; +} + +int devfs_read(const struct fs_read *const fr, struct fs_ret *const r) +{ + struct read *re = NULL; + struct fs_fd *const fd = fr->fd; + const struct fs_mp *const mp = fd->mp; + const struct inode *const inode = fd->inode.memi; + const struct devfs_ops *const o = devfs_ops(mp->prv, inode->name); + + if (!o) + { + errno = ENOENT; + goto failure; + } + else if (!(re = malloc(sizeof *re))) + goto failure; + + *re = (const struct read) + { + .n = fr->n, + .fd = fd, + .pr = r, + .r = *r + }; + + const struct drv_event_done d = + { + .f = done, + .args = re + }; + + const struct drv_event_ops *const ops = &o->ops; + + if (ops->read(fr->buf, fr->n, fd->start + fd->offset, &d, ops->args)) + goto failure; + + *r = (const struct fs_ret){.f = wait, .args = re}; + return 0; + +failure: + free(re); + return -1; +} diff --git a/src/fs/devfs/src/read_nb.c b/src/fs/devfs/src/read_nb.c new file mode 100644 index 0000000..2f30d5c --- /dev/null +++ b/src/fs/devfs/src/read_nb.c @@ -0,0 +1,41 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <fs/fs.h> +#include <errno.h> + +int devfs_read_nb(const struct fs_read *const fr) +{ + struct fs_fd *const fd = fr->fd; + const struct fs_mp *const mp = fd->mp; + const struct inode *const inode = fd->inode.memi; + const struct devfs_ops *const o = devfs_ops(mp->prv, inode->name); + + if (!o) + { + errno = ENOENT; + return -1; + } + + const struct drv_event_ops *const ops = &o->ops; + + return ops->read_nb(fr->buf, fr->n, ops->args); +} diff --git a/src/fs/devfs/src/register.c b/src/fs/devfs/src/register.c new file mode 100644 index 0000000..5ff7b33 --- /dev/null +++ b/src/fs/devfs/src/register.c @@ -0,0 +1,44 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <fs/fs.h> + +const struct fs devfs = +{ + .type = "devfs", + .mount = devfs_mount, + .stat = devfs_stat, + .mkdir = devfs_mkdir, + .open = devfs_open, + .read = devfs_read, + .read_nb = devfs_read_nb, + .write = devfs_write, + .close = devfs_close, + .iops = + { + .search = devfs_search, + .flags = devfs_flags + } +}; + +int devfs_register(void) +{ + return fs_register(&devfs); +} diff --git a/src/fs/devfs/src/search.c b/src/fs/devfs/src/search.c new file mode 100644 index 0000000..4360a9f --- /dev/null +++ b/src/fs/devfs/src/search.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <fs/fs.h> +#include <ramfs.h> + +int devfs_search(const char *const path, const struct fs_mp *const mp, + union inode_result *const inode, struct fs_ret *const r) +{ + return ramfs_search(path, mp->prv->rfs, inode, r); +} diff --git a/src/fs/devfs/src/stat.c b/src/fs/devfs/src/stat.c new file mode 100644 index 0000000..50af3ee --- /dev/null +++ b/src/fs/devfs/src/stat.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <ramfs.h> + +int devfs_stat(const struct fs_stat *const s, const struct fs_mp *const mp, + const union inode_result *const i, struct fs_ret *const r) +{ + return ramfs_stat(s, mp->prv->rfs, i, r); +} diff --git a/src/fs/devfs/src/status.c b/src/fs/devfs/src/status.c new file mode 100644 index 0000000..fb73c94 --- /dev/null +++ b/src/fs/devfs/src/status.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs/ops.h> +#include <drv/event.h> +#include <sys/types.h> +#include <stdbool.h> + +int devfs_status(const char *const node, const struct drv_event_ops *const ops, + const bool available, const mode_t mode, void *const args) +{ + struct fs_mp_prv *const mp = args; + + return available ? devfs_mknod(node, mode, 0, ops, mp) + : devfs_unlink(node, mp); +} diff --git a/src/fs/devfs/src/unlink.c b/src/fs/devfs/src/unlink.c new file mode 100644 index 0000000..3cd87b4 --- /dev/null +++ b/src/fs/devfs/src/unlink.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs/ops.h> +#include <sys/types.h> +#include <errno.h> + +int devfs_unlink(const char *const node, struct fs_mp_prv *const mp) +{ + return -1; +} diff --git a/src/fs/devfs/src/update.c b/src/fs/devfs/src/update.c new file mode 100644 index 0000000..b437044 --- /dev/null +++ b/src/fs/devfs/src/update.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/types.h> +#include <devfs/ops.h> +#include <drv/drv.h> + +int devfs_update(struct fs_mp_prv *const pr) +{ + return drv_update(pr->drv); +} diff --git a/src/fs/devfs/src/write.c b/src/fs/devfs/src/write.c new file mode 100644 index 0000000..392666c --- /dev/null +++ b/src/fs/devfs/src/write.c @@ -0,0 +1,95 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <devfs.h> +#include <devfs/ops.h> +#include <devfs/types.h> +#include <fs/fs.h> +#include <state.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> + +struct write +{ + bool done; + struct fs_fd *fd; + struct fs_ret *pr, r; +}; + +static int done(const int error, void *const args) +{ + struct write *const w = args; + + w->done = true; + return 0; +} + +static enum state wait(void *const args) +{ + struct write *const w = args; + + if (!w->done) + return STATE_AGAIN; + + *w->pr = w->r; + free(w); + return STATE_AGAIN; +} + +int devfs_write(const struct fs_write *const fw, struct fs_ret *const r) +{ + struct fs_fd *const fd = fw->fd; + const struct fs_mp *const mp = fd->mp; + const struct inode *const inode = fd->inode.memi; + const struct devfs_ops *const o = devfs_ops(mp->prv, inode->name); + struct write *const w = malloc(sizeof *w); + + if (!w) + goto failure; + else if (!o) + { + errno = ENOENT; + goto failure; + } + + *w = (const struct write) + { + .fd = fd, + .pr = r, + .r = *r + }; + + const struct drv_event_done d = + { + .f = done, + .args = w + }; + + const struct drv_event_ops *const ops = &o->ops; + + if (ops->write(fw->buf, fw->n, &d, ops->args)) + goto failure; + + *r = (const struct fs_ret){.f = wait, .args = w}; + return 0; + +failure: + free(w); + return -1; +} diff --git a/src/fs/include/fs/fs.h b/src/fs/include/fs/fs.h new file mode 100644 index 0000000..aebe1db --- /dev/null +++ b/src/fs/include/fs/fs.h @@ -0,0 +1,146 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef FS_H +#define FS_H + +#include <fs/inode.h> +#include <state.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <stdbool.h> +#include <stddef.h> + +struct fs_mountpoint; +struct fs_mp_prv; +struct fs_fd_prv; + +struct fs_stat +{ + const char *path; + struct stat *sb; + uid_t uid; + gid_t gid; +}; + +struct fs_mkdir +{ + const char *path; + mode_t mode; + uid_t uid; + gid_t gid; +}; + +struct fs_mount +{ + const char *src, *tgt; + mode_t mode; + uid_t uid; + gid_t gid; +}; + +struct fs_umount +{ + const char *tgt; + mode_t mode; + uid_t uid; + gid_t gid; +}; + +struct fs_open +{ + const char *path; + struct fs_fd *fd; + int flags; + mode_t mode; + uid_t uid; + gid_t gid; +}; + +struct fs_read +{ + struct fs_fd *fd; + void *buf; + size_t n; +}; + +struct fs_write +{ + struct fs_fd *fd; + const void *buf; + size_t n; +}; + +struct fs_ret +{ + enum state (*f)(void *args); + void *args; +}; + +enum {FS_DEV_REQUIRED = 1}; + +struct fs +{ + const char *type; + int flags; + int (*mount)(const struct fs_mount *, struct fs_ret *); + int (*umount)(const struct fs_umount *, struct fs_ret *); + int (*stat)(const struct fs_stat *, const struct fs_mp *, + const union inode_result *, struct fs_ret *); + int (*mkdir)(const struct fs_mkdir *, const struct fs_mp *, + const union inode_result *, struct fs_ret *); + int (*open)(const struct fs_open *, const struct fs_mp *, + const union inode_result *, struct fs_ret *); + int (*close)(struct fs_fd *); + int (*read)(const struct fs_read *, struct fs_ret *); + int (*read_nb)(const struct fs_read *); + int (*write)(const struct fs_write *, struct fs_ret *); + int (*eof)(const struct fs_fd *); + struct inode_ops iops; +}; + +struct fs_mp +{ + const char *src, *tgt; + const struct fs *fs; + struct fs_mp_prv *prv; +}; + +struct fs_fd +{ + int error; + off_t start, offset, size; + struct fs_fd_prv *prv; + const struct fs_mp *mp, *tgt_mp; + union inode_result inode, tgt_inode; +}; + +typedef int (*fs_update_fn)(struct fs_mp_prv *); + +int fs_register(const struct fs *fs); +int fs_update(void); +int fs_mountpoint(const char *src, const char *tgt, const struct fs *fs, + fs_update_fn fn, struct fs_mp_prv *pr); +const struct fs *fs_from_type(const char *type); +int fs_mp_from_path(const char *path, struct fs_mp *mp); +struct fs_mp *fs_mps_from_path(const char *path, size_t *n); +const char *fs_relpath(const char *path); +char *fs_parent(const char *path); +int fs_next(const char *path, char **next, size_t *i); + +#endif diff --git a/src/fs/include/fs/inode.h b/src/fs/include/fs/inode.h new file mode 100644 index 0000000..fc24d74 --- /dev/null +++ b/src/fs/include/fs/inode.h @@ -0,0 +1,81 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef FS_INODE_H +#define FS_INODE_H + +#include <state.h> +#include <sys/types.h> +#include <time.h> + +struct fs; +struct fs_mp; +struct fs_ret; +struct inode_prv; + +enum +{ + INODE_DIR = 1, + INODE_REGFILE = 1 << 1, + INODE_BLOCKDEV = 1 << 2, + INODE_MOUNTPOINT = 1 << 3, +}; + +struct inode +{ + char *name; + int flags; + ino_t ino; + mode_t mode; + uid_t uid; + gid_t gid; + off_t size; + struct timespec atim, mtim, ctim; + struct inode *parent, *child, *left, *right; + struct inode_prv *prv; + void (*free)(void *); +}; + +union inode_result +{ + struct inode cachei, *memi; +}; + +typedef int (*inode_search_done)(enum state state, const char *relpath, + const struct fs_mp *mp, const union inode_result *inode, void *args); + +struct inode_search +{ + const char *path; + inode_search_done done; + void *args; +}; + +struct inode_ops +{ + int (*search)(const char *path, const struct fs_mp *mp, + union inode_result *inode, struct fs_ret *r); + int (*reserve)(const struct inode *i, void *args, struct fs_ret *r); + int (*flags)(const union inode_result *i); +}; + +int inode_search(const struct inode_search *s, struct fs_ret *r); +void inode_search_free(struct inode_search *s); +void inode_free(struct inode *i); + +#endif diff --git a/src/fs/iso9660/CMakeLists.txt b/src/fs/iso9660/CMakeLists.txt new file mode 100644 index 0000000..736fc4e --- /dev/null +++ b/src/fs/iso9660/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(iso9660) +add_subdirectory(src) +target_include_directories(iso9660 PUBLIC include PRIVATE private_include) +target_link_libraries(iso9660 PUBLIC c PRIVATE fs kprintf state) diff --git a/src/fs/iso9660/include/iso9660.h b/src/fs/iso9660/include/iso9660.h new file mode 100644 index 0000000..e7d1864 --- /dev/null +++ b/src/fs/iso9660/include/iso9660.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ISO9660_H +#define ISO9660_H + +int iso9660_register(void); + +#endif diff --git a/src/fs/iso9660/private_include/iso9660/ops.h b/src/fs/iso9660/private_include/iso9660/ops.h new file mode 100644 index 0000000..b85d025 --- /dev/null +++ b/src/fs/iso9660/private_include/iso9660/ops.h @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ISO9660_OPS_H +#define ISO9660_OPS_H + +#include <fs/fs.h> +#include <fs/inode.h> + +int iso9660_mount(const struct fs_mount *m, struct fs_ret *r); +int iso9660_mkdir(const struct fs_mkdir *m, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int iso9660_open(const struct fs_open *o, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int iso9660_read(const struct fs_read *r, struct fs_ret *ret); +int iso9660_write(const struct fs_write *w, struct fs_ret *r); +int iso9660_stat(const struct fs_stat *s, const struct fs_mp *mp, + const union inode_result *inode, struct fs_ret *r); +int iso9660_close(struct fs_fd *fd); +int iso9660_eof(const struct fs_fd *fd); +int iso9660_search(const char *path, const struct fs_mp *prv, + union inode_result *inode, struct fs_ret *r); + +#endif diff --git a/src/fs/iso9660/private_include/iso9660/routines.h b/src/fs/iso9660/private_include/iso9660/routines.h new file mode 100644 index 0000000..467cce2 --- /dev/null +++ b/src/fs/iso9660/private_include/iso9660/routines.h @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ISO9660_ROUTINES_H +#define ISO9660_ROUTINES_H + +#include <iso9660/types.h> +#include <stddef.h> +#include <stdint.h> +#include <time.h> + +int iso9660_check_header(const struct iso9660_magic *m); +uint16_t iso9660_lmsb16(const struct iso9660_lmsb16 *p); +uint32_t iso9660_lmsb32(const struct iso9660_lmsb32 *p); +int iso9660_totm(const struct iso9660_dt *dt, struct tm *tm); +int iso9660_totimespec(const struct iso9660_dt *dt, struct timespec *ts); +int iso9660_etotimespec(const struct iso9660_entry_dt *dt, struct timespec *ts); +struct tm iso9660_gmtime(const struct iso9660_entry_dt *dt); + +#endif diff --git a/src/fs/iso9660/private_include/iso9660/types.h b/src/fs/iso9660/private_include/iso9660/types.h new file mode 100644 index 0000000..55544fb --- /dev/null +++ b/src/fs/iso9660/private_include/iso9660/types.h @@ -0,0 +1,148 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ISO9660_TYPES_H +#define ISO9660_TYPES_H + +#include <fs/fs.h> +#include <fs/inode.h> +#include <stdint.h> + +#define ISO9660_LE ((const union {int a; char c;}){.a = 1}.c) + +struct fs_mp_prv +{ + int dummy; +}; + +enum +{ + ISO9660_TYPE_BOOT_RECORD, + ISO9660_TYPE_PRIMARY_VD, + ISO9660_TYPE_SUPPLEMENTARY_VD, + ISO9660_TYPE_VOLUME_PARTITION, + ISO9660_TYPE_TERMINATOR = 0xff, +}; + +struct inode_prv +{ + long offset; +}; + +struct iso9660_magic +{ + uint8_t id[sizeof "CD001" - 1]; +}; + +struct iso9660_header +{ + uint8_t type; + struct iso9660_magic magic; + uint8_t version; +}; + +struct iso9660_lmsb16 +{ + uint8_t le[sizeof (uint16_t)], be[sizeof (uint16_t)]; +}; + +struct iso9660_lmsb32 +{ + uint8_t le[sizeof (uint32_t)], be[sizeof (uint32_t)]; +}; + +struct iso9660_dt +{ + char year[sizeof "9999" - 1], + month[sizeof "12" - 1], + day[sizeof "31" - 1], + hour[sizeof "23" - 1], + min[sizeof "59" - 1], + sec[sizeof "59" - 1], + hsec[sizeof "99" - 1]; + int8_t zone; +}; + +struct iso9660_lsb32 +{ + uint8_t data[sizeof (uint32_t)]; +}; + +struct iso9660_msb32 +{ + uint8_t data[sizeof (uint32_t)]; +}; + +struct iso9660_entry_dt +{ + uint8_t year, month, day, hour, min, sec, offset; +}; + +enum +{ + ISO9660_FLAGS_HIDDEN = 1, + ISO9660_FLAGS_DIR = 1 << 1, + ISO9660_FLAGS_ASSOC = 1 << 2, + ISO9660_FLAGS_HAS_FORMAT = 1 << 3, + ISO9660_FLAGS_HAS_UID_GID = 1 << 4, + ISO9660_FLAGS_NOT_FINAL = 1 << 7 +}; + +struct iso9660_entry +{ + uint8_t len, attr; + struct iso9660_lmsb32 extent_loc, data_len; + struct iso9660_entry_dt dt; + uint8_t flags; + uint8_t funit_sz, interleave_sz; + struct iso9660_lmsb16 seq_num; + uint8_t id_len; +}; + +struct iso9660_pvd +{ + uint8_t :8, sysid[32], vid[32], unused[8]; + struct iso9660_lmsb32 space_size; + uint8_t unused_2[32]; + struct iso9660_lmsb16 set_size, seq_num, block_size; + struct iso9660_lmsb32 pathtable_size; + struct iso9660_lsb32 lpath_loc, optlpath_loc; + struct iso9660_msb32 mpath_loc, optmpath_loc; + struct iso9660_entry root_dir; + uint8_t padding, set_id[128], pub_id[128], dprep_id[128], app_id[128], + copyright_id[37], abstract_id[37], bibl_id[37]; + struct iso9660_dt creat, mod, exp, eff; + uint8_t fs_version, :8, reserved[512 + 653]; +}; + + +struct iso9660_vd +{ + struct iso9660_header header; + + union + { + struct iso9660_pvd pvd; + } u; +}; + +enum {ISO9660_SECTOR_SZ = 2048}; + +extern const struct fs iso9660; + +#endif diff --git a/src/fs/iso9660/src/CMakeLists.txt b/src/fs/iso9660/src/CMakeLists.txt new file mode 100644 index 0000000..740e404 --- /dev/null +++ b/src/fs/iso9660/src/CMakeLists.txt @@ -0,0 +1,35 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(iso9660 PRIVATE + check_header.c + close.c + eof.c + etotimespec.c + gmtime.c + lmsb16.c + lmsb32.c + mount.c + mkdir.c + open.c + stat.c + read.c + register.c + search.c + totimespec.c + totm.c + write.c +) diff --git a/src/fs/iso9660/src/check_header.c b/src/fs/iso9660/src/check_header.c new file mode 100644 index 0000000..f504187 --- /dev/null +++ b/src/fs/iso9660/src/check_header.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/routines.h> +#include <kprintf.h> +#include <stdint.h> +#include <string.h> + +int iso9660_check_header(const struct iso9660_magic *const m) +{ + static const struct iso9660_magic em = {{'C', 'D', '0', '0', '1'}}; + + if (memcmp(m, &em, sizeof *m)) + { + const uint8_t *const b = m->id; + + kprintf("Invalid ISO9660 header: " + "{%hhx, %hhx, %hhx, %hhx, %hhx}\n", b[0], b[1], b[2], b[3], b[4]); + return -1; + } + + return 0; +} diff --git a/src/fs/iso9660/src/close.c b/src/fs/iso9660/src/close.c new file mode 100644 index 0000000..d43da29 --- /dev/null +++ b/src/fs/iso9660/src/close.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <fs/fs.h> + +int iso9660_close(struct fs_fd *const fd) +{ + return -1; +} diff --git a/src/fs/iso9660/src/eof.c b/src/fs/iso9660/src/eof.c new file mode 100644 index 0000000..1c36b63 --- /dev/null +++ b/src/fs/iso9660/src/eof.c @@ -0,0 +1,33 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <iso9660/types.h> +#include <fs/inode.h> + +int iso9660_eof(const struct fs_fd *const fd) +{ + const union inode_result *const i = &fd->tgt_inode; + const off_t sz = i->cachei.size; + + if (!sz) + return 1; + + return fd->offset >= sz - 1; +} diff --git a/src/fs/iso9660/src/etotimespec.c b/src/fs/iso9660/src/etotimespec.c new file mode 100644 index 0000000..21debf7 --- /dev/null +++ b/src/fs/iso9660/src/etotimespec.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <time.h> + +int iso9660_etotimespec(const struct iso9660_entry_dt *const dt, + struct timespec *const ts) +{ + struct tm tm = iso9660_gmtime(dt); + const time_t t = mktime(&tm); + + if (t == (time_t)-1) + return -1; + + *ts = (const struct timespec) + { + .tv_sec = t, + .tv_nsec = 0 + }; + + return 0; +} diff --git a/src/fs/iso9660/src/gmtime.c b/src/fs/iso9660/src/gmtime.c new file mode 100644 index 0000000..2649688 --- /dev/null +++ b/src/fs/iso9660/src/gmtime.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <time.h> + +struct tm iso9660_gmtime(const struct iso9660_entry_dt *const dt) +{ + return (const struct tm) + { + .tm_year = dt->year + 1900, + .tm_mon = dt->month, + .tm_mday = dt->day, + .tm_hour = dt->hour, + .tm_min = dt->min, + .tm_sec = dt->sec + }; +} diff --git a/src/fs/iso9660/src/lmsb16.c b/src/fs/iso9660/src/lmsb16.c new file mode 100644 index 0000000..d404b2c --- /dev/null +++ b/src/fs/iso9660/src/lmsb16.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <stdint.h> +#include <string.h> + +uint16_t iso9660_lmsb16(const struct iso9660_lmsb16 *const p) +{ + const uint16_t *const d = (const void *)(ISO9660_LE ? p->le : p->be); + uint16_t ret; + + memcpy(&ret, d, sizeof ret); + return ret; +} diff --git a/src/fs/iso9660/src/lmsb32.c b/src/fs/iso9660/src/lmsb32.c new file mode 100644 index 0000000..2811226 --- /dev/null +++ b/src/fs/iso9660/src/lmsb32.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <stdint.h> +#include <string.h> + +uint32_t iso9660_lmsb32(const struct iso9660_lmsb32 *const p) +{ + const uint32_t *const d = (const void *)(ISO9660_LE ? p->le : p->be); + uint32_t ret; + + memcpy(&ret, d, sizeof ret); + return ret; +} diff --git a/src/fs/iso9660/src/mkdir.c b/src/fs/iso9660/src/mkdir.c new file mode 100644 index 0000000..9d30659 --- /dev/null +++ b/src/fs/iso9660/src/mkdir.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <fs/fs.h> +#include <fs/inode.h> + +int iso9660_mkdir(const struct fs_mkdir *const m, const struct fs_mp *const mp, + const union inode_result *const inode, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/iso9660/src/mount.c b/src/fs/iso9660/src/mount.c new file mode 100644 index 0000000..83e7a6d --- /dev/null +++ b/src/fs/iso9660/src/mount.c @@ -0,0 +1,180 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <fs/fs.h> +#include <kprintf.h> +#include <state.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +struct mount +{ + char *src, *tgt; + struct fs_fd fd; + struct fs_ret *r; + struct fs_mount mount; + struct iso9660_header header; + const struct fs_mp *mp; +}; + +static void free_mount(struct mount *const m) +{ + if (!m) + return; + + m->mp->fs->close(&m->fd); + free(m->src); + free(m->tgt); + free(m); +} + +static enum state check_header(void *const args) +{ + enum state ret = STATE_OK; + struct mount *const m = args; + + if (iso9660_check_header(&m->header.magic)) + ret = STATE_FATAL; + else if (fs_mountpoint(m->src, m->tgt, &iso9660, NULL, NULL)) + { + kprintf("Failed to allocate mountpoint {source=%s, target=%s}\n", + m->src, m->tgt); + ret = STATE_FATAL; + } + + free_mount(m); + return ret; +} + +static enum state read_header(void *const args) +{ + struct mount *const m = args; + struct fs_fd *const fd = &m->fd; + const struct fs *const fs = m->mp->fs; + const struct fs_read r = + { + .buf = &m->header, + .n = sizeof m->header, + .fd = fd + }; + + if (fd->error) + { + errno = fd->error; + goto failure; + } + + *m->r = (const struct fs_ret) + { + .f = check_header, + .args = m + }; + + fd->offset = 16 * ISO9660_SECTOR_SZ; + + if (fs->read(&r, m->r)) + goto failure; + + return STATE_AGAIN; + +failure: + free_mount(m); + return STATE_FATAL; +} + +static int search_done(const enum state state, const char *const relpath, + const struct fs_mp *const mp, const union inode_result *const inode, + void *const args) +{ + struct mount *const m = args; + const struct fs_mount *const fm = &m->mount; + + if (!inode) + { + errno = ENOENT; + goto failure; + } + + const struct fs_open o = + { + .fd = &m->fd, + .gid = fm->gid, + .uid = fm->uid, + .mode = fm->mode, + .path = relpath + }; + + *m->r = (const struct fs_ret) + { + .f = read_header, + .args = m + }; + + if (mp->fs->open(&o, mp, inode, m->r)) + goto failure; + + m->mp = mp; + return 0; + +failure: + free_mount(m); + return -1; +} + +int iso9660_mount(const struct fs_mount *const fm, struct fs_ret *const r) +{ + char *srcdup = NULL, *tgtdup = NULL; + struct mount *const m = malloc(sizeof *m); + + if (!m + || !(srcdup = strdup(fm->src)) + || !(tgtdup = strdup(fm->tgt))) + goto failure; + + *m = (const struct mount) + { + .src = srcdup, + .tgt = tgtdup, + .mount = *fm, + .r = r + }; + + const struct inode_search s = + { + .args = m, + .path = fm->src, + .done = search_done + }; + + if (inode_search(&s, r)) + goto failure; + + return 0; + +failure: + free(srcdup); + free(tgtdup); + free(m); + return -1; +} diff --git a/src/fs/iso9660/src/open.c b/src/fs/iso9660/src/open.c new file mode 100644 index 0000000..1ea6ad7 --- /dev/null +++ b/src/fs/iso9660/src/open.c @@ -0,0 +1,107 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <errno.h> +#include <stdlib.h> + +struct open +{ + struct inode inode; + struct fs_fd *fd; + struct fs_ret *pr, r; + const struct fs_mp *mp; +}; + +static int search_done(const enum state state, const char *const relpath, + const struct fs_mp *const mp, const union inode_result *const inode, + void *const args) +{ + int ret = 0; + struct open *const op = args; + const struct inode *const mpinode = &op->inode; + struct fs_fd *const fd = op->fd; + + if (mpinode->flags & INODE_DIR) + { + fd->error = EISDIR; + ret = -1; + } + else if (state) + { + fd->error = ENODEV; + ret = -1; + } + else + { + *fd = (const struct fs_fd) + { + .start = mpinode->prv->offset, + .tgt_inode.cachei = op->inode, + .size = mpinode->size, + .tgt_mp = op->mp, + .inode = *inode, + .mp = mp + }; + + *op->pr = op->r; + } + + free(op); + return ret; +} + +int iso9660_open(const struct fs_open *const o, const struct fs_mp *const mp, + const union inode_result *const inode, struct fs_ret *const r) +{ + const struct inode *const i = &inode->cachei; + struct open *const op = malloc(sizeof *op); + + if (!op) + return -1; + + const struct inode_search s = + { + .args = op, + .path = mp->src, + .done = search_done + }; + + *op = (const struct open) + { + .fd = o->fd, + .inode = *i, + .mp = mp, + .pr = r, + .r = *r + }; + + if (inode_search(&s, r)) + goto failure; + + return 0; + +failure: + free(op); + return -1; +} diff --git a/src/fs/iso9660/src/read.c b/src/fs/iso9660/src/read.c new file mode 100644 index 0000000..6e14845 --- /dev/null +++ b/src/fs/iso9660/src/read.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <fs/fs.h> +#include <stddef.h> + +int iso9660_read(const struct fs_read *const fr, struct fs_ret *const ret) +{ + return -1; +} diff --git a/src/fs/iso9660/src/register.c b/src/fs/iso9660/src/register.c new file mode 100644 index 0000000..70a33f9 --- /dev/null +++ b/src/fs/iso9660/src/register.c @@ -0,0 +1,44 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <fs/fs.h> + +const struct fs iso9660 = +{ + .type = "iso9660", + .flags = FS_DEV_REQUIRED, + .mount = iso9660_mount, + .stat = iso9660_stat, + .mkdir = iso9660_mkdir, + .open = iso9660_open, + .read = iso9660_read, + .write = iso9660_write, + .close = iso9660_close, + .eof = iso9660_eof, + .iops = + { + .search = iso9660_search + } +}; + +int iso9660_register(void) +{ + return fs_register(&iso9660); +} diff --git a/src/fs/iso9660/src/search.c b/src/fs/iso9660/src/search.c new file mode 100644 index 0000000..a7a5150 --- /dev/null +++ b/src/fs/iso9660/src/search.c @@ -0,0 +1,557 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <fs/fs.h> +#include <kprintf.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +struct id +{ + char buf[UCHAR_MAX]; +}; + +struct search +{ + union inode_result *inode; + const struct fs_mp *src_mp; + struct iso9660_entry entry; + const char *src, *path; + struct fs_ret r, *pr; + struct fs_fd fd; + off_t offset; + size_t token_i; + char *token; + void *buf; + struct id id; +}; + +static int prepare_entry(struct search *); +static int next_entry(struct search *); + +static void free_search(struct search *const s) +{ + if (!s) + return; + else if (s->src_mp) + s->src_mp->fs->close(&s->fd); + + free(s->buf); + free(s->token); + free(s); +} + +static int set_inode(struct search *const s, + const struct iso9660_entry *const e, const struct id *const id) +{ + struct inode *const inode = &s->inode->cachei; + struct inode_prv *p = NULL; + char *namedup = NULL; + struct timespec ts, atim; + + if (clock_gettime(CLOCK_REALTIME, &atim)) + goto failure; + else if (iso9660_etotimespec(&e->dt, &ts)) + { + kprintf("Invalid datetime, path=%s\n", s->path); + goto failure; + } + else if (!(namedup = strdup(id->buf)) || !(p = malloc(sizeof *p))) + goto failure; + + *p = (const struct inode_prv) + { + .offset = iso9660_lmsb32(&e->extent_loc) * ISO9660_SECTOR_SZ + }; + + *inode = (const struct inode) + { + .size = iso9660_lmsb32(&e->data_len), + .flags = INODE_REGFILE, + .name = namedup, + .mode = 0555, + .atim = atim, + .free = free, + .ctim = ts, + .mtim = ts, + .prv = p + }; + + return 0; + +failure: + free(p); + free(namedup); + return -1; +} + +static int next_token(struct search *const s) +{ + free(s->token); + s->token = NULL; + + if (fs_next(s->path, &s->token, &s->token_i)) + { + kprintf("Failed to extract next token, path=%s, i=%zu\n", s->path, + s->token_i); + return -1; + } + + return 0; +} + +static int check_version(const char *const version) +{ + char *end; + + errno = 0; + strtoul(version, &end, 10); + + return errno || *end; +} + +static void extract_id(const char *id, struct id *const out, + const char *const ext, const char *const version) +{ + char *p = out->buf; + + if (ext) + { + const ptrdiff_t n = ext - id; + const char *const e = ext + 1; + + memcpy(p, id, n); + p += n; + id += n; + + if (*e) + { + const ptrdiff_t n = version ? version - e : strlen(e); + + memcpy(p, id, n); + p += n; + } + } + else if (version) + { + memcpy(p, id, version - id); + p += version - id; + } + else + { + const ptrdiff_t n = strlen(id); + + memcpy(p, id, n); + p += n; + } + + *p = '\0'; + p = out->buf; + + while (*p) + { + *p = tolower(*p); + p++; + } +} + +static int parse_id(const char *const id, struct id *const out) +{ + static const char accept[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + const char *const ext = strchr(id, '.'), *const version = strchr(id, ';'); + const size_t n = strspn(id, accept), len = strlen(id); + + /* Ensure only valid characters are met if no version or extension. */ + if (!version && !ext && n != len) + return -1; + /* Ensure file version appears only after file extension, + * if both are present. */ + else if (version && ext && ext > version) + return -1; + /* Ensure one and only one file version and/or extension appear. */ + else if ((version && strchr(version + 1, ';')) + || (ext && strchr(ext + 1, '.'))) + return -1; + else if (version && check_version(version + 1)) + return -1; + /* When present, ensure valid characters only until the file extension + * is found. */ + else if (ext && n != ext - id) + return -1; + + extract_id(id, out, ext, version); + return 0; +} + +static enum state id_read(void *const args) +{ + struct search *volatile const s = args; + const struct iso9660_entry *const e = &s->entry; + const char *const id = s->id.buf; + struct id outid; + + if (!*id || !strcmp(id, "\1")) + { + if (next_entry(s)) + goto failure; + } + else if (parse_id(id, &outid)) + { + kprintf("Invalid file or directory identifier=%s\n", id); + goto failure; + } + else if (!strcmp(outid.buf, s->token)) + { + char *token; + + if (fs_next(s->path, &token, &s->token_i)) + { + kprintf("Failed to extract next token, path=%s, i=%zu\n", + s->path, s->token_i); + goto failure; + } + else if (!token) + { + if (set_inode(s, e, &outid)) + goto failure; + + *s->pr = s->r; + free_search(s); + return STATE_AGAIN; + } + else if (!(e->flags & ISO9660_FLAGS_DIR)) + { + kprintf("Intermediate node %s not a directory, path=%s\n", + id, s->path); + goto failure; + } + else + { + s->fd.offset = iso9660_lmsb32(&e->extent_loc) * ISO9660_SECTOR_SZ; + + if (prepare_entry(s)) + goto failure; + } + + free(s->token); + free(s->buf); + s->token = token; + s->buf = NULL; + } + else if (next_entry(s)) + goto failure; + + return STATE_AGAIN; + +failure: + free_search(s); + return STATE_FATAL; +} + +static enum state entry_read(void *const args) +{ + struct search *const s = args; + const struct iso9660_entry *const e = &s->entry; + + if (e->len < sizeof *e) + { + kprintf("Unexpected entry length %hhu, expected %zu\n", e->len, + sizeof *e); + goto failure; + } + + char *const buf = s->id.buf; + const struct fs_mp *const mp = s->fd.mp; + const struct fs_read r = + { + .buf = buf, + .n = e->id_len, + .fd = &s->fd + }; + + *(buf + e->id_len) = '\0'; + *s->pr = (const struct fs_ret) + { + .f = id_read, + .args = s + }; + + if (mp->fs->read(&r, s->pr)) + goto failure; + + return STATE_AGAIN; + +failure: + free_search(s); + return STATE_FATAL; +} + +static int prepare_entry(struct search *const s) +{ + const struct fs_read r = + { + .buf = &s->entry, + .fd = &s->fd, + .n = sizeof s->entry + }; + + *s->pr = (const struct fs_ret) + { + .f = entry_read, + .args = s + }; + + s->offset = s->fd.offset; + return s->src_mp->fs->read(&r, s->pr); +} + +static int next_entry(struct search *const s) +{ + const struct iso9660_entry *const e = &s->entry; + struct fs_fd *const fd = &s->fd; + + fd->offset = s->offset + e->len; + return prepare_entry(s); +} + +static int set_root_inode(const struct iso9660_pvd *const pvd, + struct search *const s) +{ + struct inode *const inode = &s->inode->cachei; + struct inode_prv *p = NULL; + char *namedup = NULL; + + if (clock_gettime(CLOCK_REALTIME, &inode->atim)) + goto failure; + else if (iso9660_totimespec(&pvd->creat, &inode->ctim)) + { + kprintf("Invalid volume creation time\n"); + goto failure; + } + else if (iso9660_totimespec(&pvd->mod, &inode->mtim)) + { + kprintf("Invalid volume modification time\n"); + goto failure; + } + else if (!(namedup = strdup("/")) || !(p = malloc(sizeof *p))) + goto failure; + + *p = (const struct inode_prv) + { + .offset = offsetof(struct iso9660_pvd, root_dir) + }; + + inode->flags = INODE_DIR; + inode->mode = 0555; + inode->name = namedup; + inode->prv = p; + *s->pr = s->r; + free_search(s); + return 0; + +failure: + free(p); + free(namedup); + return -1; +} + +static int check_pvd(const struct iso9660_vd *const vd) +{ + const struct iso9660_pvd *const pvd = &vd->u.pvd; + const struct iso9660_entry *const e = &pvd->root_dir; + const struct iso9660_header *const h = &vd->header; + const uint16_t block_size = iso9660_lmsb16(&pvd->block_size); + const size_t exp_sz = sizeof (struct iso9660_entry) + sizeof pvd->padding; + + if (iso9660_check_header(&h->magic)) + return -1; + else if (h->version != 1) + { + kprintf("Unsupported ISO9660 version %#hhx, expected 1\n", h->version); + return -1; + } + else if (h->type != ISO9660_TYPE_PRIMARY_VD) + { + kprintf("Unexpected volume descriptor type %#hhx, expected=%#x\n", + h->type, ISO9660_TYPE_PRIMARY_VD); + return -1; + } + else if (pvd->fs_version != 1) + { + kprintf("Unexpected file structure version %#hhx, expected 1\n", + pvd->fs_version); + return -1; + } + else if (block_size != ISO9660_SECTOR_SZ) + { + kprintf("Unsupported block size %" PRIu16 ", expected %d\n", + block_size, ISO9660_SECTOR_SZ); + return -1; + } + else if (e->len != exp_sz) + { + kprintf("Unexpected root directory length %hhd, expected %zu\n", + e->len, exp_sz); + return -1; + } + else if (!(e->flags & ISO9660_FLAGS_DIR)) + { + kprintf("Directory flag (%#hx) not found in file flags (%#hhx)\n", + ISO9660_FLAGS_DIR, e->flags); + return -1; + } + + return 0; +} + +static enum state read_pvd_done(void *const args) +{ + struct search *const s = args; + struct fs_fd *const fd = &s->fd; + const struct iso9660_vd *const vd = s->buf; + const struct iso9660_pvd *const pvd = &vd->u.pvd; + const struct iso9660_entry *const e = &pvd->root_dir; + const uint32_t lba = iso9660_lmsb32(&e->extent_loc); + + fd->offset = lba * ISO9660_SECTOR_SZ; + + if (check_pvd(vd)) + goto failure; + else if (!strcmp(s->src, "/")) + { + if (set_root_inode(pvd, s)) + goto failure; + + return STATE_AGAIN; + } + else if (next_token(s) || prepare_entry(s)) + goto failure; + + return STATE_AGAIN; + +failure: + free_search(s); + return STATE_FATAL; +} + +static enum state read_pvd(void *const args) +{ + struct search *const s = args; + struct fs_fd *const fd = &s->fd; + + if (!(s->buf = malloc(ISO9660_SECTOR_SZ)) || next_token(s)) + goto failure; + + const struct fs_read r = + { + .buf = s->buf, + .fd = fd, + .n = ISO9660_SECTOR_SZ + }; + + *s->pr = (const struct fs_ret) + { + .f = read_pvd_done, + .args = s + }; + + fd->offset = 16 * ISO9660_SECTOR_SZ; + + if (s->src_mp->fs->read(&r, s->pr)) + goto failure; + + return STATE_AGAIN; + +failure: + free_search(s); + return STATE_FATAL; +} + +static int src_done(const enum state state, const char *const relpath, + const struct fs_mp *const mp, const union inode_result *const inode, + void *const args) +{ + struct search *const s = args; + + if (state) + { + kprintf("Failed to find source inode for %s\n", s->src); + return -1; + } + + s->src_mp = mp; + *s->pr = (const struct fs_ret) + { + .f = read_pvd, + .args = s + }; + + const struct fs_open o = + { + .fd = &s->fd, + .path = mp->src, + .flags = O_RDONLY + }; + + return mp->fs->open(&o, mp, inode, s->pr); +} + +int iso9660_search(const char *const path, const struct fs_mp *const mp, + union inode_result *const inode, struct fs_ret *const r) +{ + struct search *const s = malloc(sizeof *s); + + if (!s) + goto failure; + + *s = (const struct search) + { + .inode = inode, + .src = mp->src, + .path = path, + .r = *r, + .pr = r + }; + + const struct inode_search is = + { + .path = mp->src, + .done = src_done, + .args = s, + }; + + if (inode_search(&is, r)) + goto failure; + + return 0; + +failure: + free(s); + return -1; +} diff --git a/src/fs/iso9660/src/stat.c b/src/fs/iso9660/src/stat.c new file mode 100644 index 0000000..53732fe --- /dev/null +++ b/src/fs/iso9660/src/stat.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <fs/fs.h> +#include <sys/stat.h> + +int iso9660_stat(const struct fs_stat *const s, const struct fs_mp *const mp, + const union inode_result *const inode, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/iso9660/src/totimespec.c b/src/fs/iso9660/src/totimespec.c new file mode 100644 index 0000000..735deb7 --- /dev/null +++ b/src/fs/iso9660/src/totimespec.c @@ -0,0 +1,54 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +int iso9660_totimespec(const struct iso9660_dt *const dt, + struct timespec *const ts) +{ + char hsec[sizeof dt->hsec + 1], *end; + unsigned long v; + struct tm tm; + time_t t; + + if (iso9660_totm(dt, &tm) + || ((t = mktime(&tm)) == (time_t)-1)) + return -1; + + errno = 0; + memcpy(hsec, dt->hsec, sizeof dt->hsec); + hsec[sizeof dt->hsec] = '\0'; + v = strtoul(hsec, &end, 10); + + if (errno || *end || v >= 100) + return -1; + + *ts = (const struct timespec) + { + .tv_sec = t, + .tv_nsec = v * 100000ul + }; + + return 0; +} diff --git a/src/fs/iso9660/src/totm.c b/src/fs/iso9660/src/totm.c new file mode 100644 index 0000000..1e94359 --- /dev/null +++ b/src/fs/iso9660/src/totm.c @@ -0,0 +1,72 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/routines.h> +#include <iso9660/types.h> +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +int iso9660_totm(const struct iso9660_dt *const dt, struct tm *const tm) +{ + char year[sizeof dt->year + 1], + month[sizeof dt->month + 1], + day[sizeof dt->day + 1], + hour[sizeof dt->hour + 1], + min[sizeof dt->min + 1], + sec[sizeof dt->sec + 1]; + + struct buf + { + const char *src; + char *s; + int *v; + size_t n; + } bufs[] = + { + {.src = dt->year, .s = year, .n = sizeof dt->year, .v = &tm->tm_year}, + {.src = dt->month, .s = month, .n = sizeof dt->month, .v = &tm->tm_mon}, + {.src = dt->day, .s = day, .n = sizeof dt->day, .v = &tm->tm_yday}, + {.src = dt->hour, .s = hour, .n = sizeof dt->hour, .v = &tm->tm_hour}, + {.src = dt->min, .s = min, .n = sizeof dt->min, .v = &tm->tm_min}, + {.src = dt->sec, .s = sec, .n = sizeof dt->sec, .v = &tm->tm_sec} + }; + + for (size_t i = 0; i < sizeof bufs / sizeof *bufs; i++) + { + struct buf *const b = &bufs[i]; + unsigned long v; + char *end; + + memcpy(b->s, b->src, b->n - 1); + b->s[b->n] = '\0'; + errno = 0; + v = strtoul(b->s, &end, 10); + + if (errno || *end || v > INT_MAX) + return -1; + + *b->v = v; + } + + return 0; +} diff --git a/src/fs/iso9660/src/write.c b/src/fs/iso9660/src/write.c new file mode 100644 index 0000000..2ce3823 --- /dev/null +++ b/src/fs/iso9660/src/write.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <iso9660.h> +#include <iso9660/ops.h> +#include <fs/fs.h> +#include <errno.h> + +int iso9660_write(const struct fs_write *const w, struct fs_ret *const r) +{ + errno = EROFS; + return -1; +} diff --git a/src/fs/private_include/fs/private.h b/src/fs/private_include/fs/private.h new file mode 100644 index 0000000..9ccebaf --- /dev/null +++ b/src/fs/private_include/fs/private.h @@ -0,0 +1,63 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef FS_TYPES_H +#define FS_TYPES_H + +#include <fs/fs.h> +#include <fs/inode.h> +#include <state.h> +#include <sys/types.h> + +struct fs_fd_prv; + +struct fs_register +{ + const struct fs *fs; + struct fs_register *next; +}; + +struct fs_mountpoint +{ + char *src, *tgt; + const struct fs *fs; + struct fs_mp_prv *prv; + struct fs_mountpoint *next; + fs_update_fn update; +}; + +struct fs_add +{ + char *src, *tgt; + struct inode_search *search; + struct inode *inode; + mode_t mode; + const struct fs *fs; + enum state (*next)(struct fs_add *); +}; + +struct fs_fd +{ + long off; + struct fs_fd_prv *prv; +}; + +extern struct fs_register *fs_rhead, *fs_rtail; +extern struct fs_mountpoint *fs_mphead, *fs_mptail; + +#endif diff --git a/src/fs/private_include/fs/types.h b/src/fs/private_include/fs/types.h new file mode 100644 index 0000000..e860d77 --- /dev/null +++ b/src/fs/private_include/fs/types.h @@ -0,0 +1,55 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef FS_TYPES_H +#define FS_TYPES_H + +#include <fs/fs.h> +#include <fs/inode.h> +#include <state.h> +#include <sys/types.h> + +struct fs_register +{ + const struct fs *fs; + struct fs_register *next; +}; + +struct fs_mountpoint +{ + char *src, *tgt; + const struct fs *fs; + struct fs_mp_prv *prv; + struct fs_mountpoint *next; + fs_update_fn update; +}; + +struct fs_add +{ + char *src, *tgt; + struct inode_search *search; + struct inode *inode; + mode_t mode; + const struct fs *fs; + enum state (*next)(struct fs_add *); +}; + +extern struct fs_register *fs_rhead, *fs_rtail; +extern struct fs_mountpoint *fs_mphead, *fs_mptail; + +#endif diff --git a/src/fs/ramfs/CMakeLists.txt b/src/fs/ramfs/CMakeLists.txt new file mode 100644 index 0000000..477e8a7 --- /dev/null +++ b/src/fs/ramfs/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(ramfs) +add_subdirectory(src) +target_include_directories(ramfs PUBLIC include PRIVATE private_include) +target_link_libraries(ramfs PUBLIC state c PRIVATE fs drv) diff --git a/src/fs/ramfs/include/ramfs.h b/src/fs/ramfs/include/ramfs.h new file mode 100644 index 0000000..74160e1 --- /dev/null +++ b/src/fs/ramfs/include/ramfs.h @@ -0,0 +1,43 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef RAMFS_H +#define RAMFS_H + +#include <fs/fs.h> +#include <fs/inode.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stddef.h> + +struct ramfs *ramfs_mount(const struct fs_mount *m, struct fs_ret *r); +int ramfs_mkdir(const struct fs_mkdir *m, struct ramfs *rfs, + const union inode_result *i, struct fs_ret *r); +int ramfs_open(const struct fs_open *o, struct inode *i, struct fs_ret *r); +int ramfs_read(const struct fs_read *r, struct fs_ret *ret); +int ramfs_write(const struct fs_write *w, struct fs_ret *r); +int ramfs_stat(const struct fs_stat *s, const struct ramfs *rfs, + const union inode_result *inode, struct fs_ret *r); +int ramfs_close(struct fs_fd *fd); +int ramfs_search(const char *path, const struct ramfs *rfs, + union inode_result *inode, struct fs_ret *r); +int ramfs_flags(const union inode_result *i); +int ramfs_mknod(const char *node, mode_t mode, dev_t dev, struct ramfs *rfs); +void ramfs_free(struct ramfs *rfs); + +#endif diff --git a/src/fs/ramfs/private_include/ramfs/types.h b/src/fs/ramfs/private_include/ramfs/types.h new file mode 100644 index 0000000..9be5899 --- /dev/null +++ b/src/fs/ramfs/private_include/ramfs/types.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef RAMFS_TYPES_H +#define RAMFS_TYPES_H + +#include <fs/fs.h> +#include <fs/inode.h> + +struct ramfs +{ + struct inode *root; + ino_t ino; +}; + +#endif diff --git a/src/fs/ramfs/src/CMakeLists.txt b/src/fs/ramfs/src/CMakeLists.txt new file mode 100644 index 0000000..a35e23e --- /dev/null +++ b/src/fs/ramfs/src/CMakeLists.txt @@ -0,0 +1,29 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(ramfs PRIVATE + close.c + free.c + flags.c + mount.c + mkdir.c + mknod.c + open.c + stat.c + read.c + search.c + write.c +) diff --git a/src/fs/ramfs/src/close.c b/src/fs/ramfs/src/close.c new file mode 100644 index 0000000..5243a77 --- /dev/null +++ b/src/fs/ramfs/src/close.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <fs/fs.h> + +int ramfs_close(struct fs_fd *const fd) +{ + return -1; +} diff --git a/src/fs/ramfs/src/flags.c b/src/fs/ramfs/src/flags.c new file mode 100644 index 0000000..7f51b81 --- /dev/null +++ b/src/fs/ramfs/src/flags.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <fs/inode.h> + +int ramfs_flags(const union inode_result *const i) +{ + return i->memi->flags; +} diff --git a/src/fs/ramfs/src/free.c b/src/fs/ramfs/src/free.c new file mode 100644 index 0000000..10fcbd6 --- /dev/null +++ b/src/fs/ramfs/src/free.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <ramfs/types.h> +#include <stddef.h> +#include <stdlib.h> + +void ramfs_free(struct ramfs *const r) +{ + if (!r) + return; + + inode_free(r->root); + free(r); +} diff --git a/src/fs/ramfs/src/mkdir.c b/src/fs/ramfs/src/mkdir.c new file mode 100644 index 0000000..f62984d --- /dev/null +++ b/src/fs/ramfs/src/mkdir.c @@ -0,0 +1,79 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <ramfs/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <state.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static enum state done(void *const args) +{ + return STATE_OK; +} + +int ramfs_mkdir(const struct fs_mkdir *const m, struct ramfs *const rfs, + const union inode_result *const inode, struct fs_ret *const r) +{ + struct timespec ts; + struct inode *ni = NULL; + struct inode *const parent = inode->memi; + char *const name = strdup(m->path); + + if (!name + || clock_gettime(CLOCK_REALTIME, &ts) + || !(ni = malloc(sizeof *ni))) + goto failure; + + *ni = (const struct inode) + { + .name = name, + .mode = m->mode, + .uid = m->uid, + .gid = m->gid, + .flags = INODE_DIR, + .atim = ts, + .ctim = ts, + .mtim = ts, + .ino = rfs->ino++, + .parent = parent + }; + + if (!parent->child) + parent->child = ni; + else + for (struct inode *i = parent->child; i; i = i->right) + if (!i->right) + { + i->right = ni; + ni->left = i; + break; + } + + parent->atim = parent->mtim = ts; + *r = (const struct fs_ret){.f = done}; + return 0; + +failure: + free(ni); + free(name); + return -1; +} diff --git a/src/fs/ramfs/src/mknod.c b/src/fs/ramfs/src/mknod.c new file mode 100644 index 0000000..d142ab1 --- /dev/null +++ b/src/fs/ramfs/src/mknod.c @@ -0,0 +1,87 @@ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <ramfs/types.h> +#include <fs/inode.h> +#include <sys/types.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static struct inode *find(const char *const node, struct inode *const root) +{ + for (struct inode *c = root->child; c; c = c->right) + if (!strcmp(c->name, node)) + return c; + + return NULL; +} + +int ramfs_mknod(const char *const node, const mode_t mode, const dev_t dev, + struct ramfs *const rfs) +{ + struct inode *const r = rfs->root, + *const inode = find(node, r), + *newinode = NULL; + char *nodedup = NULL; + struct timespec ts; + + if (inode) + { + errno = EEXIST; + goto failure; + } + else if (clock_gettime(CLOCK_REALTIME, &ts) + || !(nodedup = strdup(node)) + || !(newinode = malloc(sizeof *newinode))) + goto failure; + + *newinode = (const struct inode) + { + .atim = ts, + .ctim = ts, + .mtim = ts, + .flags = INODE_BLOCKDEV, + .mode = mode, + .parent = rfs->root, + .name = nodedup + }; + + if (!r->child) + r->child = newinode; + else + for (struct inode *c = r->child; c; c = c->right) + if (!c->right) + { + c->right = newinode; + newinode->left = c; + break; + } + + r->atim = r->mtim = ts; + return 0; + +failure: + free(nodedup); + free(newinode); + return -1; +} diff --git a/src/fs/ramfs/src/mount.c b/src/fs/ramfs/src/mount.c new file mode 100644 index 0000000..567c2da --- /dev/null +++ b/src/fs/ramfs/src/mount.c @@ -0,0 +1,69 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <ramfs/types.h> +#include <fs/fs.h> +#include <state.h> +#include <sys/types.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static enum state mount(void *const args) +{ + return STATE_OK; +} + +struct ramfs *ramfs_mount(const struct fs_mount *const m, + struct fs_ret *const r) +{ + struct ramfs *ret = NULL; + struct timespec ts; + char *const name = strdup("/"); + struct inode *root = NULL; + + if (!name + || clock_gettime(CLOCK_REALTIME, &ts) + || !(root = malloc(sizeof *root)) + || !(ret = malloc(sizeof *ret))) + goto failure; + + *root = (const struct inode) + { + .name = name, + .mode = m->mode, + .uid = m->uid, + .gid = m->gid, + .atim = ts, + .mtim = ts, + .ctim = ts + }; + + *ret = (const struct ramfs){.root = root}; + *r = (const struct fs_ret){.f = mount}; + ret->ino++; + return ret; + +failure: + free(root); + free(ret); + free(name); + return NULL; +} diff --git a/src/fs/ramfs/src/open.c b/src/fs/ramfs/src/open.c new file mode 100644 index 0000000..894b160 --- /dev/null +++ b/src/fs/ramfs/src/open.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <fs/fs.h> + +int ramfs_open(const struct fs_open *const o,struct inode *const i, + struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/ramfs/src/read.c b/src/fs/ramfs/src/read.c new file mode 100644 index 0000000..cc96744 --- /dev/null +++ b/src/fs/ramfs/src/read.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <fs/fs.h> +#include <stddef.h> + +int ramfs_read(const struct fs_read *const r, struct fs_ret *const ret) +{ + return -1; +} diff --git a/src/fs/ramfs/src/search.c b/src/fs/ramfs/src/search.c new file mode 100644 index 0000000..24e2a98 --- /dev/null +++ b/src/fs/ramfs/src/search.c @@ -0,0 +1,143 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <ramfs/types.h> +#include <fs/fs.h> +#include <state.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +struct search +{ + union inode_result *inode; + const struct ramfs *rfs; + struct fs_ret r, *pr; + const char *path; +}; + +static void free_search(struct search *const s) +{ + free(s); +} + +static int find_node(const char *const path, struct inode **const out, + size_t *const i) +{ + int ret = -1; + char *node; + struct inode *volatile const inode = *out; + + if (fs_next(path, &node, i)) + return -1; + else if (!strcmp(inode->name, node)) + { + if (*i >= strlen(path)) + { + free(node); + return 1; + } + + *out = inode->child; + } + else + { + bool found = false; + + for (struct inode *in = inode->right; in; in = in->right) + if (!strcmp(in->name, node)) + { + if (*i >= strlen(path)) + { + *out = in; + free(node); + return 1; + } + + *out = in->child; + found = true; + break; + } + + if (!found) + goto end; + } + + ret = 0; + +end: + free(node); + return ret; +} + +static enum state search(void *const args) +{ + enum state ret = STATE_FATAL; + struct search *const s = args; + struct inode *inode = s->rfs->root; + size_t i = 0; + + for (;;) + { + const int n = find_node(s->path, &inode, &i); + + if (n < 0) + goto end; + else if (n > 0) + break; + } + + s->inode->memi = inode; + *s->pr = s->r; + ret = STATE_AGAIN; + +end: + free_search(s); + return ret; +} + +int ramfs_search(const char *const path, const struct ramfs *const rfs, + union inode_result *const inode, struct fs_ret *const r) +{ + struct search *const s = malloc(sizeof *s); + + if (!s) + goto failure; + + *s = (const struct search) + { + .inode = inode, + .path = path, + .rfs = rfs, + .r = *r, + .pr = r + }; + + *r = (const struct fs_ret) + { + .f = search, + .args = s + }; + + return 0; + +failure: + free(s); + return -1; +} diff --git a/src/fs/ramfs/src/stat.c b/src/fs/ramfs/src/stat.c new file mode 100644 index 0000000..6bb1b23 --- /dev/null +++ b/src/fs/ramfs/src/stat.c @@ -0,0 +1,53 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <fs/fs.h> +#include <state.h> +#include <sys/stat.h> + +static enum state done(void *const args) +{ + return STATE_OK; +} + +int ramfs_stat(const struct fs_stat *const s, const struct ramfs *const rfs, + const union inode_result *const inode, struct fs_ret *const r) +{ + const struct inode *const i = inode->memi; + + *s->sb = (const struct stat) + { + .st_atim = i->atim, + .st_ctim = i->ctim, + .st_mtim = i->mtim, + .st_size = i->size, + .st_blksize = 1, + .st_ino = i->ino, + .st_uid = i->uid, + .st_gid = i->gid, + .st_mode = i->mode + }; + + *r = (const struct fs_ret) + { + .f = done + }; + + return 0; +} diff --git a/src/fs/ramfs/src/write.c b/src/fs/ramfs/src/write.c new file mode 100644 index 0000000..ca49c22 --- /dev/null +++ b/src/fs/ramfs/src/write.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ramfs.h> +#include <fs/fs.h> +#include <stddef.h> + +int ramfs_write(const struct fs_write *const w, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/rootfs/CMakeLists.txt b/src/fs/rootfs/CMakeLists.txt new file mode 100644 index 0000000..588d14b --- /dev/null +++ b/src/fs/rootfs/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(rootfs) +add_subdirectory(src) +target_include_directories(rootfs PUBLIC include PRIVATE private_include) +target_link_libraries(rootfs PUBLIC state c PRIVATE fs ramfs) diff --git a/src/fs/rootfs/include/rootfs.h b/src/fs/rootfs/include/rootfs.h new file mode 100644 index 0000000..2327079 --- /dev/null +++ b/src/fs/rootfs/include/rootfs.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ROOTFS_H +#define ROOTFS_H + +int rootfs_register(void); + +#endif diff --git a/src/fs/rootfs/private_include/rootfs/ops.h b/src/fs/rootfs/private_include/rootfs/ops.h new file mode 100644 index 0000000..decdf8b --- /dev/null +++ b/src/fs/rootfs/private_include/rootfs/ops.h @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ROOTFS_OPS_H +#define ROOTFS_OPS_H + +#include <fs/fs.h> +#include <fs/inode.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stddef.h> + +int rootfs_mount(const struct fs_mount *m, struct fs_ret *r); +int rootfs_mkdir(const struct fs_mkdir *m, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int rootfs_open(const struct fs_open *o, const struct fs_mp *mp, + const union inode_result *i, struct fs_ret *r); +int rootfs_read(const struct fs_read *r, struct fs_ret *ret); +int rootfs_write(const struct fs_write *w, struct fs_ret *r); +int rootfs_stat(const struct fs_stat *s, const struct fs_mp *mp, + const union inode_result *inode, struct fs_ret *r); +int rootfs_close(struct fs_fd *fd); +int rootfs_search(const char *path, const struct fs_mp *mp, + union inode_result *inode, struct fs_ret *r); +int rootfs_flags(const union inode_result *i); + +#endif diff --git a/src/fs/rootfs/private_include/rootfs/types.h b/src/fs/rootfs/private_include/rootfs/types.h new file mode 100644 index 0000000..471d9d3 --- /dev/null +++ b/src/fs/rootfs/private_include/rootfs/types.h @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef ROOTFS_TYPES_H +#define ROOTFS_TYPES_H + +#include <fs/fs.h> +#include <ramfs.h> + +struct fs_mp_prv +{ + struct ramfs *rfs; +}; + +extern const struct fs rootfs; + +#endif diff --git a/src/fs/rootfs/src/CMakeLists.txt b/src/fs/rootfs/src/CMakeLists.txt new file mode 100644 index 0000000..8e295e1 --- /dev/null +++ b/src/fs/rootfs/src/CMakeLists.txt @@ -0,0 +1,28 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(rootfs PRIVATE + close.c + flags.c + mount.c + mkdir.c + open.c + stat.c + read.c + register.c + search.c + write.c +) diff --git a/src/fs/rootfs/src/close.c b/src/fs/rootfs/src/close.c new file mode 100644 index 0000000..1704e48 --- /dev/null +++ b/src/fs/rootfs/src/close.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <fs/fs.h> + +int rootfs_close(struct fs_fd *const fd) +{ + return -1; +} diff --git a/src/fs/rootfs/src/flags.c b/src/fs/rootfs/src/flags.c new file mode 100644 index 0000000..5a0d5a6 --- /dev/null +++ b/src/fs/rootfs/src/flags.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/ops.h> +#include <fs/inode.h> + +int rootfs_flags(const union inode_result *const i) +{ + return i->memi->flags; +} diff --git a/src/fs/rootfs/src/mkdir.c b/src/fs/rootfs/src/mkdir.c new file mode 100644 index 0000000..5f4118f --- /dev/null +++ b/src/fs/rootfs/src/mkdir.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/ops.h> +#include <rootfs/types.h> +#include <fs/fs.h> +#include <fs/inode.h> +#include <ramfs.h> + +int rootfs_mkdir(const struct fs_mkdir *const m, const struct fs_mp *const mp, + const union inode_result *const inode, struct fs_ret *const r) +{ + return ramfs_mkdir(m, mp->prv->rfs, inode, r); +} diff --git a/src/fs/rootfs/src/mount.c b/src/fs/rootfs/src/mount.c new file mode 100644 index 0000000..4ef6258 --- /dev/null +++ b/src/fs/rootfs/src/mount.c @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/types.h> +#include <ramfs.h> +#include <fs/fs.h> +#include <stdlib.h> + +int rootfs_mount(const struct fs_mount *const m, struct fs_ret *const r) +{ + struct ramfs *rfs = NULL; + struct fs_mp_prv *const p = malloc(sizeof *p); + + if (!p + || !(rfs = ramfs_mount(m, r)) + || fs_mountpoint(m->src, m->tgt, &rootfs, NULL, p)) + goto failure; + + *p = (const struct fs_mp_prv){.rfs = rfs}; + return 0; + +failure: + ramfs_free(rfs); + free(p); + return -1; +} diff --git a/src/fs/rootfs/src/open.c b/src/fs/rootfs/src/open.c new file mode 100644 index 0000000..4a88f41 --- /dev/null +++ b/src/fs/rootfs/src/open.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/ops.h> +#include <fs/fs.h> + +int rootfs_open(const struct fs_open *const o, const struct fs_mp *const mp, + const union inode_result *const i, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/rootfs/src/read.c b/src/fs/rootfs/src/read.c new file mode 100644 index 0000000..50fe963 --- /dev/null +++ b/src/fs/rootfs/src/read.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <fs/fs.h> +#include <stddef.h> + +int rootfs_read(const struct fs_read *const r, struct fs_ret *const ret) +{ + return -1; +} diff --git a/src/fs/rootfs/src/register.c b/src/fs/rootfs/src/register.c new file mode 100644 index 0000000..02032d8 --- /dev/null +++ b/src/fs/rootfs/src/register.c @@ -0,0 +1,43 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/ops.h> +#include <fs/fs.h> + +const struct fs rootfs = +{ + .type = "rootfs", + .mount = rootfs_mount, + .stat = rootfs_stat, + .mkdir = rootfs_mkdir, + .open = rootfs_open, + .read = rootfs_read, + .write = rootfs_write, + .close = rootfs_close, + .iops = + { + .search = rootfs_search, + .flags = rootfs_flags + } +}; + +int rootfs_register(void) +{ + return fs_register(&rootfs); +} diff --git a/src/fs/rootfs/src/search.c b/src/fs/rootfs/src/search.c new file mode 100644 index 0000000..269f5d0 --- /dev/null +++ b/src/fs/rootfs/src/search.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/ops.h> +#include <rootfs/types.h> +#include <fs/fs.h> +#include <ramfs.h> + +int rootfs_search(const char *const path, const struct fs_mp *const mp, + union inode_result *const inode, struct fs_ret *const r) +{ + return ramfs_search(path, mp->prv->rfs, inode, r); +} diff --git a/src/fs/rootfs/src/stat.c b/src/fs/rootfs/src/stat.c new file mode 100644 index 0000000..1561190 --- /dev/null +++ b/src/fs/rootfs/src/stat.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <rootfs/ops.h> +#include <fs/fs.h> +#include <sys/stat.h> + +int rootfs_stat(const struct fs_stat *const s, const struct fs_mp *const mp, + const union inode_result *const inode, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/rootfs/src/write.c b/src/fs/rootfs/src/write.c new file mode 100644 index 0000000..874e40c --- /dev/null +++ b/src/fs/rootfs/src/write.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <rootfs.h> +#include <fs/fs.h> +#include <stddef.h> + +int rootfs_write(const struct fs_write *const w, struct fs_ret *const r) +{ + return -1; +} diff --git a/src/fs/src/CMakeLists.txt b/src/fs/src/CMakeLists.txt new file mode 100644 index 0000000..efeb0f1 --- /dev/null +++ b/src/fs/src/CMakeLists.txt @@ -0,0 +1,30 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(fs PRIVATE + from_type.c + headtail.c + mountpoint.c + mp_from_path.c + mps_from_path.c + parent.c + register.c + relpath.c + update.c + next.c +) + +add_subdirectory(inode) diff --git a/src/fs/src/from_type.c b/src/fs/src/from_type.c new file mode 100644 index 0000000..360384b --- /dev/null +++ b/src/fs/src/from_type.c @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +const struct fs *fs_from_type(const char *const type) +{ + for (const struct fs_register *r = fs_rhead; r; r = r->next) + { + const struct fs *const fs = r->fs; + + if (!strcmp(type, fs->type)) + return fs; + } + + return NULL; +} diff --git a/src/fs/src/headtail.c b/src/fs/src/headtail.c new file mode 100644 index 0000000..9df580f --- /dev/null +++ b/src/fs/src/headtail.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/types.h> + +struct fs_register *fs_rhead, *fs_rtail; +struct fs_mountpoint *fs_mphead, *fs_mptail; diff --git a/src/fs/src/inode/CMakeLists.txt b/src/fs/src/inode/CMakeLists.txt new file mode 100644 index 0000000..350dd71 --- /dev/null +++ b/src/fs/src/inode/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(fs PRIVATE + free.c + search.c +) diff --git a/src/fs/src/inode/free.c b/src/fs/src/inode/free.c new file mode 100644 index 0000000..3eca47d --- /dev/null +++ b/src/fs/src/inode/free.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/inode.h> +#include <stdlib.h> + +void inode_free(struct inode *const i) +{ + if (i) + { + inode_free(i->child); + free(i->name); + + if (i->free) + i->free(i->prv); + } + + free(i); +} diff --git a/src/fs/src/inode/search.c b/src/fs/src/inode/search.c new file mode 100644 index 0000000..4715dd2 --- /dev/null +++ b/src/fs/src/inode/search.c @@ -0,0 +1,121 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/inode.h> +#include <fs/fs.h> +#include <fs/types.h> +#include <state.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +struct search +{ + struct fs_mp *mp; + size_t n, mp_i; + struct fs_ret *r; + union inode_result inode; + struct inode_search search; +}; + +static void free_search(struct search *const s) +{ + free(s); +} + +static enum state search_mp(struct search *const s) +{ + const struct inode_search *const is = &s->search; + const struct fs_mp *const cur = &s->mp[s->mp_i], + *const next = s->mp_i + 1 < s->n ? + &s->mp[s->mp_i + 1] : NULL; + const struct fs *const fs = cur->fs; + const char *relpath = next ? next->tgt : is->path; + + for (size_t i = 0; i < s->mp_i; i++) + relpath += strlen(s->mp[s->mp_i].tgt); + + if (fs && fs->iops.search(relpath, cur, &s->inode, s->r)) + return STATE_FATAL; + + s->mp_i++; + return STATE_AGAIN; +} + +static enum state search(void *const args) +{ + struct search *const s = args; + const struct inode_search *const is = &s->search; + + if (!s->mp) + { + const int ret = is->done(STATE_FATAL, NULL, NULL, NULL, is->args); + + free_search(s); + return ret ? STATE_FATAL : STATE_AGAIN; + } + else if (s->mp_i < s->n) + return search_mp(s); + else + { + const char *relpath = is->path; + + for (size_t i = 0; i < s->n; i++) + relpath += strlen(s->mp[i].tgt); + + const int ret = is->done(STATE_OK, relpath, &s->mp[s->n - 1], + &s->inode, is->args); + + free_search(s); + return ret ? STATE_FATAL : STATE_AGAIN; + } + + return STATE_FATAL; +} + +int inode_search(const struct inode_search *const is, struct fs_ret *const r) +{ + struct search *s = NULL; + size_t n; + /* TODO: do not check for errors yet. */ + struct fs_mp *const mp = fs_mps_from_path(is->path, &n); + + if (!(s = malloc(sizeof *s))) + goto failure; + + *s = (const struct search) + { + .search = *is, + .mp = mp, + .n = n, + .r = r + }; + + *r = (const struct fs_ret) + { + .f = search, + .args = s + }; + + return 0; + +failure: + free(s); + free(mp); + return -1; +} diff --git a/src/fs/src/mountpoint.c b/src/fs/src/mountpoint.c new file mode 100644 index 0000000..32b6ea9 --- /dev/null +++ b/src/fs/src/mountpoint.c @@ -0,0 +1,60 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <stdlib.h> +#include <string.h> + +int fs_mountpoint(const char *const src, const char *const tgt, + const struct fs *const fs, const fs_update_fn fn, + struct fs_mp_prv *const pr) +{ + struct fs_mountpoint *m = NULL; + char *srcdup = NULL, *const tgtdup = strdup(tgt); + + if (!tgtdup) + goto failure; + else if (src && !(srcdup = strdup(src))) + goto failure; + else if (!(m = malloc(sizeof *m))) + goto failure; + + *m = (const struct fs_mountpoint) + { + .src = srcdup, + .tgt = tgtdup, + .update = fn, + .fs = fs, + .prv = pr + }; + + if (!fs_mphead) + fs_mphead = m; + else if (fs_mptail) + fs_mptail->next = m; + + fs_mptail = m; + return 0; + +failure: + free(srcdup); + free(tgtdup); + free(m); + return -1; +} diff --git a/src/fs/src/mp_from_path.c b/src/fs/src/mp_from_path.c new file mode 100644 index 0000000..4a963d3 --- /dev/null +++ b/src/fs/src/mp_from_path.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <string.h> + +int fs_mp_from_path(const char *const path, struct fs_mp *const mp) +{ + for (const struct fs_mountpoint *p = fs_mphead; p; p = p->next) + if (!strcmp(path, p->tgt)) + { + *mp = (const struct fs_mp) + { + .fs = p->fs, + .prv = p->prv, + .src = p->src, + .tgt= p->tgt + }; + + return 0; + } + + return -1; +} diff --git a/src/fs/src/mps_from_path.c b/src/fs/src/mps_from_path.c new file mode 100644 index 0000000..4825ccc --- /dev/null +++ b/src/fs/src/mps_from_path.c @@ -0,0 +1,89 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +static struct fs_mp *find(const char *const path, size_t *const out) +{ + struct fs_mp *ret = NULL; + size_t n = 0; + + for (const struct fs_mountpoint *p = fs_mphead; p; p = p->next) + { + const size_t len = strlen(p->tgt); + + if (!strncmp(p->tgt, path, len)) + { + const size_t sz = n + 1; + struct fs_mp *const m = realloc(ret, sz * sizeof *m); + + if (!m) + goto failure; + + m[n++] = (const struct fs_mp) + { + .fs = p->fs, + .prv = p->prv, + .src = p->src, + .tgt = p->tgt + }; + + ret = m; + } + } + + *out = n; + return ret; + +failure: + free(ret); + return NULL; +} + +static void sort(struct fs_mp *const m, const size_t n) +{ + for (size_t i = 1; i < n; i++) + { + struct fs_mp am = m[i]; + const size_t len = strlen(am.tgt); + size_t j = i; + + while (j && len < strlen(m[j - 1].tgt)) + { + m[j] = m [j - 1]; + j--; + } + + m[j] = am; + } +} + +struct fs_mp *fs_mps_from_path(const char *const path, size_t *const n) +{ + struct fs_mp *const ret = find(path, n); + + if (!ret) + return NULL; + + sort(ret, *n); + return ret; +} diff --git a/src/fs/src/next.c b/src/fs/src/next.c new file mode 100644 index 0000000..62fdd80 --- /dev/null +++ b/src/fs/src/next.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +int fs_next(const char *const path, char **const out, size_t *const i) +{ + char *next = NULL; + + if (*i >= strlen(path)) + { + *out = NULL; + return 0; + } + + const char *const s = &path[*i]; + + if (*s == '/') + { + if (!(next = strdup("/"))) + goto failure; + + (*i)++; + *out = next; + return 0; + } + + const char *sep = strchr(s, '/'); + next = sep ? strndup(s, sep - s) : strdup(s); + + if (!next) + goto failure; + else if (sep) + while (*sep && *sep == '/') + sep++; + + *i += sep ? sep - s : strlen(s); + *out = next; + return 0; + +failure: + free(next); + return -1; +} diff --git a/src/fs/src/parent.c b/src/fs/src/parent.c new file mode 100644 index 0000000..9cf51f6 --- /dev/null +++ b/src/fs/src/parent.c @@ -0,0 +1,33 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +char *fs_parent(const char *const path) +{ + char *ret = NULL; + const char *const sep = strrchr(path, '/'); + + if (!sep || !(ret = strndup(path, sep - path + 1))) + return NULL; + + return ret; +} diff --git a/src/fs/src/register.c b/src/fs/src/register.c new file mode 100644 index 0000000..d28e47a --- /dev/null +++ b/src/fs/src/register.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <stdlib.h> + +int fs_register(const struct fs *const fs) +{ + struct fs_register *const r = malloc(sizeof *r); + + if (!r) + return -1; + else if (!fs_rhead) + fs_rhead = r; + else if (fs_rtail) + fs_rtail->next = r; + + fs_rtail = r; + *r = (const struct fs_register){.fs = fs}; + return 0; +} diff --git a/src/fs/src/relpath.c b/src/fs/src/relpath.c new file mode 100644 index 0000000..565ea53 --- /dev/null +++ b/src/fs/src/relpath.c @@ -0,0 +1,43 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <string.h> + +const char *fs_relpath(const char *const path) +{ + size_t lastn = 0; + const struct fs_mountpoint *mp = NULL; + + for (const struct fs_mountpoint *m = fs_mphead; m; m = m->next) + { + const size_t n = strlen(m->tgt); + + if (!strncmp(m->tgt, path, n) && lastn < n) + { + lastn = n; + mp = m; + } + } + + if (!mp) + return NULL; + + return path + strlen(mp->tgt); +} diff --git a/src/fs/src/update.c b/src/fs/src/update.c new file mode 100644 index 0000000..1e6d9ea --- /dev/null +++ b/src/fs/src/update.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <fs/fs.h> +#include <fs/types.h> +#include <stddef.h> + +int fs_update(void) +{ + for (const struct fs_mountpoint *m = fs_mphead; m; m = m->next) + if (m->update && m->update(m->prv)) + return -1; + + return 0; +} diff --git a/src/gfx/CMakeLists.txt b/src/gfx/CMakeLists.txt new file mode 100644 index 0000000..85bf890 --- /dev/null +++ b/src/gfx/CMakeLists.txt @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(gfx) +add_subdirectory(src) +target_include_directories(gfx PUBLIC include) + +if(PS1_BUILD) + add_subdirectory(ps1) +elseif(SDL1_2_BUILD) + add_subdirectory(sdl-1.2) +endif() diff --git a/src/gfx/include/gfx/gfx.h b/src/gfx/include/gfx/gfx.h new file mode 100644 index 0000000..c9b4931 --- /dev/null +++ b/src/gfx/include/gfx/gfx.h @@ -0,0 +1,47 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef GFX_H +#define GFX_H + +#include <gfx/port.h> +#include <stdbool.h> + +int gfx_init(void); +int gfx_draw(void); +int gfx_update(void); +bool gfx_ready(void); +int gfx_toggle_fullscreen(void); +int gfx_set_fullscreen(short w, short h); +bool gfx_fullscreen_available(void); +bool gfx_fullscreen(void); +int gfx_display_size(short *w, short *h); + +void gfx_rect_init(struct gfx_rect *r); +void semitrans_rect_init(struct gfx_rect *r); +void stp_4line_init(struct stp_4line *l); +void quad_sort(struct quad *q); +int gfx_rect_sort(struct gfx_rect *r); +void stp_4line_sort(struct stp_4line *l); +int quad_from_sprite(const struct gfx_sprite *s, struct quad *q); +bool gfx_inside_drawenv(short x, short y, short w, short h); +void gfx_deinit(void); + +extern int screen_w, screen_h; + +#endif /* GFX_H */ diff --git a/src/gfx/include/gfx/sprite.h b/src/gfx/include/gfx/sprite.h new file mode 100644 index 0000000..7b1bf8d --- /dev/null +++ b/src/gfx/include/gfx/sprite.h @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef GFX_SPRITE_H +#define GFX_SPRITE_H + +#include <gfx/port.h> +#include <stddef.h> + +typedef int (*gfx_read)(void *buf, size_t n, void *args); + +int gfx_sprite_load(struct gfx_sprite *s, gfx_read r, void *args); +int gfx_sprite_sort(struct gfx_sprite *s); +int gfx_sprite_clone(const struct gfx_sprite *src, struct gfx_sprite *dst); +void gfx_sprite_free(struct gfx_sprite *s); + +#endif diff --git a/src/gfx/ps1/CMakeLists.txt b/src/gfx/ps1/CMakeLists.txt new file mode 100644 index 0000000..f98ee50 --- /dev/null +++ b/src/gfx/ps1/CMakeLists.txt @@ -0,0 +1,40 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_subdirectory(src) +target_include_directories(gfx PUBLIC include PRIVATE private_include) +target_link_libraries(gfx PRIVATE + drv_ps1_event + drv_ps1_dma + drv_ps1_irq + drv_ps1_gpu +) + +set(modes VMODE_PAL VMODE_NTSC) + +if(VIDEO_MODE) + if(NOT "${VIDEO_MODE}" IN_LIST modes) + message(FATAL_ERROR "Invalid video mode ${VIDEO_MODE}. Available options:\n" + "${modes}\n" + "Run CMake again using one of the available video modes e.g.: cmake .. -DVIDEO_MODE=VMODE_PAL") + endif() + + target_compile_definitions(gfx PRIVATE VIDEO_MODE=${VIDEO_MODE}) +else() + message(FATAL_ERROR "Please define video mode. Available options:\n" + "${modes}\n" + "Run CMake again using one of the available video modes e.g.: cmake .. -DVIDEO_MODE=VMODE_PAL") +endif() diff --git a/src/gfx/ps1/include/gfx/port.h b/src/gfx/ps1/include/gfx/port.h new file mode 100644 index 0000000..faf9a50 --- /dev/null +++ b/src/gfx/ps1/include/gfx/port.h @@ -0,0 +1,126 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef GFX_PS1_H +#define GFX_PS1_H + +#include <stdint.h> + +union gfx_common +{ + struct + { + uint32_t tpagex :4, tpagey :1, stp :2, bpp :2, dither :1, + draw_to_disp :1, disable :1, xflip :1, yflip :1, :10; + uint8_t cmd; + } f; + + uint32_t mask; +}; + +union gfx_sznext +{ + struct + { + uint32_t next :24, sz :8; + } f; + + uint32_t cmd_next; +}; + +struct gfx_sprite +{ + union gfx_sznext sznext; + union gfx_common common; + uint8_t r, g, b; + uint8_t cmd; + int16_t x, y; + uint8_t u, v; + uint16_t clutid; + uint16_t w, h; +}; + +struct quad +{ + union gfx_sznext sznext; + uint8_t r, g, b; + uint8_t cmd; + int16_t x0, y0; + uint8_t u0, v0; + uint16_t clutid; + int16_t x1, y1; + uint8_t u1, v1; + + union + { + struct + { + /* 0-8 Same as GP0(E1h).Bit0-8. */ + uint16_t lb :9; + uint16_t :2; + /* 11 Same as GP0(E1h).Bit11. */ + uint16_t hb :1; + uint16_t :4; + } bit; + + uint16_t mask; + } tpage; + + int16_t x2, y2; + uint8_t u2, v2; + uint16_t :16; + int16_t x3, y3; + uint8_t u3, v3; + uint16_t :16; +}; + +struct gfx_rect +{ + union gfx_sznext sznext; + union gfx_common common; + uint8_t r, g, b; + uint8_t cmd; + int16_t x, y; + uint16_t w, h; +}; + +struct stp_4line +{ + union gfx_sznext sznext; + union gfx_common common; + uint8_t r, g, b; + uint8_t cmd; + int16_t x, y; + + struct stp_4line_vtx + { + uint32_t r :8, g :8, b :8, :8; + int16_t x, y; + } vertices[4]; + + uint32_t end; +}; + +void gfx_add_to_list(union gfx_sznext *p); +void *gfx_heap_top(void); +struct gfx_sprite *gfx_sprite_get(void); +struct quad *quad_get(void); +struct gfx_rect *gfx_rect_get(void); +struct stp_4line *stp_4line_get(void); + +#endif diff --git a/src/gfx/ps1/private_include/gfx/private.h b/src/gfx/ps1/private_include/gfx/private.h new file mode 100644 index 0000000..72d8f39 --- /dev/null +++ b/src/gfx/ps1/private_include/gfx/private.h @@ -0,0 +1,19 @@ +#ifndef GFX_PS1_PRIVATE_H +#define GFX_PS1_PRIVATE_H + +#include <gfx/gfx.h> + +enum +{ + SCREEN_W = 640, + SCREEN_H = 480 +}; + +void gfx_swapheap(void); +void gfx_initenvs(void); +void gfx_swapbuffers(void); +void gfx_swapenvs(void); + +extern int gfx_vblank_ev; + +#endif diff --git a/src/gfx/ps1/src/4line.c b/src/gfx/ps1/src/4line.c new file mode 100644 index 0000000..766eb2d --- /dev/null +++ b/src/gfx/ps1/src/4line.c @@ -0,0 +1,15 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <psxgpu.h> +#include <stdint.h> +#include <string.h> + +void stp_4line_init(struct stp_4line *const l) +{ + memset(l, 0, sizeof *l); + l->sznext.f.sz = (sizeof *l - sizeof l->sznext) / sizeof (uint32_t); + l->common.f.cmd = DRAW_MODE; + l->cmd = 0x5A; + enum {TERMINATION_CODE = 0x55555555}; + l->end = TERMINATION_CODE; +} diff --git a/src/gfx/ps1/src/CMakeLists.txt b/src/gfx/ps1/src/CMakeLists.txt new file mode 100644 index 0000000..5b08b24 --- /dev/null +++ b/src/gfx/ps1/src/CMakeLists.txt @@ -0,0 +1,33 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + # 4line.c + # env.c + draw.c + heap.c + init.c + ready.c + swapenvs.c + # quad.c + # rect.c + # sort.c + # sprite.c + vblank.c +) + +add_subdirectory(sprite) +add_subdirectory(rect) diff --git a/src/gfx/ps1/src/deinit.c b/src/gfx/ps1/src/deinit.c new file mode 100644 index 0000000..e5683f0 --- /dev/null +++ b/src/gfx/ps1/src/deinit.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> + +void gfx_deinit(void) +{ +} diff --git a/src/gfx/ps1/src/draw.c b/src/gfx/ps1/src/draw.c new file mode 100644 index 0000000..a935143 --- /dev/null +++ b/src/gfx/ps1/src/draw.c @@ -0,0 +1,71 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/dma.h> +#include <drv/ps1/gpu.h> +#include <stddef.h> + +static union gfx_sznext *first, *last; + +void gfx_add_to_list(union gfx_sznext *const p) +{ + if (!first) + first = p; + else if (last) + last->f.next = (uint32_t)p; + + last = p; +} + +int gfx_draw(void) +{ + static union gfx_sznext term = {.cmd_next = 0xffffff}; + + gfx_add_to_list(&term); + + if (SCREEN_W != 640) + gfx_swapenvs(); + + gfx_swapheap(); + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .dma = + { + .cmd = GP1_DMA_DIR, + .dir = GP1_DMA_DIR_CPU_TO_GP0 + } + }.mask; + + D2_MADR->mask = (uint32_t)first; + D2_BCR->syncmode_2.reserved = 0; + D2_CHCR->mask = (const union chcr) + { + .bits = + { + .sync_mode = CHCR_SYNC_MODE_LINKED_LIST, + .dir = CHCR_DIR_FROM_RAM, + .start_busy = 1 + } + }.mask; + + first = NULL; + return 0; +} diff --git a/src/gfx/ps1/src/env.c b/src/gfx/ps1/src/env.c new file mode 100644 index 0000000..100f366 --- /dev/null +++ b/src/gfx/ps1/src/env.c @@ -0,0 +1,71 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <psxgpu.h> +#include <errno.h> +#include <stdbool.h> + +static GsDispEnv dispenv; +enum {ENV_Y = SCREEN_H + 16}; + +static GsDrawEnv drawenv = +{ + .y = ENV_Y, + .w = SCREEN_W, + .h = SCREEN_H +}; + +int screen_w = SCREEN_W, screen_h = SCREEN_H; + +void gfx_swapbuffers(void) +{ + const short y = drawenv.y; + + drawenv.y = dispenv.y; + dispenv.y = y; + GsSetDrawEnv(&drawenv); + GsSetDispEnv(&dispenv); +} + +void gfx_initenvs(void) +{ + GsSetDrawEnv(&drawenv); + GsSetDispEnv(&dispenv); +} + +int gfx_toggle_fullscreen(void) +{ + errno = ENOTSUP; + return -1; +} + +int gfx_set_fullscreen(const short w, const short h) +{ + errno = ENOTSUP; + return -1; +} + +bool gfx_fullscreen_available(void) +{ + return false; +} + +bool gfx_fullscreen(void) +{ + return true; +} + +int gfx_display_size(short *const w, short *const h) +{ + *w = SCREEN_W; + *h = SCREEN_H; + return 0; +} + +bool gfx_inside_drawenv(const short x, const short y, const short w, + const short h) +{ + return (x + w >= 0) + && x < drawenv.w + && (y + h >= 0) + && y < drawenv.h; +} diff --git a/src/gfx/ps1/src/heap.c b/src/gfx/ps1/src/heap.c new file mode 100644 index 0000000..402ee41 --- /dev/null +++ b/src/gfx/ps1/src/heap.c @@ -0,0 +1,74 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <stddef.h> + +static unsigned int sel; +static size_t heap_i; + +void gfx_swapheap(void) +{ + sel ^= 1; + heap_i = 0; +} + +static void *get_element(const size_t sz) +{ + enum + { + HEAP_SZ = sizeof (struct gfx_rect) + + (SCREEN_W / 10) * sizeof (struct gfx_sprite), + N_HEAPS = 2 + }; + + static char heaps[N_HEAPS][HEAP_SZ]; + const size_t new_sz = heap_i + sz; + void *ret = NULL; + + if (new_sz <= sizeof *heaps / sizeof **heaps) + { + ret = &heaps[sel][heap_i]; + heap_i = new_sz; + } + else + return NULL; + + return ret; +} + +struct gfx_sprite *gfx_sprite_get(void) +{ + return get_element(sizeof (struct gfx_sprite)); +} + +struct quad *quad_get(void) +{ + return get_element(sizeof (struct quad)); +} + +struct gfx_rect *gfx_rect_get(void) +{ + return get_element(sizeof (struct gfx_rect)); +} + +struct stp_4line *stp_4line_get(void) +{ + return get_element(sizeof (struct stp_4line)); +} diff --git a/src/gfx/ps1/src/init.c b/src/gfx/ps1/src/init.c new file mode 100644 index 0000000..a640202 --- /dev/null +++ b/src/gfx/ps1/src/init.c @@ -0,0 +1,199 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/dma.h> +#include <drv/ps1/gpu.h> +#include <drv/ps1/irq.h> +#include <stddef.h> + +struct res +{ + int hres, hres2, vres, interlace; +}; + +static void getres(const short w, struct res *const r) +{ + *r = (const struct res){0}; + + switch (w) + { + case 320: + r->hres = 1; + break; + case 368: + r->hres2 = 1; + break; + case 512: + r->hres = 2; + break; + case 640: + r->hres = 3; + r->vres = 1; + r->interlace = 1; + break; + } +} + +volatile int vblank_set; + +static int irq(void) +{ + vblank_set = 1; + I_STAT->bits.vblank = 0; + return 0; +} + +int gfx_init(void) +{ + const int event = OpenEvent(CLASS_VBLANK, SPEC_INTERRUPTED, MODE_EXECUTE, + irq); + + if (event == -1) + return -1; + + I_MASK->bits.vblank = 1; + EnableEvent(gfx_vblank_ev = event); + + GP1->mask = (const union drv_ps1_gpu_gp1) + {.reset_gpu.cmd = GP1_RESET_GPU}.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .fill_vram = + { + .cmd = GP0_FILL_VRAM, + .w = 1024 / 16, + .h = 512 + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + {.reset_cmdbuf.cmd = GP1_RESET_CMDBUF}.mask; + + DPCR->mask |= (const union dpcr){.bits.gpu_en = 1}.mask; + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .dma = + { + .cmd = GP1_DMA_DIR, + .dir = GP1_DMA_DIR_CPU_TO_GP0 + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .display = + { + .cmd = GP1_DISPLAY_ENABLE, + } + }.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_mode = + { + .cmd = GP0_DRAW_MODE, + .draw_to_display = 1 + } + }.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.tex_window.cmd = GP0_TEX_WINDOW}.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.draw_area_tl.cmd = GP0_DRAW_AREA_TOP_LEFT}.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_area_br = + { + .cmd = GP0_DRAW_AREA_BOTTOM_RIGHT, + .x = SCREEN_W - 1, + .y = SCREEN_H - 1, + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .h_display_range = + { + .cmd = GP1_H_DISPLAY_RANGE, + .x1 = 0x260, + .x2 = 0x260 + 320 * 8 + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .disparea = + { + .cmd = GP1_START_DISPLAY_AREA + } + }.mask; + +#if 0 + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .v_display_range = + { + .cmd = GP1_V_DISPLAY_RANGE, +#if VIDEO_MODE == VMODE_PAL + .y1 = 0xa3, + .y2 = 0xa3 + (SCREEN_H / 2) +#elif VIDEO_MODE == VMODE_NTSC + .y1 = 0x88 - (224 / 2), + .y2 = 0x88 + (224 / 2) +#endif + } + }.mask; +#else +#if 0 + /* TODO: use structs above. */ + GP1->mask = 0x06C4E24E; + GP1->mask = 0x07040010; +#else + /* values found from BIOS init state*/ + GP1->mask = 0x06c7e27e; + GP1->mask = 0x0704682b; +#endif +#endif + + struct res r; + + getres(SCREEN_W, &r); + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .display_mode = + { + .cmd = GP1_DISPLAY_MODE, + .hres = r.hres, + .hres2 = r.hres2, + .vres = r.vres, + .vinterlace = r.interlace, +#if VIDEO_MODE == VMODE_PAL + .vmode = 1 +#endif + } + }.mask; + + return 0; +} diff --git a/src/gfx/ps1/src/quad.c b/src/gfx/ps1/src/quad.c new file mode 100644 index 0000000..bfabee2 --- /dev/null +++ b/src/gfx/ps1/src/quad.c @@ -0,0 +1,24 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <gfx/port.h> +#include <stdint.h> +#include <string.h> + +static void quad_init(struct quad *const q) +{ + memset(q, 0, sizeof *q); + q->sznext.f.sz = (sizeof *q - sizeof q->sznext) / sizeof (uint32_t); + q->cmd = 0x2d; +} + +int quad_from_sprite(const struct gfx_sprite *const s, struct quad *const q) +{ + quad_init(q); + q->tpage.mask = s->common.mask; + q->clutid = s->clutid; + q->u0 = q->u2 = s->u; + q->v0 = q->v1 = s->v; + q->u1 = q->u3 = s->u + s->w - 1; + q->v2 = q->v3 = s->v + s->h - 1; + return 0; +} diff --git a/src/gfx/ps1/src/ready.c b/src/gfx/ps1/src/ready.c new file mode 100644 index 0000000..bcb5b29 --- /dev/null +++ b/src/gfx/ps1/src/ready.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/event.h> +#include <drv/ps1/gpu.h> +#include <stdbool.h> + +bool gfx_ready(void) +{ + extern volatile int vblank_set; + + if (GPUSTAT->bits.ready_cmd + && GPUSTAT->bits.ready_dma + && vblank_set) + { + vblank_set = 0; + return true; + } + + return false; +} diff --git a/src/gfx/ps1/src/rect/CMakeLists.txt b/src/gfx/ps1/src/rect/CMakeLists.txt new file mode 100644 index 0000000..a14378e --- /dev/null +++ b/src/gfx/ps1/src/rect/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + init.c + sort.c +) diff --git a/src/gfx/ps1/src/rect/init.c b/src/gfx/ps1/src/rect/init.c new file mode 100644 index 0000000..5fe0a85 --- /dev/null +++ b/src/gfx/ps1/src/rect/init.c @@ -0,0 +1,41 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/gpu.h> + +static void common_init(struct gfx_rect *const r) +{ + *r = (const struct gfx_rect){0}; + r->sznext.f.sz = (sizeof *r - sizeof r->sznext) / sizeof (uint32_t); + r->common.f.cmd = GP0_DRAW_MODE; + r->common.f.draw_to_disp = 1; +} + +void gfx_rect_init(struct gfx_rect *const r) +{ + common_init(r); + r->cmd = 0x60; +} + +void gfx_semitrans_rect_init(struct gfx_rect *const r) +{ + common_init(r); + r->cmd = 0x62; +} diff --git a/src/gfx/ps1/src/rect/sort.c b/src/gfx/ps1/src/rect/sort.c new file mode 100644 index 0000000..b7f5ebc --- /dev/null +++ b/src/gfx/ps1/src/rect/sort.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/gpu.h> + +int gfx_rect_sort(struct gfx_rect *const r) +{ + gfx_add_to_list(&r->sznext); + return 0; +} diff --git a/src/gfx/ps1/src/sprite/CMakeLists.txt b/src/gfx/ps1/src/sprite/CMakeLists.txt new file mode 100644 index 0000000..32e1b9f --- /dev/null +++ b/src/gfx/ps1/src/sprite/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + clone.c + free.c + load.c + sort.c +) diff --git a/src/gfx/ps1/src/sprite/clone.c b/src/gfx/ps1/src/sprite/clone.c new file mode 100644 index 0000000..45bc802 --- /dev/null +++ b/src/gfx/ps1/src/sprite/clone.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> + +int gfx_sprite_clone(const struct gfx_sprite *const src, + struct gfx_sprite *const dst) +{ + *dst = *src; + return 0; +} diff --git a/src/gfx/ps1/src/sprite/free.c b/src/gfx/ps1/src/sprite/free.c new file mode 100644 index 0000000..922c1ff --- /dev/null +++ b/src/gfx/ps1/src/sprite/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> + +void sprite_free(struct gfx_sprite *const src) +{ +} diff --git a/src/gfx/ps1/src/sprite/load.c b/src/gfx/ps1/src/sprite/load.c new file mode 100644 index 0000000..2dd12ae --- /dev/null +++ b/src/gfx/ps1/src/sprite/load.c @@ -0,0 +1,192 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <gfx/private.h> +#include <drv/ps1/gpu.h> +#include <stdint.h> + +static void init(struct gfx_sprite *const s) +{ + *s = (const struct gfx_sprite){0}; + s->sznext.f.sz = (sizeof *s - sizeof s->sznext) / sizeof (uint32_t); + s->common.f.cmd = GP0_DRAW_MODE; + s->common.f.draw_to_disp = 1; + s->cmd = GP0_TEXTRECT_VARSZ_OPAQ_RAW; +} + +struct tim_pos +{ + uint16_t x, y, w, h; +}; + +static void transfer_init(const struct tim_pos *const p) +{ + while (!GPUSTAT->bits.ready_cmd) + ; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.copy_rect.cmd = GP0_COPY_RECT_CPU_VRAM}.mask; + GP0->mask = (const union drv_ps1_gpu_gp0) + {.coord = {.x = p->x, .y = p->y}}.mask; + GP0->mask = (const union drv_ps1_gpu_gp0) + {.size = {.w = p->w, .h = p->h}}.mask; +} + +static int transfer(const size_t sz, const gfx_read r, void *const args) +{ + const size_t rem = sz % sizeof (uint32_t); + + if (sz >= sizeof (uint32_t)) + { + for (size_t i = 0; i < sz / sizeof (uint32_t); i++) + { + uint32_t pix; + + if (r(&pix, sizeof pix, args)) + return -1; + + GP0->mask = pix; + } + } + + if (rem) + { + uint32_t pix = 0; + + if (r(&pix, rem, args)) + return -1; + + GP0->mask = pix; + } + + return 0; +} + +struct header +{ + uint32_t sz; + struct tim_pos pos; +}; + +static short get_clutid(const short x, const short y) +{ + return (x & 0x3ff) >> 4 | (y & 0x1ff) << 6; +} + +static int upload_clut(struct gfx_sprite *const s, const gfx_read r, + void *const args) +{ + struct header clut; + + if (r(&clut, sizeof clut, args)) + return -1; + + transfer_init(&clut.pos); + + const size_t sz = clut.sz - sizeof clut; + + if (transfer(sz, r, args)) + return -1; + + s->clutid = get_clutid(clut.pos.x, clut.pos.y); + return 0; +} + +enum bpp +{ + BPP_4 = 0, + BPP_8 = 1, + BPP_16 = 2, + BPP_24 = 4 +}; + +static int upload_img(struct gfx_sprite *const s, const enum bpp bpp, + const gfx_read r, void *const args) +{ + struct header img; + + if (r(&img, sizeof img, args)) + return -1; + + transfer_init(&img.pos); + + const size_t sz = img.sz - sizeof img; + + if (transfer(sz, r, args)) + return -1; + + enum + { + VRAM_X = 1024, + VRAM_Y = 512, + TPAGE_WIDTH = 64 + }; + + s->common.f.tpagex = img.pos.x / TPAGE_WIDTH; + s->common.f.tpagey = img.pos.y / (VRAM_Y / 2); + s->u = img.pos.x % TPAGE_WIDTH; + s->v = img.pos.y % (VRAM_Y / 2); + + switch (bpp) + { + case BPP_4: + s->w = img.pos.w * 4; + s->u <<= 2; + break; + + case BPP_8: + s->w = img.pos.w * 2; + s->u <<= 1; + break; + + case BPP_16: + s->w = img.pos.w; + break; + + case BPP_24: + s->w = img.pos.w + (img.pos.w / 2); + break; + } + + s->h = img.pos.h; + return 0; +} + +int gfx_sprite_load(struct gfx_sprite *s, const gfx_read r, void *const args) +{ + init(s); + + struct + { + uint32_t version, bpp :3, has_clut :1, :28; + } h; + + enum {VERSION_ID = 0x10}; + + if (r(&h, sizeof h, args) + || h.version != VERSION_ID + || h.bpp == BPP_24 + || (h.has_clut && upload_clut(s, r, args)) + || upload_img(s, h.bpp, r, args)) + return -1; + + s->common.f.bpp = h.bpp ? __builtin_ctz(h.bpp) + 1 : 0; + return 0; +} diff --git a/src/gfx/ps1/src/sprite/sort.c b/src/gfx/ps1/src/sprite/sort.c new file mode 100644 index 0000000..3a4b020 --- /dev/null +++ b/src/gfx/ps1/src/sprite/sort.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/port.h> + +int gfx_sprite_sort(struct gfx_sprite *const s) +{ + gfx_add_to_list(&s->sznext); + return 0; +} diff --git a/src/gfx/ps1/src/swapenvs.c b/src/gfx/ps1/src/swapenvs.c new file mode 100644 index 0000000..0b08ee2 --- /dev/null +++ b/src/gfx/ps1/src/swapenvs.c @@ -0,0 +1,58 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/gpu.h> + +void gfx_swapenvs(void) +{ + static short dispenv, drawenv = 256; + const short y = dispenv; + + dispenv = drawenv; + drawenv = y; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_area_tl = + { + .cmd = GP0_DRAW_AREA_TOP_LEFT, + .y = drawenv + } + }.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_area_br = + { + .cmd = GP0_DRAW_AREA_BOTTOM_RIGHT, + .x = SCREEN_W - 1, + .y = drawenv + SCREEN_H - 1, + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .disparea = + { + .cmd = GP1_START_DISPLAY_AREA, + .y = dispenv + } + }.mask; +} diff --git a/src/libc/src/free.c b/src/gfx/ps1/src/vblank.c index d89a80a..eb47597 100644 --- a/src/libc/src/free.c +++ b/src/gfx/ps1/src/vblank.c @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -16,8 +16,6 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#include <stdlib.h> +#include <gfx/private.h> -void free(void *const ptr) -{ -} +int gfx_vblank_ev; diff --git a/src/gfx/sdl-1.2/CMakeLists.txt b/src/gfx/sdl-1.2/CMakeLists.txt new file mode 100644 index 0000000..cd37d06 --- /dev/null +++ b/src/gfx/sdl-1.2/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_subdirectory(src) +target_include_directories(gfx PUBLIC include PRIVATE private_include) +target_link_libraries(gfx PUBLIC SDL::SDL PRIVATE SDL::SDL_gfx) diff --git a/src/gfx/sdl-1.2/include/gfx/port.h b/src/gfx/sdl-1.2/include/gfx/port.h new file mode 100644 index 0000000..bf94a38 --- /dev/null +++ b/src/gfx/sdl-1.2/include/gfx/port.h @@ -0,0 +1,58 @@ +#ifndef GFX_SDL_H +#define GFX_SDL_H + +#include <SDL.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct gfx_sprite +{ + SDL_Surface *s, *s_x; + short x, y, w, h; + unsigned char u, v; + bool transparent; +}; + +struct quad +{ + unsigned char r, g, b; + short x0, x1, x2, x3; + short y0, y1, y2, y3; + unsigned char u0, u1, u2, u3; + unsigned char v0, v1, v2, v3; + short w, h; + bool transparent; + SDL_Surface *s, *s_x; +}; + +struct gfx_rect +{ + unsigned char r, g, b; + short x, y, w, h; + bool stp; +}; + +struct stp_4line +{ + short x, y; + unsigned char r, g, b; + + struct stp_4line_vtx + { + unsigned char r, g, b; + short x, y; + } vertices[4]; +}; + +#define common_get_or_ret(t, x, ret) \ + struct t x##__, *const x = &x##__ + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_SDL_H */ diff --git a/src/gfx/sdl-1.2/private_include/gfx/private.h b/src/gfx/sdl-1.2/private_include/gfx/private.h new file mode 100644 index 0000000..e1af764 --- /dev/null +++ b/src/gfx/sdl-1.2/private_include/gfx/private.h @@ -0,0 +1,26 @@ +#ifndef GFX_SDL_12_PRIVATE_H +#define GFX_SDL_12_PRIVATE_H + +#include <gfx/gfx.h> +#include <SDL.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +enum +{ + SCREEN_W = 320, + SCREEN_H = 240 +}; + +int sprite_screen_resize_ev(struct gfx_sprite *s); +void gfx_register_sprite(struct gfx_sprite *s); +SDL_Surface *gfx_screen(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_SDL_12_PRIVATE_H */ diff --git a/src/gfx/sdl-1.2/src/CMakeLists.txt b/src/gfx/sdl-1.2/src/CMakeLists.txt new file mode 100644 index 0000000..75ccb78 --- /dev/null +++ b/src/gfx/sdl-1.2/src/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + env.c + line.c + quad.c + rect.c + sprite.c +) diff --git a/src/gfx/sdl-1.2/src/env.c b/src/gfx/sdl-1.2/src/env.c new file mode 100644 index 0000000..2a51b97 --- /dev/null +++ b/src/gfx/sdl-1.2/src/env.c @@ -0,0 +1,204 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <sdl-1.2/gfx/private.h> +#include <SDL.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +int screen_w = SCREEN_W, screen_h = SCREEN_H; +static bool fullscreen; +static SDL_Surface *screen; +static struct gfx_sprite **list; +static size_t list_len; + +void gfx_deinit(void) +{ + /* screen should be already freed by SDL_Quit. */ + free(list); + SDL_QuitSubSystem(SDL_INIT_VIDEO); +} + +static struct +{ + int w, h; +} display, windowed; + +void gfx_register_sprite(struct gfx_sprite *const s) +{ + list = realloc(list, (list_len + 1) * sizeof *list); + + if (list) + list[list_len++] = s; +} + +static int resize_screen(int w, int h, const bool full_screen) +{ + Uint32 flags = SDL_HWSURFACE | SDL_RESIZABLE | SDL_ANYFORMAT | SDL_DOUBLEBUF; + + const SDL_VideoInfo *const info = SDL_GetVideoInfo(); + + if (!info) + { + fprintf(stderr, "SDL_GetVideoInfo: %s\n", SDL_GetError()); + return -1; + } + + static bool init; + + if (!init) + { + display.w = info->current_w; + display.h = info->current_h; + init = true; + } + + if (fullscreen) + { + flags |= SDL_FULLSCREEN; + w = display.w; + h = display.h; + } + else + { + windowed.w = w; + windowed.h = h; + } + + int bpp = info->vfmt->BitsPerPixel; + + if (screen) + SDL_FreeSurface(screen); + + const int max_bpp = SDL_VideoModeOK(w, h, 0, flags); + + if (max_bpp < 0) + { + fprintf(stderr, "SDL_VideoModeOK: %s\n", SDL_GetError()); + return -1; + } + else if (bpp > max_bpp) + bpp = max_bpp; + + if (!(screen = SDL_SetVideoMode(w, h, 0, flags))) + { + fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); + return -1; + } + + for (size_t i = 0; i < list_len; i++) + if (sprite_screen_resize_ev(list[i])) + return -1; + + screen_w = w; + screen_h = h; + fullscreen = full_screen; + return 0; +} + +SDL_Surface *gfx_screen(void) +{ + return screen; +} + +int gfx_display_size(short *const w, short *const h) +{ + *w = display.w; + *h = display.h; + return 0; +} + +int gfx_init(void) +{ + if (SDL_InitSubSystem(SDL_INIT_VIDEO)) + { + fprintf(stderr, "%s: SDL_InitSubSystem: %s\n", + __func__, SDL_GetError()); + return -1; + } + + return resize_screen(screen_w, screen_h, fullscreen); +} + +bool gfx_inside_drawenv(const short x, const short y, const short w, + const short h) +{ + return (x + w >= 0) + && x < screen_w + && (y + h >= 0) + && y < screen_h; +} + +static int get_resize_events(void) +{ + int n; + SDL_Event ev; + + while ((n = SDL_PeepEvents(&ev, 1, SDL_GETEVENT, + SDL_VIDEORESIZEMASK)) > 0) + { + if (ev.type == SDL_VIDEORESIZE) + { + const SDL_ResizeEvent *const res = &ev.resize; + + if (resize_screen(res->w, res->h, false)) + return -1; + } + } + + if (n < 0) + { + fprintf(stderr, "%s: SDL_PeepEvents: %s\n", + __func__, SDL_GetError()); + return -1; + } + + return 0; +} + +int gfx_toggle_fullscreen(void) +{ + fullscreen ^= true; + + const int w = fullscreen ? display.w : windowed.w; + const int h = fullscreen ? display.h : windowed.h; + + return resize_screen(w, h, fullscreen); +} + +int gfx_set_fullscreen(const short w, const short h) +{ + return resize_screen(display.w = w, display.h = h, fullscreen = true); +} + +bool gfx_fullscreen_available(void) +{ + return true; +} + +bool gfx_fullscreen(void) +{ + return fullscreen; +} + +int gfx_draw(void) +{ + enum {FPS = 50, REFRESH_MS = 1000 / FPS}; + static Uint32 prev; + const Uint32 cur = SDL_GetTicks(); + + if (cur - prev < REFRESH_MS) + SDL_Delay(REFRESH_MS - (cur - prev)); + + prev = SDL_GetTicks(); + + if (SDL_Flip(screen)) + { + fprintf(stderr, "SDL_Flip: %s\n", SDL_GetError()); + return -1; + } + + get_resize_events(); + return 0; +} diff --git a/src/gfx/sdl-1.2/src/line.c b/src/gfx/sdl-1.2/src/line.c new file mode 100644 index 0000000..b06a414 --- /dev/null +++ b/src/gfx/sdl-1.2/src/line.c @@ -0,0 +1,16 @@ +#include <gfx/gfx.h> +#include <gfx/port.h> +#include <sdl-1.2/gfx/private.h> +#include <stddef.h> + +void stp_4line_init(struct stp_4line *const l) +{ +} + +void semitrans_stp_4line_init(struct stp_4line *r) +{ +} + +void stp_4line_sort(struct stp_4line *const r) +{ +} diff --git a/src/gfx/sdl-1.2/src/quad.c b/src/gfx/sdl-1.2/src/quad.c new file mode 100644 index 0000000..1617a8b --- /dev/null +++ b/src/gfx/sdl-1.2/src/quad.c @@ -0,0 +1,44 @@ +#include <gfx/gfx.h> +#include <gfx/port.h> +#include <sdl-1.2/gfx/private.h> +#include <stddef.h> +#include <stdlib.h> + +int quad_from_sprite(const struct gfx_sprite *const s, struct quad *const q) +{ + q->s = s->s; + q->s_x = s->s_x; + q->u0 = q->u2 = s->u; + q->v0 = q->v1 = s->v; + q->u1 = q->u3 = s->u + s->w - 1; + q->v2 = q->v3 = s->v + s->h - 1; + q->w = s->w; + q->h = s->h; + return 0; +} + +void quad_sort(struct quad *const q) +{ + const bool xflip = q->x0 > q->x1; + + SDL_Rect r = + { + .x = xflip ? q->x1 : q->x0, + .y = q->y0 + }; + + const short w = q->u1 - q->u0 + 1, h = q->v2 - q->v0 + 1; + + SDL_Rect clip = + { + .x = xflip ? q->w - q->u0 - w: q->u0, + .y = q->v0, + .w = w, + .h = h + }; + + SDL_Surface *const s = xflip ? q->s_x : q->s; + + if (SDL_BlitSurface(s, &clip, gfx_screen(), &r)) + fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError()); +} diff --git a/src/gfx/sdl-1.2/src/rect.c b/src/gfx/sdl-1.2/src/rect.c new file mode 100644 index 0000000..57a2ab3 --- /dev/null +++ b/src/gfx/sdl-1.2/src/rect.c @@ -0,0 +1,35 @@ +#include <gfx/gfx.h> +#include <gfx/port.h> +#include <sdl-1.2/gfx/private.h> +#include <SDL.h> + +void gfx_rect_sort(struct gfx_rect *const r) +{ + SDL_Rect rct = + { + .x = r->x, + .y = r->y, + .w = r->w, + .h = r->h + }; + + SDL_Surface *const screen = gfx_screen(); + const Uint32 map = SDL_MapRGB(screen->format, r->r, r->g, r->b); + + if (SDL_FillRect(screen, &rct, map)) + { + fprintf(stderr, "SDL_FillRect: %s\n", SDL_GetError()); + return; + } +} + +void gfx_rect_init(struct gfx_rect *const r) +{ + *r = (const struct gfx_rect){0}; +} + +void semitrans_rect_init(struct gfx_rect *const r) +{ + gfx_rect_init(r); + r->stp = true; +} diff --git a/src/gfx/sdl-1.2/src/sprite.c b/src/gfx/sdl-1.2/src/sprite.c new file mode 100644 index 0000000..086e2b5 --- /dev/null +++ b/src/gfx/sdl-1.2/src/sprite.c @@ -0,0 +1,143 @@ +#include <gfx/gfx.h> +#include <gfx/port.h> +#include <header.h> +#include <sdl-1.2/gfx/private.h> +#include <SDL.h> +#include <SDL_rotozoom.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> + +void sprite_free(struct gfx_sprite *const s) +{ + if (s && s->s) + SDL_FreeSurface(s->s); +} + +int sprite_clone(const struct gfx_sprite *const src, struct gfx_sprite *const dst) +{ + *dst = *src; + return 0; +} + +static int set_transparent(SDL_Surface *const s) +{ + /* Magenta as transparent. */ + const Uint32 map = SDL_MapRGB(s->format, 255, 0, 255); + const int ret = SDL_SetColorKey(s, SDL_SRCCOLORKEY | SDL_RLEACCEL, map); + + if (ret) + fprintf(stderr, "SDL_SetColorKey: %s\n", SDL_GetError()); + + return ret; +} + +int sprite_screen_resize_ev(struct gfx_sprite *const s) +{ + int ret = -1; + SDL_Surface *const old = s->s, *const old_x = s->s_x; + + if (s->transparent && (set_transparent(old) || set_transparent(old_x))) + goto end; + else if (!(s->s = SDL_DisplayFormat(old))) + { + fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError()); + goto end; + } + else if (!(s->s_x = SDL_DisplayFormat(old_x))) + { + fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError()); + goto end; + } + + ret = 0; + +end: + SDL_FreeSurface(old); + SDL_FreeSurface(old_x); + return ret; +} + +static int load_header(struct gfx_sprite *const s, FILE *const f) +{ + if (header_load_bool(f, "transparent", &s->transparent)) + return -1; + + return 0; +} + +static int load_bitmap(struct gfx_sprite *const s, FILE *const f) +{ + int ret = -1; + SDL_RWops *ops = NULL; + SDL_Surface *ts = NULL, *zs = NULL; + + if (!(ops = SDL_RWFromFP(f, 0))) + { + fprintf(stderr, "SDL_RWFromFP: %s\n", SDL_GetError()); + goto end; + } + else if (!(ts = SDL_LoadBMP_RW(ops, 0))) + { + fprintf(stderr, "SDL_LoadBMP_RW: %s\n", SDL_GetError()); + goto end; + } + else if (!(zs = zoomSurface(ts, -1, 1, 0))) + { + fprintf(stderr, "zoomSurface: %s\n", SDL_GetError()); + goto end; + } + else if (s->transparent && (set_transparent(ts) || set_transparent(zs))) + goto end; + else if (!(s->s = SDL_DisplayFormat(ts))) + { + fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError()); + goto end; + } + else if (!(s->s_x = SDL_DisplayFormat(zs))) + { + fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError()); + goto end; + } + + gfx_register_sprite(s); + s->w = ts->w; + s->h = ts->h; + ret = 0; + +end: + SDL_FreeRW(ops); + SDL_FreeSurface(ts); + SDL_FreeSurface(zs); + return ret; +} + +int sprite_from_fp(struct gfx_sprite *const s, FILE *const f) +{ + *s = (const struct gfx_sprite){0}; + + if (load_header(s, f) || load_bitmap(s, f)) + return -1; + + return 0; +} + +void sprite_sort(struct gfx_sprite *const s) +{ + SDL_Rect r = + { + .x = s->x, + .y = s->y + }; + + SDL_Rect clip = + { + .x = s->u, + .y = s->v, + .w = s->w, + .h = s->h + }; + + if (SDL_BlitSurface(s->s, &clip, gfx_screen(), &r)) + fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError()); +} diff --git a/src/gfx/src/CMakeLists.txt b/src/gfx/src/CMakeLists.txt new file mode 100644 index 0000000..b62fca4 --- /dev/null +++ b/src/gfx/src/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + dim.c + update.c +) diff --git a/src/gfx/src/dim.c b/src/gfx/src/dim.c new file mode 100644 index 0000000..5413469 --- /dev/null +++ b/src/gfx/src/dim.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/private.h> + +int screen_w = SCREEN_W, screen_h = SCREEN_H; diff --git a/src/gfx/src/update.c b/src/gfx/src/update.c new file mode 100644 index 0000000..95980f9 --- /dev/null +++ b/src/gfx/src/update.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> + +int gfx_update(void) +{ + if (!gfx_ready()) + return 0; + + return gfx_draw(); +} diff --git a/src/init/CMakeLists.txt b/src/init/CMakeLists.txt new file mode 100644 index 0000000..d9b70b0 --- /dev/null +++ b/src/init/CMakeLists.txt @@ -0,0 +1,34 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(init) +add_subdirectory(src) +target_include_directories(init PUBLIC include PRIVATE private_include) +target_link_libraries(init PRIVATE + aio + devfs + drv + io + kprintf + loop + rootfs + iso9660 +) + +if(PS1_BUILD) + add_subdirectory(ps1) + target_link_libraries(init PRIVATE init_ps1) +endif() diff --git a/src/init/include/init.h b/src/init/include/init.h new file mode 100644 index 0000000..a1050ab --- /dev/null +++ b/src/init/include/init.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef INIT_H +#define INIT_H + +int init_time(void); +int init_port(void); +int init_boot(void); +int init_vfs(void); +int init_run(void); + +#endif diff --git a/src/init/private_include/init/port.h b/src/init/private_include/init/port.h new file mode 100644 index 0000000..7211534 --- /dev/null +++ b/src/init/private_include/init/port.h @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef INIT_PORT_H +#define INIT_PORT_H + +int init_port_boot(void); +int init_port_run(void); + +#endif diff --git a/src/init/private_include/init/types.h b/src/init/private_include/init/types.h new file mode 100644 index 0000000..7f6114d --- /dev/null +++ b/src/init/private_include/init/types.h @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef INIT_TYPES_H +#define INIT_TYPES_H + +#include <aio.h> +#include <sys/stat.h> +#include <time.h> + +struct init +{ + struct aio *aio; + struct stat sb; + unsigned retries; + struct timespec last_retry; + int (*next)(struct init *); +}; + +extern struct init init_vars; + +#endif diff --git a/src/init/ps1/CMakeLists.txt b/src/init/ps1/CMakeLists.txt new file mode 100644 index 0000000..21df5d7 --- /dev/null +++ b/src/init/ps1/CMakeLists.txt @@ -0,0 +1,37 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(init_ps1) +add_subdirectory(src) +target_include_directories(init_ps1 PRIVATE private_include) +target_link_libraries(init_ps1 + PUBLIC + c + init + PRIVATE + aio + bin + drv_ps1_bios + drv_ps1_cpu + drv_ps1_irq + drv_ps1_rcnt + drv_ps1_time + iso9660 + kprintf + loop + net + state +) diff --git a/src/init/ps1/private_include/init/ps1/types.h b/src/init/ps1/private_include/init/ps1/types.h new file mode 100644 index 0000000..66702d1 --- /dev/null +++ b/src/init/ps1/private_include/init/ps1/types.h @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef INIT_PS1_TYPES_H +#define INIT_PS1_TYPES_H + +#include <aio.h> +#include <sys/stat.h> +#include <time.h> + +struct init_ps1 +{ + struct aio *aio; + struct stat *sb; + unsigned retries; + const char *path; + struct timespec last_retry; + int (*next)(struct init_ps1 *); + int (*success)(struct init_ps1 *); + int (*retry)(struct init_ps1 *); +}; + +extern struct init_ps1 init_ps1; + +#endif diff --git a/src/init/ps1/src/CMakeLists.txt b/src/init/ps1/src/CMakeLists.txt new file mode 100644 index 0000000..68dab00 --- /dev/null +++ b/src/init/ps1/src/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(init_ps1 PRIVATE + boot.c + globalvars.c + port.c + run.c + time.c +) diff --git a/src/init/ps1/src/boot.c b/src/init/ps1/src/boot.c new file mode 100644 index 0000000..062078c --- /dev/null +++ b/src/init/ps1/src/boot.c @@ -0,0 +1,251 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <init/ps1/types.h> +#include <aio.h> +#include <bin.h> +#include <iso9660.h> +#include <kprintf.h> +#include <loop.h> +#include <net.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <state.h> +#include <time.h> + +struct boot +{ + struct aio *aio; + struct init_ps1 *p; +}; + +enum {RETRIES = 5}; +static const char serial[] = "/dev/ttyS0"; + +static int retry_cd(struct init_ps1 *); + +static int wait_retry(struct init_ps1 *const p) +{ + struct timespec ts; + const time_t last = p->last_retry.tv_sec, timeout = 5; + + if (clock_gettime(CLOCK_REALTIME, &ts)) + return -1; + else if (ts.tv_sec - last >= timeout) + p->next = p->retry; + + return 0; +} + +static int stat_done(const enum state s, void *const args) +{ + int ret = 0; + struct init_ps1 *const p = args; + + if (s) + { + struct timespec ts; + + if (!--p->retries || clock_gettime(CLOCK_REALTIME, &ts)) + { + ret = -1; + goto end; + } + + p->last_retry = ts; + p->next = wait_retry; + } + else + { + p->next = p->success; + kprintf("Successfully initialized %s (took %u attempts)\n", + p->path, RETRIES - p->retries + 1); + } + +end: + loop_rm_aio(p->aio); + aio_free(p->aio); + free(p->sb); + return ret; +} + +static int mount_done(const enum state state, void *const args) +{ + struct boot *const b = args; + + if (loop_rm_aio(b->aio)) + return -1; + + aio_free(b->aio); + free(b); + + if (state) + kprintf("Failed to mount ISO9660 filesystem\n"); + else + { + const char *const args[] = {NULL}; + + kprintf("ISO9660 filesystem mounted successfully\n"); + kprintf("Opening second-stage initd\n"); + + /* TODO: create symbolic from /mnt/cdrom/bin to /bin */ + return bin_exec("/mnt/cdrom/bin/initd", args, 0, 0); + } + + return 0; +} + +static int mount_cd(struct init_ps1 *const p) +{ + struct aio *aio = NULL; + struct boot *const b = malloc(sizeof *b); + + if (!b) + goto failure; + + const struct aio_mount fm = + { + .mount = + { + .src = "/dev/cd0", + .tgt = "/mnt/cdrom", + .mode = 0755 + }, + + .type = "iso9660" + }; + + const struct aio_done d = + { + .args = b, + .f = mount_done + }; + + if (!(aio = aio_mount(&fm, &d)) || loop_add_aio(aio)) + goto failure; + + p->next = NULL; + *b = (const struct boot){.aio = aio, .p = p}; + kprintf("Mounting ISO9660 filesystem from %s to %s\n", + fm.mount.src, fm.mount.tgt); + return 0; + +failure: + kprintf("Failed to mount ISO9660 filesystem\n"); + aio_free(aio); + free(b); + return -1; +} + +static int retry_cd(struct init_ps1 *const p) +{ + static const char path[] = "/dev/cd0"; + struct aio *aio = NULL; + struct stat *const sb = malloc(sizeof *sb); + + if (!sb) + goto failure; + + const struct fs_stat s = {.path = path, .sb = sb}; + const struct aio_done d = {.f = stat_done, .args = p}; + const unsigned retries = p->retries; + + if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio)) + goto failure; + + *p = (const struct init_ps1) + { + .aio = aio, + .sb = sb, + .path = path, + .retries = retries, + .success = mount_cd, + .last_retry = {.tv_sec = (time_t)-1} + }; + + p->next = NULL; + kprintf("Initializing CD-ROM to %s (attempt %u)\n", path, + RETRIES - p->retries + 1); + return 0; + +failure: + free(aio); + free(sb); + return -1; +} + +static int init_net(struct init_ps1 *const p) +{ + if (net_init(serial)) + return -1; + + p->next = retry_cd; + return 0; +} + +static int retry_serial(struct init_ps1 *const p) +{ + struct aio *aio = NULL; + struct stat *const sb = malloc(sizeof *sb); + + if (!sb) + goto failure; + + const struct fs_stat s = {.path = serial, .sb = sb}; + const struct aio_done d = {.f = stat_done, .args = p}; + const unsigned retries = p->retries; + + if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio)) + goto failure; + + *p = (const struct init_ps1) + { + .aio = aio, + .sb = sb, + .path = serial, + .retries = retries, + .success = init_net, + .last_retry = {.tv_sec = (time_t)-1} + }; + + p->next = NULL; + kprintf("Initializing serial device to %s (attempt %u)\n", serial, + RETRIES - p->retries + 1); + return 0; + +failure: + free(aio); + free(sb); + return -1; +} + +int init_port_boot(void) +{ + if (iso9660_register()) + return -1; + + init_ps1 = (const struct init_ps1) + { + .retries = RETRIES, + .next = retry_serial + }; + + return 0; +} diff --git a/src/init/ps1/src/globalvars.c b/src/init/ps1/src/globalvars.c new file mode 100644 index 0000000..fcf6a6c --- /dev/null +++ b/src/init/ps1/src/globalvars.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init/ps1/types.h> + +struct init_ps1 init_ps1; diff --git a/src/init/ps1/src/port.c b/src/init/ps1/src/port.c new file mode 100644 index 0000000..9bc2a8e --- /dev/null +++ b/src/init/ps1/src/port.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/irq.h> + +int init_port(void) +{ + EnterCriticalSection(); + SetConf(16, 1, (void *)0x801ff800); + ExitCriticalSection(); + + return drv_ps1_irq_init(); +} diff --git a/src/init/ps1/src/run.c b/src/init/ps1/src/run.c new file mode 100644 index 0000000..bc4b645 --- /dev/null +++ b/src/init/ps1/src/run.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <init/ps1/types.h> + +int init_port_run(void) +{ + struct init_ps1 *const p = &init_ps1; + + return p->next ? p->next(p) : 0; +} diff --git a/src/init/ps1/src/time.c b/src/init/ps1/src/time.c new file mode 100644 index 0000000..1978945 --- /dev/null +++ b/src/init/ps1/src/time.c @@ -0,0 +1,47 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <init/ps1/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cpu.h> +#include <drv/ps1/rcnt.h> +#include <drv/ps1/time.h> +#include <time.h> + +int init_time(void) +{ + struct timespec ts; + const union drv_ps1_rcnt_cfg cfg = + { + .bits = + { + .reset = 1, + .repeat = 1, + .irq_tgt = 1, + .clocksrc = 3 + } + }; + + if (clock_getres(CLOCK_REALTIME, &ts)) + return -1; + + const uint16_t target = (DRV_PS1_CPU_F / 8) / (ts.tv_nsec / 1000); + + return drv_ps1_rcnt_init(DRV_PS1_RCNT2, target, &cfg, drv_ps1_time_tick); +} diff --git a/src/init/src/CMakeLists.txt b/src/init/src/CMakeLists.txt new file mode 100644 index 0000000..ac94d56 --- /dev/null +++ b/src/init/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(init PRIVATE + boot.c + run.c + vars.c + vfs.c +) diff --git a/src/init/src/boot.c b/src/init/src/boot.c new file mode 100644 index 0000000..30d9a9e --- /dev/null +++ b/src/init/src/boot.c @@ -0,0 +1,121 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <init/port.h> +#include <init/types.h> +#include <aio.h> +#include <kprintf.h> +#include <loop.h> +#include <stdlib.h> +#include <time.h> + +static int retry(struct init *); +enum {RETRIES = 5}; + +static int run(struct init *const init) +{ + return init_port_run(); +} + +static int port(struct init *const init) +{ + kprintf("tty initilization successful (took %u attempts)\n", + RETRIES - init->retries + 1); + + if (init_port_boot()) + return -1; + + init->next = run; + return 0; +} + +static int wait_retry(struct init *const init) +{ + struct timespec ts; + const time_t last = init->last_retry.tv_sec, timeout = 5; + + if (clock_gettime(CLOCK_REALTIME, &ts)) + return -1; + else if (ts.tv_sec - last >= timeout) + init->next = retry; + + return 0; +} + +static int stat_done(const enum state s, void *const args) +{ + int ret = 0; + struct init *const init = args; + + if (s) + { + struct timespec ts; + + if (!--init->retries || clock_gettime(CLOCK_REALTIME, &ts)) + { + ret = -1; + goto end; + } + + init->last_retry = ts; + init->next = wait_retry; + } + else + init->next = port; + +end: + loop_rm_aio(init->aio); + aio_free(init->aio); + return ret; +} + +static int retry(struct init *const init) +{ + struct aio *aio = NULL; + const struct fs_stat s = {.path = "/dev/tty", .sb = &init->sb}; + const struct aio_done d = {.f = stat_done, .args = init}; + const unsigned retries = init->retries; + + if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio)) + goto failure; + + *init = (const struct init) + { + .aio = aio, + .retries = retries, + .last_retry = {.tv_sec = (time_t)-1} + }; + + return 0; + +failure: + free(aio); + return -1; +} + +int init_boot(void) +{ + init_vars = (const struct init) + { + .retries = RETRIES, + .next = retry + }; + + return 0; +} diff --git a/src/init/src/run.c b/src/init/src/run.c new file mode 100644 index 0000000..9fa643d --- /dev/null +++ b/src/init/src/run.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <init/types.h> + +int init_run(void) +{ + struct init *const p = &init_vars; + + return p->next ? p->next(p) : 0; +} diff --git a/src/init/src/vars.c b/src/init/src/vars.c new file mode 100644 index 0000000..10d4858 --- /dev/null +++ b/src/init/src/vars.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init/types.h> + +struct init init_vars; diff --git a/src/init/src/vfs.c b/src/init/src/vfs.c new file mode 100644 index 0000000..6fe0904 --- /dev/null +++ b/src/init/src/vfs.c @@ -0,0 +1,86 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <init.h> +#include <aio.h> +#include <drv/drv.h> +#include <io.h> +#include <devfs.h> +#include <rootfs.h> +#include <iso9660.h> +#include <sys/stat.h> +#include <stddef.h> + +int init_vfs(void) +{ + static const struct aio_mount m[] = + { + { + .mount = + { + .tgt = "/", + .mode = 0755 + }, + + .type = "rootfs" + }, + + { + .mount = + { + .tgt = "/dev", + .mode = 0755 + }, + + .type = "devfs" + } + }; + + static const struct fs_mkdir mk[] = + { + { + .path = "/dev", + .mode = 0755 + }, + + { + .path = "/mnt", + .mode = 0755 + }, + + { + .path = "/mnt/cdrom", + .mode = 0755 + } + }; + + if (rootfs_register() + || devfs_register() + || io_mount(m)) + return -1; + + for (size_t i = 0; i < sizeof mk / sizeof *mk; i++) + if (io_mkdir(&mk[i])) + return -1; + + for (size_t i = 1; i < sizeof m / sizeof *m; i++) + if (io_mount(&m[i])) + return -1; + + return 0; +} diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt new file mode 100644 index 0000000..9418e9e --- /dev/null +++ b/src/io/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(io) +add_subdirectory(src) +target_include_directories(io PUBLIC include) +target_link_libraries(io PUBLIC aio) diff --git a/src/io/include/io.h b/src/io/include/io.h new file mode 100644 index 0000000..0a3a3de --- /dev/null +++ b/src/io/include/io.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef IO_H +#define IO_H + +#include <aio.h> +#include <sys/types.h> + +int io_mkdir(const struct fs_mkdir *m); +int io_mount(const struct aio_mount *m); +int io_open(const struct fs_open *o); +int io_write(const struct fs_write *w); + +#endif diff --git a/src/io/src/CMakeLists.txt b/src/io/src/CMakeLists.txt new file mode 100644 index 0000000..4c8b2f5 --- /dev/null +++ b/src/io/src/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(io PRIVATE + mkdir.c + mount.c + open.c + write.c +) diff --git a/src/io/src/mkdir.c b/src/io/src/mkdir.c new file mode 100644 index 0000000..fc141bb --- /dev/null +++ b/src/io/src/mkdir.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <io.h> +#include <aio.h> +#include <fs/fs.h> +#include <errno.h> + +int io_mkdir(const struct fs_mkdir *const m) +{ + int ret = 0; + struct aio *const aio = aio_mkdir(m, NULL); + struct aio_poll p = {.aio = aio}; + + if (!aio || aio_poll(&p, -1) < 0 || p.error) + { + ret = -1; + + if (p.error) + errno = p.error; + } + + aio_free(aio); + return ret; +} diff --git a/src/io/src/mount.c b/src/io/src/mount.c new file mode 100644 index 0000000..e8a1af9 --- /dev/null +++ b/src/io/src/mount.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <io.h> +#include <aio.h> +#include <fs/fs.h> +#include <stddef.h> + +int io_mount(const struct aio_mount *const m) +{ + int ret = 0; + struct aio *const aio = aio_mount(m, NULL); + struct aio_poll p = {.aio = aio}; + + if (!aio || aio_poll(&p, -1) < 0 || p.error) + ret = -1; + + aio_free(aio); + return ret; +} diff --git a/src/io/src/open.c b/src/io/src/open.c new file mode 100644 index 0000000..89b1fe9 --- /dev/null +++ b/src/io/src/open.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <io.h> +#include <aio.h> +#include <fs/fs.h> +#include <stddef.h> + +int io_open(const struct fs_open *const o) +{ + int ret = 0; + struct aio *const aio = aio_open(o, NULL); + struct aio_poll p = {.aio = aio}; + + if (!aio || aio_poll(&p, -1) < 0 || p.error) + ret = -1; + + aio_free(aio); + return ret; +} diff --git a/src/io/src/write.c b/src/io/src/write.c new file mode 100644 index 0000000..7e8f70f --- /dev/null +++ b/src/io/src/write.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <io.h> +#include <aio.h> +#include <fs/fs.h> +#include <stddef.h> + +int io_write(const struct fs_write *const w) +{ + int ret = 0; + struct aio *const aio = aio_write(w, NULL); + struct aio_poll p = {.aio = aio}; + + if (!aio || aio_poll(&p, -1) < 0 || p.error) + ret = -1; + + aio_free(aio); + return ret; +} diff --git a/src/kprintf/CMakeLists.txt b/src/kprintf/CMakeLists.txt new file mode 100644 index 0000000..fcc53c9 --- /dev/null +++ b/src/kprintf/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(kprintf) +add_subdirectory(src) +target_include_directories(kprintf PUBLIC include PRIVATE private_include) +target_link_libraries(kprintf PUBLIC c PRIVATE io nanowasm) diff --git a/src/kprintf/include/kprintf.h b/src/kprintf/include/kprintf.h new file mode 100644 index 0000000..fb0710f --- /dev/null +++ b/src/kprintf/include/kprintf.h @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef KPRINTF_H +#define KPRINTF_H + +#include <stdarg.h> +#include <stdbool.h> + +#if __GNUC__ +#define KPRINTF_ATTR __attribute__ ((format (__printf__, 1, 2))) +#define KTPRINTF_ATTR __attribute__ ((format (__printf__, 2, 3))) +#else +#define KPRINTF_ATTR +#define KTPRINTF_ATTR +#endif + +int kprintf(const char *fmt, ...) KPRINTF_ATTR; +int ktprintf(bool time, const char *fmt, ...); +int kvprintf(const char *fmt, va_list va); +int ktvprintf(bool time, const char *fmt, va_list va); + +#endif diff --git a/src/kprintf/src/CMakeLists.txt b/src/kprintf/src/CMakeLists.txt new file mode 100644 index 0000000..6bdfbc7 --- /dev/null +++ b/src/kprintf/src/CMakeLists.txt @@ -0,0 +1,26 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(kprintf PRIVATE + kprintf.c + kvprintf.c + ktprintf.c + ktvprintf.c + nwp_log.c + wip_log.c +) + +target_link_libraries(kprintf PRIVATE nanowasm wip) diff --git a/src/kprintf/src/kprintf.c b/src/kprintf/src/kprintf.c new file mode 100644 index 0000000..de90e59 --- /dev/null +++ b/src/kprintf/src/kprintf.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <kprintf.h> +#include <io.h> +#include <fcntl.h> +#include <stdarg.h> +#include <printf.h> + +int kprintf(const char *const fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = kvprintf(fmt, ap); + va_end(ap); + return ret; +} diff --git a/src/kprintf/src/ktprintf.c b/src/kprintf/src/ktprintf.c new file mode 100644 index 0000000..f619d54 --- /dev/null +++ b/src/kprintf/src/ktprintf.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <kprintf.h> +#include <io.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdbool.h> +#include <printf.h> + +int ktprintf(const bool time, const char *const fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = ktvprintf(time, fmt, ap); + va_end(ap); + return ret; +} diff --git a/src/kprintf/src/ktvprintf.c b/src/kprintf/src/ktvprintf.c new file mode 100644 index 0000000..a3529c4 --- /dev/null +++ b/src/kprintf/src/ktvprintf.c @@ -0,0 +1,80 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <kprintf.h> +#include <io.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdarg.h> +#include <printf.h> +#include <time.h> + +struct kvprintf +{ + struct fs_fd fd; + size_t n; +}; + +static void writechar(const char c, void *const args) +{ + static char buf[128]; + static size_t bufi; + struct kvprintf *k = args; + + buf[bufi++] = c; + + if (c == '\n' || bufi >= sizeof buf) + { + const struct fs_write w = + { + .buf = buf, + .fd = &k->fd, + .n = bufi + }; + + io_write(&w); + bufi = 0; + } + + k->n++; +} + +int ktvprintf(const bool time, const char *const fmt, va_list ap) +{ + struct timespec ts; + struct kvprintf k = {0}; + const struct fs_open o = + { + .fd = &k.fd, + .path = "/dev/tty", + .mode = O_WRONLY + }; + + if (time && clock_gettime(CLOCK_REALTIME, &ts)) + return -1; + + const long ms = ts.tv_nsec / 1000000; + + if (io_open(&o) + || (time + && fctprintf(writechar, &k, "[%lld.%03ld] ", ts.tv_sec, ms) < 0) + || fctvprintf(writechar, &k, fmt, ap) < 0) + return -1; + + return k.n; +} diff --git a/src/kprintf/src/kvprintf.c b/src/kprintf/src/kvprintf.c new file mode 100644 index 0000000..69890cb --- /dev/null +++ b/src/kprintf/src/kvprintf.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <kprintf.h> +#include <stdarg.h> +#include <stdbool.h> + +int kvprintf(const char *fmt, va_list va) +{ + return ktvprintf(true, fmt, va); +} diff --git a/src/kprintf/src/nwp_log.c b/src/kprintf/src/nwp_log.c new file mode 100644 index 0000000..2db9969 --- /dev/null +++ b/src/kprintf/src/nwp_log.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <kprintf.h> +#include <nanowasm/nw.h> +#include <stdarg.h> + +int nwp_log(const char *const fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = ktvprintf(false, fmt, ap); + va_end(ap); + return ret; +} diff --git a/src/kprintf/src/wip_log.c b/src/kprintf/src/wip_log.c new file mode 100644 index 0000000..67f4f8f --- /dev/null +++ b/src/kprintf/src/wip_log.c @@ -0,0 +1,44 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <kprintf.h> +#include <wip/wip.h> +#include <stdarg.h> + + +#include <drv/ps1/bios.h> +#include <dynstr.h> +int wip_log(const char *const fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); +#if 1 + ret = ktvprintf(false, fmt, ap); +#else + struct dynstr d; + dynstr_init(&d); + if (dynstr_vappend(&d, fmt, ap)) ret = -1; + else + ret = Printf("%s", d.str); + dynstr_free(&d); +#endif + va_end(ap); + return ret; +} diff --git a/src/libc/CMakeLists.txt b/src/libc/CMakeLists.txt index 952df35..309e47a 100644 --- a/src/libc/CMakeLists.txt +++ b/src/libc/CMakeLists.txt @@ -1,4 +1,4 @@ -# wanix, a Unix-like operating system for WebAssembly +# wnix, a Unix-like operating system for WebAssembly applications. # Copyright (C) 2025 Xavier Del Campo Romero # # This program is free software: you can redistribute it and/or modify @@ -15,16 +15,17 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. set(src - "src/errno.c" - "src/free.c" - "src/malloc.c" - "src/memcmp.c" - "src/memcpy.c" - "src/memset.c" - "src/strchr.c" - "src/streams.c" - "src/strerror.c" - "src/strlen.c" + printf/printf.c + tinyalloc/tinyalloc.c ) add_library(c ${src}) -target_include_directories(c PUBLIC "include" PRIVATE "private_include") +add_subdirectory(src) +add_subdirectory(newlib) +target_include_directories(c PUBLIC include printf + PRIVATE private_include tinyalloc) + +target_compile_definitions(c PRIVATE TA_DISABLE_SPLIT TA_DISABLE_COMPACT) + +if(NOT LIBC_FREESTANDING) + target_link_libraries(c PRIVATE aio fs drv) +endif() diff --git a/src/libc/COPYING.NEWLIB b/src/libc/COPYING.NEWLIB new file mode 100644 index 0000000..9a2680d --- /dev/null +++ b/src/libc/COPYING.NEWLIB @@ -0,0 +1,1572 @@ +The newlib subdirectory is a collection of software from several sources. + +Each file may have its own copyright/license that is embedded in the source +file. Unless otherwise noted in the body of the source file(s), the following copyright +notices will apply to the contents of the newlib subdirectory: + +(1) Red Hat Incorporated + +Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved. + +This copyrighted material is made available to anyone wishing to use, +modify, copy, or redistribute it subject to the terms and conditions +of the BSD License. This program is distributed in the hope that +it will be useful, but WITHOUT ANY WARRANTY expressed or implied, +including the implied warranties of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. A copy of this license is available at +http://www.opensource.org/licenses. Any Red Hat trademarks that are +incorporated in the source code or documentation are not subject to +the BSD License and may only be used or replicated with the express +permission of Red Hat, Inc. + +(2) University of California, Berkeley + +Copyright (c) 1981-2000 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +(3) David M. Gay (AT&T 1991, Lucent 1998) + +The author of this software is David M. Gay. + +Copyright (c) 1991 by AT&T. + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY +REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY +OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +------------------------------------------------------------------- + +The author of this software is David M. Gay. + +Copyright (C) 1998-2001 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + +(4) Advanced Micro Devices + +Copyright 1989, 1990 Advanced Micro Devices, Inc. + +This software is the property of Advanced Micro Devices, Inc (AMD) which +specifically grants the user the right to modify, use and distribute this +software provided this notice is not removed or altered. All other rights +are reserved by AMD. + +AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS +SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL +DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR +USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the 29K Technical Support Center at +800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or +0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. + +Advanced Micro Devices, Inc. +29K Support Products +Mail Stop 573 +5900 E. Ben White Blvd. +Austin, TX 78741 +800-292-9263 + +(5) + +(6) + +(7) Sun Microsystems + +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice is preserved. + +(8) Hewlett Packard + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +(9) Hans-Peter Nilsson + +Copyright (C) 2001 Hans-Peter Nilsson + +Permission to use, copy, modify, and distribute this software is +freely granted, provided that the above copyright notice, this notice +and the following disclaimer are preserved with no changes. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +(10) Stephane Carrez (m68hc11-elf/m68hc12-elf targets only) + +Copyright (C) 1999, 2000, 2001, 2002 Stephane Carrez (stcarrez@nerim.fr) + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(11) Christopher G. Demetriou + +Copyright (c) 2001 Christopher G. Demetriou +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(12) SuperH, Inc. + +Copyright 2002 SuperH, Inc. All rights reserved + +This software is the property of SuperH, Inc (SuperH) which specifically +grants the user the right to modify, use and distribute this software +provided this notice is not removed or altered. All other rights are +reserved by SuperH. + +SUPERH MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO +THIS SOFTWARE. IN NO EVENT SHALL SUPERH BE LIABLE FOR INDIRECT, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM +THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the SuperH Support Center via +e-mail at softwaresupport@superh.com . + +SuperH, Inc. +405 River Oaks Parkway +San Jose +CA 95134 +USA + +(13) Royal Institute of Technology + +Copyright (c) 1999 Kungliga Tekniska Högskolan +(Royal Institute of Technology, Stockholm, Sweden). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of KTH nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(14) Alexey Zelkin + +Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(15) Andrey A. Chernov + +Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(16) FreeBSD + +Copyright (c) 1997-2002 FreeBSD Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(17) S. L. Moshier + +Author: S. L. Moshier. + +Copyright (c) 1984,2000 S.L. Moshier + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION +OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS +SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +(18) Citrus Project + +Copyright (c)1999 Citrus Project, +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(19) Todd C. Miller + +Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(20) DJ Delorie (i386 / arm) +Copyright (C) 1991 DJ Delorie +All rights reserved. + +Redistribution, modification, and use in source and binary forms is permitted +provided that the above copyright notice and following paragraph are +duplicated in all such forms. + +This file is distributed WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +(21) Free Software Foundation LGPL License (*-linux* targets only) + + Copyright (C) 1990-1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + +(22) Xavier Leroy LGPL License (i[3456]86-*-linux* targets only) + +Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Library General Public License for more details. + +(23) Intel (i960) + +Copyright (c) 1993 Intel Corporation + +Intel hereby grants you permission to copy, modify, and distribute this +software and its documentation. Intel grants this permission provided +that the above copyright notice appears in all copies and that both the +copyright notice and this permission notice appear in supporting +documentation. In addition, Intel grants this permission provided that +you prominently mark as "not part of the original" any modifications +made to this software or documentation, and that the name of Intel +Corporation not be used in advertising or publicity pertaining to +distribution of the software or the documentation without specific, +written prior permission. + +Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR +IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY +OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or +representations regarding the use of, or the results of the use of, +the software and documentation in terms of correctness, accuracy, +reliability, currentness, or otherwise; and you rely on the software, +documentation and results solely at your own risk. + +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, +LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES +OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM +PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. + +(24) Hewlett-Packard (hppa targets only) + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +(25) Henry Spencer (only *-linux targets) + +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. + +(26) Mike Barcroft + +Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(27) Konstantin Chuguev (--enable-newlib-iconv) + +Copyright (c) 1999, 2000 + Konstantin Chuguev. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + iconv (Charset Conversion Library) v2.0 + +(28) Artem Bityuckiy (--enable-newlib-iconv) + +Copyright (c) 2003, Artem B. Bityuckiy, SoftMine Corporation. +Rights transferred to Franklin Electronic Publishers. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(29) IBM, Sony, Toshiba (only spu-* targets) + + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +(30) - Alex Tatmanjants (targets using libc/posix) + + Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> + at Electronni Visti IA, Kiev, Ukraine. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +(31) - M. Warner Losh (targets using libc/posix) + + Copyright (c) 1998, M. Warner Losh <imp@freebsd.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +(32) - Andrey A. Chernov (targets using libc/posix) + + Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +(33) - Daniel Eischen (targets using libc/posix) + + Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + +(34) - Jon Beniston (only lm32-* targets) + + Contributed by Jon Beniston <jon@beniston.com> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + +(35) - Arm Ltd + + SPDX-License-Identifier: BSD-3-Clause + + Copyright (c) 2009-2022 Arm Ltd + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(36) - Xilinx, Inc. (microblaze-* and powerpc-* targets) + +Copyright (c) 2004, 2009 Xilinx, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of Xilinx nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +(37) Texas Instruments Incorporated (tic6x-*, *-tirtos targets) + +Copyright (c) 1996-2010,2014 Texas Instruments Incorporated +http://www.ti.com/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + Neither the name of Texas Instruments Incorporated nor the names + of its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(38) National Semiconductor (cr16-* and crx-* targets) + +Copyright (c) 2004 National Semiconductor Corporation + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(39) - Adapteva, Inc. (epiphany-* targets) + +Copyright (c) 2011, Adapteva, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Adapteva nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(40) - Altera Corportion (nios2-* targets) + +Copyright (c) 2003 Altera Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + o Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + o Neither the name of Altera Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ALTERA CORPORATION, THE COPYRIGHT HOLDER, +AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(41) Ed Schouten - Free BSD + +Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(42) - Rolls-Royce Controls and Data Services Limited (visium-* targets) + +Copyright (c) 2015 Rolls-Royce Controls and Data Services Limited. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Rolls-Royce Controls and Data Services Limited nor + the names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(43) - FTDI (ft32-* targets) + +Copyright (C) 2014 FTDI (support@ftdichip.com) + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(44) - Synopsys Inc (arc*-* targets) + +Copyright (c) 2015, Synopsys, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1) Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2) Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3) Neither the name of the Synopsys, Inc., nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +(45) embedded brains - RTEMS targets + +Copyright (c) 2017 embedded brains GmbH +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(46) John Baldwin - RTEMS targets + +Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the author nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(47) Jeffrey Roberson - RTEMS targets + +Copyright (c) 2008, Jeffrey Roberson <jeff@freebsd.org> +All rights reserved. + +Copyright (c) 2008 Nokia Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice unmodified, this list of conditions, and the following + disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(48) - SiFive Inc. (riscv-* targets) + +Copyright (c) 2017 SiFive Inc. All rights reserved. + +This copyrighted material is made available to anyone wishing to use, +modify, copy, or redistribute it subject to the terms and conditions +of the FreeBSD License. This program is distributed in the hope that +it will be useful, but WITHOUT ANY WARRANTY expressed or implied, +including the implied warranties of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. A copy of this license is available at +http://www.opensource.org/licenses. + +(49) Michael R. Neilly (riscv-* targets) + +(c) Copyright 2017 Michael R. Neilly +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +* Neither the names of the copyright holders nor the names of their +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +(50) Mentor Graphics (amdgcn-* targets) + +Copyright (c) 2014-2017 Mentor Graphics. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +(51) BSD-2-Clause-FreeBSD (pru-* targets) + +SPDX-License-Identifier: BSD-2-Clause-FreeBSD + +Copyright (c) 2018-2019 Dimitar Dimitrov <dimitar@dinux.eu> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(52) Andrew Turner (arm-* targets) + +Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(53) BSD-2-Clause-FreeBSD David Schultz (arm-* targets) + +SPDX-License-Identifier: BSD-2-Clause-FreeBSD + +Copyright (c) 2004-2011 David Schultz <das@FreeBSD.ORG> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(54) - C-SKY Microsystems (csky-* targets) + +Copyright (c) 2020 C-SKY Microsystems All rights reserved. + +This copyrighted material is made available to anyone wishing to use, +modify, copy, or redistribute it subject to the terms and conditions +of the FreeBSD License. This program is distributed in the hope that +it will be useful, but WITHOUT ANY WARRANTY expressed or implied, +including the implied warranties of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. A copy of this license is available at +http://www.opensource.org/licenses. + +(55) BSD-3-Clause-FreeBSD Peter Wemm (rtems targets) + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (c) 1997 Peter Wemm <peter@freebsd.org> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +(56) MIT OR Apache-2.0 WITH LLVM-exception (newlib/libc/machine/aarch64) + +SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception + + +MIT License +----------- + +Copyright (c) 1999-2023, Arm Limited. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Apache-2.0 WITH LLVM-exception +------------------------------ + + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) 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 + + (d) 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +(57) Steven G. Kargl - libm ld128 functions + +/*- + * Copyright (c) 2017-2023 Steven G. Kargl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + diff --git a/src/libc/include/ctype.h b/src/libc/include/ctype.h new file mode 100644 index 0000000..861da65 --- /dev/null +++ b/src/libc/include/ctype.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _CTYPE_H +#define _CTYPE_H + +int isalpha(int __c); +int islower(int __c); +int isspace(int __c); +int isupper(int __c); +int tolower(int __c); +int toupper(int __c); + +#endif diff --git a/src/libc/include/errno.h b/src/libc/include/errno.h index 0456645..3646089 100644 --- a/src/libc/include/errno.h +++ b/src/libc/include/errno.h @@ -1,3 +1,38 @@ +/* Copyright (C) 1991-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + #ifndef _ERRNO_H #define _ERRNO_H @@ -5,7 +40,7 @@ extern int errno; enum { - OK, + SUCCESS, EPERM, ENOENT, ESRCH, @@ -38,6 +73,105 @@ enum EROFS, EMLINK, EPIPE, + EDOM, + ERANGE, + EDEADLK, + ENAMETOOLONG, + ENOLCK, + ENOSYS, + ENOTEMPTY, + ELOOP, + ENOMSG, + EIDRM, + ECHRNG, + EL2NSYNC, + EL3HLT, + EL3RST, + ELNRNG, + EUNATCH, + ENOCSI, + EL2HLT, + EBADE, + EBADR, + EXFULL, + ENOANO, + EBADRQC, + EBADSLT, + EBFONT, + ENOSTR, + ENODATA, + ETIME, + ENOSR, + ENONET, + ENOPKG, + EREMOTE, + ENOLINK, + EADV, + ESRMNT, + ECOMM, + EPROTO, + EMULTIHOP, + EDOTDOT, + EBADMSG, + EOVERFLOW, + ENOTUNIQ, + EBADFD, + EREMCHG, + ELIBACC, + ELIBBAD, + ELIBSCN, + ELIBMAX, + ELIBEXEC, + EILSEQ, + ERESTART, + ESTRPIPE, + EUSERS, + ENOTSOCK, + EDESTADDRREQ, + EMSGSIZE, + EPROTOTYPE, + ENOPROTOOPT, + EPROTONOSUPPORT, + ESOCKTNOSUPPORT, + ENOTSUP, + EPFNOSUPPORT, + EAFNOSUPPORT, + EADDRINUSE, + EADDRNOTAVAIL, + ENETDOWN, + ENETUNREACH, + ENETRESET, + ECONNABORTED, + ECONNRESET, + ENOBUFS, + EISCONN, + ENOTCONN, + ESHUTDOWN, + ETOOMANYREFS, + ETIMEDOUT, + ECONNREFUSED, + EHOSTDOWN, + EHOSTUNREACH, + EALREADY, + EINPROGRESS, + ESTALE, + EUCLEAN, + ENOTNAM, + ENAVAIL, + EISNAM, + EREMOTEIO, + EDQUOT, + ENOMEDIUM, + EMEDIUMTYPE, + ECANCELED, + ENOKEY, + EKEYEXPIRED, + EKEYREVOKED, + EKEYREJECTED, + EOWNERDEAD, + ENOTRECOVERABLE, + ERFKILL, + EHWPOISON }; #endif diff --git a/src/libc/include/fcntl.h b/src/libc/include/fcntl.h new file mode 100644 index 0000000..282ced8 --- /dev/null +++ b/src/libc/include/fcntl.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _FCNTL_H +#define _FCNTL_H + +enum +{ + O_RDONLY = 1, + O_WRONLY = 1 << 1, + O_RDWR = O_RDONLY | O_WRONLY +}; + +#endif diff --git a/src/libc/include/inttypes.h b/src/libc/include/inttypes.h new file mode 100644 index 0000000..afb424c --- /dev/null +++ b/src/libc/include/inttypes.h @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#define PRIu8 "hhu" +#define PRIu16 "hu" +#define PRIu32 "lu" +#define PRIu64 "llu" +#define PRIi8 "hhd" +#define PRIi16 "hd" +#define PRIi32 "ld" +#define PRIi64 "lld" +#define PRIx8 "hhx" +#define PRIx16 "hx" +#define PRIx32 "lx" +#define PRIx64 "llx" + +#endif diff --git a/src/libc/include/limits.h b/src/libc/include/limits.h new file mode 100644 index 0000000..6c50848 --- /dev/null +++ b/src/libc/include/limits.h @@ -0,0 +1,152 @@ +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#ifndef _LIMITS_H___ +#define _LIMITS_H___ + +/* Number of bits in a `char'. */ +#undef CHAR_BIT +#define CHAR_BIT __CHAR_BIT__ + +/* Maximum length of a multibyte character. */ +#ifndef MB_LEN_MAX +#define MB_LEN_MAX 1 +#endif + +/* Minimum and maximum values a `signed char' can hold. */ +#undef SCHAR_MIN +#define SCHAR_MIN (-SCHAR_MAX - 1) +#undef SCHAR_MAX +#define SCHAR_MAX __SCHAR_MAX__ + +/* Maximum value an `unsigned char' can hold. (Minimum is 0). */ +#undef UCHAR_MAX +#if __SCHAR_MAX__ == __INT_MAX__ +# define UCHAR_MAX (SCHAR_MAX * 2U + 1U) +#else +# define UCHAR_MAX (SCHAR_MAX * 2 + 1) +#endif + +/* Minimum and maximum values a `char' can hold. */ +#ifdef __CHAR_UNSIGNED__ +# undef CHAR_MIN +# if __SCHAR_MAX__ == __INT_MAX__ +# define CHAR_MIN 0U +# else +# define CHAR_MIN 0 +# endif +# undef CHAR_MAX +# define CHAR_MAX UCHAR_MAX +#else +# undef CHAR_MIN +# define CHAR_MIN SCHAR_MIN +# undef CHAR_MAX +# define CHAR_MAX SCHAR_MAX +#endif + +/* Minimum and maximum values a `signed short int' can hold. */ +#undef SHRT_MIN +#define SHRT_MIN (-SHRT_MAX - 1) +#undef SHRT_MAX +#define SHRT_MAX __SHRT_MAX__ + +/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */ +#undef USHRT_MAX +#if __SHRT_MAX__ == __INT_MAX__ +# define USHRT_MAX (SHRT_MAX * 2U + 1U) +#else +# define USHRT_MAX (SHRT_MAX * 2 + 1) +#endif + +/* Minimum and maximum values a `signed int' can hold. */ +#undef INT_MIN +#define INT_MIN (-INT_MAX - 1) +#undef INT_MAX +#define INT_MAX __INT_MAX__ + +/* Maximum value an `unsigned int' can hold. (Minimum is 0). */ +#undef UINT_MAX +#define UINT_MAX (INT_MAX * 2U + 1U) + +/* Minimum and maximum values a `signed long int' can hold. + (Same as `int'). */ +#undef LONG_MIN +#define LONG_MIN (-LONG_MAX - 1L) +#undef LONG_MAX +#define LONG_MAX __LONG_MAX__ + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ +#undef ULONG_MAX +#define ULONG_MAX (LONG_MAX * 2UL + 1UL) + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - 1LL) +# undef LLONG_MAX +# define LLONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULLONG_MAX +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +#endif + +#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__) +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LONG_LONG_MIN +# define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL) +# undef LONG_LONG_MAX +# define LONG_LONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULONG_LONG_MAX +# define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL) +#endif + +#ifdef __STDC_WANT_IEC_60559_BFP_EXT__ +/* TS 18661-1 widths of integer types. */ +# undef CHAR_WIDTH +# define CHAR_WIDTH __SCHAR_WIDTH__ +# undef SCHAR_WIDTH +# define SCHAR_WIDTH __SCHAR_WIDTH__ +# undef UCHAR_WIDTH +# define UCHAR_WIDTH __SCHAR_WIDTH__ +# undef SHRT_WIDTH +# define SHRT_WIDTH __SHRT_WIDTH__ +# undef USHRT_WIDTH +# define USHRT_WIDTH __SHRT_WIDTH__ +# undef INT_WIDTH +# define INT_WIDTH __INT_WIDTH__ +# undef UINT_WIDTH +# define UINT_WIDTH __INT_WIDTH__ +# undef LONG_WIDTH +# define LONG_WIDTH __LONG_WIDTH__ +# undef ULONG_WIDTH +# define ULONG_WIDTH __LONG_WIDTH__ +# undef LLONG_WIDTH +# define LLONG_WIDTH __LONG_LONG_WIDTH__ +# undef ULLONG_WIDTH +# define ULLONG_WIDTH __LONG_LONG_WIDTH__ +#endif + +#endif /* _LIMITS_H___ */ diff --git a/src/libc/include/setjmp.h b/src/libc/include/setjmp.h new file mode 100644 index 0000000..d372c91 --- /dev/null +++ b/src/libc/include/setjmp.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _STDJUMP_H +#define _STDJUMP_H + +typedef struct +{ + unsigned pc, sp, fp, s0, s1, s2, s3, s4, s5, s6, s7, gp; +} jmp_buf[1]; + +int setjmp(jmp_buf __env); + +#endif diff --git a/src/libc/include/stdarg.h b/src/libc/include/stdarg.h new file mode 100644 index 0000000..eeb4d3f --- /dev/null +++ b/src/libc/include/stdarg.h @@ -0,0 +1,127 @@ +/* Copyright (C) 1989-2018 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* + * ISO C Standard: 7.15 Variable arguments <stdarg.h> + */ + +#ifndef _STDARG_H +#ifndef _ANSI_STDARG_H_ +#ifndef __need___va_list +#define _STDARG_H +#define _ANSI_STDARG_H_ +#endif /* not __need___va_list */ +#undef __need___va_list + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef __builtin_va_list __gnuc_va_list; +#endif + +/* Define the standard macros for the user, + if this invocation was from the user program. */ +#ifdef _STDARG_H + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \ + || __cplusplus + 0 >= 201103L +#define va_copy(d,s) __builtin_va_copy(d,s) +#endif +#define __va_copy(d,s) __builtin_va_copy(d,s) + +/* Define va_list, if desired, from __gnuc_va_list. */ +/* We deliberately do not define va_list when called from + stdio.h, because ANSI C says that stdio.h is not supposed to define + va_list. stdio.h needs to have access to that data type, + but must not use that name. It should use the name __gnuc_va_list, + which is safe because it is reserved for the implementation. */ + +#ifdef _BSD_VA_LIST +#undef _BSD_VA_LIST +#endif + +#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) +/* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. + SVR4 uses _VA_LIST as a flag in stdarg.h, but we should + have no conflict with that. */ +#ifndef _VA_LIST_ +#define _VA_LIST_ +#ifdef __i860__ +#ifndef _VA_LIST +#define _VA_LIST va_list +#endif +#endif /* __i860__ */ +typedef __gnuc_va_list va_list; +#ifdef _SCO_DS +#define __VA_LIST +#endif +#endif /* _VA_LIST_ */ +#else /* not __svr4__ || _SCO_DS */ + +/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. + But on BSD NET2 we must not test or define or undef it. + (Note that the comments in NET 2's ansi.h + are incorrect for _VA_LIST_--see stdio.h!) */ +#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) +/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ +#ifndef _VA_LIST_DEFINED +/* The macro _VA_LIST is used in SCO Unix 3.2. */ +#ifndef _VA_LIST +/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ +#ifndef _VA_LIST_T_H +/* The macro __va_list__ is used by BeOS. */ +#ifndef __va_list__ +typedef __gnuc_va_list va_list; +#endif /* not __va_list__ */ +#endif /* not _VA_LIST_T_H */ +#endif /* not _VA_LIST */ +#endif /* not _VA_LIST_DEFINED */ +#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) +#define _VA_LIST_ +#endif +#ifndef _VA_LIST +#define _VA_LIST +#endif +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif +#ifndef _VA_LIST_T_H +#define _VA_LIST_T_H +#endif +#ifndef __va_list__ +#define __va_list__ +#endif + +#endif /* not _VA_LIST_, except on certain systems */ + +#endif /* not __svr4__ */ + +#endif /* _STDARG_H */ + +#endif /* not _ANSI_STDARG_H_ */ +#endif /* not _STDARG_H */ diff --git a/src/libc/include/stdbool.h b/src/libc/include/stdbool.h new file mode 100644 index 0000000..aa55406 --- /dev/null +++ b/src/libc/include/stdbool.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1998-2018 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* + * ISO C Standard: 7.16 Boolean type and values <stdbool.h> + */ + +#ifndef _STDBOOL_H +#define _STDBOOL_H + +#ifndef __cplusplus + +#define bool _Bool +#define true 1 +#define false 0 + +#else /* __cplusplus */ + +/* Supporting _Bool in C++ is a GCC extension. */ +#define _Bool bool + +#if __cplusplus < 201103L +/* Defining these macros in C++98 is a GCC extension. */ +#define bool bool +#define false false +#define true true +#endif + +#endif /* __cplusplus */ + +/* Signal that all the definitions are present. */ +#define __bool_true_false_are_defined 1 + +#endif /* stdbool.h */ diff --git a/src/libc/include/stddef.h b/src/libc/include/stddef.h new file mode 100644 index 0000000..31b96a7 --- /dev/null +++ b/src/libc/include/stddef.h @@ -0,0 +1,451 @@ +/* Copyright (C) 1989-2018 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* + * ISO C Standard: 7.17 Common definitions <stddef.h> + */ +#if (!defined(_STDDEF_H) && !defined(_STDDEF_H_) && !defined(_ANSI_STDDEF_H) \ + && !defined(__STDDEF_H__)) \ + || defined(__need_wchar_t) || defined(__need_size_t) \ + || defined(__need_ptrdiff_t) || defined(__need_NULL) \ + || defined(__need_wint_t) + +/* Any one of these symbols __need_* means that GNU libc + wants us just to define one data type. So don't define + the symbols that indicate this file's entire job has been done. */ +#if (!defined(__need_wchar_t) && !defined(__need_size_t) \ + && !defined(__need_ptrdiff_t) && !defined(__need_NULL) \ + && !defined(__need_wint_t)) +#define _STDDEF_H +#define _STDDEF_H_ +/* snaroff@next.com says the NeXT needs this. */ +#define _ANSI_STDDEF_H +#endif + +#ifndef __sys_stdtypes_h +/* This avoids lossage on SunOS but only if stdtypes.h comes first. + There's no way to win with the other order! Sun lossage. */ + +/* On 4.3bsd-net2, make sure ansi.h is included, so we have + one less case to deal with in the following. */ +#if defined (__BSD_NET2__) || defined (____386BSD____) || (defined (__FreeBSD__) && (__FreeBSD__ < 5)) || defined(__NetBSD__) +#include <machine/ansi.h> +#endif +/* On FreeBSD 5, machine/ansi.h does not exist anymore... */ +#if defined (__FreeBSD__) && (__FreeBSD__ >= 5) +#include <sys/_types.h> +#endif + +/* In 4.3bsd-net2, machine/ansi.h defines these symbols, which are + defined if the corresponding type is *not* defined. + FreeBSD-2.1 defines _MACHINE_ANSI_H_ instead of _ANSI_H_. + NetBSD defines _I386_ANSI_H_ and _X86_64_ANSI_H_ instead of _ANSI_H_ */ +#if defined(_ANSI_H_) || defined(_MACHINE_ANSI_H_) || defined(_X86_64_ANSI_H_) || defined(_I386_ANSI_H_) +#if !defined(_SIZE_T_) && !defined(_BSD_SIZE_T_) +#define _SIZE_T +#endif +#if !defined(_PTRDIFF_T_) && !defined(_BSD_PTRDIFF_T_) +#define _PTRDIFF_T +#endif +/* On BSD/386 1.1, at least, machine/ansi.h defines _BSD_WCHAR_T_ + instead of _WCHAR_T_. */ +#if !defined(_WCHAR_T_) && !defined(_BSD_WCHAR_T_) +#ifndef _BSD_WCHAR_T_ +#define _WCHAR_T +#endif +#endif +/* Undef _FOO_T_ if we are supposed to define foo_t. */ +#if defined (__need_ptrdiff_t) || defined (_STDDEF_H_) +#undef _PTRDIFF_T_ +#undef _BSD_PTRDIFF_T_ +#endif +#if defined (__need_size_t) || defined (_STDDEF_H_) +#undef _SIZE_T_ +#undef _BSD_SIZE_T_ +#endif +#if defined (__need_wchar_t) || defined (_STDDEF_H_) +#undef _WCHAR_T_ +#undef _BSD_WCHAR_T_ +#endif +#endif /* defined(_ANSI_H_) || defined(_MACHINE_ANSI_H_) || defined(_X86_64_ANSI_H_) || defined(_I386_ANSI_H_) */ + +/* Sequent's header files use _PTRDIFF_T_ in some conflicting way. + Just ignore it. */ +#if defined (__sequent__) && defined (_PTRDIFF_T_) +#undef _PTRDIFF_T_ +#endif + +/* On VxWorks, <type/vxTypesBase.h> may have defined macros like + _TYPE_size_t which will typedef size_t. fixincludes patched the + vxTypesBase.h so that this macro is only defined if _GCC_SIZE_T is + not defined, and so that defining this macro defines _GCC_SIZE_T. + If we find that the macros are still defined at this point, we must + invoke them so that the type is defined as expected. */ +#if defined (_TYPE_ptrdiff_t) && (defined (__need_ptrdiff_t) || defined (_STDDEF_H_)) +_TYPE_ptrdiff_t; +#undef _TYPE_ptrdiff_t +#endif +#if defined (_TYPE_size_t) && (defined (__need_size_t) || defined (_STDDEF_H_)) +_TYPE_size_t; +#undef _TYPE_size_t +#endif +#if defined (_TYPE_wchar_t) && (defined (__need_wchar_t) || defined (_STDDEF_H_)) +_TYPE_wchar_t; +#undef _TYPE_wchar_t +#endif + +/* In case nobody has defined these types, but we aren't running under + GCC 2.00, make sure that __PTRDIFF_TYPE__, __SIZE_TYPE__, and + __WCHAR_TYPE__ have reasonable values. This can happen if the + parts of GCC is compiled by an older compiler, that actually + include gstddef.h, such as collect2. */ + +/* Signed type of difference of two pointers. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (_STDDEF_H) || defined (__need_ptrdiff_t) +#ifndef _PTRDIFF_T /* in case <sys/types.h> has defined it. */ +#ifndef _T_PTRDIFF_ +#ifndef _T_PTRDIFF +#ifndef __PTRDIFF_T +#ifndef _PTRDIFF_T_ +#ifndef _BSD_PTRDIFF_T_ +#ifndef ___int_ptrdiff_t_h +#ifndef _GCC_PTRDIFF_T +#ifndef _PTRDIFF_T_DECLARED /* DragonFly */ +#define _PTRDIFF_T +#define _T_PTRDIFF_ +#define _T_PTRDIFF +#define __PTRDIFF_T +#define _PTRDIFF_T_ +#define _BSD_PTRDIFF_T_ +#define ___int_ptrdiff_t_h +#define _GCC_PTRDIFF_T +#define _PTRDIFF_T_DECLARED +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ long int +#endif +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#endif /* _PTRDIFF_T_DECLARED */ +#endif /* _GCC_PTRDIFF_T */ +#endif /* ___int_ptrdiff_t_h */ +#endif /* _BSD_PTRDIFF_T_ */ +#endif /* _PTRDIFF_T_ */ +#endif /* __PTRDIFF_T */ +#endif /* _T_PTRDIFF */ +#endif /* _T_PTRDIFF_ */ +#endif /* _PTRDIFF_T */ + +/* If this symbol has done its job, get rid of it. */ +#undef __need_ptrdiff_t + +#endif /* _STDDEF_H or __need_ptrdiff_t. */ + +/* Unsigned type of `sizeof' something. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (_STDDEF_H) || defined (__need_size_t) +#ifndef __size_t__ /* BeOS */ +#ifndef __SIZE_T__ /* Cray Unicos/Mk */ +#ifndef _SIZE_T /* in case <sys/types.h> has defined it. */ +#ifndef _SYS_SIZE_T_H +#ifndef _T_SIZE_ +#ifndef _T_SIZE +#ifndef __SIZE_T +#ifndef _SIZE_T_ +#ifndef _BSD_SIZE_T_ +#ifndef _SIZE_T_DEFINED_ +#ifndef _SIZE_T_DEFINED +#ifndef _BSD_SIZE_T_DEFINED_ /* Darwin */ +#ifndef _SIZE_T_DECLARED /* FreeBSD 5 */ +#ifndef ___int_size_t_h +#ifndef _GCC_SIZE_T +#ifndef _SIZET_ +#ifndef __size_t +#define __size_t__ /* BeOS */ +#define __SIZE_T__ /* Cray Unicos/Mk */ +#define _SIZE_T +#define _SYS_SIZE_T_H +#define _T_SIZE_ +#define _T_SIZE +#define __SIZE_T +#define _SIZE_T_ +#define _BSD_SIZE_T_ +#define _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED +#define _BSD_SIZE_T_DEFINED_ /* Darwin */ +#define _SIZE_T_DECLARED /* FreeBSD 5 */ +#define ___int_size_t_h +#define _GCC_SIZE_T +#define _SIZET_ +#if (defined (__FreeBSD__) && (__FreeBSD__ >= 5)) \ + || defined(__DragonFly__) \ + || defined(__FreeBSD_kernel__) +/* __size_t is a typedef on FreeBSD 5, must not trash it. */ +#elif defined (__VMS__) +/* __size_t is also a typedef on VMS. */ +#else +#define __size_t +#endif +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ long unsigned int +#endif +#if !(defined (__GNUG__) && defined (size_t)) +typedef __SIZE_TYPE__ size_t; +#ifdef __BEOS__ +typedef long ssize_t; +#endif /* __BEOS__ */ +#endif /* !(defined (__GNUG__) && defined (size_t)) */ +#endif /* __size_t */ +#endif /* _SIZET_ */ +#endif /* _GCC_SIZE_T */ +#endif /* ___int_size_t_h */ +#endif /* _SIZE_T_DECLARED */ +#endif /* _BSD_SIZE_T_DEFINED_ */ +#endif /* _SIZE_T_DEFINED */ +#endif /* _SIZE_T_DEFINED_ */ +#endif /* _BSD_SIZE_T_ */ +#endif /* _SIZE_T_ */ +#endif /* __SIZE_T */ +#endif /* _T_SIZE */ +#endif /* _T_SIZE_ */ +#endif /* _SYS_SIZE_T_H */ +#endif /* _SIZE_T */ +#endif /* __SIZE_T__ */ +#endif /* __size_t__ */ +#undef __need_size_t +#endif /* _STDDEF_H or __need_size_t. */ + + +/* Wide character type. + Locale-writers should change this as necessary to + be big enough to hold unique values not between 0 and 127, + and not (wchar_t) -1, for each defined multibyte character. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (_STDDEF_H) || defined (__need_wchar_t) +#ifndef __wchar_t__ /* BeOS */ +#ifndef __WCHAR_T__ /* Cray Unicos/Mk */ +#ifndef _WCHAR_T +#ifndef _T_WCHAR_ +#ifndef _T_WCHAR +#ifndef __WCHAR_T +#ifndef _WCHAR_T_ +#ifndef _BSD_WCHAR_T_ +#ifndef _BSD_WCHAR_T_DEFINED_ /* Darwin */ +#ifndef _BSD_RUNE_T_DEFINED_ /* Darwin */ +#ifndef _WCHAR_T_DECLARED /* FreeBSD 5 */ +#ifndef _WCHAR_T_DEFINED_ +#ifndef _WCHAR_T_DEFINED +#ifndef _WCHAR_T_H +#ifndef ___int_wchar_t_h +#ifndef __INT_WCHAR_T_H +#ifndef _GCC_WCHAR_T +#define __wchar_t__ /* BeOS */ +#define __WCHAR_T__ /* Cray Unicos/Mk */ +#define _WCHAR_T +#define _T_WCHAR_ +#define _T_WCHAR +#define __WCHAR_T +#define _WCHAR_T_ +#define _BSD_WCHAR_T_ +#define _WCHAR_T_DEFINED_ +#define _WCHAR_T_DEFINED +#define _WCHAR_T_H +#define ___int_wchar_t_h +#define __INT_WCHAR_T_H +#define _GCC_WCHAR_T +#define _WCHAR_T_DECLARED + +/* On BSD/386 1.1, at least, machine/ansi.h defines _BSD_WCHAR_T_ + instead of _WCHAR_T_, and _BSD_RUNE_T_ (which, unlike the other + symbols in the _FOO_T_ family, stays defined even after its + corresponding type is defined). If we define wchar_t, then we + must undef _WCHAR_T_; for BSD/386 1.1 (and perhaps others), if + we undef _WCHAR_T_, then we must also define rune_t, since + headers like runetype.h assume that if machine/ansi.h is included, + and _BSD_WCHAR_T_ is not defined, then rune_t is available. + machine/ansi.h says, "Note that _WCHAR_T_ and _RUNE_T_ must be of + the same type." */ +#ifdef _BSD_WCHAR_T_ +#undef _BSD_WCHAR_T_ +#ifdef _BSD_RUNE_T_ +#if !defined (_ANSI_SOURCE) && !defined (_POSIX_SOURCE) +typedef _BSD_RUNE_T_ rune_t; +#define _BSD_WCHAR_T_DEFINED_ +#define _BSD_RUNE_T_DEFINED_ /* Darwin */ +#if defined (__FreeBSD__) && (__FreeBSD__ < 5) +/* Why is this file so hard to maintain properly? In contrast to + the comment above regarding BSD/386 1.1, on FreeBSD for as long + as the symbol has existed, _BSD_RUNE_T_ must not stay defined or + redundant typedefs will occur when stdlib.h is included after this file. */ +#undef _BSD_RUNE_T_ +#endif +#endif +#endif +#endif +/* FreeBSD 5 can't be handled well using "traditional" logic above + since it no longer defines _BSD_RUNE_T_ yet still desires to export + rune_t in some cases... */ +#if defined (__FreeBSD__) && (__FreeBSD__ >= 5) +#if !defined (_ANSI_SOURCE) && !defined (_POSIX_SOURCE) +#if __BSD_VISIBLE +#ifndef _RUNE_T_DECLARED +typedef __rune_t rune_t; +#define _RUNE_T_DECLARED +#endif +#endif +#endif +#endif + +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif /* _WCHAR_T_DECLARED */ +#endif /* _BSD_RUNE_T_DEFINED_ */ +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif /* __WCHAR_T__ */ +#endif /* __wchar_t__ */ +#undef __need_wchar_t +#endif /* _STDDEF_H or __need_wchar_t. */ + +#if defined (__need_wint_t) +#ifndef _WINT_T +#define _WINT_T + +#ifndef __WINT_TYPE__ +#define __WINT_TYPE__ unsigned int +#endif +typedef __WINT_TYPE__ wint_t; +#endif +#undef __need_wint_t +#endif + +/* In 4.3bsd-net2, leave these undefined to indicate that size_t, etc. + are already defined. */ +/* BSD/OS 3.1 and FreeBSD [23].x require the MACHINE_ANSI_H check here. */ +/* NetBSD 5 requires the I386_ANSI_H and X86_64_ANSI_H checks here. */ +#if defined(_ANSI_H_) || defined(_MACHINE_ANSI_H_) || defined(_X86_64_ANSI_H_) || defined(_I386_ANSI_H_) +/* The references to _GCC_PTRDIFF_T_, _GCC_SIZE_T_, and _GCC_WCHAR_T_ + are probably typos and should be removed before 2.8 is released. */ +#ifdef _GCC_PTRDIFF_T_ +#undef _PTRDIFF_T_ +#undef _BSD_PTRDIFF_T_ +#endif +#ifdef _GCC_SIZE_T_ +#undef _SIZE_T_ +#undef _BSD_SIZE_T_ +#endif +#ifdef _GCC_WCHAR_T_ +#undef _WCHAR_T_ +#undef _BSD_WCHAR_T_ +#endif +/* The following ones are the real ones. */ +#ifdef _GCC_PTRDIFF_T +#undef _PTRDIFF_T_ +#undef _BSD_PTRDIFF_T_ +#endif +#ifdef _GCC_SIZE_T +#undef _SIZE_T_ +#undef _BSD_SIZE_T_ +#endif +#ifdef _GCC_WCHAR_T +#undef _WCHAR_T_ +#undef _BSD_WCHAR_T_ +#endif +#endif /* _ANSI_H_ || _MACHINE_ANSI_H_ || _X86_64_ANSI_H_ || _I386_ANSI_H_ */ + +#endif /* __sys_stdtypes_h */ + +/* A null pointer constant. */ + +#if defined (_STDDEF_H) || defined (__need_NULL) +#undef NULL /* in case <stdio.h> has defined it. */ +#ifdef __GNUG__ +#define NULL __null +#else /* G++ */ +#ifndef __cplusplus +#define NULL ((void *)0) +#else /* C++ */ +#define NULL 0 +#endif /* C++ */ +#endif /* G++ */ +#endif /* NULL not defined and <stddef.h> or need NULL. */ +#undef __need_NULL + +#ifdef _STDDEF_H + +/* Offset of member MEMBER in a struct of type TYPE. */ +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) + +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ + || (defined(__cplusplus) && __cplusplus >= 201103L) +#ifndef _GCC_MAX_ALIGN_T +#define _GCC_MAX_ALIGN_T +/* Type whose alignment is supported in every context and is at least + as great as that of any standard type not using alignment + specifiers. */ +typedef struct { + long long __max_align_ll __attribute__((__aligned__(__alignof__(long long)))); + long double __max_align_ld __attribute__((__aligned__(__alignof__(long double)))); + /* _Float128 is defined as a basic type, so max_align_t must be + sufficiently aligned for it. This code must work in C++, so we + use __float128 here; that is only available on some + architectures, but only on i386 is extra alignment needed for + __float128. */ +#ifdef __i386__ + __float128 __max_align_f128 __attribute__((__aligned__(__alignof(__float128)))); +#endif +} max_align_t; +#endif +#endif /* C11 or C++11. */ + +#if defined(__cplusplus) && __cplusplus >= 201103L +#ifndef _GXX_NULLPTR_T +#define _GXX_NULLPTR_T + typedef decltype(nullptr) nullptr_t; +#endif +#endif /* C++11. */ + +#endif /* _STDDEF_H was defined this time */ + +#endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__ + || __need_XXX was not defined before */ diff --git a/src/libc/include/stdint.h b/src/libc/include/stdint.h new file mode 100644 index 0000000..ba8419a --- /dev/null +++ b/src/libc/include/stdint.h @@ -0,0 +1,33 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _STDINT_H +#define _STDINT_H + +typedef unsigned char uint8_t, uint_least8_t; +typedef signed char int8_t, int_least8_t; +typedef unsigned short uint16_t, uint_least16_t; +typedef short int16_t, int_least16_t; +typedef unsigned uintptr_t, uint32_t, uint_least32_t, uint_fast8_t, + uint_fast16_t, uint_fast32_t; +typedef int intptr_t, int32_t, int_least32_t, int_fast8_t, int_fast16_t, + int_fast32_t; +typedef unsigned long long uint64_t, uint_least64_t, uint_fast64_t, uintmax_t; +typedef long long int64_t, int_least64_t, int_fast64_t, intmax_t; + +#endif diff --git a/src/libc/include/stdio.h b/src/libc/include/stdio.h index 1d0e27c..b9c1a38 100644 --- a/src/libc/include/stdio.h +++ b/src/libc/include/stdio.h @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -19,17 +19,11 @@ #ifndef _STDIO_H #define _STDIO_H -enum -{ - EOF = -1 -}; +enum {EOF = -1}; -typedef struct __file FILE; +int puts(const char *__s); +int putchar(int __c); -FILE *fopen(const char *__path, const char *__mode); -int printf(const char *__fmt, ...); -int fprintf(FILE *__stream, const char *__fmt, ...); - -extern FILE *stdin, *stdout, *stderr; +#include <printf.h> #endif diff --git a/src/libc/include/stdlib.h b/src/libc/include/stdlib.h index 4065f1c..8f97ea3 100644 --- a/src/libc/include/stdlib.h +++ b/src/libc/include/stdlib.h @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -24,8 +24,25 @@ #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 +#define abort() __abort(__FILE__, __LINE__) + +typedef struct +{ + int quot, rem; +} div_t; + +int abs(int __v); +long labs(long __v); +long long llabs(long long __v); void *malloc(size_t __n); void *calloc(size_t __nemb, size_t __size); +void *realloc(void *__ptr, size_t __size); void free(void *__p); +long strtol(const char *__s, char **__end, int __base); +long long strtoll(const char *__s, char **__end, int __base); +unsigned long strtoul(const char *__s, char **__end, int __base); +unsigned long long strtoull(const char *__s, char **__end, int __base); +void __abort(const char *__file, int __lineno); +div_t div(int __numerator, int __denominator); #endif diff --git a/src/libc/include/string.h b/src/libc/include/string.h index 20c9cf3..1e62a84 100644 --- a/src/libc/include/string.h +++ b/src/libc/include/string.h @@ -1,3 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + #ifndef _STRING_H #define _STRING_H @@ -6,8 +24,17 @@ int memcmp(const void *__s1, const void *__s2, size_t __n); void *memcpy(void *__dst, const void *__src, size_t __n); void *memset(void *__dst, int __c, size_t __n); +int strcasecmp(const char *__a, const char *__b); char *strchr(const char *__s, int __n); -char *strerror(int errnum); +int strcmp(const char *__a, const char *__b); +char *strdup(const char *__s); +char *strerror(int __errnum); +int strncmp(const char *__a, const char *__b, size_t __n); +char *strndup(const char *__s, size_t __n); +char *strpbrk(const char *const __s, const char *__accept); size_t strlen(const char *__s); +char *strrchr(const char *__s, int __c); +size_t strspn(const char *__s, const char *__accept); +size_t strcspn(const char *__s, const char * __reject); #endif diff --git a/src/libc/include/sys/mount.h b/src/libc/include/sys/mount.h new file mode 100644 index 0000000..eae6d63 --- /dev/null +++ b/src/libc/include/sys/mount.h @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +int mount(const char *__src, const char *__tgt, const char *__type, + unsigned long __flags, const void *__args); + +#endif diff --git a/src/libc/include/sys/stat.h b/src/libc/include/sys/stat.h new file mode 100644 index 0000000..08fcf9a --- /dev/null +++ b/src/libc/include/sys/stat.h @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include <sys/types.h> +#include <time.h> + +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + struct timespec st_atim, st_mtim, st_ctim; + blksize_t st_blksize; + blkcnt_t st_blocks; +}; + +int mkdir(const char *pathname, mode_t flags); + +#endif diff --git a/src/libc/include/sys/types.h b/src/libc/include/sys/types.h new file mode 100644 index 0000000..86ca604 --- /dev/null +++ b/src/libc/include/sys/types.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +typedef unsigned dev_t, mode_t, nlink_t, uid_t, gid_t, blksize_t, blkcnt_t; +typedef unsigned long ino_t, off_t; +typedef int pid_t; + +#endif diff --git a/src/libc/include/time.h b/src/libc/include/time.h new file mode 100644 index 0000000..3b78d22 --- /dev/null +++ b/src/libc/include/time.h @@ -0,0 +1,46 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _TIME_H +#define _TIME_H + +typedef enum +{ + CLOCK_REALTIME +} clockid_t; + +typedef long long time_t; + +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; + +struct tm +{ + int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, + tm_isdst; +}; + +int clock_getres(clockid_t __id, struct timespec *__ts); +int clock_gettime(clockid_t __id, struct timespec *__ts); +int clock_settime(clockid_t __id, const struct timespec *__ts); +time_t mktime(struct tm *__tm); + +#endif diff --git a/src/libc/include/unistd.h b/src/libc/include/unistd.h new file mode 100644 index 0000000..ec4fc13 --- /dev/null +++ b/src/libc/include/unistd.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include <stdint.h> + +void *sbrk(intptr_t increment); + +#endif diff --git a/src/libc/newlib/CMakeLists.txt b/src/libc/newlib/CMakeLists.txt new file mode 100644 index 0000000..aedf961 --- /dev/null +++ b/src/libc/newlib/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_subdirectory(src) +target_include_directories(c PRIVATE private_include) diff --git a/src/libc/newlib/private_include/sys/_tz_structs.h b/src/libc/newlib/private_include/sys/_tz_structs.h new file mode 100644 index 0000000..f20aacb --- /dev/null +++ b/src/libc/newlib/private_include/sys/_tz_structs.h @@ -0,0 +1,30 @@ +#ifndef _SYS__TZ_STRUCTS_H_ +#define _SYS__TZ_STRUCTS_H_ + +#include <time.h> + +typedef struct __tzrule_struct +{ + char ch; + int m; /* Month of year if ch=M */ + int n; /* Week of month if ch=M */ + int d; /* Day of week if ch=M, day of year if ch=J or ch=D */ + int s; /* Time of day in seconds */ + time_t change; + long offset; /* Match type of _timezone. */ +} __tzrule_type; + +typedef struct __tzinfo_struct +{ + int __tznorth; + int __tzyear; + __tzrule_type __tzrule[2]; +} __tzinfo_type; + +__tzinfo_type *__gettzinfo (void); + +extern char *_tzname[2]; +extern int _daylight; +extern long _timezone; + +#endif /* _SYS__TZ_STRUCTS_H_ */ diff --git a/src/libc/newlib/src/CMakeLists.txt b/src/libc/newlib/src/CMakeLists.txt new file mode 100644 index 0000000..f2f8ba4 --- /dev/null +++ b/src/libc/newlib/src/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_subdirectory(stdlib) +add_subdirectory(time) diff --git a/src/libc/newlib/src/stdlib/CMakeLists.txt b/src/libc/newlib/src/stdlib/CMakeLists.txt new file mode 100644 index 0000000..ab499b9 --- /dev/null +++ b/src/libc/newlib/src/stdlib/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + div.c +) diff --git a/src/libc/newlib/src/stdlib/div.c b/src/libc/newlib/src/stdlib/div.c new file mode 100644 index 0000000..2a19cae --- /dev/null +++ b/src/libc/newlib/src/stdlib/div.c @@ -0,0 +1,121 @@ +/* +FUNCTION +<<div>>---divide two integers + +INDEX + div + +SYNOPSIS + #include <stdlib.h> + div_t div(int <[n]>, int <[d]>); + +DESCRIPTION +Divide +@tex +$n/d$, +@end tex +@ifnottex +<[n]>/<[d]>, +@end ifnottex +returning quotient and remainder as two integers in a structure <<div_t>>. + +RETURNS +The result is represented with the structure + +. typedef struct +. { +. int quot; +. int rem; +. } div_t; + +where the <<quot>> field represents the quotient, and <<rem>> the +remainder. For nonzero <[d]>, if `<<<[r]> = div(<[n]>,<[d]>);>>' then +<[n]> equals `<<<[r]>.rem + <[d]>*<[r]>.quot>>'. + +To divide <<long>> rather than <<int>> values, use the similar +function <<ldiv>>. + +PORTABILITY +<<div>> is ANSI. + +No supporting OS subroutines are required. +*/ + +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdlib.h> /* div_t */ + +div_t +div (int num, + int denom) +{ + div_t r; + + r.quot = num / denom; + r.rem = num % denom; + /* + * The ANSI standard says that |r.quot| <= |n/d|, where + * n/d is to be computed in infinite precision. In other + * words, we should always truncate the quotient towards + * 0, never -infinity or +infinity. + * + * Machine division and remainer may work either way when + * one or both of n or d is negative. If only one is + * negative and r.quot has been truncated towards -inf, + * r.rem will have the same sign as denom and the opposite + * sign of num; if both are negative and r.quot has been + * truncated towards -inf, r.rem will be positive (will + * have the opposite sign of num). These are considered + * `wrong'. + * + * If both are num and denom are positive, r will always + * be positive. + * + * This all boils down to: + * if num >= 0, but r.rem < 0, we got the wrong answer. + * In that case, to get the right answer, add 1 to r.quot and + * subtract denom from r.rem. + * if num < 0, but r.rem > 0, we also have the wrong answer. + * In this case, to get the right answer, subtract 1 from r.quot and + * add denom to r.rem. + */ + if (num >= 0 && r.rem < 0) { + ++r.quot; + r.rem -= denom; + } + else if (num < 0 && r.rem > 0) { + --r.quot; + r.rem += denom; + } + return (r); +} diff --git a/src/libc/newlib/src/time/CMakeLists.txt b/src/libc/newlib/src/time/CMakeLists.txt new file mode 100644 index 0000000..ea7167f --- /dev/null +++ b/src/libc/newlib/src/time/CMakeLists.txt @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + gettzinfo.c + month_lengths.c + mktime.c + tzvars.c + tzcalc_limits.c +) + +target_compile_definitions(c PRIVATE __SINGLE_THREAD__) diff --git a/src/libc/newlib/src/time/gettzinfo.c b/src/libc/newlib/src/time/gettzinfo.c new file mode 100644 index 0000000..c28e72f --- /dev/null +++ b/src/libc/newlib/src/time/gettzinfo.c @@ -0,0 +1,15 @@ +#include <sys/types.h> +#include "local.h" + +/* Shared timezone information for libc/time functions. */ +static __tzinfo_type tzinfo = {1, 0, + { {'J', 0, 0, 0, 0, (time_t)0, 0L }, + {'J', 0, 0, 0, 0, (time_t)0, 0L } + } +}; + +__tzinfo_type * +__gettzinfo (void) +{ + return &tzinfo; +} diff --git a/src/libc/newlib/src/time/local.h b/src/libc/newlib/src/time/local.h new file mode 100644 index 0000000..41940c0 --- /dev/null +++ b/src/libc/newlib/src/time/local.h @@ -0,0 +1,38 @@ +/* local header used by libc/time routines */ +#include <time.h> +#include <sys/_tz_structs.h> + +#define SECSPERMIN 60L +#define MINSPERHOUR 60L +#define HOURSPERDAY 24L +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY) +#define DAYSPERWEEK 7 +#define MONSPERYEAR 12 + +#define YEAR_BASE 1900 +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY 4 +#define EPOCH_YEARS_SINCE_LEAP 2 +#define EPOCH_YEARS_SINCE_CENTURY 70 +#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370 + +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +int __tzcalc_limits (int __year); + +extern const int __month_lengths[2][MONSPERYEAR]; + +void _tzset_unlocked (void); + +/* locks for multi-threading */ +#ifdef __SINGLE_THREAD__ +#define TZ_LOCK +#define TZ_UNLOCK +#else +#define TZ_LOCK __tz_lock() +#define TZ_UNLOCK __tz_unlock() +#endif + +void __tz_lock (void); +void __tz_unlock (void); diff --git a/src/libc/newlib/src/time/mktime.c b/src/libc/newlib/src/time/mktime.c new file mode 100644 index 0000000..4ca1493 --- /dev/null +++ b/src/libc/newlib/src/time/mktime.c @@ -0,0 +1,288 @@ +/* + * mktime.c + * Original Author: G. Haley + * + * Converts the broken-down time, expressed as local time, in the structure + * pointed to by tim_p into a calendar time value. The original values of the + * tm_wday and tm_yday fields of the structure are ignored, and the original + * values of the other fields have no restrictions. On successful completion + * the fields of the structure are set to represent the specified calendar + * time. Returns the specified calendar time. If the calendar time can not be + * represented, returns the value (time_t) -1. + * + * Modifications: Fixed tm_isdst usage - 27 August 2008 Craig Howland. + */ + +/* +FUNCTION +<<mktime>>---convert time to arithmetic representation + +INDEX + mktime + +SYNOPSIS + #include <time.h> + time_t mktime(struct tm *<[timp]>); + +DESCRIPTION +<<mktime>> assumes the time at <[timp]> is a local time, and converts +its representation from the traditional representation defined by +<<struct tm>> into a representation suitable for arithmetic. + +<<localtime>> is the inverse of <<mktime>>. + +RETURNS +If the contents of the structure at <[timp]> do not form a valid +calendar time representation, the result is <<-1>>. Otherwise, the +result is the time, converted to a <<time_t>> value. + +PORTABILITY +ANSI C requires <<mktime>>. + +<<mktime>> requires no supporting OS subroutines. +*/ + +#include "local.h" +#include <stdlib.h> +#include <sys/_tz_structs.h> +#include <time.h> + +#define TZ_LOCK +#define TZ_UNLOCK +#define _tzset_unlocked() +#define YEAR_BASE 1900 + +#define _SEC_IN_MINUTE 60L +#define _SEC_IN_HOUR 3600L +#define _SEC_IN_DAY 86400L + +static const int DAYS_IN_MONTH[12] = +{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x]) + +static const int _DAYS_BEFORE_MONTH[12] = +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + +#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0)) +#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365) + +static void +validate_structure (struct tm *tim_p) +{ + div_t res; + int days_in_feb = 28; + + /* calculate time & date to account for out of range values */ + if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59) + { + res = div (tim_p->tm_sec, 60); + tim_p->tm_min += res.quot; + if ((tim_p->tm_sec = res.rem) < 0) + { + tim_p->tm_sec += 60; + --tim_p->tm_min; + } + } + + if (tim_p->tm_min < 0 || tim_p->tm_min > 59) + { + res = div (tim_p->tm_min, 60); + tim_p->tm_hour += res.quot; + if ((tim_p->tm_min = res.rem) < 0) + { + tim_p->tm_min += 60; + --tim_p->tm_hour; + } + } + + if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23) + { + res = div (tim_p->tm_hour, 24); + tim_p->tm_mday += res.quot; + if ((tim_p->tm_hour = res.rem) < 0) + { + tim_p->tm_hour += 24; + --tim_p->tm_mday; + } + } + + if (tim_p->tm_mon < 0 || tim_p->tm_mon > 11) + { + res = div (tim_p->tm_mon, 12); + tim_p->tm_year += res.quot; + if ((tim_p->tm_mon = res.rem) < 0) + { + tim_p->tm_mon += 12; + --tim_p->tm_year; + } + } + + if (_DAYS_IN_YEAR (tim_p->tm_year) == 366) + days_in_feb = 29; + + if (tim_p->tm_mday <= 0) + { + while (tim_p->tm_mday <= 0) + { + if (--tim_p->tm_mon == -1) + { + tim_p->tm_year--; + tim_p->tm_mon = 11; + days_in_feb = + ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? + 29 : 28); + } + tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon); + } + } + else + { + while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon)) + { + tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon); + if (++tim_p->tm_mon == 12) + { + tim_p->tm_year++; + tim_p->tm_mon = 0; + days_in_feb = + ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? + 29 : 28); + } + } + } +} + +time_t +mktime (struct tm *tim_p) +{ + time_t tim = 0; + long days = 0; + int year, isdst=0; + __tzinfo_type *tz = __gettzinfo (); + + /* validate structure */ + validate_structure (tim_p); + + /* compute hours, minutes, seconds */ + tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) + + (tim_p->tm_hour * _SEC_IN_HOUR); + + /* compute days in year */ + days += tim_p->tm_mday - 1; + days += _DAYS_BEFORE_MONTH[tim_p->tm_mon]; + if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366) + days++; + + /* compute day of the year */ + tim_p->tm_yday = days; + + if (tim_p->tm_year > 10000 || tim_p->tm_year < -10000) + return (time_t) -1; + + /* compute days in other years */ + if ((year = tim_p->tm_year) > 70) + { + for (year = 70; year < tim_p->tm_year; year++) + days += _DAYS_IN_YEAR (year); + } + else if (year < 70) + { + for (year = 69; year > tim_p->tm_year; year--) + days -= _DAYS_IN_YEAR (year); + days -= _DAYS_IN_YEAR (year); + } + + /* compute total seconds */ + tim += (time_t)days * _SEC_IN_DAY; + + TZ_LOCK; + + _tzset_unlocked (); + + if (_daylight) + { + int tm_isdst; + int y = tim_p->tm_year + YEAR_BASE; + /* Convert user positive into 1 */ + tm_isdst = tim_p->tm_isdst > 0 ? 1 : tim_p->tm_isdst; + isdst = tm_isdst; + + if (y == tz->__tzyear || __tzcalc_limits (y)) + { + /* calculate start of dst in dst local time and + start of std in both std local time and dst local time */ + time_t startdst_dst = tz->__tzrule[0].change + - (time_t) tz->__tzrule[1].offset; + time_t startstd_dst = tz->__tzrule[1].change + - (time_t) tz->__tzrule[1].offset; + time_t startstd_std = tz->__tzrule[1].change + - (time_t) tz->__tzrule[0].offset; + /* if the time is in the overlap between dst and std local times */ + if (tim >= startstd_std && tim < startstd_dst) + ; /* we let user decide or leave as -1 */ + else + { + isdst = (tz->__tznorth + ? (tim >= startdst_dst && tim < startstd_std) + : (tim >= startdst_dst || tim < startstd_std)); + /* if user committed and was wrong, perform correction, but not + * if the user has given a negative value (which + * asks mktime() to determine if DST is in effect or not) */ + if (tm_isdst >= 0 && (isdst ^ tm_isdst) == 1) + { + /* we either subtract or add the difference between + time zone offsets, depending on which way the user got it + wrong. The diff is typically one hour, or 3600 seconds, + and should fit in a 16-bit int, even though offset + is a long to accomodate 12 hours. */ + int diff = (int) (tz->__tzrule[0].offset + - tz->__tzrule[1].offset); + if (!isdst) + diff = -diff; + tim_p->tm_sec += diff; + tim += diff; /* we also need to correct our current time calculation */ + int mday = tim_p->tm_mday; + validate_structure (tim_p); + mday = tim_p->tm_mday - mday; + /* roll over occurred */ + if (mday) { + /* compensate for month roll overs */ + if (mday > 1) + mday = -1; + else if (mday < -1) + mday = 1; + /* update days for wday calculation */ + days += mday; + /* handle yday */ + if ((tim_p->tm_yday += mday) < 0) { + --year; + tim_p->tm_yday = _DAYS_IN_YEAR(year) - 1; + } else { + mday = _DAYS_IN_YEAR(year); + if (tim_p->tm_yday > (mday - 1)) + tim_p->tm_yday -= mday; + } + } + } + } + } + } + + /* add appropriate offset to put time in gmt format */ + if (isdst == 1) + tim += (time_t) tz->__tzrule[1].offset; + else /* otherwise assume std time */ + tim += (time_t) tz->__tzrule[0].offset; + + TZ_UNLOCK; + + /* reset isdst flag to what we have calculated */ + tim_p->tm_isdst = isdst; + + /* compute day of the week */ + if ((tim_p->tm_wday = (days + 4) % 7) < 0) + tim_p->tm_wday += 7; + + return tim; +} diff --git a/src/libc/newlib/src/time/month_lengths.c b/src/libc/newlib/src/time/month_lengths.c new file mode 100644 index 0000000..03fac2f --- /dev/null +++ b/src/libc/newlib/src/time/month_lengths.c @@ -0,0 +1,14 @@ +/* + * month_lengths.c + * + * Array __month_lengths[] is (indirectly) needed by tzset(), mktime(), + * gmtime() and localtime(). To break any dependencies, this array is moved to + * separate source file. + */ + +#include "local.h" + +const int __month_lengths[2][MONSPERYEAR] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +} ; diff --git a/src/libc/newlib/src/time/tzcalc_limits.c b/src/libc/newlib/src/time/tzcalc_limits.c new file mode 100644 index 0000000..00044a5 --- /dev/null +++ b/src/libc/newlib/src/time/tzcalc_limits.c @@ -0,0 +1,76 @@ +/* + * tzcalc_limits.c + * Original Author: Adapted from tzcode maintained by Arthur David Olson. + * Modifications: + * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston + * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> + * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> + * - Moved __tzcalc_limits() to separate file - 05/09/14, Freddie Chopin <freddie_chopin@op.pl> + */ + +#include "local.h" + +int +__tzcalc_limits (int year) +{ + int days, year_days, years; + int i, j; + __tzinfo_type *const tz = __gettzinfo (); + + if (year < EPOCH_YEAR) + return 0; + + tz->__tzyear = year; + + years = (year - EPOCH_YEAR); + + year_days = years * 365 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - + (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; + + for (i = 0; i < 2; ++i) + { + if (tz->__tzrule[i].ch == 'J') + { + /* The Julian day n (1 <= n <= 365). */ + days = year_days + tz->__tzrule[i].d + + (isleap(year) && tz->__tzrule[i].d >= 60); + /* Convert to yday */ + --days; + } + else if (tz->__tzrule[i].ch == 'D') + days = year_days + tz->__tzrule[i].d; + else + { + const int yleap = isleap(year); + int m_day, m_wday, wday_diff; + const int *const ip = __month_lengths[yleap]; + + days = year_days; + + for (j = 1; j < tz->__tzrule[i].m; ++j) + days += ip[j-1]; + + m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; + + wday_diff = tz->__tzrule[i].d - m_wday; + if (wday_diff < 0) + wday_diff += DAYSPERWEEK; + m_day = (tz->__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; + + while (m_day >= ip[j-1]) + m_day -= DAYSPERWEEK; + + days += m_day; + } + + /* store the change-over time in GMT form by adding offset */ + tz->__tzrule[i].change = (time_t) days * SECSPERDAY + + tz->__tzrule[i].s + tz->__tzrule[i].offset; + } + + tz->__tznorth = (tz->__tzrule[0].change < tz->__tzrule[1].change); + + return 1; +} diff --git a/src/libc/newlib/src/time/tzvars.c b/src/libc/newlib/src/time/tzvars.c new file mode 100644 index 0000000..aabf3c4 --- /dev/null +++ b/src/libc/newlib/src/time/tzvars.c @@ -0,0 +1,9 @@ +#include <time.h> +#include <sys/_tz_structs.h> + +/* Global timezone variables. */ + +/* Default timezone to GMT */ +char *_tzname[2] = {"GMT", "GMT"}; +int _daylight = 0; +long _timezone = 0; diff --git a/src/libc/printf b/src/libc/printf -Subproject d3b984684bb8a8bdc48cc7a1abecb93ce59bbe3 +Subproject 9baeae718716c41bc9a347810b33071a3718dd3 diff --git a/src/libc/private_include/libc/file.h b/src/libc/private_include/libc/file.h index 3ba554c..dabeb89 100644 --- a/src/libc/private_include/libc/file.h +++ b/src/libc/private_include/libc/file.h @@ -1,15 +1,4 @@ #ifndef LIBC_FILE_H #define LIBC_FILE_H -enum -{ - STDIN_FILENO, - STDOUT_FILENO, - STDERR_FILENO -}; - -struct __file -{ -}; - #endif diff --git a/src/libc/private_include/libc/malloc.h b/src/libc/private_include/libc/malloc.h new file mode 100644 index 0000000..2afdd9b --- /dev/null +++ b/src/libc/private_include/libc/malloc.h @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LIBC_MALLOC_H +#define LIBC_MALLOC_H + +void __malloc_init(void); +extern int __malloc_ta_init; + +#endif diff --git a/src/libc/src/CMakeLists.txt b/src/libc/src/CMakeLists.txt new file mode 100644 index 0000000..11e7a3c --- /dev/null +++ b/src/libc/src/CMakeLists.txt @@ -0,0 +1,34 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + errno.c + ta_init.c +) + +add_subdirectory(ctype) +add_subdirectory(stdio) +add_subdirectory(stdlib) +add_subdirectory(string) + +if(NOT LIBC_FREESTANDING) + add_subdirectory(time) + add_subdirectory(unistd) +endif() + +if(PS1_BUILD) + add_subdirectory(ps1) +endif() diff --git a/src/libc/src/ctype/CMakeLists.txt b/src/libc/src/ctype/CMakeLists.txt new file mode 100644 index 0000000..8be1e2c --- /dev/null +++ b/src/libc/src/ctype/CMakeLists.txt @@ -0,0 +1,24 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + isalpha.c + islower.c + isspace.c + isupper.c + tolower.c + toupper.c +) diff --git a/src/libc/src/ctype/isalpha.c b/src/libc/src/ctype/isalpha.c new file mode 100644 index 0000000..bbc0256 --- /dev/null +++ b/src/libc/src/ctype/isalpha.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ctype.h> + +int isalpha(const int c) +{ + return islower(c) || isupper(c); +} diff --git a/src/libc/src/ctype/islower.c b/src/libc/src/ctype/islower.c new file mode 100644 index 0000000..f30f7e7 --- /dev/null +++ b/src/libc/src/ctype/islower.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ctype.h> + +int islower(const int c) +{ + return c >= 'a' && c <= 'z'; +} diff --git a/src/libc/src/ctype/isspace.c b/src/libc/src/ctype/isspace.c new file mode 100644 index 0000000..a38d360 --- /dev/null +++ b/src/libc/src/ctype/isspace.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ctype.h> + +int isspace(const int c) +{ + return c == ' ' || c == '\t'; +} diff --git a/src/libc/src/ctype/isupper.c b/src/libc/src/ctype/isupper.c new file mode 100644 index 0000000..01a5644 --- /dev/null +++ b/src/libc/src/ctype/isupper.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ctype.h> + +int isupper(const int c) +{ + return c >= 'A' && c <= 'Z'; +} diff --git a/src/libc/src/ctype/tolower.c b/src/libc/src/ctype/tolower.c new file mode 100644 index 0000000..26c08fd --- /dev/null +++ b/src/libc/src/ctype/tolower.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ctype.h> + +int tolower(const int c) +{ + if (isupper(c)) + return c - 'A' + 'a'; + + return c; +} diff --git a/src/libc/src/ctype/toupper.c b/src/libc/src/ctype/toupper.c new file mode 100644 index 0000000..e153a52 --- /dev/null +++ b/src/libc/src/ctype/toupper.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <ctype.h> + +int toupper(const int c) +{ + if (islower(c)) + return c - 'a' + 'A'; + + return c; +} diff --git a/src/libc/src/errno.c b/src/libc/src/errno.c index d013499..3d6fe8b 100644 --- a/src/libc/src/errno.c +++ b/src/libc/src/errno.c @@ -1,3 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + #include <errno.h> int errno; diff --git a/src/libc/src/memcmp.c b/src/libc/src/memcmp.c deleted file mode 100644 index f24d300..0000000 --- a/src/libc/src/memcmp.c +++ /dev/null @@ -1,12 +0,0 @@ -#include <string.h> - -int memcmp(const void *const s1, const void *const s2, const size_t n) -{ - const unsigned char *a = s1, *b = s2; - - for (size_t i = 0; i < n; i++, a++, b++) - if (*a != *b) - return *a - *b; - - return 0; -} diff --git a/src/libc/src/memcpy.c b/src/libc/src/memcpy.c deleted file mode 100644 index 7014e63..0000000 --- a/src/libc/src/memcpy.c +++ /dev/null @@ -1,13 +0,0 @@ -#include <string.h> -#include <stddef.h> - -void *memcpy(void *const dst, const void *const src, const size_t n) -{ - unsigned char *d = dst; - const unsigned char *s = src; - - for (size_t i = 0; i < n; i++) - *d++ = *s++; - - return dst; -} diff --git a/src/libc/src/memset.c b/src/libc/src/memset.c deleted file mode 100644 index 90eb611..0000000 --- a/src/libc/src/memset.c +++ /dev/null @@ -1,12 +0,0 @@ -#include <string.h> -#include <stddef.h> - -void *memset(void *const dst, const int c, const size_t n) -{ - unsigned char *d = dst; - - for (size_t i = 0; i < n; i++) - *d++ = c; - - return dst; -} diff --git a/src/libc/src/ps1/CMakeLists.txt b/src/libc/src/ps1/CMakeLists.txt new file mode 100644 index 0000000..54012df --- /dev/null +++ b/src/libc/src/ps1/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + putchar.c + setjmp.c +) + +target_link_libraries(c PRIVATE drv_ps1_bios) +target_compile_options(c PRIVATE -ffreestanding) diff --git a/src/libc/src/ps1/putchar.c b/src/libc/src/ps1/putchar.c new file mode 100644 index 0000000..81c98ec --- /dev/null +++ b/src/libc/src/ps1/putchar.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +int putchar(const int c) +{ + return EOF; +} + +void _putchar(const char c) +{ + putchar(c); +} diff --git a/src/libc/src/ps1/setjmp.c b/src/libc/src/ps1/setjmp.c new file mode 100644 index 0000000..40e488f --- /dev/null +++ b/src/libc/src/ps1/setjmp.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <setjmp.h> +#include <drv/ps1/bios.h> + +int setjmp(jmp_buf buf) +{ + return SaveState(buf); +} diff --git a/src/libc/src/stdio/CMakeLists.txt b/src/libc/src/stdio/CMakeLists.txt new file mode 100644 index 0000000..ca590a1 --- /dev/null +++ b/src/libc/src/stdio/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + puts.c +) diff --git a/src/libc/src/stdio/puts.c b/src/libc/src/stdio/puts.c new file mode 100644 index 0000000..262941a --- /dev/null +++ b/src/libc/src/stdio/puts.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +int puts(const char *s) +{ + for (; *s; s++) + if (putchar(*s) < 0) + return -1; + + return putchar('\n'); +} diff --git a/src/libc/src/stdlib/CMakeLists.txt b/src/libc/src/stdlib/CMakeLists.txt new file mode 100644 index 0000000..f75b364 --- /dev/null +++ b/src/libc/src/stdlib/CMakeLists.txt @@ -0,0 +1,30 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + abort.c + abs.c + calloc.c + free.c + malloc.c + labs.c + llabs.c + realloc.c + strtol.c + strtoll.c + strtoul.c + strtoull.c +) diff --git a/src/libc/src/stdlib/abort.c b/src/libc/src/stdlib/abort.c new file mode 100644 index 0000000..1fa6799 --- /dev/null +++ b/src/libc/src/stdlib/abort.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +void __abort(const char *const filename, const int lineno) +{ + for (;;) + ; +} diff --git a/src/libc/src/malloc.c b/src/libc/src/stdlib/abs.c index aa5ff31..785d060 100644 --- a/src/libc/src/malloc.c +++ b/src/libc/src/stdlib/abs.c @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -17,9 +17,8 @@ */ #include <stdlib.h> -#include <stddef.h> -void *malloc(const size_t __n) +int abs(const int v) { - return NULL; + return v < 0 ? -v : v; } diff --git a/src/libc/src/stdlib/calloc.c b/src/libc/src/stdlib/calloc.c new file mode 100644 index 0000000..c5e1dee --- /dev/null +++ b/src/libc/src/stdlib/calloc.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +void *calloc(const size_t nemb, const size_t size) +{ + const size_t n = nemb * size; + void *const ret = malloc(n); + + if (ret) + memset(ret, 0, n); + + return ret; +} diff --git a/src/libc/src/stdlib/free.c b/src/libc/src/stdlib/free.c new file mode 100644 index 0000000..1986c48 --- /dev/null +++ b/src/libc/src/stdlib/free.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <tinyalloc.h> +#include <libc/malloc.h> +#include <stdlib.h> + +void free(void *const ptr) +{ + if (!ptr) + return; + else if (!__malloc_ta_init || !ta_free(ptr)) + abort(); +} diff --git a/src/libc/src/stdlib/labs.c b/src/libc/src/stdlib/labs.c new file mode 100644 index 0000000..9759238 --- /dev/null +++ b/src/libc/src/stdlib/labs.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +long labs(const long v) +{ + return v < 0 ? -v : v; +} diff --git a/src/libc/src/stdlib/llabs.c b/src/libc/src/stdlib/llabs.c new file mode 100644 index 0000000..e737850 --- /dev/null +++ b/src/libc/src/stdlib/llabs.c @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +long long llabs(const long long v) +{ + return v < 0 ? -v : v; +} diff --git a/src/libc/src/stdlib/malloc.c b/src/libc/src/stdlib/malloc.c new file mode 100644 index 0000000..81bdeb5 --- /dev/null +++ b/src/libc/src/stdlib/malloc.c @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <libc/malloc.h> +#include <tinyalloc.h> +#include <errno.h> +#include <stdint.h> + +void *malloc(const size_t n) +{ + if (!__malloc_ta_init) + { + /* README.md states 16 is a "good default value". */ + if (!ta_init(1024, 16, sizeof (intmax_t))) + abort(); + + __malloc_ta_init = 1; + } + + void *const ret = ta_alloc(n); + + if (!ret) + errno = ENOMEM; + + return ret; +} diff --git a/src/libc/src/stdlib/realloc.c b/src/libc/src/stdlib/realloc.c new file mode 100644 index 0000000..dabfc05 --- /dev/null +++ b/src/libc/src/stdlib/realloc.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <tinyalloc.h> +#include <stdlib.h> + +void *realloc(void *const ptr, const size_t size) +{ + return ta_realloc(ptr, size); +} diff --git a/src/libc/src/stdlib/strtol.c b/src/libc/src/stdlib/strtol.c new file mode 100644 index 0000000..b8dbdd9 --- /dev/null +++ b/src/libc/src/stdlib/strtol.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <errno.h> +#include <limits.h> + +long strtol(const char *s, char **end, int base) +{ + long long v = strtoll(s, end, base); + + if (v > LONG_MAX || v < LONG_MIN) + errno = ERANGE; + + return v; +} diff --git a/src/libc/src/stdlib/strtoll.c b/src/libc/src/stdlib/strtoll.c new file mode 100644 index 0000000..69f77d1 --- /dev/null +++ b/src/libc/src/stdlib/strtoll.c @@ -0,0 +1,91 @@ +/* + * Original source code from PSXSDK, by Giuseppe Gata. + * Released under a weak copyleft-like license, pasted below: + * + * You can use this library for any project, commercial and non-commercial, + * open-source and closed-source. But if you modify the library, you must + * redistribute the source for the modifications you did to it. + * Not doing that constitutes an infringement of this license. + * You are not obliged to redistribute the source code of this library if it + * was not modified at all by you or anyone related to you. + * + * There is no advertising clause; you aren't obliged to mention this library + * in any documentation of your work using it; however, it would be a nice gesture + * if you did so. + * + * These terms were written to not make people close this work which was released + * for all to share. In fact, no use is otherwise restricted. + */ + +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> + +long long strtoll(const char *nptr, char **endptr, int base) +{ + int r = 0; + int t = 0; + int n = 0; + + while(*nptr && isspace(*nptr)) + nptr++; + + if(*nptr == '-') + { + nptr++; + n = 1; + } + + if(*nptr == '0') + { + if(*(nptr+1) == 'x' || *(nptr+1) == 'X') + { + if(base != 0 && base != 16) + { + errno = EINVAL; + return 0; + } + + base = 16; + nptr+=2; + } + else if(base != 0 && base != 8) + { + errno = EINVAL; + return 0; + } + else + base = 8; + } + else if (base == 0) + base = 10; + + if(base < 2 || base > 36) + { + errno = EINVAL; + return 0; + } + + while(*nptr) + { + if (*nptr >= '0' && *nptr <= '9') + t = *nptr - '0'; + else if (*nptr >= 'a' && *nptr <= 'z') + t = (*nptr - 'a') + 10; + else if (*nptr >= 'A' && *nptr <= 'Z') + t = (*nptr - 'A') + 10; + else + t = 1000; + + if(t>=base) + break; + + r*=base; + r+=t; + nptr++; + } + + if(endptr)*endptr = (char*)nptr; + return n?-r:r; +} diff --git a/src/libc/src/stdlib/strtoul.c b/src/libc/src/stdlib/strtoul.c new file mode 100644 index 0000000..f31c3dd --- /dev/null +++ b/src/libc/src/stdlib/strtoul.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <errno.h> +#include <limits.h> + +unsigned long strtoul(const char *s, char **end, int base) +{ + unsigned long long v = strtoull(s, end, base); + + if (v > ULONG_MAX) + errno = ERANGE; + + return v; +} diff --git a/src/libc/src/stdlib/strtoull.c b/src/libc/src/stdlib/strtoull.c new file mode 100644 index 0000000..e8d2bd8 --- /dev/null +++ b/src/libc/src/stdlib/strtoull.c @@ -0,0 +1,85 @@ +/* + * Original source code from PSXSDK, by Giuseppe Gata. + * Released under a weak copyleft-like license, pasted below: + * + * You can use this library for any project, commercial and non-commercial, + * open-source and closed-source. But if you modify the library, you must + * redistribute the source for the modifications you did to it. + * Not doing that constitutes an infringement of this license. + * You are not obliged to redistribute the source code of this library if it + * was not modified at all by you or anyone related to you. + * + * There is no advertising clause; you aren't obliged to mention this library + * in any documentation of your work using it; however, it would be a nice gesture + * if you did so. + * + * These terms were written to not make people close this work which was released + * for all to share. In fact, no use is otherwise restricted. + */ + +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> + +unsigned long long strtoull(const char *nptr, char **endptr, int base) +{ + int r = 0; + int t = 0; + int n = 0; + + while(*nptr && isspace(*nptr)) + nptr++; + + if(*nptr == '0') + { + if(*(nptr+1) == 'x' || *(nptr+1) == 'X') + { + if(base != 0 && base != 16) + { + errno = EINVAL; + return 0; + } + + base = 16; + nptr+=2; + } + else if(base != 0 && base != 8) + { + errno = EINVAL; + return 0; + } + else + base = 8; + } + else if (base == 0) + base = 10; + + if(base < 2 || base > 36) + { + errno = EINVAL; + return 0; + } + + while(*nptr) + { + if (*nptr >= '0' && *nptr <= '9') + t = *nptr - '0'; + else if (*nptr >= 'a' && *nptr <= 'z') + t = (*nptr - 'a') + 10; + else if (*nptr >= 'A' && *nptr <= 'Z') + t = (*nptr - 'A') + 10; + else + t = 1000; + + if(t>=base) + break; + + r*=base; + r+=t; + nptr++; + } + + if(endptr)*endptr = (char*)nptr; + return n?-r:r; +} diff --git a/src/libc/src/streams.c b/src/libc/src/streams.c deleted file mode 100644 index 95289e3..0000000 --- a/src/libc/src/streams.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <libc/file.h> -#include <stdio.h> - -static FILE f[3]; -FILE *stdin = &f[STDIN_FILENO], *stdout = &f[STDOUT_FILENO], - *stderr = &f[STDERR_FILENO]; diff --git a/src/libc/src/strerror.c b/src/libc/src/strerror.c deleted file mode 100644 index 6444e98..0000000 --- a/src/libc/src/strerror.c +++ /dev/null @@ -1,46 +0,0 @@ -#include <string.h> -#include <errno.h> - -char *strerror(const int errnum) -{ - static const char *const s[] = - { - [EPERM] = "Operation not permitted", - [ENOENT] = "No such file or directory", - [ESRCH] = "No such process", - [EINTR] = "Interrupted system call", - [EIO] = "Input/output error", - [ENXIO] = "No such device or address", - [E2BIG] = "Argument list too long", - [ENOEXEC] = "Exec format error", - [EBADF] = "Bad file descriptor", - [ECHILD] = "No child processes", - [EAGAIN] = "Resource temporarily unavailable", - [ENOMEM] = "Cannot allocate memory", - [EACCES] = "Permission denied", - [EFAULT] = "Bad address", - [ENOTBLK] = "Block device required", - [EBUSY] = "Device or resource busy", - [EEXIST] = "File exists", - [EXDEV] = "Invalid cross-device link", - [ENODEV] = "No such device", - [ENOTDIR] = "Not a directory", - [EISDIR] = "Is a directory", - [EINVAL] = "Invalid argument", - [ENFILE] = "Too many open files in system", - [EMFILE] = "Too many open files", - [ENOTTY] = "Inappropriate ioctl for device", - [ETXTBSY] = "Text file busy", - [EFBIG] = "File too large", - [ENOSPC] = "No space left on device", - [ESPIPE] = "Illegal seek", - [EROFS] = "Read-only file system", - [EMLINK] = "Too many links", - [EPIPE] = "Broken pipe", - }; - - if (errnum < 0 || errnum >= sizeof s / sizeof *s) - return "Unknown errno"; - - return (char *)s[errnum]; -} diff --git a/src/libc/src/string/CMakeLists.txt b/src/libc/src/string/CMakeLists.txt new file mode 100644 index 0000000..b0c565f --- /dev/null +++ b/src/libc/src/string/CMakeLists.txt @@ -0,0 +1,32 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + memcmp.c + memcpy.c + memset.c + strcasecmp.c + strchr.c + strcmp.c + strdup.c + strerror.c + strlen.c + strncmp.c + strndup.c + strpbrk.c + strrchr.c + strspn.c +) diff --git a/src/libc/src/string/memcmp.c b/src/libc/src/string/memcmp.c new file mode 100644 index 0000000..33a6a6d --- /dev/null +++ b/src/libc/src/string/memcmp.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> + +int memcmp(const void *const s1, const void *const s2, const size_t n) +{ + const unsigned char *a = s1, *b = s2; + + for (size_t i = 0; i < n; i++, a++, b++) + if (*a != *b) + return *a - *b; + + return 0; +} diff --git a/src/libc/src/string/memcpy.c b/src/libc/src/string/memcpy.c new file mode 100644 index 0000000..b82f9b5 --- /dev/null +++ b/src/libc/src/string/memcpy.c @@ -0,0 +1,57 @@ +/* + * Original source code from PSXSDK, by Xavier Del Campo Romero. + * Released under a weak copyleft-like license, pasted below: + * + * You can use this library for any project, commercial and non-commercial, + * open-source and closed-source. But if you modify the library, you must + * redistribute the source for the modifications you did to it. + * Not doing that constitutes an infringement of this license. + * You are not obliged to redistribute the source code of this library if it + * was not modified at all by you or anyone related to you. + * + * There is no advertising clause; you aren't obliged to mention this library + * in any documentation of your work using it; however, it would be a nice gesture + * if you did so. + * + * These terms were written to not make people close this work which was released + * for all to share. In fact, no use is otherwise restricted. + */ + +#include <string.h> +#include <stddef.h> + +void *memcpy(void *const dst, const void *const src, size_t n) +{ + union + { + const void *v; + const unsigned char *c; + const unsigned int *w; + } srcl; + + union + { + void *v; + unsigned char *c; + unsigned int *w; + } dstl; + + srcl.v = src; + dstl.v = dst; + + /* Avoid unaligned access before doing word access. */ + while (n && (((ptrdiff_t)dstl.v & (sizeof (int) - 1)) + || ((ptrdiff_t)srcl.v & (sizeof (int) - 1)))) + { + *dstl.c++ = *srcl.c++; + n--; + } + + for (; n >= sizeof (int); n -= sizeof (int)) + *dstl.w++ = *srcl.w++; + + while (n--) + *dstl.c++ = *srcl.c++; + + return dst; +} diff --git a/src/libc/src/string/memset.c b/src/libc/src/string/memset.c new file mode 100644 index 0000000..a68aa32 --- /dev/null +++ b/src/libc/src/string/memset.c @@ -0,0 +1,46 @@ +/* + * Original source code from PSXSDK, by Giuseppe Gata. + * Released under a weak copyleft-like license, pasted below: + * + * You can use this library for any project, commercial and non-commercial, + * open-source and closed-source. But if you modify the library, you must + * redistribute the source for the modifications you did to it. + * Not doing that constitutes an infringement of this license. + * You are not obliged to redistribute the source code of this library if it + * was not modified at all by you or anyone related to you. + * + * There is no advertising clause; you aren't obliged to mention this library + * in any documentation of your work using it; however, it would be a nice gesture + * if you did so. + * + * These terms were written to not make people close this work which was released + * for all to share. In fact, no use is otherwise restricted. + */ + +#include <string.h> +#include <stddef.h> + +void *memset(void *const dst, const int c, size_t n) +{ + union + { + void *v; + unsigned char *c; + unsigned *w; + } dstl = {.v = dst}; + + /* Avoid unaligned access before doing word access. */ + while (n && ((ptrdiff_t)dstl.v & (sizeof *dstl.w - 1))) + { + *dstl.c++ = c; + n--; + } + + for (; n >= sizeof *dstl.w; n -= sizeof *dstl.w) + *dstl.w++ = c; + + while (n--) + *dstl.c++ = c; + + return dst; +} diff --git a/src/libc/src/string/strcasecmp.c b/src/libc/src/string/strcasecmp.c new file mode 100644 index 0000000..fbc4463 --- /dev/null +++ b/src/libc/src/string/strcasecmp.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <ctype.h> + +int strcasecmp(const char *a, const char *b) +{ + while (*a && *b) + { + const unsigned char ac = *a, bc = *b; + + if (isalpha(ac) && isalpha(bc)) + if (toupper(ac) != toupper(bc)) + break; + + a++; + b++; + } + + return !!*a || !!*b; +} diff --git a/src/libc/src/strchr.c b/src/libc/src/string/strchr.c index 3a1fd0b..3a1fd0b 100644 --- a/src/libc/src/strchr.c +++ b/src/libc/src/string/strchr.c diff --git a/src/libc/src/string/strcmp.c b/src/libc/src/string/strcmp.c new file mode 100644 index 0000000..aa96e3c --- /dev/null +++ b/src/libc/src/string/strcmp.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> + +int strcmp(const char *a, const char *b) +{ + while (*a && *b && *a++ == *b++) + ; + + return !!*a || !!*b; +} diff --git a/src/libc/src/string/strcspn.c b/src/libc/src/string/strcspn.c new file mode 100644 index 0000000..7c87caf --- /dev/null +++ b/src/libc/src/string/strcspn.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stddef.h> + +size_t strcspn(const char *s, const char *const reject) +{ + size_t ret = 0; + + while (!strpbrk(s++, reject)) + ret++; + + return ret; +} diff --git a/src/libc/src/string/strdup.c b/src/libc/src/string/strdup.c new file mode 100644 index 0000000..226ef68 --- /dev/null +++ b/src/libc/src/string/strdup.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdlib.h> + +char *strdup(const char *const s) +{ + const size_t n = strlen(s) + 1; + char *const ret = malloc(n); + + if (!ret) + return NULL; + + memcpy(ret, s, n); + return ret; +} diff --git a/src/libc/src/string/strerror.c b/src/libc/src/string/strerror.c new file mode 100644 index 0000000..64f13de --- /dev/null +++ b/src/libc/src/string/strerror.c @@ -0,0 +1,181 @@ +/* Copyright (C) 1991-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <errno.h> + +char *strerror(const int errnum) +{ + static const char *const s[] = + { + [SUCCESS] = "Success", + [EPERM] = "Operation not permitted", + [ENOENT] = "No such file or directory", + [ESRCH] = "No such process", + [EINTR] = "Interrupted system call", + [EIO] = "Input/output error", + [ENXIO] = "No such device or address", + [E2BIG] = "Argument list too long", + [ENOEXEC] = "Exec format error", + [EBADF] = "Bad file descriptor", + [ECHILD] = "No child processes", + [EAGAIN] = "Resource temporarily unavailable", + [ENOMEM] = "Cannot allocate memory", + [EACCES] = "Permission denied", + [EFAULT] = "Bad address", + [ENOTBLK] = "Block device required", + [EBUSY] = "Device or resource busy", + [EEXIST] = "File exists", + [EXDEV] = "Invalid cross-device link", + [ENODEV] = "No such device", + [ENOTDIR] = "Not a directory", + [EISDIR] = "Is a directory", + [EINVAL] = "Invalid argument", + [ENFILE] = "Too many open files in system", + [EMFILE] = "Too many open files", + [ENOTTY] = "Inappropriate ioctl for device", + [ETXTBSY] = "Text file busy", + [EFBIG] = "File too large", + [ENOSPC] = "No space left on device", + [ESPIPE] = "Illegal seek", + [EROFS] = "Read-only file system", + [EMLINK] = "Too many links", + [EPIPE] = "Broken pipe", + [EDOM] = "Numerical argument out of domain", + [ERANGE] = "Numerical result out of range", + [EDEADLK] = "Resource deadlock avoided", + [ENAMETOOLONG] = "File name too long", + [ENOLCK] = "No locks available", + [ENOSYS] = "Function not implemented", + [ENOTEMPTY] = "Directory not empty", + [ELOOP] = "Too many levels of symbolic links", + [ENOMSG] = "No message of desired type", + [EIDRM] = "Identifier removed", + [ECHRNG] = "Channel number out of range", + [EL2NSYNC] = "Level 2 not synchronized", + [EL3HLT] = "Level 3 halted", + [EL3RST] = "Level 3 reset", + [ELNRNG] = "Link number out of range", + [EUNATCH] = "Protocol driver not attached", + [ENOCSI] = "No CSI structure available", + [EL2HLT] = "Level 2 halted", + [EBADE] = "Invalid exchange", + [EBADR] = "Invalid request descriptor", + [EXFULL] = "Exchange full", + [ENOANO] = "No anode", + [EBADRQC] = "Invalid request code", + [EBADSLT] = "Invalid slot", + [EBFONT] = "Bad font file format", + [ENOSTR] = "Device not a stream", + [ENODATA] = "No data available", + [ETIME] = "Timer expired", + [ENOSR] = "Out of streams resources", + [ENONET] = "Machine is not on the network", + [ENOPKG] = "Package not installed", + [EREMOTE] = "Object is remote", + [ENOLINK] = "Link has been severed", + [EADV] = "Advertise error", + [ESRMNT] = "Srmount error", + [ECOMM] = "Communication error on send", + [EPROTO] = "Protocol error", + [EMULTIHOP] = "Multihop attempted", + [EDOTDOT] = "RFS specific error", + [EBADMSG] = "Bad message", + [EOVERFLOW] = "Value too large for defined data type", + [ENOTUNIQ] = "Name not unique on network", + [EBADFD] = "File descriptor in bad state", + [EREMCHG] = "Remote address changed", + [ELIBACC] = "Can not access a needed shared library", + [ELIBBAD] = "Accessing a corrupted shared library", + [ELIBSCN] = ".lib section in a.out corrupted", + [ELIBMAX] = "Attempting to link in too many shared libraries", + [ELIBEXEC] = "Cannot exec a shared library directly", + [EILSEQ] = "Invalid or incomplete multibyte or wide character", + [ERESTART] = "Interrupted system call should be restarted", + [ESTRPIPE] = "Streams pipe error", + [EUSERS] = "Too many users", + [ENOTSOCK] = "Socket operation on non-socket", + [EDESTADDRREQ] = "Destination address required", + [EMSGSIZE] = "Message too long", + [EPROTOTYPE] = "Protocol wrong type for socket", + [ENOPROTOOPT] = "Protocol not available", + [EPROTONOSUPPORT] = "Protocol not supported", + [ESOCKTNOSUPPORT] = "Socket type not supported", + [ENOTSUP] = "Operation not supported", + [EPFNOSUPPORT] = "Protocol family not supported", + [EAFNOSUPPORT] = "Address family not supported by protocol", + [EADDRINUSE] = "Address already in use", + [EADDRNOTAVAIL] = "Cannot assign requested address", + [ENETDOWN] = "Network is down", + [ENETUNREACH] = "Network is unreachable", + [ENETRESET] = "Network dropped connection on reset", + [ECONNABORTED] = "Software caused connection abort", + [ECONNRESET] = "Connection reset by peer", + [ENOBUFS] = "No buffer space available", + [EISCONN] = "Transport endpoint is already connected", + [ENOTCONN] = "Transport endpoint is not connected", + [ESHUTDOWN] = "Cannot send after transport endpoint shutdown", + [ETOOMANYREFS] = "Too many references: cannot splice", + [ETIMEDOUT] = "Connection timed out", + [ECONNREFUSED] = "Connection refused", + [EHOSTDOWN] = "Host is down", + [EHOSTUNREACH] = "No route to host", + [EALREADY] = "Operation already in progress", + [EINPROGRESS] = "Operation now in progress", + [ESTALE] = "Stale file handle", + [EUCLEAN] = "Structure needs cleaning", + [ENOTNAM] = "Not a XENIX named type file", + [ENAVAIL] = "No XENIX semaphores available", + [EISNAM] = "Is a named type file", + [EREMOTEIO] = "Remote I/O error", + [EDQUOT] = "Disk quota exceeded", + [ENOMEDIUM] = "No medium found", + [EMEDIUMTYPE] = "Wrong medium type", + [ECANCELED] = "Operation canceled", + [ENOKEY] = "Required key not available", + [EKEYEXPIRED] = "Key has expired", + [EKEYREVOKED] = "Key has been revoked", + [EKEYREJECTED] = "Key was rejected by service", + [EOWNERDEAD] = "Owner died", + [ENOTRECOVERABLE] = "State not recoverable", + [ERFKILL] = "Operation not possible due to RF-kill", + [EHWPOISON] = "Memory page has hardware error", + }; + + if (errnum < 0 || errnum >= sizeof s / sizeof *s) + return "Unknown errno"; + + return (char *)s[errnum]; +} diff --git a/src/libc/src/string/strlen.c b/src/libc/src/string/strlen.c new file mode 100644 index 0000000..d2d1146 --- /dev/null +++ b/src/libc/src/string/strlen.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stddef.h> + +size_t strlen(const char *s) +{ + size_t ret = 0; + + while (*s++) + ret++; + + return ret; +} diff --git a/src/libc/src/string/strncmp.c b/src/libc/src/string/strncmp.c new file mode 100644 index 0000000..dc583e7 --- /dev/null +++ b/src/libc/src/string/strncmp.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stddef.h> + +int strncmp(const char *a, const char *b, const size_t n) +{ + for (size_t i = 0; i < n; i++) + if (!*a || !*b || *a++ != *b++) + return -1; + + return 0; +} diff --git a/src/libc/src/string/strndup.c b/src/libc/src/string/strndup.c new file mode 100644 index 0000000..3815c01 --- /dev/null +++ b/src/libc/src/string/strndup.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdlib.h> + +char *strndup(const char *const s, const size_t n) +{ + char *const ret = malloc(n + 1); + + if (!ret) + return NULL; + + memcpy(ret, s, n); + ret[n] = '\0'; + return ret; +} diff --git a/src/libc/src/string/strpbrk.c b/src/libc/src/string/strpbrk.c new file mode 100644 index 0000000..ac618fa --- /dev/null +++ b/src/libc/src/string/strpbrk.c @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> + +char *strpbrk(const char *const s, const char *accept) +{ + char c, *ret = NULL; + + while ((c = *accept++)) + { + char *p = strchr(s, c); + + if (!p) + continue; + else if (!ret || ret > p) + ret = p; + } + + return ret; +} diff --git a/src/libc/src/string/strrchr.c b/src/libc/src/string/strrchr.c new file mode 100644 index 0000000..1d7a8fa --- /dev/null +++ b/src/libc/src/string/strrchr.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stddef.h> + +char *strrchr(const char *s, const int c) +{ + const size_t len = strlen(s); + + for (size_t i = len; i <= len; i--) + if (s[i] == c) + return (char *)&s[i]; + + return NULL; +} diff --git a/src/libc/src/string/strspn.c b/src/libc/src/string/strspn.c new file mode 100644 index 0000000..25e6cef --- /dev/null +++ b/src/libc/src/string/strspn.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stddef.h> + +size_t strspn(const char *s, const char *const accept) +{ + size_t ret = 0; + + while (*s) + { + const char *const ss = strpbrk(s, accept); + + if (ss == s) + ret++; + else if (ret) + return ret; + + s++; + } + + return ret; +} diff --git a/src/libc/src/strlen.c b/src/libc/src/strlen.c deleted file mode 100644 index 43efcc5..0000000 --- a/src/libc/src/strlen.c +++ /dev/null @@ -1,12 +0,0 @@ -#include <string.h> -#include <stddef.h> - -size_t strlen(const char *s) -{ - size_t ret = 0; - - while (*s++) - ret++; - - return ret; -} diff --git a/src/libc/src/ta_init.c b/src/libc/src/ta_init.c new file mode 100644 index 0000000..118f62a --- /dev/null +++ b/src/libc/src/ta_init.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <libc/malloc.h> + +int __malloc_ta_init; diff --git a/src/libc/src/time/CMakeLists.txt b/src/libc/src/time/CMakeLists.txt new file mode 100644 index 0000000..907811d --- /dev/null +++ b/src/libc/src/time/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + clock_getres.c + clock_gettime.c + clock_settime.c +) diff --git a/src/libc/src/time/clock_getres.c b/src/libc/src/time/clock_getres.c new file mode 100644 index 0000000..84d0f39 --- /dev/null +++ b/src/libc/src/time/clock_getres.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <time.h> +#include <drv/time.h> + +int clock_getres(const clockid_t id, struct timespec *const ts) +{ + return drv_time_getres(id, ts); +} diff --git a/src/libc/src/time/clock_gettime.c b/src/libc/src/time/clock_gettime.c new file mode 100644 index 0000000..8d124a5 --- /dev/null +++ b/src/libc/src/time/clock_gettime.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <time.h> +#include <drv/time.h> + +int clock_gettime(const clockid_t id, struct timespec *const ts) +{ + return drv_time_gettime(id, ts); +} diff --git a/src/libc/src/time/clock_settime.c b/src/libc/src/time/clock_settime.c new file mode 100644 index 0000000..08dc7e1 --- /dev/null +++ b/src/libc/src/time/clock_settime.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <time.h> +#include <drv/time.h> + +int clock_settime(const clockid_t id, const struct timespec *const ts) +{ + return drv_time_settime(id, ts); +} diff --git a/src/libc/src/unistd/CMakeLists.txt b/src/libc/src/unistd/CMakeLists.txt new file mode 100644 index 0000000..a896727 --- /dev/null +++ b/src/libc/src/unistd/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(c PRIVATE + sbrk.c +) diff --git a/src/libc/src/unistd/sbrk.c b/src/libc/src/unistd/sbrk.c new file mode 100644 index 0000000..459d476 --- /dev/null +++ b/src/libc/src/unistd/sbrk.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <unistd.h> +#include <stddef.h> +#include <stdint.h> + +extern char __bss_end[], __ram_end[]; +static char *base = __bss_end; + +void *sbrk(const intptr_t increment) +{ + + + + if (base + increment >= __ram_end) + return NULL; + + void *p = base; + + base += increment; + return p; +} diff --git a/src/libc/tinyalloc b/src/libc/tinyalloc -Subproject 30457f9169c9f21c5ffee8b393cd977137ab446 +Subproject fd8128d9b84e362abdbd05fafe252421edee8ab diff --git a/src/loop/CMakeLists.txt b/src/loop/CMakeLists.txt new file mode 100644 index 0000000..5d1e3e2 --- /dev/null +++ b/src/loop/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(loop) +add_subdirectory(src) +target_include_directories(loop PUBLIC include PRIVATE private_include) +target_link_libraries(loop PUBLIC aio PRIVATE bin fs gfx init net) diff --git a/src/loop/include/loop.h b/src/loop/include/loop.h new file mode 100644 index 0000000..e6ccb29 --- /dev/null +++ b/src/loop/include/loop.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LOOP_H +#define LOOP_H + +#include <aio.h> + +int loop_run(void); +int loop_add_aio(struct aio *a); +int loop_rm_aio(struct aio *a); + +#endif diff --git a/src/loop/private_include/loop/types.h b/src/loop/private_include/loop/types.h new file mode 100644 index 0000000..fb345d0 --- /dev/null +++ b/src/loop/private_include/loop/types.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LOOP_TYPES_H +#define LOOP_TYPES_H + +#include <aio.h> + +extern struct aio_poll *loop_aio_head, *loop_aio_tail; + +#endif diff --git a/src/loop/src/CMakeLists.txt b/src/loop/src/CMakeLists.txt new file mode 100644 index 0000000..8fcedfa --- /dev/null +++ b/src/loop/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(loop PRIVATE + add_aio.c + globals.c + rm_aio.c + run.c +) diff --git a/src/loop/src/add_aio.c b/src/loop/src/add_aio.c new file mode 100644 index 0000000..a71d482 --- /dev/null +++ b/src/loop/src/add_aio.c @@ -0,0 +1,43 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <loop.h> +#include <loop/types.h> +#include <aio.h> +#include <stdlib.h> + +int loop_add_aio(struct aio *const a) +{ + struct aio_poll *const p = malloc(sizeof *p); + + if (!p) + return -1; + + *p = (const struct aio_poll){.aio = a}; + + if (!loop_aio_head) + loop_aio_head = p; + else if (loop_aio_tail) + { + loop_aio_tail->next = p; + p->prev = loop_aio_tail; + } + + loop_aio_tail = p; + return 0; +} diff --git a/src/loop/src/globals.c b/src/loop/src/globals.c new file mode 100644 index 0000000..429d936 --- /dev/null +++ b/src/loop/src/globals.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <loop/types.h> + +struct aio_poll *loop_aio_head, *loop_aio_tail; diff --git a/src/loop/src/rm_aio.c b/src/loop/src/rm_aio.c new file mode 100644 index 0000000..5d4f159 --- /dev/null +++ b/src/loop/src/rm_aio.c @@ -0,0 +1,48 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <loop.h> +#include <loop/types.h> +#include <aio.h> +#include <stdlib.h> + +int loop_rm_aio(struct aio *const aio) +{ + for (struct aio_poll *p = loop_aio_head; p; p = p->next) + if (p->aio == aio) + { + struct aio_poll *const prev = p->prev, *const next = p->next; + + if (!prev) + { + loop_aio_head = next; + + if (next) + next->prev = NULL; + } + else if ((prev->next = next)) + next->prev = prev; + else + loop_aio_tail = prev; + + free(p); + return 0; + } + + return -1; +} diff --git a/src/loop/src/run.c b/src/loop/src/run.c new file mode 100644 index 0000000..ea3ef26 --- /dev/null +++ b/src/loop/src/run.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <loop.h> +#include <loop/types.h> +#include <aio.h> +#include <bin.h> +#include <fs/fs.h> +#include <gfx/gfx.h> +#include <init.h> +#include <net.h> + +int loop_run(void) +{ + if (fs_update() + || aio_poll(loop_aio_head, 0) < 0 + || init_run() + || net_update() + || bin_update() + || gfx_update()) + return -1; + + return 0; +} @@ -1,5 +1,5 @@ /* - * wanix, a Unix-like operating system for WebAssembly + * wnix, a Unix-like operating system for WebAssembly applications. * Copyright (C) 2025 Xavier Del Campo Romero * * This program is free software: you can redistribute it and/or modify @@ -16,31 +16,19 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#include <aio.h> -#include <errno.h> -#include <stdio.h> +#include <init.h> +#include <gfx/gfx.h> +#include <loop.h> #include <stdlib.h> -#include <string.h> int main(void) { - int ret = EXIT_FAILURE; - struct aio *aio = aio_open("/media/cdrom/", "rb"); + if (init_port() || init_time() || gfx_init() || init_boot() || init_vfs()) + return EXIT_FAILURE; - if (!aio) - { - fprintf(stderr, "%s: aio_open failed: %s\n", __func__, strerror(errno)); - goto end; - } + for (;;) + if (loop_run()) + return EXIT_FAILURE; - ret = EXIT_SUCCESS; - -end: - if (aio && aio_close(aio)) - { - fprintf(stderr, "%s: aio_close failed: %s\n", __func__, strerror(errno)); - ret = EXIT_FAILURE; - } - - return ret; + return EXIT_SUCCESS; } diff --git a/src/nanowasm b/src/nanowasm -Subproject d65c912cb571f6e4946bfd7cbdfcdf4204d09b7 +Subproject 1e3a4e9ff4d9963aa77dc6135f351f90d927e9e diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt new file mode 100644 index 0000000..e0822e7 --- /dev/null +++ b/src/net/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(net) +add_subdirectory(src) +target_include_directories(net PUBLIC include PRIVATE private_include) +target_link_libraries(net PRIVATE aio loop state wip) diff --git a/src/net/include/net.h b/src/net/include/net.h new file mode 100644 index 0000000..0ae9dc1 --- /dev/null +++ b/src/net/include/net.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef NET_H +#define NET_H + +int net_init(const char *dev); +int net_update(void); +int net_shutdown(void); + +#endif diff --git a/src/net/private_include/net/ops.h b/src/net/private_include/net/ops.h new file mode 100644 index 0000000..abeea39 --- /dev/null +++ b/src/net/private_include/net/ops.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef NET_OPS_H +#define NET_OPS_H + +#include <stddef.h> + +void *net_alloc(size_t n, void *user); +void *net_realloc(void *, size_t n, void *user); +void net_free(void *p, void *user); +int net_read(void *buf, size_t n, void *user); +int net_write(const void *buf, size_t n, void *user); + +#endif diff --git a/src/net/private_include/net/types.h b/src/net/private_include/net/types.h new file mode 100644 index 0000000..eab5843 --- /dev/null +++ b/src/net/private_include/net/types.h @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef NET_TYPES_H +#define NET_TYPES_H + +#include <aio.h> +#include <fs/fs.h> +#include <wip/wip.h> +#include <stddef.h> +#include <stdbool.h> + +struct net +{ + bool init; + size_t available; + struct aio *aio; + struct wip w; + struct fs_fd fd; +}; + +extern struct net net; + +#endif diff --git a/src/net/src/CMakeLists.txt b/src/net/src/CMakeLists.txt new file mode 100644 index 0000000..c011446 --- /dev/null +++ b/src/net/src/CMakeLists.txt @@ -0,0 +1,24 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(net PRIVATE + init.c + net.c + shutdown.c + update.c +) + +add_subdirectory(ops) diff --git a/src/net/src/init.c b/src/net/src/init.c new file mode 100644 index 0000000..9e66981 --- /dev/null +++ b/src/net/src/init.c @@ -0,0 +1,78 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/ops.h> +#include <net/types.h> +#include <aio.h> +#include <loop.h> +#include <wip/wip.h> +#include <fcntl.h> +#include <stdbool.h> + +static int open_done(const enum state state, void *const args) +{ + struct net *const n = &net; + + if (loop_rm_aio(n->aio)) + return -1; + + aio_free(n->aio); + n->aio = NULL; + n->init = true; + return 0; +} + +int net_init(const char *const dev) +{ + struct net *const n = &net; + struct aio *aio = NULL; + const struct wip_cfg cfg = + { + .alloc = net_alloc, + .realloc = net_realloc, + .free = net_free, + .read = net_read, + .write = net_write, + .user = n + }; + + const struct fs_open op = + { + .path = dev, + .fd = &n->fd, + .flags = O_RDWR + }; + + const struct aio_done d = + { + .f = open_done, + .args = n + }; + + if (!(aio = aio_open(&op, &d)) || loop_add_aio(aio)) + goto failure; + + *n = (const struct net){.aio = aio}; + wip_init(&n->w, &cfg); + return 0; + +failure: + aio_free(aio); + return -1; +} diff --git a/src/net/src/net.c b/src/net/src/net.c new file mode 100644 index 0000000..b2dbd1a --- /dev/null +++ b/src/net/src/net.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/types.h> + +struct net net; diff --git a/src/net/src/ops/CMakeLists.txt b/src/net/src/ops/CMakeLists.txt new file mode 100644 index 0000000..40d4490 --- /dev/null +++ b/src/net/src/ops/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(net PRIVATE + alloc.c + free.c + read.c + realloc.c + write.c +) diff --git a/src/net/src/ops/alloc.c b/src/net/src/ops/alloc.c new file mode 100644 index 0000000..6152a92 --- /dev/null +++ b/src/net/src/ops/alloc.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/ops.h> +#include <net/types.h> +#include <wip/wip.h> +#include <stddef.h> +#include <stdlib.h> + +void *net_alloc(const size_t n, void *const user) +{ + return malloc(n); +} diff --git a/src/net/src/ops/free.c b/src/net/src/ops/free.c new file mode 100644 index 0000000..0f1f63b --- /dev/null +++ b/src/net/src/ops/free.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/ops.h> +#include <net/types.h> +#include <wip/wip.h> +#include <stddef.h> +#include <stdlib.h> + +void net_free(void *const p, void *const user) +{ + free(p); +} diff --git a/src/net/src/ops/read.c b/src/net/src/ops/read.c new file mode 100644 index 0000000..1fca206 --- /dev/null +++ b/src/net/src/ops/read.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/ops.h> +#include <net/types.h> +#include <aio.h> +#include <loop.h> +#include <wip/wip.h> +#include <stddef.h> + +int net_read(void *const buf, const size_t n, void *const user) +{ + struct net *const net = user; + const struct fs_read r = + { + .fd = &net->fd, + .buf = buf, + .n = n + }; + + return aio_read_nb(&r); +} diff --git a/src/net/src/ops/realloc.c b/src/net/src/ops/realloc.c new file mode 100644 index 0000000..329cbe5 --- /dev/null +++ b/src/net/src/ops/realloc.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/ops.h> +#include <net/types.h> +#include <wip/wip.h> +#include <stddef.h> +#include <stdlib.h> + +void *net_realloc(void *const p, const size_t n, void *const user) +{ + return realloc(p, n); +} diff --git a/src/net/src/ops/write.c b/src/net/src/ops/write.c new file mode 100644 index 0000000..2bf9093 --- /dev/null +++ b/src/net/src/ops/write.c @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/ops.h> +#include <net/types.h> +#include <wip/wip.h> +#include <stddef.h> + +int net_write(const void *const buf, const size_t n, void *const user) +{ + /* TODO */ + return -1; +} diff --git a/src/net/src/shutdown.c b/src/net/src/shutdown.c new file mode 100644 index 0000000..b815e2c --- /dev/null +++ b/src/net/src/shutdown.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/types.h> +#include <wip/wip.h> + +int net_shutdown(void) +{ + return -1; +} diff --git a/src/net/src/update.c b/src/net/src/update.c new file mode 100644 index 0000000..b7a0954 --- /dev/null +++ b/src/net/src/update.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <net.h> +#include <net/types.h> +#include <wip/wip.h> + +int net_update(void) +{ + struct net *const n = &net; + + if (!n->init) + return 0; + + return wip_run(&n->w) == WIP_FATAL ? -1 : 0; +} diff --git a/src/page/CMakeLists.txt b/src/page/CMakeLists.txt new file mode 100644 index 0000000..2aa2d4c --- /dev/null +++ b/src/page/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(page) +add_subdirectory(src) +target_include_directories(page PUBLIC include PRIVATE private_include) +target_link_libraries(page PRIVATE kprintf) diff --git a/src/page/include/page.h b/src/page/include/page.h new file mode 100644 index 0000000..d5af4be --- /dev/null +++ b/src/page/include/page.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PAGE_H +#define PAGE_H + +#include <stddef.h> + +struct page; + +int page_read(struct page **head, unsigned long addr, void *buf, size_t n); +int page_write(struct page **head, unsigned long addr, const void *buf, + size_t n); +int page_shrink(struct page **head, unsigned long addr); + +#endif diff --git a/src/page/private_include/page/mem.h b/src/page/private_include/page/mem.h new file mode 100644 index 0000000..abb2c6d --- /dev/null +++ b/src/page/private_include/page/mem.h @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PAGE_MEM_H +#define PAGE_MEM_H + +#include <page/types.h> +#include <stddef.h> + +struct page *page_mem_alloc(unsigned long addr); + +#endif diff --git a/src/page/private_include/page/mem/ops.h b/src/page/private_include/page/mem/ops.h new file mode 100644 index 0000000..5e50256 --- /dev/null +++ b/src/page/private_include/page/mem/ops.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PAGE_MEM_OPS_H +#define PAGE_MEM_OPS_H + +#include <page/types.h> + +int page_mem_read(struct page *p, void *buf, size_t n, unsigned long addr); +int page_mem_write(struct page *p, const void *buf, size_t n, unsigned long addr); +void page_mem_free(struct page *p); + +extern const struct page_ops page_mem_ops; + +#endif diff --git a/src/page/private_include/page/mem/types.h b/src/page/private_include/page/mem/types.h new file mode 100644 index 0000000..fe0fc74 --- /dev/null +++ b/src/page/private_include/page/mem/types.h @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PAGE_MEM_TYPES_H +#define PAGE_MEM_TYPES_H + +struct page_prv +{ + char buf[256]; +}; + +#endif diff --git a/src/page/private_include/page/routines.h b/src/page/private_include/page/routines.h new file mode 100644 index 0000000..359ca6b --- /dev/null +++ b/src/page/private_include/page/routines.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PAGE_ROUTINES_H +#define PAGE_ROUTINES_H + +#include <page.h> + +void page_free(struct page *p); +struct page *page_from_addr(struct page *head, unsigned long addr); +int page_add(struct page *p, unsigned long addr, + struct page *(*alloc)(unsigned long)); + +#endif diff --git a/src/page/private_include/page/types.h b/src/page/private_include/page/types.h new file mode 100644 index 0000000..ae1ff99 --- /dev/null +++ b/src/page/private_include/page/types.h @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef PAGE_TYPES_H +#define PAGE_TYPES_H + +#include <stddef.h> + +struct page; + +struct page_ops +{ + int (*read)(struct page *p, void *buf, size_t n, unsigned long addr); + int (*write)(struct page *p, const void *buf, size_t n, unsigned long addr); + void (*free)(struct page *p); +}; + +struct page +{ + const struct page_ops *ops; + unsigned long addr; + size_t sz; + struct page_prv *prv; + struct page *prev, *next; +}; + +#endif diff --git a/src/page/src/CMakeLists.txt b/src/page/src/CMakeLists.txt new file mode 100644 index 0000000..9f771b4 --- /dev/null +++ b/src/page/src/CMakeLists.txt @@ -0,0 +1,26 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(page PRIVATE + add.c + free.c + from_addr.c + read.c + shrink.c + write.c +) + +add_subdirectory(mem) diff --git a/src/page/src/add.c b/src/page/src/add.c new file mode 100644 index 0000000..5ac3c37 --- /dev/null +++ b/src/page/src/add.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/routines.h> +#include <page/types.h> + +int page_add(struct page *const p, const unsigned long addr, + struct page *(*const alloc)(unsigned long)) +{ + struct page *const np = alloc(addr); + + if (!np) + return -1; + + if (p->next) + { + p->next->prev = np; + np->next = p->next; + } + + p->next = np; + np->prev = p; + return 0; +} diff --git a/src/page/src/free.c b/src/page/src/free.c new file mode 100644 index 0000000..f9b72fb --- /dev/null +++ b/src/page/src/free.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/routines.h> +#include <page/types.h> +#include <stdlib.h> + +void page_free(struct page *const p) +{ + if (!p) + return; + else if (p->next) + p->next->prev = p->prev; + + if (p->prev) + p->prev->next = p->next; + + p->ops->free(p); + free(p); +} diff --git a/src/page/src/from_addr.c b/src/page/src/from_addr.c new file mode 100644 index 0000000..8727db6 --- /dev/null +++ b/src/page/src/from_addr.c @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/routines.h> +#include <page/types.h> +#include <stddef.h> + +struct page *page_from_addr(struct page *const head, const unsigned long addr) +{ + for (struct page *p = head; p; p = p->next) + if (addr >= p->addr && addr < p->addr + p->sz) + return p; + + return NULL; +} diff --git a/src/page/src/mem/CMakeLists.txt b/src/page/src/mem/CMakeLists.txt new file mode 100644 index 0000000..ea430c3 --- /dev/null +++ b/src/page/src/mem/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(page PRIVATE + alloc.c + free.c + ops.c + read.c + write.c +) diff --git a/src/page/src/mem/alloc.c b/src/page/src/mem/alloc.c new file mode 100644 index 0000000..be9f43d --- /dev/null +++ b/src/page/src/mem/alloc.c @@ -0,0 +1,50 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/mem.h> +#include <page/mem/ops.h> +#include <page/mem/types.h> +#include <page/types.h> +#include <stddef.h> +#include <stdlib.h> + +struct page *page_mem_alloc(const unsigned long addr) +{ + struct page *const ret = malloc(sizeof *ret); + struct page_prv *const prv = malloc(sizeof *prv); + const unsigned long start = addr - (addr % sizeof prv->buf); + + if (!ret || !prv) + goto failure; + + *prv = (const struct page_prv){0}; + *ret = (const struct page) + { + .sz = sizeof prv->buf, + .ops = &page_mem_ops, + .addr = start, + .prv = prv + }; + + return ret; + +failure: + free(prv); + free(ret); + return NULL; +} diff --git a/src/page/src/mem/free.c b/src/page/src/mem/free.c new file mode 100644 index 0000000..6834288 --- /dev/null +++ b/src/page/src/mem/free.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/types.h> +#include <page/mem/ops.h> +#include <page/mem/types.h> +#include <stddef.h> +#include <stdlib.h> + +void page_mem_free(struct page *const p) +{ + if (!p->prv) + return; + + free(p->prv); +} diff --git a/src/page/src/mem/ops.c b/src/page/src/mem/ops.c new file mode 100644 index 0000000..843b82a --- /dev/null +++ b/src/page/src/mem/ops.c @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/mem/ops.h> +#include <page/types.h> + +const struct page_ops page_mem_ops = +{ + .read = page_mem_read, + .write = page_mem_write, + .free = page_mem_free +}; diff --git a/src/page/src/mem/read.c b/src/page/src/mem/read.c new file mode 100644 index 0000000..67d5594 --- /dev/null +++ b/src/page/src/mem/read.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/types.h> +#include <page/mem/ops.h> +#include <page/mem/types.h> +#include <stddef.h> +#include <string.h> + +int page_mem_read(struct page *const p, void *const buf, const size_t n, + const unsigned long addr) +{ + const unsigned long offset = addr - p->addr; + const char *const src = &p->prv->buf[offset]; + const size_t rem = p->sz - offset, w = rem < n ? rem : n; + + memcpy(buf, src, w); + return w; +} diff --git a/src/page/src/mem/write.c b/src/page/src/mem/write.c new file mode 100644 index 0000000..7cf8f40 --- /dev/null +++ b/src/page/src/mem/write.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page/types.h> +#include <page/mem/ops.h> +#include <page/mem/types.h> +#include <stddef.h> +#include <string.h> + +int page_mem_write(struct page *const p, const void *const buf, const size_t n, + const unsigned long addr) +{ + const unsigned long offset = addr - p->addr; + char *const dst = &p->prv->buf[offset]; + const size_t rem = p->sz - offset, w = rem < n ? rem : n; + + memcpy(dst, buf, w); + return w; +} diff --git a/src/page/src/read.c b/src/page/src/read.c new file mode 100644 index 0000000..9c50711 --- /dev/null +++ b/src/page/src/read.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page.h> +#include <page/routines.h> +#include <page/types.h> +#include <page/mem.h> + +int page_read(struct page **const head, const unsigned long addr, + void *const buf, const size_t n) +{ + if (!*head) + return (*head = page_mem_alloc(addr)) ? 0 : -1; + + struct page *const p = page_from_addr(*head, addr); + + if (!p) + /* TODO: decide best strategy (fs, mem, etc.) */ + return page_add(*head, addr, page_mem_alloc); + + return p->ops->read(p, buf, n, addr); +} diff --git a/src/page/src/shrink.c b/src/page/src/shrink.c new file mode 100644 index 0000000..53873f6 --- /dev/null +++ b/src/page/src/shrink.c @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page.h> +#include <page/routines.h> +#include <page/types.h> + +int page_shrink(struct page **const head, const unsigned long addr) +{ + for (struct page *p = *head; p;) + { + struct page *const next = p->next; + + if (p->addr > addr) + page_free(p); + + p = next; + } + + return 0; +} diff --git a/src/page/src/write.c b/src/page/src/write.c new file mode 100644 index 0000000..a28ed2b --- /dev/null +++ b/src/page/src/write.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <page.h> +#include <page/mem.h> +#include <page/routines.h> +#include <page/types.h> +#include <stddef.h> + +int page_write(struct page **const head, const unsigned long addr, + const void *const buf, const size_t n) +{ + if (!*head) + return (*head = page_mem_alloc(addr)) ? 0 : -1; + + struct page *const p = page_from_addr(*head, addr); + + if (!p) + /* TODO: decide best strategy (fs, mem, etc.) */ + return page_add(*head, addr, page_mem_alloc); + + return p->ops->write(p, buf, n, addr); +} diff --git a/src/ps1/CMakeLists.txt b/src/ps1/CMakeLists.txt index 6ba4543..0aa710c 100644 --- a/src/ps1/CMakeLists.txt +++ b/src/ps1/CMakeLists.txt @@ -1,5 +1,37 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + target_link_libraries(${PROJECT_NAME} PRIVATE c) target_link_libraries(nanowasm PRIVATE c) +target_link_libraries(wip PRIVATE c) +target_link_libraries(dynstr PRIVATE c) target_sources(${PROJECT_NAME} PRIVATE start.c) target_link_options(${PROJECT_NAME} PRIVATE -T${CMAKE_CURRENT_LIST_DIR}/playstation.x) +add_custom_target(system_cnf ALL + ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_LIST_DIR}/system.cnf ${CMAKE_BINARY_DIR} +) +add_custom_target(mkpsxiso_xml ALL + ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_LIST_DIR}/wnix.xml ${CMAKE_BINARY_DIR} +) +add_custom_target(license ALL + ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_LIST_DIR}/infoeur.dat ${CMAKE_BINARY_DIR} +) +add_dependencies(mkpsxiso_xml system_cnf license ${PROJECT_NAME}) +add_dependencies(bin_cue mkpsxiso_xml) diff --git a/src/ps1/playstation.x b/src/ps1/playstation.x index 00a1a74..71a4c34 100644 --- a/src/ps1/playstation.x +++ b/src/ps1/playstation.x @@ -68,5 +68,7 @@ SECTIONS __bss_start = ADDR(.bss); __bss_end = ADDR(.bss) + SIZEOF(.bss); + __ram_end = 0x8020FFFF; + __scratchpad = 0x1f800000; } diff --git a/src/ps1/start.c b/src/ps1/start.c index 09ca6c9..c5558fe 100644 --- a/src/ps1/start.c +++ b/src/ps1/start.c @@ -1,7 +1,7 @@ __attribute__((__section__(".text.startup"))) void _start(void) { int main(void); - extern char *__bss_start, *__bss_end; + extern char __bss_start[], __bss_end[]; for (char *s = __bss_start; s < __bss_end; s++) *s = 0; diff --git a/src/ps1/system.cnf b/src/ps1/system.cnf index 1c3aebe..8c30bfa 100644 --- a/src/ps1/system.cnf +++ b/src/ps1/system.cnf @@ -1,4 +1,4 @@ -BOOT = cdrom:\wanix.exe;1 -TCB = 1 -EVENT = 8 -STACK = 801FF800 +BOOT = cdrom:\wnix.exe;1
+TCB = 1
+EVENT = 10
+STACK = 801FF800
diff --git a/src/ps1/wnix.xml b/src/ps1/wnix.xml new file mode 100644 index 0000000..b7a695e --- /dev/null +++ b/src/ps1/wnix.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<iso_project image_name="wnix.bin" cue_sheet="wnix.cue" no_xa="0"> + <track type="data"> + <identifiers + volume = "WNIX" + volume_set = "WNIX" + publisher = "WNIX" + /> + <license file="infoeur.dat"/> + <directory_tree> + <file name="system.cnf" source="system.cnf"/> + <file name="wnix.exe" source="wnix.exe"/> + <dir name="bin" source="bin"> + <file name="initd" source="bin/initd"/> + <file name="yes" source="bin/yes"/> + </dir> + <dummy sectors="13500" type="0"/> + </directory_tree> + </track> +</iso_project> diff --git a/src/state/CMakeLists.txt b/src/state/CMakeLists.txt new file mode 100644 index 0000000..ef2c6db --- /dev/null +++ b/src/state/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(state INTERFACE) +target_include_directories(state INTERFACE include) diff --git a/src/state/include/state.h b/src/state/include/state.h new file mode 100644 index 0000000..cd78dae --- /dev/null +++ b/src/state/include/state.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef STATE_H +#define STATE_H + +enum state +{ + STATE_OK, + STATE_AGAIN, + STATE_FATAL +}; + +#endif diff --git a/src/wip b/src/wip -Subproject f103800ac4d766c261a99a580c20a2447610152 +Subproject c11cb04929f28853142b14339b66f561ca028f3 diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index afb5355..682781f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,9 +1,38 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + cmake_minimum_required(VERSION 3.13) -project(utils) +project(tools) +set(MKPSXISO_NO_LIBFLAC ON) add_subdirectory(mkpsxiso) -add_executable(container "container.c") -add_executable(add-header "add-header.c") +add_subdirectory(nwc) +add_executable(container container.c) +add_executable(add-header add-header.c) +add_executable(elf2exe elf2exe.c) set(cflags -Wall -g3) target_compile_options(container PUBLIC ${cflags}) target_compile_options(add-header PUBLIC ${cflags}) -install(TARGETS container add-header DESTINATION bin) +target_compile_options(elf2exe PUBLIC ${cflags}) +target_compile_definitions(elf2exe + PRIVATE OBJCOPY_PATH=\"mipsel-unknown-elf-objcopy\") +install(TARGETS container add-header elf2exe nwc DESTINATION bin) + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_subdirectory(tun2tcp) +else() + message(STATUS "CMAKE_SYSTEM_NAME (${CMAKE_SYSTEM_NAME}) is not Linux, " + "skipping tun2tcp") +endif() diff --git a/tools/elf2exe.c b/tools/elf2exe.c new file mode 100755 index 0000000..8ce3702 --- /dev/null +++ b/tools/elf2exe.c @@ -0,0 +1,250 @@ +/*
+ * Original source code from PSXSDK, by Giuseppe Gata.
+ * Released under a weak copyleft-like license, pasted below:
+ *
+ * You can use this library for any project, commercial and non-commercial,
+ * open-source and closed-source. But if you modify the library, you must
+ * redistribute the source for the modifications you did to it.
+ * Not doing that constitutes an infringement of this license.
+ * You are not obliged to redistribute the source code of this library if it
+ * was not modified at all by you or anyone related to you.
+ *
+ * There is no advertising clause; you aren't obliged to mention this library
+ * in any documentation of your work using it; however, it would be a nice gesture
+ * if you did so.
+ *
+ * These terms were written to not make people close this work which was released
+ * for all to share. In fact, no use is otherwise restricted.
+ */
+
+/*
+ * elf2exe
+ *
+ * Converts an ELF executable to PS-EXE, using objcopy
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+const unsigned char psexe_magic[8] = {'P','S','-','X',' ','E','X','E'};
+const char *psexe_marker_usa = "Sony Computer Entertainment Inc. for North America area";
+const char *psexe_marker_jpn = "Sony Computer Entertainment Inc. for Japan area";
+const char *psexe_marker_eur = "Sony Computer Entertainment Inc. for Europe area";
+char *psexe_marker;
+
+//#define OBJCOPY_PATH "mipsel-unknown-elf-objcopy"
+
+int main(int argc, char *argv[])
+{
+ FILE *objcopy_out, *psexe;
+ char stringbuf[2048];
+ unsigned char charbuf;
+ int x;
+ unsigned int sz;
+ unsigned int gp = 0;
+
+ if(argc < 3)
+ {
+ printf("elf2exe - Converts an ELF executable to PS-EXE\n");
+ printf("usage: elf2exe [elf] [ps-x exe] <options>\n");
+ printf("\n");
+ printf("Options:\n");
+ printf("-mark_jpn - Use Japanese ascii marker (default: USA)\n");
+ printf("-mark_eur - Use European ascii marker (default: USA)\n");
+ printf("-mark=<mark> - Use custom ascii marker <mark>\n");
+ return -1;
+ }
+
+ psexe_marker = (char*)psexe_marker_usa;
+
+ for(x = 3; x < argc; x++)
+ {
+ if(strcmp(argv[x], "-mark_jpn") == 0)
+ psexe_marker = (char*)psexe_marker_jpn;
+
+ if(strcmp(argv[x], "-mark_eur") == 0)
+ psexe_marker = (char*)psexe_marker_eur;
+
+ if(strncmp(argv[x], "-mark=", 6) == 0)
+ {
+ if(strlen(argv[x]) >= 7)
+ psexe_marker = argv[x] + 6;
+ }
+
+ if(strncmp(argv[x], "-gp=", 4) == 0)
+ {
+ if(strlen(argv[x]) >= 5)
+ sscanf(argv[x] + 4, "%x", &gp);
+ }
+ }
+
+/*
+ * Now open the output file
+ */
+
+ psexe = fopen(argv[2], "wb");
+
+ if(psexe == NULL)
+ {
+ printf("Couldn't open %s for writing. Aborting!\n", argv[2]);
+ return -1;
+ }
+
+/*
+ * Write PSEXE magic string
+ */
+ fwrite(psexe_magic, sizeof(char), 8, psexe);
+
+/*
+ * Seek output file to 0x10, Initial Program Counter
+ */
+ fseek(psexe, 0x10, SEEK_SET);
+
+/*
+ * Write initial program counter = 0x80010000
+ */
+ charbuf = 0x00;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x01;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x80;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+
+/*
+ * Global Pointer
+ */
+ charbuf = gp & 0xff;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = (gp & 0xff00) >> 8;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = (gp & 0xff0000) >> 16;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = (gp & 0xff000000) >> 24;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+
+/*
+ * Seek output file to 0x18, Text section start address
+ */
+ fseek(psexe, 0x18, SEEK_SET);
+
+/*
+ * Write text section start address = 0
+ */
+ charbuf = 0x00;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x00;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x01;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x80;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+
+/*
+ * Seek output file to 0x30, Initial Stack Pointer
+ */
+ fseek(psexe, 0x30, SEEK_SET);
+
+/*
+ * Write Initial Stack Pointer = 0x801FFFF0
+ */
+ charbuf = 0xF0;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0xFF;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x1F;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = 0x80;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+
+
+/*
+ * Seek output to 0x4C, ASCII marker
+ */
+ fseek(psexe, 0x4C, SEEK_SET);
+
+ x = 0;
+
+/*
+ * Write ASCII marker string
+ */
+ while(psexe_marker[x])
+ fwrite(&psexe_marker[x++], sizeof(char), 1, psexe);
+
+/*
+ * Run objcopy now
+ */
+ sprintf(stringbuf, OBJCOPY_PATH" -O binary %s %s.bin", argv[1], argv[1]);
+ system(stringbuf);
+
+ sprintf(stringbuf, "%s.bin", argv[1]);
+
+/*
+ * Open objcopy output
+ */
+
+ objcopy_out = fopen(stringbuf, "rb");
+ if(objcopy_out == NULL)
+ {
+ printf("Could not open objcopy output at %s. Check your permissions. Aborting.\n",
+ stringbuf);
+ return -1;
+ }
+
+/*
+ * Seek to 0x800, Program Start
+ * and write the output of objcopy into the PS-X EXE
+ */
+ fseek(psexe, 0x800, SEEK_SET);
+
+ while(!feof(objcopy_out))
+ {
+ x = fgetc(objcopy_out);
+ fputc(x, psexe);
+ }
+
+
+ fclose(objcopy_out);
+
+/*
+ * Get the file size of the PS-X EXE
+ */
+ fseek(psexe, 0, SEEK_END);
+ sz = ftell(psexe);
+ fseek(psexe, 0, SEEK_SET);
+
+ if(sz % 2048 != 0)
+ {
+ fseek(psexe, (((sz / 2048) + 1)*2048) - 1, SEEK_SET);
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ sz = ftell(psexe);
+ }
+
+/*
+ * Write the address of the text section in the header of the PS-X EXE
+ */
+
+ sz -= 0x800;
+
+ fseek(psexe, 0x1C, SEEK_SET);
+
+ charbuf = sz & 0xff;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = (sz & 0xff00) >> 8;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = (sz & 0xff0000) >> 16;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+ charbuf = (sz & 0xff000000) >> 24;
+ fwrite(&charbuf, sizeof(char), 1, psexe);
+
+ fclose(psexe);
+
+/*
+ * Remove objcopy output
+ */
+ sprintf(stringbuf, "%s.bin", argv[1]);
+ remove(stringbuf);
+
+ return 0;
+}
diff --git a/tools/nwc b/tools/nwc -Subproject 1a9ca72b3b88054403995ce71887d09052f4ef4 +Subproject 15d2bb51e092d6dc34fa5fb5c1eb9b64c7c597b diff --git a/tools/tun2tcp/CMakeLists.txt b/tools/tun2tcp/CMakeLists.txt new file mode 100644 index 0000000..674aef6 --- /dev/null +++ b/tools/tun2tcp/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +cmake_minimum_required(VERSION 3.13) +project(tun2tcp C) +add_executable(${PROJECT_NAME} tun2tcp.c) +target_compile_options(${PROJECT_NAME} PUBLIC ${cflags}) +install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/tools/tun2tcp/README.md b/tools/tun2tcp/README.md new file mode 100644 index 0000000..9fcc641 --- /dev/null +++ b/tools/tun2tcp/README.md @@ -0,0 +1,13 @@ +# tun2serial + +```sh +# setcap cap_net_admin+ep ./tun2serial +# sudo ip addr add 10.0.0.1/24 dev tun0 +# sudo ip link set tun0 up +# socat TCP-L:6699 /dev/ttyUSB0,rawer,b1200 +``` + +## Thanks + +- https://backreference.org/2010/03/26/tuntap-interface-tutorial/index.html +- https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/ diff --git a/tools/tun2tcp/tun2tcp.c b/tools/tun2tcp/tun2tcp.c new file mode 100644 index 0000000..4b6615f --- /dev/null +++ b/tools/tun2tcp/tun2tcp.c @@ -0,0 +1,160 @@ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netinet/ip.h> +#include <net/if.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <fcntl.h> +#include <termios.h> +#include <unistd.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +static int getport(const char *const s, unsigned short *const port) +{ + char *end; + unsigned long v; + + errno = 0; + v = strtoull(s, &end, 10); + + if (errno || *end || v > USHRT_MAX) + return -1; + + *port = v; + return 0; +} + +int main(int argc, char *argv[]) +{ + static const char path[] = "/dev/net/tun"; + char *s = NULL; + int ret = EXIT_FAILURE, cfd = -1, tfd = -1; + unsigned short port; + + if (argc != 2) + { + fprintf(stderr, "%s <port>\n", *argv); + goto end; + } + else if (getport(argv[1], &port)) + { + fprintf(stderr, "invalid port: %s\n", argv[1]); + goto end; + } + else if ((cfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("socket(2)"); + goto end; + } + + const struct sockaddr_in addr = + { + .sin_family = AF_INET, + .sin_addr.s_addr = inet_addr("127.0.0.1"), + .sin_port = htons(port) + }; + + const struct ifreq ifr = {.ifr_flags = IFF_TUN | IFF_NO_PI}; + + if (connect(cfd, (const struct sockaddr *)&addr, sizeof addr)) + { + perror("connect(2)"); + goto end; + } + else if ((tfd = open(path, O_RDWR)) < 0) + { + fprintf(stderr, "open(2) %s: %s\n", path, strerror(errno)); + goto end; + } + else if (ioctl(tfd, TUNSETIFF, &ifr) < 0) + { + perror("ioctl(2)"); + goto end; + } + else if (!(s = strdup(ifr.ifr_name))) + { + perror("strdup(3)"); + goto end; + } + + fprintf(stderr, "set up TUN device %s\n", s); + unsigned long long total = 0; + + for (;;) + { + char b[1500]; + ssize_t n = read(tfd, &b, sizeof b); + + if (n < 0) + { + perror("read(2)"); + goto end; + } + + fprintf(stderr, "read %zu bytes\n", n); + + size_t rem = n; + + while (rem) + { + const void *p = b; + + fprintf(stderr, "sending %zu bytes\n", rem); + + if ((n = write(cfd, p, rem)) < 0) + { + perror("write(2)"); + goto end; + } + + fprintf(stderr, "sent %zu bytes, total: %llu\n", n, total += n); + + p = (const char *)p + n; + rem -= n; + } + } + + ret = EXIT_SUCCESS; + +end: + + if (cfd >= 0 && close(cfd)) + { + ret = EXIT_FAILURE; + perror("close(2)"); + } + + if (tfd >= 0 && close(tfd)) + { + ret = EXIT_FAILURE; + fprintf(stderr, "close(2) %s: %s\n", path, strerror(errno)); + } + + free(s); + return ret; +} |
