[Yellowstone][Mammoth] Delete unused cpp code.
This commit is contained in:
parent
d58cbed0df
commit
c1db6cb11f
|
@ -1,14 +1,7 @@
|
|||
add_library(mammoth STATIC
|
||||
file/file.cpp
|
||||
input/keyboard.cpp
|
||||
ipc/channel.cpp
|
||||
ipc/endpoint_client.cpp
|
||||
ipc/endpoint_server.cpp
|
||||
ipc/port_client.cpp
|
||||
ipc/port_server.cpp
|
||||
proc/process.cpp
|
||||
proc/thread.cpp
|
||||
sync/mutex.cpp
|
||||
sync/semaphore.cpp
|
||||
util/debug.cpp
|
||||
util/init.cpp
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
#include "file/file.h"
|
||||
|
||||
#include <glacier/string/str_split.h>
|
||||
#include <mammoth/util/init.h>
|
||||
#include <victoriafalls/victoriafalls.yunq.client.h>
|
||||
#include <yellowstone/yellowstone.yunq.client.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#include "util/debug.h"
|
||||
|
||||
namespace mmth {
|
||||
namespace {
|
||||
|
||||
using yellowstone::Endpoint;
|
||||
using yellowstone::GetEndpointRequest;
|
||||
using yellowstone::YellowstoneClient;
|
||||
|
||||
VFSClient* gVfsClient = nullptr;
|
||||
|
||||
void GetVfsClientIfNeeded() {
|
||||
if (gVfsClient == nullptr) {
|
||||
// TODO: Add an unowned client so we don't have to duplicate this cap every
|
||||
// time.
|
||||
uint64_t dup_cap;
|
||||
check(ZCapDuplicate(gInitEndpointCap, kZionPerm_All, &dup_cap));
|
||||
YellowstoneClient client(dup_cap);
|
||||
|
||||
GetEndpointRequest yreq;
|
||||
yreq.set_endpoint_name("victoriafalls");
|
||||
Endpoint yresp;
|
||||
check(client.GetEndpoint(yreq, yresp));
|
||||
|
||||
gVfsClient = new VFSClient(yresp.endpoint());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SetVfsCap(z_cap_t vfs_cap) { gVfsClient = new VFSClient(vfs_cap); }
|
||||
|
||||
File File::Open(glcr::StringView path) {
|
||||
GetVfsClientIfNeeded();
|
||||
|
||||
OpenFileRequest req;
|
||||
req.set_path(path);
|
||||
OpenFileResponse resp;
|
||||
check(gVfsClient->OpenFile(req, resp));
|
||||
|
||||
return File(OwnedMemoryRegion::FromCapability(resp.memory()), resp.size());
|
||||
}
|
||||
|
||||
glcr::StringView File::as_str() {
|
||||
return glcr::StringView((char*)raw_ptr(), size_);
|
||||
}
|
||||
|
||||
void* File::raw_ptr() { return reinterpret_cast<void*>(file_data_.vaddr()); }
|
||||
uint8_t* File::byte_ptr() {
|
||||
return reinterpret_cast<uint8_t*>(file_data_.vaddr());
|
||||
}
|
||||
|
||||
glcr::ErrorOr<glcr::Vector<glcr::String>> ListDirectory(glcr::StringView path) {
|
||||
GetVfsClientIfNeeded();
|
||||
|
||||
GetDirectoryRequest req;
|
||||
req.set_path(path);
|
||||
Directory dir;
|
||||
auto status = gVfsClient->GetDirectory(req, dir);
|
||||
if (!status.ok()) {
|
||||
dbgln("Error in getting directory: {}", status.message());
|
||||
return status.code();
|
||||
}
|
||||
|
||||
auto file_views = glcr::StrSplit(dir.filenames(), ',');
|
||||
glcr::Vector<glcr::String> files;
|
||||
for (const auto& view : glcr::StrSplit(dir.filenames(), ',')) {
|
||||
files.PushBack(view);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,38 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/vector.h>
|
||||
#include <glacier/memory/move.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <glacier/string/string.h>
|
||||
#include <glacier/string/string_view.h>
|
||||
|
||||
#include "mammoth/util/memory_region.h"
|
||||
|
||||
namespace mmth {
|
||||
|
||||
// Intended for use in yellowstone since it already has the VFS cap.
|
||||
void SetVfsCap(z_cap_t vfs_cap);
|
||||
|
||||
class File {
|
||||
public:
|
||||
static File Open(glcr::StringView path);
|
||||
|
||||
uint64_t size() { return size_; }
|
||||
|
||||
glcr::StringView as_str();
|
||||
|
||||
void* raw_ptr();
|
||||
uint8_t* byte_ptr();
|
||||
|
||||
private:
|
||||
OwnedMemoryRegion file_data_;
|
||||
uint64_t size_;
|
||||
|
||||
File(OwnedMemoryRegion&& file, uint64_t size)
|
||||
: file_data_(glcr::Move(file)), size_(size) {}
|
||||
};
|
||||
|
||||
// TODO: Move this to a separate file.
|
||||
glcr::ErrorOr<glcr::Vector<glcr::String>> ListDirectory(glcr::StringView path);
|
||||
|
||||
} // namespace mmth
|
|
@ -1,228 +0,0 @@
|
|||
#include "input/keyboard.h"
|
||||
|
||||
#include <mammoth/util/init.h>
|
||||
#include <voyageurs/voyageurs.yunq.client.h>
|
||||
#include <yellowstone/yellowstone.yunq.client.h>
|
||||
|
||||
#include "util/debug.h"
|
||||
|
||||
namespace mmth {
|
||||
namespace {
|
||||
|
||||
using yellowstone::Endpoint;
|
||||
using yellowstone::GetEndpointRequest;
|
||||
using yellowstone::YellowstoneClient;
|
||||
|
||||
void KeyboardListenerEntry(void* keyboard_base) {
|
||||
reinterpret_cast<KeyboardListenerBase*>(keyboard_base)->ListenLoop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
KeyboardListenerBase::KeyboardListenerBase() {
|
||||
auto server_or = PortServer::Create();
|
||||
if (!server_or) {
|
||||
crash("Failed to create server", server_or.error());
|
||||
}
|
||||
server_ = server_or.value();
|
||||
}
|
||||
|
||||
void KeyboardListenerBase::Register() {
|
||||
uint64_t dup_cap;
|
||||
check(ZCapDuplicate(gInitEndpointCap, kZionPerm_All, &dup_cap));
|
||||
YellowstoneClient client(dup_cap);
|
||||
|
||||
GetEndpointRequest req;
|
||||
req.set_endpoint_name("voyageurs");
|
||||
Endpoint endpt;
|
||||
check(client.GetEndpoint(req, endpt));
|
||||
|
||||
VoyageursClient vclient(endpt.endpoint());
|
||||
KeyboardListener listn;
|
||||
|
||||
// TODO: Create a "ASSIGN_OR_CRASH" macro to simplify this.
|
||||
auto client_or = server_.CreateClient();
|
||||
if (!client_or.ok()) {
|
||||
crash("Failed to create client", client_or.error());
|
||||
}
|
||||
listn.set_port_capability(client_or.value().cap());
|
||||
check(vclient.RegisterKeyboardListener(listn));
|
||||
}
|
||||
|
||||
Thread KeyboardListenerBase::Listen() {
|
||||
return Thread(KeyboardListenerEntry, this);
|
||||
}
|
||||
|
||||
void KeyboardListenerBase::ListenLoop() {
|
||||
while (true) {
|
||||
auto scancode_or = server_.RecvUint16();
|
||||
if (!scancode_or.ok()) {
|
||||
check(scancode_or.error());
|
||||
}
|
||||
uint16_t scancode = scancode_or.value();
|
||||
|
||||
Keycode k = ScancodeToKeycode(scancode & 0xFF);
|
||||
uint8_t modifiers = (scancode >> 8) & 0xFF;
|
||||
HandleKeycode(k, modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardListenerBase::HandleKeycode(Keycode code, uint8_t modifiers) {
|
||||
char c = '\0';
|
||||
|
||||
if (code >= kA && code <= kZ) {
|
||||
if (IsShift(modifiers)) {
|
||||
const char* alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
c = alpha[code - kA];
|
||||
|
||||
} else {
|
||||
const char* alpha = "abcdefghijklmnopqrstuvwxyz";
|
||||
c = alpha[code - kA];
|
||||
}
|
||||
} else if (code >= k1 && code <= k0) {
|
||||
if (IsShift(modifiers)) {
|
||||
const char* num = "!@#$%^&*()";
|
||||
c = num[code - k1];
|
||||
} else {
|
||||
const char* num = "1234567890";
|
||||
c = num[code - k1];
|
||||
}
|
||||
} else if (code >= kMinus && code <= kBacktick) {
|
||||
if (IsShift(modifiers)) {
|
||||
const char* sym = "_+{}|?:\"<>~";
|
||||
c = sym[code - kMinus];
|
||||
} else {
|
||||
const char* sym = "-=[]\\/;',.`";
|
||||
c = sym[code - kMinus];
|
||||
}
|
||||
} else if (code == kEnter) {
|
||||
c = '\n';
|
||||
} else if (code == kSpace) {
|
||||
c = ' ';
|
||||
} else if (code == kTab) {
|
||||
c = '\t';
|
||||
} else if (code == kBackspace) {
|
||||
c = '\b';
|
||||
}
|
||||
|
||||
if (c != '\0') {
|
||||
HandleCharacter(c);
|
||||
}
|
||||
}
|
||||
|
||||
Keycode KeyboardListenerBase::ScancodeToKeycode(uint16_t scancode) {
|
||||
switch (scancode) {
|
||||
case 0x04:
|
||||
return kA;
|
||||
case 0x05:
|
||||
return kB;
|
||||
case 0x06:
|
||||
return kC;
|
||||
case 0x07:
|
||||
return kD;
|
||||
case 0x08:
|
||||
return kE;
|
||||
case 0x09:
|
||||
return kF;
|
||||
case 0x0A:
|
||||
return kG;
|
||||
case 0x0B:
|
||||
return kH;
|
||||
case 0x0C:
|
||||
return kI;
|
||||
case 0x0D:
|
||||
return kJ;
|
||||
case 0x0E:
|
||||
return kK;
|
||||
case 0x0F:
|
||||
return kL;
|
||||
case 0x10:
|
||||
return kM;
|
||||
case 0x11:
|
||||
return kN;
|
||||
case 0x12:
|
||||
return kO;
|
||||
case 0x13:
|
||||
return kP;
|
||||
case 0x14:
|
||||
return kQ;
|
||||
case 0x15:
|
||||
return kR;
|
||||
case 0x16:
|
||||
return kS;
|
||||
case 0x17:
|
||||
return kT;
|
||||
case 0x18:
|
||||
return kU;
|
||||
case 0x19:
|
||||
return kV;
|
||||
case 0x1A:
|
||||
return kW;
|
||||
case 0x1B:
|
||||
return kX;
|
||||
case 0x1C:
|
||||
return kY;
|
||||
case 0x1D:
|
||||
return kZ;
|
||||
case 0x1E:
|
||||
return k1;
|
||||
case 0x1F:
|
||||
return k2;
|
||||
case 0x20:
|
||||
return k3;
|
||||
case 0x21:
|
||||
return k4;
|
||||
case 0x22:
|
||||
return k5;
|
||||
case 0x23:
|
||||
return k6;
|
||||
case 0x24:
|
||||
return k7;
|
||||
case 0x25:
|
||||
return k8;
|
||||
case 0x26:
|
||||
return k9;
|
||||
case 0x27:
|
||||
return k0;
|
||||
case 0x28:
|
||||
return kEnter;
|
||||
case 0x29:
|
||||
return kEsc;
|
||||
case 0x2A:
|
||||
return kBackspace;
|
||||
case 0x2B:
|
||||
return kTab;
|
||||
case 0x2C:
|
||||
return kSpace;
|
||||
case 0x2D:
|
||||
return kMinus;
|
||||
case 0x2E:
|
||||
return kEquals;
|
||||
case 0x2F:
|
||||
return kLBrace;
|
||||
case 0x30:
|
||||
return kRBrace;
|
||||
case 0x31:
|
||||
return kBSlash;
|
||||
case 0x33:
|
||||
return kSemicolon;
|
||||
case 0x34:
|
||||
return kQuote;
|
||||
case 0x35:
|
||||
return kBacktick;
|
||||
case 0x36:
|
||||
return kComma;
|
||||
case 0x37:
|
||||
return kPeriod;
|
||||
case 0x38:
|
||||
return kFSlash;
|
||||
case 0x39:
|
||||
return kEsc; // Capslock
|
||||
}
|
||||
|
||||
dbgln("Unknown scancode {x}", scancode);
|
||||
|
||||
return kUnknownKeycode;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,113 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "mammoth/ipc/port_server.h"
|
||||
#include "mammoth/proc/thread.h"
|
||||
|
||||
namespace mmth {
|
||||
|
||||
enum Keycode {
|
||||
kUnknownKeycode = 0x0,
|
||||
|
||||
kA = 0x1,
|
||||
kB = 0x2,
|
||||
kC = 0x3,
|
||||
kD = 0x4,
|
||||
kE = 0x5,
|
||||
kF = 0x6,
|
||||
kG = 0x7,
|
||||
kH = 0x8,
|
||||
kI = 0x9,
|
||||
kJ = 0xA,
|
||||
kK = 0xB,
|
||||
kL = 0xC,
|
||||
kM = 0xD,
|
||||
kN = 0xE,
|
||||
kO = 0xF,
|
||||
kP = 0x10,
|
||||
kQ = 0x11,
|
||||
kR = 0x12,
|
||||
kS = 0x13,
|
||||
kT = 0x14,
|
||||
kU = 0x15,
|
||||
kV = 0x16,
|
||||
kW = 0x17,
|
||||
kX = 0x18,
|
||||
kY = 0x19,
|
||||
kZ = 0x1A,
|
||||
|
||||
k1 = 0x20,
|
||||
k2 = 0x21,
|
||||
k3 = 0x22,
|
||||
k4 = 0x23,
|
||||
k5 = 0x24,
|
||||
k6 = 0x25,
|
||||
k7 = 0x26,
|
||||
k8 = 0x27,
|
||||
k9 = 0x28,
|
||||
k0 = 0x29,
|
||||
|
||||
kSpace = 0x30,
|
||||
kEnter = 0x31,
|
||||
kTab = 0x32,
|
||||
kBackspace = 0x33,
|
||||
kDelete = 0x34,
|
||||
|
||||
kMinus = 0x40,
|
||||
kEquals = 0x41,
|
||||
kLBrace = 0x42,
|
||||
kRBrace = 0x43,
|
||||
kBSlash = 0x44,
|
||||
kFSlash = 0x45,
|
||||
kSemicolon = 0x46,
|
||||
kQuote = 0x47,
|
||||
kComma = 0x48,
|
||||
kPeriod = 0x49,
|
||||
kBacktick = 0x4A,
|
||||
|
||||
kLShift = 0x50,
|
||||
kRShift = 0x51,
|
||||
kLCtrl = 0x52,
|
||||
kRCtrl = 0x53,
|
||||
kLAlt = 0x54,
|
||||
kRAlt = 0x55,
|
||||
kSuper = 0x56,
|
||||
kEsc = 0x57,
|
||||
kUp = 0x58,
|
||||
kDown = 0x59,
|
||||
kLeft = 0x5A,
|
||||
kRight = 0x5B,
|
||||
};
|
||||
|
||||
class KeyboardListenerBase {
|
||||
public:
|
||||
KeyboardListenerBase();
|
||||
KeyboardListenerBase(const KeyboardListenerBase&) = delete;
|
||||
KeyboardListenerBase(KeyboardListenerBase&&) = delete;
|
||||
|
||||
void Register();
|
||||
|
||||
Thread Listen();
|
||||
|
||||
void ListenLoop();
|
||||
|
||||
// Override this to recieve all raw keycodes. By default
|
||||
// this function will try to translate each keycode into
|
||||
// a printable character and call HandleCharacter.
|
||||
virtual void HandleKeycode(Keycode code, uint8_t modifiers);
|
||||
|
||||
// This function is called by the default HandleKeycode
|
||||
// implementation if you do not override it. If it recieves
|
||||
// input that corresponds to a printable character it will
|
||||
virtual void HandleCharacter(char c){};
|
||||
|
||||
private:
|
||||
PortServer server_;
|
||||
|
||||
Keycode ScancodeToKeycode(uint16_t scancode);
|
||||
|
||||
bool IsShift(uint8_t modifiers) {
|
||||
return (modifiers & 0x2) || (modifiers & 0x20);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mmth
|
|
@ -1,60 +0,0 @@
|
|||
#include "ipc/channel.h"
|
||||
|
||||
#include <zcall.h>
|
||||
|
||||
#include "util/debug.h"
|
||||
|
||||
namespace mmth {
|
||||
namespace {
|
||||
|
||||
uint64_t strlen(const char* ptr) {
|
||||
uint64_t len = 0;
|
||||
while (*ptr != '\0') {
|
||||
len++;
|
||||
ptr++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Channel::adopt_cap(uint64_t id) {
|
||||
if (chan_cap_ != 0) {
|
||||
crash("Adopting over channel.", glcr::ALREADY_EXISTS);
|
||||
}
|
||||
chan_cap_ = id;
|
||||
}
|
||||
z_cap_t Channel::release_cap() {
|
||||
z_cap_t cap = chan_cap_;
|
||||
chan_cap_ = 0;
|
||||
return cap;
|
||||
}
|
||||
|
||||
z_cap_t Channel::cap() { return chan_cap_; }
|
||||
|
||||
z_err_t Channel::WriteStr(const char* msg) {
|
||||
if (!chan_cap_) {
|
||||
return glcr::NULL_PTR;
|
||||
}
|
||||
return ZChannelSend(chan_cap_, strlen(msg), msg, 0, nullptr);
|
||||
}
|
||||
|
||||
z_err_t Channel::ReadStr(char* buffer, uint64_t* size) {
|
||||
if (!chan_cap_) {
|
||||
return glcr::NULL_PTR;
|
||||
}
|
||||
uint64_t num_caps = 0;
|
||||
return ZChannelRecv(chan_cap_, size, reinterpret_cast<uint8_t*>(buffer),
|
||||
&num_caps, nullptr);
|
||||
}
|
||||
|
||||
z_err_t CreateChannels(Channel& c1, Channel& c2) {
|
||||
z_cap_t chan1, chan2;
|
||||
RET_ERR(ZChannelCreate(&chan1, &chan2));
|
||||
|
||||
c1.adopt_cap(chan1);
|
||||
c2.adopt_cap(chan2);
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,51 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error.h>
|
||||
#include <stdint.h>
|
||||
#include <zcall.h>
|
||||
|
||||
namespace mmth {
|
||||
|
||||
class Channel {
|
||||
public:
|
||||
Channel() {}
|
||||
void adopt_cap(uint64_t id);
|
||||
z_cap_t release_cap();
|
||||
z_cap_t cap();
|
||||
|
||||
z_err_t WriteStr(const char* msg);
|
||||
z_err_t ReadStr(char* buffer, uint64_t* size);
|
||||
|
||||
template <typename T>
|
||||
z_err_t WriteStruct(T*);
|
||||
|
||||
template <typename T>
|
||||
z_err_t ReadStructAndCap(T*, uint64_t*);
|
||||
|
||||
// FIXME: Close channel here.
|
||||
~Channel() {}
|
||||
|
||||
private:
|
||||
z_cap_t chan_cap_ = 0;
|
||||
};
|
||||
|
||||
uint64_t CreateChannels(Channel& c1, Channel& c2);
|
||||
|
||||
template <typename T>
|
||||
z_err_t Channel::WriteStruct(T* obj) {
|
||||
return ZChannelSend(chan_cap_, sizeof(T), obj, 0, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
z_err_t Channel::ReadStructAndCap(T* obj, uint64_t* cap) {
|
||||
uint64_t num_bytes = sizeof(T);
|
||||
uint64_t num_caps = 1;
|
||||
RET_ERR(ZChannelRecv(chan_cap_, &num_bytes, obj, &num_caps, cap));
|
||||
|
||||
if (num_caps != 1 || num_bytes != sizeof(T)) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,9 +0,0 @@
|
|||
#include "ipc/endpoint_server.h"
|
||||
|
||||
namespace mmth {
|
||||
|
||||
glcr::UniquePtr<EndpointClient> EndpointClient::AdoptEndpoint(z_cap_t cap) {
|
||||
return glcr::UniquePtr<EndpointClient>(new EndpointClient(cap));
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,69 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/pair.h>
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <zcall.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
namespace mmth {
|
||||
|
||||
class EndpointClient {
|
||||
public:
|
||||
EndpointClient() = delete;
|
||||
EndpointClient(const EndpointClient&) = delete;
|
||||
EndpointClient& operator=(const EndpointClient&) = delete;
|
||||
|
||||
static glcr::UniquePtr<EndpointClient> AdoptEndpoint(z_cap_t cap);
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> CallEndpointGetCap(const Req& req);
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<Resp> CallEndpoint(const Req& req);
|
||||
|
||||
z_cap_t GetCap() const { return cap_; }
|
||||
|
||||
private:
|
||||
EndpointClient(uint64_t cap) : cap_(cap) {}
|
||||
z_cap_t cap_;
|
||||
};
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> EndpointClient::CallEndpointGetCap(
|
||||
const Req& req) {
|
||||
uint64_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, 0, nullptr, &reply_port_cap));
|
||||
|
||||
Resp resp;
|
||||
z_cap_t cap = 0;
|
||||
uint64_t num_caps = 1;
|
||||
uint64_t num_bytes = sizeof(Resp);
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &num_bytes, &resp, &num_caps, &cap));
|
||||
|
||||
if (num_bytes != sizeof(resp) || num_caps != 1) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
|
||||
return glcr::Pair{resp, cap};
|
||||
}
|
||||
|
||||
template <typename Req, typename Resp>
|
||||
glcr::ErrorOr<Resp> EndpointClient::CallEndpoint(const Req& req) {
|
||||
uint64_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, 0, nullptr, &reply_port_cap));
|
||||
|
||||
Resp resp;
|
||||
uint64_t num_bytes = sizeof(Resp);
|
||||
uint64_t num_caps = 0;
|
||||
RET_ERR(
|
||||
ZReplyPortRecv(reply_port_cap, &num_bytes, &resp, &num_caps, nullptr));
|
||||
|
||||
if (num_bytes != sizeof(resp)) {
|
||||
return glcr::FAILED_PRECONDITION;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,45 +0,0 @@
|
|||
#include "ipc/endpoint_server.h"
|
||||
|
||||
#include "util/debug.h"
|
||||
|
||||
namespace mmth {
|
||||
// Declared as friend in EndpointServer.
|
||||
void EndpointServerThreadBootstrap(void* endpoint_server) {
|
||||
reinterpret_cast<EndpointServer*>(endpoint_server)->ServerThread();
|
||||
}
|
||||
|
||||
glcr::ErrorOr<glcr::UniquePtr<EndpointClient>> EndpointServer::CreateClient() {
|
||||
uint64_t client_cap;
|
||||
RET_ERR(ZCapDuplicate(endpoint_cap_, ~(kZionPerm_Read), &client_cap));
|
||||
return EndpointClient::AdoptEndpoint(client_cap);
|
||||
}
|
||||
|
||||
Thread EndpointServer::RunServer() {
|
||||
return Thread(EndpointServerThreadBootstrap, this);
|
||||
}
|
||||
|
||||
void EndpointServer::ServerThread() {
|
||||
while (true) {
|
||||
uint64_t message_size = kBufferSize;
|
||||
uint64_t reply_port_cap = 0;
|
||||
uint64_t num_caps = 0;
|
||||
glcr::ErrorCode err = static_cast<glcr::ErrorCode>(
|
||||
ZEndpointRecv(endpoint_cap_, &message_size, recieve_buffer_, &num_caps,
|
||||
nullptr, &reply_port_cap));
|
||||
if (err != glcr::OK) {
|
||||
dbgln("Error in receive: {x}", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
RequestContext request(recieve_buffer_, message_size);
|
||||
ResponseContext response(reply_port_cap);
|
||||
// FIXME: Consider pumping these errors into the response as well.
|
||||
check(HandleRequest(request, response));
|
||||
if (!response.HasWritten()) {
|
||||
dbgln("Returning without having written a response. Req type {x}",
|
||||
request.request_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "mammoth/ipc/endpoint_client.h"
|
||||
#include "mammoth/ipc/request_context.h"
|
||||
#include "mammoth/ipc/response_context.h"
|
||||
#include "mammoth/proc/thread.h"
|
||||
|
||||
namespace mmth {
|
||||
class EndpointServer {
|
||||
public:
|
||||
EndpointServer() = delete;
|
||||
EndpointServer(const EndpointServer&) = delete;
|
||||
EndpointServer& operator=(const EndpointServer&) = delete;
|
||||
|
||||
glcr::ErrorOr<glcr::UniquePtr<EndpointClient>> CreateClient();
|
||||
|
||||
Thread RunServer();
|
||||
|
||||
virtual glcr::ErrorCode HandleRequest(RequestContext& request,
|
||||
ResponseContext& response) = 0;
|
||||
|
||||
protected:
|
||||
EndpointServer(z_cap_t cap) : endpoint_cap_(cap) {}
|
||||
|
||||
private:
|
||||
z_cap_t endpoint_cap_;
|
||||
|
||||
static const uint64_t kBufferSize = 1024;
|
||||
uint8_t recieve_buffer_[kBufferSize];
|
||||
|
||||
friend void EndpointServerThreadBootstrap(void* endpoint_server);
|
||||
void ServerThread();
|
||||
};
|
||||
|
||||
} // namespace mmth
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class RequestContext {
|
||||
public:
|
||||
RequestContext(void* buffer, uint64_t buffer_length)
|
||||
: buffer_(buffer), buffer_length_(buffer_length) {
|
||||
if (buffer_length_ < sizeof(uint64_t)) {
|
||||
request_id_ = -1;
|
||||
} else {
|
||||
request_id_ = *reinterpret_cast<uint64_t*>(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t request_id() { return request_id_; }
|
||||
|
||||
template <typename T>
|
||||
glcr::ErrorCode As(T** arg) {
|
||||
if (buffer_length_ < sizeof(T)) {
|
||||
return glcr::INVALID_ARGUMENT;
|
||||
}
|
||||
*arg = reinterpret_cast<T*>(buffer_);
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t request_id_;
|
||||
void* buffer_;
|
||||
uint64_t buffer_length_;
|
||||
};
|
|
@ -1,159 +0,0 @@
|
|||
#include "proc/process.h"
|
||||
|
||||
#include <glacier/status/error.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#include "ipc/endpoint_server.h"
|
||||
#include "ipc/port_client.h"
|
||||
#include "ipc/port_server.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/init.h"
|
||||
|
||||
#define MAM_PROC_DEBUG 0
|
||||
|
||||
namespace mmth {
|
||||
namespace {
|
||||
|
||||
typedef struct {
|
||||
char ident[16];
|
||||
uint16_t type;
|
||||
uint16_t machine;
|
||||
uint32_t version;
|
||||
uint64_t entry;
|
||||
uint64_t phoff;
|
||||
uint64_t shoff;
|
||||
uint32_t flags;
|
||||
uint16_t ehsize;
|
||||
uint16_t phentsize;
|
||||
uint16_t phnum;
|
||||
uint16_t shentsize;
|
||||
uint16_t shnum;
|
||||
uint16_t shstrndx;
|
||||
} Elf64Header;
|
||||
|
||||
typedef struct {
|
||||
uint32_t name;
|
||||
uint32_t type;
|
||||
uint64_t flags;
|
||||
uint64_t addr;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
uint32_t link;
|
||||
uint32_t info;
|
||||
uint64_t addralign;
|
||||
uint64_t entsize;
|
||||
} Elf64SectionHeader;
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
uint64_t offset;
|
||||
uint64_t vaddr;
|
||||
uint64_t paddr;
|
||||
uint64_t filesz;
|
||||
uint64_t memsz;
|
||||
uint64_t align;
|
||||
} Elf64ProgramHeader;
|
||||
|
||||
void memcpy(uint64_t base, uint64_t len, uint64_t dest) {
|
||||
uint8_t* srcptr = reinterpret_cast<uint8_t*>(base);
|
||||
uint8_t* destptr = reinterpret_cast<uint8_t*>(dest);
|
||||
for (uint64_t i = 0; i < len; i++) {
|
||||
destptr[i] = srcptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) {
|
||||
Elf64Header* header = reinterpret_cast<Elf64Header*>(base);
|
||||
Elf64ProgramHeader* programs =
|
||||
reinterpret_cast<Elf64ProgramHeader*>(base + header->phoff);
|
||||
for (uint64_t i = 0; i < header->phnum; i++) {
|
||||
Elf64ProgramHeader& program = programs[i];
|
||||
if (program.type != 1) {
|
||||
// Only load loadable types.
|
||||
// TODO: This may break if the stack is far away?
|
||||
continue;
|
||||
}
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln(glcr::StrFormat("Program:\n\tType: {}\n\tFlags: {}\n\t", program.type,
|
||||
program.flags));
|
||||
dbgln("Create mem object");
|
||||
#endif
|
||||
uint64_t page_offset = program.vaddr & 0xFFF;
|
||||
uint64_t mem_cap;
|
||||
uint64_t size = page_offset + program.memsz;
|
||||
check(ZMemoryObjectCreate(size, &mem_cap));
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln("Map Local");
|
||||
#endif
|
||||
uint64_t vaddr;
|
||||
check(ZAddressSpaceMap(gSelfVmasCap, 0, mem_cap, 0, &vaddr));
|
||||
uint8_t* offset = reinterpret_cast<uint8_t*>(vaddr);
|
||||
for (uint64_t j = 0; j < size; j++) {
|
||||
offset[j] = 0;
|
||||
}
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln("Copy");
|
||||
#endif
|
||||
memcpy(base + program.offset, program.filesz, vaddr + page_offset);
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln(glcr::StrFormat("Map Foreign: {x} {x} {x}",
|
||||
program.vaddr - page_offset, size, vaddr));
|
||||
#endif
|
||||
check(ZAddressSpaceMap(as_cap, program.vaddr - page_offset, mem_cap, 0,
|
||||
&vaddr));
|
||||
}
|
||||
return header->entry;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
glcr::ErrorOr<z_cap_t> SpawnProcessFromElfRegion(uint64_t program,
|
||||
z_cap_t yellowstone_client) {
|
||||
uint64_t proc_cap;
|
||||
uint64_t as_cap;
|
||||
uint64_t foreign_port_id;
|
||||
uint64_t port_cap;
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln("Port Create");
|
||||
#endif
|
||||
ASSIGN_OR_RETURN(PortServer server, PortServer::Create());
|
||||
ASSIGN_OR_RETURN(PortClient pclient, server.CreateClient());
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln("Spawn");
|
||||
#endif
|
||||
RET_ERR(ZProcessSpawn(gSelfProcCap, server.cap(), &proc_cap, &as_cap,
|
||||
&foreign_port_id));
|
||||
|
||||
uint64_t entry_point = LoadElfProgram(program, as_cap);
|
||||
|
||||
if (entry_point == 0) {
|
||||
crash("Entry Point == 0", glcr::INTERNAL);
|
||||
}
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln("Thread Create");
|
||||
#endif
|
||||
uint64_t thread_cap;
|
||||
RET_ERR(ZThreadCreate(proc_cap, &thread_cap));
|
||||
|
||||
uint64_t dup_proc_cap;
|
||||
RET_ERR(ZCapDuplicate(proc_cap, kZionPerm_All, &dup_proc_cap));
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, dup_proc_cap));
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_SELF_VMAS, as_cap));
|
||||
RET_ERR(pclient.WriteMessage<uint64_t>(Z_INIT_ENDPOINT, yellowstone_client));
|
||||
|
||||
#if MAM_PROC_DEBUG
|
||||
dbgln("Thread start");
|
||||
#endif
|
||||
RET_ERR(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0));
|
||||
|
||||
return proc_cap;
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <stdint.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
namespace mmth {
|
||||
|
||||
glcr::ErrorOr<z_cap_t> SpawnProcessFromElfRegion(uint64_t program,
|
||||
z_cap_t yellowstone_client);
|
||||
|
||||
} // namespace mmth
|
|
@ -1,31 +0,0 @@
|
|||
#include "sync/mutex.h"
|
||||
|
||||
#include <zcall.h>
|
||||
|
||||
namespace mmth {
|
||||
|
||||
Mutex::Mutex(Mutex&& other) : mutex_cap_(other.mutex_cap_) {
|
||||
other.mutex_cap_ = 0;
|
||||
}
|
||||
|
||||
Mutex& Mutex::operator=(Mutex&& other) {
|
||||
// TODO: Release existing mutex if it exists.
|
||||
mutex_cap_ = other.mutex_cap_;
|
||||
other.mutex_cap_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
glcr::ErrorOr<Mutex> Mutex::Create() {
|
||||
z_cap_t mutex_cap;
|
||||
RET_ERR(ZMutexCreate(&mutex_cap));
|
||||
return Mutex(mutex_cap);
|
||||
}
|
||||
|
||||
glcr::ErrorCode Mutex::Lock() {
|
||||
return static_cast<glcr::ErrorCode>(ZMutexLock(mutex_cap_));
|
||||
}
|
||||
glcr::ErrorCode Mutex::Release() {
|
||||
return static_cast<glcr::ErrorCode>(ZMutexRelease(mutex_cap_));
|
||||
}
|
||||
|
||||
} // namespace mmth
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
namespace mmth {
|
||||
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex(const Mutex&) = delete;
|
||||
Mutex(Mutex&&);
|
||||
Mutex& operator=(Mutex&&);
|
||||
|
||||
static glcr::ErrorOr<Mutex> Create();
|
||||
|
||||
glcr::ErrorCode Lock();
|
||||
glcr::ErrorCode Release();
|
||||
|
||||
private:
|
||||
z_cap_t mutex_cap_;
|
||||
|
||||
Mutex(z_cap_t mutex_cap) : mutex_cap_(mutex_cap) {}
|
||||
};
|
||||
|
||||
} // namespace mmth
|
|
@ -1,25 +1,2 @@
|
|||
add_executable(yellowstone
|
||||
hw/gpt.cpp
|
||||
hw/pcie.cpp
|
||||
yellowstone.cpp
|
||||
yellowstone_server.cpp
|
||||
)
|
||||
|
||||
target_include_directories(yellowstone
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(yellowstone
|
||||
denali_yunq
|
||||
mammoth
|
||||
glacier
|
||||
victoriafalls_yunq
|
||||
yellowstone_yunq
|
||||
)
|
||||
|
||||
set_target_properties(yellowstone PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
|
||||
)
|
||||
|
||||
yunq_gen(lib/yellowstone lib yellowstone)
|
||||
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
#include "hw/gpt.h"
|
||||
|
||||
#include <glacier/memory/move.h>
|
||||
#include <glacier/status/error.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#define GPT_DEBUG 0
|
||||
|
||||
const uint64_t kSectorSize = 512;
|
||||
|
||||
const uint64_t kGptPartitionSignature = 0x54524150'20494645;
|
||||
|
||||
const uint64_t kLfsDataLow = 0x477284830fc63daf;
|
||||
const uint64_t kLfsDataHigh = 0xe47d47d8693d798e;
|
||||
|
||||
struct MbrPartition {
|
||||
uint8_t boot_indicator;
|
||||
uint8_t starting_chs[3];
|
||||
uint8_t os_type;
|
||||
uint8_t ending_chs[3];
|
||||
uint32_t starting_lba;
|
||||
uint32_t ending_lba;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ParititionHeader {
|
||||
uint64_t signature;
|
||||
uint32_t revision;
|
||||
uint32_t header_size;
|
||||
uint32_t crc_32;
|
||||
uint32_t reserved;
|
||||
uint64_t lba_self;
|
||||
uint64_t lba_mirror;
|
||||
uint64_t lba_min;
|
||||
uint64_t lba_max;
|
||||
uint64_t guid_low;
|
||||
uint64_t guid_high;
|
||||
uint64_t lba_partition_entries;
|
||||
uint32_t num_partitions;
|
||||
uint32_t parition_entry_size;
|
||||
uint32_t partition_entry_crc32;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PartitionEntry {
|
||||
uint64_t type_guid_low;
|
||||
uint64_t type_guid_high;
|
||||
uint64_t part_guid_low;
|
||||
uint64_t part_guid_high;
|
||||
uint64_t lba_start;
|
||||
uint64_t lba_end;
|
||||
uint64_t attributes;
|
||||
char partition_name[72];
|
||||
} __attribute__((packed));
|
||||
|
||||
GptReader::GptReader(glcr::UniquePtr<DenaliClient> denali)
|
||||
: denali_(glcr::Move(denali)) {}
|
||||
|
||||
glcr::Status GptReader::ParsePartitionTables() {
|
||||
ReadRequest req;
|
||||
req.set_device_id(0);
|
||||
req.mutable_block().set_lba(0);
|
||||
req.mutable_block().set_size(2);
|
||||
ReadResponse resp;
|
||||
RETURN_ERROR(denali_->Read(req, resp));
|
||||
mmth::OwnedMemoryRegion lba_1_and_2 =
|
||||
mmth::OwnedMemoryRegion::FromCapability(resp.memory());
|
||||
uint16_t* mbr_sig = reinterpret_cast<uint16_t*>(lba_1_and_2.vaddr() + 0x1FE);
|
||||
if (*mbr_sig != 0xAA55) {
|
||||
return glcr::FailedPrecondition(
|
||||
glcr::StrFormat("Invalid MBR Sig: {x}", *mbr_sig));
|
||||
}
|
||||
MbrPartition* first_partition =
|
||||
reinterpret_cast<MbrPartition*>(lba_1_and_2.vaddr() + 0x1BE);
|
||||
|
||||
if (first_partition->boot_indicator != 0) {
|
||||
// FIXME: This shouldn't be set but I can't figure out why it is.
|
||||
dbgln("WARN: Boot indicator set: {}", first_partition->boot_indicator);
|
||||
}
|
||||
if (first_partition->os_type != 0xEE) {
|
||||
return glcr::FailedPrecondition(
|
||||
glcr::StrFormat("Incorrect OS type: {x}", first_partition->os_type));
|
||||
}
|
||||
#if GPT_DEBUG
|
||||
dbgln("LBAs: ({x}, {x})", first_partition->starting_lba,
|
||||
first_partition->ending_lba);
|
||||
#endif
|
||||
|
||||
// FIXME: Don't hardcode sector size.
|
||||
ParititionHeader* header =
|
||||
reinterpret_cast<ParititionHeader*>(lba_1_and_2.vaddr() + 512);
|
||||
|
||||
uint64_t num_partitions = header->num_partitions;
|
||||
uint64_t entry_size = header->parition_entry_size;
|
||||
uint64_t num_blocks = (num_partitions * entry_size) / 512;
|
||||
|
||||
#if GPT_DEBUG
|
||||
dbgln("signature {}", header->signature);
|
||||
dbgln("lba_partition_entries {x}", header->lba_partition_entries);
|
||||
dbgln("num_partitions: {x}", num_partitions);
|
||||
dbgln("partition_entry_size: {x}", entry_size);
|
||||
dbgln("Num blocks: {x}", num_blocks);
|
||||
#endif
|
||||
|
||||
req.set_device_id(0);
|
||||
req.mutable_block().set_lba(header->lba_partition_entries);
|
||||
req.mutable_block().set_size(num_blocks);
|
||||
RETURN_ERROR(denali_->Read(req, resp));
|
||||
mmth::OwnedMemoryRegion part_table =
|
||||
mmth::OwnedMemoryRegion::FromCapability(resp.memory());
|
||||
for (uint64_t i = 0; i < num_partitions; i++) {
|
||||
PartitionEntry* entry = reinterpret_cast<PartitionEntry*>(
|
||||
part_table.vaddr() + (i * entry_size));
|
||||
if (entry->type_guid_low != 0 || entry->type_guid_high != 0) {
|
||||
#if GPT_DEBUG
|
||||
dbgln("Entry {}", i);
|
||||
dbgln("T Guid: {x}-{x}", entry->type_guid_high, entry->type_guid_low);
|
||||
dbgln("P Guid: {x}-{x}", entry->part_guid_high, entry->part_guid_low);
|
||||
dbgln("LBA: {x}, {x}", entry->lba_start, entry->lba_end);
|
||||
dbgln("Attrs: {x}", entry->attributes);
|
||||
#endif
|
||||
// For now we hardcode these values to the type that is
|
||||
// created in our setup script.
|
||||
// FIXME: Set up our own root partition type guid at some
|
||||
// point.
|
||||
if (entry->type_guid_low == kLfsDataLow &&
|
||||
entry->type_guid_high == kLfsDataHigh) {
|
||||
primary_partition_lba_ = entry->lba_start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <denali/denali.yunq.client.h>
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <glacier/status/error.h>
|
||||
#include <stdint.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
class GptReader {
|
||||
public:
|
||||
GptReader(glcr::UniquePtr<DenaliClient> denali);
|
||||
|
||||
glcr::Status ParsePartitionTables();
|
||||
|
||||
uint64_t GetPrimaryPartitionLba() { return primary_partition_lba_; }
|
||||
|
||||
private:
|
||||
glcr::UniquePtr<DenaliClient> denali_;
|
||||
uint64_t primary_partition_lba_;
|
||||
};
|
|
@ -1,110 +0,0 @@
|
|||
#include "hw/pcie.h"
|
||||
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/init.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#define PCI_DEBUG 1
|
||||
|
||||
namespace {
|
||||
|
||||
PciDeviceHeader* PciHeader(uint64_t base, uint64_t bus, uint64_t dev,
|
||||
uint64_t fun) {
|
||||
return reinterpret_cast<PciDeviceHeader*>(base + (bus << 20) + (dev << 15) +
|
||||
(fun << 12));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PciReader::PciReader() {
|
||||
uint64_t vaddr;
|
||||
check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootPciVmmoCap, 0, &vaddr));
|
||||
|
||||
PciDump(vaddr);
|
||||
|
||||
header_ = PciHeader(vaddr, 0, 0, 0);
|
||||
}
|
||||
|
||||
z_cap_t PciReader::GetAhciVmmo() {
|
||||
uint64_t new_cap;
|
||||
check(ZMemoryObjectDuplicate(gBootPciVmmoCap, achi_device_offset_,
|
||||
kPcieConfigurationSize, &new_cap));
|
||||
return new_cap;
|
||||
}
|
||||
|
||||
z_cap_t PciReader::GetXhciVmmo() {
|
||||
uint64_t new_cap;
|
||||
check(ZMemoryObjectDuplicate(gBootPciVmmoCap, xhci_device_offset_,
|
||||
kPcieConfigurationSize, &new_cap));
|
||||
return new_cap;
|
||||
}
|
||||
|
||||
void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev,
|
||||
uint64_t fun) {
|
||||
PciDeviceHeader* hdr = PciHeader(base, bus, dev, fun);
|
||||
if (hdr->vendor_id == 0xFFFF) {
|
||||
return;
|
||||
}
|
||||
#if PCI_DEBUG
|
||||
dbgln(
|
||||
"[{}.{}.{}] (Vendor, Device): ({x}, {x}), (Type, Class, Sub, PIF): ({}, "
|
||||
"{x}, {x}, {x})",
|
||||
bus, dev, fun, hdr->vendor_id, hdr->device_id, hdr->header_type,
|
||||
hdr->class_code, hdr->subclass, hdr->prog_interface);
|
||||
#endif
|
||||
|
||||
if ((hdr->class_code == 0x6) && (hdr->subclass == 0x4)) {
|
||||
dbgln("FIXME: Handle PCI to PCI bridge.");
|
||||
}
|
||||
if (hdr->class_code == 0x1) {
|
||||
#if PCI_DEBUG
|
||||
dbgln("SATA Device at: {x}", reinterpret_cast<uint64_t>(hdr) - base);
|
||||
#endif
|
||||
achi_device_offset_ = reinterpret_cast<uint64_t>(hdr) - base;
|
||||
}
|
||||
|
||||
if (hdr->class_code == 0xC && hdr->subclass == 0x3) {
|
||||
if (hdr->prog_interface == 0x30) {
|
||||
xhci_device_offset_ = reinterpret_cast<uint64_t>(hdr) - base;
|
||||
} else {
|
||||
dbgln("WARN: Non-XHCI USB Controller found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PciReader::DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) {
|
||||
PciDeviceHeader* hdr = PciHeader(base, bus, dev, 0);
|
||||
if (hdr->vendor_id == 0xFFFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionDump(base, bus, dev, 0);
|
||||
|
||||
// Device is multifunction.
|
||||
if (hdr->header_type & 0x80) {
|
||||
for (uint64_t f = 1; f < 0x8; f++) {
|
||||
FunctionDump(base, bus, dev, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PciReader::BusDump(uint64_t base, uint64_t bus) {
|
||||
for (uint64_t dev = 0; dev < 0x20; dev++) {
|
||||
DeviceDump(base, bus, dev);
|
||||
}
|
||||
}
|
||||
|
||||
void PciReader::PciDump(uint64_t base) {
|
||||
PciDeviceHeader* hdr = PciHeader(base, 0, 0, 0);
|
||||
if ((hdr->header_type & 0x80) == 0) {
|
||||
// Single bus system.
|
||||
BusDump(base, 0);
|
||||
} else {
|
||||
for (uint64_t f = 0; f < 8; f++) {
|
||||
PciDeviceHeader* f_hdr = PciHeader(base, 0, 0, f);
|
||||
if (f_hdr->vendor_id != 0xFFFF) {
|
||||
BusDump(base, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
struct PciDeviceHeader {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint16_t command_reg;
|
||||
uint16_t status_reg;
|
||||
uint8_t revision;
|
||||
uint8_t prog_interface;
|
||||
uint8_t subclass;
|
||||
uint8_t class_code;
|
||||
uint8_t cache_line_size;
|
||||
uint8_t latency_timer;
|
||||
uint8_t header_type;
|
||||
uint8_t bist;
|
||||
} __attribute__((packed));
|
||||
|
||||
// TODO: Figure out if it safe to hardcode this.
|
||||
// For the memory mapped access to PCI, it may be true that
|
||||
// each configuration item is always the size of a single page.
|
||||
const uint64_t kPcieConfigurationSize = 0x1000;
|
||||
|
||||
class PciReader {
|
||||
public:
|
||||
PciReader();
|
||||
|
||||
z_cap_t GetAhciVmmo();
|
||||
z_cap_t GetXhciVmmo();
|
||||
|
||||
private:
|
||||
PciDeviceHeader* header_;
|
||||
|
||||
uint64_t achi_device_offset_ = 0;
|
||||
uint64_t xhci_device_offset_ = 0;
|
||||
|
||||
void PciDump(uint64_t vaddr);
|
||||
void BusDump(uint64_t base, uint64_t bus);
|
||||
void DeviceDump(uint64_t base, uint64_t bus, uint64_t dev);
|
||||
void FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, uint64_t fun);
|
||||
};
|
|
@ -1,70 +0,0 @@
|
|||
#include <glacier/string/str_format.h>
|
||||
#include <glacier/string/str_split.h>
|
||||
#include <mammoth/file/file.h>
|
||||
#include <mammoth/proc/process.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/init.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <zcall.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "hw/gpt.h"
|
||||
#include "hw/pcie.h"
|
||||
#include "yellowstone_server.h"
|
||||
|
||||
glcr::ErrorCode SpawnProcess(z_cap_t vmmo_cap, z_cap_t yellowstone_cap) {
|
||||
mmth::OwnedMemoryRegion region =
|
||||
mmth::OwnedMemoryRegion::FromCapability(vmmo_cap);
|
||||
auto error_or =
|
||||
mmth::SpawnProcessFromElfRegion(region.vaddr(), yellowstone_cap);
|
||||
if (error_or.ok()) {
|
||||
return glcr::OK;
|
||||
}
|
||||
return error_or.error();
|
||||
}
|
||||
|
||||
uint64_t main(uint64_t port_cap) {
|
||||
check(ParseInitPort(port_cap));
|
||||
dbgln("Yellowstone Initializing.");
|
||||
|
||||
ASSIGN_OR_RETURN(auto server, yellowstone::YellowstoneServer::Create());
|
||||
Thread server_thread = server->RunServer();
|
||||
|
||||
ASSIGN_OR_RETURN(uint64_t client_cap, server->CreateClientCap());
|
||||
check(SpawnProcess(gBootDenaliVmmoCap, client_cap));
|
||||
|
||||
server->WaitDenaliRegistered();
|
||||
|
||||
ASSIGN_OR_RETURN(client_cap, server->CreateClientCap());
|
||||
check(SpawnProcess(gBootVictoriaFallsVmmoCap, client_cap));
|
||||
|
||||
server->WaitVictoriaFallsRegistered();
|
||||
|
||||
dbgln("VFS Available.");
|
||||
|
||||
mmth::File init_file = mmth::File::Open("/init.txt");
|
||||
|
||||
glcr::Vector<glcr::StringView> files =
|
||||
glcr::StrSplit(init_file.as_str(), '\n');
|
||||
|
||||
for (glcr::StringView& file : files) {
|
||||
if (!file.empty()) {
|
||||
// TODO: Implement startup dependencies.
|
||||
if (file == "teton") {
|
||||
server->WaitVoyageursRegistered();
|
||||
}
|
||||
mmth::File binary = mmth::File::Open(glcr::StrFormat("/bin/{}", file));
|
||||
|
||||
ASSIGN_OR_RETURN(client_cap, server->CreateClientCap());
|
||||
auto error_or = mmth::SpawnProcessFromElfRegion(
|
||||
(uint64_t)binary.raw_ptr(), client_cap);
|
||||
if (!error_or.ok()) {
|
||||
check(error_or.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check(server_thread.Join());
|
||||
dbgln("Yellowstone Finished Successfully.");
|
||||
return 0;
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
#include "yellowstone_server.h"
|
||||
|
||||
#include <denali/denali.yunq.client.h>
|
||||
#include <glacier/string/string.h>
|
||||
#include <mammoth/file/file.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/init.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <zcall.h>
|
||||
|
||||
#include "hw/gpt.h"
|
||||
#include "hw/pcie.h"
|
||||
|
||||
namespace yellowstone {
|
||||
namespace {
|
||||
|
||||
struct PartitionInfo {
|
||||
uint64_t device_id;
|
||||
uint64_t partition_lba;
|
||||
};
|
||||
|
||||
glcr::ErrorOr<PartitionInfo> HandleDenaliRegistration(z_cap_t endpoint_cap) {
|
||||
GptReader reader(
|
||||
glcr::UniquePtr<DenaliClient>(new DenaliClient(endpoint_cap)));
|
||||
|
||||
auto status = reader.ParsePartitionTables();
|
||||
if (!status.ok()) {
|
||||
dbgln("GPT Reader: {}", status.message());
|
||||
return status.code();
|
||||
}
|
||||
|
||||
return PartitionInfo{.device_id = 0,
|
||||
.partition_lba = reader.GetPrimaryPartitionLba()};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> YellowstoneServer::Create() {
|
||||
z_cap_t endpoint_cap;
|
||||
RET_ERR(ZEndpointCreate(&endpoint_cap));
|
||||
|
||||
return glcr::UniquePtr<YellowstoneServer>(
|
||||
new YellowstoneServer(endpoint_cap));
|
||||
}
|
||||
|
||||
YellowstoneServer::YellowstoneServer(z_cap_t endpoint_cap)
|
||||
: YellowstoneServerBase(endpoint_cap) {}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetAhciInfo(AhciInfo& info) {
|
||||
info.set_ahci_region(pci_reader_.GetAhciVmmo());
|
||||
info.set_region_length(kPcieConfigurationSize);
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetXhciInfo(XhciInfo& info) {
|
||||
info.set_xhci_region(pci_reader_.GetXhciVmmo());
|
||||
info.set_region_length(kPcieConfigurationSize);
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetFramebufferInfo(
|
||||
FramebufferInfo& info) {
|
||||
// FIXME: Don't do this for each request.
|
||||
mmth::OwnedMemoryRegion region =
|
||||
mmth::OwnedMemoryRegion::FromCapability(gBootFramebufferVmmoCap);
|
||||
ZFramebufferInfo* fb = reinterpret_cast<ZFramebufferInfo*>(region.vaddr());
|
||||
|
||||
info.set_address_phys(fb->address_phys);
|
||||
info.set_width(fb->width);
|
||||
info.set_height(fb->height);
|
||||
info.set_pitch(fb->pitch);
|
||||
info.set_bpp(fb->bpp);
|
||||
info.set_memory_model(fb->memory_model);
|
||||
info.set_red_mask_size(fb->red_mask_size);
|
||||
info.set_red_mask_shift(fb->red_mask_shift);
|
||||
info.set_green_mask_size(fb->green_mask_size);
|
||||
info.set_green_mask_shift(fb->green_mask_shift);
|
||||
info.set_blue_mask_size(fb->blue_mask_size);
|
||||
info.set_blue_mask_shift(fb->blue_mask_shift);
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetDenali(DenaliInfo& info) {
|
||||
if (!endpoint_map_.Contains("denali")) {
|
||||
return glcr::NotFound("Denali Capability Not registered");
|
||||
}
|
||||
z_cap_t new_denali;
|
||||
check(ZCapDuplicate(endpoint_map_.at("denali"), kZionPerm_All, &new_denali));
|
||||
info.set_denali_endpoint(new_denali);
|
||||
info.set_device_id(device_id_);
|
||||
info.set_lba_offset(lba_offset_);
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleRegisterEndpoint(
|
||||
const RegisterEndpointRequest& req) {
|
||||
dbgln("Registering {}.", req.endpoint_name().view());
|
||||
check(endpoint_map_.Insert(req.endpoint_name(), req.endpoint_capability()));
|
||||
if (req.endpoint_name() == "denali") {
|
||||
z_cap_t dup_cap;
|
||||
check(ZCapDuplicate(req.endpoint_capability(), kZionPerm_All, &dup_cap));
|
||||
auto part_info_or = HandleDenaliRegistration(dup_cap);
|
||||
if (!part_info_or.ok()) {
|
||||
check(part_info_or.error());
|
||||
}
|
||||
device_id_ = part_info_or.value().device_id;
|
||||
lba_offset_ = part_info_or.value().partition_lba;
|
||||
|
||||
has_denali_semaphore_.Signal();
|
||||
} else if (req.endpoint_name() == "victoriafalls") {
|
||||
// FIXME: Probably make a separate copy for use within yellowstone vs
|
||||
// transmit to other processes.
|
||||
mmth::SetVfsCap(req.endpoint_capability());
|
||||
has_victoriafalls_semaphore_.Signal();
|
||||
} else if (req.endpoint_name() == "voyageurs") {
|
||||
has_voyageurs_.Signal();
|
||||
} else {
|
||||
dbgln("[WARN] Got endpoint cap type: {}", req.endpoint_name().cstr());
|
||||
}
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status YellowstoneServer::HandleGetEndpoint(const GetEndpointRequest& req,
|
||||
Endpoint& resp) {
|
||||
if (!endpoint_map_.Contains(req.endpoint_name())) {
|
||||
return glcr::NotFound(
|
||||
glcr::StrFormat("Endpoint '{}' not found.", req.endpoint_name()));
|
||||
}
|
||||
z_cap_t cap = endpoint_map_.at(req.endpoint_name());
|
||||
z_cap_t new_cap;
|
||||
check(ZCapDuplicate(cap, kZionPerm_All, &new_cap));
|
||||
resp.set_endpoint(new_cap);
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
void YellowstoneServer::WaitDenaliRegistered() { has_denali_semaphore_.Wait(); }
|
||||
|
||||
void YellowstoneServer::WaitVictoriaFallsRegistered() {
|
||||
has_victoriafalls_semaphore_.Wait();
|
||||
}
|
||||
|
||||
void YellowstoneServer::WaitVoyageursRegistered() { has_voyageurs_.Wait(); }
|
||||
|
||||
} // namespace yellowstone
|
|
@ -1,46 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/hash_map.h>
|
||||
#include <glacier/memory/shared_ptr.h>
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <mammoth/sync/semaphore.h>
|
||||
#include <victoriafalls/victoriafalls.yunq.client.h>
|
||||
|
||||
#include "hw/pcie.h"
|
||||
#include "lib/yellowstone/yellowstone.yunq.server.h"
|
||||
|
||||
namespace yellowstone {
|
||||
|
||||
class YellowstoneServer : public YellowstoneServerBase {
|
||||
public:
|
||||
static glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> Create();
|
||||
|
||||
glcr::Status HandleGetAhciInfo(AhciInfo&) override;
|
||||
glcr::Status HandleGetXhciInfo(XhciInfo&) override;
|
||||
glcr::Status HandleGetFramebufferInfo(FramebufferInfo&) override;
|
||||
glcr::Status HandleGetDenali(DenaliInfo&) override;
|
||||
glcr::Status HandleRegisterEndpoint(const RegisterEndpointRequest&) override;
|
||||
glcr::Status HandleGetEndpoint(const GetEndpointRequest&, Endpoint&) override;
|
||||
|
||||
void WaitDenaliRegistered();
|
||||
void WaitVictoriaFallsRegistered();
|
||||
void WaitVoyageursRegistered();
|
||||
|
||||
private:
|
||||
glcr::HashMap<glcr::String, z_cap_t> endpoint_map_;
|
||||
|
||||
uint64_t device_id_ = 0;
|
||||
uint64_t lba_offset_ = 0;
|
||||
glcr::SharedPtr<VFSClient> vfs_client_;
|
||||
|
||||
PciReader pci_reader_;
|
||||
|
||||
mmth::Semaphore has_denali_semaphore_;
|
||||
mmth::Semaphore has_victoriafalls_semaphore_;
|
||||
mmth::Semaphore has_voyageurs_;
|
||||
|
||||
YellowstoneServer(z_cap_t endpoint_cap);
|
||||
};
|
||||
|
||||
} // namespace yellowstone
|
Loading…
Reference in New Issue