diff --git a/Cargo.lock b/Cargo.lock index df93c2d9..784f7974 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,6 +152,7 @@ dependencies = [ "dirs", "fdt", "heapless", + "log", "r-efi", "rand", "ssh2", @@ -217,6 +218,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "num-traits" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index 89a41fbf..355c80ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ bitflags = "2.6.0" atomic_refcell = "0.1.13" r-efi = { version = "4.5.0", features = ["efiapi"] } heapless = "0.8.0" +log = "0.4.22" [target.'cfg(target_arch = "aarch64")'.dependencies] tock-registers = "0.9.0" diff --git a/src/arch/x86_64/paging.rs b/src/arch/x86_64/paging.rs index 6449eb48..9ee23229 100644 --- a/src/arch/x86_64/paging.rs +++ b/src/arch/x86_64/paging.rs @@ -2,6 +2,7 @@ // Copyright 2020 Google LLC use core::cell::SyncUnsafeCell; +use log::info; use x86_64::{ registers::control::Cr3, structures::paging::{PageSize, PageTable, PageTableFlags, PhysFrame, Size2MiB}, @@ -25,7 +26,7 @@ pub fn setup() { // SAFETY: This function is idempontent and only writes to static memory and // CR3. Thus, it is safe to run multiple times or on multiple threads. let (l4, l3, l2s) = unsafe { (L4_TABLE.get_mut(), L3_TABLE.get_mut(), L2_TABLES.get_mut()) }; - log!("Setting up {} GiB identity mapping", ADDRESS_SPACE_GIB); + info!("Setting up {} GiB identity mapping", ADDRESS_SPACE_GIB); let pt_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; // Setup Identity map using L2 huge pages @@ -51,7 +52,7 @@ pub fn setup() { if cr3_frame != l4_frame { unsafe { Cr3::write(l4_frame, cr3_flags) }; } - log!("Page tables setup"); + info!("Page tables setup"); } // Map a virtual address to a PhysAddr (assumes identity mapping) diff --git a/src/efi/device_path.rs b/src/efi/device_path.rs index cb47062c..3918171c 100644 --- a/src/efi/device_path.rs +++ b/src/efi/device_path.rs @@ -7,6 +7,7 @@ use core::{ ptr::null_mut, }; +use log::error; use r_efi::{ efi::{self, MemoryType, Status}, protocols::device_path::Protocol as DevicePathProtocol, @@ -49,7 +50,7 @@ impl DevicePath { } if dpp.r#type == r_efi::protocols::device_path::TYPE_END && dpp.sub_type == 0xff { - log!("Unexpected end of device path"); + error!("Unexpected end of device path"); return DevicePath::Unsupported; } let len = unsafe { core::mem::transmute::<[u8; 2], u16>(dpp.length) }; diff --git a/src/efi/file.rs b/src/efi/file.rs index 0246043a..d411388f 100644 --- a/src/efi/file.rs +++ b/src/efi/file.rs @@ -3,6 +3,7 @@ use core::ffi::c_void; +use log::error; use r_efi::{ efi::{self, Char16, Guid, Status}, protocols::{ @@ -51,7 +52,7 @@ pub extern "efiapi" fn open( match &wrapper.node { crate::fat::Node::Directory(d) => d, _ => { - log!("Attempt to open from non-directory is unsupported"); + error!("Attempt to open from non-directory is unsupported"); return Status::UNSUPPORTED; } } diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 00000000..7b9d4903 --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2024 Akira Moroo + +pub struct Logger; + +impl log::Log for Logger { + fn enabled(&self, metadata: &log::Metadata) -> bool { + metadata.level() <= log::Level::Info + } + + fn log(&self, record: &log::Record) { + if self.enabled(record.metadata()) { + log!("[{}] {}", record.level(), record.args()); + } + } + + fn flush(&self) {} +} + +pub fn init() { + log::set_logger(&Logger).expect("Failed to set logger"); + log::set_max_level(log::LevelFilter::Info); +} diff --git a/src/main.rs b/src/main.rs index e97c68c1..599ab9e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ #[cfg(all(not(test), not(feature = "integration_tests")))] use core::panic::PanicInfo; +use log::{error, info, warn}; #[cfg(all( not(test), not(feature = "integration_tests"), @@ -55,6 +56,7 @@ mod fdt; mod integration; mod layout; mod loader; +mod logger; mod mem; mod part; mod pci; @@ -111,10 +113,10 @@ fn boot_from_device( info: &dyn bootinfo::Info, ) -> Result<(), Error> { if let Err(err) = device.init() { - log!("Error configuring block device: {:?}", err); + error!("Error configuring block device: {:?}", err); return Err(Error::Virtio(err)); } - log!( + info!( "Virtio block device configured. Capacity: {} sectors", device.get_capacity() ); @@ -122,59 +124,59 @@ fn boot_from_device( let (start, end) = match part::find_efi_partition(device) { Ok(p) => p, Err(err) => { - log!("Failed to find EFI partition: {:?}", err); + error!("Failed to find EFI partition: {:?}", err); return Err(Error::Partition(err)); } }; - log!("Found EFI partition"); + info!("Found EFI partition"); let mut f = fat::Filesystem::new(device, start, end); if let Err(err) = f.init() { - log!("Failed to create filesystem: {:?}", err); + error!("Failed to create filesystem: {:?}", err); return Err(Error::Fat(err)); } - log!("Filesystem ready"); + info!("Filesystem ready"); match loader::load_default_entry(&f, info) { Ok(mut kernel) => { - log!("Jumping to kernel"); + info!("Jumping to kernel"); kernel.boot(); return Ok(()); } Err(err) => { - log!("Error loading default entry: {:?}", err); + warn!("Error loading default entry: {:?}", err); // Fall through to EFI boot } } - log!("Using EFI boot."); + info!("Using EFI boot."); let mut file = match f.open(efi::EFI_BOOT_PATH) { Ok(file) => file, Err(err) => { - log!("Failed to load default EFI binary: {:?}", err); + error!("Failed to load default EFI binary: {:?}", err); return Err(Error::Fat(err)); } }; - log!("Found bootloader: {}", efi::EFI_BOOT_PATH); + info!("Found bootloader: {}", efi::EFI_BOOT_PATH); let mut l = pe::Loader::new(&mut file); let (entry_addr, load_addr, size) = match l.load(info.kernel_load_addr()) { Ok(load_info) => load_info, Err(err) => { - log!("Error loading executable: {:?}", err); + error!("Error loading executable: {:?}", err); return Err(Error::Pe(err)); } }; #[cfg(target_arch = "aarch64")] if code_range().start < (info.kernel_load_addr() + size) as usize { - log!("Error Boot Image is too large"); + error!("Error Boot Image is too large"); return Err(Error::ImageTooLarge); } - log!("Executable loaded"); + info!("Executable loaded"); efi::efi_exec(entry_addr, load_addr, size, info, &f, device); Ok(()) } @@ -183,6 +185,7 @@ fn boot_from_device( #[no_mangle] pub extern "C" fn rust64_start(#[cfg(not(feature = "coreboot"))] pvh_info: &pvh::StartInfo) -> ! { serial::PORT.borrow_mut().init(); + logger::init(); arch::x86_64::sse::enable_sse(); arch::x86_64::paging::setup(); @@ -204,6 +207,7 @@ pub extern "C" fn rust64_start(x0: *const u8) -> ! { // Use atomic operation before MMU enabled may cause exception, see https://www.ipshop.xyz/5909.html serial::PORT.borrow_mut().init(); + logger::init(); let info = fdt::StartInfo::new( x0, @@ -226,8 +230,9 @@ pub extern "C" fn rust64_start(a0: u64, a1: *const u8) -> ! { use crate::bootinfo::{EntryType, Info, MemoryEntry}; serial::PORT.borrow_mut().init(); + logger::init(); - log!("Starting on RV64 0x{:x} 0x{:x}", a0, a1 as u64,); + info!("Starting on RV64 0x{:x} 0x{:x}", a0, a1 as u64,); let info = fdt::StartInfo::new( a1, @@ -243,7 +248,7 @@ pub extern "C" fn rust64_start(a0: u64, a1: *const u8) -> ! { for i in 0..info.num_entries() { let region = info.entry(i); - log!( + info!( "Memory region {}MiB@0x{:x}", region.size / 1024 / 1024, region.addr @@ -258,7 +263,7 @@ pub extern "C" fn rust64_start(a0: u64, a1: *const u8) -> ! { } fn main(info: &dyn bootinfo::Info) -> ! { - log!("\nBooting with {}", info.name()); + info!("Booting with {}", info.name()); pci::print_bus(); diff --git a/src/pci.rs b/src/pci.rs index a71c7d31..ad2e62c7 100644 --- a/src/pci.rs +++ b/src/pci.rs @@ -3,6 +3,7 @@ use atomic_refcell::AtomicRefCell; +use log::{info, warn}; #[cfg(target_arch = "x86_64")] use x86_64::instructions::port::{Port, PortWriteOnly}; @@ -152,11 +153,9 @@ pub fn print_bus() { if vendor_id == INVALID_VENDOR_ID { continue; } - log!( + info!( "Found PCI device vendor={:x} device={:x} in slot={}", - vendor_id, - device_id, - device + vendor_id, device_id, device ); } } @@ -251,13 +250,9 @@ impl PciDevice { self.vendor_id = vendor_id; self.device_id = device_id; - log!( + info!( "PCI Device: {}:{}.{} {:x}:{:x}", - self.bus, - self.device, - self.func, - self.vendor_id, - self.device_id + self.bus, self.device, self.func, self.vendor_id, self.device_id ); // Enable responses in memory space @@ -328,11 +323,9 @@ impl PciDevice { #[allow(clippy::disallowed_names)] for bar in &self.bars { - log!( + info!( "Bar: type={:?} address=0x{:x} size=0x{:x}", - bar.bar_type, - bar.address, - bar.size + bar.bar_type, bar.address, bar.size ); } } @@ -379,11 +372,9 @@ impl PciDevice { #[allow(clippy::disallowed_names)] for bar in &self.bars { - log!( + info!( "Updated BARs: type={:?} address={:x} size={:x}", - bar.bar_type, - bar.address, - bar.size + bar.bar_type, bar.address, bar.size ); } @@ -445,7 +436,7 @@ impl VirtioTransport for VirtioPciTransport { // bit 4 of status is capability bit if status & 1 << 4 == 0 { - log!("No capabilities detected"); + warn!("No capabilities detected"); return Err(VirtioError::UnsupportedDevice); }