openhcl_boot/
boot_logger.rs1#[cfg(target_arch = "x86_64")]
12use crate::arch::tdx::TdxIoAccess;
13use crate::host_params::shim_params::IsolationType;
14use crate::single_threaded::SingleThreaded;
15use core::cell::RefCell;
16use core::fmt;
17use core::fmt::Write;
18use memory_range::MemoryRange;
19#[cfg(target_arch = "x86_64")]
20use minimal_rt::arch::InstrIoAccess;
21use minimal_rt::arch::Serial;
22use string_page_buf::StringBuffer;
23
24enum Logger {
25 #[cfg(target_arch = "x86_64")]
26 Serial(Serial<InstrIoAccess>),
27 #[cfg(target_arch = "aarch64")]
28 Serial(Serial),
29 #[cfg(target_arch = "x86_64")]
30 TdxSerial(Serial<TdxIoAccess>),
31 None,
32}
33
34impl Logger {
35 fn write_str(&mut self, s: &str) -> fmt::Result {
36 match self {
37 Logger::Serial(serial) => serial.write_str(s),
38 #[cfg(target_arch = "x86_64")]
39 Logger::TdxSerial(serial) => serial.write_str(s),
40 Logger::None => Ok(()),
41 }
42 }
43}
44
45pub struct BootLogger {
46 logger: SingleThreaded<RefCell<Logger>>,
47 in_memory_logger: SingleThreaded<RefCell<Option<StringBuffer<'static>>>>,
48}
49
50pub static BOOT_LOGGER: BootLogger = BootLogger {
51 logger: SingleThreaded(RefCell::new(Logger::None)),
52 in_memory_logger: SingleThreaded(RefCell::new(None)),
53};
54
55pub fn boot_logger_memory_init(buffer: MemoryRange) {
58 if buffer.is_empty() {
59 return;
60 }
61
62 let log_buffer_ptr = buffer.start() as *mut u8;
63 let log_buffer_slice =
69 unsafe { core::slice::from_raw_parts_mut(log_buffer_ptr, buffer.len() as usize) };
70
71 *BOOT_LOGGER.in_memory_logger.borrow_mut() = Some(
72 StringBuffer::new(log_buffer_slice)
73 .expect("log buffer should be valid from fixed at build config"),
74 );
75}
76
77pub fn boot_logger_runtime_init(isolation_type: IsolationType, com3_serial_available: bool) {
79 let mut logger = BOOT_LOGGER.logger.borrow_mut();
80
81 *logger = match (isolation_type, com3_serial_available) {
82 #[cfg(target_arch = "x86_64")]
83 (IsolationType::None, true) => Logger::Serial(Serial::init(InstrIoAccess)),
84 #[cfg(target_arch = "aarch64")]
85 (IsolationType::None, true) => Logger::Serial(Serial::init()),
86 #[cfg(target_arch = "x86_64")]
87 (IsolationType::Tdx, true) => Logger::TdxSerial(Serial::init(TdxIoAccess)),
88 _ => Logger::None,
89 };
90}
91
92impl Write for &BootLogger {
93 fn write_str(&mut self, s: &str) -> fmt::Result {
94 if let Some(buf) = self.in_memory_logger.borrow_mut().as_mut() {
95 let _ = buf.append(s);
97 }
98 self.logger.borrow_mut().write_str(s)
99 }
100}
101
102macro_rules! log {
108 () => {};
109 ($($arg:tt)*) => {
110 {
111 use core::fmt::Write;
112 let _ = writeln!(&$crate::boot_logger::BOOT_LOGGER, $($arg)*);
113 }
114 };
115}
116
117pub(crate) use log;
118
119#[expect(unused_macros)]
126macro_rules! debug_log {
127 ($($arg:tt)*) => {
128 $crate::boot_logger::log!($($arg)*)
129 };
130}
131
132#[expect(unused_imports)]
135pub(crate) use debug_log;