123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883 |
- #![no_std]
- #![deny(missing_debug_implementations)]
- use core::fmt;
- use header::{Tag, TagIter};
- pub use boot_loader_name::BootLoaderNameTag;
- pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionType, ElfSectionFlags};
- pub use framebuffer::{FramebufferTag, FramebufferType, FramebufferField, FramebufferColor};
- pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
- pub use module::{ModuleTag, ModuleIter};
- pub use command_line::CommandLineTag;
- pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
- #[macro_use]
- extern crate bitflags;
- mod header;
- mod boot_loader_name;
- mod elf_sections;
- mod memory_map;
- mod module;
- mod command_line;
- mod rsdp;
- mod framebuffer;
- pub unsafe fn load(address: usize) -> BootInformation {
- assert_eq!(0, address & 0b111);
- let multiboot = &*(address as *const BootInformationInner);
- assert_eq!(0, multiboot.total_size & 0b111);
- assert!(multiboot.has_valid_end_tag());
- BootInformation { inner: multiboot, offset: 0 }
- }
- pub unsafe fn load_with_offset(address: usize, offset: usize) -> BootInformation {
- if !cfg!(test) {
- assert_eq!(0, address & 0b111);
- assert_eq!(0, offset & 0b111);
- }
- let multiboot = &*((address + offset) as *const BootInformationInner);
- assert_eq!(0, multiboot.total_size & 0b111);
- assert!(multiboot.has_valid_end_tag());
- BootInformation { inner: multiboot, offset: offset }
- }
- pub struct BootInformation {
- inner: *const BootInformationInner,
- offset: usize,
- }
- #[repr(C, packed)]
- struct BootInformationInner {
- total_size: u32,
- _reserved: u32,
- }
- impl BootInformation {
- pub fn start_address(&self) -> usize {
- self.inner as usize
- }
- pub fn end_address(&self) -> usize {
- self.start_address() + self.total_size()
- }
- pub fn total_size(&self) -> usize {
- self.get().total_size as usize
- }
- pub fn elf_sections_tag(&self) -> Option<ElfSectionsTag> {
- self.get_tag(9).map(|tag| unsafe {
- elf_sections::elf_sections_tag(tag, self.offset)
- })
- }
- pub fn memory_map_tag<'a>(&'a self) -> Option<&'a MemoryMapTag> {
- self.get_tag(6).map(|tag| unsafe { &*(tag as *const Tag as *const MemoryMapTag) })
- }
- pub fn module_tags(&self) -> ModuleIter {
- module::module_iter(self.tags())
- }
- pub fn boot_loader_name_tag<'a>(&'a self) -> Option<&'a BootLoaderNameTag> {
- self.get_tag(2).map(|tag| unsafe { &*(tag as *const Tag as *const BootLoaderNameTag) })
- }
- pub fn command_line_tag<'a>(&'a self) -> Option<&'a CommandLineTag> {
- self.get_tag(1).map(|tag| unsafe { &*(tag as *const Tag as *const CommandLineTag) })
- }
- pub fn framebuffer_tag<'a>(&'a self) -> Option<FramebufferTag<'a>> {
- self.get_tag(8).map(|tag| framebuffer::framebuffer_tag(tag))
- }
- pub fn rsdp_v1_tag<'a>(&self) -> Option<&'a RsdpV1Tag> {
- self.get_tag(14).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV1Tag) })
- }
- pub fn rsdp_v2_tag<'a>(&'a self) -> Option<&'a RsdpV2Tag> {
- self.get_tag(15).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV2Tag) })
- }
- fn get(&self) -> &BootInformationInner {
- unsafe { &*self.inner }
- }
- fn get_tag<'a>(&'a self, typ: u32) -> Option<&'a Tag> {
- self.tags().find(|tag| tag.typ == typ)
- }
- fn tags(&self) -> TagIter {
- TagIter::new(unsafe { self.inner.offset(1) } as *const _)
- }
- }
- impl BootInformationInner {
- fn has_valid_end_tag(&self) -> bool {
- const END_TAG: Tag = Tag { typ: 0, size: 8 };
- let self_ptr = self as *const _;
- let end_tag_addr = self_ptr as usize + (self.total_size - END_TAG.size) as usize;
- let end_tag = unsafe { &*(end_tag_addr as *const Tag) };
- end_tag.typ == END_TAG.typ && end_tag.size == END_TAG.size
- }
- }
- impl fmt::Debug for BootInformation {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- writeln!(f, "multiboot information")?;
- writeln!(f, "S: {:#010X}, E: {:#010X}, L: {:#010X}",
- self.start_address(), self.end_address(), self.total_size())?;
- if let Some(boot_loader_name_tag) = self.boot_loader_name_tag() {
- writeln!(f, "boot loader name: {}", boot_loader_name_tag.name())?;
- }
- if let Some(command_line_tag) = self.command_line_tag() {
- writeln!(f, "command line: {}", command_line_tag.command_line())?;
- }
- if let Some(memory_map_tag) = self.memory_map_tag() {
- writeln!(f, "memory areas:")?;
- for area in memory_map_tag.memory_areas() {
- writeln!(f, " S: {:#010X}, E: {:#010X}, L: {:#010X}",
- area.start_address(), area.end_address(), area.size())?;
- }
- }
- if let Some(elf_sections_tag) = self.elf_sections_tag() {
- writeln!(f, "kernel sections:")?;
- for s in elf_sections_tag.sections() {
- writeln!(f, " name: {:15}, S: {:#08X}, E: {:#08X}, L: {:#08X}, F: {:#04X}",
- s.name(), s.start_address(),
- s.start_address() + s.size(), s.size(), s.flags().bits())?;
- }
- }
- writeln!(f, "module tags:")?;
- for mt in self.module_tags() {
- writeln!(f, " name: {:15}, S: {:#010X}, E: {:#010X}",
- mt.name(), mt.start_address(), mt.end_address())?;
- }
- Ok(())
- }
- }
- pub(crate) struct Reader {
- pub(crate) ptr: *const u8,
- pub(crate) off: usize
- }
- impl Reader {
- pub(crate) fn new<T>(ptr: *const T) -> Reader {
- Reader {
- ptr: ptr as *const u8,
- off: 0
- }
- }
- pub(crate) fn read_u8(&mut self) -> u8 {
- self.off += 1;
- unsafe {
- core::ptr::read(self.ptr.offset((self.off - 1) as isize))
- }
- }
- pub(crate) fn read_u16(&mut self) -> u16 {
- self.read_u8() as u16 | (self.read_u8() as u16) << 8
- }
- pub(crate) fn read_u32(&mut self) -> u32 {
- self.read_u16() as u32 | (self.read_u16() as u32) << 16
- }
- pub(crate) fn read_u64(&mut self) -> u64 {
- self.read_u32() as u64 | (self.read_u32() as u64) << 32
- }
- pub(crate) fn skip(&mut self, n: usize) {
- self.off += n;
- }
- }
- #[cfg(test)]
- mod tests {
- use super::{load, load_with_offset};
- use super::{BootInformation, ElfSectionFlags, ElfSectionType};
- use super::FramebufferType;
- #[test]
- fn no_tags() {
- #[repr(C, align(8))]
- struct Bytes([u8; 16]);
- let bytes: Bytes = Bytes([
- 16, 0, 0, 0, // total_size
- 0, 0, 0, 0, // reserved
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, 0, // end tag size
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- assert!(bi.elf_sections_tag().is_none());
- assert!(bi.memory_map_tag().is_none());
- assert!(bi.module_tags().next().is_none());
- assert!(bi.boot_loader_name_tag().is_none());
- assert!(bi.command_line_tag().is_none());
- }
- #[test]
- #[should_panic]
- fn invalid_total_size() {
- #[repr(C, align(8))]
- struct Bytes([u8; 15]);
- let bytes: Bytes = Bytes([
- 15, 0, 0, 0, // total_size
- 0, 0, 0, 0, // reserved
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, // end tag size
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- assert!(bi.elf_sections_tag().is_none());
- assert!(bi.memory_map_tag().is_none());
- assert!(bi.module_tags().next().is_none());
- assert!(bi.boot_loader_name_tag().is_none());
- assert!(bi.command_line_tag().is_none());
- }
- #[test]
- #[should_panic]
- fn invalid_end_tag() {
- #[repr(C, align(8))]
- struct Bytes([u8; 16]);
- let bytes: Bytes = Bytes([
- 16, 0, 0, 0, // total_size
- 0, 0, 0, 0, // reserved
- 0, 0, 0, 0, // end tag type
- 9, 0, 0, 0, // end tag size
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- assert!(bi.elf_sections_tag().is_none());
- assert!(bi.memory_map_tag().is_none());
- assert!(bi.module_tags().next().is_none());
- assert!(bi.boot_loader_name_tag().is_none());
- assert!(bi.command_line_tag().is_none());
- }
- #[test]
- fn name_tag() {
- #[repr(C, align(8))]
- struct Bytes([u8; 32]);
- let bytes: Bytes = Bytes([
- 32, 0, 0, 0, // total_size
- 0, 0, 0, 0, // reserved
- 2, 0, 0, 0, // boot loader name tag type
- 13, 0, 0, 0, // boot loader name tag size
- 110, 97, 109, 101, // boot loader name 'name'
- 0, 0, 0, 0, // boot loader name null + padding
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, 0, // end tag size
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- assert!(bi.elf_sections_tag().is_none());
- assert!(bi.memory_map_tag().is_none());
- assert!(bi.module_tags().next().is_none());
- assert_eq!("name", bi.boot_loader_name_tag().unwrap().name());
- assert!(bi.command_line_tag().is_none());
- }
- #[test]
- fn framebuffer_tag_rgb() {
- // direct RGB mode test:
- // taken from GRUB2 running in QEMU at
- // 1280x720 with 32bpp in BGRA format.
- #[repr(C, align(8))]
- struct Bytes([u8; 56]);
- let bytes: Bytes = Bytes([
- 56, 0, 0, 0, // total size
- 0, 0, 0, 0, // reserved
- 8, 0, 0, 0, // framebuffer tag type
- 40, 0, 0, 0, // framebuffer tag size
- 0, 0, 0, 253, // framebuffer low dword of address
- 0, 0, 0, 0, // framebuffer high dword of address
- 0, 20, 0, 0, // framebuffer pitch
- 0, 5, 0, 0, // framebuffer width
- 208, 2, 0, 0, // framebuffer height
- 32, 1, 0, 0, // framebuffer bpp, type, reserved word
- 16, 8, 8, 8, // framebuffer red pos/size, green pos/size
- 0, 8, 0, 0, // framebuffer blue pos/size, padding word
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, 0 // end tag size
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- use framebuffer::{FramebufferTag, FramebufferField, FramebufferType};
- assert_eq!(bi.framebuffer_tag(), Some(FramebufferTag {
- address: 4244635648,
- pitch: 5120,
- width: 1280,
- height: 720,
- bpp: 32,
- buffer_type: FramebufferType::RGB {
- red: FramebufferField {
- position: 16, size: 8
- },
- green: FramebufferField {
- position: 8, size: 8
- },
- blue: FramebufferField {
- position: 0, size: 8
- }
- }
- }))
- }
- #[test]
- fn framebuffer_tag_indexed() {
- // indexed mode test:
- // this is synthetic, as I can't get QEMU
- // to run in indexed color mode.
- #[repr(C, align(8))]
- struct Bytes([u8; 56]);
- let bytes: Bytes = Bytes([
- 56, 0, 0, 0, // total size
- 0, 0, 0, 0, // reserved
- 8, 0, 0, 0, // framebuffer tag type
- 40, 0, 0, 0, // framebuffer tag size
- 0, 0, 0, 253, // framebuffer low dword of address
- 0, 0, 0, 0, // framebuffer high dword of address
- 0, 20, 0, 0, // framebuffer pitch
- 0, 5, 0, 0, // framebuffer width
- 208, 2, 0, 0, // framebuffer height
- 32, 0, 0, 0, // framebuffer bpp, type, reserved word
- 0, 1, 0, 0, // framebuffer palette length
- 0, 24, 1, 0, // framebuffer palette address
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, 0 // end tag size
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- use framebuffer::FramebufferType;
- assert!(bi.framebuffer_tag().is_some());
- let fbi = bi.framebuffer_tag().unwrap();
- assert_eq!(fbi.address, 4244635648);
- assert_eq!(fbi.pitch, 5120);
- assert_eq!(fbi.width, 1280);
- assert_eq!(fbi.height, 720);
- assert_eq!(fbi.bpp, 32);
- match fbi.buffer_type {
- FramebufferType::Indexed { palette } => {
- assert_eq!(palette.as_ptr() as usize, 71680);
- assert_eq!(palette.len(), 256);
- },
- _ => panic!("Expected indexed framebuffer type.")
- }
- }
- #[test]
- fn grub2() {
- #[repr(C, align(8))]
- struct Bytes([u8; 960]);
- let mut bytes: Bytes = Bytes([
- 192, 3, 0, 0, // total_size
- 0, 0, 0, 0, // reserved
- 1, 0, 0, 0, // boot command tag type
- 9, 0, 0, 0, // boot command tag size
- 0, 0, 0, 0, // boot command null + padding
- 0, 0, 0, 0, // boot command padding
- 2, 0, 0, 0, // boot loader name tag type
- 26, 0, 0, 0, // boot loader name tag size
- 71, 82, 85, 66, // boot loader name
- 32, 50, 46, 48, // boot loader name
- 50, 126, 98, 101, // boot loader name
- 116, 97, 51, 45, // boot loader name
- 53, 0, 0, 0, // boot loader name null + padding
- 0, 0, 0, 0, // boot loader name padding
- 10, 0, 0, 0, // APM tag type
- 28, 0, 0, 0, // APM tag size
- 2, 1, 0, 240, // APM version, cseg
- 207, 212, 0, 0, // APM offset
- 0, 240, 0, 240, // APM cseg_16, dseg
- 3, 0, 240, 255, // APM flags, cseg_len
- 240, 255, 240, 255, // APM cseg_16_len, dseg_len
- 0, 0, 0, 0, // APM padding
- 6, 0, 0, 0, // memory map tag type
- 160, 0, 0, 0, // memory map tag size
- 24, 0, 0, 0, // memory map entry_size
- 0, 0, 0, 0, // memory map entry_version
- 0, 0, 0, 0, // memory map entry 0 base_addr
- 0, 0, 0, 0, // memory map entry 0 base_addr
- 0, 252, 9, 0, // memory map entry 0 length
- 0, 0, 0, 0, // memory map entry 0 length
- 1, 0, 0, 0, // memory map entry 0 type
- 0, 0, 0, 0, // memory map entry 0 reserved
- 0, 252, 9, 0, // memory map entry 1 base_addr
- 0, 0, 0, 0, // memory map entry 1 base_addr
- 0, 4, 0, 0, // memory map entry 1 length
- 0, 0, 0, 0, // memory map entry 1 length
- 2, 0, 0, 0, // memory map entry 1 type
- 0, 0, 0, 0, // memory map entry 1 reserved
- 0, 0, 15, 0, // memory map entry 2 base_addr
- 0, 0, 0, 0, // memory map entry 2 base_addr
- 0, 0, 1, 0, // memory map entry 2 length
- 0, 0, 0, 0, // memory map entry 2 length
- 2, 0, 0, 0, // memory map entry 2 type
- 0, 0, 0, 0, // memory map entry 2 reserved
- 0, 0, 16, 0, // memory map entry 3 base_addr
- 0, 0, 0, 0, // memory map entry 3 base_addr
- 0, 0, 238, 7, // memory map entry 3 length
- 0, 0, 0, 0, // memory map entry 3 length
- 1, 0, 0, 0, // memory map entry 3 type
- 0, 0, 0, 0, // memory map entry 3 reserved
- 0, 0, 254, 7, // memory map entry 4 base_addr
- 0, 0, 0, 0, // memory map entry 4 base_addr
- 0, 0, 2, 0, // memory map entry 4 length
- 0, 0, 0, 0, // memory map entry 4 length
- 2, 0, 0, 0, // memory map entry 4 type
- 0, 0, 0, 0, // memory map entry 4 reserved
- 0, 0, 252, 255, // memory map entry 5 base_addr
- 0, 0, 0, 0, // memory map entry 5 base_addr
- 0, 0, 4, 0, // memory map entry 5 length
- 0, 0, 0, 0, // memory map entry 5 length
- 2, 0, 0, 0, // memory map entry 5 type
- 0, 0, 0, 0, // memory map entry 5 reserved
- 9, 0, 0, 0, // elf symbols tag type
- 84, 2, 0, 0, // elf symbols tag size
- 9, 0, 0, 0, // elf symbols num
- 64, 0, 0, 0, // elf symbols entsize
- 8, 0, 0, 0, // elf symbols shndx
- 0, 0, 0, 0, // elf symbols entry 0 name
- 0, 0, 0, 0, // elf symbols entry 0 type
- 0, 0, 0, 0, // elf symbols entry 0 flags
- 0, 0, 0, 0, // elf symbols entry 0 flags
- 0, 0, 0, 0, // elf symbols entry 0 addr
- 0, 0, 0, 0, // elf symbols entry 0 addr
- 0, 0, 0, 0, // elf symbols entry 0 offset
- 0, 0, 0, 0, // elf symbols entry 0 offset
- 0, 0, 0, 0, // elf symbols entry 0 size
- 0, 0, 0, 0, // elf symbols entry 0 size
- 0, 0, 0, 0, // elf symbols entry 0 link
- 0, 0, 0, 0, // elf symbols entry 0 info
- 0, 0, 0, 0, // elf symbols entry 0 addralign
- 0, 0, 0, 0, // elf symbols entry 0 addralign
- 0, 0, 0, 0, // elf symbols entry 0 entsize
- 0, 0, 0, 0, // elf symbols entry 0 entsize
- 27, 0, 0, 0, // elf symbols entry 1 name
- 1, 0, 0, 0, // elf symbols entry 1 type
- 2, 0, 0, 0, // elf symbols entry 1 flags
- 0, 0, 0, 0, // elf symbols entry 1 flags
- 0, 0, 16, 0, // elf symbols entry 1 addr
- 0, 128, 255, 255, // elf symbols entry 1 addr
- 0, 16, 0, 0, // elf symbols entry 1 offset
- 0, 0, 0, 0, // elf symbols entry 1 offset
- 0, 48, 0, 0, // elf symbols entry 1 size
- 0, 0, 0, 0, // elf symbols entry 1 size
- 0, 0, 0, 0, // elf symbols entry 1 link
- 0, 0, 0, 0, // elf symbols entry 1 info
- 16, 0, 0, 0, // elf symbols entry 1 addralign
- 0, 0, 0, 0, // elf symbols entry 1 addralign
- 0, 0, 0, 0, // elf symbols entry 1 entsize
- 0, 0, 0, 0, // elf symbols entry 1 entsize
- 35, 0, 0, 0, // elf symbols entry 2 name
- 1, 0, 0, 0, // elf symbols entry 2 type
- 6, 0, 0, 0, // elf symbols entry 2 flags
- 0, 0, 0, 0, // elf symbols entry 2 flags
- 0, 48, 16, 0, // elf symbols entry 2 addr
- 0, 128, 255, 255, // elf symbols entry 2 addr
- 0, 64, 0, 0, // elf symbols entry 2 offset
- 0, 0, 0, 0, // elf symbols entry 2 offset
- 0, 144, 0, 0, // elf symbols entry 2 size
- 0, 0, 0, 0, // elf symbols entry 2 size
- 0, 0, 0, 0, // elf symbols entry 2 link
- 0, 0, 0, 0, // elf symbols entry 2 info
- 16, 0, 0, 0, // elf symbols entry 2 addralign
- 0, 0, 0, 0, // elf symbols entry 2 addralign
- 0, 0, 0, 0, // elf symbols entry 2 entsize
- 0, 0, 0, 0, // elf symbols entry 2 entsize
- 41, 0, 0, 0, // elf symbols entry 3 name
- 1, 0, 0, 0, // elf symbols entry 3 type
- 3, 0, 0, 0, // elf symbols entry 3 flags
- 0, 0, 0, 0, // elf symbols entry 3 flags
- 0, 192, 16, 0, // elf symbols entry 3 addr
- 0, 128, 255, 255, // elf symbols entry 3 addr
- 0, 208, 0, 0, // elf symbols entry 3 offset
- 0, 0, 0, 0, // elf symbols entry 3 offset
- 0, 32, 0, 0, // elf symbols entry 3 size
- 0, 0, 0, 0, // elf symbols entry 3 size
- 0, 0, 0, 0, // elf symbols entry 3 link
- 0, 0, 0, 0, // elf symbols entry 3 info
- 8, 0, 0, 0, // elf symbols entry 3 addralign
- 0, 0, 0, 0, // elf symbols entry 3 addralign
- 0, 0, 0, 0, // elf symbols entry 3 entsize
- 0, 0, 0, 0, // elf symbols entry 3 entsize
- 47, 0, 0, 0, // elf symbols entry 4 name
- 8, 0, 0, 0, // elf symbols entry 4 type
- 3, 0, 0, 0, // elf symbols entry 4 flags
- 0, 0, 0, 0, // elf symbols entry 4 flags
- 0, 224, 16, 0, // elf symbols entry 4 addr
- 0, 128, 255, 255, // elf symbols entry 4 addr
- 0, 240, 0, 0, // elf symbols entry 4 offset
- 0, 0, 0, 0, // elf symbols entry 4 offset
- 0, 80, 0, 0, // elf symbols entry 4 size
- 0, 0, 0, 0, // elf symbols entry 4 size
- 0, 0, 0, 0, // elf symbols entry 4 link
- 0, 0, 0, 0, // elf symbols entry 4 info
- 0, 16, 0, 0, // elf symbols entry 4 addralign
- 0, 0, 0, 0, // elf symbols entry 4 addralign
- 0, 0, 0, 0, // elf symbols entry 4 entsize
- 0, 0, 0, 0, // elf symbols entry 4 entsize
- 52, 0, 0, 0, // elf symbols entry 5 name
- 1, 0, 0, 0, // elf symbols entry 5 type
- 3, 0, 0, 0, // elf symbols entry 5 flags
- 0, 0, 0, 0, // elf symbols entry 5 flags
- 0, 48, 17, 0, // elf symbols entry 5 addr
- 0, 128, 255, 255, // elf symbols entry 5 addr
- 0, 240, 0, 0, // elf symbols entry 5 offset
- 0, 0, 0, 0, // elf symbols entry 5 offset
- 0, 0, 0, 0, // elf symbols entry 5 size
- 0, 0, 0, 0, // elf symbols entry 5 size
- 0, 0, 0, 0, // elf symbols entry 5 link
- 0, 0, 0, 0, // elf symbols entry 5 info
- 1, 0, 0, 0, // elf symbols entry 5 addralign
- 0, 0, 0, 0, // elf symbols entry 5 addralign
- 0, 0, 0, 0, // elf symbols entry 5 entsize
- 0, 0, 0, 0, // elf symbols entry 5 entsize
- 1, 0, 0, 0, // elf symbols entry 6 name
- 2, 0, 0, 0, // elf symbols entry 6 type
- 0, 0, 0, 0, // elf symbols entry 6 flags
- 0, 0, 0, 0, // elf symbols entry 6 flags
- 0, 48, 17, 0, // elf symbols entry 6 addr
- 0, 0, 0, 0, // elf symbols entry 6 addr
- 0, 240, 0, 0, // elf symbols entry 6 offset
- 0, 0, 0, 0, // elf symbols entry 6 offset
- 224, 43, 0, 0, // elf symbols entry 6 size
- 0, 0, 0, 0, // elf symbols entry 6 size
- 7, 0, 0, 0, // elf symbols entry 6 link
- 102, 1, 0, 0, // elf symbols entry 6 info
- 8, 0, 0, 0, // elf symbols entry 6 addralign
- 0, 0, 0, 0, // elf symbols entry 6 addralign
- 24, 0, 0, 0, // elf symbols entry 6 entsize
- 0, 0, 0, 0, // elf symbols entry 6 entsize
- 9, 0, 0, 0, // elf symbols entry 7 name
- 3, 0, 0, 0, // elf symbols entry 7 type
- 0, 0, 0, 0, // elf symbols entry 7 flags
- 0, 0, 0, 0, // elf symbols entry 7 flags
- 224, 91, 17, 0, // elf symbols entry 7 addr
- 0, 0, 0, 0, // elf symbols entry 7 addr
- 224, 27, 1, 0, // elf symbols entry 7 offset
- 0, 0, 0, 0, // elf symbols entry 7 offset
- 145, 55, 0, 0, // elf symbols entry 7 size
- 0, 0, 0, 0, // elf symbols entry 7 size
- 0, 0, 0, 0, // elf symbols entry 7 link
- 0, 0, 0, 0, // elf symbols entry 7 info
- 1, 0, 0, 0, // elf symbols entry 7 addralign
- 0, 0, 0, 0, // elf symbols entry 7 addralign
- 0, 0, 0, 0, // elf symbols entry 7 entsize
- 0, 0, 0, 0, // elf symbols entry 7 entsize
- 17, 0, 0, 0, // elf symbols entry 8 name
- 3, 0, 0, 0, // elf symbols entry 8 type
- 0, 0, 0, 0, // elf symbols entry 8 flags
- 0, 0, 0, 0, // elf symbols entry 8 flags
- 113, 147, 17, 0, // elf symbols entry 8 addr
- 0, 0, 0, 0, // elf symbols entry 8 addr
- 113, 83, 1, 0, // elf symbols entry 8 offset
- 0, 0, 0, 0, // elf symbols entry 8 offset
- 65, 0, 0, 0, // elf symbols entry 8 size
- 0, 0, 0, 0, // elf symbols entry 8 size
- 0, 0, 0, 0, // elf symbols entry 8 link
- 0, 0, 0, 0, // elf symbols entry 8 info
- 1, 0, 0, 0, // elf symbols entry 8 addralign
- 0, 0, 0, 0, // elf symbols entry 8 addralign
- 0, 0, 0, 0, // elf symbols entry 8 entsize
- 0, 0, 0, 0, // elf symbols entry 8 entsize
- 0, 0, 0, 0, // elf symbols padding
- 4, 0, 0, 0, // basic memory tag type
- 16, 0, 0, 0, // basic memory tag size
- 127, 2, 0, 0, // basic memory mem_lower
- 128, 251, 1, 0, // basic memory mem_upper
- 5, 0, 0, 0, // BIOS boot device tag type
- 20, 0, 0, 0, // BIOS boot device tag size
- 224, 0, 0, 0, // BIOS boot device biosdev
- 255, 255, 255, 255, // BIOS boot device partition
- 255, 255, 255, 255, // BIOS boot device subpartition
- 0, 0, 0, 0, // BIOS boot device padding
- 8, 0, 0, 0, // framebuffer info tag type
- 32, 0, 0, 0, // framebuffer info tag size
- 0, 128, 11, 0, // framebuffer info framebuffer_addr
- 0, 0, 0, 0, // framebuffer info framebuffer_addr
- 160, 0, 0, 0, // framebuffer info framebuffer_pitch
- 80, 0, 0, 0, // framebuffer info framebuffer_width
- 25, 0, 0, 0, // framebuffer info framebuffer_height
- 16, 2, 0, 0, // framebuffer info framebuffer_[bpp,type], reserved, color_info
- 14, 0, 0, 0, // ACPI old tag type
- 28, 0, 0, 0, // ACPI old tag size
- 82, 83, 68, 32, // ACPI old
- 80, 84, 82, 32, // ACPI old
- 89, 66, 79, 67, // ACPI old
- 72, 83, 32, 0, // ACPI old
- 220, 24, 254, 7, // ACPI old
- 0, 0, 0, 0, // ACPI old padding
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, 0, // end tag size
- ]);
- #[repr(C, align(8))]
- struct StringBytes([u8; 65]);
- let string_bytes: StringBytes = StringBytes([
- 0, 46, 115, 121,
- 109, 116, 97, 98,
- 0, 46, 115, 116,
- 114, 116, 97, 98,
- 0, 46, 115, 104,
- 115, 116, 114, 116,
- 97, 98, 0, 46,
- 114, 111, 100, 97,
- 116, 97, 0, 46,
- 116, 101, 120, 116,
- 0, 46, 100, 97,
- 116, 97, 0, 46,
- 98, 115, 115, 0,
- 46, 100, 97, 116,
- 97, 46, 114, 101,
- 108, 46, 114, 111,
- 0,
- ]);
- let string_addr = string_bytes.0.as_ptr() as u64;
- for i in 0..8 {
- bytes.0[796 + i] = (string_addr >> (i * 8)) as u8;
- }
- let addr = bytes.0.as_ptr() as usize;
- test_grub2_boot_info(
- unsafe { load(addr) },
- addr,
- string_addr,
- &bytes.0,
- &string_bytes.0,
- );
- test_grub2_boot_info(
- unsafe { load_with_offset(addr, 0) },
- addr,
- string_addr,
- &bytes.0,
- &string_bytes.0,
- );
- let offset = 8usize;
- for i in 0..8 {
- bytes.0[796 + i] = ((string_addr - offset as u64) >> (i * 8)) as u8;
- }
- test_grub2_boot_info(
- unsafe { load_with_offset(addr - offset, offset) },
- addr,
- string_addr - offset as u64,
- &bytes.0,
- &string_bytes.0,
- );
- }
- fn test_grub2_boot_info(
- bi: BootInformation,
- addr: usize,
- string_addr: u64,
- bytes: &[u8],
- string_bytes: &[u8],
- ) {
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.len(), bi.end_address());
- assert_eq!(bytes.len(), bi.total_size());
- let es = bi.elf_sections_tag().unwrap();
- let mut s = es.sections();
- let s1 = s.next().unwrap();
- assert_eq!(".rodata", s1.name());
- assert_eq!(0xFFFF_8000_0010_0000, s1.start_address());
- assert_eq!(0xFFFF_8000_0010_3000, s1.end_address());
- assert_eq!(0x0000_0000_0000_3000, s1.size());
- assert_eq!(ElfSectionFlags::ALLOCATED, s1.flags());
- assert_eq!(ElfSectionType::ProgramSection, s1.section_type());
- let s2 = s.next().unwrap();
- assert_eq!(".text", s2.name());
- assert_eq!(0xFFFF_8000_0010_3000, s2.start_address());
- assert_eq!(0xFFFF_8000_0010_C000, s2.end_address());
- assert_eq!(0x0000_0000_0000_9000, s2.size());
- assert_eq!(ElfSectionFlags::EXECUTABLE | ElfSectionFlags::ALLOCATED, s2.flags());
- assert_eq!(ElfSectionType::ProgramSection, s2.section_type());
- let s3 = s.next().unwrap();
- assert_eq!(".data", s3.name());
- assert_eq!(0xFFFF_8000_0010_C000, s3.start_address());
- assert_eq!(0xFFFF_8000_0010_E000, s3.end_address());
- assert_eq!(0x0000_0000_0000_2000, s3.size());
- assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s3.flags());
- assert_eq!(ElfSectionType::ProgramSection, s3.section_type());
- let s4 = s.next().unwrap();
- assert_eq!(".bss", s4.name());
- assert_eq!(0xFFFF_8000_0010_E000, s4.start_address());
- assert_eq!(0xFFFF_8000_0011_3000, s4.end_address());
- assert_eq!(0x0000_0000_0000_5000, s4.size());
- assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s4.flags());
- assert_eq!(ElfSectionType::Uninitialized, s4.section_type());
- let s5 = s.next().unwrap();
- assert_eq!(".data.rel.ro", s5.name());
- assert_eq!(0xFFFF_8000_0011_3000, s5.start_address());
- assert_eq!(0xFFFF_8000_0011_3000, s5.end_address());
- assert_eq!(0x0000_0000_0000_0000, s5.size());
- assert_eq!(ElfSectionFlags::ALLOCATED | ElfSectionFlags::WRITABLE, s5.flags());
- assert_eq!(ElfSectionType::ProgramSection, s5.section_type());
- let s6 = s.next().unwrap();
- assert_eq!(".symtab", s6.name());
- assert_eq!(0x0000_0000_0011_3000, s6.start_address());
- assert_eq!(0x0000_0000_0011_5BE0, s6.end_address());
- assert_eq!(0x0000_0000_0000_2BE0, s6.size());
- assert_eq!(ElfSectionFlags::empty(), s6.flags());
- assert_eq!(ElfSectionType::LinkerSymbolTable, s6.section_type());
- let s7 = s.next().unwrap();
- assert_eq!(".strtab", s7.name());
- assert_eq!(0x0000_0000_0011_5BE0, s7.start_address());
- assert_eq!(0x0000_0000_0011_9371, s7.end_address());
- assert_eq!(0x0000_0000_0000_3791, s7.size());
- assert_eq!(ElfSectionFlags::empty(), s7.flags());
- assert_eq!(ElfSectionType::StringTable, s7.section_type());
- let s8 = s.next().unwrap();
- assert_eq!(".shstrtab", s8.name());
- assert_eq!(string_addr, s8.start_address());
- assert_eq!(string_addr + string_bytes.len() as u64, s8.end_address());
- assert_eq!(string_bytes.len() as u64, s8.size());
- assert_eq!(ElfSectionFlags::empty(), s8.flags());
- assert_eq!(ElfSectionType::StringTable, s8.section_type());
- assert!(s.next().is_none());
- let mut mm = bi.memory_map_tag().unwrap().memory_areas();
- let mm1 = mm.next().unwrap();
- assert_eq!(0x00000000, mm1.start_address());
- assert_eq!(0x009_FC00, mm1.end_address());
- assert_eq!(0x009_FC00, mm1.size());
- let mm2 = mm.next().unwrap();
- assert_eq!(0x010_0000, mm2.start_address());
- assert_eq!(0x7FE_0000, mm2.end_address());
- assert_eq!(0x7EE_0000, mm2.size());
- assert!(mm.next().is_none());
- // Test the RSDP tag
- let rsdp_old = bi.rsdp_v1_tag().unwrap();
- assert_eq!("RSD PTR ", rsdp_old.signature().unwrap());
- assert_eq!(89, rsdp_old.checksum());
- assert_eq!("BOCHS ", rsdp_old.oem_id().unwrap());
- assert_eq!(0, rsdp_old.revision());
- assert_eq!(0x7FE18DC, rsdp_old.rsdt_address());
- assert!(bi.module_tags().next().is_none());
- assert_eq!("GRUB 2.02~beta3-5", bi.boot_loader_name_tag().unwrap().name());
- assert_eq!("", bi.command_line_tag().unwrap().command_line());
- // Test the Framebuffer tag
- let fbi = bi.framebuffer_tag().unwrap();
- assert_eq!(fbi.address, 753664);
- assert_eq!(fbi.pitch, 160);
- assert_eq!(fbi.width, 80);
- assert_eq!(fbi.height, 25);
- assert_eq!(fbi.bpp, 16);
- assert_eq!(fbi.buffer_type, FramebufferType::Text);
- }
- #[test]
- fn elf_sections() {
- #[repr(C, align(8))]
- struct Bytes([u8; 168]);
- let mut bytes: Bytes = Bytes([
- 168, 0, 0, 0, // total_size
- 0, 0, 0, 0, // reserved
- 9, 0, 0, 0, // elf symbols tag type
- 20, 2, 0, 0, // elf symbols tag size
- 2, 0, 0, 0, // elf symbols num
- 64, 0, 0, 0, // elf symbols entsize
- 1, 0, 0, 0, // elf symbols shndx
- 0, 0, 0, 0, // elf symbols entry 0 name
- 0, 0, 0, 0, // elf symbols entry 0 type
- 0, 0, 0, 0, // elf symbols entry 0 flags
- 0, 0, 0, 0, // elf symbols entry 0 flags
- 0, 0, 0, 0, // elf symbols entry 0 addr
- 0, 0, 0, 0, // elf symbols entry 0 addr
- 0, 0, 0, 0, // elf symbols entry 0 offset
- 0, 0, 0, 0, // elf symbols entry 0 offset
- 0, 0, 0, 0, // elf symbols entry 0 size
- 0, 0, 0, 0, // elf symbols entry 0 size
- 0, 0, 0, 0, // elf symbols entry 0 link
- 0, 0, 0, 0, // elf symbols entry 0 info
- 0, 0, 0, 0, // elf symbols entry 0 addralign
- 0, 0, 0, 0, // elf symbols entry 0 addralign
- 0, 0, 0, 0, // elf symbols entry 0 entsize
- 0, 0, 0, 0, // elf symbols entry 0 entsize
- 1, 0, 0, 0, // elf symbols entry 1 name
- 3, 0, 0, 0, // elf symbols entry 1 type
- 0, 0, 0, 0, // elf symbols entry 1 flags
- 0, 0, 0, 0, // elf symbols entry 1 flags
- 255, 255, 255, 255, // elf symbols entry 1 addr
- 255, 255, 255, 255, // elf symbols entry 1 addr
- 113, 83, 1, 0, // elf symbols entry 1 offset
- 0, 0, 0, 0, // elf symbols entry 1 offset
- 11, 0, 0, 0, // elf symbols entry 1 size
- 0, 0, 0, 0, // elf symbols entry 1 size
- 0, 0, 0, 0, // elf symbols entry 1 link
- 0, 0, 0, 0, // elf symbols entry 1 info
- 1, 0, 0, 0, // elf symbols entry 1 addralign
- 0, 0, 0, 0, // elf symbols entry 1 addralign
- 0, 0, 0, 0, // elf symbols entry 1 entsize
- 0, 0, 0, 0, // elf symbols entry 1 entsize
- 0, 0, 0, 0, // elf symbols padding
- 0, 0, 0, 0, // end tag type
- 8, 0, 0, 0, // end tag size
- ]);
- #[repr(C, align(8))]
- struct StringBytes([u8; 11]);
- let string_bytes: StringBytes = StringBytes([
- 0, 46, 115, 104,
- 115, 116, 114, 116,
- 97, 98, 0,
- ]);
- let string_addr = string_bytes.0.as_ptr() as u64;
- for i in 0..8 {
- let offset = 108;
- assert_eq!(255, bytes.0[offset + i]);
- bytes.0[offset + i] = (string_addr >> (i * 8)) as u8;
- }
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size() as usize);
- let es = bi.elf_sections_tag().unwrap();
- let mut s = es.sections();
- let s1 = s.next().unwrap();
- assert_eq!(".shstrtab", s1.name());
- assert_eq!(string_addr, s1.start_address());
- assert_eq!(string_addr + string_bytes.0.len() as u64, s1.end_address());
- assert_eq!(string_bytes.0.len() as u64, s1.size());
- assert_eq!(ElfSectionFlags::empty(), s1.flags());
- assert_eq!(ElfSectionType::StringTable, s1.section_type());
- assert!(s.next().is_none());
- }
- }
|