#include #include #include extern "C" void __euler_do_syscall( uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx); namespace euler::syscall { encoded_color encode_color( uint8_t r, uint8_t g, uint8_t b) { uint64_t rax = 0; uint64_t rdi = (uint32_t)r | ((uint32_t)g << 8) | ((uint32_t)b << 16); uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); return (encoded_color)(rax & 0xffffffff); } void get_framebuffer( encoded_color *&buffer_out, uint32_t &width_out, uint32_t &height_out, uint32_t &pitch_out) { uint64_t rax = 1; uint64_t rdi; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); buffer_out = (encoded_color *)rax; width_out = rdi & 0xffffffff; height_out = rdi >> 32; pitch_out = rsi & 0xffffffff; } stream_result open_file( const std::string &file_path, bool allow_creation, bool only_allow_creation, stream_handle &handle_out) { uint64_t rax = 2; uint64_t rdi = (uint64_t)file_path.data(); uint64_t rsi = file_path.size(); uint64_t rdx = ( allow_creation ? 0x1 : 0x0) | (only_allow_creation ? 0x2 : 0x0); __euler_do_syscall(rax, rdi, rsi, rdx); handle_out = rdi; return (stream_result)rax; } [[noreturn]] void end_this_thread(int32_t exit_code) { uint64_t rax = 3; uint64_t rdi = (uint32_t)exit_code; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); __builtin_unreachable(); } void *get_new_pages(uint64_t n_pages) { uint64_t rax = 4; uint64_t rdi = n_pages; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); return (void *)rax; } std::variant get_input_packet() { uint64_t rax = 5; uint64_t rdi; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); if (rax & 0x80) return (mouse_packet){ . left_button_down = (rax & 0x01) != 0, . right_button_down = (rax & 0x02) != 0, .middle_button_down = (rax & 0x04) != 0, .x_changed = (int16_t)(rdi & 0xffff), .y_changed = (int16_t)(rsi & 0xffff) }; return (key_packet){ .was_key_up_event = (rdi & 0x40000) != 0, . num_lock = (rdi & 0x20000) != 0, . caps_lock = (rdi & 0x10000) != 0, . right_win = (rdi & 0x8000) != 0, . left_win = (rdi & 0x4000) != 0, . right_alt = (rdi & 0x2000) != 0, . left_alt = (rdi & 0x1000) != 0, . right_ctrl = (rdi & 0x800) != 0, . left_ctrl = (rdi & 0x400) != 0, . right_shift = (rdi & 0x200) != 0, . left_shift = (rdi & 0x100) != 0, . key_code = (uint8_t)(rdi & 0xff) }; } void create_private_socket( stream_handle &end_1_out, stream_handle &end_2_out) { uint64_t rax = 6; uint64_t rdi; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); end_1_out = rax; end_2_out = rdi; } stream_result create_socket_listener( const std::string &id, listener_handle &handle_out) { uint64_t rax = 7; uint64_t rdi = (uint64_t)id.data(); uint64_t rsi = id.size(); uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); handle_out = rdi; return (stream_result)rax; } void stop_socket_listener(listener_handle handle) { uint64_t rax = 8; uint64_t rdi = handle; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); } stream_result accept_socket_connection( listener_handle listener, stream_handle &stream_out) { uint64_t rax = 9; uint64_t rdi = listener; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); stream_out = rdi; return (stream_result)rax; } stream_result connect_to_socket( const std::string &id, stream_handle &handle_out) { uint64_t rax = 10; uint64_t rdi = (uint64_t)id.data(); uint64_t rsi = id.size(); uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); handle_out = rdi; return (stream_result)rax; } void close_stream(stream_handle handle) { uint64_t rax = 11; uint64_t rdi = handle; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); } stream_result seek_stream( stream_handle handle, seek_from from, int64_t offset) { uint64_t rax = 12; uint64_t rdi = (uint64_t)handle; uint64_t rsi = (uint8_t)from; uint64_t rdx = (uint64_t)offset; __euler_do_syscall(rax, rdi, rsi, rdx); return (stream_result)rax; } stream_result read_from_stream( stream_handle handle, uint64_t bytes, void *into) { uint64_t rax = 13; uint64_t rdi = (uint64_t)handle; uint64_t rsi = bytes; uint64_t rdx = (uint64_t)into; __euler_do_syscall(rax, rdi, rsi, rdx); return (stream_result)rax; } stream_result write_to_stream( stream_handle handle, uint64_t bytes, const void *from) { uint64_t rax = 14; uint64_t rdi = (uint64_t)handle; uint64_t rsi = bytes; uint64_t rdx = (uint64_t)from; __euler_do_syscall(rax, rdi, rsi, rdx); return (stream_result)rax; } stream_result get_stream_length( stream_handle handle, uint64_t &length_out) { uint64_t rax = 15; uint64_t rdi = (uint64_t)handle; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); length_out = rdi; return (stream_result)rax; } stream_result start_process( const std::string &file_path, const std::vector> &environment_variables, const std::vector> &gifted_streams, process_handle &handle_out) { std::vector ev_structs(environment_variables.size() * 4); for (size_t i = 0; i < environment_variables.size(); ++i) { ev_structs[i * 4] = environment_variables[i]. first.size(); ev_structs[i * 4 + 1] = (uint64_t)environment_variables[i]. first.data(); ev_structs[i * 4 + 2] = environment_variables[i].second.size(); ev_structs[i * 4 + 3] = (uint64_t)environment_variables[i].second.data(); } std::vector gs_structs(gifted_streams.size() * 2); for (size_t i = 0; i < environment_variables.size(); ++i) { gs_structs[i * 2] = (uint64_t)gifted_streams[i]. first; gs_structs[i * 2 + 1] = (uint64_t)gifted_streams[i].second; } uint64_t psi_struct[] = { file_path.size(), (uint64_t) file_path.data(), environment_variables.size(), (uint64_t)ev_structs.data(), gifted_streams.size(), (uint64_t)gs_structs.data() }; uint64_t rax = 16; uint64_t rdi = (uint64_t)psi_struct; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); handle_out = rdi; return (stream_result)rax; } [[noreturn]] void end_this_process(int32_t exit_code) { uint64_t rax = 17; uint64_t rdi = (uint32_t)exit_code; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); __builtin_unreachable(); } stream_result set_stream_length( stream_handle handle, uint64_t new_length) { uint64_t rax = 18; uint64_t rdi = (uint64_t)handle; uint64_t rsi = new_length; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); return (stream_result)rax; } stream_result get_other_end_process_handle( stream_handle stream, process_handle &process_out) { uint64_t rax = 19; uint64_t rdi = (uint64_t)stream; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); process_out = (process_handle)rdi; return (stream_result)rax; } //entry_point must not return void start_thread(void (*entry_point)(uint64_t), uint64_t arg) { uint64_t rax = 20; uint64_t rdi = (uint64_t)entry_point; uint64_t rsi = arg; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); } //entry_point must not return void start_thread(void (*entry_point)()) { uint64_t rax = 20; uint64_t rdi = (uint64_t)entry_point; uint64_t rsi = 0; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); } //return value is number of bytes cleared uint64_t clear_socket_read_queue(stream_handle handle) { uint64_t rax = 21; uint64_t rdi = handle; uint64_t rsi; uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); return rax; } //this function has a race condition if the variable is changed //or unset by another thread between the two syscalls. std::optional try_get_environment_variable( const std::string &name) { uint64_t rax = 22; uint64_t rdi = (uint64_t)name.data(); uint64_t rsi = name.size(); uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); if (rax == (uint64_t)-1) return {}; std::string s; s.resize(rax); rax = 23; rdi = (uint64_t)name.data(); rsi = name.size(); rdx = (uint64_t)s.data(); __euler_do_syscall(rax, rdi, rsi, rdx); //do i need to tell gcc that s is modified? return s; } void set_thread_name(const std::string &name) { uint64_t rax = 24; uint64_t rdi = (uint64_t)name.data(); uint64_t rsi = name.size(); uint64_t rdx; __euler_do_syscall(rax, rdi, rsi, rdx); } }