/* * Copyright (c) 2024 Google Inc. All rights reserved * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // TODO: replace with `trusty-log` crate once it is `no_std`-compatible use alloc::ffi::CString; use alloc::format; use core::ffi::c_uint; use log::{LevelFilter, Log, Metadata, Record}; use crate::init::lk_init_level; use crate::LK_INIT_HOOK; use crate::sys::fflush; use crate::sys::fputs; use crate::sys::lk_stderr; use crate::sys::LK_LOGLEVEL_RUST; static TRUSTY_LOGGER: TrustyKernelLogger = TrustyKernelLogger; pub struct TrustyKernelLogger; impl Log for TrustyKernelLogger { fn enabled(&self, _metadata: &Metadata) -> bool { true } fn log(&self, record: &Record) { if self.enabled(record.metadata()) { let cstr = CString::new(format!("{} - {}\n", record.level(), record.args())).unwrap(); // Safety: // The pointer returned by `cstr.as_ptr()` is valid because the lifetime of the // `CString` encompasses the lifetime of the unsafe block. // `lk_stderr()` returns a FILE pointer that is valid or null. unsafe { fputs(cstr.as_ptr(), lk_stderr()) }; } } fn flush(&self) { // Safety: // `lk_stderr()` returns a FILE pointer that is valid or null. unsafe { fflush(lk_stderr()) }; } } /// Initialize logging for Rust in the kernel /// /// By default, only warnings and errors are logged (even in debug builds). /// /// The log level (`LK_LOGLEVEL_RUST`) is controlled by these make variables: /// - `LOG_LEVEL_KERNEL_RUST` if set, /// - `LOG_LEVEL_KERNEL` if set, and /// - `DEBUG` otherwise. /// /// Values below (above) expected values sets the log level to off (trace). extern "C" fn kernel_log_init_func(_level: c_uint) { log::set_logger(&TRUSTY_LOGGER).unwrap(); // Level or LevelFilter cannot be created directly from integers // https://github.com/rust-lang/log/issues/460 // // bindgen emits `LK_LOGLEVEL_RUST` as `u32` when the value is // a positive integer and omits it otherwise thus causing the // build to fail. log::set_max_level(match LK_LOGLEVEL_RUST { 0 => LevelFilter::Off, 1 => LevelFilter::Error, 2 => LevelFilter::Warn, // the default for Trusty 3 => LevelFilter::Info, 4 => LevelFilter::Debug, _ => LevelFilter::Trace, // enable trace! at 5+ }); } LK_INIT_HOOK!(kernel_log_init, kernel_log_init_func, lk_init_level::LK_INIT_LEVEL_HEAP);