Skip to content

Commit fffa7ce

Browse files
Log level feature (#303)
1 parent 66c1218 commit fffa7ce

File tree

5 files changed

+84
-16
lines changed

5 files changed

+84
-16
lines changed

Diff for: api/build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fn main() {
2222
(88, 9),
2323
(97, 9),
2424
(106, 9),
25+
(115, 1),
2526
];
2627

2728
let mut code = String::new();

Diff for: api/src/config.rs

+56-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ pub struct BootloaderConfig {
2727
/// Configuration for the frame buffer that can be used by the kernel to display pixels
2828
/// on the screen.
2929
pub frame_buffer: FrameBuffer,
30+
31+
/// Configuration for changing the level of the filter of the messages that are shown in the
32+
/// screen when booting. The default is 'Trace'.
33+
pub log_level: LevelFilter,
3034
}
3135

3236
impl BootloaderConfig {
@@ -35,7 +39,7 @@ impl BootloaderConfig {
3539
0x3D,
3640
];
3741
#[doc(hidden)]
38-
pub const SERIALIZED_LEN: usize = 115;
42+
pub const SERIALIZED_LEN: usize = 116;
3943

4044
/// Creates a new default configuration with the following values:
4145
///
@@ -48,6 +52,7 @@ impl BootloaderConfig {
4852
version: ApiVersion::new_default(),
4953
mappings: Mappings::new_default(),
5054
frame_buffer: FrameBuffer::new_default(),
55+
log_level: LevelFilter::Trace,
5156
}
5257
}
5358

@@ -61,6 +66,7 @@ impl BootloaderConfig {
6166
mappings,
6267
kernel_stack_size,
6368
frame_buffer,
69+
log_level,
6470
} = self;
6571
let ApiVersion {
6672
version_major,
@@ -133,13 +139,15 @@ impl BootloaderConfig {
133139
},
134140
);
135141

136-
concat_106_9(
142+
let buf = concat_106_9(
137143
buf,
138144
match minimum_framebuffer_width {
139145
Option::None => [0; 9],
140146
Option::Some(addr) => concat_1_8([1], addr.to_le_bytes()),
141147
},
142-
)
148+
);
149+
150+
concat_115_1(buf, (*log_level as u8).to_le_bytes())
143151
}
144152

145153
/// Tries to deserialize a config byte array that was created using [`Self::serialize`].
@@ -252,6 +260,13 @@ impl BootloaderConfig {
252260
(frame_buffer, s)
253261
};
254262

263+
let (&log_level, s) = split_array_ref(s);
264+
let log_level = LevelFilter::from_u8(u8::from_le_bytes(log_level));
265+
let log_level = match log_level {
266+
Option::Some(level) => level,
267+
Option::None => return Err("log_level invalid"),
268+
};
269+
255270
if !s.is_empty() {
256271
return Err("unexpected rest");
257272
}
@@ -261,6 +276,7 @@ impl BootloaderConfig {
261276
kernel_stack_size: u64::from_le_bytes(kernel_stack_size),
262277
mappings,
263278
frame_buffer,
279+
log_level,
264280
})
265281
}
266282

@@ -271,6 +287,7 @@ impl BootloaderConfig {
271287
mappings: Mappings::random(),
272288
kernel_stack_size: rand::random(),
273289
frame_buffer: FrameBuffer::random(),
290+
log_level: LevelFilter::Trace,
274291
}
275292
}
276293
}
@@ -534,6 +551,42 @@ impl Default for Mapping {
534551
}
535552
}
536553

554+
/// An enum representing the available verbosity level filters of the logger.
555+
///
556+
/// Based on
557+
/// https://github.com/rust-lang/log/blob/dc32ab999f52805d5ce579b526bd9d9684c38d1a/src/lib.rs#L552-565
558+
#[repr(u8)]
559+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
560+
pub enum LevelFilter {
561+
/// A level lower than all log levels.
562+
Off,
563+
/// Corresponds to the `Error` log level.
564+
Error,
565+
/// Corresponds to the `Warn` log level.
566+
Warn,
567+
/// Corresponds to the `Info` log level.
568+
Info,
569+
/// Corresponds to the `Debug` log level.
570+
Debug,
571+
/// Corresponds to the `Trace` log level.
572+
Trace,
573+
}
574+
575+
impl LevelFilter {
576+
/// Converts a u8 into a Option<LevelFilter>
577+
pub fn from_u8(value: u8) -> Option<LevelFilter> {
578+
match value {
579+
0 => Some(Self::Off),
580+
1 => Some(Self::Error),
581+
2 => Some(Self::Warn),
582+
3 => Some(Self::Info),
583+
4 => Some(Self::Debug),
584+
5 => Some(Self::Trace),
585+
_ => None,
586+
}
587+
}
588+
}
589+
537590
/// Taken from https://github.com/rust-lang/rust/blob/e100ec5bc7cd768ec17d75448b29c9ab4a39272b/library/core/src/slice/mod.rs#L1673-L1677
538591
///
539592
/// TODO replace with `split_array` feature in stdlib as soon as it's stabilized,

Diff for: bios/stage-4/src/main.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
#![no_main]
33

44
use crate::memory_descriptor::MemoryRegion;
5-
use bootloader_api::info::{FrameBufferInfo, PixelFormat};
5+
use bootloader_api::{
6+
config::LevelFilter,
7+
info::{FrameBufferInfo, PixelFormat},
8+
};
69
use bootloader_x86_64_bios_common::{BiosFramebufferInfo, BiosInfo, E820MemoryRegion};
710
use bootloader_x86_64_common::RawFrameBufferInfo;
811
use bootloader_x86_64_common::{
@@ -24,10 +27,6 @@ mod memory_descriptor;
2427
#[no_mangle]
2528
#[link_section = ".start"]
2629
pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
27-
let framebuffer_info = init_logger(info.framebuffer);
28-
log::info!("4th Stage");
29-
log::info!("{info:x?}");
30-
3130
let memory_map: &mut [E820MemoryRegion] = unsafe {
3231
core::slice::from_raw_parts_mut(
3332
info.memory_map_addr as *mut _,
@@ -102,8 +101,6 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
102101
// it's mapped using `invlpg`, for efficiency.
103102
x86_64::instructions::tlb::flush_all();
104103

105-
log::info!("BIOS boot");
106-
107104
let page_tables = create_page_tables(&mut frame_allocator);
108105

109106
let kernel_slice = {
@@ -112,6 +109,12 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
112109
};
113110
let kernel = Kernel::parse(kernel_slice);
114111

112+
let framebuffer_info = init_logger(info.framebuffer, kernel.config.log_level);
113+
114+
log::info!("4th Stage");
115+
log::info!("{info:x?}");
116+
log::info!("BIOS boot");
117+
115118
let system_info = SystemInfo {
116119
framebuffer: Some(RawFrameBufferInfo {
117120
addr: PhysAddr::new(info.framebuffer.region.start),
@@ -123,7 +126,7 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
123126
load_and_switch_to_kernel(kernel, frame_allocator, page_tables, system_info);
124127
}
125128

126-
fn init_logger(info: BiosFramebufferInfo) -> FrameBufferInfo {
129+
fn init_logger(info: BiosFramebufferInfo, log_level: LevelFilter) -> FrameBufferInfo {
127130
let framebuffer_info = FrameBufferInfo {
128131
byte_len: info.region.len.try_into().unwrap(),
129132
width: info.width.into(),
@@ -152,7 +155,7 @@ fn init_logger(info: BiosFramebufferInfo) -> FrameBufferInfo {
152155
)
153156
};
154157

155-
bootloader_x86_64_common::init_logger(framebuffer, framebuffer_info);
158+
bootloader_x86_64_common::init_logger(framebuffer, framebuffer_info, log_level);
156159

157160
framebuffer_info
158161
}

Diff for: common/src/lib.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use crate::legacy_memory_region::{LegacyFrameAllocator, LegacyMemoryRegion};
66
use bootloader_api::{
7-
config::Mapping,
7+
config::{LevelFilter, Mapping},
88
info::{FrameBuffer, FrameBufferInfo, MemoryRegion, TlsTemplate},
99
BootInfo, BootloaderConfig,
1010
};
@@ -35,13 +35,24 @@ pub mod logger;
3535
const PAGE_SIZE: u64 = 4096;
3636

3737
/// Initialize a text-based logger using the given pixel-based framebuffer as output.
38-
pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo) {
38+
pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo, log_level: LevelFilter) {
3939
let logger = logger::LOGGER.get_or_init(move || logger::LockedLogger::new(framebuffer, info));
4040
log::set_logger(logger).expect("logger already set");
41-
log::set_max_level(log::LevelFilter::Trace);
41+
log::set_max_level(convert_level(log_level));
4242
log::info!("Framebuffer info: {:?}", info);
4343
}
4444

45+
fn convert_level(level: LevelFilter) -> log::LevelFilter {
46+
match level {
47+
LevelFilter::Off => log::LevelFilter::Off,
48+
LevelFilter::Error => log::LevelFilter::Error,
49+
LevelFilter::Warn => log::LevelFilter::Warn,
50+
LevelFilter::Info => log::LevelFilter::Info,
51+
LevelFilter::Debug => log::LevelFilter::Debug,
52+
LevelFilter::Trace => log::LevelFilter::Trace,
53+
}
54+
}
55+
4556
/// Required system information that should be queried from the BIOS or UEFI firmware.
4657
#[derive(Debug, Copy, Clone)]
4758
pub struct SystemInfo {

Diff for: uefi/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ fn init_logger(st: &SystemTable<Boot>, config: BootloaderConfig) -> Option<RawFr
420420

421421
log::info!("UEFI boot");
422422

423-
bootloader_x86_64_common::init_logger(slice, info);
423+
bootloader_x86_64_common::init_logger(slice, info, config.log_level);
424424

425425
Some(RawFrameBufferInfo {
426426
addr: PhysAddr::new(framebuffer.as_mut_ptr() as u64),

0 commit comments

Comments
 (0)