├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── RELEASE-1.0.md ├── blockdev ├── CMakeLists.txt ├── blockdev.cpp ├── blockdev.hpp ├── blockdev_store.cpp ├── blockdev_store.hpp ├── partition.cpp └── partition.hpp ├── boot.s ├── cmake ├── Toolchain-cloudabi-common.cmake ├── Toolchain-i686-cloudabi.cmake ├── Toolchain-i686-elf.cmake ├── aprotoc.cmake └── arch.cmake ├── concur ├── CMakeLists.txt ├── condition.cpp ├── condition.hpp ├── cv.cpp └── cv.hpp ├── contrib ├── compiler-rt │ ├── CMakeLists.txt │ ├── LICENSE.TXT │ ├── assembly.h │ └── i386 │ │ ├── udivdi3.S │ │ └── umoddi3.S └── libcxxabi │ ├── CMakeLists.txt │ ├── CREDITS.TXT │ ├── LICENSE.TXT │ ├── __cxxabi_config.h │ ├── cxxabi.h │ ├── private_typeinfo.cpp │ ├── private_typeinfo.h │ ├── stdlib_exception.cpp │ └── stdlib_typeinfo.cpp ├── fd ├── CMakeLists.txt ├── blockdevstoresock.cpp ├── blockdevstoresock.hpp ├── bootfs.cpp ├── bootfs.hpp ├── fd.hpp ├── ifstoresock.cpp ├── ifstoresock.hpp ├── initrdfs.cpp ├── initrdfs.hpp ├── mem_mapping.cpp ├── mem_mapping.hpp ├── memory_fd.cpp ├── memory_fd.hpp ├── process_fd.cpp ├── process_fd.hpp ├── procfs.cpp ├── procfs.hpp ├── pseudo_fd.cpp ├── pseudo_fd.hpp ├── rawsock.cpp ├── rawsock.hpp ├── reverse_fd.cpp ├── reverse_fd.hpp ├── reverse_proto.hpp ├── scheduler.cpp ├── scheduler.hpp ├── scheduler.s ├── shmfs.cpp ├── shmfs.hpp ├── sock.cpp ├── sock.hpp ├── thread.cpp ├── thread.hpp ├── unixsock.cpp ├── unixsock.hpp ├── userlandsock.cpp ├── userlandsock.hpp ├── vfs.cpp ├── vfs.hpp └── vga_fd.hpp ├── global.hpp ├── hw ├── CMakeLists.txt ├── arch │ └── x86 │ │ ├── x86.cpp │ │ ├── x86.hpp │ │ ├── x86_ata.cpp │ │ ├── x86_ata.hpp │ │ ├── x86_fpu.cpp │ │ ├── x86_fpu.hpp │ │ ├── x86_kbd.cpp │ │ ├── x86_kbd.hpp │ │ ├── x86_pit.cpp │ │ ├── x86_pit.hpp │ │ ├── x86_rtc.cpp │ │ ├── x86_rtc.hpp │ │ ├── x86_serial.cpp │ │ └── x86_serial.hpp ├── cpu_io.hpp ├── device.cpp ├── device.hpp ├── driver.hpp ├── driver_store.cpp ├── driver_store.hpp ├── interrupt.S ├── interrupt.cpp ├── interrupt.hpp ├── interrupt_table.cpp ├── interrupt_table.hpp ├── multiboot.cpp ├── multiboot.hpp ├── net │ ├── ethernet_device.cpp │ ├── ethernet_device.hpp │ ├── intel_i217.cpp │ ├── intel_i217.hpp │ ├── intel_i217_flags.hpp │ ├── virtio.cpp │ └── virtio.hpp ├── pci_bus.cpp ├── pci_bus.hpp ├── root_device.cpp ├── root_device.hpp ├── segments.cpp ├── segments.hpp ├── segments.s ├── sse.cpp ├── sse.hpp ├── test │ ├── interrupt_stub.c │ ├── segments_stub.c │ ├── test_main.cpp │ ├── test_multiboot.cpp │ ├── test_segments.cpp │ ├── test_vga.cpp │ └── test_vga_stream.cpp ├── vga.cpp ├── vga.hpp ├── vga_stream.cpp └── vga_stream.hpp ├── kernel_main.cpp ├── linker.ld ├── memory ├── CMakeLists.txt ├── allocation.cpp ├── allocation.hpp ├── allocation_tracker.cpp ├── allocation_tracker.hpp ├── allocator.cpp ├── allocator.hpp ├── bucketizer.hpp ├── mallocator.hpp ├── map_virtual.cpp ├── map_virtual.hpp ├── page_allocator.cpp ├── page_allocator.hpp ├── segregator.hpp ├── smart_ptr.hpp └── test │ └── test_main.cpp ├── misc ├── CMakeLists.txt ├── bochs │ ├── CMakeLists.txt │ └── bochsrc.txt ├── disk │ └── make_rootdisk.sh ├── initrd │ ├── CMakeLists.txt │ └── produce_initrd.sh ├── iso │ ├── CMakeLists.txt │ ├── menu.lst │ ├── produce_iso.sh │ └── stage2_eltorito └── python │ └── cosix.py ├── net ├── CMakeLists.txt ├── ethernet_interface.cpp ├── ethernet_interface.hpp ├── interface.cpp ├── interface.hpp ├── interface_store.cpp ├── interface_store.hpp ├── loopback_interface.hpp └── test │ └── test_main.cpp ├── oslibc ├── CMakeLists.txt ├── assert.cpp ├── assert.hpp ├── bitmap.cpp ├── bitmap.hpp ├── checksum.h ├── crc32.c ├── ctype.cpp ├── ctype.h ├── cxx_support.cpp ├── error.h ├── in.h ├── iovec.cpp ├── iovec.hpp ├── list.hpp ├── numeric.c ├── numeric.h ├── string.c ├── string.h ├── test │ ├── test_iovec.cpp │ ├── test_list.cpp │ ├── test_main.cpp │ ├── test_numeric.cpp │ ├── test_string.cpp │ └── test_uuid.cpp ├── utility.hpp └── uuid.hpp ├── proc ├── CMakeLists.txt ├── process_store.cpp ├── process_store.hpp ├── syscall │ ├── clock_syscalls.cpp │ ├── concur_syscalls.cpp │ ├── fd_syscalls.cpp │ ├── file_syscalls.cpp │ ├── mem_syscalls.cpp │ ├── poll_syscalls.cpp │ ├── proc_syscalls.cpp │ ├── random_syscalls.cpp │ ├── sock_syscalls.cpp │ └── thread_syscalls.cpp ├── syscall_context.hpp └── syscalls.hpp ├── rng ├── CMakeLists.txt ├── rng.cpp └── rng.hpp ├── term ├── CMakeLists.txt ├── console_terminal.cpp ├── console_terminal.hpp ├── escape_codes.cpp ├── escape_codes.hpp ├── terminal.cpp ├── terminal.hpp ├── terminal_fd.cpp ├── terminal_fd.hpp ├── terminal_store.cpp ├── terminal_store.hpp └── test │ ├── test_escape_codes.cpp │ └── test_main.cpp ├── time ├── CMakeLists.txt ├── clock_store.cpp └── clock_store.hpp └── userland ├── CMakeLists.txt ├── concur_test ├── CMakeLists.txt └── concur_test.cpp ├── dhclient ├── CMakeLists.txt └── dhclient.cpp ├── external_binaries.h.in ├── extfs ├── CMakeLists.txt ├── extfs.cpp ├── extfs.hpp └── main.cpp ├── flower_test ├── CMakeLists.txt ├── configuration.proto └── flower_test.cpp ├── httpd ├── CMakeLists.txt └── httpd.cpp ├── init ├── CMakeLists.txt └── init.cpp ├── ircclient ├── CMakeLists.txt ├── main.cpp ├── session.cpp ├── session.hpp ├── sessionview.cpp ├── sessionview.hpp ├── terminal.cpp └── terminal.hpp ├── libcosix ├── CMakeLists.txt ├── cosix │ ├── networkd.hpp │ └── util.hpp ├── networkd.cpp └── util.cpp ├── libpseudofd ├── CMakeLists.txt ├── cosix │ └── reverse.hpp ├── reverse.cpp └── reversefd.cpp ├── mmap_test ├── CMakeLists.txt └── mmap_test.cpp ├── networkd ├── CMakeLists.txt ├── arp.cpp ├── arp.hpp ├── client.cpp ├── client.hpp ├── interface.cpp ├── interface.hpp ├── ip.cpp ├── ip.hpp ├── ip_socket.cpp ├── ip_socket.hpp ├── networkd.cpp ├── networkd.hpp ├── routing_table.cpp ├── routing_table.hpp ├── tcp.cpp ├── tcp.hpp ├── tcp_socket.cpp ├── tcp_socket.hpp ├── udp.cpp ├── udp.hpp ├── udp_socket.cpp ├── udp_socket.hpp └── util.hpp ├── partition ├── CMakeLists.txt └── main.cpp ├── pipe_test ├── CMakeLists.txt └── pipe_test.cpp ├── pseudo_test ├── CMakeLists.txt └── pseudo_test.cpp ├── pythonshell ├── CMakeLists.txt └── pythonshell.cpp ├── tcptest ├── CMakeLists.txt └── tcptest.cpp ├── telnetd ├── CMakeLists.txt ├── telnetd.cpp ├── tterm.cpp └── tterm.hpp ├── time_test ├── CMakeLists.txt └── time_test.cpp ├── tmpfs ├── CMakeLists.txt ├── main.cpp ├── tmpfs.cpp └── tmpfs.hpp ├── tmptest ├── CMakeLists.txt └── tmptest.cpp ├── udptest ├── CMakeLists.txt └── udptest.cpp ├── unixsock_test ├── CMakeLists.txt └── unixsock_test.cpp ├── vdso.ld ├── vdso_support.h └── vdso_support.s.in /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "wubwubcmake"] 2 | path = wubwubcmake 3 | url = https://github.com/NickNick/wubwubcmake.git 4 | [submodule "catch"] 5 | path = contrib/catch 6 | url = https://github.com/philsquared/Catch.git 7 | [submodule "cloudabi"] 8 | path = cloudabi 9 | url = https://github.com/NuxiNL/cloudabi.git 10 | [submodule "cloudlibc"] 11 | path = cloudlibc 12 | url = https://github.com/NuxiNL/cloudlibc.git 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless otherwise specified (in a source file, source directory or in this 2 | file), all code in this repository is covered under the license below. As a 3 | contributor, you agree to allow your contribution to be used under this 4 | license. 5 | 6 | Copyright (c) 2015-2017 Sjors Gielen, Cosix developers and contributors. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /blockdev/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BAREMETAL_ENABLED) 2 | add_library(blockdev 3 | blockdev_store.hpp blockdev_store.cpp 4 | blockdev.hpp blockdev.cpp 5 | partition.hpp partition.cpp 6 | ) 7 | endif() 8 | -------------------------------------------------------------------------------- /blockdev/blockdev.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace cloudos; 7 | 8 | blockdev::blockdev() 9 | : fd_t(CLOUDABI_FILETYPE_BLOCK_DEVICE, 0, "unnamed blockdev") 10 | { 11 | } 12 | 13 | blockdev::~blockdev() 14 | { 15 | } 16 | 17 | void blockdev::set_name(const char *n) 18 | { 19 | memcpy(name, n, sizeof(name)); 20 | } 21 | 22 | bool blockdev::convert_count_offset(uint64_t &count, uint64_t &offset) { 23 | // Convert count to sectorcount 24 | if(count == 0) { 25 | error = 0; 26 | return false; 27 | } 28 | if((count % sector_size) != 0) { 29 | // count must be a complete number of sectors. We can read more 30 | // and chop it off, but I'm making that the responsibility of 31 | // the caller 32 | error = EINVAL; 33 | return false; 34 | } 35 | count /= sector_size; 36 | 37 | // Convert offset to LBA 38 | if((offset % sector_size) != 0) { 39 | // also here 40 | error = EINVAL; 41 | return false; 42 | } 43 | offset /= sector_size; 44 | return true; 45 | } 46 | 47 | size_t blockdev::pread(void *str, size_t count, size_t offset) 48 | { 49 | // TODO: count and offset should be uint64_t to access large drives 50 | uint64_t sectorcount = count; 51 | uint64_t lba = offset; 52 | if(!convert_count_offset(sectorcount, lba)) { 53 | return 0; 54 | } 55 | 56 | error = read_sectors(str, lba, sectorcount); 57 | if(error) { 58 | return 0; 59 | } else { 60 | return count; 61 | } 62 | } 63 | 64 | size_t blockdev::pwrite(const char *str, size_t count, size_t offset) 65 | { 66 | // TODO: count and offset should be uint64_t to access large drives 67 | uint64_t sectorcount = count; 68 | uint64_t lba = offset; 69 | if(!convert_count_offset(sectorcount, lba)) { 70 | return 0; 71 | } 72 | 73 | error = write_sectors(str, lba, sectorcount); 74 | if(error) { 75 | return 0; 76 | } else { 77 | return count; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /blockdev/blockdev.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | namespace cloudos { 10 | 11 | struct blockdev : public fd_t { 12 | blockdev(); 13 | ~blockdev() override; 14 | 15 | /** 16 | * This method returns the block devices unique name. This pointer is 17 | * owned by this interface, and must not be freed. (If the interface is 18 | * still being constructed, this method returns the empty string.) 19 | */ 20 | inline const char *get_name() { 21 | return name; 22 | } 23 | 24 | size_t pread(void *str, size_t count, size_t offset) final override; 25 | size_t pwrite(const char *str, size_t count, size_t offset) final override; 26 | 27 | virtual cloudabi_errno_t read_sectors(void *str, uint64_t lba, uint64_t sectorcount) = 0; 28 | virtual cloudabi_errno_t write_sectors(const void *str, uint64_t lba, uint64_t sectorcount) = 0; 29 | 30 | private: 31 | bool convert_count_offset(uint64_t &count, uint64_t &offset); 32 | 33 | void set_name(const char *name); 34 | // TODO: make this configurable 35 | static const int sector_size = 512; 36 | 37 | friend struct blockdev_store; 38 | }; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /blockdev/blockdev_store.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace cloudos; 8 | 9 | blockdev_store::blockdev_store() 10 | : blockdevs_(nullptr) 11 | {} 12 | 13 | shared_ptr blockdev_store::get_blockdev(const char *name) 14 | { 15 | blockdev_list *found = find(blockdevs_, [name](blockdev_list *item) { 16 | return strcmp(item->data->get_name(), name) == 0; 17 | }); 18 | return found == nullptr ? shared_ptr() : found->data; 19 | } 20 | 21 | cloudabi_errno_t blockdev_store::register_blockdev(shared_ptr i, const char *prefix) 22 | { 23 | // TODO: do this using printf 24 | char name[8]; 25 | size_t prefixlen = strlen(prefix); 26 | if(prefixlen > 6) { 27 | prefixlen = 6; 28 | } 29 | memcpy(name, prefix, prefixlen); 30 | 31 | uint8_t suffix = 0; 32 | while(suffix < 10) { 33 | assert(prefixlen + 1 < sizeof(name)); 34 | name[prefixlen] = 0x30 + suffix; 35 | name[prefixlen + 1] = 0; 36 | if(get_blockdev(name) == nullptr) { 37 | return register_blockdev_fixed_name(i, name); 38 | } 39 | suffix++; 40 | } 41 | return EEXIST; 42 | } 43 | 44 | cloudabi_errno_t blockdev_store::register_blockdev_fixed_name(shared_ptr i, const char *name) 45 | { 46 | if(get_blockdev(name) != nullptr) { 47 | return EEXIST; 48 | } 49 | 50 | i->set_name(name); 51 | 52 | blockdev_list *next_entry = allocate(i); 53 | append(&blockdevs_, next_entry); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /blockdev/blockdev_store.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cloudos { 8 | 9 | struct blockdev; 10 | 11 | typedef linked_list> blockdev_list; 12 | 13 | struct blockdev_store 14 | { 15 | blockdev_store(); 16 | 17 | shared_ptr get_blockdev(const char *name); 18 | cloudabi_errno_t register_blockdev(shared_ptr i, const char *prefix); 19 | cloudabi_errno_t register_blockdev_fixed_name(shared_ptr i, const char *name); 20 | 21 | inline blockdev_list *get_blockdevs() { 22 | return blockdevs_; 23 | } 24 | 25 | private: 26 | blockdev_list *blockdevs_; 27 | }; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /blockdev/partition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace cloudos; 4 | 5 | partition::partition(shared_ptr b, uint64_t o, uint64_t c) 6 | : bdev(b) 7 | , lba_offset(o) 8 | , sectorcount(c) 9 | {} 10 | 11 | partition::~partition() 12 | {} 13 | 14 | cloudabi_errno_t partition::read_sectors(void *str, uint64_t lba, uint64_t sc) 15 | { 16 | if((lba + sc) > sectorcount) { 17 | // partition is not this big 18 | return EINVAL; 19 | } 20 | 21 | // relative -> absolute addressing 22 | return bdev->read_sectors(str, lba + lba_offset, sc); 23 | } 24 | 25 | cloudabi_errno_t partition::write_sectors(const void *str, uint64_t lba, uint64_t sc) 26 | { 27 | if((lba + sc) > sectorcount) { 28 | // partition is not this big 29 | return EINVAL; 30 | } 31 | 32 | // relative -> absolute addressing 33 | return bdev->write_sectors(str, lba + lba_offset, sc); 34 | } 35 | -------------------------------------------------------------------------------- /blockdev/partition.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace cloudos { 5 | 6 | struct partition : public blockdev { 7 | partition(shared_ptr bd, uint64_t lba_offset, uint64_t sectorcount); 8 | ~partition() override; 9 | 10 | cloudabi_errno_t read_sectors(void *str, uint64_t lba, uint64_t sectorcount) override; 11 | cloudabi_errno_t write_sectors(const void *str, uint64_t lba, uint64_t sectorcount) override; 12 | 13 | private: 14 | shared_ptr bdev; 15 | uint64_t lba_offset; 16 | uint64_t sectorcount; 17 | }; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /cmake/Toolchain-cloudabi-common.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER ${CLOUDABI_TRIPLET}-cc) 2 | set(CMAKE_CXX_COMPILER ${CLOUDABI_TRIPLET}-c++) 3 | set(CMAKE_AR ${CLOUDABI_TRIPLET}-ar CACHE FILEPATH "Archiver") 4 | set(CMAKE_RANLIB ${CLOUDABI_TRIPLET}-ranlib CACHE FILEPATH "Ranlib") 5 | -------------------------------------------------------------------------------- /cmake/Toolchain-i686-cloudabi.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6.0) 2 | SET(CMAKE_SYSTEM_NAME Generic) 3 | 4 | set(CLOUDABI_TRIPLET i686-unknown-cloudabi) 5 | include(${CMAKE_CURRENT_LIST_DIR}/Toolchain-cloudabi-common.cmake) 6 | 7 | # Work-around for clang r264966 8 | if(NOT CLOUDABI_NO_X86_CALL_FRAME_SET) 9 | set(CLOUDABI_NO_X86_CALL_FRAME_SET 1) 10 | set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS_INIT} -mllvm -no-x86-call-frame-opt") 11 | set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} -mllvm -no-x86-call-frame-opt") 12 | endif() 13 | -------------------------------------------------------------------------------- /cmake/aprotoc.cmake: -------------------------------------------------------------------------------- 1 | set(APROTOC_NAME "aprotoc" CACHE STRING "Name of the aprotoc command") 2 | find_program(APROTOC_COMMAND ${APROTOC_NAME}) 3 | mark_as_advanced(APROTOC_COMMAND) 4 | if(NOT APROTOC_COMMAND) 5 | message(FATAL_ERROR "Could not find aprotoc, set APROTOC_NAME") 6 | endif() 7 | 8 | function(add_aprotoc base) 9 | get_filename_component(base_dir ${base} DIRECTORY) 10 | add_custom_command( 11 | OUTPUT ${base}.ad.h 12 | COMMAND mkdir -p ${CMAKE_BINARY_DIR}/${base_dir} && ${APROTOC_COMMAND} <${CMAKE_SOURCE_DIR}/${base}.proto >${CMAKE_BINARY_DIR}/${base}.ad.h 13 | DEPENDS ${CMAKE_SOURCE_DIR}/${base}.proto 14 | ) 15 | endfunction() 16 | -------------------------------------------------------------------------------- /concur/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BAREMETAL_ENABLED) 2 | add_library(concur 3 | cv.hpp cv.cpp 4 | condition.hpp condition.cpp 5 | ) 6 | endif() 7 | -------------------------------------------------------------------------------- /concur/cv.cpp: -------------------------------------------------------------------------------- 1 | #include "cv.hpp" 2 | 3 | using namespace cloudos; 4 | 5 | void cv_t::wait() { 6 | thread_condition c(&signaler); 7 | 8 | thread_condition_waiter w; 9 | w.add_condition(&c); 10 | w.wait(); 11 | } 12 | 13 | void cv_t::notify() { 14 | signaler.condition_notify(); 15 | } 16 | 17 | void cv_t::broadcast() { 18 | signaler.condition_broadcast(); 19 | } 20 | -------------------------------------------------------------------------------- /concur/cv.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "condition.hpp" 5 | 6 | namespace cloudos { 7 | 8 | /** Condition variable implementation. 9 | * 10 | * A condition variable allows a thread to efficiently wait for some condition. 11 | * Instead of constantly yielding until the condition becomes true, the thread 12 | * can add itself to a cv's waiting list and mark itself blocked. Then, when 13 | * another thread may have changed the condition, it notifies the CV, and one 14 | * thread may check whether its condition is now good. (It can also 'broadcast' 15 | * the CV, in which case all threads may check whether their conditions are now 16 | * good.) 17 | * 18 | * This CV implementation, unlike normal implementations, does not take a 19 | * mutex. This mutex is normally held by a user while checking the condition, 20 | * then passed to wait() so it is unlocked while blocking on the CV. This 21 | * prevents a race condition where the condition is found false, but before 22 | * CV::wait() is called, the condition becomes true and the CV is notified. 23 | * Because the thread enters the waiting list too late, it is never woken up, 24 | * even though the condition became true. However, because this kernel is 25 | * uniprocessor and does not do kernel thread preemption, this race condition 26 | * can never occur. 27 | */ 28 | struct cv_t { 29 | inline thread_condition_signaler &get_signaler() { 30 | return signaler; 31 | } 32 | 33 | void wait(); 34 | void notify(); 35 | void broadcast(); 36 | 37 | private: 38 | thread_condition_signaler signaler; 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /contrib/compiler-rt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BAREMETAL_ENABLED) 2 | add_library(compiler_rt_builtins i386/udivdi3.S i386/umoddi3.S) 3 | endif() 4 | -------------------------------------------------------------------------------- /contrib/libcxxabi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BAREMETAL_ENABLED) 2 | add_library(cxxabi_rtti 3 | private_typeinfo.cpp private_typeinfo.h 4 | stdlib_typeinfo.cpp 5 | stdlib_exception.cpp 6 | ) 7 | target_compile_options(cxxabi_rtti PRIVATE -Wno-zero-as-null-pointer-constant) 8 | endif() 9 | -------------------------------------------------------------------------------- /contrib/libcxxabi/CREDITS.TXT: -------------------------------------------------------------------------------- 1 | This file is a partial list of people who have contributed to the LLVM/libc++abi 2 | project. If you have contributed a patch or made some other contribution to 3 | LLVM/libc++abi, please submit a patch to this file to add yourself, and it will be 4 | done! 5 | 6 | The list is sorted by surname and formatted to allow easy grepping and 7 | beautification by scripts. The fields are: name (N), email (E), web-address 8 | (W), PGP key ID and fingerprint (P), description (D), and snail-mail address 9 | (S). 10 | 11 | N: Aaron Ballman 12 | E: aaron@aaronballman.com 13 | D: Minor patches 14 | 15 | N: Logan Chien 16 | E: logan.chien@mediatek.com 17 | D: ARM EHABI Unwind & Exception Handling 18 | 19 | N: Marshall Clow 20 | E: mclow.lists@gmail.com 21 | E: marshall@idio.com 22 | D: Architect and primary coauthor of libc++abi 23 | 24 | N: Matthew Dempsky 25 | E: matthew@dempsky.org 26 | D: Minor patches and bug fixes. 27 | 28 | N: Nowar Gu 29 | E: wenhan.gu@gmail.com 30 | D: Minor patches and fixes 31 | 32 | N: Howard Hinnant 33 | E: hhinnant@apple.com 34 | D: Architect and primary coauthor of libc++abi 35 | 36 | N: Dana Jansens 37 | E: danakj@chromium.org 38 | D: ARM EHABI Unwind & Exception Handling 39 | 40 | N: Nick Kledzik 41 | E: kledzik@apple.com 42 | 43 | N: Antoine Labour 44 | E: piman@chromium.org 45 | D: ARM EHABI Unwind & Exception Handling 46 | 47 | N: Bruce Mitchener, Jr. 48 | E: bruce.mitchener@gmail.com 49 | D: Minor typo fixes 50 | 51 | N: Andrew Morrow 52 | E: andrew.c.morrow@gmail.com 53 | D: Minor patches and fixes 54 | 55 | N: Erik Olofsson 56 | E: erik.olofsson@hansoft.se 57 | E: erik@olofsson.info 58 | D: Minor patches and fixes 59 | 60 | N: Jon Roelofs 61 | E: jonathan@codesourcery.com 62 | D: ARM EHABI Unwind & Exception Handling, Bare-metal 63 | 64 | N: Nico Weber 65 | E: thakis@chromium.org 66 | D: ARM EHABI Unwind & Exception Handling 67 | 68 | N: Albert J. Wong 69 | E: ajwong@google.com 70 | D: ARM EHABI Unwind & Exception Handling 71 | 72 | -------------------------------------------------------------------------------- /contrib/libcxxabi/__cxxabi_config.h: -------------------------------------------------------------------------------- 1 | //===-------------------------- __cxxabi_config.h -------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is dual licensed under the MIT and the University of Illinois Open 6 | // Source Licenses. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #ifndef ____CXXABI_CONFIG_H 11 | #define ____CXXABI_CONFIG_H 12 | 13 | #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ 14 | !defined(__ARM_DWARF_EH__) 15 | #define _LIBCXXABI_ARM_EHABI 16 | #endif 17 | 18 | #if !defined(__has_attribute) 19 | #define __has_attribute(_attribute_) 0 20 | #endif 21 | 22 | #if defined(_WIN32) 23 | #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) 24 | #define _LIBCXXABI_HIDDEN 25 | #define _LIBCXXABI_DATA_VIS 26 | #define _LIBCXXABI_FUNC_VIS 27 | #define _LIBCXXABI_TYPE_VIS 28 | #elif defined(_LIBCXXABI_BUILDING_LIBRARY) 29 | #define _LIBCXXABI_HIDDEN 30 | #define _LIBCXXABI_DATA_VIS __declspec(dllexport) 31 | #define _LIBCXXABI_FUNC_VIS __declspec(dllexport) 32 | #define _LIBCXXABI_TYPE_VIS __declspec(dllexport) 33 | #else 34 | #define _LIBCXXABI_HIDDEN 35 | #define _LIBCXXABI_DATA_VIS __declspec(dllimport) 36 | #define _LIBCXXABI_FUNC_VIS __declspec(dllimport) 37 | #define _LIBCXXABI_TYPE_VIS __declspec(dllimport) 38 | #endif 39 | #else 40 | #if !defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) 41 | #define _LIBCXXABI_HIDDEN __attribute__((__visibility__("hidden"))) 42 | #define _LIBCXXABI_DATA_VIS __attribute__((__visibility__("default"))) 43 | #define _LIBCXXABI_FUNC_VIS __attribute__((__visibility__("default"))) 44 | #if __has_attribute(__type_visibility__) 45 | #define _LIBCXXABI_TYPE_VIS __attribute__((__type_visibility__("default"))) 46 | #else 47 | #define _LIBCXXABI_TYPE_VIS __attribute__((__visibility__("default"))) 48 | #endif 49 | #else 50 | #define _LIBCXXABI_HIDDEN 51 | #define _LIBCXXABI_DATA_VIS 52 | #define _LIBCXXABI_FUNC_VIS 53 | #define _LIBCXXABI_TYPE_VIS 54 | #endif 55 | #endif 56 | 57 | #if defined(_WIN32) 58 | #define _LIBCXXABI_WEAK 59 | #else 60 | #define _LIBCXXABI_WEAK __attribute__((__weak__)) 61 | #endif 62 | 63 | #endif // ____CXXABI_CONFIG_H 64 | -------------------------------------------------------------------------------- /contrib/libcxxabi/stdlib_exception.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------------- exception.cpp ---------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is dual licensed under the MIT and the University of Illinois Open 6 | // Source Licenses. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #define _LIBCPP_BUILDING_LIBRARY 11 | #define _LIBCPP_BUILDING_NEW 12 | #include 13 | #include 14 | 15 | namespace std 16 | { 17 | 18 | // exception 19 | 20 | exception::~exception() _NOEXCEPT 21 | { 22 | } 23 | 24 | const char* exception::what() const _NOEXCEPT 25 | { 26 | return "std::exception"; 27 | } 28 | 29 | // bad_exception 30 | 31 | bad_exception::~bad_exception() _NOEXCEPT 32 | { 33 | } 34 | 35 | const char* bad_exception::what() const _NOEXCEPT 36 | { 37 | return "std::bad_exception"; 38 | } 39 | 40 | 41 | // bad_alloc 42 | 43 | bad_alloc::bad_alloc() _NOEXCEPT 44 | { 45 | } 46 | 47 | bad_alloc::~bad_alloc() _NOEXCEPT 48 | { 49 | } 50 | 51 | const char* 52 | bad_alloc::what() const _NOEXCEPT 53 | { 54 | return "std::bad_alloc"; 55 | } 56 | 57 | // bad_array_new_length 58 | 59 | bad_array_new_length::bad_array_new_length() _NOEXCEPT 60 | { 61 | } 62 | 63 | bad_array_new_length::~bad_array_new_length() _NOEXCEPT 64 | { 65 | } 66 | 67 | const char* 68 | bad_array_new_length::what() const _NOEXCEPT 69 | { 70 | return "bad_array_new_length"; 71 | } 72 | 73 | // bad_array_length 74 | 75 | #ifndef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED 76 | 77 | class _LIBCPP_EXCEPTION_ABI bad_array_length 78 | : public bad_alloc 79 | { 80 | public: 81 | bad_array_length() _NOEXCEPT; 82 | virtual ~bad_array_length() _NOEXCEPT; 83 | virtual const char* what() const _NOEXCEPT; 84 | }; 85 | 86 | #endif // _LIBCPP_BAD_ARRAY_LENGTH_DEFINED 87 | 88 | bad_array_length::bad_array_length() _NOEXCEPT 89 | { 90 | } 91 | 92 | bad_array_length::~bad_array_length() _NOEXCEPT 93 | { 94 | } 95 | 96 | const char* 97 | bad_array_length::what() const _NOEXCEPT 98 | { 99 | return "bad_array_length"; 100 | } 101 | 102 | 103 | } // std 104 | -------------------------------------------------------------------------------- /contrib/libcxxabi/stdlib_typeinfo.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------- typeinfo.cpp ---------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is dual licensed under the MIT and the University of Illinois Open 6 | // Source Licenses. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | 12 | namespace std 13 | { 14 | 15 | // type_info 16 | 17 | type_info::~type_info() 18 | { 19 | } 20 | 21 | // bad_cast 22 | 23 | bad_cast::bad_cast() _NOEXCEPT 24 | { 25 | } 26 | 27 | bad_cast::~bad_cast() _NOEXCEPT 28 | { 29 | } 30 | 31 | const char* 32 | bad_cast::what() const _NOEXCEPT 33 | { 34 | return "std::bad_cast"; 35 | } 36 | 37 | // bad_typeid 38 | 39 | bad_typeid::bad_typeid() _NOEXCEPT 40 | { 41 | } 42 | 43 | bad_typeid::~bad_typeid() _NOEXCEPT 44 | { 45 | } 46 | 47 | const char* 48 | bad_typeid::what() const _NOEXCEPT 49 | { 50 | return "std::bad_typeid"; 51 | } 52 | 53 | } // std 54 | -------------------------------------------------------------------------------- /fd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BAREMETAL_ENABLED) 2 | add_library(fd 3 | fd.hpp 4 | memory_fd.cpp memory_fd.hpp 5 | mem_mapping.cpp mem_mapping.hpp 6 | process_fd.cpp process_fd.hpp 7 | scheduler.cpp scheduler.hpp scheduler.s 8 | procfs.cpp procfs.hpp 9 | bootfs.cpp bootfs.hpp 10 | initrdfs.cpp initrdfs.hpp 11 | thread.cpp thread.hpp 12 | pseudo_fd.cpp pseudo_fd.hpp 13 | sock.cpp sock.hpp 14 | unixsock.cpp unixsock.hpp 15 | userlandsock.cpp userlandsock.hpp 16 | ifstoresock.cpp ifstoresock.hpp 17 | rawsock.cpp rawsock.hpp 18 | reverse_fd.cpp reverse_fd.hpp 19 | shmfs.cpp shmfs.hpp 20 | blockdevstoresock.cpp blockdevstoresock.hpp 21 | vfs.cpp vfs.hpp 22 | ) 23 | 24 | # for elf.h: 25 | target_include_directories(fd SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/cloudlibc/src/include") 26 | 27 | # for external_binaries.h: 28 | target_include_directories(fd PRIVATE "${CMAKE_BINARY_DIR}") 29 | endif() 30 | -------------------------------------------------------------------------------- /fd/blockdevstoresock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace cloudos { 5 | 6 | struct blockdevstoresock : public userlandsock { 7 | blockdevstoresock(const char *n); 8 | 9 | private: 10 | void handle_command(const char *cmd, const char *arg) override; 11 | }; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /fd/bootfs.cpp: -------------------------------------------------------------------------------- 1 | #include "bootfs.hpp" 2 | #include 3 | #include "global.hpp" 4 | #include 5 | #include "userland/external_binaries.h" 6 | 7 | using namespace cloudos; 8 | 9 | namespace cloudos { 10 | 11 | struct bootfs_directory_fd : fd_t { 12 | bootfs_directory_fd(const char *n) 13 | : fd_t(CLOUDABI_FILETYPE_DIRECTORY, 0, n) {} 14 | 15 | void lookup(const char *file, size_t filelen, cloudabi_oflags_t oflags, cloudabi_filestat_t *filestat) override; 16 | shared_ptr inode_open(cloudabi_device_t, cloudabi_inode_t, const cloudabi_fdstat_t *) override; 17 | }; 18 | 19 | struct bootfs_file_fd : public memory_fd { 20 | bootfs_file_fd(external_binary_t const &file, const char *n) 21 | : memory_fd(file.start, file.end - file.start, n) 22 | {} 23 | }; 24 | 25 | } 26 | 27 | void bootfs_directory_fd::lookup(const char *file, size_t filelen, cloudabi_oflags_t, cloudabi_filestat_t *filestat) { 28 | filestat->st_dev = device; 29 | filestat->st_nlink = 1; 30 | filestat->st_atim = 0; 31 | filestat->st_mtim = 0; 32 | filestat->st_ctim = 0; 33 | 34 | if (strncmp(file, ".", filelen) == 0) { 35 | filestat->st_ino = 0; 36 | filestat->st_filetype = CLOUDABI_FILETYPE_DIRECTORY; 37 | filestat->st_size = 0; 38 | error = 0; 39 | return; 40 | } 41 | 42 | for(size_t i = 0; external_binaries_table[i].name; ++i) { 43 | auto &binary = external_binaries_table[i]; 44 | if(strncmp(file, binary.name, filelen) == 0) { 45 | filestat->st_ino = i + 1; 46 | filestat->st_filetype = CLOUDABI_FILETYPE_REGULAR_FILE; 47 | filestat->st_size = binary.end - binary.start; 48 | error = 0; 49 | return; 50 | } 51 | } 52 | 53 | error = ENOENT; 54 | return; 55 | } 56 | 57 | shared_ptr bootfs_directory_fd::inode_open(cloudabi_device_t st_dev, cloudabi_inode_t st_ino, const cloudabi_fdstat_t *) { 58 | if (st_dev != device) { 59 | error = EINVAL; 60 | return nullptr; 61 | } 62 | 63 | // TODO: check fdstat_t 64 | 65 | for(size_t i = 0; external_binaries_table[i].name; ++i) { 66 | if (st_ino == i + 1) { 67 | char name[64]; 68 | strncpy(name, "bootfs/", sizeof(name)); 69 | strncat(name, external_binaries_table[i].name, sizeof(name) - strlen(name) - 1); 70 | return make_shared(external_binaries_table[i], name); 71 | } 72 | } 73 | 74 | error = EINVAL; 75 | return nullptr; 76 | } 77 | 78 | shared_ptr bootfs::get_root_fd() { 79 | return make_shared("bootfs_root"); 80 | } 81 | -------------------------------------------------------------------------------- /fd/bootfs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "fd.hpp" 4 | 5 | namespace cloudos { 6 | 7 | struct bootfs { 8 | static shared_ptr get_root_fd(); 9 | }; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /fd/ifstoresock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace cloudos { 5 | 6 | struct ifstoresock : public userlandsock { 7 | ifstoresock(const char *n); 8 | 9 | private: 10 | void handle_command(const char *cmd, const char *arg) override; 11 | }; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /fd/initrdfs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "fd.hpp" 4 | 5 | namespace cloudos { 6 | 7 | struct multiboot_module; 8 | 9 | struct initrdfs { 10 | initrdfs(multiboot_module *initrd); 11 | 12 | shared_ptr get_root_fd(); 13 | 14 | private: 15 | uint8_t *initrd_start = nullptr; 16 | size_t initrd_size = 0; 17 | }; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /fd/memory_fd.cpp: -------------------------------------------------------------------------------- 1 | #include "memory_fd.hpp" 2 | 3 | using namespace cloudos; 4 | 5 | memory_fd::memory_fd(const char *n, cloudabi_inode_t i) 6 | : seekable_fd_t(CLOUDABI_FILETYPE_REGULAR_FILE, 0, n) 7 | , alloc({nullptr, 0}) 8 | , file_length(0) 9 | , inode(i) 10 | , owned(false) 11 | {} 12 | 13 | memory_fd::memory_fd(Blk a, size_t l, const char *n, cloudabi_inode_t i) 14 | : memory_fd(n, i) 15 | { 16 | reset(a, l); 17 | } 18 | 19 | memory_fd::memory_fd(void *a, size_t l, const char *n, cloudabi_inode_t i) 20 | : memory_fd(n, i) 21 | { 22 | reset(a, l); 23 | } 24 | 25 | void memory_fd::reset() { 26 | alloc = {nullptr, 0}; 27 | file_length = 0; 28 | inode = 0; 29 | owned = false; 30 | } 31 | 32 | void memory_fd::reset(Blk a, size_t l, cloudabi_inode_t i) { 33 | alloc = a; 34 | file_length = l; 35 | inode = i; 36 | owned = true; 37 | } 38 | 39 | void memory_fd::reset(void *a, size_t l, cloudabi_inode_t i) { 40 | alloc = {a, 0}; 41 | file_length = l; 42 | inode = i; 43 | owned = false; 44 | } 45 | 46 | memory_fd::~memory_fd() 47 | { 48 | if(owned) { 49 | deallocate(alloc); 50 | } 51 | } 52 | 53 | size_t memory_fd::read(void *dest, size_t count) { 54 | error = 0; 55 | if(pos >= file_length) { 56 | // EOF, don't change dest 57 | return 0; 58 | } 59 | 60 | size_t bytes_left = file_length - pos; 61 | size_t copied = count < bytes_left ? count : bytes_left; 62 | if(copied != 0) { 63 | assert(dest != nullptr); 64 | assert(alloc.ptr != nullptr); 65 | memcpy(reinterpret_cast(dest), reinterpret_cast(alloc.ptr) + pos, copied); 66 | pos += copied; 67 | } 68 | error = 0; 69 | return copied; 70 | } 71 | 72 | void memory_fd::file_stat_fget(cloudabi_filestat_t *buf) { 73 | buf->st_dev = device; 74 | buf->st_ino = inode; 75 | buf->st_filetype = type; 76 | buf->st_nlink = 1; 77 | buf->st_size = file_length; 78 | buf->st_atim = 0; 79 | buf->st_mtim = 0; 80 | buf->st_ctim = 0; 81 | error = 0; 82 | } 83 | -------------------------------------------------------------------------------- /fd/memory_fd.hpp: -------------------------------------------------------------------------------- 1 | #include "fd.hpp" 2 | 3 | namespace cloudos { 4 | 5 | /** Memory file descriptor 6 | * 7 | * This file descriptor acts as a read-only fd to a regular file with the 8 | * given static contents. 9 | */ 10 | struct memory_fd : public seekable_fd_t { 11 | // Empty constructor: read() will fail, but you can override read() 12 | // to replace the returned string with reset(), call memory_fd::read(), 13 | // then reset() again. 14 | memory_fd(const char *name, cloudabi_inode_t inode = 0); 15 | 16 | // Owning memory constructor: will return the data in the allocation, 17 | // and free the Blk when destructed. 18 | memory_fd(Blk allocation, size_t file_length, const char *name, cloudabi_inode_t inode = 0); 19 | 20 | // Non-owning memory constructor: will return the data in the 21 | // allocation, will not free the Blk when destructed. 22 | memory_fd(void *address, size_t file_length, const char *name, cloudabi_inode_t inode = 0); 23 | ~memory_fd() override; 24 | 25 | size_t read(void *dest, size_t count) override; 26 | void file_stat_fget(cloudabi_filestat_t *buf) override; 27 | 28 | void reset(); 29 | void reset(Blk allocation, size_t file_length, cloudabi_inode_t inode = 0); 30 | void reset(void *address, size_t file_length, cloudabi_inode_t inode = 0); 31 | 32 | private: 33 | Blk alloc; 34 | size_t file_length; 35 | cloudabi_inode_t inode; 36 | bool owned; 37 | }; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /fd/procfs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "fd.hpp" 4 | 5 | namespace cloudos { 6 | 7 | struct procfs { 8 | static shared_ptr get_root_fd(); 9 | 10 | private: 11 | }; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /fd/rawsock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cloudos { 9 | 10 | struct rawsock : public sock_t, public enable_shared_from_this { 11 | rawsock(interface *iface, cloudabi_fdflags_t f, const char *n); 12 | ~rawsock() override; 13 | 14 | void init(); 15 | 16 | bool has_messages() const; 17 | cloudabi_errno_t get_read_signaler(thread_condition_signaler **s) override; 18 | 19 | void sock_shutdown(cloudabi_sdflags_t how) override; 20 | void sock_recv(const cloudabi_recv_in_t* in, cloudabi_recv_out_t *out) override; 21 | void sock_send(const cloudabi_send_in_t* in, cloudabi_send_out_t *out) override; 22 | 23 | void frame_received(uint8_t *frame, size_t frame_length); 24 | 25 | private: 26 | // TODO: make this a weak ptr 27 | interface *iface; 28 | 29 | thread_condition_signaler read_signaler; 30 | 31 | linked_list *messages = nullptr; 32 | cv_t read_cv; 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /fd/reverse_fd.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace cloudos { 7 | 8 | using reverse_proto::reverse_request_t; 9 | using reverse_proto::reverse_response_t; 10 | using reverse_proto::pseudofd_t; 11 | 12 | struct pseudo_fd; 13 | 14 | typedef linked_list> pseudo_list; 15 | 16 | struct reversefd_t : public unixsock { 17 | reversefd_t(cloudabi_filetype_t sockettype, cloudabi_fdflags_t f, const char *n); 18 | ~reversefd_t() override; 19 | 20 | void subscribe_fd_read_events(shared_ptr fd); 21 | virtual void have_bytes_received() override; 22 | 23 | // send a request and block until we get a response 24 | Blk send_request(reverse_request_t *request, const char *buffer, reverse_response_t *response); 25 | 26 | private: 27 | shared_ptr get_pseudo(reverse_proto::pseudofd_t pseudo_id); 28 | void handle_gratituous_message(); 29 | cloudabi_errno_t read_response(reverse_response_t *response, Blk *recv_buf); 30 | 31 | size_t bytes_read = 0; 32 | reverse_proto::reverse_response_t message; 33 | Blk recv_data; 34 | 35 | pseudo_list *pseudos = nullptr; 36 | 37 | bool sending_request = false; 38 | cv_t response_arrived_cv; 39 | cv_t request_done_cv; 40 | }; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /fd/reverse_proto.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace reverse_proto { 4 | 5 | typedef uint64_t pseudofd_t; 6 | 7 | struct reverse_request_t { 8 | pseudofd_t pseudofd = 0; 9 | enum class operation { 10 | lookup = 0, // filename in buffer, oflags in flags, returns inode in result and filestat_t in buffer 11 | stat_fget, 12 | stat_put, // fsflags in inode, buffer is filestat_t* + filename 13 | stat_fput, // fsflags in inode, buffer is filestat_t* 14 | is_readable, 15 | datasync, 16 | sync, 17 | // all the calls below use the inode, not the filename 18 | open, 19 | create, // filename in buffer 20 | allocate, // length in flags 21 | readdir, // cookie in result (0 if last entry), put a cloudabi_dirent_t + name in buffer 22 | readlink, 23 | rename, // send fd2 as 'flags', and buffer is 'filename1filename2' 24 | symlink, // buffer is 'filename1filename2' 25 | link, // send fd2 as 'flags', and buffer is 'filename1filename2' 26 | unlink, 27 | pread, 28 | pwrite, // if flags is CLOUDABI_FDFLAG_APPEND, ignore offset, always append, return pos in result 29 | close, 30 | // the calls below are for UNIX sockets; inode is 0 31 | sock_shutdown, 32 | sock_recv, 33 | sock_send 34 | } op; 35 | uint64_t inode = 0; 36 | uint64_t flags = 0; 37 | uint64_t offset = 0; 38 | uint16_t send_length = 0; // bytes following this request (for filenames & writes) 39 | uint16_t recv_length = 0; // length to read 40 | }; 41 | 42 | struct reverse_response_t { 43 | int64_t result = 0; // < 0 is -errno, 0 is success, >= 0 is result (can be inode or pseudo-fd) 44 | uint64_t flags = 0; // filetype in case of lookup/open 45 | bool gratituous = false; 46 | uint16_t send_length = 0; // bytes following this response 47 | uint16_t recv_length = 0; // bytes actually read 48 | }; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /fd/scheduler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "thread.hpp" 4 | 5 | namespace cloudos { 6 | 7 | struct interrupt_state_t; 8 | 9 | struct scheduler { 10 | scheduler(); 11 | 12 | inline bool is_waiting_for_ready_task() { 13 | return waiting_for_ready_task; 14 | } 15 | 16 | [[noreturn]] void initial_yield(); 17 | [[noreturn]] void thread_final_yield(); 18 | void thread_yield(); 19 | 20 | void thread_ready(shared_ptr thr); 21 | void thread_exiting(shared_ptr thr); 22 | void thread_blocked(shared_ptr thr); 23 | 24 | shared_ptr get_running_thread(); 25 | 26 | private: 27 | void wait_for_next(); 28 | void schedule_next(); 29 | 30 | thread_list *running = nullptr; 31 | thread_list *ready = nullptr; 32 | thread_list *dealloc_later = nullptr; 33 | bool waiting_for_ready_task = true; 34 | }; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /fd/scheduler.s: -------------------------------------------------------------------------------- 1 | .global switch_thread 2 | switch_thread: 3 | /* void switch_thread(void **old_sp, void *sp) */ 4 | mov 4(%esp), %eax 5 | mov 8(%esp), %ecx 6 | /* store callee saved registers */ 7 | push %ebx 8 | push %edi 9 | push %esi 10 | push %ebp 11 | /* store my stack ptr in *eax */ 12 | mov %esp, (%eax) 13 | /* load stack ptr from ecx */ 14 | mov %ecx, %esp 15 | /* load callee saved registers */ 16 | pop %ebp 17 | pop %esi 18 | pop %edi 19 | pop %ebx 20 | /* return to thread */ 21 | ret 22 | 23 | .global initial_kernel_stack 24 | initial_kernel_stack: 25 | .long 0 26 | .long 0 27 | .long 0 28 | .long 0 29 | .long do_iret 30 | 1: 31 | 32 | .global initial_kernel_stack_size 33 | initial_kernel_stack_size: 34 | .int 1b - initial_kernel_stack 35 | -------------------------------------------------------------------------------- /fd/shmfs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "fd.hpp" 4 | 5 | namespace cloudos { 6 | 7 | struct shmfs { 8 | shmfs(cloudabi_device_t device = 0); 9 | 10 | shared_ptr get_shm(); 11 | 12 | private: 13 | cloudabi_device_t device; 14 | }; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /fd/sock.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace cloudos; 4 | 5 | sock_t::sock_t(cloudabi_filetype_t sockettype, cloudabi_fdflags_t flags, const char *n) 6 | : fd_t(sockettype, flags, n) 7 | { 8 | assert(sockettype == CLOUDABI_FILETYPE_SOCKET_DGRAM 9 | || sockettype == CLOUDABI_FILETYPE_SOCKET_STREAM); 10 | } 11 | 12 | size_t sock_t::read(void *dest, size_t count) 13 | { 14 | cloudabi_iovec_t iovec[1]; 15 | iovec[0].buf = dest; 16 | iovec[0].buf_len = count; 17 | 18 | cloudabi_recv_in_t recv_in[1]; 19 | recv_in[0].ri_data = &iovec[0]; 20 | recv_in[0].ri_data_len = 1; 21 | recv_in[0].ri_fds = nullptr; 22 | recv_in[0].ri_fds_len = 0; 23 | recv_in[0].ri_flags = 0; 24 | 25 | cloudabi_recv_out_t recv_out[1]; 26 | recv_out[0].ro_datalen = 0; 27 | 28 | sock_recv(recv_in, recv_out); 29 | assert(recv_out[0].ro_fdslen == 0); 30 | return recv_out[0].ro_datalen; 31 | } 32 | 33 | size_t sock_t::write(const char *str, size_t count) 34 | { 35 | cloudabi_ciovec_t iovec[1]; 36 | iovec[0].buf = str; 37 | iovec[0].buf_len = count; 38 | 39 | cloudabi_send_in_t send_in[1]; 40 | send_in[0].si_data = &iovec[0]; 41 | send_in[0].si_data_len = 1; 42 | send_in[0].si_fds = nullptr; 43 | send_in[0].si_fds_len = 0; 44 | send_in[0].si_flags = 0; 45 | 46 | cloudabi_send_out_t send_out[1]; 47 | send_out[0].so_datalen = 0; 48 | 49 | sock_send(send_in, send_out); 50 | return send_out[0].so_datalen; 51 | } 52 | -------------------------------------------------------------------------------- /fd/sock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace cloudos { 7 | 8 | struct sock_t : public fd_t { 9 | sock_t(cloudabi_filetype_t sockettype, cloudabi_fdflags_t flags, const char *n); 10 | 11 | enum sockstatus_t { 12 | // If this socket is in SHUTDOWN, it cannot send() anymore, but 13 | // can still recv(). If othersock->status is SHUTDOWN, we can 14 | // send(), but the other side can't. 15 | IDLE, CONNECTING, CONNECTED, SHUTDOWN 16 | }; 17 | 18 | size_t read(void *dest, size_t count) override; 19 | size_t write(const char *str, size_t count) override; 20 | 21 | void sock_shutdown(cloudabi_sdflags_t /*how*/) override 22 | { 23 | if(status == sockstatus_t::CONNECTED) { 24 | error = EINVAL; 25 | } else { 26 | error = ENOTCONN; 27 | } 28 | } 29 | 30 | void sock_recv(const cloudabi_recv_in_t* /*in*/, cloudabi_recv_out_t* /*out*/) override 31 | { 32 | if(status == sockstatus_t::CONNECTED || status == sockstatus_t::SHUTDOWN) { 33 | error = EINVAL; 34 | } else { 35 | error = ENOTCONN; 36 | } 37 | } 38 | 39 | void sock_send(const cloudabi_send_in_t* /*in*/, cloudabi_send_out_t* /*out*/) override 40 | { 41 | if(status == sockstatus_t::SHUTDOWN) { 42 | error = EPIPE; 43 | } else if(status == sockstatus_t::CONNECTED) { 44 | error = EINVAL; 45 | } else { 46 | error = ENOTCONN; 47 | } 48 | } 49 | 50 | protected: 51 | sockstatus_t status = sockstatus_t::IDLE; 52 | }; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /fd/unixsock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cloudos { 8 | 9 | struct unixsock_message; 10 | typedef linked_list unixsock_message_list; 11 | 12 | struct unixsock_message { 13 | Blk buf; 14 | size_t stream_data_recv = 0; 15 | // fd_mapping_t contains a shared_ptr. With shared_ptr, fd's 16 | // survive in-flight (i.e. they are not destructed when a close() 17 | // happens between send() and recv()). 18 | linked_list *fd_list = nullptr; 19 | }; 20 | 21 | struct unixsock : public sock_t, public enable_shared_from_this { 22 | unixsock(cloudabi_filetype_t sockettype, cloudabi_fdflags_t flags, const char *n); 23 | ~unixsock() override; 24 | 25 | size_t bytes_readable() const; 26 | bool is_readable(); 27 | bool is_shutdown(); 28 | bool is_writeable(); 29 | cloudabi_errno_t get_read_signaler(thread_condition_signaler **s) override; 30 | cloudabi_errno_t get_write_signaler(thread_condition_signaler **s) override; 31 | 32 | void socketpair(shared_ptr other); 33 | 34 | size_t read(void *dest, size_t count) override; 35 | size_t write(const char *str, size_t count) override; 36 | 37 | void sock_shutdown(cloudabi_sdflags_t how) override; 38 | void sock_recv(const cloudabi_recv_in_t* in, cloudabi_recv_out_t *out) override; 39 | void sock_send(const cloudabi_send_in_t* in, cloudabi_send_out_t *out) override; 40 | 41 | thread_condition_data *allocate_current_condition_data(); 42 | 43 | protected: 44 | // This function is called by another unixsock when bytes were just added to 45 | // this sock's recv_messages / num_recv_bytes. Because it's virtual, this allows 46 | // creating unixsocks with additional behaviour when bytes are received, such as 47 | // the reverse_fd. 48 | virtual void have_bytes_received(); 49 | 50 | private: 51 | weak_ptr othersock; 52 | 53 | static constexpr size_t MAX_SIZE_BUFFERS = 1024 * 1024; 54 | static constexpr size_t MAX_FD_PER_MESSAGE = 20; 55 | 56 | size_t num_recv_bytes = 0; 57 | unixsock_message_list *recv_messages = nullptr; 58 | cv_t recv_messages_cv; 59 | thread_condition_signaler recv_signaler; 60 | thread_condition_signaler send_signaler; 61 | }; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /fd/userlandsock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace cloudos { 7 | 8 | /** 9 | * A utility base class for a socket that can be used for communication with userland 10 | * processes. 11 | */ 12 | struct userlandsock : public sock_t { 13 | userlandsock(const char *n); 14 | ~userlandsock() override; 15 | 16 | void sock_shutdown(cloudabi_sdflags_t how) override; 17 | void sock_recv(const cloudabi_recv_in_t* in, cloudabi_recv_out_t *out) override; 18 | void sock_send(const cloudabi_send_in_t* in, cloudabi_send_out_t *out) override; 19 | 20 | protected: 21 | virtual void handle_command(const char *cmd, const char *parameter) = 0; 22 | 23 | void set_response(const char *message); 24 | void add_fd_to_response(int fd); 25 | 26 | private: 27 | void clear_response(); 28 | 29 | bool has_message = false; 30 | Blk message_buf; 31 | linked_list *message_fds = nullptr; 32 | cv_t read_cv; 33 | cv_t write_cv; 34 | }; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /fd/vga_fd.hpp: -------------------------------------------------------------------------------- 1 | #include "fd.hpp" 2 | 3 | namespace cloudos { 4 | 5 | /** VGA stream file descriptor 6 | * 7 | * This fd is write-only. If something is written to it, this appears on 8 | * the VGA console as-is. 9 | */ 10 | struct vga_fd : public fd_t { 11 | inline vga_fd(const char *n) : fd_t(CLOUDABI_FILETYPE_CHARACTER_DEVICE, 0, n) {} 12 | 13 | inline size_t write(const char *str, size_t count) override { 14 | for(size_t i = 0; i < count; ++i) { 15 | get_vga_stream() << str[i]; 16 | } 17 | error = 0; 18 | return count; 19 | } 20 | }; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /hw/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BAREMETAL_ENABLED) 2 | set(EXTRA_HW_SOURCES segments.s interrupt.S) 3 | set_source_files_properties(segments.s interrupt.S PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") 4 | else() 5 | set(EXTRA_HW_SOURCES test/segments_stub.c test/interrupt_stub.c) 6 | endif() 7 | 8 | add_library(hw 9 | vga.cpp vga.hpp 10 | vga_stream.hpp vga_stream.cpp 11 | multiboot.hpp multiboot.cpp 12 | segments.hpp segments.cpp 13 | interrupt_table.hpp interrupt_table.cpp 14 | interrupt.hpp interrupt.cpp 15 | sse.hpp sse.cpp 16 | pci_bus.hpp pci_bus.cpp 17 | driver.hpp 18 | driver_store.hpp driver_store.cpp 19 | device.hpp device.cpp 20 | root_device.hpp root_device.cpp 21 | net/ethernet_device.hpp net/ethernet_device.cpp 22 | net/virtio.hpp net/virtio.cpp 23 | net/intel_i217.hpp net/intel_i217_flags.hpp net/intel_i217.cpp 24 | arch/x86/x86.hpp arch/x86/x86.cpp 25 | arch/x86/x86_pit.hpp arch/x86/x86_pit.cpp 26 | arch/x86/x86_kbd.hpp arch/x86/x86_kbd.cpp 27 | arch/x86/x86_serial.hpp arch/x86/x86_serial.cpp 28 | arch/x86/x86_fpu.hpp arch/x86/x86_fpu.cpp 29 | arch/x86/x86_rtc.hpp arch/x86/x86_rtc.cpp 30 | arch/x86/x86_ata.hpp arch/x86/x86_ata.cpp 31 | ${EXTRA_HW_SOURCES}) 32 | list(APPEND hw_tests 33 | test/test_vga.cpp 34 | test/test_vga_stream.cpp 35 | test/test_multiboot.cpp 36 | test/test_segments.cpp) 37 | target_link_libraries(hw oslibc memory) 38 | 39 | if(TESTING_ENABLED) 40 | add_executable(hw_test ${hw_tests} test/test_main.cpp) 41 | target_include_directories(hw_test PRIVATE ${TESTING_CATCH_INCLUDE}) 42 | target_link_libraries(hw_test hw) 43 | add_test(NAME hw_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND hw_test) 44 | endif() 45 | -------------------------------------------------------------------------------- /hw/arch/x86/x86.cpp: -------------------------------------------------------------------------------- 1 | #include "x86.hpp" 2 | #include "x86_ata.hpp" 3 | #include "x86_pit.hpp" 4 | #include "x86_kbd.hpp" 5 | #include "x86_serial.hpp" 6 | #include "x86_fpu.hpp" 7 | #include "x86_rtc.hpp" 8 | #include 9 | 10 | using namespace cloudos; 11 | 12 | const char *x86_driver::description() { 13 | return "x86 PC driver"; 14 | } 15 | 16 | device *x86_driver::probe_root_device(device *root) { 17 | return allocate(root); 18 | } 19 | 20 | x86_pc::x86_pc(device *parent) : device(parent) {} 21 | 22 | const char *x86_pc::description() { 23 | return "x86 PC"; 24 | } 25 | 26 | cloudabi_errno_t x86_pc::init() { 27 | auto *pit = allocate(this); 28 | pit->init(); 29 | auto *kbd = allocate(this); 30 | kbd->init(); 31 | auto *serial = allocate(this); 32 | serial->init(); 33 | auto *fpu = allocate(this); 34 | fpu->init(); 35 | auto *rtc = allocate(this); 36 | rtc->init(); 37 | auto *ata = allocate(this); 38 | ata->init(); 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /hw/arch/x86/x86.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cloudos { 8 | 9 | struct x86_driver : public driver { 10 | const char *description() override; 11 | device *probe_root_device(device *root) override; 12 | }; 13 | 14 | /** 15 | * This device represents a standard x86 PC. As its children, it has all the 16 | * devices we normally expect on such a PC, such as the timer and the keyboard 17 | * controller. 18 | */ 19 | struct x86_pc : public device { 20 | x86_pc(device *parent); 21 | 22 | const char *description() override; 23 | cloudabi_errno_t init() override; 24 | }; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /hw/arch/x86/x86_ata.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace cloudos { 11 | 12 | struct x86_ata; 13 | 14 | /** 15 | * This device represents a disk connected to an ATA controller. 16 | */ 17 | struct x86_ata_device : public device, public blockdev { 18 | x86_ata_device(x86_ata *controller, int io_port, bool master, uint16_t *identifydata); 19 | 20 | const char *description() override; 21 | cloudabi_errno_t init() override; 22 | 23 | cloudabi_errno_t read_sectors(void *str, uint64_t lba, uint64_t sectorcount) override; 24 | cloudabi_errno_t write_sectors(const void *str, uint64_t lba, uint64_t sectorcount) override; 25 | 26 | private: 27 | x86_ata *controller; 28 | uint16_t identifydata[256]; 29 | char description_with_name[40]; 30 | int io_port; 31 | bool master; 32 | }; 33 | 34 | /** 35 | * This device represents the two x86 ATA controllers. 36 | */ 37 | struct x86_ata : public device, public irq_handler { 38 | x86_ata(device *parent); 39 | 40 | const char *description() override; 41 | cloudabi_errno_t init() override; 42 | 43 | void handle_irq(uint8_t irq) override; 44 | 45 | cloudabi_errno_t read_sectors(int io_port, bool master, uint64_t lba, uint64_t sectorcount, void *str); 46 | cloudabi_errno_t write_sectors(int io_port, bool master, uint64_t lba, uint64_t sectorcount, const void *str); 47 | 48 | private: 49 | void select_bus_device(int port, bool lba, bool master); 50 | bool identify_bus_device(int port, bool master, uint16_t *data); 51 | 52 | uint8_t busa_selected = 0; 53 | uint8_t busb_selected = 0; 54 | 55 | bool locked = false; 56 | cv_t unlocked_cv; 57 | }; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /hw/arch/x86/x86_fpu.cpp: -------------------------------------------------------------------------------- 1 | #include "x86_fpu.hpp" 2 | #include 3 | #include 4 | 5 | using namespace cloudos; 6 | 7 | x86_fpu::x86_fpu(device *parent) : device(parent), irq_handler() { 8 | } 9 | 10 | const char *x86_fpu::description() { 11 | return "x86 FPU"; 12 | } 13 | 14 | cloudabi_errno_t x86_fpu::init() { 15 | register_irq(13); 16 | return 0; 17 | } 18 | 19 | void x86_fpu::handle_irq(uint8_t) { 20 | /* ignore it */ 21 | } 22 | -------------------------------------------------------------------------------- /hw/arch/x86/x86_fpu.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cloudos { 9 | 10 | /** 11 | * This device represents an x86 FPU. It primarily serves to handle exceptions. 12 | */ 13 | struct x86_fpu : public device, public irq_handler { 14 | x86_fpu(device *parent); 15 | 16 | const char *description() override; 17 | cloudabi_errno_t init() override; 18 | 19 | void handle_irq(uint8_t irq) override; 20 | }; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /hw/arch/x86/x86_kbd.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace cloudos { 9 | 10 | /** 11 | * This device represents a standard x86 keyboard controller. It handles IRQ 1. 12 | */ 13 | struct x86_kbd : public device, public irq_handler { 14 | x86_kbd(device *parent); 15 | 16 | const char *description() override; 17 | cloudabi_errno_t init() override; 18 | 19 | void handle_irq(uint8_t irq) override; 20 | 21 | private: 22 | void pump_character(); 23 | uint8_t get_scancode_raw(); 24 | bool ignore_irq = false; 25 | 26 | uint8_t scancode_buffer[8]; 27 | uint8_t get_scancode(); 28 | void delay_scancode(uint8_t sc); 29 | 30 | uint8_t ledstate = 0; 31 | 32 | bool led_enabled(uint8_t led); 33 | void toggle_led(uint8_t led); 34 | void enable_led(uint8_t led); 35 | void disable_led(uint8_t led); 36 | void set_ledstate(); 37 | 38 | void send_cmdbyte(uint8_t cmd); 39 | 40 | uint8_t modifiers = 0; 41 | }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /hw/arch/x86/x86_pit.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include