From 3bacfea1830da807546faec15af0cef840497ff5 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Tue, 6 Feb 2024 20:49:43 -0800 Subject: [PATCH] [Yellowstone] Add method to get XHCI configuration space. --- sys/yellowstone/hw/pcie.cpp | 17 ++++++- sys/yellowstone/hw/pcie.h | 2 + .../lib/yellowstone/yellowstone.yunq | 6 +++ .../yellowstone/yellowstone.yunq.client.cpp | 44 ++++++++++++++++++- .../lib/yellowstone/yellowstone.yunq.client.h | 4 ++ .../lib/yellowstone/yellowstone.yunq.cpp | 43 ++++++++++++++++++ .../lib/yellowstone/yellowstone.yunq.h | 30 +++++++++++++ .../yellowstone/yellowstone.yunq.server.cpp | 19 +++++++- .../lib/yellowstone/yellowstone.yunq.server.h | 4 ++ sys/yellowstone/yellowstone_server.cpp | 6 +++ sys/yellowstone/yellowstone_server.h | 1 + 11 files changed, 172 insertions(+), 4 deletions(-) diff --git a/sys/yellowstone/hw/pcie.cpp b/sys/yellowstone/hw/pcie.cpp index 08a2e7b..ebec187 100644 --- a/sys/yellowstone/hw/pcie.cpp +++ b/sys/yellowstone/hw/pcie.cpp @@ -4,7 +4,7 @@ #include #include -#define PCI_DEBUG 0 +#define PCI_DEBUG 1 namespace { @@ -32,6 +32,13 @@ z_cap_t PciReader::GetAhciVmmo() { 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); @@ -55,6 +62,14 @@ void PciReader::FunctionDump(uint64_t base, uint64_t bus, uint64_t dev, #endif achi_device_offset_ = reinterpret_cast(hdr) - base; } + + if (hdr->class_code == 0xC && hdr->subclass == 0x3) { + if (hdr->prog_interface == 0x30) { + xhci_device_offset_ = reinterpret_cast(hdr) - base; + } else { + dbgln("WARN: Non-XHCI USB Controller found"); + } + } } void PciReader::DeviceDump(uint64_t base, uint64_t bus, uint64_t dev) { diff --git a/sys/yellowstone/hw/pcie.h b/sys/yellowstone/hw/pcie.h index d9e5778..6b73b31 100644 --- a/sys/yellowstone/hw/pcie.h +++ b/sys/yellowstone/hw/pcie.h @@ -28,11 +28,13 @@ class PciReader { 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); diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq b/sys/yellowstone/lib/yellowstone/yellowstone.yunq index 95b3dfb..3bf9d9d 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq @@ -4,6 +4,7 @@ interface Yellowstone { method RegisterEndpoint(RegisterEndpointRequest) -> (); method GetEndpoint(GetEndpointRequest) -> (Endpoint); method GetAhciInfo() -> (AhciInfo); + method GetXhciInfo() -> (XhciInfo); method GetFramebufferInfo() -> (FramebufferInfo); method GetDenali() -> (DenaliInfo); } @@ -26,6 +27,11 @@ message AhciInfo { u64 region_length; } +message XhciInfo { + capability xhci_region; + u64 region_length; +} + message FramebufferInfo { u64 address_phys; u64 width; diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.cpp b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.cpp index 03352e1..05f451c 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.cpp +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.cpp @@ -137,7 +137,7 @@ glcr::Status YellowstoneClient::GetAhciInfo(AhciInfo& response) { -glcr::Status YellowstoneClient::GetFramebufferInfo(FramebufferInfo& response) { +glcr::Status YellowstoneClient::GetXhciInfo(XhciInfo& response) { uint64_t buffer_size = kBufferSize; uint64_t cap_size = kCapBufferSize; @@ -177,7 +177,7 @@ glcr::Status YellowstoneClient::GetFramebufferInfo(FramebufferInfo& response) { -glcr::Status YellowstoneClient::GetDenali(DenaliInfo& response) { +glcr::Status YellowstoneClient::GetFramebufferInfo(FramebufferInfo& response) { uint64_t buffer_size = kBufferSize; uint64_t cap_size = kCapBufferSize; @@ -217,5 +217,45 @@ glcr::Status YellowstoneClient::GetDenali(DenaliInfo& response) { +glcr::Status YellowstoneClient::GetDenali(DenaliInfo& response) { + + uint64_t buffer_size = kBufferSize; + uint64_t cap_size = kCapBufferSize; + + const uint32_t kSentinel = 0xBEEFDEAD; + buffer_.WriteAt(0, kSentinel); + buffer_.WriteAt(8, 5); + + cap_buffer_.Reset(); + + uint64_t length = 0; + + + buffer_.WriteAt(4, 16 + length); + + z_cap_t reply_port_cap; + RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap)); + + // FIXME: Add a way to zero out the first buffer. + RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr())); + + if (buffer_.At(0) != kSentinel) { + return glcr::InvalidResponse("Got an invalid response from server."); + } + + // Check Response Code. + RET_ERR(buffer_.At(8)); + + + yunq::MessageView resp_view(buffer_, 16); + RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_)); + + + return glcr::OK; +} + + + + } // namepace yellowstone diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.h b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.h index 1793f69..afe8619 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.h +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.client.h @@ -34,6 +34,10 @@ class YellowstoneClient { + [[nodiscard]] glcr::Status GetXhciInfo(XhciInfo& response); + + + [[nodiscard]] glcr::Status GetFramebufferInfo(FramebufferInfo& response); diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.cpp b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.cpp index 78827d7..1134546 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.cpp +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.cpp @@ -178,6 +178,49 @@ uint64_t AhciInfo::SerializeInternal(yunq::Serializer& serializer) const { return serializer.size(); } +glcr::Status XhciInfo::ParseFromBytes(const yunq::MessageView& message) { + RETURN_ERROR(ParseFromBytesInternal(message)); + // Parse xhci_region. + ASSIGN_OR_RETURN(xhci_region_, message.ReadCapability(0)); + return glcr::Status::Ok(); +} + +glcr::Status XhciInfo::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) { + RETURN_ERROR(ParseFromBytesInternal(message)); + // Parse xhci_region. + ASSIGN_OR_RETURN(xhci_region_, message.ReadCapability(0, caps)); + return glcr::Status::Ok(); +} + +glcr::Status XhciInfo::ParseFromBytesInternal(const yunq::MessageView& message) { + RETURN_ERROR(message.CheckHeader()); + // Parse xhci_region. + // Parse region_length. + ASSIGN_OR_RETURN(region_length_, message.ReadField(1)); + + return glcr::Status::Ok(); +} + +uint64_t XhciInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { + yunq::Serializer serializer(bytes, offset, 2); + return SerializeInternal(serializer); +} + +uint64_t XhciInfo::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { + yunq::Serializer serializer(bytes, offset, 2, caps); + return SerializeInternal(serializer); +} + +uint64_t XhciInfo::SerializeInternal(yunq::Serializer& serializer) const { + // Write xhci_region. + serializer.WriteCapability(0, xhci_region_); + // Write region_length. + serializer.WriteField(1, region_length_); + + serializer.WriteHeader(); + + return serializer.size(); +} glcr::Status FramebufferInfo::ParseFromBytes(const yunq::MessageView& message) { RETURN_ERROR(ParseFromBytesInternal(message)); return glcr::Status::Ok(); diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.h b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.h index fff090e..8130d35 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.h +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.h @@ -123,6 +123,36 @@ class AhciInfo { uint64_t SerializeInternal(yunq::Serializer& serializer) const; }; +class XhciInfo { + public: + XhciInfo() {} + // Delete copy and move until implemented. + XhciInfo(const XhciInfo&) = delete; + XhciInfo(XhciInfo&&) = default; + XhciInfo& operator=(XhciInfo&&) = default; + + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message); + [[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&); + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const; + uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const; + + const z_cap_t& xhci_region() const { return xhci_region_; } + z_cap_t& mutable_xhci_region() { return xhci_region_; } + void set_xhci_region(const z_cap_t& value) { xhci_region_ = value; } + + const uint64_t& region_length() const { return region_length_; } + uint64_t& mutable_region_length() { return region_length_; } + void set_region_length(const uint64_t& value) { region_length_ = value; } + + private: + z_cap_t xhci_region_; + uint64_t region_length_; + + // Parses everything except for caps. + glcr::Status ParseFromBytesInternal(const yunq::MessageView& message); + + uint64_t SerializeInternal(yunq::Serializer& serializer) const; +}; class FramebufferInfo { public: FramebufferInfo() {} diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.cpp b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.cpp index d410658..5d8c670 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.cpp +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.cpp @@ -164,6 +164,23 @@ glcr::Status YellowstoneServerBase::HandleRequest(const glcr::ByteBuffer& reques + XhciInfo yunq_response; + + + + RETURN_ERROR(HandleGetXhciInfo(yunq_response)); + + + + resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps); + + break; + } + case 4: { + + + + FramebufferInfo yunq_response; @@ -176,7 +193,7 @@ glcr::Status YellowstoneServerBase::HandleRequest(const glcr::ByteBuffer& reques break; } - case 4: { + case 5: { diff --git a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.h b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.h index b725140..bdaa1fb 100644 --- a/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.h +++ b/sys/yellowstone/lib/yellowstone/yellowstone.yunq.server.h @@ -41,6 +41,10 @@ class YellowstoneServerBase { + [[nodiscard]] virtual glcr::Status HandleGetXhciInfo(XhciInfo&) = 0; + + + [[nodiscard]] virtual glcr::Status HandleGetFramebufferInfo(FramebufferInfo&) = 0; diff --git a/sys/yellowstone/yellowstone_server.cpp b/sys/yellowstone/yellowstone_server.cpp index e4e05d6..999adfb 100644 --- a/sys/yellowstone/yellowstone_server.cpp +++ b/sys/yellowstone/yellowstone_server.cpp @@ -52,6 +52,12 @@ glcr::Status YellowstoneServer::HandleGetAhciInfo(AhciInfo& info) { 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. diff --git a/sys/yellowstone/yellowstone_server.h b/sys/yellowstone/yellowstone_server.h index 6866001..c9bf99b 100644 --- a/sys/yellowstone/yellowstone_server.h +++ b/sys/yellowstone/yellowstone_server.h @@ -17,6 +17,7 @@ class YellowstoneServer : public YellowstoneServerBase { static glcr::ErrorOr> 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;