From 48c7721b0fc090159dac0851af8966ae7731754e Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Wed, 25 Oct 2023 23:08:45 -0700 Subject: [PATCH] [VictoriaFalls] Add a VFS yunq stub and register it. --- sys/victoriafalls/CMakeLists.txt | 7 +- .../lib/victoriafalls/victoriafalls.yunq | 12 ++ .../victoriafalls.yunq.client.cpp | 41 +++++ .../victoriafalls/victoriafalls.yunq.client.h | 28 ++++ .../lib/victoriafalls/victoriafalls.yunq.cpp | 158 ++++++++++++++++++ .../lib/victoriafalls/victoriafalls.yunq.h | 46 +++++ .../victoriafalls.yunq.server.cpp | 106 ++++++++++++ .../victoriafalls/victoriafalls.yunq.server.h | 37 ++++ sys/victoriafalls/victoriafalls.cpp | 9 + sys/victoriafalls/victoriafalls_server.cpp | 14 ++ sys/victoriafalls/victoriafalls_server.h | 16 ++ 11 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.cpp create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.h create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.cpp create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.h create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.cpp create mode 100644 sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.h create mode 100644 sys/victoriafalls/victoriafalls_server.cpp create mode 100644 sys/victoriafalls/victoriafalls_server.h diff --git a/sys/victoriafalls/CMakeLists.txt b/sys/victoriafalls/CMakeLists.txt index e5e91e9..964bbab 100644 --- a/sys/victoriafalls/CMakeLists.txt +++ b/sys/victoriafalls/CMakeLists.txt @@ -2,7 +2,9 @@ add_executable(victoriafalls fs/ext2/ext2_block_reader.cpp fs/ext2/ext2_driver.cpp fs/ext2/inode_table.cpp - victoriafalls.cpp) + victoriafalls.cpp + victoriafalls_server.cpp + ) target_include_directories(victoriafalls PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} @@ -12,6 +14,7 @@ target_link_libraries(victoriafalls denali_yunq glacier mammoth + victoriafalls_yunq yellowstone_yunq ) @@ -19,3 +22,5 @@ set_target_properties(victoriafalls PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}" LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}" ) + +yunq_gen(lib/victoriafalls lib victoriafalls) diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq new file mode 100644 index 0000000..a3f37d1 --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq @@ -0,0 +1,12 @@ +interface VFS { + method OpenFile(OpenFileRequest) -> (OpenFileResponse); +} + +message OpenFileRequest { + string path; +} + +message OpenFileResponse { + string path; + capability memory; +} diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.cpp b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.cpp new file mode 100644 index 0000000..21af098 --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.cpp @@ -0,0 +1,41 @@ +// Generated file - DO NOT MODIFY +#include "victoriafalls.yunq.client.h" + +#include +#include +#include + + + + +glcr::ErrorCode VFSClient::OpenFile(const OpenFileRequest& request, OpenFileResponse& response) { + uint64_t buffer_size = kBufferSize; + uint64_t cap_size = kCapBufferSize; + + const uint32_t kSentinel = 0xBEEFDEAD; + buffer_.WriteAt(0, kSentinel); + buffer_.WriteAt(8, 0); + + cap_buffer_.Reset(); + uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_); + buffer_.WriteAt(4, 16 + length); + + z_cap_t reply_port_cap; + RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap)); + + // FIXME: Add a way to zero out the first buffer. + RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr())); + + if (buffer_.At(0) != kSentinel) { + return glcr::INVALID_RESPONSE; + } + + // Check Response Code. + RET_ERR(buffer_.At(8)); + + response.ParseFromBytes(buffer_, 16, cap_buffer_); + + return glcr::OK; +} + + diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.h b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.h new file mode 100644 index 0000000..cf28c33 --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.client.h @@ -0,0 +1,28 @@ +// Generated file - DO NOT MODIFY +#pragma once + +#include +#include +#include +#include + +#include "victoriafalls.yunq.h" + +class VFSClient { + public: + VFSClient(z_cap_t VFS_cap) : endpoint_(VFS_cap) {} + VFSClient(const VFSClient&) = delete; + VFSClient(VFSClient&& other) : endpoint_(other.endpoint_) {other.endpoint_ = 0;}; + + z_cap_t Capability() { return endpoint_; } + + + [[nodiscard]] glcr::ErrorCode OpenFile(const OpenFileRequest& request, OpenFileResponse& response); + + private: + z_cap_t endpoint_; + uint64_t kBufferSize = 0x1000; + glcr::ByteBuffer buffer_{kBufferSize}; + uint64_t kCapBufferSize = 0x10; + glcr::CapBuffer cap_buffer_{kCapBufferSize}; +}; diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.cpp b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.cpp new file mode 100644 index 0000000..5d0d37c --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.cpp @@ -0,0 +1,158 @@ +// Generated file -- DO NOT MODIFY. +#include "victoriafalls.yunq.h" + +namespace { + +const uint64_t header_size = 24; // 4x uint32, 1x uint64 + +struct ExtPointer { + uint32_t offset; + uint32_t length; +}; + +void CheckHeader(const glcr::ByteBuffer& bytes) { + // TODO: Check ident. + // TODO: Parse core size. + // TODO: Parse extension size. + // TODO: Check CRC32 + // TODO: Parse options. +} + +void WriteHeader(glcr::ByteBuffer& bytes, uint64_t offset, uint32_t core_size, uint32_t extension_size) { + bytes.WriteAt(offset + 0, 0xDEADBEEF); // TODO: Chose a more unique ident sequence. + bytes.WriteAt(offset + 4, core_size); + bytes.WriteAt(offset + 8, extension_size); + bytes.WriteAt(offset + 12, 0); // TODO: Calculate CRC32. + bytes.WriteAt(offset + 16, 0); // TODO: Add options. +} + +} // namespace +void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { + CheckHeader(bytes); + // Parse path. + auto path_pointer = bytes.At(offset + header_size + (8 * 0)); + + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); +} + +void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { + CheckHeader(bytes); + // Parse path. + auto path_pointer = bytes.At(offset + header_size + (8 * 0)); + + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); +} + +uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { + uint32_t next_extension = header_size + 8 * 1; + const uint32_t core_size = next_extension; + // Write path. + ExtPointer path_ptr{ + .offset = next_extension, + // FIXME: Check downcast of str length. + .length = (uint32_t)path().length(), + }; + + bytes.WriteStringAt(offset + next_extension, path()); + next_extension += path_ptr.length; + + bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); + + // The next extension pointer is the length of the message. + WriteHeader(bytes, offset, core_size, next_extension); + + return next_extension; +} + +uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { + uint32_t next_extension = header_size + 8 * 1; + const uint32_t core_size = next_extension; + uint64_t next_cap = 0; + // Write path. + ExtPointer path_ptr{ + .offset = next_extension, + // FIXME: Check downcast of str length. + .length = (uint32_t)path().length(), + }; + + bytes.WriteStringAt(offset + next_extension, path()); + next_extension += path_ptr.length; + + bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); + + // The next extension pointer is the length of the message. + WriteHeader(bytes, offset, core_size, next_extension); + + return next_extension; +} +void OpenFileResponse::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) { + CheckHeader(bytes); + // Parse path. + auto path_pointer = bytes.At(offset + header_size + (8 * 0)); + + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + // Parse memory. + // FIXME: Implement in-buffer capabilities for inprocess serialization. + set_memory(0); +} + +void OpenFileResponse::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) { + CheckHeader(bytes); + // Parse path. + auto path_pointer = bytes.At(offset + header_size + (8 * 0)); + + set_path(bytes.StringAt(offset + path_pointer.offset, path_pointer.length)); + // Parse memory. + uint64_t memory_ptr = bytes.At(offset + header_size + (8 * 1)); + + set_memory(caps.At(memory_ptr)); +} + +uint64_t OpenFileResponse::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { + uint32_t next_extension = header_size + 8 * 2; + const uint32_t core_size = next_extension; + // Write path. + ExtPointer path_ptr{ + .offset = next_extension, + // FIXME: Check downcast of str length. + .length = (uint32_t)path().length(), + }; + + bytes.WriteStringAt(offset + next_extension, path()); + next_extension += path_ptr.length; + + bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); + // Write memory. + // FIXME: Implement inbuffer capabilities. + bytes.WriteAt(offset + header_size + (8 * 1), 0); + + // The next extension pointer is the length of the message. + WriteHeader(bytes, offset, core_size, next_extension); + + return next_extension; +} + +uint64_t OpenFileResponse::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { + uint32_t next_extension = header_size + 8 * 2; + const uint32_t core_size = next_extension; + uint64_t next_cap = 0; + // Write path. + ExtPointer path_ptr{ + .offset = next_extension, + // FIXME: Check downcast of str length. + .length = (uint32_t)path().length(), + }; + + bytes.WriteStringAt(offset + next_extension, path()); + next_extension += path_ptr.length; + + bytes.WriteAt(offset + header_size + (8 * 0), path_ptr); + // Write memory. + caps.WriteAt(next_cap, memory()); + bytes.WriteAt(offset + header_size + (8 * 1), next_cap++); + + // The next extension pointer is the length of the message. + WriteHeader(bytes, offset, core_size, next_extension); + + return next_extension; +} \ No newline at end of file diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.h b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.h new file mode 100644 index 0000000..a34b5b4 --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.h @@ -0,0 +1,46 @@ +// Generated file - DO NOT MODIFY +#pragma once + +#include +#include +#include +#include +class OpenFileRequest { + public: + OpenFileRequest() {} + // Delete copy and move until implemented. + OpenFileRequest(const OpenFileRequest&) = delete; + OpenFileRequest(OpenFileRequest&&) = delete; + + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; + glcr::String path() const { return path_; } + void set_path(const glcr::String& value) { path_ = value; } + + private: + glcr::String path_; + +}; +class OpenFileResponse { + public: + OpenFileResponse() {} + // Delete copy and move until implemented. + OpenFileResponse(const OpenFileResponse&) = delete; + OpenFileResponse(OpenFileResponse&&) = delete; + + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); + void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; + glcr::String path() const { return path_; } + void set_path(const glcr::String& value) { path_ = value; } + z_cap_t memory() const { return memory_; } + void set_memory(const z_cap_t& value) { memory_ = value; } + + private: + glcr::String path_; + z_cap_t memory_; + +}; \ No newline at end of file diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.cpp b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.cpp new file mode 100644 index 0000000..aa537ef --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.cpp @@ -0,0 +1,106 @@ +// Generated file -- DO NOT MODIFY. +#include "victoriafalls.yunq.server.h" + +#include +#include + +namespace { + +const uint32_t kSentinel = 0xBEEFDEAD; +const uint32_t kHeaderSize = 0x10; + +void WriteError(glcr::ByteBuffer& buffer, glcr::ErrorCode err) { + buffer.WriteAt(0, kSentinel); + buffer.WriteAt(4, kHeaderSize); + buffer.WriteAt(8, err); +} + +void WriteHeader(glcr::ByteBuffer& buffer, uint64_t message_length) { + buffer.WriteAt(0, kSentinel); + buffer.WriteAt(4, kHeaderSize + message_length); + buffer.WriteAt(8, glcr::OK); +} + +} // namespace + + + +void VFSServerBaseThreadBootstrap(void* server_base) { + ((VFSServerBase*)server_base)->ServerThread(); +} + +glcr::ErrorOr VFSServerBase::CreateClient() { + uint64_t client_cap; + // FIXME: Restrict permissions to send-only here. + RET_ERR(ZCapDuplicate(endpoint_, &client_cap)); + return VFSClient(client_cap); +} + +Thread VFSServerBase::RunServer() { + return Thread(VFSServerBaseThreadBootstrap, this); +} + +void VFSServerBase::ServerThread() { + glcr::ByteBuffer recv_buffer(0x1000); + glcr::CapBuffer recv_cap(0x10); + glcr::ByteBuffer resp_buffer(0x1000); + glcr::CapBuffer resp_cap(0x10); + z_cap_t reply_port_cap; + + while (true) { + uint64_t recv_cap_size = 0x10; + uint64_t recv_buf_size = 0x1000; + recv_cap.Reset(); + glcr::ErrorCode recv_err = ZEndpointRecv(endpoint_, &recv_buf_size, recv_buffer.RawPtr(), &recv_cap_size, recv_cap.RawPtr(), &reply_port_cap); + if (recv_err != glcr::OK) { + dbgln("Error in receive: %x", recv_err); + continue; + } + + uint64_t resp_length = 0; + + glcr::ErrorCode reply_err = glcr::OK; + resp_cap.Reset(); + glcr::ErrorCode err = HandleRequest(recv_buffer, recv_cap, resp_buffer, resp_length, resp_cap); + if (err != glcr::OK) { + WriteError(resp_buffer, err); + reply_err = ZReplyPortSend(reply_port_cap, kHeaderSize, resp_buffer.RawPtr(), 0, nullptr); + } else { + WriteHeader(resp_buffer, resp_length); + reply_err = ZReplyPortSend(reply_port_cap, kHeaderSize + resp_length, resp_buffer.RawPtr(), resp_cap.UsedSlots(), resp_cap.RawPtr()); + } + if (reply_err != glcr::OK) { + dbgln("Error in reply: %x", reply_err); + } + } + +} + +glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request, + const glcr::CapBuffer& req_caps, + glcr::ByteBuffer& response, uint64_t& resp_length, + glcr::CapBuffer& resp_caps) { + if (request.At(0) != kSentinel) { + return glcr::INVALID_ARGUMENT; + } + + uint64_t method_select = request.At(8); + + switch(method_select) { + case 0: { + OpenFileRequest yunq_request; + OpenFileResponse yunq_response; + + yunq_request.ParseFromBytes(request, kHeaderSize, req_caps); + + RET_ERR(HandleOpenFile(yunq_request, yunq_response)); + + resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps); + break; + } + default: { + return glcr::UNIMPLEMENTED; + } + } + return glcr::OK; +} diff --git a/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.h b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.h new file mode 100644 index 0000000..b2d82ab --- /dev/null +++ b/sys/victoriafalls/lib/victoriafalls/victoriafalls.yunq.server.h @@ -0,0 +1,37 @@ +// Generated File -- DO NOT MODIFY. +#pragma once + +#include +#include +#include + +#include "victoriafalls.yunq.h" +#include "victoriafalls.yunq.client.h" + + + +class VFSServerBase { + public: + VFSServerBase(z_cap_t VFS_cap) : endpoint_(VFS_cap) {} + VFSServerBase(const VFSServerBase&) = delete; + VFSServerBase(VFSServerBase&&) = delete; + + glcr::ErrorOr CreateClient(); + + [[nodiscard]] Thread RunServer(); + + + [[nodiscard]] virtual glcr::ErrorCode HandleOpenFile(const OpenFileRequest&, OpenFileResponse&) = 0; + + + private: + z_cap_t endpoint_; + + friend void VFSServerBaseThreadBootstrap(void*); + void ServerThread(); + + [[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, const glcr::CapBuffer& req_caps, + glcr::ByteBuffer& response, uint64_t& resp_length, + glcr::CapBuffer& resp_caps); +}; + diff --git a/sys/victoriafalls/victoriafalls.cpp b/sys/victoriafalls/victoriafalls.cpp index 4bd7442..555a3f6 100644 --- a/sys/victoriafalls/victoriafalls.cpp +++ b/sys/victoriafalls/victoriafalls.cpp @@ -4,6 +4,7 @@ #include #include "fs/ext2/ext2_driver.h" +#include "victoriafalls_server.h" uint64_t main(uint64_t init_cap) { ParseInitPort(init_cap); @@ -20,6 +21,14 @@ uint64_t main(uint64_t init_cap) { ASSIGN_OR_RETURN(Ext2Driver ext2, Ext2Driver::Init(glcr::Move(denali))); ASSIGN_OR_RETURN(Inode * root, ext2.GetInode(2)); + + ASSIGN_OR_RETURN(auto server, VFSServer::Create()); + + RegisterEndpointRequest req; + req.set_endpoint_name("victoriafalls"); + ASSIGN_OR_RETURN(auto client, server->CreateClient()); + req.set_endpoint_capability(client.Capability()); + check(yellowstone.RegisterEndpoint(req, empty)); check(ext2.ProbeDirectory(root)); return 0; diff --git a/sys/victoriafalls/victoriafalls_server.cpp b/sys/victoriafalls/victoriafalls_server.cpp new file mode 100644 index 0000000..04041ce --- /dev/null +++ b/sys/victoriafalls/victoriafalls_server.cpp @@ -0,0 +1,14 @@ +#include "victoriafalls_server.h" + +#include + +glcr::ErrorOr> VFSServer::Create() { + z_cap_t endpoint_cap; + RET_ERR(ZEndpointCreate(&endpoint_cap)); + return glcr::UniquePtr(new VFSServer(endpoint_cap)); +} + +glcr::ErrorCode VFSServer::HandleOpenFile(const OpenFileRequest&, + OpenFileResponse&) { + return glcr::OK; +} diff --git a/sys/victoriafalls/victoriafalls_server.h b/sys/victoriafalls/victoriafalls_server.h new file mode 100644 index 0000000..64dd89a --- /dev/null +++ b/sys/victoriafalls/victoriafalls_server.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "victoriafalls/victoriafalls.yunq.server.h" + +class VFSServer : public VFSServerBase { + public: + static glcr::ErrorOr> Create(); + + glcr::ErrorCode HandleOpenFile(const OpenFileRequest&, + OpenFileResponse&) override; + + private: + VFSServer(z_cap_t endpoint_cap) : VFSServerBase(endpoint_cap) {} +};