1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
use crate::TagType;
use core::str::Utf8Error;
/// This tag contains the name of the bootloader that is booting the kernel.
///
/// The name is a normal C-style UTF-8 zero-terminated string that can be
/// obtained via the `name` method.
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)] // only repr(C) would add unwanted padding before first_section
pub struct BootLoaderNameTag {
typ: TagType,
size: u32,
/// Null-terminated UTF-8 string
string: u8,
}
impl BootLoaderNameTag {
/// Read the name of the bootloader that is booting the kernel.
/// This is an null-terminated UTF-8 string. If this returns `Err` then perhaps the memory
/// is invalid or the bootloader doesn't follow the spec.
///
/// # Examples
///
/// ```ignore
/// if let Some(tag) = boot_info.boot_loader_name_tag() {
/// let name = tag.name();
/// assert_eq!("GRUB 2.02~beta3-5", name);
/// }
/// ```
pub fn name(&self) -> Result<&str, Utf8Error> {
use core::{mem, slice, str};
// strlen without null byte
let strlen = self.size as usize - mem::size_of::<BootLoaderNameTag>();
let bytes = unsafe { slice::from_raw_parts((&self.string) as *const u8, strlen) };
str::from_utf8(bytes)
}
}
#[cfg(test)]
mod tests {
use crate::TagType;
const MSG: &str = "hello";
/// Returns the tag structure in bytes in native endian format.
fn get_bytes() -> std::vec::Vec<u8> {
// size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
let size = (4 + 4 + MSG.as_bytes().len() + 1) as u32;
[
&((TagType::BootLoaderName as u32).to_ne_bytes()),
&size.to_ne_bytes(),
MSG.as_bytes(),
// Null Byte
&[0],
]
.iter()
.flat_map(|bytes| bytes.iter())
.copied()
.collect()
}
/// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
#[test]
fn test_parse_str() {
let tag = get_bytes();
let tag = unsafe {
tag.as_ptr()
.cast::<super::BootLoaderNameTag>()
.as_ref()
.unwrap()
};
assert_eq!({ tag.typ }, TagType::BootLoaderName);
assert_eq!(tag.name().expect("must be valid UTF-8"), MSG);
}
}