extern crate core;
extern crate multiboot;
use core::mem;
use multiboot::information::{
ColorInfoRgb, ColorInfoType, ElfSymbols, FramebufferTable, MemoryEntry, MemoryManagement,
MemoryType, Module, Multiboot, MultibootInfo, PAddr, SymbolType,
};
struct Mem {
string_buffer: [u8; 5],
module_buffer: [u8; 16],
}
impl Mem {
fn new() -> Self {
Self {
string_buffer: [0; 5],
module_buffer: [0; 16],
}
}
}
impl MemoryManagement for Mem {
unsafe fn paddr_to_slice(&self, _addr: PAddr, _size: usize) -> Option<&'static [u8]> {
None
}
unsafe fn allocate(&mut self, length: usize) -> Option<(PAddr, &mut [u8])> {
match length {
5 => Some((0x12345678, &mut self.string_buffer)), 16 => Some((0xaaaaaaaa, &mut self.module_buffer)), _ => None,
}
}
unsafe fn deallocate(&mut self, addr: PAddr) {
if addr != 0 {
unimplemented!()
}
}
}
#[test]
fn empty() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_memory_bounds(None);
multiboot.set_command_line(None);
multiboot.set_modules(None);
multiboot.set_symbols(None);
multiboot.set_memory_regions(None);
multiboot.set_boot_loader_name(None);
multiboot.set_framebuffer_table(None);
let expected: [u8; 120] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
}
#[test]
fn memory_bounds() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_memory_bounds(Some((640, 8 * 1024)));
let expected: [u8; 120] = [
0x01, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
}
#[test]
fn command_line() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_command_line(Some("test"));
let expected: [u8; 120] = [
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
assert_eq!(mem.string_buffer, [0x74, 0x65, 0x73, 0x74, 0x00]); }
#[test]
fn modules() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_modules(Some(&[Module::new(0x12345678, 0x87654321, Some("test"))]));
let expected: [u8; 120] = [
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
assert_eq!(mem.string_buffer, [0x74, 0x65, 0x73, 0x74, 0x00]); assert_eq!(
mem.module_buffer,
[
0x78, 0x56, 0x34, 0x12, 0x21, 0x43, 0x65, 0x87, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00 ]
);
}
#[test]
fn symbols() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_symbols(Some(SymbolType::Elf(ElfSymbols::from_addr(
1, 8, 0x12345678, 0,
))));
let expected: [u8; 120] = [
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
}
#[test]
fn mmap() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_memory_regions(Some((0x12345678, 1)));
let expected: [u8; 120] = [
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
let memory_entry = MemoryEntry::new(0x12345678, 4096, MemoryType::Defect);
let expected_entry: [u8; 24] = [
0x14, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, ];
assert_eq!(
unsafe { mem::transmute::<_, [u8; 24]>(memory_entry) },
expected_entry
);
}
#[test]
fn boot_loader_name() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_boot_loader_name(Some("test"));
let expected: [u8; 120] = [
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
assert_eq!(mem.string_buffer, [0x74, 0x65, 0x73, 0x74, 0x00]); }
#[test]
fn framebuffer() {
let mut mem = Mem::new();
let mut info = MultibootInfo::default();
let mut multiboot = Multiboot::from_ref(&mut info, &mut mem);
multiboot.set_framebuffer_table(Some(FramebufferTable::new(
0x12345678,
800 * 4,
800,
600,
32,
ColorInfoType::Rgb(ColorInfoRgb {
red_field_position: 0,
red_mask_size: 8,
green_field_position: 8,
green_mask_size: 8,
blue_field_position: 16,
blue_mask_size: 8,
}),
)));
let expected: [u8; 120] = [
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, ];
assert_eq!(multiboot_info_to_bytes(info), expected);
}
fn multiboot_info_to_bytes(info: MultibootInfo) -> [u8; 120] {
assert_eq!(mem::size_of::<MultibootInfo>(), 120);
let mut bytes = [0; 120];
let info_bytes: [u8; 120] = unsafe { mem::transmute(info) };
for (index, byte) in info_bytes.iter().enumerate() {
if ![0x6E, 0x6F, 0x76, 0x77].contains(&index) {
bytes[index] = *byte;
}
}
bytes
}