diff --git a/multiboot2-header/Changelog.md b/multiboot2-header/Changelog.md index 55986349..df9f05e8 100644 --- a/multiboot2-header/Changelog.md +++ b/multiboot2-header/Changelog.md @@ -2,8 +2,9 @@ ## Unreleased +- **Breaking** All functions that returns something useful are now `#[must_use]` - updated dependencies -- MSRV is 1.75 +- documentation enhancements ## 0.4.0 (2024-05-01) diff --git a/multiboot2-header/src/address.rs b/multiboot2-header/src/address.rs index e15e5035..7a450e9e 100644 --- a/multiboot2-header/src/address.rs +++ b/multiboot2-header/src/address.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::mem::size_of; /// This information does not need to be provided if the kernel image is in ELF @@ -8,9 +8,7 @@ use core::mem::size_of; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct AddressHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, /// Contains the address corresponding to the beginning of the Multiboot2 header — the physical memory location at which the magic value is supposed to be loaded. This field serves to synchronize the mapping between OS image offsets and physical memory addresses. header_addr: u32, /// Contains the physical address of the beginning of the text segment. The offset in the OS image file at which to start loading is defined by the offset at which the header was found, minus (header_addr - load_addr). load_addr must be less than or equal to header_addr. @@ -24,6 +22,8 @@ pub struct AddressHeaderTag { } impl AddressHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new( flags: HeaderTagFlag, header_addr: u32, @@ -31,10 +31,9 @@ impl AddressHeaderTag { load_end_addr: u32, bss_end_addr: u32, ) -> Self { - AddressHeaderTag { - typ: HeaderTagType::Address, - flags, - size: size_of::() as u32, + let header = HeaderTagHeader::new(HeaderTagType::Address, flags, size_of::() as u32); + Self { + header, header_addr, load_addr, load_end_addr, @@ -42,24 +41,44 @@ impl AddressHeaderTag { } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Returns the header address. + #[must_use] pub const fn header_addr(&self) -> u32 { self.header_addr } + + /// Returns the load begin address. + #[must_use] pub const fn load_addr(&self) -> u32 { self.load_addr } + + /// Returns the load end address. + #[must_use] pub const fn load_end_addr(&self) -> u32 { self.load_end_addr } + + /// Returns the bss end address. + #[must_use] pub const fn bss_end_addr(&self) -> u32 { self.bss_end_addr } diff --git a/multiboot2-header/src/builder/header.rs b/multiboot2-header/src/builder/header.rs index 0ab65d28..ff6ba7bb 100644 --- a/multiboot2-header/src/builder/header.rs +++ b/multiboot2-header/src/builder/header.rs @@ -72,6 +72,8 @@ pub struct HeaderBuilder { } impl HeaderBuilder { + /// Creates a new builder. + #[must_use] pub const fn new(arch: HeaderTagISA) -> Self { Self { arch, @@ -98,6 +100,7 @@ impl HeaderBuilder { /// Returns the expected length of the Multiboot2 header, when the /// [`Self::build`]-method gets called. + #[must_use] pub fn expected_len(&self) -> usize { let base_len = size_of::(); // size_or_up_aligned not required, because basic header length is 16 and the @@ -159,7 +162,8 @@ impl HeaderBuilder { } /// Constructs the bytes for a valid Multiboot2 header with the given properties. - pub fn build(mut self) -> HeaderBytes { + #[must_use] + pub fn build(self) -> HeaderBytes { const ALIGN: usize = 8; // PHASE 1/2: Prepare Vector @@ -205,7 +209,7 @@ impl HeaderBuilder { } /// Helper method that adds all the tags to the given vector. - fn build_add_tags(&mut self, bytes: &mut Vec) { + fn build_add_tags(&self, bytes: &mut Vec) { Self::build_add_bytes( bytes, // important that we write the correct expected length into the header! @@ -247,7 +251,10 @@ impl HeaderBuilder { } // clippy thinks this can be a const fn but the compiler denies it - #[allow(clippy::missing_const_for_fn)] + // #[allow(clippy::missing_const_for_fn)] + /// Adds information requests from the + /// [`InformationRequestHeaderTagBuilder`] to the builder. + #[must_use] pub fn information_request_tag( mut self, information_request_tag: InformationRequestHeaderTagBuilder, @@ -255,38 +262,65 @@ impl HeaderBuilder { self.information_request_tag = Some(information_request_tag); self } + + /// Adds a [`AddressHeaderTag`] to the builder. + #[must_use] pub const fn address_tag(mut self, address_tag: AddressHeaderTag) -> Self { self.address_tag = Some(address_tag); self } + + /// Adds a [`EntryAddressHeaderTag`] to the builder. + #[must_use] pub const fn entry_tag(mut self, entry_tag: EntryAddressHeaderTag) -> Self { self.entry_tag = Some(entry_tag); self } + + /// Adds a [`ConsoleHeaderTag`] to the builder. + #[must_use] pub const fn console_tag(mut self, console_tag: ConsoleHeaderTag) -> Self { self.console_tag = Some(console_tag); self } + + /// Adds a [`FramebufferHeaderTag`] to the builder. + #[must_use] pub const fn framebuffer_tag(mut self, framebuffer_tag: FramebufferHeaderTag) -> Self { self.framebuffer_tag = Some(framebuffer_tag); self } + + /// Adds a [`ModuleAlignHeaderTag`] to the builder. + #[must_use] pub const fn module_align_tag(mut self, module_align_tag: ModuleAlignHeaderTag) -> Self { self.module_align_tag = Some(module_align_tag); self } + + /// Adds a [`EfiBootServiceHeaderTag`] to the builder. + #[must_use] pub const fn efi_bs_tag(mut self, efi_bs_tag: EfiBootServiceHeaderTag) -> Self { self.efi_bs_tag = Some(efi_bs_tag); self } + + /// Adds a [`EntryEfi32HeaderTag`] to the builder. + #[must_use] pub const fn efi_32_tag(mut self, efi_32_tag: EntryEfi32HeaderTag) -> Self { self.efi_32_tag = Some(efi_32_tag); self } + + /// Adds a [`EntryEfi64HeaderTag`] to the builder. + #[must_use] pub const fn efi_64_tag(mut self, efi_64_tag: EntryEfi64HeaderTag) -> Self { self.efi_64_tag = Some(efi_64_tag); self } + + /// Adds a [`RelocatableHeaderTag`] to the builder. + #[must_use] pub const fn relocatable_tag(mut self, relocatable_tag: RelocatableHeaderTag) -> Self { self.relocatable_tag = Some(relocatable_tag); self diff --git a/multiboot2-header/src/builder/information_request.rs b/multiboot2-header/src/builder/information_request.rs index 543e7cc9..f5448541 100644 --- a/multiboot2-header/src/builder/information_request.rs +++ b/multiboot2-header/src/builder/information_request.rs @@ -22,6 +22,7 @@ pub struct InformationRequestHeaderTagBuilder { #[cfg(feature = "builder")] impl InformationRequestHeaderTagBuilder { /// New builder. + #[must_use] pub const fn new(flag: HeaderTagFlag) -> Self { Self { irs: BTreeSet::new(), @@ -31,6 +32,7 @@ impl InformationRequestHeaderTagBuilder { /// Returns the expected length of the information request tag, /// when the `build`-method gets called. + #[must_use] pub fn expected_len(&self) -> usize { let basic_header_size = size_of::>(); let req_tags_size = self.irs.len() * size_of::(); @@ -38,12 +40,14 @@ impl InformationRequestHeaderTagBuilder { } /// Adds an [`MbiTagType`] to the information request. + #[must_use] pub fn add_ir(mut self, tag: MbiTagType) -> Self { self.irs.insert(tag); self } /// Adds multiple [`MbiTagType`] to the information request. + #[must_use] pub fn add_irs(mut self, tags: &[MbiTagType]) -> Self { self.irs.extend(tags); self diff --git a/multiboot2-header/src/builder/traits.rs b/multiboot2-header/src/builder/traits.rs index f936c4e8..cea09fdf 100644 --- a/multiboot2-header/src/builder/traits.rs +++ b/multiboot2-header/src/builder/traits.rs @@ -11,7 +11,7 @@ use core::mem::size_of; /// Trait for all tags that helps to create a byte array from the tag. /// Useful in builders to construct a byte vector that /// represents the Multiboot2 header with all its tags. -pub(crate) trait StructAsBytes: Sized { +pub trait StructAsBytes: Sized { /// Returns the size in bytes of the struct, as known during compile /// time. This doesn't use read the "size" field of tags. fn byte_size(&self) -> usize { diff --git a/multiboot2-header/src/console.rs b/multiboot2-header/src/console.rs index 6307201d..392a6c07 100644 --- a/multiboot2-header/src/console.rs +++ b/multiboot2-header/src/console.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::mem::size_of; /// Possible flags for [`ConsoleHeaderTag`]. @@ -16,31 +16,42 @@ pub enum ConsoleHeaderTagFlags { #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct ConsoleHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, console_flags: ConsoleHeaderTagFlags, } impl ConsoleHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag, console_flags: ConsoleHeaderTagFlags) -> Self { - ConsoleHeaderTag { - typ: HeaderTagType::ConsoleFlags, - flags, - size: size_of::() as u32, + let header = + HeaderTagHeader::new(HeaderTagType::ConsoleFlags, flags, size_of::() as u32); + Self { + header, console_flags, } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Returns the [`ConsoleHeaderTagFlags`]. + #[must_use] pub const fn console_flags(&self) -> ConsoleHeaderTagFlags { self.console_flags } diff --git a/multiboot2-header/src/end.rs b/multiboot2-header/src/end.rs index 15f8c76f..1e806460 100644 --- a/multiboot2-header/src/end.rs +++ b/multiboot2-header/src/end.rs @@ -1,15 +1,11 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::mem::size_of; /// Terminates a list of optional tags in a Multiboot2 header. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct EndHeaderTag { - // u16 value - typ: HeaderTagType, - // u16 value - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, } impl Default for EndHeaderTag { @@ -19,22 +15,33 @@ impl Default for EndHeaderTag { } impl EndHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new() -> Self { - EndHeaderTag { - typ: HeaderTagType::End, - flags: HeaderTagFlag::Required, - size: size_of::() as u32, - } + let header = HeaderTagHeader::new( + HeaderTagType::EntryAddress, + HeaderTagFlag::Required, + size_of::() as u32, + ); + Self { header } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } } diff --git a/multiboot2-header/src/entry_address.rs b/multiboot2-header/src/entry_address.rs index 513e7b35..cef429e3 100644 --- a/multiboot2-header/src/entry_address.rs +++ b/multiboot2-header/src/entry_address.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::fmt; use core::fmt::{Debug, Formatter}; use core::mem::size_of; @@ -8,31 +8,39 @@ use core::mem::size_of; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct EntryAddressHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, entry_addr: u32, } impl EntryAddressHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag, entry_addr: u32) -> Self { - EntryAddressHeaderTag { - typ: HeaderTagType::EntryAddress, - flags, - size: size_of::() as u32, - entry_addr, - } + let header = + HeaderTagHeader::new(HeaderTagType::EntryAddress, flags, size_of::() as u32); + Self { header, entry_addr } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Returns the entry address. + #[must_use] pub const fn entry_addr(&self) -> u32 { self.entry_addr } @@ -41,9 +49,9 @@ impl EntryAddressHeaderTag { impl Debug for EntryAddressHeaderTag { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("EntryAddressHeaderTag") - .field("type", &{ self.typ }) - .field("flags", &{ self.flags }) - .field("size", &{ self.size }) + .field("type", &self.typ()) + .field("flags", &self.flags()) + .field("size", &self.size()) .field("entry_addr", &(self.entry_addr as *const u32)) .finish() } diff --git a/multiboot2-header/src/entry_efi_32.rs b/multiboot2-header/src/entry_efi_32.rs index 5f6818c1..c6ca3a71 100644 --- a/multiboot2-header/src/entry_efi_32.rs +++ b/multiboot2-header/src/entry_efi_32.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::fmt; use core::fmt::{Debug, Formatter}; use core::mem::size_of; @@ -12,31 +12,42 @@ use core::mem::size_of; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct EntryEfi32HeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, entry_addr: u32, } impl EntryEfi32HeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag, entry_addr: u32) -> Self { - EntryEfi32HeaderTag { - typ: HeaderTagType::EntryAddressEFI32, + let header = HeaderTagHeader::new( + HeaderTagType::EntryAddressEFI32, flags, - size: size_of::() as u32, - entry_addr, - } + size_of::() as u32, + ); + Self { header, entry_addr } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Returns the entry address. + #[must_use] pub const fn entry_addr(&self) -> u32 { self.entry_addr } @@ -45,9 +56,9 @@ impl EntryEfi32HeaderTag { impl Debug for EntryEfi32HeaderTag { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("EntryEfi32HeaderTag") - .field("type", &{ self.typ }) - .field("flags", &{ self.flags }) - .field("size", &{ self.size }) + .field("type", &self.typ()) + .field("flags", &self.flags()) + .field("size", &self.size()) .field("entry_addr", &(self.entry_addr as *const u32)) .finish() } diff --git a/multiboot2-header/src/entry_efi_64.rs b/multiboot2-header/src/entry_efi_64.rs index dea41a95..e145f5cf 100644 --- a/multiboot2-header/src/entry_efi_64.rs +++ b/multiboot2-header/src/entry_efi_64.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::fmt; use core::fmt::{Debug, Formatter}; use core::mem::size_of; @@ -12,31 +12,42 @@ use core::mem::size_of; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct EntryEfi64HeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, entry_addr: u32, } impl EntryEfi64HeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag, entry_addr: u32) -> Self { - EntryEfi64HeaderTag { - typ: HeaderTagType::EntryAddressEFI64, + let header = HeaderTagHeader::new( + HeaderTagType::EntryAddressEFI64, flags, - size: size_of::() as u32, - entry_addr, - } + size_of::() as u32, + ); + Self { header, entry_addr } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Returns the entry address. + #[must_use] pub const fn entry_addr(&self) -> u32 { self.entry_addr } @@ -45,9 +56,9 @@ impl EntryEfi64HeaderTag { impl Debug for EntryEfi64HeaderTag { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("EntryEfi64HeaderTag") - .field("type", &{ self.typ }) - .field("flags", &{ self.flags }) - .field("size", &{ self.size }) + .field("type", &self.typ()) + .field("flags", &self.flags()) + .field("size", &self.size()) .field("entry_addr", &(self.entry_addr as *const u32)) .finish() } diff --git a/multiboot2-header/src/framebuffer.rs b/multiboot2-header/src/framebuffer.rs index 1b9d1772..1e96e6f1 100644 --- a/multiboot2-header/src/framebuffer.rs +++ b/multiboot2-header/src/framebuffer.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::mem::size_of; /// Specifies the preferred graphics mode. If this tag @@ -8,41 +8,58 @@ use core::mem::size_of; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct FramebufferHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, width: u32, height: u32, depth: u32, } impl FramebufferHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag, width: u32, height: u32, depth: u32) -> Self { - FramebufferHeaderTag { - typ: HeaderTagType::Framebuffer, - flags, - size: size_of::() as u32, + let header = + HeaderTagHeader::new(HeaderTagType::Framebuffer, flags, size_of::() as u32); + Self { + header, width, height, depth, } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Returns the width. + #[must_use] pub const fn width(&self) -> u32 { self.width } + + /// Returns the height. + #[must_use] pub const fn height(&self) -> u32 { self.height } + + /// Returns the depth. + #[must_use] pub const fn depth(&self) -> u32 { self.depth } diff --git a/multiboot2-header/src/header.rs b/multiboot2-header/src/header.rs index cb256f92..4c3c988b 100644 --- a/multiboot2-header/src/header.rs +++ b/multiboot2-header/src/header.rs @@ -1,8 +1,8 @@ use crate::{ AddressHeaderTag, ConsoleHeaderTag, EfiBootServiceHeaderTag, EndHeaderTag, EntryAddressHeaderTag, EntryEfi32HeaderTag, EntryEfi64HeaderTag, FramebufferHeaderTag, - HeaderTag, HeaderTagISA, HeaderTagType, InformationRequestHeaderTag, ModuleAlignHeaderTag, - RelocatableHeaderTag, + HeaderTagHeader, HeaderTagISA, HeaderTagType, InformationRequestHeaderTag, + ModuleAlignHeaderTag, RelocatableHeaderTag, }; use core::fmt::{Debug, Formatter}; use core::mem::size_of; @@ -103,89 +103,106 @@ impl<'a> Multiboot2Header<'a> { } /// Wrapper around [`Multiboot2BasicHeader::verify_checksum`]. + #[must_use] pub const fn verify_checksum(&self) -> bool { self.0.verify_checksum() } /// Wrapper around [`Multiboot2BasicHeader::header_magic`]. + #[must_use] pub const fn header_magic(&self) -> u32 { self.0.header_magic() } /// Wrapper around [`Multiboot2BasicHeader::arch`]. + #[must_use] pub const fn arch(&self) -> HeaderTagISA { self.0.arch() } /// Wrapper around [`Multiboot2BasicHeader::length`]. + #[must_use] pub const fn length(&self) -> u32 { self.0.length() } /// Wrapper around [`Multiboot2BasicHeader::checksum`]. + #[must_use] pub const fn checksum(&self) -> u32 { self.0.checksum() } /// Wrapper around [`Multiboot2BasicHeader::tag_iter`]. + #[must_use] pub fn iter(&self) -> Multiboot2HeaderTagIter { self.0.tag_iter() } /// Wrapper around [`Multiboot2BasicHeader::calc_checksum`]. + #[must_use] pub const fn calc_checksum(magic: u32, arch: HeaderTagISA, length: u32) -> u32 { Multiboot2BasicHeader::calc_checksum(magic, arch, length) } /// Search for the address header tag. + #[must_use] pub fn address_tag(&self) -> Option<&AddressHeaderTag> { self.get_tag(HeaderTagType::Address) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const AddressHeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const AddressHeaderTag) }) } /// Search for the entry address header tag. + #[must_use] pub fn entry_address_tag(&self) -> Option<&EntryAddressHeaderTag> { self.get_tag(HeaderTagType::EntryAddress) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const EntryAddressHeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const EntryAddressHeaderTag) }) } /// Search for the EFI32 entry address header tag. + #[must_use] pub fn entry_address_efi32_tag(&self) -> Option<&EntryEfi32HeaderTag> { self.get_tag(HeaderTagType::EntryAddressEFI32) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const EntryEfi32HeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const EntryEfi32HeaderTag) }) } /// Search for the EFI64 entry address header tag. + #[must_use] pub fn entry_address_efi64_tag(&self) -> Option<&EntryEfi64HeaderTag> { self.get_tag(HeaderTagType::EntryAddressEFI64) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const EntryEfi64HeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const EntryEfi64HeaderTag) }) } /// Search for the console flags header tag. + #[must_use] pub fn console_flags_tag(&self) -> Option<&ConsoleHeaderTag> { self.get_tag(HeaderTagType::ConsoleFlags) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const ConsoleHeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const ConsoleHeaderTag) }) } /// Search for the framebuffer header tag. + #[must_use] pub fn framebuffer_tag(&self) -> Option<&FramebufferHeaderTag> { self.get_tag(HeaderTagType::Framebuffer) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const FramebufferHeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const FramebufferHeaderTag) }) } /// Search for the module align header tag. + #[must_use] pub fn module_align_tag(&self) -> Option<&ModuleAlignHeaderTag> { self.get_tag(HeaderTagType::ModuleAlign) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const ModuleAlignHeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const ModuleAlignHeaderTag) }) } /// Search for the EFI Boot Services header tag. + #[must_use] pub fn efi_boot_services_tag(&self) -> Option<&EfiBootServiceHeaderTag> { - self.get_tag(HeaderTagType::EfiBS) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const EfiBootServiceHeaderTag) }) + self.get_tag(HeaderTagType::EfiBS).map(|tag| unsafe { + &*(tag as *const HeaderTagHeader as *const EfiBootServiceHeaderTag) + }) } /// Search for the EFI32 entry address header tag. + #[must_use] pub fn relocatable_tag(&self) -> Option<&RelocatableHeaderTag> { self.get_tag(HeaderTagType::Relocatable) - .map(|tag| unsafe { &*(tag as *const HeaderTag as *const RelocatableHeaderTag) }) + .map(|tag| unsafe { &*(tag as *const HeaderTagHeader as *const RelocatableHeaderTag) }) } - fn get_tag(&self, typ: HeaderTagType) -> Option<&HeaderTag> { + fn get_tag(&self, typ: HeaderTagType) -> Option<&HeaderTagHeader> { self.iter() .map(|tag| unsafe { tag.as_ref() }.unwrap()) .find(|tag| tag.typ() == typ) @@ -229,7 +246,7 @@ impl Multiboot2BasicHeader { pub(crate) const fn new(arch: HeaderTagISA, length: u32) -> Self { let magic = MAGIC; let checksum = Self::calc_checksum(magic, arch, length); - Multiboot2BasicHeader { + Self { header_magic: magic, arch, length, @@ -238,25 +255,38 @@ impl Multiboot2BasicHeader { } /// Verifies that a Multiboot2 header is valid. + #[must_use] pub const fn verify_checksum(&self) -> bool { let check = Self::calc_checksum(self.header_magic, self.arch, self.length); check == self.checksum } /// Calculates the checksum as described in the spec. + #[must_use] pub const fn calc_checksum(magic: u32, arch: HeaderTagISA, length: u32) -> u32 { (0x100000000 - magic as u64 - arch as u64 - length as u64) as u32 } + /// Returns the header magic. + #[must_use] pub const fn header_magic(&self) -> u32 { self.header_magic } + + /// Returns the [`HeaderTagISA`]. + #[must_use] pub const fn arch(&self) -> HeaderTagISA { self.arch } + + /// Returns the length. + #[must_use] pub const fn length(&self) -> u32 { self.length } + + /// Returns the checksum. + #[must_use] pub const fn checksum(&self) -> u32 { self.checksum } @@ -265,12 +295,13 @@ impl Multiboot2BasicHeader { /// /// # Panics /// See doc of [`Multiboot2HeaderTagIter`]. + #[must_use] pub fn tag_iter(&self) -> Multiboot2HeaderTagIter { - let base_hdr_size = size_of::(); + let base_hdr_size = size_of::(); if base_hdr_size == self.length as usize { panic!("No end tag!"); } - let tag_base_addr = self as *const Multiboot2BasicHeader; + let tag_base_addr = self as *const Self; // cast to u8 so that the offset in bytes works correctly let tag_base_addr = tag_base_addr as *const u8; // tag_base_addr should now point behind the "static" members @@ -278,7 +309,7 @@ impl Multiboot2BasicHeader { // align pointer to 8 byte according to spec let tag_base_addr = unsafe { tag_base_addr.add(tag_base_addr.align_offset(8)) }; // cast back - let tag_base_addr = tag_base_addr as *const HeaderTag; + let tag_base_addr = tag_base_addr as *const HeaderTagHeader; let tags_len = self.length as usize - base_hdr_size; Multiboot2HeaderTagIter::new(tag_base_addr, tags_len as u32) } @@ -307,7 +338,7 @@ impl Debug for Multiboot2BasicHeader { #[derive(Clone)] pub struct Multiboot2HeaderTagIter { /// 8-byte aligned base address - base: *const HeaderTag, + base: *const HeaderTagHeader, /// Offset in bytes from the base address. /// Always <= than size. n: u32, @@ -324,11 +355,11 @@ pub struct Multiboot2HeaderTagIter { } impl Multiboot2HeaderTagIter { - fn new(base: *const HeaderTag, size: u32) -> Self { + fn new(base: *const HeaderTagHeader, size: u32) -> Self { // transform to byte pointer => offset works properly let base = base as *const u8; let base = unsafe { base.add(base.align_offset(8)) }; - let base = base as *const HeaderTag; + let base = base as *const HeaderTagHeader; Self { base, n: 0, @@ -340,7 +371,7 @@ impl Multiboot2HeaderTagIter { } impl Iterator for Multiboot2HeaderTagIter { - type Item = *const HeaderTag; + type Item = *const HeaderTagHeader; fn next(&mut self) -> Option { // no more bytes left to check; length reached @@ -351,7 +382,7 @@ impl Iterator for Multiboot2HeaderTagIter { // transform to byte ptr => offset works correctly let ptr = self.base as *const u8; let ptr = unsafe { ptr.add(self.n as usize) }; - let ptr = ptr as *const HeaderTag; + let ptr = ptr as *const HeaderTagHeader; assert_eq!(ptr as usize % 8, 0, "must be 8-byte aligned"); let tag = unsafe { &*ptr }; assert!( diff --git a/multiboot2-header/src/information_request.rs b/multiboot2-header/src/information_request.rs index c5bb1d6c..f19e15bc 100644 --- a/multiboot2-header/src/information_request.rs +++ b/multiboot2-header/src/information_request.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, MbiTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, MbiTagType}; use crate::{HeaderTagType, MbiTagTypeId}; use core::fmt; use core::fmt::{Debug, Formatter}; @@ -11,9 +11,7 @@ use multiboot2::TagType; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct InformationRequestHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, // Length is determined by size. // Must be parsed during runtime with unsafe pointer magic and the size field. requests: [MbiTagTypeId; N], @@ -23,28 +21,38 @@ impl InformationRequestHeaderTag { /// Creates a new object. The size parameter is the value of the size property. /// It doesn't have to match with `N` necessarily, because during compile time we /// can't know the size of the tag in all runtime situations. + #[must_use] pub fn new(flags: HeaderTagFlag, requests: [MbiTagTypeId; N], size: Option) -> Self { - InformationRequestHeaderTag { - typ: HeaderTagType::InformationRequest, + let header = HeaderTagHeader::new( + HeaderTagType::InformationRequest, flags, - size: size.unwrap_or(size_of::() as u32), - requests, - } + size.unwrap_or(size_of::() as u32), + ); + Self { header, requests } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } /// Returns the requests as array. Only works if the number of requests /// is known at compile time. For safety and correctness during runtime, /// you should use `req_iter()`. + #[must_use] pub const fn requests(&self) -> [MbiTagTypeId; N] { // cheap to copy, otherwise difficult with lifetime self.requests @@ -54,9 +62,10 @@ impl InformationRequestHeaderTag { /// from the `size`-property. This method is useful /// because this struct uses a const generic, but during runtime /// we don't know the value in almost any case. + #[must_use] pub const fn dynamic_requests_size(&self) -> u32 { let base_struct_size = size_of::>(); - let size_diff = self.size - base_struct_size as u32; + let size_diff = self.size() - base_struct_size as u32; if size_diff > 0 { size_diff / size_of::() as u32 } else { @@ -65,10 +74,11 @@ impl InformationRequestHeaderTag { } /// Returns an [`InformationRequestHeaderTagIter`]. + #[must_use] pub const fn req_iter(&self) -> InformationRequestHeaderTagIter { let base_struct_size = size_of::>(); let count = self.dynamic_requests_size(); - let base_ptr = self as *const InformationRequestHeaderTag; + let base_ptr = self as *const Self; let base_ptr = base_ptr as *const u8; let base_ptr = unsafe { base_ptr.add(base_struct_size) }; let base_ptr = base_ptr as *const MbiTagTypeId; @@ -79,10 +89,10 @@ impl InformationRequestHeaderTag { impl Debug for InformationRequestHeaderTag { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("InformationRequestHeaderTag") - .field("type", &{ self.typ }) - .field("flags", &{ self.flags }) - .field("size", &{ self.size }) - .field("requests", &{ self.req_iter() }) + .field("type", &self.typ()) + .field("flags", &self.flags()) + .field("size", &self.size()) + .field("requests", &self.req_iter()) .finish() } } diff --git a/multiboot2-header/src/lib.rs b/multiboot2-header/src/lib.rs index 165bace8..578511e8 100644 --- a/multiboot2-header/src/lib.rs +++ b/multiboot2-header/src/lib.rs @@ -38,10 +38,22 @@ #![no_std] #![cfg_attr(feature = "unstable", feature(error_in_core))] -#![deny(rustdoc::all)] -#![deny(clippy::all)] -#![deny(clippy::missing_const_for_fn)] +// --- BEGIN STYLE CHECKS --- +#![deny( + clippy::all, + clippy::cargo, + clippy::nursery, + clippy::must_use_candidate, + // clippy::restriction, + // clippy::pedantic +)] +// now allow a few rules which are denied by the above statement +// --> They are either ridiculous, not necessary, or we can't fix them. +#![allow(clippy::multiple_crate_versions)] +#![deny(missing_docs)] #![deny(missing_debug_implementations)] +#![deny(rustdoc::all)] +// --- END STYLE CHECKS --- #[cfg(feature = "builder")] extern crate alloc; diff --git a/multiboot2-header/src/module_align.rs b/multiboot2-header/src/module_align.rs index 0ec2eb4b..c67acc58 100644 --- a/multiboot2-header/src/module_align.rs +++ b/multiboot2-header/src/module_align.rs @@ -1,32 +1,38 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::mem::size_of; /// If this tag is present, provided boot modules must be page aligned. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct ModuleAlignHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, } impl ModuleAlignHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag) -> Self { - ModuleAlignHeaderTag { - typ: HeaderTagType::ModuleAlign, - flags, - size: size_of::() as u32, - } + let header = + HeaderTagHeader::new(HeaderTagType::ModuleAlign, flags, size_of::() as u32); + Self { header } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } } diff --git a/multiboot2-header/src/relocatable.rs b/multiboot2-header/src/relocatable.rs index ca8aea49..80cfaf96 100644 --- a/multiboot2-header/src/relocatable.rs +++ b/multiboot2-header/src/relocatable.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::fmt; use core::fmt::{Debug, Formatter}; use core::mem::size_of; @@ -22,9 +22,7 @@ pub enum RelocatableHeaderTagPreference { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct RelocatableHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, /// Lowest possible physical address at which image should be loaded. The bootloader cannot load any part of image below this address min_addr: u32, /// Highest possible physical address at which loaded image should end. The bootloader cannot load any part of image above this address. @@ -35,6 +33,8 @@ pub struct RelocatableHeaderTag { } impl RelocatableHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new( flags: HeaderTagFlag, min_addr: u32, @@ -42,10 +42,10 @@ impl RelocatableHeaderTag { align: u32, preference: RelocatableHeaderTagPreference, ) -> Self { - RelocatableHeaderTag { - typ: HeaderTagType::Relocatable, - flags, - size: size_of::() as u32, + let header = + HeaderTagHeader::new(HeaderTagType::Relocatable, flags, size_of::() as u32); + Self { + header, min_addr, max_addr, align, @@ -53,24 +53,44 @@ impl RelocatableHeaderTag { } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } + + /// Return the minimum address. + #[must_use] pub const fn min_addr(&self) -> u32 { self.min_addr } + + /// Return the maximum address. + #[must_use] pub const fn max_addr(&self) -> u32 { self.max_addr } + + /// Return the alignment. + #[must_use] pub const fn align(&self) -> u32 { self.align } + + /// Return the preference. + #[must_use] pub const fn preference(&self) -> RelocatableHeaderTagPreference { self.preference } @@ -79,9 +99,9 @@ impl RelocatableHeaderTag { impl Debug for RelocatableHeaderTag { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("RelocatableHeaderTag") - .field("type", &{ self.typ }) - .field("flags", &{ self.flags }) - .field("size", &{ self.size }) + .field("type", &self.typ()) + .field("flags", &self.flags()) + .field("size", &self.size()) // trick to print this as hexadecimal pointer .field("min_addr", &(self.min_addr as *const u32)) .field("max_addr", &(self.max_addr as *const u32)) diff --git a/multiboot2-header/src/tags.rs b/multiboot2-header/src/tags.rs index 51242697..c51aedc0 100644 --- a/multiboot2-header/src/tags.rs +++ b/multiboot2-header/src/tags.rs @@ -17,7 +17,7 @@ pub enum HeaderTagISA { /// Possible types for header tags of a Multiboot2 header. The names and values are taken /// from the example C code at the bottom of the Multiboot2 specification. This value -/// stands in the `typ` property of [`crate::tags::HeaderTag`]. +/// stands in the `typ` property of [`HeaderTagHeader`]. #[repr(u16)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum HeaderTagType { @@ -47,6 +47,7 @@ pub enum HeaderTagType { impl HeaderTagType { /// Returns the number of possible variants. + #[must_use] pub const fn count() -> u32 { 11 } @@ -56,31 +57,46 @@ impl HeaderTagType { #[repr(u16)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum HeaderTagFlag { + /// Bootloader must provide this tag. If this is not possible, the + /// bootloader will fail loading the kernel. Required = 0, + /// Bootloader should provide the tag if possible. Optional = 1, } -/// Common properties for all header tags. Other tags may have additional fields -/// that depend on the `typ` and the `size` field. All tags share the same beginning of the -/// struct. +/// The common header that all header tags share. Specific tags may have +/// additional fields that depend on the `typ` and the `size` field. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] -pub struct HeaderTag { +pub struct HeaderTagHeader { + typ: HeaderTagType, /* u16 */ // u16 value - typ: HeaderTagType, - // u16 value - flags: HeaderTagFlag, + flags: HeaderTagFlag, /* u16 */ size: u32, - // maybe additional fields (tag specific) + // Followed by optional additional tag specific fields. } -impl HeaderTag { +impl HeaderTagHeader { + /// Creates a new header. + #[must_use] + pub const fn new(typ: HeaderTagType, flags: HeaderTagFlag, size: u32) -> Self { + Self { typ, flags, size } + } + + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { self.typ } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { self.flags } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { self.size } @@ -88,10 +104,10 @@ impl HeaderTag { #[cfg(test)] mod tests { - use crate::HeaderTag; + use crate::HeaderTagHeader; #[test] fn test_assert_size() { - assert_eq!(core::mem::size_of::(), 2 + 2 + 4); + assert_eq!(core::mem::size_of::(), 2 + 2 + 4); } } diff --git a/multiboot2-header/src/uefi_bs.rs b/multiboot2-header/src/uefi_bs.rs index 93204b3f..ce8b0a32 100644 --- a/multiboot2-header/src/uefi_bs.rs +++ b/multiboot2-header/src/uefi_bs.rs @@ -1,4 +1,4 @@ -use crate::{HeaderTagFlag, HeaderTagType}; +use crate::{HeaderTagFlag, HeaderTagHeader, HeaderTagType}; use core::mem::size_of; /// This tag indicates that payload supports starting without terminating UEFI boot services. @@ -6,28 +6,33 @@ use core::mem::size_of; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct EfiBootServiceHeaderTag { - typ: HeaderTagType, - flags: HeaderTagFlag, - size: u32, + header: HeaderTagHeader, } impl EfiBootServiceHeaderTag { + /// Constructs a new tag. + #[must_use] pub const fn new(flags: HeaderTagFlag) -> Self { - EfiBootServiceHeaderTag { - typ: HeaderTagType::EfiBS, - flags, - size: size_of::() as u32, - } + let header = HeaderTagHeader::new(HeaderTagType::EfiBS, flags, size_of::() as u32); + Self { header } } + /// Returns the [`HeaderTagType`]. + #[must_use] pub const fn typ(&self) -> HeaderTagType { - self.typ + self.header.typ() } + + /// Returns the [`HeaderTagFlag`]s. + #[must_use] pub const fn flags(&self) -> HeaderTagFlag { - self.flags + self.header.flags() } + + /// Returns the size. + #[must_use] pub const fn size(&self) -> u32 { - self.size + self.header.size() } }