From 75d1175d7672985c7481fe21e3e441c0ae534647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Asensio=20Garc=C3=ADa?= Date: Fri, 30 Dec 2022 20:47:33 +0100 Subject: [PATCH 1/7] Add the log_level feature. --- api/Cargo.toml | 1 + api/build.rs | 1 + api/src/config.rs | 33 ++++++++++++++++++++++++++++++--- bios/stage-4/src/main.rs | 16 ++++++++-------- common/src/lib.rs | 4 ++-- uefi/src/main.rs | 2 +- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/api/Cargo.toml b/api/Cargo.toml index ef687b0c..28a52fef 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -9,6 +9,7 @@ description = "Makes a kernel compatible with the bootloader crate" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +log = "0.4.17" [dev-dependencies] rand = "0.8.4" diff --git a/api/build.rs b/api/build.rs index a5e4b72d..bacb5bf9 100644 --- a/api/build.rs +++ b/api/build.rs @@ -22,6 +22,7 @@ fn main() { (88, 9), (97, 9), (106, 9), + (115, 1), ]; let mut code = String::new(); diff --git a/api/src/config.rs b/api/src/config.rs index 3eb4fb87..3dbc907a 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -27,6 +27,10 @@ pub struct BootloaderConfig { /// Configuration for the frame buffer that can be used by the kernel to display pixels /// on the screen. pub frame_buffer: FrameBuffer, + + /// Configuration for changing the level of the filter of the messages that are shown in the + /// screen when booting. The default is 'Trace'. + pub log_level: log::LevelFilter, } impl BootloaderConfig { @@ -35,7 +39,7 @@ impl BootloaderConfig { 0x3D, ]; #[doc(hidden)] - pub const SERIALIZED_LEN: usize = 115; + pub const SERIALIZED_LEN: usize = 116; /// Creates a new default configuration with the following values: /// @@ -48,6 +52,7 @@ impl BootloaderConfig { version: ApiVersion::new_default(), mappings: Mappings::new_default(), frame_buffer: FrameBuffer::new_default(), + log_level: log::LevelFilter::Trace, } } @@ -61,6 +66,7 @@ impl BootloaderConfig { mappings, kernel_stack_size, frame_buffer, + log_level, } = self; let ApiVersion { version_major, @@ -133,13 +139,23 @@ impl BootloaderConfig { }, ); - concat_106_9( + let buf = concat_106_9( buf, match minimum_framebuffer_width { Option::None => [0; 9], Option::Some(addr) => concat_1_8([1], addr.to_le_bytes()), }, - ) + ); + + let log_level: u8 = match quiet { + log::LevelFilter::Trace => 0, + log::LevelFilter::Info => 1, + log::LevelFilter::Warn => 2, + log::LevelFilter::Error => 3, + log::LevelFilter::Off => 4, + }; + + concat_115_1(buf, log_level.to_le_bytes()); } /// Tries to deserialize a config byte array that was created using [`Self::serialize`]. @@ -252,6 +268,16 @@ impl BootloaderConfig { (frame_buffer, s) }; + let (&log_level, s) = split_array_ref(s); + let log_level = match u8::from_le_bytes(log_level) { + 0 => log::LevelFilter::Trace, + 1 => log::LevelFilter::Info, + 2 => log::LevelFilter::Warn, + 3 => log::LevelFilter::Error, + 4 => log::LevelFilter::Off, + _ => return Err("log_level invalid"), + }; + if !s.is_empty() { return Err("unexpected rest"); } @@ -261,6 +287,7 @@ impl BootloaderConfig { kernel_stack_size: u64::from_le_bytes(kernel_stack_size), mappings, frame_buffer, + log_level, }) } diff --git a/bios/stage-4/src/main.rs b/bios/stage-4/src/main.rs index bd44b396..f97cf870 100644 --- a/bios/stage-4/src/main.rs +++ b/bios/stage-4/src/main.rs @@ -24,10 +24,6 @@ mod memory_descriptor; #[no_mangle] #[link_section = ".start"] pub extern "C" fn _start(info: &mut BiosInfo) -> ! { - let framebuffer_info = init_logger(info.framebuffer); - log::info!("4th Stage"); - log::info!("{info:x?}"); - let memory_map: &mut [E820MemoryRegion] = unsafe { core::slice::from_raw_parts_mut( info.memory_map_addr as *mut _, @@ -102,8 +98,6 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! { // it's mapped using `invlpg`, for efficiency. x86_64::instructions::tlb::flush_all(); - log::info!("BIOS boot"); - let page_tables = create_page_tables(&mut frame_allocator); let kernel_slice = { @@ -112,6 +106,12 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! { }; let kernel = Kernel::parse(kernel_slice); + let framebuffer_info = init_logger(info.framebuffer, kernel.config.log_level); + + log::info!("4th Stage"); + log::info!("{info:x?}"); + log::info!("BIOS boot"); + let system_info = SystemInfo { framebuffer: Some(RawFrameBufferInfo { addr: PhysAddr::new(info.framebuffer.region.start), @@ -123,7 +123,7 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! { load_and_switch_to_kernel(kernel, frame_allocator, page_tables, system_info); } -fn init_logger(info: BiosFramebufferInfo) -> FrameBufferInfo { +fn init_logger(info: BiosFramebufferInfo, log_level: log::LevelFilter) -> FrameBufferInfo { let framebuffer_info = FrameBufferInfo { byte_len: info.region.len.try_into().unwrap(), width: info.width.into(), @@ -152,7 +152,7 @@ fn init_logger(info: BiosFramebufferInfo) -> FrameBufferInfo { ) }; - bootloader_x86_64_common::init_logger(framebuffer, framebuffer_info); + bootloader_x86_64_common::init_logger(framebuffer, framebuffer_info, log_level); framebuffer_info } diff --git a/common/src/lib.rs b/common/src/lib.rs index 4a204972..bc5cfe1b 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -35,10 +35,10 @@ pub mod logger; const PAGE_SIZE: u64 = 4096; /// Initialize a text-based logger using the given pixel-based framebuffer as output. -pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo) { +pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo, log_level: log::LevelFilter) { let logger = logger::LOGGER.get_or_init(move || logger::LockedLogger::new(framebuffer, info)); log::set_logger(logger).expect("logger already set"); - log::set_max_level(log::LevelFilter::Trace); + log::set_max_level(log_level); log::info!("Framebuffer info: {:?}", info); } diff --git a/uefi/src/main.rs b/uefi/src/main.rs index e94bc00c..d96d60c1 100644 --- a/uefi/src/main.rs +++ b/uefi/src/main.rs @@ -420,7 +420,7 @@ fn init_logger(st: &SystemTable, config: BootloaderConfig) -> Option Date: Fri, 30 Dec 2022 20:59:55 +0100 Subject: [PATCH 2/7] Fix mistakes in config.rs --- api/src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/config.rs b/api/src/config.rs index 3dbc907a..6fed4eee 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -147,7 +147,7 @@ impl BootloaderConfig { }, ); - let log_level: u8 = match quiet { + let log_level: u8 = match log_level { log::LevelFilter::Trace => 0, log::LevelFilter::Info => 1, log::LevelFilter::Warn => 2, @@ -155,7 +155,7 @@ impl BootloaderConfig { log::LevelFilter::Off => 4, }; - concat_115_1(buf, log_level.to_le_bytes()); + concat_115_1(buf, log_level.to_le_bytes()) } /// Tries to deserialize a config byte array that was created using [`Self::serialize`]. From 4f8d96323be64bf831e052bb8ace91b6d461f0d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Asensio=20Garc=C3=ADa?= <101601871+asensio-project@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:13:15 +0100 Subject: [PATCH 3/7] Add support for the Debug level --- api/src/config.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/api/src/config.rs b/api/src/config.rs index 6fed4eee..b5a952d9 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -149,10 +149,11 @@ impl BootloaderConfig { let log_level: u8 = match log_level { log::LevelFilter::Trace => 0, - log::LevelFilter::Info => 1, - log::LevelFilter::Warn => 2, - log::LevelFilter::Error => 3, - log::LevelFilter::Off => 4, + log::LevelFilter::Debug => 1, + log::LevelFilter::Info => 2, + log::LevelFilter::Warn => 3, + log::LevelFilter::Error => 4, + log::LevelFilter::Off => 5, }; concat_115_1(buf, log_level.to_le_bytes()) @@ -271,10 +272,11 @@ impl BootloaderConfig { let (&log_level, s) = split_array_ref(s); let log_level = match u8::from_le_bytes(log_level) { 0 => log::LevelFilter::Trace, - 1 => log::LevelFilter::Info, - 2 => log::LevelFilter::Warn, - 3 => log::LevelFilter::Error, - 4 => log::LevelFilter::Off, + 1 => log::LevelFilter::Debug, + 2 => log::LevelFilter::Info, + 3 => log::LevelFilter::Warn, + 4 => log::LevelFilter::Error, + 5 => log::LevelFilter::Off, _ => return Err("log_level invalid"), }; From 8bda57ac27a4c157f01b5864868e4cb48dbc4c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Asensio=20Garc=C3=ADa?= <101601871+asensio-project@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:35:48 +0100 Subject: [PATCH 4/7] Fix a test --- api/src/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/config.rs b/api/src/config.rs index b5a952d9..374982d0 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -300,6 +300,7 @@ impl BootloaderConfig { mappings: Mappings::random(), kernel_stack_size: rand::random(), frame_buffer: FrameBuffer::random(), + log_level: rand::random(), } } } From f531f33ccd801e4c308c7021c958aec73666f89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Asensio=20Garc=C3=ADa?= <101601871+asensio-project@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:40:43 +0100 Subject: [PATCH 5/7] Fix a test ( Second Review ) --- api/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/config.rs b/api/src/config.rs index 374982d0..af017992 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -300,7 +300,7 @@ impl BootloaderConfig { mappings: Mappings::random(), kernel_stack_size: rand::random(), frame_buffer: FrameBuffer::random(), - log_level: rand::random(), + log_level: log::LevelFilter::Trace, } } } From a7e77f9f09feaa354d6a85cc7b24354ef45ad855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Asensio=20Garc=C3=ADa?= <101601871+asensio-project@users.noreply.github.com> Date: Fri, 30 Dec 2022 21:56:23 +0100 Subject: [PATCH 6/7] Fix format --- common/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/src/lib.rs b/common/src/lib.rs index bc5cfe1b..ef584bbd 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -35,7 +35,11 @@ pub mod logger; const PAGE_SIZE: u64 = 4096; /// Initialize a text-based logger using the given pixel-based framebuffer as output. -pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo, log_level: log::LevelFilter) { +pub fn init_logger( + framebuffer: &'static mut [u8], + info: FrameBufferInfo, + log_level: log::LevelFilter, +) { let logger = logger::LOGGER.get_or_init(move || logger::LockedLogger::new(framebuffer, info)); log::set_logger(logger).expect("logger already set"); log::set_max_level(log_level); From d1da62f8bb45d7d42f2088c1fc758f29f2b40f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Asensio=20Garc=C3=ADa?= Date: Mon, 2 Jan 2023 23:42:59 +0100 Subject: [PATCH 7/7] Use a custom LevelFilter instead the log's one --- api/Cargo.toml | 1 - api/src/config.rs | 65 +++++++++++++++++++++++++++------------- bios/stage-4/src/main.rs | 7 +++-- common/src/lib.rs | 21 ++++++++----- 4 files changed, 63 insertions(+), 31 deletions(-) diff --git a/api/Cargo.toml b/api/Cargo.toml index 28a52fef..ef687b0c 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -9,7 +9,6 @@ description = "Makes a kernel compatible with the bootloader crate" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -log = "0.4.17" [dev-dependencies] rand = "0.8.4" diff --git a/api/src/config.rs b/api/src/config.rs index af017992..a7660746 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -30,7 +30,7 @@ pub struct BootloaderConfig { /// Configuration for changing the level of the filter of the messages that are shown in the /// screen when booting. The default is 'Trace'. - pub log_level: log::LevelFilter, + pub log_level: LevelFilter, } impl BootloaderConfig { @@ -52,7 +52,7 @@ impl BootloaderConfig { version: ApiVersion::new_default(), mappings: Mappings::new_default(), frame_buffer: FrameBuffer::new_default(), - log_level: log::LevelFilter::Trace, + log_level: LevelFilter::Trace, } } @@ -147,16 +147,7 @@ impl BootloaderConfig { }, ); - let log_level: u8 = match log_level { - log::LevelFilter::Trace => 0, - log::LevelFilter::Debug => 1, - log::LevelFilter::Info => 2, - log::LevelFilter::Warn => 3, - log::LevelFilter::Error => 4, - log::LevelFilter::Off => 5, - }; - - concat_115_1(buf, log_level.to_le_bytes()) + concat_115_1(buf, (*log_level as u8).to_le_bytes()) } /// Tries to deserialize a config byte array that was created using [`Self::serialize`]. @@ -270,14 +261,10 @@ impl BootloaderConfig { }; let (&log_level, s) = split_array_ref(s); - let log_level = match u8::from_le_bytes(log_level) { - 0 => log::LevelFilter::Trace, - 1 => log::LevelFilter::Debug, - 2 => log::LevelFilter::Info, - 3 => log::LevelFilter::Warn, - 4 => log::LevelFilter::Error, - 5 => log::LevelFilter::Off, - _ => return Err("log_level invalid"), + let log_level = LevelFilter::from_u8(u8::from_le_bytes(log_level)); + let log_level = match log_level { + Option::Some(level) => level, + Option::None => return Err("log_level invalid"), }; if !s.is_empty() { @@ -300,7 +287,7 @@ impl BootloaderConfig { mappings: Mappings::random(), kernel_stack_size: rand::random(), frame_buffer: FrameBuffer::random(), - log_level: log::LevelFilter::Trace, + log_level: LevelFilter::Trace, } } } @@ -564,6 +551,42 @@ impl Default for Mapping { } } +/// An enum representing the available verbosity level filters of the logger. +/// +/// Based on +/// https://github.com/rust-lang/log/blob/dc32ab999f52805d5ce579b526bd9d9684c38d1a/src/lib.rs#L552-565 +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum LevelFilter { + /// A level lower than all log levels. + Off, + /// Corresponds to the `Error` log level. + Error, + /// Corresponds to the `Warn` log level. + Warn, + /// Corresponds to the `Info` log level. + Info, + /// Corresponds to the `Debug` log level. + Debug, + /// Corresponds to the `Trace` log level. + Trace, +} + +impl LevelFilter { + /// Converts a u8 into a Option + pub fn from_u8(value: u8) -> Option { + match value { + 0 => Some(Self::Off), + 1 => Some(Self::Error), + 2 => Some(Self::Warn), + 3 => Some(Self::Info), + 4 => Some(Self::Debug), + 5 => Some(Self::Trace), + _ => None, + } + } +} + /// Taken from https://github.com/rust-lang/rust/blob/e100ec5bc7cd768ec17d75448b29c9ab4a39272b/library/core/src/slice/mod.rs#L1673-L1677 /// /// TODO replace with `split_array` feature in stdlib as soon as it's stabilized, diff --git a/bios/stage-4/src/main.rs b/bios/stage-4/src/main.rs index f97cf870..d6a50b9c 100644 --- a/bios/stage-4/src/main.rs +++ b/bios/stage-4/src/main.rs @@ -2,7 +2,10 @@ #![no_main] use crate::memory_descriptor::MemoryRegion; -use bootloader_api::info::{FrameBufferInfo, PixelFormat}; +use bootloader_api::{ + config::LevelFilter, + info::{FrameBufferInfo, PixelFormat}, +}; use bootloader_x86_64_bios_common::{BiosFramebufferInfo, BiosInfo, E820MemoryRegion}; use bootloader_x86_64_common::RawFrameBufferInfo; use bootloader_x86_64_common::{ @@ -123,7 +126,7 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! { load_and_switch_to_kernel(kernel, frame_allocator, page_tables, system_info); } -fn init_logger(info: BiosFramebufferInfo, log_level: log::LevelFilter) -> FrameBufferInfo { +fn init_logger(info: BiosFramebufferInfo, log_level: LevelFilter) -> FrameBufferInfo { let framebuffer_info = FrameBufferInfo { byte_len: info.region.len.try_into().unwrap(), width: info.width.into(), diff --git a/common/src/lib.rs b/common/src/lib.rs index ef584bbd..fc1c7d59 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -4,7 +4,7 @@ use crate::legacy_memory_region::{LegacyFrameAllocator, LegacyMemoryRegion}; use bootloader_api::{ - config::Mapping, + config::{LevelFilter, Mapping}, info::{FrameBuffer, FrameBufferInfo, MemoryRegion, TlsTemplate}, BootInfo, BootloaderConfig, }; @@ -35,17 +35,24 @@ pub mod logger; const PAGE_SIZE: u64 = 4096; /// Initialize a text-based logger using the given pixel-based framebuffer as output. -pub fn init_logger( - framebuffer: &'static mut [u8], - info: FrameBufferInfo, - log_level: log::LevelFilter, -) { +pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo, log_level: LevelFilter) { let logger = logger::LOGGER.get_or_init(move || logger::LockedLogger::new(framebuffer, info)); log::set_logger(logger).expect("logger already set"); - log::set_max_level(log_level); + log::set_max_level(convert_level(log_level)); log::info!("Framebuffer info: {:?}", info); } +fn convert_level(level: LevelFilter) -> log::LevelFilter { + match level { + LevelFilter::Off => log::LevelFilter::Off, + LevelFilter::Error => log::LevelFilter::Error, + LevelFilter::Warn => log::LevelFilter::Warn, + LevelFilter::Info => log::LevelFilter::Info, + LevelFilter::Debug => log::LevelFilter::Debug, + LevelFilter::Trace => log::LevelFilter::Trace, + } +} + /// Required system information that should be queried from the BIOS or UEFI firmware. #[derive(Debug, Copy, Clone)] pub struct SystemInfo {