blob: 74d21ea7afcdb0cf5bea231027189dc307da359c [file] [log] [blame]
/*
* 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);