2023-06-22 02:19:16 -07:00
|
|
|
#include "yellowstone_server.h"
|
|
|
|
|
|
|
|
#include <denali/denali.h>
|
|
|
|
#include <glacier/string/string.h>
|
|
|
|
#include <mammoth/debug.h>
|
2023-07-05 16:03:20 -07:00
|
|
|
#include <mammoth/init.h>
|
|
|
|
#include <mammoth/process.h>
|
2023-06-22 02:19:16 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "hw/gpt.h"
|
2023-08-01 17:46:26 -07:00
|
|
|
#include "hw/pcie.h"
|
2023-06-22 02:19:16 -07:00
|
|
|
#include "include/yellowstone.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
void RegistrationThreadBootstrap(void* yellowstone) {
|
|
|
|
dbgln("Yellowstone registration starting");
|
|
|
|
static_cast<YellowstoneServer*>(yellowstone)->RegistrationThread();
|
|
|
|
}
|
|
|
|
|
2023-07-05 16:03:20 -07:00
|
|
|
struct PartitionInfo {
|
|
|
|
uint64_t device_id;
|
|
|
|
uint64_t partition_lba;
|
|
|
|
};
|
|
|
|
|
|
|
|
glcr::ErrorOr<PartitionInfo> HandleDenaliRegistration(z_cap_t endpoint_cap) {
|
2023-06-26 11:54:36 -07:00
|
|
|
GptReader reader(glcr::UniquePtr<DenaliClient>(
|
|
|
|
new DenaliClient(EndpointClient::AdoptEndpoint(endpoint_cap))));
|
2023-06-22 02:19:16 -07:00
|
|
|
|
2023-07-05 16:03:20 -07:00
|
|
|
RET_ERR(reader.ParsePartitionTables());
|
|
|
|
|
|
|
|
return PartitionInfo{.device_id = 0,
|
|
|
|
.partition_lba = reader.GetPrimaryPartitionLba()};
|
2023-06-22 02:19:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2023-06-26 11:38:17 -07:00
|
|
|
glcr::ErrorOr<glcr::UniquePtr<YellowstoneServer>> YellowstoneServer::Create() {
|
2023-08-01 15:52:08 -07:00
|
|
|
z_cap_t cap;
|
|
|
|
RET_ERR(ZEndpointCreate(&cap));
|
2023-06-26 08:41:44 -07:00
|
|
|
ASSIGN_OR_RETURN(PortServer port, PortServer::Create());
|
2023-08-01 15:52:08 -07:00
|
|
|
return glcr::UniquePtr<YellowstoneServer>(new YellowstoneServer(cap, port));
|
2023-06-22 02:19:16 -07:00
|
|
|
}
|
|
|
|
|
2023-08-01 15:52:08 -07:00
|
|
|
YellowstoneServer::YellowstoneServer(z_cap_t endpoint_cap, PortServer port)
|
2023-10-24 18:24:26 -07:00
|
|
|
: YellowstoneServerBase(endpoint_cap), register_port_(port) {}
|
2023-06-22 02:19:16 -07:00
|
|
|
|
|
|
|
Thread YellowstoneServer::RunRegistration() {
|
|
|
|
return Thread(RegistrationThreadBootstrap, this);
|
|
|
|
}
|
|
|
|
|
2023-10-24 18:24:26 -07:00
|
|
|
glcr::ErrorCode YellowstoneServer::HandleGetAhciInfo(const Empty&,
|
|
|
|
AhciInfo& info) {
|
|
|
|
info.set_ahci_region(pci_reader_.GetAhciVmmo());
|
|
|
|
info.set_region_length(kPcieConfigurationSize);
|
|
|
|
return glcr::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
glcr::ErrorCode YellowstoneServer::HandleGetDenali(const Empty&,
|
|
|
|
DenaliInfo& info) {
|
|
|
|
z_cap_t new_denali;
|
|
|
|
check(ZCapDuplicate(denali_cap_, &new_denali));
|
|
|
|
info.set_denali_endpoint(new_denali);
|
|
|
|
info.set_device_id(device_id_);
|
|
|
|
info.set_lba_offset(lba_offset_);
|
|
|
|
return glcr::OK;
|
|
|
|
}
|
|
|
|
glcr::ErrorCode YellowstoneServer::HandleGetRegister(const Empty&,
|
|
|
|
RegisterInfo& info) {
|
|
|
|
auto client_or = register_port_.CreateClient();
|
|
|
|
if (!client_or.ok()) {
|
|
|
|
dbgln("Error creating register client: %u", client_or.error());
|
|
|
|
return glcr::INTERNAL;
|
2023-06-22 02:19:16 -07:00
|
|
|
}
|
2023-10-24 18:24:26 -07:00
|
|
|
info.set_register_port(client_or.value().cap());
|
2023-08-01 15:52:08 -07:00
|
|
|
return glcr::OK;
|
2023-06-22 02:19:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void YellowstoneServer::RegistrationThread() {
|
|
|
|
while (true) {
|
|
|
|
uint64_t num_bytes = kBufferSize;
|
|
|
|
z_cap_t endpoint_cap;
|
|
|
|
// FIXME: Better error handling here.
|
|
|
|
check(register_port_.RecvCap(&num_bytes, registration_buffer_,
|
|
|
|
&endpoint_cap));
|
|
|
|
glcr::String name(registration_buffer_);
|
|
|
|
if (name == "denali") {
|
|
|
|
denali_cap_ = endpoint_cap;
|
2023-07-05 16:03:20 -07:00
|
|
|
auto part_info_or = HandleDenaliRegistration(denali_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;
|
|
|
|
|
|
|
|
uint64_t vaddr;
|
|
|
|
check(
|
|
|
|
ZAddressSpaceMap(gSelfVmasCap, 0, gBootVictoriaFallsVmmoCap, &vaddr));
|
2023-08-01 15:52:08 -07:00
|
|
|
auto client_or = CreateClient();
|
2023-07-05 16:03:20 -07:00
|
|
|
if (!client_or.ok()) {
|
|
|
|
check(client_or.error());
|
|
|
|
}
|
2023-10-24 18:24:26 -07:00
|
|
|
check(SpawnProcessFromElfRegion(vaddr, client_or.value().Capability()));
|
2023-06-22 02:19:16 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name == "victoriafalls") {
|
|
|
|
victoria_falls_cap_ = endpoint_cap;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dbgln("[WARN] Got endpoint cap type:");
|
|
|
|
dbgln(name.cstr());
|
|
|
|
}
|
|
|
|
}
|