1use std::sync::Mutex;
2
3use secgate::util::{Descriptor, HandleMgr, SimpleBuffer};
4use twizzler_abi::{
5 object::{ObjID, Protections},
6 syscall::{
7 sys_kernel_console_write, sys_object_create, BackingType, KernelConsoleSource,
8 KernelConsoleWriteFlags, LifetimeType, ObjectCreate, ObjectCreateFlags,
9 },
10};
11use twizzler_rt_abi::{
12 error::{ArgumentError, GenericError, ResourceError, TwzError},
13 object::MapFlags,
14};
15
16struct LogClient {
18 buffer: SimpleBuffer,
19}
20
21impl LogClient {
22 fn sbid(&self) -> ObjID {
23 self.buffer.handle().id()
24 }
25}
26
27impl LogClient {
28 fn new() -> Option<Self> {
29 let id = sys_object_create(
31 ObjectCreate::new(
32 BackingType::Normal,
33 LifetimeType::Volatile,
34 None,
35 ObjectCreateFlags::empty(),
36 Protections::all(),
37 ),
38 &[],
39 &[],
40 )
41 .ok()?;
42 let handle =
43 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::WRITE | MapFlags::READ)
44 .ok()?;
45 let buffer = SimpleBuffer::new(handle);
46 Some(Self { buffer })
47 }
48}
49
50struct Logger {
52 handles: HandleMgr<LogClient>,
53 count: usize,
54}
55
56impl Logger {
57 const fn new() -> Self {
58 Self {
59 handles: HandleMgr::new(None),
60 count: 0,
61 }
62 }
63}
64
65struct LogBoi {
66 inner: Mutex<Logger>,
67}
68
69static LOGBOI: LogBoi = LogBoi {
70 inner: Mutex::new(Logger::new()),
71};
72
73#[secgate::entry(lib = "logboi")]
74pub fn logboi_open_handle() -> Result<(Descriptor, ObjID), TwzError> {
75 let info = secgate::get_caller().unwrap();
76 let mut logger = LOGBOI.inner.lock().ok().ok_or(GenericError::Internal)?;
77 let client = LogClient::new().ok_or(ResourceError::Unavailable)?;
78 let id = client.sbid();
79 let desc = logger
80 .handles
81 .insert(info.source_context().unwrap_or(0.into()), client)
82 .ok_or(ResourceError::Unavailable)?;
83
84 Ok((desc, id))
85}
86
87#[secgate::entry(lib = "logboi")]
88pub fn logboi_close_handle(desc: Descriptor) -> Result<(), TwzError> {
89 let info = secgate::get_caller().unwrap();
90 let mut logger = LOGBOI.inner.lock().unwrap();
91 logger
92 .handles
93 .remove(info.source_context().unwrap_or(0.into()), desc);
94 Ok(())
95}
96
97#[secgate::entry(lib = "logboi")]
98pub fn logboi_post(desc: Descriptor, buf_len: usize) -> Result<(), TwzError> {
99 let info = secgate::get_caller().unwrap();
100 let mut buf = vec![0u8; buf_len];
101 let mut logger = LOGBOI.inner.lock().unwrap();
102 let Some(client) = logger
103 .handles
104 .lookup(info.source_context().unwrap_or(0.into()), desc)
105 else {
106 return Err(ArgumentError::BadHandle.into());
107 };
108 let len = client.buffer.read(&mut buf);
109 let msg = format!(
110 "[log:{}] {}\n",
111 logger.count,
112 String::from_utf8_lossy(&buf[0..len])
113 );
114 logger.count += 1;
115 let _ = sys_kernel_console_write(
116 KernelConsoleSource::Console,
117 msg.as_bytes(),
118 KernelConsoleWriteFlags::DISCARD_ON_FULL,
119 );
120 Ok(())
121}