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