[Yellowstone] Allow registering denali.
This commit is contained in:
parent
c9b484089e
commit
e90018b42e
|
@ -78,6 +78,10 @@ impl MemoryRegion {
|
||||||
pub fn cap(&self) -> &Capability {
|
pub fn cap(&self) -> &Capability {
|
||||||
&self.mem_cap
|
&self.mem_cap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn duplicate(&self, offset: u64, length: u64) -> Result<Capability, ZError> {
|
||||||
|
syscall::memory_obj_duplicate(&self.mem_cap, offset, length)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for MemoryRegion {
|
impl Drop for MemoryRegion {
|
||||||
|
|
|
@ -167,6 +167,24 @@ pub fn memory_object_inspect(mem_cap: &Capability) -> Result<u64, ZError> {
|
||||||
Ok(mem_size)
|
Ok(mem_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn memory_obj_duplicate(
|
||||||
|
mem_cap: &Capability,
|
||||||
|
base_offset: u64,
|
||||||
|
length: u64,
|
||||||
|
) -> Result<Capability, ZError> {
|
||||||
|
let mut new_cap = 0;
|
||||||
|
syscall(
|
||||||
|
zion::kZionMemoryObjectDuplicate,
|
||||||
|
&zion::ZMemoryObjectDuplicateReq {
|
||||||
|
vmmo_cap: mem_cap.raw(),
|
||||||
|
base_offset,
|
||||||
|
length,
|
||||||
|
new_vmmo_cap: &mut new_cap,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
Ok(Capability::take(new_cap))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn address_space_map(vmmo_cap: &Capability) -> Result<u64, ZError> {
|
pub fn address_space_map(vmmo_cap: &Capability) -> Result<u64, ZError> {
|
||||||
let mut vaddr: u64 = 0;
|
let mut vaddr: u64 = 0;
|
||||||
// FIXME: Allow caller to pass these options.
|
// FIXME: Allow caller to pass these options.
|
||||||
|
|
|
@ -6,7 +6,7 @@ use mammoth::zion::z_cap_t;
|
||||||
use mammoth::zion::ZError;
|
use mammoth::zion::ZError;
|
||||||
|
|
||||||
pub trait YunqServer {
|
pub trait YunqServer {
|
||||||
fn server_loop(&self) {
|
fn server_loop(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
let mut byte_buffer = ByteBuffer::<1024>::new();
|
let mut byte_buffer = ByteBuffer::<1024>::new();
|
||||||
let mut cap_buffer = vec![0; 10];
|
let mut cap_buffer = vec![0; 10];
|
||||||
|
@ -44,7 +44,7 @@ pub trait YunqServer {
|
||||||
.duplicate(!mammoth::zion::kZionPerm_Read)
|
.duplicate(!mammoth::zion::kZionPerm_Read)
|
||||||
}
|
}
|
||||||
fn handle_request(
|
fn handle_request(
|
||||||
&self,
|
&mut self,
|
||||||
method_number: u64,
|
method_number: u64,
|
||||||
byte_buffer: &mut ByteBuffer<1024>,
|
byte_buffer: &mut ByteBuffer<1024>,
|
||||||
cap_buffer: &mut Vec<z_cap_t>,
|
cap_buffer: &mut Vec<z_cap_t>,
|
||||||
|
|
|
@ -6,11 +6,14 @@ extern crate alloc;
|
||||||
use mammoth::{
|
use mammoth::{
|
||||||
cap::Capability,
|
cap::Capability,
|
||||||
define_entry, elf,
|
define_entry, elf,
|
||||||
zion::{kZionPerm_Read, z_cap_t, z_err_t, ZError},
|
init::BOOT_PCI_VMMO,
|
||||||
|
mem::MemoryRegion,
|
||||||
|
zion::{z_cap_t, z_err_t, ZError},
|
||||||
};
|
};
|
||||||
use yellowstone_yunq::YellowstoneServer;
|
use yellowstone_yunq::YellowstoneServer;
|
||||||
use yunq::server::YunqServer;
|
use yunq::server::YunqServer;
|
||||||
|
|
||||||
|
mod pci;
|
||||||
mod server;
|
mod server;
|
||||||
|
|
||||||
define_entry!();
|
define_entry!();
|
||||||
|
@ -23,8 +26,11 @@ fn spawn_from_vmmo(vmmo_cap: z_cap_t, server_cap: Capability) -> Result<(), ZErr
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn main() -> z_err_t {
|
extern "C" fn main() -> z_err_t {
|
||||||
|
let pci_region = MemoryRegion::from_cap(Capability::take(unsafe { BOOT_PCI_VMMO }))
|
||||||
|
.expect("Failed to create PCI region");
|
||||||
let context = alloc::rc::Rc::new(
|
let context = alloc::rc::Rc::new(
|
||||||
server::YellowstoneServerContext::new().expect("Failed to create yellowstone context"),
|
server::YellowstoneServerContext::new(pci_region)
|
||||||
|
.expect("Failed to create yellowstone context"),
|
||||||
);
|
);
|
||||||
let handler = server::YellowstoneServerImpl::new(context.clone());
|
let handler = server::YellowstoneServerImpl::new(context.clone());
|
||||||
let server = YellowstoneServer::new(handler).expect("Couldn't create yellowstone server");
|
let server = YellowstoneServer::new(handler).expect("Couldn't create yellowstone server");
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
use mammoth::{cap::Capability, mem::MemoryRegion, zion::ZError};
|
||||||
|
|
||||||
|
pub struct PciReader {
|
||||||
|
memory_region: MemoryRegion,
|
||||||
|
}
|
||||||
|
|
||||||
|
type DevPredicate = fn(u8, u8, u8) -> bool;
|
||||||
|
|
||||||
|
impl PciReader {
|
||||||
|
pub fn new(memory_region: MemoryRegion) -> Self {
|
||||||
|
Self { memory_region }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ahci_region(&self) -> Result<Capability, ZError> {
|
||||||
|
match self.probe_pci(|class, _, _| class == 0x1) {
|
||||||
|
Some(m) => Ok(m),
|
||||||
|
None => Err(ZError::NOT_FOUND),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_pci(&self, pred: DevPredicate) -> Option<Capability> {
|
||||||
|
let base_header = self.pci_header(0, 0, 0);
|
||||||
|
if (base_header.header_type & 0x80) == 0 {
|
||||||
|
if let Some(dev) = self.probe_bus(pred, 0) {
|
||||||
|
return Some(dev);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for fun in 0..8 {
|
||||||
|
let fun_hdr = self.pci_header(0, 0, fun);
|
||||||
|
if fun_hdr.vendor_id != 0xFFFF {
|
||||||
|
if let Some(dev) = self.probe_bus(pred, fun) {
|
||||||
|
return Some(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_bus(&self, pred: DevPredicate, bus: u8) -> Option<Capability> {
|
||||||
|
for dev in 0..0x20 {
|
||||||
|
if let Some(dev) = self.probe_device(pred, bus, dev) {
|
||||||
|
return Some(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_device(&self, pred: DevPredicate, bus: u8, dev: u8) -> Option<Capability> {
|
||||||
|
let device_base_header = self.pci_header(bus, dev, 0);
|
||||||
|
if device_base_header.vendor_id == 0xFFFF {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dev) = self.probe_function(pred, bus, dev, 0) {
|
||||||
|
return Some(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_base_header.header_type & 0x80) != 0 {
|
||||||
|
for fun in 1..8 {
|
||||||
|
if let Some(dev) = self.probe_function(pred, bus, dev, fun) {
|
||||||
|
return Some(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_function(&self, pred: DevPredicate, bus: u8, dev: u8, fun: u8) -> Option<Capability> {
|
||||||
|
let function_header = self.pci_header(bus, dev, fun);
|
||||||
|
|
||||||
|
mammoth::debug!(
|
||||||
|
"PCI Function: {:#x} {:#x} {:#x}",
|
||||||
|
function_header.class_code,
|
||||||
|
function_header.subclass,
|
||||||
|
function_header.prog_interface
|
||||||
|
);
|
||||||
|
|
||||||
|
if pred(
|
||||||
|
function_header.class_code,
|
||||||
|
function_header.subclass,
|
||||||
|
function_header.prog_interface,
|
||||||
|
) {
|
||||||
|
mammoth::debug!("Found!");
|
||||||
|
let offset = pci_header_offset(bus, dev, fun);
|
||||||
|
Some(
|
||||||
|
self.memory_region
|
||||||
|
.duplicate(offset as u64, 0x1000)
|
||||||
|
.expect("Failed to duplicate PCI cap"),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pci_header(&self, bus: u8, dev: u8, fun: u8) -> &PciHeader {
|
||||||
|
let offset = pci_header_offset(bus, dev, fun);
|
||||||
|
let header_slice: &[u8] =
|
||||||
|
&self.memory_region.slice()[offset..offset + size_of::<PciHeader>()];
|
||||||
|
unsafe { header_slice.as_ptr().cast::<PciHeader>().as_ref().unwrap() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct PciHeader {
|
||||||
|
vendor_id: u16,
|
||||||
|
device_id: u16,
|
||||||
|
command_reg: u16,
|
||||||
|
status_reg: u16,
|
||||||
|
revision: u8,
|
||||||
|
prog_interface: u8,
|
||||||
|
subclass: u8,
|
||||||
|
class_code: u8,
|
||||||
|
cache_line_size: u8,
|
||||||
|
latency_timer: u8,
|
||||||
|
header_type: u8,
|
||||||
|
bist: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pci_header_offset(bus: u8, dev: u8, fun: u8) -> usize {
|
||||||
|
((bus as usize) << 20) | ((dev as usize) << 15) | ((fun as usize) << 12)
|
||||||
|
}
|
|
@ -1,18 +1,23 @@
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use mammoth::zion::ZError;
|
use alloc::{collections::BTreeMap, string::String};
|
||||||
|
use mammoth::{cap::Capability, mem::MemoryRegion, zion::ZError};
|
||||||
use yellowstone_yunq::{
|
use yellowstone_yunq::{
|
||||||
AhciInfo, DenaliInfo, Endpoint, FramebufferInfo, GetEndpointRequest, RegisterEndpointRequest,
|
AhciInfo, DenaliInfo, Endpoint, FramebufferInfo, GetEndpointRequest, RegisterEndpointRequest,
|
||||||
XhciInfo, YellowstoneServerHandler,
|
XhciInfo, YellowstoneServerHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::pci::PciReader;
|
||||||
|
|
||||||
pub struct YellowstoneServerContext {
|
pub struct YellowstoneServerContext {
|
||||||
denali_semaphore: mammoth::sync::Semaphore,
|
denali_semaphore: mammoth::sync::Semaphore,
|
||||||
|
pci_reader: PciReader,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YellowstoneServerContext {
|
impl YellowstoneServerContext {
|
||||||
pub fn new() -> Result<Self, ZError> {
|
pub fn new(pci_region: MemoryRegion) -> Result<Self, ZError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
denali_semaphore: mammoth::sync::Semaphore::new()?,
|
denali_semaphore: mammoth::sync::Semaphore::new()?,
|
||||||
|
pci_reader: PciReader::new(pci_region),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,36 +28,50 @@ impl YellowstoneServerContext {
|
||||||
|
|
||||||
pub struct YellowstoneServerImpl {
|
pub struct YellowstoneServerImpl {
|
||||||
context: Rc<YellowstoneServerContext>,
|
context: Rc<YellowstoneServerContext>,
|
||||||
|
service_map: BTreeMap<String, Capability>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YellowstoneServerImpl {
|
impl YellowstoneServerImpl {
|
||||||
pub fn new(context: Rc<YellowstoneServerContext>) -> Self {
|
pub fn new(context: Rc<YellowstoneServerContext>) -> Self {
|
||||||
Self { context }
|
Self {
|
||||||
|
context,
|
||||||
|
service_map: BTreeMap::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YellowstoneServerHandler for YellowstoneServerImpl {
|
impl YellowstoneServerHandler for YellowstoneServerImpl {
|
||||||
fn register_endpoint(&self, req: &RegisterEndpointRequest) -> Result<(), ZError> {
|
fn register_endpoint(&mut self, req: RegisterEndpointRequest) -> Result<(), ZError> {
|
||||||
|
let signal_denali = req.endpoint_name == "denali";
|
||||||
|
self.service_map
|
||||||
|
.insert(req.endpoint_name, Capability::take(req.endpoint_capability));
|
||||||
|
|
||||||
|
if signal_denali {
|
||||||
|
self.context.denali_semaphore.signal()?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_endpoint(&mut self, req: GetEndpointRequest) -> Result<Endpoint, ZError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_endpoint(&self, req: &GetEndpointRequest) -> Result<Endpoint, ZError> {
|
fn get_ahci_info(&mut self) -> Result<AhciInfo, ZError> {
|
||||||
|
Ok(AhciInfo {
|
||||||
|
ahci_region: self.context.pci_reader.get_ahci_region()?.release(),
|
||||||
|
region_length: 0x1000,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_xhci_info(&mut self) -> Result<XhciInfo, ZError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ahci_info(&self) -> Result<AhciInfo, ZError> {
|
fn get_framebuffer_info(&mut self) -> Result<FramebufferInfo, ZError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_xhci_info(&self) -> Result<XhciInfo, ZError> {
|
fn get_denali(&mut self) -> Result<DenaliInfo, ZError> {
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_framebuffer_info(&self) -> Result<FramebufferInfo, ZError> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_denali(&self) -> Result<DenaliInfo, ZError> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ fn generate_server_case(method: &Method) -> TokenStream {
|
||||||
(Some(req), Some(_)) => quote! {
|
(Some(req), Some(_)) => quote! {
|
||||||
#id => {
|
#id => {
|
||||||
let req = #req::parse_from_request(byte_buffer, cap_buffer)?;
|
let req = #req::parse_from_request(byte_buffer, cap_buffer)?;
|
||||||
let resp = self.handler.#name(&req)?;
|
let resp = self.handler.#name(req)?;
|
||||||
cap_buffer.resize(0, 0);
|
cap_buffer.resize(0, 0);
|
||||||
let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?;
|
let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?;
|
||||||
Ok(resp_len)
|
Ok(resp_len)
|
||||||
|
@ -91,7 +91,7 @@ fn generate_server_case(method: &Method) -> TokenStream {
|
||||||
(Some(req), None) => quote! {
|
(Some(req), None) => quote! {
|
||||||
#id => {
|
#id => {
|
||||||
let req = #req::parse_from_request(byte_buffer, cap_buffer)?;
|
let req = #req::parse_from_request(byte_buffer, cap_buffer)?;
|
||||||
self.handler.#name(&req)?;
|
self.handler.#name(req)?;
|
||||||
cap_buffer.resize(0, 0);
|
cap_buffer.resize(0, 0);
|
||||||
// TODO: Implement serialization for EmptyMessage so this is less hacky.
|
// TODO: Implement serialization for EmptyMessage so this is less hacky.
|
||||||
yunq::message::serialize_error(byte_buffer, ZError::from(0));
|
yunq::message::serialize_error(byte_buffer, ZError::from(0));
|
||||||
|
@ -116,13 +116,13 @@ fn generate_server_method(method: &Method) -> TokenStream {
|
||||||
let maybe_resp = method.response.clone().map(|r| ident(&r));
|
let maybe_resp = method.response.clone().map(|r| ident(&r));
|
||||||
match (maybe_req, maybe_resp) {
|
match (maybe_req, maybe_resp) {
|
||||||
(Some(req), Some(resp)) => quote! {
|
(Some(req), Some(resp)) => quote! {
|
||||||
fn #name (&self, req: & #req) -> Result<#resp, ZError>;
|
fn #name (&mut self, req: #req) -> Result<#resp, ZError>;
|
||||||
},
|
},
|
||||||
(Some(req), None) => quote! {
|
(Some(req), None) => quote! {
|
||||||
fn #name (&self, req: & #req) -> Result<(), ZError>;
|
fn #name (&mut self, req: #req) -> Result<(), ZError>;
|
||||||
},
|
},
|
||||||
(None, Some(resp)) => quote! {
|
(None, Some(resp)) => quote! {
|
||||||
fn #name (&self) -> Result<#resp, ZError>;
|
fn #name (&mut self) -> Result<#resp, ZError>;
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ fn generate_server(interface: &Interface) -> TokenStream {
|
||||||
|
|
||||||
pub fn run_server(&self) -> Result<Box<thread::Thread>, ZError> {
|
pub fn run_server(&self) -> Result<Box<thread::Thread>, ZError> {
|
||||||
let thread_entry = |server_ptr: *const c_void| {
|
let thread_entry = |server_ptr: *const c_void| {
|
||||||
let server = unsafe { (server_ptr as *const #server_name<T>).as_ref().expect("Failed to convert to server") };
|
let server = unsafe { (server_ptr as *mut #server_name<T>).as_mut().expect("Failed to convert to server") };
|
||||||
server.server_loop();
|
server.server_loop();
|
||||||
};
|
};
|
||||||
thread::Thread::spawn(
|
thread::Thread::spawn(
|
||||||
|
@ -169,7 +169,7 @@ fn generate_server(interface: &Interface) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request(
|
fn handle_request(
|
||||||
&self,
|
&mut self,
|
||||||
method_number: u64,
|
method_number: u64,
|
||||||
byte_buffer: &mut ByteBuffer<1024>,
|
byte_buffer: &mut ByteBuffer<1024>,
|
||||||
cap_buffer: &mut Vec<z_cap_t>,
|
cap_buffer: &mut Vec<z_cap_t>,
|
||||||
|
|
Loading…
Reference in New Issue