use core::fmt::{self, Write};
const DEBUGCON_PORT: u16 = 0xE9;
#[inline]
fn out_u8(byte: u8) {
unsafe {
core::arch::asm!(
"out dx, al",
in("dx") DEBUGCON_PORT,
in("al") byte,
options(nomem, nostack, preserves_flags),
);
}
}
struct DebugConsole;
impl Write for DebugConsole {
fn write_str(&mut self, s: &str) -> fmt::Result {
for &b in s.as_bytes() {
out_u8(b);
}
Ok(())
}
}
fn efi_time_to_unix(t: &uefi::runtime::Time) -> (u64, u32) {
let year = t.year() as u64;
let month = t.month() as u64;
let day = t.day() as u64;
let (y, m) = if month <= 2 {
(year - 1, month + 9)
} else {
(year, month - 3)
};
const EPOCH_DAYS: u64 = 719_468;
let era = y / 400;
let yoe = y % 400; let doy = (153 * m + 2) / 5 + day - 1; let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; let days = era * 146_097 + doe - EPOCH_DAYS;
let secs = days * 86_400 + t.hour() as u64 * 3_600 + t.minute() as u64 * 60 + t.second() as u64;
let millis = t.nanosecond() / 1_000_000;
(secs, millis)
}
fn get_timestamp() -> (u64, u32) {
match uefi::runtime::get_time() {
Ok(t) => efi_time_to_unix(&t),
Err(_) => (0, 0),
}
}
pub fn write_str(s: &str) {
let _ = DebugConsole.write_str(s);
}
pub fn write_fmt(args: fmt::Arguments<'_>) {
let _ = DebugConsole.write_fmt(args);
}
pub fn write_log_line(prefix: &str, args: fmt::Arguments<'_>) {
let (secs, millis) = get_timestamp();
let _ = DebugConsole.write_fmt(format_args!("{secs}.{millis:03} "));
let _ = DebugConsole.write_str(prefix);
let _ = DebugConsole.write_fmt(args);
let _ = DebugConsole.write_str("\r\n");
}
#[macro_export]
macro_rules! vck_log {
($($arg:tt)*) => {
$crate::debug::write_log_line("vck-loader: ", core::format_args!($($arg)*))
};
}