boot2dump/lib.rs
1//! A library for OS developers to save a kernel crash log happened in your
2//! own kernel into a file on disk reboot the computer.
3//!
4//! # Prerequisites
5//!
6//! You kernel needs to satisfy the following prerequisites to use this crate:
7//!
8//! - The CPU is x86_64 and is in the 64-bit mode.
9//! - The file system is ext4 and its on a virtio-blk device.
10//! - A **sufficiently large** file for the crash log (e.g. in the following example, `kerla.dump`)
11//! already exists in the **root directory**.
12//! - Virtual addresses starting `0xffff_8000_0000_0000` are straight mapped into
13//! from the physical addresses 0 (i.e. `0xffff_8000_0001_0000` points to `0x1_0000`).
14//! It should cover the memory pages where boot2dump image exist.
15//!
16//! # How to Use
17//!
18//! The usage is pretty simple: at the end of your panic handler, call
19//! [`save_to_file_and_reboot`]. It will save the given buffer into a file
20//! and then reboot the computer.
21//!
22//! # Example
23//!
24//! ```ignore
25//! use boot2dump::save_to_file_and_reboot;
26//!
27//! #[panic_handler]
28//! fn panic(info: &core::panic::PanicInfo) -> ! {
29//! // Save the panic message into a file. Let's hope `format!` won't panic...
30//! let message = format!("{}", info).as_bytes();
31//! save_to_file_and_reboot("kerla.dump", message.as_bytes());
32//! }
33//! ```
34#![no_std]
35
36#[repr(align(4096))]
37struct PageAligned;
38
39// A quick workaround for aligning the image location to a page boundary.
40// https://users.rust-lang.org/t/can-i-conveniently-compile-bytes-into-a-rust-program-with-a-specific-alignment/24049/2
41#[repr(C)]
42struct Image<T: ?Sized> {
43 _align: [PageAligned; 0],
44 data: T,
45}
46
47static BOOT2DUMP: &'static Image<[u8]> = &Image {
48 _align: [],
49 data: *include_bytes!("../boot2dump.bin"),
50};
51
52/// Saves `data` into `filename` on the disk and then reboots the computer.
53///
54/// Currently, it only supports saving to a file in the root directory. Thus,
55/// `filename` should be a filename without slashes (`/`), for example,
56/// `kerla.dump`.
57///
58/// # Safety
59///
60/// This function will boot another operating system (boot2dump) and it may cause
61/// a problem.
62pub unsafe fn save_to_file_and_reboot(filename: &str, data: &[u8]) -> ! {
63 type EntryPoint = extern "C" fn(*const u8, u64, *const u8, u64);
64 let entrypoint = core::mem::transmute::<_, EntryPoint>(BOOT2DUMP.data.as_ptr());
65 entrypoint(
66 filename.as_ptr(),
67 filename.len() as u64,
68 data.as_ptr(),
69 data.len() as u64,
70 );
71 core::hint::unreachable_unchecked();
72}