From 006f9f8ac57b709d003ce05533536ba0399df723 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Sat, 17 Aug 2024 12:55:13 -0700 Subject: [PATCH] [Teton] Exec process in rust. --- rust/lib/mammoth/src/elf.rs | 343 +++++++++++++++++++++++++++++ rust/lib/mammoth/src/init.rs | 6 +- rust/lib/mammoth/src/lib.rs | 1 + rust/lib/mammoth/src/mem.rs | 22 +- rust/lib/mammoth/src/port.rs | 28 +++ rust/lib/mammoth/src/syscall.rs | 70 ++++++ rust/lib/mammoth/src/zion.rs | 6 + rust/lib/victoriafalls/src/file.rs | 4 +- rust/sys/teton/src/psf.rs | 5 +- rust/sys/teton/src/terminal.rs | 13 ++ rust/usr/testbed/src/main.rs | 51 ----- 11 files changed, 488 insertions(+), 61 deletions(-) create mode 100644 rust/lib/mammoth/src/elf.rs diff --git a/rust/lib/mammoth/src/elf.rs b/rust/lib/mammoth/src/elf.rs new file mode 100644 index 0000000..af7bd74 --- /dev/null +++ b/rust/lib/mammoth/src/elf.rs @@ -0,0 +1,343 @@ +use crate::debug; +use crate::init; +use crate::syscall; +use crate::zion::z_cap_t; +use crate::zion::ZError; + +use alloc::fmt::Debug; + +const ELF_MAGIC: u32 = 0x464C457F; + +const ELF_IDENT_32BIT: u8 = 0x1; +const ELF_IDENT_64BIT: u8 = 0x2; + +const ELF_ENDIAN_LITTLE: u8 = 0x1; +const ELF_ENDIAN_BIG: u8 = 0x2; + +const ELF_VERSION_CURRENT: u8 = 0x1; + +const ELF_ABI_SYSV: u8 = 0x0; +const ELF_ABI_LINUX: u8 = 0x3; + +const ELF_FILE_RELOC: u16 = 0x1; +const ELF_FILE_EXEC: u16 = 0x2; +const ELF_FILE_DYN: u16 = 0x3; +const ELF_FILE_CORE: u16 = 0x4; + +const ELF_MACH_X86: u16 = 0x3; +const ELF_MACH_AMD64: u16 = 0x3e; + +#[repr(C, packed(1))] +// Header spec from wikipedia: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#ELF_header +struct Elf64Header { + // 0x7F454C46 (0x7F followed by 'ELF') + magic: u32, + + // 1 for 32 bit, 2 for 64 bit. + elf_class: u8, + + // 1 for little, 2 for big. + endianess: u8, + + // Current version is 1. + ident_version: u8, + + // Target OS abi. + abi: u8, + abi_version: u8, + + ident_padding: [u8; 7], + + file_type: u16, + machine: u16, + version: u32, + entry: u64, + program_header_offset: u64, + section_header_offset: u64, + flags: u32, + header_size: u16, + program_header_entry_size: u16, + program_header_count: u16, + section_header_entry_size: u16, + section_header_entry_number: u16, + section_header_str_index: u16, +} + +impl Debug for Elf64Header { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let magic = self.magic; + let elf_class = match self.elf_class { + ELF_IDENT_32BIT => "32 bit", + ELF_IDENT_64BIT => "64 bit", + _ => "Unknown", + }; + let endianess = match self.endianess { + ELF_ENDIAN_LITTLE => "Little", + ELF_ENDIAN_BIG => "Big", + _ => "Unknown", + }; + + let ident_version = self.ident_version; + let version = self.version; + + f.write_fmt(format_args!( + "ELF Header Magic: {:#x}, Class: {}, Endianess: {}, Version (ident): {}, Version: {}\n", + magic, elf_class, endianess, ident_version, version, + ))?; + + let abi = match self.abi { + ELF_ABI_SYSV => "SYSV", + ELF_ABI_LINUX => "Linux", + _ => "Unknown", + }; + let abi_version = self.abi_version; + + f.write_fmt(format_args!("\tABI: {}, Version: {}\n", abi, abi_version))?; + + let file_type = match self.file_type { + ELF_FILE_EXEC => "Executable", + ELF_FILE_RELOC => "Relocatable", + ELF_FILE_DYN => "Shared Obj", + ELF_FILE_CORE => "Core file", + _ => "Unknown", + }; + + let machine = match self.machine { + ELF_MACH_X86 => "x86 (32bit)", + ELF_MACH_AMD64 => "x86-64", + _ => "Unknown", + }; + + let entry_point = self.entry; + + f.write_fmt(format_args!( + "\tFile type: {}, Machine Arch: {}, Entry point {:#x}", + file_type, machine, entry_point + )) + } +} + +fn validate_header(elf_header: &Elf64Header) -> Result<(), ZError> { + if elf_header.magic != ELF_MAGIC { + let magic = elf_header.magic; + debug!( + "Elf header incorrect got {:#x} expected {:#x}", + magic, ELF_MAGIC + ); + return Err(ZError::INVALID_ARGUMENT); + } + + if elf_header.elf_class != ELF_IDENT_64BIT { + let class = elf_header.elf_class; + debug!( + "Elf class must be {} for 64 bit, got: {}", + ELF_IDENT_64BIT, class + ); + return Err(ZError::INVALID_ARGUMENT); + } + + if elf_header.endianess != ELF_ENDIAN_LITTLE { + let endianess = elf_header.endianess; + debug!( + "Elf endianess must be {} for little, got: {}", + ELF_ENDIAN_LITTLE, endianess + ); + return Err(ZError::INVALID_ARGUMENT); + } + + if elf_header.ident_version != ELF_VERSION_CURRENT { + let version = elf_header.ident_version; + debug!( + "Elf version (ident) must be {}, got: {}", + ELF_VERSION_CURRENT, version + ); + return Err(ZError::INVALID_ARGUMENT); + } + + if elf_header.file_type != ELF_FILE_EXEC { + let file_type = elf_header.file_type; + debug!( + "Elf file type must be {} for executable, got {:x}", + ELF_FILE_EXEC, file_type + ); + return Err(ZError::INVALID_ARGUMENT); + } + + Ok(()) +} + +const ELF_PROG_NULL: u32 = 0x0; +const ELF_PROG_LOAD: u32 = 0x1; +const ELF_PROG_DYNAMIC: u32 = 0x2; +const ELF_PROG_INTERP: u32 = 0x3; +const ELF_PROG_NOTE: u32 = 0x4; +const ELF_PROG_SHLIB: u32 = 0x5; +const ELF_PROG_PTHDR: u32 = 0x6; +const ELF_PROG_THREAD_LOCAL: u32 = 0x7; + +// Stack unwind tables. +const ELF_PROG_GNU_EH_FRAME: u32 = 0x6474e550; +const ELF_PROG_GNU_STACK: u32 = 0x6474e551; +const ELF_PROG_GNU_RELRO: u32 = 0x6474e552; + +#[repr(C, packed(1))] +struct Elf64ProgramHeader { + prog_type: u32, + flags: u32, + offset: u64, + vaddr: u64, + paddr: u64, + file_size: u64, + mem_size: u64, + align: u64, +} + +impl Debug for Elf64ProgramHeader { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let prog_type = match self.prog_type { + ELF_PROG_NULL => "NULL", + ELF_PROG_LOAD => "LOAD", + ELF_PROG_DYNAMIC => "DYNAMIC", + ELF_PROG_INTERP => "INTERP", + ELF_PROG_NOTE => "NOTE", + ELF_PROG_SHLIB => "SHARED LIB", + ELF_PROG_PTHDR => "PROG TABLE HEADER", + ELF_PROG_THREAD_LOCAL => "THREAD LOCAL", + ELF_PROG_GNU_EH_FRAME => "GNU EH FRAME", + ELF_PROG_GNU_RELRO => "GNU RELOCATABLE", + ELF_PROG_GNU_STACK => "GNU STACK", + _ => "UNKNOWN", + }; + + let offset = self.offset; + let vaddr = self.vaddr; + let paddr = self.paddr; + let file_size = self.file_size; + let mem_size = self.mem_size; + let align = self.align; + f.write_fmt(format_args!( + "Type: {}, offset: {:#x}, vaddr: {:#x}, paddr: {:#x}, file_size: {:#x}, mem_size: {:#x}, align: {:#x}", + prog_type, offset, vaddr, paddr, file_size, mem_size, align + )) + } +} + +fn load_program_segment( + prog_header: &Elf64ProgramHeader, + file: &[u8], + vmas: z_cap_t, +) -> Result<(), ZError> { + debug!("{:?}", prog_header); + match prog_header.prog_type { + ELF_PROG_NULL + | ELF_PROG_NOTE + | ELF_PROG_PTHDR + | ELF_PROG_GNU_STACK + | ELF_PROG_GNU_RELRO + | ELF_PROG_GNU_EH_FRAME => Ok(()), + ELF_PROG_LOAD => { + let page_offset = prog_header.vaddr & 0xFFF; + let mem_size = page_offset + prog_header.mem_size; + + let mem_object = crate::mem::MemoryRegion::new(mem_size)?; + + for i in mem_object.mut_slice() { + *i = 0; + } + + let file_start = prog_header.offset as usize; + let file_end = file_start + prog_header.file_size as usize; + let from_slice = &file[file_start..file_end]; + + let mem_start = page_offset as usize; + let mem_end = mem_start + (prog_header.file_size as usize); + let to_slice: &mut [u8] = &mut mem_object.mut_slice()[mem_start..mem_end]; + + to_slice.copy_from_slice(from_slice); + + let vaddr = prog_header.vaddr - page_offset; + syscall::address_space_map_external(vmas, mem_object.cap(), vaddr) + } + ELF_PROG_DYNAMIC => { + debug!("Unimplemented dynamic elf sections."); + Err(ZError::UNIMPLEMENTED) + } + ELF_PROG_INTERP => { + debug!("Unimplemented interpreter elf sections."); + Err(ZError::UNIMPLEMENTED) + } + ELF_PROG_SHLIB => { + debug!("Unimplemented shared lib elf sections."); + Err(ZError::UNIMPLEMENTED) + } + ELF_PROG_THREAD_LOCAL => { + debug!("Unimplemented thread local elf sections."); + Err(ZError::UNIMPLEMENTED) + } + _ => { + let prog_type = prog_header.prog_type; + debug!("Unknown elf program header type: {:#x}", prog_type); + Err(ZError::UNKNOWN) + } + } +} + +fn load_elf_program(elf_file: &[u8], vmas: z_cap_t) -> Result { + assert!(elf_file.len() > size_of::()); + let header: &Elf64Header = unsafe { + elf_file + .as_ptr() + .cast::() + .as_ref() + .ok_or(ZError::NULL_PTR)? + }; + debug!("{:?}", header); + validate_header(header)?; + + for prog_ind in 0..header.program_header_count { + let prog_header_offset = header.program_header_offset + + ((prog_ind as u64) * (header.program_header_entry_size as u64)); + let prog_header_end = prog_header_offset + header.program_header_entry_size as u64; + let prog_header_slice = &elf_file[prog_header_offset as usize..prog_header_end as usize]; + let prog_header: &Elf64ProgramHeader = unsafe { + prog_header_slice + .as_ptr() + .cast::() + .as_ref() + .ok_or(ZError::NULL_PTR)? + }; + + load_program_segment(prog_header, elf_file, vmas)?; + } + Ok(header.entry) +} + +pub fn spawn_process_from_elf(elf_file: &[u8]) -> Result { + let self_cap = unsafe { init::SELF_PROC_CAP }; + let port_cap = syscall::port_create()?; + let port_cap_dup = syscall::cap_duplicate(port_cap, u64::MAX)?; + + let (new_proc_cap, new_as_cap, foreign_port_id) = + syscall::process_spawn(self_cap, port_cap_dup)?; + + let entry_point = load_elf_program(elf_file, new_as_cap)?; + + let port = crate::port::PortClient::take_from(port_cap); + + port.write_u64_and_cap( + crate::init::Z_INIT_SELF_PROC, + syscall::cap_duplicate(new_proc_cap, u64::MAX)?, + )?; + port.write_u64_and_cap(crate::init::Z_INIT_SELF_VMAS, new_as_cap)?; + port.write_u64_and_cap( + crate::init::Z_INIT_ENDPOINT, + syscall::cap_duplicate(unsafe { crate::init::INIT_ENDPOINT }, u64::MAX)?, + )?; + + let thread_cap = syscall::thread_create(new_proc_cap)?; + syscall::thread_start(thread_cap, entry_point, foreign_port_id, 0)?; + + syscall::cap_release(thread_cap)?; + + Ok(new_proc_cap) +} diff --git a/rust/lib/mammoth/src/init.rs b/rust/lib/mammoth/src/init.rs index 27dede9..752a446 100644 --- a/rust/lib/mammoth/src/init.rs +++ b/rust/lib/mammoth/src/init.rs @@ -2,9 +2,9 @@ use crate::syscall; use crate::zion::z_cap_t; // From /zion/include/ztypes.h -const Z_INIT_SELF_PROC: u64 = 0x4000_0000; -const Z_INIT_SELF_VMAS: u64 = 0x4000_0001; -const Z_INIT_ENDPOINT: u64 = 0x4100_0000; +pub const Z_INIT_SELF_PROC: u64 = 0x4000_0000; +pub const Z_INIT_SELF_VMAS: u64 = 0x4000_0001; +pub const Z_INIT_ENDPOINT: u64 = 0x4100_0000; pub static mut SELF_PROC_CAP: z_cap_t = 0; pub static mut SELF_VMAS_CAP: z_cap_t = 0; diff --git a/rust/lib/mammoth/src/lib.rs b/rust/lib/mammoth/src/lib.rs index f58e774..7f8d665 100644 --- a/rust/lib/mammoth/src/lib.rs +++ b/rust/lib/mammoth/src/lib.rs @@ -8,6 +8,7 @@ extern crate alloc; #[macro_use] pub mod macros; +pub mod elf; pub mod init; pub mod mem; pub mod port; diff --git a/rust/lib/mammoth/src/mem.rs b/rust/lib/mammoth/src/mem.rs index dd1834c..96653d7 100644 --- a/rust/lib/mammoth/src/mem.rs +++ b/rust/lib/mammoth/src/mem.rs @@ -46,6 +46,16 @@ impl MemoryRegion { }) } + pub fn new(size: u64) -> Result { + let mem_cap = syscall::memory_object_create(size)?; + let virt_addr = syscall::address_space_map(mem_cap)?; + Ok(Self { + mem_cap, + virt_addr, + size, + }) + } + pub fn slice(&self) -> &[T] { unsafe { slice::from_raw_parts( @@ -63,12 +73,20 @@ impl MemoryRegion { ) } } + + pub fn cap(&self) -> z_cap_t { + self.mem_cap + } } impl Drop for MemoryRegion { fn drop(&mut self) { - syscall::address_space_unmap(self.virt_addr, self.virt_addr + self.size) - .expect("Failed to unmap memory"); + // FIXME: We shouldn't have to do this manual adjustment. + let mut max = self.virt_addr + self.size; + if (max & 0xFFF) != 0 { + max += 0x1000 - (max & 0xFFF); + } + syscall::address_space_unmap(self.virt_addr, max).expect("Failed to unmap memory"); syscall::cap_release(self.mem_cap).expect("Failed to release memory cap"); } } diff --git a/rust/lib/mammoth/src/port.rs b/rust/lib/mammoth/src/port.rs index bd25405..854b8d8 100644 --- a/rust/lib/mammoth/src/port.rs +++ b/rust/lib/mammoth/src/port.rs @@ -40,3 +40,31 @@ impl Drop for PortServer { cap_release(self.port_cap).expect("Failed to release port cap"); } } + +pub struct PortClient { + port_cap: z_cap_t, +} + +impl PortClient { + pub fn take_from(port_cap: z_cap_t) -> Self { + Self { port_cap } + } + + pub fn copy_from(port_cap: z_cap_t) -> Result { + Ok(Self { + port_cap: cap_duplicate(port_cap, u64::MAX)?, + }) + } + + #[warn(unused_results)] + pub fn write_u64_and_cap(&self, bytes: u64, cap: z_cap_t) -> Result<(), ZError> { + let mut caps: [z_cap_t; 1] = [cap]; + crate::syscall::port_send(self.port_cap, &bytes.to_le_bytes(), &mut caps) + } +} + +impl Drop for PortClient { + fn drop(&mut self) { + cap_release(self.port_cap).expect("Failed to release port cap"); + } +} diff --git a/rust/lib/mammoth/src/syscall.rs b/rust/lib/mammoth/src/syscall.rs index d0ea030..09c1c6e 100644 --- a/rust/lib/mammoth/src/syscall.rs +++ b/rust/lib/mammoth/src/syscall.rs @@ -40,12 +40,46 @@ pub fn debug(msg: &str) { syscall(zion::kZionDebug, &req).expect("Failed to write"); } +pub fn process_spawn( + proc_cap: z_cap_t, + bootstrap_cap: z_cap_t, +) -> Result<(z_cap_t, z_cap_t, z_cap_t), ZError> { + let mut new_proc_cap = 0; + let mut new_as_cap = 0; + let mut new_bootstrap_cap = 0; + + syscall( + zion::kZionProcessSpawn, + &zion::ZProcessSpawnReq { + proc_cap, + bootstrap_cap, + new_proc_cap: &mut new_proc_cap, + new_vmas_cap: &mut new_as_cap, + new_bootstrap_cap: &mut new_bootstrap_cap, + }, + )?; + + Ok((new_proc_cap, new_as_cap, new_bootstrap_cap)) +} + pub fn process_exit(code: u64) -> ! { let _ = syscall(zion::kZionProcessExit, &zion::ZProcessExitReq { code }); unreachable!() } +pub fn process_wait(proc_cap: z_cap_t) -> Result { + let mut err_code = 0; + syscall( + zion::kZionProcessWait, + &zion::ZProcessWaitReq { + proc_cap, + exit_code: &mut err_code, + }, + )?; + Ok(err_code) +} + pub fn thread_create(proc_cap: z_cap_t) -> Result { let mut cap = 0; syscall( @@ -58,6 +92,10 @@ pub fn thread_create(proc_cap: z_cap_t) -> Result { Ok(cap) } +pub fn thread_sleep(millis: u64) -> Result<(), ZError> { + syscall(zion::kZionThreadSleep, &zion::ZThreadSleepReq { millis }) +} + pub fn thread_start(thread_cap: z_cap_t, entry: u64, arg1: u64, arg2: u64) -> Result<(), ZError> { syscall( zion::kZionThreadStart, @@ -129,6 +167,24 @@ pub fn address_space_map(vmmo_cap: z_cap_t) -> Result { Ok(vaddr) } +pub fn address_space_map_external( + vmas_cap: z_cap_t, + vmmo_cap: z_cap_t, + vaddr: u64, +) -> Result<(), ZError> { + let mut vaddr_throw: u64 = 0; + let vmas_req = zion::ZAddressSpaceMapReq { + vmmo_cap, + vmas_cap, + align: 0, + vaddr: &mut vaddr_throw as *mut u64, + vmas_offset: vaddr, + }; + + syscall(zion::kZionAddressSpaceMap, &vmas_req)?; + Ok(()) +} + pub fn address_space_unmap(lower_addr: u64, upper_addr: u64) -> Result<(), ZError> { syscall( zion::kZionAddressSpaceUnmap, @@ -151,6 +207,20 @@ pub fn port_create() -> Result { Ok(port_cap) } +pub fn port_send(port_cap: z_cap_t, bytes: &[u8], caps: &mut [z_cap_t]) -> Result<(), ZError> { + syscall( + zion::kZionPortSend, + &zion::ZPortSendReq { + port_cap, + num_bytes: bytes.len() as u64, + data: bytes.as_ptr() as *const c_void, + num_caps: caps.len() as u64, + // FIXME: This shouldn't need to be mutable. + caps: caps.as_mut_ptr(), + }, + ) +} + pub fn port_recv( port_cap: z_cap_t, bytes: &mut [u8], diff --git a/rust/lib/mammoth/src/zion.rs b/rust/lib/mammoth/src/zion.rs index 1bcadd2..9aa3a69 100644 --- a/rust/lib/mammoth/src/zion.rs +++ b/rust/lib/mammoth/src/zion.rs @@ -55,7 +55,13 @@ impl fmt::Debug for ZError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let str = match self { ZError::INVALID_ARGUMENT => "INVALID_ARGUMENT", + ZError::NOT_FOUND => "NOT_FOUND", + ZError::PERMISSION_DENIED => "PERMISSION_DENIED", + ZError::NULL_PTR => "NULL_PTR", + ZError::EMPTY => "EMPTY", + ZError::ALREADY_EXISTS => "ALREADY_EXISTS", ZError::BUFFER_SIZE => "BUFFER_SIZE", + ZError::FAILED_PRECONDITION => "FAILED_PRECONDITION", ZError::INTERNAL => "INTERNAL", ZError::UNIMPLEMENTED => "UNIMPLEMENTED", ZError::INVALID_RESPONSE => "INVALID_RESPONSE", diff --git a/rust/lib/victoriafalls/src/file.rs b/rust/lib/victoriafalls/src/file.rs index 2f37990..4877a09 100644 --- a/rust/lib/victoriafalls/src/file.rs +++ b/rust/lib/victoriafalls/src/file.rs @@ -18,7 +18,7 @@ impl File { }) } - pub fn slice(&self, offset: usize, len: usize) -> &[u8] { - &self.memory.slice()[offset..offset + len] + pub fn slice(&self) -> &[u8] { + self.memory.slice() } } diff --git a/rust/sys/teton/src/psf.rs b/rust/sys/teton/src/psf.rs index f27aba4..f6a75a6 100644 --- a/rust/sys/teton/src/psf.rs +++ b/rust/sys/teton/src/psf.rs @@ -25,8 +25,7 @@ impl Psf { pub fn new(path: &str) -> Result { let file = File::open(&path)?; - let header = file - .slice(0, core::mem::size_of::()) + let header = file.slice()[0..core::mem::size_of::()] .as_ptr() .cast(); let psf = Self { @@ -66,7 +65,7 @@ impl Psf { let offset: usize = (self.header.headersize + (index * self.header.bytes_per_glyph)) as usize; let len: usize = self.header.bytes_per_glyph as usize; - &self.file.slice(offset, len) + &self.file.slice()[offset..offset + len] } pub fn width(&self) -> u32 { diff --git a/rust/sys/teton/src/terminal.rs b/rust/sys/teton/src/terminal.rs index 4ecdc28..0ce7a53 100644 --- a/rust/sys/teton/src/terminal.rs +++ b/rust/sys/teton/src/terminal.rs @@ -112,6 +112,19 @@ impl Terminal { } } } + "exec" => match args.next() { + None => self.write_line("Specify a program"), + Some(prog) => { + let file = victoriafalls::file::File::open(prog).expect("Failed to open file"); + let proc_cap = mammoth::elf::spawn_process_from_elf(file.slice()) + .expect("Faield to spawn process"); + + let exit_code = mammoth::syscall::process_wait(proc_cap) + .expect("Failed to wait on process."); + + self.write_line(&format!("Process exit code: {}", exit_code)); + } + }, _ => self.write_line(&format!("Unrecognized command: {}", cmd)), } } diff --git a/rust/usr/testbed/src/main.rs b/rust/usr/testbed/src/main.rs index 1b27a05..0e994b5 100644 --- a/rust/usr/testbed/src/main.rs +++ b/rust/usr/testbed/src/main.rs @@ -8,46 +8,11 @@ use mammoth::debug; use mammoth::define_entry; use mammoth::thread; use mammoth::zion::z_err_t; -use mammoth::zion::ZError; use yellowstone::GetEndpointRequest; use yellowstone::YellowstoneClient; -use yellowstone::YellowstoneServer; -use yunq::server::YunqServer; define_entry!(); -struct YellowstoneImpl {} - -impl yellowstone::YellowstoneServerHandler for YellowstoneImpl { - fn register_endpoint(&self, req: &yellowstone::RegisterEndpointRequest) -> Result<(), ZError> { - debug!("{}", req.endpoint_name); - Ok(()) - } - - fn get_endpoint(&self, req: &GetEndpointRequest) -> Result { - debug!("{}", req.endpoint_name); - Ok(yellowstone::Endpoint { - endpoint: unsafe { mammoth::init::SELF_PROC_CAP }, - }) - } - - fn get_ahci_info(&self) -> Result { - todo!() - } - - fn get_xhci_info(&self) -> Result { - todo!() - } - - fn get_framebuffer_info(&self) -> Result { - todo!() - } - - fn get_denali(&self) -> Result { - todo!() - } -} - #[no_mangle] pub extern "C" fn main() -> z_err_t { debug!("Testing!"); @@ -72,21 +37,5 @@ pub extern "C" fn main() -> z_err_t { t.join().expect("Failed to wait."); - let server = YellowstoneServer::new(YellowstoneImpl {}).expect("Failed to create server"); - - let mut yellowstone = YellowstoneClient::new(server.endpoint_cap()); - - let t = server.run_server().expect("Failed to start server"); - - let endpoint = yellowstone - .get_endpoint(&GetEndpointRequest { - endpoint_name: "test".to_string(), - }) - .expect("Failed to get endpoint"); - - debug!("{:#x}", endpoint.endpoint); - - t.join().expect("Failed to wait"); - 0 }