1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747 |
- #![no_std]
- #![cfg_attr(feature = "unstable", feature(error_in_core))]
- #![deny(missing_debug_implementations)]
- #![deny(clippy::all)]
- #![deny(rustdoc::all)]
- #![allow(rustdoc::private_doc_tests)]
- #[cfg(feature = "builder")]
- extern crate alloc;
- #[cfg_attr(test, macro_use)]
- #[cfg(test)]
- extern crate std;
- use core::fmt;
- use derive_more::Display;
- pub use ptr_meta::Pointee;
- use crate::framebuffer::UnknownFramebufferType;
- pub use boot_loader_name::BootLoaderNameTag;
- #[cfg(feature = "builder")]
- use builder::traits::StructAsBytes;
- pub use command_line::CommandLineTag;
- pub use efi::{EFIImageHandle32, EFIImageHandle64, EFISdt32, EFISdt64};
- pub use elf_sections::{
- ElfSection, ElfSectionFlags, ElfSectionIter, ElfSectionType, ElfSectionsTag,
- };
- pub use framebuffer::{FramebufferColor, FramebufferField, FramebufferTag, FramebufferType};
- pub use image_load_addr::ImageLoadPhysAddr;
- pub use memory_map::{
- BasicMemoryInfoTag, EFIBootServicesNotExited, EFIMemoryAreaType, EFIMemoryDesc,
- EFIMemoryMapTag, MemoryArea, MemoryAreaIter, MemoryAreaType, MemoryMapTag,
- };
- pub use module::{ModuleIter, ModuleTag};
- pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
- pub use smbios::SmbiosTag;
- use tag_type::TagIter;
- pub use tag_type::{EndTag, Tag, TagType, TagTypeId};
- pub use vbe_info::{
- VBECapabilities, VBEControlInfo, VBEDirectColorAttributes, VBEField, VBEInfoTag,
- VBEMemoryModel, VBEModeAttributes, VBEModeInfo, VBEWindowAttributes,
- };
- #[macro_use]
- extern crate bitflags;
- mod boot_loader_name;
- mod command_line;
- mod efi;
- mod elf_sections;
- mod framebuffer;
- mod image_load_addr;
- mod memory_map;
- mod module;
- mod rsdp;
- mod smbios;
- mod tag_type;
- mod vbe_info;
- #[cfg(feature = "builder")]
- pub mod builder;
- pub const MULTIBOOT2_BOOTLOADER_MAGIC: u32 = 0x36d76289;
- pub unsafe fn load(address: usize) -> Result<BootInformation, MbiLoadError> {
- load_with_offset(address, 0)
- }
- pub unsafe fn load_with_offset(
- address: usize,
- offset: usize,
- ) -> Result<BootInformation, MbiLoadError> {
- let address = address + offset;
- let null_ptr = address == 0;
- let eight_byte_aligned = address & 0b111 == 0;
- if null_ptr || !eight_byte_aligned {
- return Err(MbiLoadError::IllegalAddress);
- }
- let multiboot = &*(address as *const BootInformationInner);
-
-
- if multiboot.total_size & 0b111 != 0 {
- return Err(MbiLoadError::IllegalTotalSize(multiboot.total_size));
- }
- if !multiboot.has_valid_end_tag() {
- return Err(MbiLoadError::NoEndTag);
- }
- Ok(BootInformation {
- inner: multiboot,
- offset,
- })
- }
- #[derive(Debug, Display)]
- pub enum MbiLoadError {
-
-
- #[display(fmt = "The address is invalid")]
- IllegalAddress,
-
-
-
- #[display(fmt = "The size of the MBI is unexpected")]
- IllegalTotalSize(u32),
-
- #[display(fmt = "There is no end tag")]
- NoEndTag,
- }
- #[cfg(feature = "unstable")]
- impl core::error::Error for MbiLoadError {}
- pub struct BootInformation {
- inner: *const BootInformationInner,
- offset: usize,
- }
- #[derive(Clone, Copy)]
- #[repr(C)]
- struct BootInformationInner {
- total_size: u32,
- _reserved: u32,
- }
- impl BootInformationInner {
- #[cfg(feature = "builder")]
- fn new(total_size: u32) -> Self {
- Self {
- total_size,
- _reserved: 0,
- }
- }
- }
- #[cfg(feature = "builder")]
- impl StructAsBytes for BootInformationInner {
- fn byte_size(&self) -> usize {
- core::mem::size_of::<Self>()
- }
- }
- 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 basic_memory_info_tag(&self) -> Option<&BasicMemoryInfoTag> {
- self.get_tag::<BasicMemoryInfoTag, _>(TagType::BasicMeminfo)
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pub fn elf_sections(&self) -> Option<ElfSectionIter> {
- let tag = self.get_tag::<ElfSectionsTag, _>(TagType::ElfSections);
- tag.map(|t| {
- assert!((t.entry_size * t.shndx) <= t.size);
- t.sections(self.offset)
- })
- }
-
- pub fn memory_map_tag(&self) -> Option<&MemoryMapTag> {
- self.get_tag::<MemoryMapTag, _>(TagType::Mmap)
- }
-
- pub fn module_tags(&self) -> ModuleIter {
- module::module_iter(self.tags())
- }
-
- pub fn boot_loader_name_tag(&self) -> Option<&BootLoaderNameTag> {
- self.get_tag::<BootLoaderNameTag, _>(TagType::BootLoaderName)
- }
-
- pub fn command_line_tag(&self) -> Option<&CommandLineTag> {
- self.get_tag::<CommandLineTag, _>(TagType::Cmdline)
- }
-
-
- pub fn framebuffer_tag(&self) -> Option<Result<&FramebufferTag, UnknownFramebufferType>> {
- self.get_tag::<FramebufferTag, _>(TagType::Framebuffer)
- .map(|tag| match tag.buffer_type() {
- Ok(_) => Ok(tag),
- Err(e) => Err(e),
- })
- }
-
- pub fn efi_sdt_32_tag(&self) -> Option<&EFISdt32> {
- self.get_tag::<EFISdt32, _>(TagType::Efi32)
- }
-
- pub fn efi_sdt_64_tag(&self) -> Option<&EFISdt64> {
- self.get_tag::<EFISdt64, _>(TagType::Efi64)
- }
-
- pub fn rsdp_v1_tag(&self) -> Option<&RsdpV1Tag> {
- self.get_tag::<RsdpV1Tag, _>(TagType::AcpiV1)
- }
-
- pub fn rsdp_v2_tag(&self) -> Option<&RsdpV2Tag> {
- self.get_tag::<RsdpV2Tag, _>(TagType::AcpiV2)
- }
-
-
-
-
- pub fn efi_memory_map_tag(&self) -> Option<&EFIMemoryMapTag> {
-
-
- match self.get_tag::<Tag, _>(TagType::EfiBs) {
- Some(_tag) => None,
- None => self.get_tag::<EFIMemoryMapTag, _>(TagType::EfiMmap),
- }
- }
-
- pub fn efi_32_ih(&self) -> Option<&EFIImageHandle32> {
- self.get_tag::<EFIImageHandle32, _>(TagType::Efi32Ih)
- }
-
- pub fn efi_64_ih(&self) -> Option<&EFIImageHandle64> {
- self.get_tag::<EFIImageHandle64, _>(TagType::Efi64Ih)
- }
-
- pub fn load_base_addr(&self) -> Option<&ImageLoadPhysAddr> {
- self.get_tag::<ImageLoadPhysAddr, _>(TagType::LoadBaseAddr)
- }
-
- pub fn vbe_info_tag(&self) -> Option<&VBEInfoTag> {
- self.get_tag::<VBEInfoTag, _>(TagType::Vbe)
- }
-
- pub fn smbios_tag(&self) -> Option<&SmbiosTag> {
- self.get_tag::<SmbiosTag, _>(TagType::Smbios)
- }
- fn get(&self) -> &BootInformationInner {
- unsafe { &*self.inner }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- pub fn get_tag<TagT: TagTrait + ?Sized, TagType: Into<TagTypeId>>(
- &self,
- typ: TagType,
- ) -> Option<&TagT> {
- let typ = typ.into();
- self.tags()
- .find(|tag| tag.typ == typ)
- .map(|tag| tag.cast_tag::<TagT>())
- }
- fn tags(&self) -> TagIter {
- TagIter::new(unsafe { self.inner.offset(1) } as *const _)
- }
- }
- impl BootInformationInner {
- fn has_valid_end_tag(&self) -> bool {
- let end_tag_prototype = EndTag::default();
- let self_ptr = self as *const _;
- let end_tag_addr = self_ptr as usize + (self.total_size - end_tag_prototype.size) as usize;
- let end_tag = unsafe { &*(end_tag_addr as *const Tag) };
- end_tag.typ == end_tag_prototype.typ && end_tag.size == end_tag_prototype.size
- }
- }
- unsafe impl Send for BootInformation {}
- impl fmt::Debug for BootInformation {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-
-
-
- const ELF_SECTIONS_LIMIT: usize = 17;
- let mut debug = f.debug_struct("Multiboot2 Boot Information");
- debug
- .field("start_address", &(self.start_address() as *const u64))
- .field("end_address", &(self.end_address() as *const u64))
- .field("total_size", &(self.total_size() as *const u64))
- .field(
- "boot_loader_name_tag",
- &self
- .boot_loader_name_tag()
- .and_then(|x| x.name().ok())
- .unwrap_or("<unknown>"),
- )
- .field(
- "command_line",
- &self
- .command_line_tag()
- .and_then(|x| x.command_line().ok())
- .unwrap_or(""),
- )
- .field("memory_areas", &self.memory_map_tag())
-
-
- .field("module_tags", &self.module_tags());
-
- let elf_sections_tag_entries_count = self.elf_sections().map(|x| x.count()).unwrap_or(0);
- if elf_sections_tag_entries_count > ELF_SECTIONS_LIMIT {
- debug.field("elf_sections_tags (count)", &elf_sections_tag_entries_count);
- } else {
- debug.field(
- "elf_sections_tags",
- &self.elf_sections().unwrap_or_default(),
- );
- }
- debug
- .field("efi_32_ih", &self.efi_32_ih())
- .field("efi_64_ih", &self.efi_64_ih())
- .field("efi_sdt_32_tag", &self.efi_sdt_32_tag())
- .field("efi_sdt_64_tag", &self.efi_sdt_64_tag())
- .field("efi_memory_map_tag", &self.efi_memory_map_tag())
- .finish()
- }
- }
- 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 { *self.ptr.add(self.off - 1) }
- }
- 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;
- }
- pub(crate) fn current_address(&self) -> usize {
- unsafe { self.ptr.add(self.off) as usize }
- }
- }
- pub trait TagTrait: Pointee {
-
- fn dst_size(base_tag: &Tag) -> Self::Metadata;
-
-
-
-
-
-
-
- unsafe fn from_base_tag<'a>(tag: &Tag) -> &'a Self {
- let ptr = tag as *const _ as *const ();
- let ptr = ptr_meta::from_raw_parts(ptr, Self::dst_size(tag));
- &*ptr
- }
- }
- impl<T: Pointee<Metadata = ()>> TagTrait for T {
- #[allow(clippy::unused_unit)]
- fn dst_size(_: &Tag) -> Self::Metadata {
- ()
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use core::str::Utf8Error;
- #[test]
- fn no_tags() {
- #[repr(C, align(8))]
- struct Bytes([u8; 16]);
- let bytes: Bytes = Bytes([
- 16, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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().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,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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().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,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 9, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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().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,
- 0, 0, 0, 0,
- 2, 0, 0, 0,
- 13, 0, 0, 0,
- 110, 97, 109, 101,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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().is_none());
- assert!(bi.memory_map_tag().is_none());
- assert!(bi.module_tags().next().is_none());
- assert_eq!(
- "name",
- bi.boot_loader_name_tag()
- .expect("tag must be present")
- .name()
- .expect("must be valid utf8")
- );
- assert!(bi.command_line_tag().is_none());
- }
- #[test]
- fn framebuffer_tag_rgb() {
-
-
-
- #[repr(C, align(8))]
- struct Bytes([u8; 56]);
- let bytes: Bytes = Bytes([
- 56, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- 40, 0, 0, 0,
- 0, 0, 0, 253,
- 0, 0, 0, 0,
- 0, 20, 0, 0,
- 0, 5, 0, 0,
- 208, 2, 0, 0,
- 32, 1, 0, 0,
- 16, 8, 8, 8,
- 0, 8, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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::{FramebufferField, FramebufferType};
- assert!(bi.framebuffer_tag().is_some());
- let fbi = bi
- .framebuffer_tag()
- .expect("Framebuffer info should be available")
- .expect("Framebuffer info type should be valid");
- 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);
- assert_eq!(
- fbi.buffer_type().unwrap(),
- 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() {
-
-
-
- #[repr(C, align(8))]
- struct Bytes([u8; 64]);
- let bytes: Bytes = Bytes([
- 64, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- 48, 0, 0, 0,
- 0, 0, 0, 253,
- 0, 0, 0, 0,
- 0, 20, 0, 0,
- 0, 5, 0, 0,
- 208, 2, 0, 0,
- 32, 0, 0, 0,
- 4, 0, 0, 0,
- 255, 0, 0, 0,
- 255, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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::{FramebufferColor, FramebufferType};
- assert!(bi.framebuffer_tag().is_some());
- let fbi = bi
- .framebuffer_tag()
- .expect("Framebuffer info should be available")
- .expect("Framebuffer info type should be valid");
- 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().unwrap() {
- FramebufferType::Indexed { palette } => assert_eq!(
- palette,
- [
- FramebufferColor {
- red: 255,
- green: 0,
- blue: 0
- },
- FramebufferColor {
- red: 0,
- green: 255,
- blue: 0
- },
- FramebufferColor {
- red: 0,
- green: 0,
- blue: 255
- },
- FramebufferColor {
- red: 0,
- green: 0,
- blue: 0
- }
- ]
- ),
- _ => panic!("Expected indexed framebuffer type."),
- }
- }
- #[test]
- fn vbe_info_tag() {
-
- #[repr(C, align(8))]
- struct Bytes([u8; 800]);
- let bytes = Bytes([
- 32, 3, 0, 0,
- 0, 0, 0, 0,
- 7, 0, 0, 0,
- 16, 3, 0, 0,
- 122, 65, 255, 255,
- 0, 96, 79, 0,
- 86, 69, 83, 65,
- 0, 3, 220, 87,
- 0, 192, 1, 0,
- 0, 0, 34, 128,
- 0, 96, 0, 1,
- 0, 0, 240, 87,
- 0, 192, 3,
- 88,
- 0, 192, 23,
- 88,
- 0, 192, 0, 1,
- 1, 1, 2, 1,
- 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 13, 1, 14, 1, 15, 1, 16, 1, 17, 1, 18, 1, 19, 1, 20, 1,
- 21, 1, 22, 1, 23, 1, 24, 1, 25, 1, 26, 1, 27, 1, 28, 1, 29, 1, 30, 1, 31, 1, 64, 1, 65,
- 1, 66, 1, 67, 1, 68, 1, 69, 1, 70, 1, 71, 1, 72, 1, 73, 1, 74, 1, 75, 1, 76, 1, 117, 1,
- 118, 1, 119, 1, 120, 1, 121, 1, 122, 1, 123, 1, 124, 1, 125, 1, 126, 1, 127, 1, 128, 1,
- 129, 1, 130, 1, 131, 1, 132, 1, 133, 1, 134, 1, 135, 1, 136, 1, 137, 1, 138, 1, 139, 1,
- 140, 1, 141, 1, 142, 1, 143, 1, 144, 1, 145, 1, 146, 1, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0,
- 5, 0, 6, 0, 7, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0, 106, 0, 255, 255, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 187, 0, 7, 0,
- 64, 0, 64, 0,
- 0, 160, 0, 0,
- 186, 84, 0, 192,
- 0, 20, 0, 5,
- 32, 3, 8, 16,
- 1, 32, 1, 6,
- 0, 3, 1, 8,
- 16, 8, 8,
- 8,
- 0, 8, 24,
- 2,
- 0, 0, 0, 253,
- 0, 0, 0, 0,
- 0, 0, 0, 20,
- 0, 0, 8, 16, 8, 8, 8, 0, 8, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- 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.vbe_info_tag().is_some());
- let vbe = bi.vbe_info_tag().unwrap();
- use vbe_info::*;
- assert_eq!({ vbe.mode }, 16762);
- assert_eq!({ vbe.interface_segment }, 65535);
- assert_eq!({ vbe.interface_offset }, 24576);
- assert_eq!({ vbe.interface_length }, 79);
- assert_eq!({ vbe.control_info.signature }, [86, 69, 83, 65]);
- assert_eq!({ vbe.control_info.version }, 768);
- assert_eq!({ vbe.control_info.oem_string_ptr }, 3221247964);
- assert_eq!(
- { vbe.control_info.capabilities },
- VBECapabilities::SWITCHABLE_DAC
- );
- assert_eq!({ vbe.control_info.mode_list_ptr }, 1610645538);
- assert_eq!({ vbe.control_info.total_memory }, 256);
- assert_eq!({ vbe.control_info.oem_software_revision }, 0);
- assert_eq!({ vbe.control_info.oem_vendor_name_ptr }, 3221247984);
- assert_eq!({ vbe.control_info.oem_product_name_ptr }, 3221248003);
- assert_eq!({ vbe.control_info.oem_product_revision_ptr }, 3221248023);
- assert!({ vbe.mode_info.mode_attributes }.contains(
- VBEModeAttributes::SUPPORTED
- | VBEModeAttributes::COLOR
- | VBEModeAttributes::GRAPHICS
- | VBEModeAttributes::NOT_VGA_COMPATIBLE
- | VBEModeAttributes::LINEAR_FRAMEBUFFER
- ));
- assert!(vbe.mode_info.window_a_attributes.contains(
- VBEWindowAttributes::RELOCATABLE
- | VBEWindowAttributes::READABLE
- | VBEWindowAttributes::WRITEABLE
- ));
- assert_eq!({ vbe.mode_info.window_granularity }, 64);
- assert_eq!({ vbe.mode_info.window_size }, 64);
- assert_eq!({ vbe.mode_info.window_a_segment }, 40960);
- assert_eq!({ vbe.mode_info.window_function_ptr }, 3221247162);
- assert_eq!({ vbe.mode_info.pitch }, 5120);
- assert_eq!({ vbe.mode_info.resolution }, (1280, 800));
- assert_eq!(vbe.mode_info.character_size, (8, 16));
- assert_eq!(vbe.mode_info.number_of_planes, 1);
- assert_eq!(vbe.mode_info.bpp, 32);
- assert_eq!(vbe.mode_info.number_of_banks, 1);
- assert_eq!(vbe.mode_info.memory_model, VBEMemoryModel::DirectColor);
- assert_eq!(vbe.mode_info.bank_size, 0);
- assert_eq!(vbe.mode_info.number_of_image_pages, 3);
- assert_eq!(
- vbe.mode_info.red_field,
- VBEField {
- position: 16,
- size: 8
- }
- );
- assert_eq!(
- vbe.mode_info.green_field,
- VBEField {
- position: 8,
- size: 8
- }
- );
- assert_eq!(
- vbe.mode_info.blue_field,
- VBEField {
- position: 0,
- size: 8
- }
- );
- assert_eq!(
- vbe.mode_info.reserved_field,
- VBEField {
- position: 24,
- size: 8
- }
- );
- assert_eq!(
- vbe.mode_info.direct_color_attributes,
- VBEDirectColorAttributes::RESERVED_USABLE
- );
- assert_eq!({ vbe.mode_info.framebuffer_base_ptr }, 4244635648);
- assert_eq!({ vbe.mode_info.offscreen_memory_offset }, 0);
- assert_eq!({ vbe.mode_info.offscreen_memory_size }, 0);
- }
- #[test]
-
- fn vbe_info_tag_size() {
- unsafe {
-
- core::mem::transmute::<[u8; 784], VBEInfoTag>([0u8; 784]);
- }
- }
- #[test]
- fn grub2() {
- #[repr(C, align(8))]
- struct Bytes([u8; 960]);
- let mut bytes: Bytes = Bytes([
- 192, 3, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 9, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 2, 0, 0, 0,
- 26, 0, 0, 0,
- 71, 82, 85, 66,
- 32, 50, 46, 48,
- 50, 126, 98, 101,
- 116, 97, 51, 45,
- 53, 0, 0, 0,
- 0, 0, 0, 0,
- 10, 0, 0, 0,
- 28, 0, 0, 0,
- 2, 1, 0, 240,
- 207, 212, 0, 0,
- 0, 240, 0, 240,
- 3, 0, 240, 255,
- 240, 255, 240, 255,
- 0, 0, 0, 0,
- 6, 0, 0, 0,
- 160, 0, 0, 0,
- 24, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 252, 9, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 252, 9, 0,
- 0, 0, 0, 0,
- 0, 4, 0, 0,
- 0, 0, 0, 0,
- 2, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 15, 0,
- 0, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 0,
- 2, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 16, 0,
- 0, 0, 0, 0,
- 0, 0, 238, 7,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 254, 7,
- 0, 0, 0, 0,
- 0, 0, 2, 0,
- 0, 0, 0, 0,
- 2, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 252, 255,
- 0, 0, 0, 0,
- 0, 0, 4, 0,
- 0, 0, 0, 0,
- 2, 0, 0, 0,
- 0, 0, 0, 0,
- 9, 0, 0, 0,
- 84, 2, 0, 0,
- 9, 0, 0, 0,
- 64, 0, 0, 0,
- 8, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 27, 0, 0, 0,
- 1, 0, 0, 0,
- 2, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 16, 0,
- 0, 128, 255, 255,
- 0, 16, 0, 0,
- 0, 0, 0, 0,
- 0, 48, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 16, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 35, 0, 0, 0,
- 1, 0, 0, 0,
- 6, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 48, 16, 0,
- 0, 128, 255, 255,
- 0, 64, 0, 0,
- 0, 0, 0, 0,
- 0, 144, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 16, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 41, 0, 0, 0,
- 1, 0, 0, 0,
- 3, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 192, 16, 0,
- 0, 128, 255, 255,
- 0, 208, 0, 0,
- 0, 0, 0, 0,
- 0, 32, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 47, 0, 0, 0,
- 8, 0, 0, 0,
- 3, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 224, 16, 0,
- 0, 128, 255, 255,
- 0, 240, 0, 0,
- 0, 0, 0, 0,
- 0, 80, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 16, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 52, 0, 0, 0,
- 1, 0, 0, 0,
- 3, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 48, 17, 0,
- 0, 128, 255, 255,
- 0, 240, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 2, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 48, 17, 0,
- 0, 0, 0, 0,
- 0, 240, 0, 0,
- 0, 0, 0, 0,
- 224, 43, 0, 0,
- 0, 0, 0, 0,
- 7, 0, 0, 0,
- 102, 1, 0, 0,
- 8, 0, 0, 0,
- 0, 0, 0, 0,
- 24, 0, 0, 0,
- 0, 0, 0, 0,
- 9, 0, 0, 0,
- 3, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 224, 91, 17, 0,
- 0, 0, 0, 0,
- 224, 27, 1, 0,
- 0, 0, 0, 0,
- 145, 55, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 17, 0, 0, 0,
- 3, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 113, 147, 17, 0,
- 0, 0, 0, 0,
- 113, 83, 1, 0,
- 0, 0, 0, 0,
- 65, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 4, 0, 0, 0,
- 16, 0, 0, 0,
- 127, 2, 0, 0,
- 128, 251, 1, 0,
- 5, 0, 0, 0,
- 20, 0, 0, 0,
- 224, 0, 0, 0,
- 255, 255, 255, 255,
- 255, 255, 255, 255,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- 32, 0, 0, 0,
- 0, 128, 11, 0,
- 0, 0, 0, 0,
- 160, 0, 0, 0,
- 80, 0, 0, 0,
- 25, 0, 0, 0,
- 16, 2, 0, 0,
- 14, 0, 0, 0,
- 28, 0, 0, 0,
- 82, 83, 68, 32,
- 80, 84, 82, 32,
- 89, 66, 79, 67,
- 72, 83, 32, 0,
- 220, 24, 254, 7,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- #[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;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- test_grub2_boot_info(bi, addr, string_addr, &bytes.0, &string_bytes.0);
- let bi = unsafe { load_with_offset(addr, 0) };
- let bi = bi.unwrap();
- test_grub2_boot_info(bi, 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;
- }
- let bi = unsafe { load_with_offset(addr - offset, offset) };
- let bi = bi.unwrap();
- test_grub2_boot_info(
- bi,
- 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 mut es = bi.elf_sections().unwrap();
- let s1 = es.next().expect("Should have one more section");
- assert_eq!(".rodata", s1.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".text", s2.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".data", s3.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".bss", s4.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".data.rel.ro", s5.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".symtab", s6.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".strtab", s7.name().expect("Should be valid utf-8"));
- 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 = es.next().expect("Should have one more section");
- assert_eq!(".shstrtab", s8.name().expect("Should be valid utf-8"));
- 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!(es.next().is_none());
- let mut mm = bi.memory_map_tag().unwrap().available_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());
- assert_eq!(MemoryAreaType::Available, mm1.typ());
- 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_eq!(MemoryAreaType::Available, mm2.typ());
- assert!(mm.next().is_none());
-
- let rsdp_old = bi.rsdp_v1_tag().unwrap();
- assert_eq!("RSD PTR ", rsdp_old.signature().unwrap());
- assert!(rsdp_old.checksum_is_valid());
- 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()
- .expect("tag must be present")
- .name()
- .expect("must be valid utf-8")
- );
- assert_eq!(
- "",
- bi.command_line_tag()
- .expect("tag must present")
- .command_line()
- .expect("must be valid utf-8")
- );
-
- let fbi = bi
- .framebuffer_tag()
- .expect("Framebuffer info should be available")
- .expect("Framebuffer info type should be valid");
- 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(), Ok(FramebufferType::Text));
- }
- #[test]
- fn elf_sections() {
- #[repr(C, align(8))]
- struct Bytes([u8; 168]);
- let mut bytes: Bytes = Bytes([
- 168, 0, 0, 0,
- 0, 0, 0, 0,
- 9, 0, 0, 0,
- 20, 2, 0, 0,
- 2, 0, 0, 0,
- 64, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 3, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 255, 255, 255, 255,
- 255, 255, 255, 255,
- 113, 83, 1, 0,
- 0, 0, 0, 0,
- 11, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- #[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) };
- let bi = bi.unwrap();
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- let mut es = bi.elf_sections().unwrap();
- let s1 = es.next().expect("Should have one more section");
- assert_eq!(".shstrtab", s1.name().expect("Should be valid utf-8"));
- 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!(es.next().is_none());
- }
- #[test]
- fn efi_memory_map() {
- use memory_map::EFIMemoryAreaType;
- #[repr(C, align(8))]
- struct Bytes([u8; 72]);
-
- let bytes: Bytes = Bytes([
- 72, 0, 0, 0,
- 0, 0, 0, 0,
- 17, 0, 0, 0,
- 56, 0, 0, 0,
- 48, 0, 0, 0,
- 1, 0, 0, 0,
- 7, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 16, 0,
- 0, 0, 0, 0,
- 0, 0, 16, 0,
- 0, 0, 0, 0,
- 4, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- let efi_memory_map = bi.efi_memory_map_tag().unwrap();
- let mut efi_mmap_iter = efi_memory_map.memory_areas();
- let desc = efi_mmap_iter.next().unwrap();
- assert_eq!(desc.physical_address(), 0x100000);
- assert_eq!(desc.size(), 16384);
- assert_eq!(desc.typ(), EFIMemoryAreaType::EfiConventionalMemory);
-
-
- struct Bytes2([u8; 80]);
- let bytes2: Bytes2 = Bytes2([
- 80, 0, 0, 0,
- 0, 0, 0, 0,
- 17, 0, 0, 0,
- 56, 0, 0, 0,
- 48, 0, 0, 0,
- 1, 0, 0, 0,
- 7, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 16, 0,
- 0, 0, 0, 0,
- 0, 0, 16, 0,
- 0, 0, 0, 0,
- 4, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 18, 0, 0, 0,
- 8, 0, 0, 0,
- 0, 0, 0, 0,
- 8, 0, 0, 0,
- ]);
- let bi = unsafe { load(bytes2.0.as_ptr() as usize) };
- let bi = bi.unwrap();
- let efi_mmap = bi.efi_memory_map_tag();
- assert!(efi_mmap.is_none());
- }
- #[test]
- #[cfg(feature = "unstable")]
-
- fn mbi_load_error_implements_error() {
- fn consumer<E: core::error::Error>(_e: E) {}
- consumer(MbiLoadError::IllegalAddress)
- }
-
- #[test]
- fn get_custom_tag_from_mbi() {
- const CUSTOM_TAG_ID: u32 = 0x1337;
- #[repr(C, align(8))]
- struct CustomTag {
- tag: TagTypeId,
- size: u32,
- foo: u32,
- }
- #[repr(C, align(8))]
- struct AlignedBytes([u8; 32]);
-
- let bytes: AlignedBytes = AlignedBytes([
- 32,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- CUSTOM_TAG_ID.to_ne_bytes()[0],
- CUSTOM_TAG_ID.to_ne_bytes()[1],
- CUSTOM_TAG_ID.to_ne_bytes()[2],
- CUSTOM_TAG_ID.to_ne_bytes()[3],
- 12,
- 0,
- 0,
- 0,
- 42,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 8,
- 0,
- 0,
- 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- let tag = bi.get_tag::<CustomTag, _>(CUSTOM_TAG_ID).unwrap();
- assert_eq!(tag.foo, 42);
- }
-
- #[test]
- fn get_custom_dst_tag_from_mbi() {
- const CUSTOM_TAG_ID: u32 = 0x1337;
- #[repr(C, align(8))]
- #[derive(crate::Pointee)]
- struct CustomTag {
- tag: TagTypeId,
- size: u32,
- name: [u8],
- }
- impl CustomTag {
- fn name(&self) -> Result<&str, Utf8Error> {
- Tag::get_dst_str_slice(&self.name)
- }
- }
- impl TagTrait for CustomTag {
- fn dst_size(base_tag: &Tag) -> usize {
-
- let tag_base_size = 8;
- assert!(base_tag.size >= 8);
- base_tag.size as usize - tag_base_size
- }
- }
- #[repr(C, align(8))]
- struct AlignedBytes([u8; 32]);
-
- let bytes: AlignedBytes = AlignedBytes([
- 32,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- CUSTOM_TAG_ID.to_ne_bytes()[0],
- CUSTOM_TAG_ID.to_ne_bytes()[1],
- CUSTOM_TAG_ID.to_ne_bytes()[2],
- CUSTOM_TAG_ID.to_ne_bytes()[3],
- 14,
- 0,
- 0,
- 0,
- b'h',
- b'e',
- b'l',
- b'l',
- b'o',
- b'\0',
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 8,
- 0,
- 0,
- 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- assert_eq!(addr, bi.start_address());
- assert_eq!(addr + bytes.0.len(), bi.end_address());
- assert_eq!(bytes.0.len(), bi.total_size());
- let tag = bi.get_tag::<CustomTag, _>(CUSTOM_TAG_ID).unwrap();
- assert_eq!(tag.name(), Ok("hello"));
- }
-
- #[test]
- fn get_tag_into_variants() {
- #[repr(C, align(8))]
- struct Bytes([u8; 32]);
- let bytes: Bytes = Bytes([
- 32,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- TagType::Cmdline.val().to_ne_bytes()[0],
- TagType::Cmdline.val().to_ne_bytes()[1],
- TagType::Cmdline.val().to_ne_bytes()[2],
- TagType::Cmdline.val().to_ne_bytes()[3],
- 13,
- 0,
- 0,
- 0,
- 110,
- 97,
- 109,
- 101,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 8,
- 0,
- 0,
- 0,
- ]);
- let addr = bytes.0.as_ptr() as usize;
- let bi = unsafe { load(addr) };
- let bi = bi.unwrap();
- let _tag = bi.get_tag::<CommandLineTag, _>(TagType::Cmdline).unwrap();
- let _tag = bi.get_tag::<CommandLineTag, _>(1).unwrap();
- let _tag = bi.get_tag::<CommandLineTag, _>(TagTypeId::new(1)).unwrap();
- }
- }
|