openhcl_boot/
boot_logger.rs1#[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
12use crate::arch::snp::SnpIoAccess;
13#[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
14use crate::arch::tdx::TdxIoAccess;
15use crate::host_params::shim_params::IsolationType;
16use crate::single_threaded::SingleThreaded;
17use core::cell::RefCell;
18use core::fmt;
19use core::fmt::Write;
20use host_fdt_parser::ComInfo;
21use memory_range::MemoryRange;
22#[cfg(target_arch = "x86_64")]
23use minimal_rt::arch::InstrIoAccess;
24use minimal_rt::arch::Serial;
25use string_page_buf::StringBuffer;
26
27enum Logger {
28 #[cfg(target_arch = "x86_64")]
29 Serial(Serial<InstrIoAccess>),
30 #[cfg(target_arch = "aarch64")]
31 #[expect(dead_code)]
32 Serial(Serial),
33 #[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
34 TdxSerial(Serial<TdxIoAccess>),
35 #[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
36 SnpSerial(Serial<SnpIoAccess>),
37 None,
38}
39
40impl Logger {
41 fn write_str(&mut self, s: &str) -> fmt::Result {
42 match self {
43 Logger::Serial(serial) => serial.write_str(s),
44 #[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
45 Logger::TdxSerial(serial) => serial.write_str(s),
46 #[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
47 Logger::SnpSerial(serial) => serial.write_str(s),
48 Logger::None => Ok(()),
49 }
50 }
51}
52
53pub struct BootLogger {
54 logger: SingleThreaded<RefCell<Logger>>,
55 in_memory_logger: SingleThreaded<RefCell<Option<StringBuffer<'static>>>>,
56}
57
58pub static BOOT_LOGGER: BootLogger = BootLogger {
59 logger: SingleThreaded(RefCell::new(Logger::None)),
60 in_memory_logger: SingleThreaded(RefCell::new(None)),
61};
62
63pub fn boot_logger_memory_init(buffer: MemoryRange) {
66 if buffer.is_empty() {
67 return;
68 }
69
70 let log_buffer_ptr = buffer.start() as *mut u8;
71 let log_buffer_slice =
77 unsafe { core::slice::from_raw_parts_mut(log_buffer_ptr, buffer.len() as usize) };
78
79 *BOOT_LOGGER.in_memory_logger.borrow_mut() = Some(
80 StringBuffer::new(log_buffer_slice)
81 .expect("log buffer should be valid from fixed at build config"),
82 );
83}
84
85pub fn boot_logger_runtime_init(isolation_type: IsolationType, com3_serial_available: ComInfo) {
90 let mut logger = BOOT_LOGGER.logger.borrow_mut();
91
92 *logger = match (isolation_type, com3_serial_available) {
93 #[cfg(target_arch = "x86_64")]
94 (IsolationType::None, ComInfo::Ns16550 { .. }) => {
95 Logger::Serial(Serial::init(InstrIoAccess))
96 }
97 #[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
102 (IsolationType::Tdx, ComInfo::Ns16550 { .. }) => {
103 Logger::TdxSerial(Serial::init(TdxIoAccess))
104 }
105 #[cfg(all(target_arch = "x86_64", feature = "cvm_boot_log"))]
106 (IsolationType::Snp, ComInfo::Ns16550 { .. }) => {
107 Logger::SnpSerial(Serial::init(SnpIoAccess))
108 }
109 _ => Logger::None,
110 };
111
112 if let Some(buf) = BOOT_LOGGER.in_memory_logger.borrow_mut().as_mut() {
114 let _ = logger.write_str(buf.contents());
115 }
116}
117
118impl Write for &BootLogger {
119 fn write_str(&mut self, s: &str) -> fmt::Result {
120 if let Some(buf) = self.in_memory_logger.borrow_mut().as_mut() {
121 let _ = buf.append(s);
123 }
124 self.logger.borrow_mut().write_str(s)
125 }
126}
127
128impl log::Log for BootLogger {
129 fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool {
130 true
132 }
133
134 fn log(&self, record: &log::Record<'_>) {
135 let _ = writeln!(&*self, "[{}] {}", record.level(), record.args());
136 }
137
138 fn flush(&self) {}
139}