Compare commits

...

2 Commits

37 changed files with 912 additions and 229 deletions

View File

@ -14,6 +14,9 @@ class ByteBuffer {
~ByteBuffer() { delete[] buffer_; } ~ByteBuffer() { delete[] buffer_; }
uint8_t* RawPtr() { return buffer_; }
const uint8_t* RawPtr() const { return buffer_; }
template <typename T> template <typename T>
void WriteAt(uint64_t offset, const T& object) { void WriteAt(uint64_t offset, const T& object) {
// FIXME: Add bounds check here. // FIXME: Add bounds check here.

View File

@ -13,12 +13,23 @@ class CapBuffer {
~CapBuffer() { delete[] buffer_; } ~CapBuffer() { delete[] buffer_; }
uint64_t* RawPtr() { return buffer_; }
uint64_t UsedSlots() { return used_slots_; }
uint64_t At(uint64_t offset) const { return buffer_[offset]; } uint64_t At(uint64_t offset) const { return buffer_[offset]; }
void WriteAt(uint64_t offset, uint64_t cap) { buffer_[offset] = cap; } void WriteAt(uint64_t offset, uint64_t cap) {
buffer_[offset] = cap;
// This is fairly hacky considering we pass out the raw ptr.
if (used_slots_ < (offset + 1)) {
used_slots_ = offset + 1;
}
}
private: private:
uint64_t* buffer_; uint64_t* buffer_;
uint64_t used_slots_ = 0;
}; };
} // namespace glcr } // namespace glcr

View File

@ -6,7 +6,7 @@
namespace { namespace {
class NaiveAllocator { class NaiveAllocator {
public: public:
constexpr static uint64_t kSize = 0x4000; constexpr static uint64_t kSize = 0x10000;
NaiveAllocator() {} NaiveAllocator() {}
bool is_init() { return next_addr_ != 0; } bool is_init() { return next_addr_ != 0; }
void Init() { void Init() {
@ -23,6 +23,7 @@ class NaiveAllocator {
uint64_t addr = next_addr_; uint64_t addr = next_addr_;
next_addr_ += size; next_addr_ += size;
if (next_addr_ >= max_addr_) { if (next_addr_ >= max_addr_) {
ZProcessExit(0xBEEF);
return 0; return 0;
} }
return reinterpret_cast<void*>(addr); return reinterpret_cast<void*>(addr);

View File

@ -5,5 +5,5 @@
#include "mammoth/endpoint_client.h" #include "mammoth/endpoint_client.h"
glcr::ErrorCode SpawnProcessFromElfRegion( glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program,
uint64_t program, glcr::UniquePtr<EndpointClient> client); z_cap_t yellowstone_client);

View File

@ -96,8 +96,8 @@ uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) {
} // namespace } // namespace
glcr::ErrorCode SpawnProcessFromElfRegion( glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program,
uint64_t program, glcr::UniquePtr<EndpointClient> client) { z_cap_t yellowstone_client) {
uint64_t proc_cap; uint64_t proc_cap;
uint64_t as_cap; uint64_t as_cap;
uint64_t foreign_port_id; uint64_t foreign_port_id;
@ -125,7 +125,7 @@ glcr::ErrorCode SpawnProcessFromElfRegion(
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, proc_cap)); RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, proc_cap));
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_VMAS, as_cap)); RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_VMAS, as_cap));
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_ENDPOINT, client->GetCap())); RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_ENDPOINT, yellowstone_client));
#if MAM_PROC_DEBUG #if MAM_PROC_DEBUG
dbgln("Thread start"); dbgln("Thread start");

View File

@ -14,7 +14,7 @@ target_include_directories(denali
target_link_libraries(denali target_link_libraries(denali
glacier glacier
mammoth mammoth
yellowstone_stub yellowstone_yunq
) )
set_target_properties(denali PROPERTIES set_target_properties(denali PROPERTIES

View File

@ -5,7 +5,7 @@
#include <mammoth/port_client.h> #include <mammoth/port_client.h>
#include <stdint.h> #include <stdint.h>
#include <yellowstone.h> #include <yellowstone.h>
#include <yellowstone_stub.h> #include <yellowstone/yellowstone.yunq.client.h>
#include "ahci/ahci_driver.h" #include "ahci/ahci_driver.h"
#include "denali_server.h" #include "denali_server.h"
@ -15,8 +15,12 @@ uint64_t main(uint64_t init_port_cap) {
glcr::UniquePtr<EndpointClient> yellowstone = glcr::UniquePtr<EndpointClient> yellowstone =
EndpointClient::AdoptEndpoint(gInitEndpointCap); EndpointClient::AdoptEndpoint(gInitEndpointCap);
YellowstoneStub stub(gInitEndpointCap); YellowstoneClient stub(gInitEndpointCap);
ASSIGN_OR_RETURN(MappedMemoryRegion ahci_region, stub.GetAhciConfig()); Empty empty;
AhciInfo ahci;
RET_ERR(stub.GetAhciInfo(empty, ahci));
MappedMemoryRegion ahci_region =
MappedMemoryRegion::FromCapability(ahci.ahci_region());
ASSIGN_OR_RETURN(auto driver, AhciDriver::Init(ahci_region)); ASSIGN_OR_RETURN(auto driver, AhciDriver::Init(ahci_region));
ASSIGN_OR_RETURN(glcr::UniquePtr<DenaliServer> server, ASSIGN_OR_RETURN(glcr::UniquePtr<DenaliServer> server,
@ -24,7 +28,14 @@ uint64_t main(uint64_t init_port_cap) {
ASSIGN_OR_RETURN(glcr::UniquePtr<EndpointClient> client, ASSIGN_OR_RETURN(glcr::UniquePtr<EndpointClient> client,
server->CreateClient()); server->CreateClient());
check(stub.Register("denali", *client));
RegisterInfo reg;
Empty empty2;
check(stub.GetRegister(empty2, reg));
PortClient register_port = PortClient::AdoptPort(reg.register_port());
check(register_port.WriteString("denali", client->GetCap()));
Thread server_thread = server->RunServer(); Thread server_thread = server->RunServer();

View File

@ -11,7 +11,7 @@ target_include_directories(victoriafalls
target_link_libraries(victoriafalls target_link_libraries(victoriafalls
glacier glacier
mammoth mammoth
yellowstone_stub yellowstone_yunq
) )
set_target_properties(victoriafalls PROPERTIES set_target_properties(victoriafalls PROPERTIES

View File

@ -1,5 +1,7 @@
#include "fs/ext2/ext2_block_reader.h" #include "fs/ext2/ext2_block_reader.h"
#include "mammoth/debug.h"
glcr::ErrorOr<glcr::SharedPtr<Ext2BlockReader>> Ext2BlockReader::Init( glcr::ErrorOr<glcr::SharedPtr<Ext2BlockReader>> Ext2BlockReader::Init(
ScopedDenaliClient&& denali) { ScopedDenaliClient&& denali) {
// Read 1024 bytes from 1024 offset. // Read 1024 bytes from 1024 offset.

View File

@ -1,6 +1,6 @@
#include <mammoth/debug.h> #include <mammoth/debug.h>
#include <mammoth/init.h> #include <mammoth/init.h>
#include <yellowstone_stub.h> #include <yellowstone/yellowstone.yunq.client.h>
#include "fs/ext2/ext2_driver.h" #include "fs/ext2/ext2_driver.h"
@ -9,8 +9,14 @@ uint64_t main(uint64_t init_cap) {
dbgln("VFs Started"); dbgln("VFs Started");
YellowstoneStub yellowstone(gInitEndpointCap); YellowstoneClient yellowstone(gInitEndpointCap);
ASSIGN_OR_RETURN(ScopedDenaliClient denali, yellowstone.GetDenali()); Empty empty;
DenaliInfo denali_info;
RET_ERR(yellowstone.GetDenali(empty, denali_info));
dbgln("LBA (recv): %u", denali_info.lba_offset());
ScopedDenaliClient denali(
EndpointClient::AdoptEndpoint(denali_info.denali_endpoint()),
denali_info.device_id(), denali_info.lba_offset());
ASSIGN_OR_RETURN(Ext2Driver ext2, Ext2Driver::Init(glcr::Move(denali))); ASSIGN_OR_RETURN(Ext2Driver ext2, Ext2Driver::Init(glcr::Move(denali)));
ASSIGN_OR_RETURN(Inode * root, ext2.GetInode(2)); ASSIGN_OR_RETURN(Inode * root, ext2.GetInode(2));

View File

@ -12,6 +12,7 @@ target_link_libraries(yellowstone
mammoth mammoth
glacier glacier
denali_stub denali_stub
yellowstone_yunq
) )
set_target_properties(yellowstone PROPERTIES set_target_properties(yellowstone PROPERTIES
@ -20,20 +21,22 @@ set_target_properties(yellowstone PROPERTIES
) )
add_library(yellowstone_stub add_library(yellowstone_yunq
stub/yellowstone_stub.cpp include/yellowstone/yellowstone.yunq.cpp
include/yellowstone/yellowstone.yunq.client.cpp
include/yellowstone/yellowstone.yunq.server.cpp
) )
target_include_directories(yellowstone_stub target_include_directories(yellowstone_yunq
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(yellowstone_stub target_link_libraries(yellowstone_yunq
denali_stub denali_stub
mammoth mammoth
) )
set_target_properties(yellowstone_stub PROPERTIES set_target_properties(yellowstone_yunq PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}" COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}" LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
) )

View File

@ -0,0 +1,24 @@
interface Yellowstone {
method GetRegister(Empty) -> (RegisterInfo);
method GetAhciInfo(Empty) -> (AhciInfo);
method GetDenali(Empty) -> (DenaliInfo);
}
message Empty {
}
message RegisterInfo {
capability register_port;
}
message AhciInfo {
capability ahci_region;
u64 region_length;
}
message DenaliInfo {
capability denali_endpoint;
u64 device_id;
u64 lba_offset;
}

View File

@ -0,0 +1,105 @@
// Generated file - DO NOT MODIFY
#include "yellowstone.yunq.client.h"
#include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h>
#include <zcall.h>
glcr::ErrorCode YellowstoneClient::GetRegister(const Empty& request, RegisterInfo& response) {
uint64_t buffer_size = kBufferSize;
uint64_t cap_size = kCapBufferSize;
const uint32_t kSentinel = 0xBEEFDEAD;
buffer_.WriteAt<uint32_t>(0, kSentinel);
buffer_.WriteAt<uint64_t>(8, 0);
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap;
// FIXME: We need to be able to send capabilities via endpoint call.
RET_ERR(ZEndpointSend(endpoint_, 16 + length, 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<uint32_t>(0) != kSentinel) {
return glcr::INVALID_RESPONSE;
}
// Check Response Code.
RET_ERR(buffer_.At<uint64_t>(8));
response.ParseFromBytes(buffer_, 16, cap_buffer_);
return glcr::OK;
}
glcr::ErrorCode YellowstoneClient::GetAhciInfo(const Empty& request, AhciInfo& response) {
uint64_t buffer_size = kBufferSize;
uint64_t cap_size = kCapBufferSize;
const uint32_t kSentinel = 0xBEEFDEAD;
buffer_.WriteAt<uint32_t>(0, kSentinel);
buffer_.WriteAt<uint64_t>(8, 1);
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap;
// FIXME: We need to be able to send capabilities via endpoint call.
RET_ERR(ZEndpointSend(endpoint_, 16 + length, 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<uint32_t>(0) != kSentinel) {
return glcr::INVALID_RESPONSE;
}
// Check Response Code.
RET_ERR(buffer_.At<uint64_t>(8));
response.ParseFromBytes(buffer_, 16, cap_buffer_);
return glcr::OK;
}
glcr::ErrorCode YellowstoneClient::GetDenali(const Empty& request, DenaliInfo& response) {
uint64_t buffer_size = kBufferSize;
uint64_t cap_size = kCapBufferSize;
const uint32_t kSentinel = 0xBEEFDEAD;
buffer_.WriteAt<uint32_t>(0, kSentinel);
buffer_.WriteAt<uint64_t>(8, 2);
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap;
// FIXME: We need to be able to send capabilities via endpoint call.
RET_ERR(ZEndpointSend(endpoint_, 16 + length, 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<uint32_t>(0) != kSentinel) {
return glcr::INVALID_RESPONSE;
}
// Check Response Code.
RET_ERR(buffer_.At<uint64_t>(8));
response.ParseFromBytes(buffer_, 16, cap_buffer_);
return glcr::OK;
}

View File

@ -0,0 +1,32 @@
// Generated file - DO NOT MODIFY
#pragma once
#include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h>
#include <glacier/status/error.h>
#include <ztypes.h>
#include "yellowstone.yunq.h"
class YellowstoneClient {
public:
YellowstoneClient(z_cap_t Yellowstone_cap) : endpoint_(Yellowstone_cap) {}
YellowstoneClient(const YellowstoneClient&) = delete;
YellowstoneClient(YellowstoneClient&& other) : endpoint_(other.endpoint_) {other.endpoint_ = 0;};
z_cap_t Capability() { return endpoint_; }
[[nodiscard]] glcr::ErrorCode GetRegister(const Empty& request, RegisterInfo& response);
[[nodiscard]] glcr::ErrorCode GetAhciInfo(const Empty& request, AhciInfo& response);
[[nodiscard]] glcr::ErrorCode GetDenali(const Empty& request, DenaliInfo& response);
private:
z_cap_t endpoint_;
uint64_t kBufferSize = 0x1000;
glcr::ByteBuffer buffer_{kBufferSize};
uint64_t kCapBufferSize = 0x10;
glcr::CapBuffer cap_buffer_{kCapBufferSize};
};

View File

@ -0,0 +1,204 @@
// Generated file -- DO NOT MODIFY.
#include "yellowstone.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<uint32_t>(offset + 0, 0xDEADBEEF); // TODO: Chose a more unique ident sequence.
bytes.WriteAt<uint32_t>(offset + 4, core_size);
bytes.WriteAt<uint32_t>(offset + 8, extension_size);
bytes.WriteAt<uint32_t>(offset + 12, 0); // TODO: Calculate CRC32.
bytes.WriteAt<uint64_t>(offset + 16, 0); // TODO: Add options.
}
} // namespace
void Empty::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) {
CheckHeader(bytes);
}
void Empty::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) {
CheckHeader(bytes);
}
uint64_t Empty::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * 0;
const uint32_t core_size = next_extension;
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
uint64_t Empty::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
uint32_t next_extension = header_size + 8 * 0;
const uint32_t core_size = next_extension;
uint64_t next_cap = 0;
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
void RegisterInfo::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) {
CheckHeader(bytes);
// Parse register_port.
// FIXME: Implement in-buffer capabilities for inprocess serialization.
set_register_port(0);
}
void RegisterInfo::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) {
CheckHeader(bytes);
// Parse register_port.
uint64_t register_port_ptr = bytes.At<uint64_t>(offset + header_size + (8 * 0));
set_register_port(caps.At(register_port_ptr));
}
uint64_t RegisterInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * 1;
const uint32_t core_size = next_extension;
// Write register_port.
// FIXME: Implement inbuffer capabilities.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 0), 0);
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
uint64_t RegisterInfo::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 register_port.
caps.WriteAt(next_cap, register_port());
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 0), next_cap++);
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
void AhciInfo::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) {
CheckHeader(bytes);
// Parse ahci_region.
// FIXME: Implement in-buffer capabilities for inprocess serialization.
set_ahci_region(0);
// Parse region_length.
set_region_length(bytes.At<uint64_t>(offset + header_size + (8 * 1)));
}
void AhciInfo::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) {
CheckHeader(bytes);
// Parse ahci_region.
uint64_t ahci_region_ptr = bytes.At<uint64_t>(offset + header_size + (8 * 0));
set_ahci_region(caps.At(ahci_region_ptr));
// Parse region_length.
set_region_length(bytes.At<uint64_t>(offset + header_size + (8 * 1)));
}
uint64_t AhciInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * 2;
const uint32_t core_size = next_extension;
// Write ahci_region.
// FIXME: Implement inbuffer capabilities.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 0), 0);
// Write region_length.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 1), region_length());
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
uint64_t AhciInfo::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 ahci_region.
caps.WriteAt(next_cap, ahci_region());
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 0), next_cap++);
// Write region_length.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 1), region_length());
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
void DenaliInfo::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset) {
CheckHeader(bytes);
// Parse denali_endpoint.
// FIXME: Implement in-buffer capabilities for inprocess serialization.
set_denali_endpoint(0);
// Parse device_id.
set_device_id(bytes.At<uint64_t>(offset + header_size + (8 * 1)));
// Parse lba_offset.
set_lba_offset(bytes.At<uint64_t>(offset + header_size + (8 * 2)));
}
void DenaliInfo::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const glcr::CapBuffer& caps) {
CheckHeader(bytes);
// Parse denali_endpoint.
uint64_t denali_endpoint_ptr = bytes.At<uint64_t>(offset + header_size + (8 * 0));
set_denali_endpoint(caps.At(denali_endpoint_ptr));
// Parse device_id.
set_device_id(bytes.At<uint64_t>(offset + header_size + (8 * 1)));
// Parse lba_offset.
set_lba_offset(bytes.At<uint64_t>(offset + header_size + (8 * 2)));
}
uint64_t DenaliInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * 3;
const uint32_t core_size = next_extension;
// Write denali_endpoint.
// FIXME: Implement inbuffer capabilities.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 0), 0);
// Write device_id.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 1), device_id());
// Write lba_offset.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 2), lba_offset());
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}
uint64_t DenaliInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
uint32_t next_extension = header_size + 8 * 3;
const uint32_t core_size = next_extension;
uint64_t next_cap = 0;
// Write denali_endpoint.
caps.WriteAt(next_cap, denali_endpoint());
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 0), next_cap++);
// Write device_id.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 1), device_id());
// Write lba_offset.
bytes.WriteAt<uint64_t>(offset + header_size + (8 * 2), lba_offset());
// The next extension pointer is the length of the message.
WriteHeader(bytes, offset, core_size, next_extension);
return next_extension;
}

View File

@ -0,0 +1,85 @@
// Generated file - DO NOT MODIFY
#pragma once
#include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h>
#include <glacier/string/string.h>
#include <ztypes.h>
class Empty {
public:
Empty() {}
// Delete copy and move until implemented.
Empty(const Empty&) = delete;
Empty(Empty&&) = 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;
private:
};
class RegisterInfo {
public:
RegisterInfo() {}
// Delete copy and move until implemented.
RegisterInfo(const RegisterInfo&) = delete;
RegisterInfo(RegisterInfo&&) = 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;
z_cap_t register_port() const { return register_port_; }
void set_register_port(const z_cap_t& value) { register_port_ = value; }
private:
z_cap_t register_port_;
};
class AhciInfo {
public:
AhciInfo() {}
// Delete copy and move until implemented.
AhciInfo(const AhciInfo&) = delete;
AhciInfo(AhciInfo&&) = 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;
z_cap_t ahci_region() const { return ahci_region_; }
void set_ahci_region(const z_cap_t& value) { ahci_region_ = value; }
uint64_t region_length() const { return region_length_; }
void set_region_length(const uint64_t& value) { region_length_ = value; }
private:
z_cap_t ahci_region_;
uint64_t region_length_;
};
class DenaliInfo {
public:
DenaliInfo() {}
// Delete copy and move until implemented.
DenaliInfo(const DenaliInfo&) = delete;
DenaliInfo(DenaliInfo&&) = 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;
z_cap_t denali_endpoint() const { return denali_endpoint_; }
void set_denali_endpoint(const z_cap_t& value) { denali_endpoint_ = value; }
uint64_t device_id() const { return device_id_; }
void set_device_id(const uint64_t& value) { device_id_ = value; }
uint64_t lba_offset() const { return lba_offset_; }
void set_lba_offset(const uint64_t& value) { lba_offset_ = value; }
private:
z_cap_t denali_endpoint_;
uint64_t device_id_;
uint64_t lba_offset_;
};

View File

@ -0,0 +1,124 @@
// Generated file -- DO NOT MODIFY.
#include "yellowstone.yunq.server.h"
#include <mammoth/debug.h>
#include <zcall.h>
namespace {
const uint32_t kSentinel = 0xBEEFDEAD;
const uint32_t kHeaderSize = 0x10;
void WriteError(glcr::ByteBuffer& buffer, glcr::ErrorCode err) {
buffer.WriteAt<uint32_t>(0, kSentinel);
buffer.WriteAt<uint32_t>(4, kHeaderSize);
buffer.WriteAt<uint64_t>(8, err);
}
void WriteHeader(glcr::ByteBuffer& buffer, uint64_t message_length) {
buffer.WriteAt<uint32_t>(0, kSentinel);
buffer.WriteAt<uint32_t>(4, kHeaderSize + message_length);
buffer.WriteAt<uint64_t>(8, glcr::OK);
}
} // namespace
void YellowstoneServerBaseThreadBootstrap(void* server_base) {
((YellowstoneServerBase*)server_base)->ServerThread();
}
glcr::ErrorOr<YellowstoneClient> YellowstoneServerBase::CreateClient() {
uint64_t client_cap;
// FIXME: Restrict permissions to send-only here.
RET_ERR(ZCapDuplicate(endpoint_, &client_cap));
return YellowstoneClient(client_cap);
}
Thread YellowstoneServerBase::RunServer() {
return Thread(YellowstoneServerBaseThreadBootstrap, this);
}
void YellowstoneServerBase::ServerThread() {
glcr::ByteBuffer recv_buffer(0x1000);
glcr::ByteBuffer resp_buffer(0x1000);
uint64_t resp_cap_size = 0x10;
glcr::CapBuffer resp_cap(resp_cap_size);
z_cap_t reply_port_cap;
while (true) {
uint64_t recv_buf_size = 0x1000;
glcr::ErrorCode recv_err = ZEndpointRecv(endpoint_, &recv_buf_size, recv_buffer.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;
glcr::ErrorCode err = HandleRequest(recv_buffer, 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", recv_err);
}
}
}
glcr::ErrorCode YellowstoneServerBase::HandleRequest(const glcr::ByteBuffer& request,
glcr::ByteBuffer& response, uint64_t& resp_length,
glcr::CapBuffer& resp_caps) {
if (request.At<uint32_t>(0) != kSentinel) {
return glcr::INVALID_ARGUMENT;
}
uint64_t method_select = request.At<uint64_t>(8);
switch(method_select) {
case 0: {
Empty yunq_request;
RegisterInfo yunq_response;
yunq_request.ParseFromBytes(request, kHeaderSize);
RET_ERR(HandleGetRegister(yunq_request, yunq_response));
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
break;
}
case 1: {
Empty yunq_request;
AhciInfo yunq_response;
yunq_request.ParseFromBytes(request, kHeaderSize);
RET_ERR(HandleGetAhciInfo(yunq_request, yunq_response));
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
break;
}
case 2: {
Empty yunq_request;
DenaliInfo yunq_response;
yunq_request.ParseFromBytes(request, kHeaderSize);
RET_ERR(HandleGetDenali(yunq_request, yunq_response));
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
break;
}
default: {
return glcr::UNIMPLEMENTED;
}
}
return glcr::OK;
}

View File

@ -0,0 +1,41 @@
// Generated File -- DO NOT MODIFY.
#pragma once
#include <glacier/status/error_or.h>
#include <mammoth/thread.h>
#include <ztypes.h>
#include "yellowstone.yunq.h"
#include "yellowstone.yunq.client.h"
class YellowstoneServerBase {
public:
YellowstoneServerBase(z_cap_t Yellowstone_cap) : endpoint_(Yellowstone_cap) {}
YellowstoneServerBase(const YellowstoneServerBase&) = delete;
YellowstoneServerBase(YellowstoneServerBase&&) = delete;
glcr::ErrorOr<YellowstoneClient> CreateClient();
[[nodiscard]] Thread RunServer();
[[nodiscard]] virtual glcr::ErrorCode HandleGetRegister(const Empty&, RegisterInfo&) = 0;
[[nodiscard]] virtual glcr::ErrorCode HandleGetAhciInfo(const Empty&, AhciInfo&) = 0;
[[nodiscard]] virtual glcr::ErrorCode HandleGetDenali(const Empty&, DenaliInfo&) = 0;
private:
z_cap_t endpoint_;
friend void YellowstoneServerBaseThreadBootstrap(void*);
void ServerThread();
[[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, glcr::ByteBuffer& response,
uint64_t& resp_length,
glcr::CapBuffer& resp_caps);
};

View File

@ -1,48 +0,0 @@
#include "include/yellowstone_stub.h"
#include <denali/denali_client.h>
#include "include/yellowstone.h"
YellowstoneStub::YellowstoneStub(z_cap_t yellowstone_cap)
: yellowstone_stub_(EndpointClient::AdoptEndpoint(yellowstone_cap)) {}
glcr::ErrorOr<MappedMemoryRegion> YellowstoneStub::GetAhciConfig() {
YellowstoneGetReq req{
.type = kYellowstoneGetAhci,
};
ASSIGN_OR_RETURN(
auto resp_cap_pair,
(yellowstone_stub_->CallEndpointGetCap<YellowstoneGetReq,
YellowstoneGetAhciResp>(req)));
return MappedMemoryRegion::FromCapability(resp_cap_pair.second());
}
glcr::ErrorOr<ScopedDenaliClient> YellowstoneStub::GetDenali() {
YellowstoneGetReq req{
.type = kYellowstoneGetDenali,
};
ASSIGN_OR_RETURN(
auto resp_and_cap,
(yellowstone_stub_->CallEndpointGetCap<YellowstoneGetReq,
YellowstoneGetDenaliResp>(req)));
return ScopedDenaliClient(
EndpointClient::AdoptEndpoint(resp_and_cap.second()), 0,
resp_and_cap.first().lba_offset);
}
glcr::ErrorCode YellowstoneStub::Register(glcr::String name,
const EndpointClient& client) {
if (register_port_.empty()) {
YellowstoneGetReq req{
.type = kYellowstoneGetRegistration,
};
ASSIGN_OR_RETURN(
auto resp_cap,
(yellowstone_stub_->CallEndpointGetCap<
YellowstoneGetReq, YellowstoneGetRegistrationResp>(req)));
register_port_ = PortClient::AdoptPort(resp_cap.second());
}
return register_port_.WriteString(name, client.GetCap());
}

View File

@ -18,9 +18,8 @@ uint64_t main(uint64_t port_cap) {
uint64_t vaddr; uint64_t vaddr;
check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr)); check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr));
ASSIGN_OR_RETURN(glcr::UniquePtr<EndpointClient> client, ASSIGN_OR_RETURN(YellowstoneClient client, server->CreateClient());
server->CreateClient()); check(SpawnProcessFromElfRegion(vaddr, client.Capability()));
check(SpawnProcessFromElfRegion(vaddr, glcr::Move(client)));
check(server_thread.Join()); check(server_thread.Join());
check(registration_thread.Join()); check(registration_thread.Join());

View File

@ -43,54 +43,36 @@ glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> YellowstoneServer::Create() {
} }
YellowstoneServer::YellowstoneServer(z_cap_t endpoint_cap, PortServer port) YellowstoneServer::YellowstoneServer(z_cap_t endpoint_cap, PortServer port)
: EndpointServer(endpoint_cap), register_port_(port) {} : YellowstoneServerBase(endpoint_cap), register_port_(port) {}
Thread YellowstoneServer::RunRegistration() { Thread YellowstoneServer::RunRegistration() {
return Thread(RegistrationThreadBootstrap, this); return Thread(RegistrationThreadBootstrap, this);
} }
glcr::ErrorCode YellowstoneServer::HandleRequest(RequestContext& request, glcr::ErrorCode YellowstoneServer::HandleGetAhciInfo(const Empty&,
ResponseContext& response) { AhciInfo& info) {
switch (request.request_id()) { info.set_ahci_region(pci_reader_.GetAhciVmmo());
case kYellowstoneGetAhci: { info.set_region_length(kPcieConfigurationSize);
dbgln("Yellowstone::GetAHCI"); return glcr::OK;
YellowstoneGetAhciResp resp{ }
.type = kYellowstoneGetAhci,
.ahci_length = kPcieConfigurationSize, glcr::ErrorCode YellowstoneServer::HandleGetDenali(const Empty&,
}; DenaliInfo& info) {
z_cap_t vmmo_cap = pci_reader_.GetAhciVmmo(); z_cap_t new_denali;
RET_ERR( check(ZCapDuplicate(denali_cap_, &new_denali));
response.WriteStructWithCap<YellowstoneGetAhciResp>(resp, vmmo_cap)); info.set_denali_endpoint(new_denali);
break; info.set_device_id(device_id_);
} info.set_lba_offset(lba_offset_);
case kYellowstoneGetRegistration: { return glcr::OK;
dbgln("Yellowstone::GetRegistration"); }
auto client_or = register_port_.CreateClient(); glcr::ErrorCode YellowstoneServer::HandleGetRegister(const Empty&,
if (!client_or.ok()) { RegisterInfo& info) {
check(client_or.error()); auto client_or = register_port_.CreateClient();
} if (!client_or.ok()) {
YellowstoneGetRegistrationResp resp; dbgln("Error creating register client: %u", client_or.error());
uint64_t reg_cap = client_or.value().cap(); return glcr::INTERNAL;
RET_ERR(response.WriteStructWithCap(resp, reg_cap));
break;
}
case kYellowstoneGetDenali: {
dbgln("Yellowstone::GetDenali");
z_cap_t new_denali;
check(ZCapDuplicate(denali_cap_, &new_denali));
YellowstoneGetDenaliResp resp{
.type = kYellowstoneGetDenali,
.device_id = device_id_,
.lba_offset = lba_offset_,
};
RET_ERR(response.WriteStructWithCap(resp, new_denali));
break;
}
default:
dbgln("Unknown request type: %x", request.request_id());
return glcr::UNIMPLEMENTED;
break;
} }
info.set_register_port(client_or.value().cap());
return glcr::OK; return glcr::OK;
} }
@ -118,7 +100,7 @@ void YellowstoneServer::RegistrationThread() {
if (!client_or.ok()) { if (!client_or.ok()) {
check(client_or.error()); check(client_or.error());
} }
check(SpawnProcessFromElfRegion(vaddr, glcr::Move(client_or.value()))); check(SpawnProcessFromElfRegion(vaddr, client_or.value().Capability()));
continue; continue;
} }

View File

@ -7,8 +7,9 @@
#include <mammoth/thread.h> #include <mammoth/thread.h>
#include "hw/pcie.h" #include "hw/pcie.h"
#include "include/yellowstone/yellowstone.yunq.server.h"
class YellowstoneServer : public EndpointServer { class YellowstoneServer : public YellowstoneServerBase {
public: public:
static glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> Create(); static glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> Create();
@ -16,8 +17,9 @@ class YellowstoneServer : public EndpointServer {
void RegistrationThread(); void RegistrationThread();
virtual glcr::ErrorCode HandleRequest(RequestContext& request, glcr::ErrorCode HandleGetAhciInfo(const Empty&, AhciInfo&) override;
ResponseContext& response) override; glcr::ErrorCode HandleGetDenali(const Empty&, DenaliInfo&) override;
glcr::ErrorCode HandleGetRegister(const Empty&, RegisterInfo&) override;
private: private:
// FIXME: Separate this to its own service. // FIXME: Separate this to its own service.

View File

@ -3,41 +3,37 @@
#include <glacier/buffer/byte_buffer.h> #include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h> #include <glacier/buffer/cap_buffer.h>
#include <zcall.h>
{% for interface in interfaces %} {% for interface in interfaces %}
{% for method in interface.methods %} {% for method in interface.methods %}
glcr::ErrorCode {{method.name}}(const {{method.request}}& request, {{method.response}}& response) { glcr::ErrorCode {{interface.name}}Client::{{method.name}}(const {{method.request}}& request, {{method.response}}& response) {
uint64_t buffer_size = 0x1000; uint64_t buffer_size = kBufferSize;
// FIXME: Maybe raise this limit. uint64_t cap_size = kCapBufferSize;
uint64_t cap_size = 100;
glcr::ByteBuffer buffer(buffer_size);
glcr::CapBuffer caps(cap_size);
const uint32_t kSentinel = 0xBEEFDEAD; const uint32_t kSentinel = 0xBEEFDEAD;
buffer.WriteAt<uint32_t>(0, kSentinel); buffer_.WriteAt<uint32_t>(0, kSentinel);
buffer.WriteAt<uint64_t>(8, {method_number}); buffer_.WriteAt<uint64_t>(8, {{loop.index0}});
uint64_t length = request.SerializeToBytes(buffer, /*offset=*/16, caps); uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
buffer.WriteAt<uint32_t>(4, 16 + length); buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap; z_cap_t reply_port_cap;
// FIXME: We need to be able to send capabilities via endpoint call. // FIXME: We need to be able to send capabilities via endpoint call.
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer.RawPtr())); RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), &reply_port_cap));
// FIXME: Add a way to zero out the first buffer. // FIXME: Add a way to zero out the first buffer.
glcr::ByteBuffer recv_buffer(buffer_size); RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
glcr::CapBuffer recv_caps(cap_size);
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, recv_buffer.RawPtr(), &cap_size, recv_caps.RawPtr()));
if (recv_buffer.At<uint32_t>(0) != kSentinel) { if (buffer_.At<uint32_t>(0) != kSentinel) {
return glcr::INVALID_RESPONSE; return glcr::INVALID_RESPONSE;
} }
// Check Response Code. // Check Response Code.
RET_ERR(recv_buffer.At<uint64_t>(8)); RET_ERR(buffer_.At<uint64_t>(8));
response.ParseFromBytes(recv_buffer, 16, recv_caps); response.ParseFromBytes(buffer_, 16, cap_buffer_);
return glcr::OK; return glcr::OK;
} }

View File

@ -1,6 +1,9 @@
// Generated file - DO NOT MODIFY // Generated file - DO NOT MODIFY
#pragma once #pragma once
#include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h>
#include <glacier/status/error.h>
#include <ztypes.h> #include <ztypes.h>
#include "{{file}}.h" #include "{{file}}.h"
@ -10,12 +13,19 @@ class {{interface.name}}Client {
public: public:
{{interface.name}}Client(z_cap_t {{interface.name}}_cap) : endpoint_({{interface.name}}_cap) {} {{interface.name}}Client(z_cap_t {{interface.name}}_cap) : endpoint_({{interface.name}}_cap) {}
{{interface.name}}Client(const {{interface.name}}Client&) = delete; {{interface.name}}Client(const {{interface.name}}Client&) = delete;
{{interface.name}}Client({{interface.name}}Client&&) = delete; {{interface.name}}Client({{interface.name}}Client&& other) : endpoint_(other.endpoint_) {other.endpoint_ = 0;};
z_cap_t Capability() { return endpoint_; }
{% for method in interface.methods %} {% for method in interface.methods %}
[[nodiscard]] glcr::ErrorCode {{method.name}}(const {{method.request}}& request, {{method.response}}& response); [[nodiscard]] glcr::ErrorCode {{method.name}}(const {{method.request}}& request, {{method.response}}& response);
{% endfor %} {% endfor %}
private: private:
z_cap_t endpoint_; z_cap_t endpoint_;
uint64_t kBufferSize = 0x1000;
glcr::ByteBuffer buffer_{kBufferSize};
uint64_t kCapBufferSize = 0x10;
glcr::CapBuffer cap_buffer_{kCapBufferSize};
}; };
{%- endfor %} {%- endfor %}

View File

@ -3,41 +3,37 @@
#include <glacier/buffer/byte_buffer.h> #include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h> #include <glacier/buffer/cap_buffer.h>
#include <zcall.h>
glcr::ErrorCode open(const OpenFileRequest& request, File& response) { glcr::ErrorCode VFSClient::open(const OpenFileRequest& request, File& response) {
uint64_t buffer_size = 0x1000; uint64_t buffer_size = kBufferSize;
// FIXME: Maybe raise this limit. uint64_t cap_size = kCapBufferSize;
uint64_t cap_size = 100;
glcr::ByteBuffer buffer(buffer_size);
glcr::CapBuffer caps(cap_size);
const uint32_t kSentinel = 0xBEEFDEAD; const uint32_t kSentinel = 0xBEEFDEAD;
buffer.WriteAt<uint32_t>(0, kSentinel); buffer_.WriteAt<uint32_t>(0, kSentinel);
buffer.WriteAt<uint64_t>(8, {method_number}); buffer_.WriteAt<uint64_t>(8, 0);
uint64_t length = request.SerializeToBytes(buffer, /*offset=*/16, caps); uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
buffer.WriteAt<uint32_t>(4, 16 + length); buffer_.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap; z_cap_t reply_port_cap;
// FIXME: We need to be able to send capabilities via endpoint call. // FIXME: We need to be able to send capabilities via endpoint call.
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer.RawPtr())); RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), &reply_port_cap));
// FIXME: Add a way to zero out the first buffer. // FIXME: Add a way to zero out the first buffer.
glcr::ByteBuffer recv_buffer(buffer_size); RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
glcr::CapBuffer recv_caps(cap_size);
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, recv_buffer.RawPtr(), &cap_size, recv_caps.RawPtr()));
if (recv_buffer.At<uint32_t>(0) != kSentinel) { if (buffer_.At<uint32_t>(0) != kSentinel) {
return glcr::INVALID_RESPONSE; return glcr::INVALID_RESPONSE;
} }
// Check Response Code. // Check Response Code.
RET_ERR(recv_buffer.At<uint64_t>(8)); RET_ERR(buffer_.At<uint64_t>(8));
response.ParseFromBytes(recv_buffer, 16, recv_caps); response.ParseFromBytes(buffer_, 16, cap_buffer_);
return glcr::OK; return glcr::OK;
} }

View File

@ -1,6 +1,9 @@
// Generated file - DO NOT MODIFY // Generated file - DO NOT MODIFY
#pragma once #pragma once
#include <glacier/buffer/byte_buffer.h>
#include <glacier/buffer/cap_buffer.h>
#include <glacier/status/error.h>
#include <ztypes.h> #include <ztypes.h>
#include "example.yunq.h" #include "example.yunq.h"
@ -9,10 +12,17 @@ class VFSClient {
public: public:
VFSClient(z_cap_t VFS_cap) : endpoint_(VFS_cap) {} VFSClient(z_cap_t VFS_cap) : endpoint_(VFS_cap) {}
VFSClient(const VFSClient&) = delete; VFSClient(const VFSClient&) = delete;
VFSClient(VFSClient&&) = delete; VFSClient(VFSClient&& other) : endpoint_(other.endpoint_) {other.endpoint_ = 0;};
z_cap_t Capability() { return endpoint_; }
[[nodiscard]] glcr::ErrorCode open(const OpenFileRequest& request, File& response); [[nodiscard]] glcr::ErrorCode open(const OpenFileRequest& request, File& response);
private: private:
z_cap_t endpoint_; z_cap_t endpoint_;
uint64_t kBufferSize = 0x1000;
glcr::ByteBuffer buffer_{kBufferSize};
uint64_t kCapBufferSize = 0x10;
glcr::CapBuffer cap_buffer_{kCapBufferSize};
}; };

View File

@ -47,7 +47,7 @@ void OpenFileRequest::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t off
set_options(bytes.At<uint64_t>(offset + header_size + (8 * 1))); set_options(bytes.At<uint64_t>(offset + header_size + (8 * 1)));
} }
uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) { uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * 2; uint32_t next_extension = header_size + 8 * 2;
const uint32_t core_size = next_extension; const uint32_t core_size = next_extension;
// Write path. // Write path.
@ -70,7 +70,7 @@ uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t off
return next_extension; return next_extension;
} }
uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) { uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
uint32_t next_extension = header_size + 8 * 2; uint32_t next_extension = header_size + 8 * 2;
const uint32_t core_size = next_extension; const uint32_t core_size = next_extension;
uint64_t next_cap = 0; uint64_t next_cap = 0;
@ -120,7 +120,7 @@ void File::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t offset, const
set_mem_cap(caps.At(mem_cap_ptr)); set_mem_cap(caps.At(mem_cap_ptr));
} }
uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) { uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * 3; uint32_t next_extension = header_size + 8 * 3;
const uint32_t core_size = next_extension; const uint32_t core_size = next_extension;
// Write path. // Write path.
@ -146,7 +146,7 @@ uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) {
return next_extension; return next_extension;
} }
uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) { uint64_t File::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
uint32_t next_extension = header_size + 8 * 3; uint32_t next_extension = header_size + 8 * 3;
const uint32_t core_size = next_extension; const uint32_t core_size = next_extension;
uint64_t next_cap = 0; uint64_t next_cap = 0;

View File

@ -14,11 +14,11 @@ class OpenFileRequest {
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset);
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&);
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
glcr::String path() { return path_; } glcr::String path() const { return path_; }
void set_path(const glcr::String& value) { path_ = value; } void set_path(const glcr::String& value) { path_ = value; }
uint64_t options() { return options_; } uint64_t options() const { return options_; }
void set_options(const uint64_t& value) { options_ = value; } void set_options(const uint64_t& value) { options_ = value; }
private: private:
@ -35,13 +35,13 @@ class File {
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset);
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&);
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
glcr::String path() { return path_; } glcr::String path() const { return path_; }
void set_path(const glcr::String& value) { path_ = value; } void set_path(const glcr::String& value) { path_ = value; }
uint64_t attrs() { return attrs_; } uint64_t attrs() const { return attrs_; }
void set_attrs(const uint64_t& value) { attrs_ = value; } void set_attrs(const uint64_t& value) { attrs_ = value; }
z_cap_t mem_cap() { return mem_cap_; } z_cap_t mem_cap() const { return mem_cap_; }
void set_mem_cap(const z_cap_t& value) { mem_cap_ = value; } void set_mem_cap(const z_cap_t& value) { mem_cap_ = value; }
private: private:

View File

@ -1,45 +1,102 @@
// Generated file - DO NOT MODIFY // Generated file -- DO NOT MODIFY.
#include "example.yunq.client.h" #include "example.yunq.server.h"
#include <glacier/buffer/byte_buffer.h> #include <mammoth/debug.h>
#include <glacier/buffer/cap_buffer.h> #include <zcall.h>
namespace {
const uint32_t kSentinel = 0xBEEFDEAD;
const uint32_t kHeaderSize = 0x10;
void WriteError(glcr::ByteBuffer& buffer, glcr::ErrorCode err) {
glcr::ErrorCode open(const OpenFileRequest& request, File& response) {
uint64_t buffer_size = 0x1000;
// FIXME: Maybe raise this limit.
uint64_t cap_size = 100;
glcr::ByteBuffer buffer(buffer_size);
glcr::CapBuffer caps(cap_size);
const uint32_t kSentinel = 0xBEEFDEAD;
buffer.WriteAt<uint32_t>(0, kSentinel); buffer.WriteAt<uint32_t>(0, kSentinel);
buffer.WriteAt<uint64_t>(8, {method_number}); buffer.WriteAt<uint32_t>(4, kHeaderSize);
buffer.WriteAt<uint64_t>(8, err);
uint64_t length = request.SerializeToBytes(buffer, /*offset=*/16, caps);
buffer.WriteAt<uint32_t>(4, 16 + length);
z_cap_t reply_port_cap;
// FIXME: We need to be able to send capabilities via endpoint call.
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer.RawPtr()));
// FIXME: Add a way to zero out the first buffer.
glcr::ByteBuffer recv_buffer(buffer_size);
glcr::CapBuffer recv_caps(cap_size);
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, recv_buffer.RawPtr(), &cap_size, recv_caps.RawPtr()));
if (recv_buffer.At<uint32_t>(0) != kSentinel) {
return glcr::INVALID_RESPONSE;
}
// Check Response Code.
RET_ERR(recv_buffer.At<uint64_t>(8));
response.ParseFromBytes(recv_buffer, 16, recv_caps);
return glcr::OK;
} }
void WriteHeader(glcr::ByteBuffer& buffer, uint64_t message_length) {
buffer.WriteAt<uint32_t>(0, kSentinel);
buffer.WriteAt<uint32_t>(4, kHeaderSize + message_length);
buffer.WriteAt<uint64_t>(8, glcr::OK);
}
} // namespace
void VFSServerBaseThreadBootstrap(void* server_base) {
((VFSServerBase*)server_base)->ServerThread();
}
glcr::ErrorOr<VFSClient> 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::ByteBuffer resp_buffer(0x1000);
uint64_t resp_cap_size = 0x10;
glcr::CapBuffer resp_cap(resp_cap_size);
z_cap_t reply_port_cap;
while (true) {
uint64_t recv_buf_size = 0x1000;
glcr::ErrorCode recv_err = ZEndpointRecv(endpoint_, &recv_buf_size, recv_buffer.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;
glcr::ErrorCode err = HandleRequest(recv_buffer, 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", recv_err);
}
}
}
glcr::ErrorCode VFSServerBase::HandleRequest(const glcr::ByteBuffer& request,
glcr::ByteBuffer& response, uint64_t& resp_length,
glcr::CapBuffer& resp_caps) {
if (request.At<uint32_t>(0) != kSentinel) {
return glcr::INVALID_ARGUMENT;
}
uint64_t method_select = request.At<uint64_t>(8);
switch(method_select) {
case 0: {
OpenFileRequest yunq_request;
File yunq_response;
yunq_request.ParseFromBytes(request, kHeaderSize);
RET_ERR(Handleopen(yunq_request, yunq_response));
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
break;
}
default: {
return glcr::UNIMPLEMENTED;
}
}
return glcr::OK;
}

View File

@ -1,19 +1,23 @@
// Generated File -- DO NOT MODIFY. // Generated File -- DO NOT MODIFY.
#pragma once #pragma once
#include <glacier/status/error_or.h>
#include <mammoth/thread.h> #include <mammoth/thread.h>
#include <ztypes.h> #include <ztypes.h>
#include "example.yunq.h" #include "example.yunq.h"
#include "example.yunq.client.h"
class VFSServerBase { class VFSServerBase {
public: public:
VFSServerBase(z_cap_t VFS_cap) : {} VFSServerBase(z_cap_t VFS_cap) : endpoint_(VFS_cap) {}
VFSServerBase(const VFSServerBase&) = delete; VFSServerBase(const VFSServerBase&) = delete;
VFSServerBase(VFSServerBase&&) = delete; VFSServerBase(VFSServerBase&&) = delete;
glcr::ErrorOr<VFSClient> CreateClient();
[[nodiscard]] Thread RunServer(); [[nodiscard]] Thread RunServer();
@ -27,6 +31,7 @@ class VFSServerBase {
void ServerThread(); void ServerThread();
[[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, glcr::ByteBuffer& response, [[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, glcr::ByteBuffer& response,
uint64_t& resp_length,
glcr::CapBuffer& resp_caps); glcr::CapBuffer& resp_caps);
}; };

View File

@ -74,7 +74,7 @@ void {{message.name}}::ParseFromBytes(const glcr::ByteBuffer& bytes, uint64_t of
{%- endfor %} {%- endfor %}
} }
uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) { uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
uint32_t next_extension = header_size + 8 * {{ message.fields | length }}; uint32_t next_extension = header_size + 8 * {{ message.fields | length }};
const uint32_t core_size = next_extension; const uint32_t core_size = next_extension;
@ -109,7 +109,7 @@ uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t of
return next_extension; return next_extension;
} }
uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) { uint64_t {{message.name}}::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
uint32_t next_extension = header_size + 8 * {{ message.fields | length}}; uint32_t next_extension = header_size + 8 * {{ message.fields | length}};
const uint32_t core_size = next_extension; const uint32_t core_size = next_extension;
uint64_t next_cap = 0; uint64_t next_cap = 0;

View File

@ -17,11 +17,11 @@ class {{message.name}} {
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset); void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset);
void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&); void ParseFromBytes(const glcr::ByteBuffer&, uint64_t offset, const glcr::CapBuffer&);
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&); uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
{%- for field in message.fields %} {%- for field in message.fields %}
{{field.cpp_type()}} {{field.name}}() { return {{field.name}}_; } {{field.cpp_type()}} {{field.name}}() const { return {{field.name}}_; }
void set_{{field.name}}(const {{field.cpp_type()}}& value) { {{field.name}}_ = value; } void set_{{field.name}}(const {{field.cpp_type()}}& value) { {{field.name}}_ = value; }
{%- endfor %} {%- endfor %}

View File

@ -26,14 +26,21 @@ void WriteHeader(glcr::ByteBuffer& buffer, uint64_t message_length) {
{% for interface in interfaces %} {% for interface in interfaces %}
void {{interface.name}}ServerBaseThreadBootstrap(void* server_base) { void {{interface.name}}ServerBaseThreadBootstrap(void* server_base) {
({{interface.name}}ServerBase*)(server_base)->ServerThread(); (({{interface.name}}ServerBase*)server_base)->ServerThread();
} }
Thread {{interface.name}}::RunServer() { glcr::ErrorOr<{{interface.name}}Client> {{interface.name}}ServerBase::CreateClient() {
uint64_t client_cap;
// FIXME: Restrict permissions to send-only here.
RET_ERR(ZCapDuplicate(endpoint_, &client_cap));
return {{interface.name}}Client(client_cap);
}
Thread {{interface.name}}ServerBase::RunServer() {
return Thread({{interface.name}}ServerBaseThreadBootstrap, this); return Thread({{interface.name}}ServerBaseThreadBootstrap, this);
} }
void {{interface.name}}::ServerThread() { void {{interface.name}}ServerBase::ServerThread() {
glcr::ByteBuffer recv_buffer(0x1000); glcr::ByteBuffer recv_buffer(0x1000);
glcr::ByteBuffer resp_buffer(0x1000); glcr::ByteBuffer resp_buffer(0x1000);
uint64_t resp_cap_size = 0x10; uint64_t resp_cap_size = 0x10;
@ -50,37 +57,42 @@ void {{interface.name}}::ServerThread() {
uint64_t resp_length = 0; uint64_t resp_length = 0;
glcr::ErrorCode err = HandlRequest(recv_buffer, resp_buffer, resp_length, resp_cap); glcr::ErrorCode reply_err = glcr::OK;
glcr::ErrorCode err = HandleRequest(recv_buffer, resp_buffer, resp_length, resp_cap);
if (err != glcr::OK) { if (err != glcr::OK) {
WriteError(resp_buffer, err); WriteError(resp_buffer, err);
ZReplyPortSend(reply_port_cap, kHeaderSize, resp_buffer.RawPtr(), 0, nullptr); reply_err = ZReplyPortSend(reply_port_cap, kHeaderSize, resp_buffer.RawPtr(), 0, nullptr);
} else { } else {
WriteHeader(resp_buffer, resp_length); WriteHeader(resp_buffer, resp_length);
ZReplyPortSend(reply_port_cap, resp_length, resp_buffer.RawPtr(), resp_cap.UsedSlots(), resp_cap.RawPtr()); 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", recv_err);
} }
} }
} }
glcr::ErrorCode {{interface.name}}::HandleRequest(const glcr::ByteBuffer& request, glcr::ByteBuffer& response, uint64_t& resp_length glcr::ErrorCode {{interface.name}}ServerBase::HandleRequest(const glcr::ByteBuffer& request,
glcr::CapBuffer& resp_caps) { glcr::ByteBuffer& response, uint64_t& resp_length,
if (recv_buffer.At<uint32_t>(0) != kSentinel) { glcr::CapBuffer& resp_caps) {
return glcr::INVALID_INPUT; if (request.At<uint32_t>(0) != kSentinel) {
return glcr::INVALID_ARGUMENT;
} }
uint64_t method_select = recv_buffer.At<uint64_t>(8); uint64_t method_select = request.At<uint64_t>(8);
switch(method_select) { switch(method_select) {
{%- for method in interface.methods %} {%- for method in interface.methods %}
case {{loop.index0}}: { case {{loop.index0}}: {
{{method.request}} request; {{method.request}} yunq_request;
{{method.response}} response; {{method.response}} yunq_response;
request.ParseFromBytes(recv_buffer, kHeaderSize); yunq_request.ParseFromBytes(request, kHeaderSize);
RET_ERR(Handle{{method.name}}(request, response)); RET_ERR(Handle{{method.name}}(yunq_request, yunq_response));
resp_length = response.SerializeToBytes(resp_buffer, kHeaderSize, resp_cap); resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
break; break;
} }
{%- endfor %} {%- endfor %}

View File

@ -1,19 +1,23 @@
// Generated File -- DO NOT MODIFY. // Generated File -- DO NOT MODIFY.
#pragma once #pragma once
#include <glacier/status/error_or.h>
#include <mammoth/thread.h> #include <mammoth/thread.h>
#include <ztypes.h> #include <ztypes.h>
#include "{{file}}.h" #include "{{file}}.h"
#include "{{file}}.client.h"
{% for interface in interfaces %} {% for interface in interfaces %}
class {{interface.name}}ServerBase { class {{interface.name}}ServerBase {
public: public:
{{interface.name}}ServerBase(z_cap_t {{interface.name}}_cap) : {} {{interface.name}}ServerBase(z_cap_t {{interface.name}}_cap) : endpoint_({{interface.name}}_cap) {}
{{interface.name}}ServerBase(const {{interface.name}}ServerBase&) = delete; {{interface.name}}ServerBase(const {{interface.name}}ServerBase&) = delete;
{{interface.name}}ServerBase({{interface.name}}ServerBase&&) = delete; {{interface.name}}ServerBase({{interface.name}}ServerBase&&) = delete;
glcr::ErrorOr<{{interface.name}}Client> CreateClient();
[[nodiscard]] Thread RunServer(); [[nodiscard]] Thread RunServer();
{% for method in interface.methods %} {% for method in interface.methods %}
@ -27,6 +31,7 @@ class {{interface.name}}ServerBase {
void ServerThread(); void ServerThread();
[[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, glcr::ByteBuffer& response, [[nodiscard]] glcr::ErrorCode HandleRequest(const glcr::ByteBuffer& request, glcr::ByteBuffer& response,
uint64_t& resp_length,
glcr::CapBuffer& resp_caps); glcr::CapBuffer& resp_caps);
}; };

View File

@ -55,7 +55,7 @@ def main():
server_impl_tmpl = jinja_env.get_template("server.cpp.jinja") server_impl_tmpl = jinja_env.get_template("server.cpp.jinja")
with open(filename + '.server.cpp', mode='w') as f: with open(filename + '.server.cpp', mode='w') as f:
server_impl = client_impl_tmpl.render(file=filename, interfaces=interfaces) server_impl = server_impl_tmpl.render(file=filename, interfaces=interfaces)
f.write(server_impl) f.write(server_impl)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -69,7 +69,10 @@ struct InterruptFrame {
}; };
extern "C" void isr_divide_by_zero(); extern "C" void isr_divide_by_zero();
extern "C" void interrupt_divide_by_zero(void* frame) { panic("DIV0"); } extern "C" void interrupt_divide_by_zero(InterruptFrame* frame) {
dbgln("RIP: %m", frame->rip);
panic("DIV0");
}
extern "C" void isr_protection_fault(); extern "C" void isr_protection_fault();
extern "C" void interrupt_protection_fault(InterruptFrame* frame) { extern "C" void interrupt_protection_fault(InterruptFrame* frame) {

View File

@ -88,6 +88,8 @@ class PhysicalMemoryManager {
MemBlock* block = front_; MemBlock* block = front_;
while (block != nullptr && block->num_pages < num_pages) { while (block != nullptr && block->num_pages < num_pages) {
dbgln("Skipping block of size %u seeking %u", block->num_pages,
num_pages);
block = block->next; block = block->next;
} }