diff --git a/.editorconfig b/.editorconfig index 75a88ac5..2537322d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,6 +9,7 @@ insert_final_newline = true indent_style = space indent_size = 4 trim_trailing_whitespace = true +max_line_length = 80 [*.yml] indent_size = 2 diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml new file mode 100644 index 00000000..30bddfa5 --- /dev/null +++ b/.github/workflows/qa.yml @@ -0,0 +1,12 @@ +name: QA + +on: [ push, pull_request ] + +jobs: + spellcheck: + name: Spellcheck + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + # Executes "typos ." + - uses: crate-ci/typos@v1.13.20 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 54f0b213..1c5bdba4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,6 +10,7 @@ env: CARGO_TERM_COLOR: always jobs: + # Regular build (with std) + test execution build: runs-on: ubuntu-latest strategy: @@ -19,7 +20,7 @@ jobs: - nightly - 1.52.1 # MSVR steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Important preparation step: override the latest default Rust version in GitHub CI # with the current value of the iteration in the "strategy.matrix.rust"-array. - uses: actions-rs/toolchain@v1 @@ -30,10 +31,11 @@ jobs: # helps to identify if the right cargo version is actually used - run: cargo version - name: Build - run: cargo build --verbose + run: cargo build --all-targets --verbose - name: Run tests run: cargo test --verbose + # no-std build without tests build_no_std: runs-on: ubuntu-latest strategy: @@ -43,7 +45,7 @@ jobs: - nightly - 1.52.1 # MSVR steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Important preparation step: override the latest default Rust version in GitHub CI # with the current value of the iteration in the "strategy.matrix.rust"-array. - uses: actions-rs/toolchain@v1 @@ -58,6 +60,26 @@ jobs: - name: Build (no_std) run: cargo build --target thumbv7em-none-eabihf + # Tests that the unstable feature, which requires nightly, builds. + build_unstable: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - nightly + steps: + - uses: actions/checkout@v3 + # Important preparation step: override the latest default Rust version in GitHub CI + # with the current value of the iteration in the "strategy.matrix.rust"-array. + - uses: actions-rs/toolchain@v1 + with: + profile: default + toolchain: ${{ matrix.rust }} + override: true + - name: Build (unstable) + run: cargo build --all-targets --features unstable + - name: Test (unstable) + run: cargo test --all-targets --features unstable # As discussed, these tasks are optional for PRs. style_checks: @@ -67,7 +89,7 @@ jobs: rust: - 1.52.1 # MSVR steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # Important preparation step: override the latest default Rust version in GitHub CI # with the current value of the iteration in the "strategy.matrix.rust"-array. - uses: actions-rs/toolchain@v1 @@ -80,6 +102,6 @@ jobs: - name: Rustfmt run: cargo fmt -- --check - name: Clippy - run: cargo clippy + run: cargo clippy --all-targets - name: Rustdoc - run: cargo doc + run: cargo doc --document-private-items diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 00000000..db059eed --- /dev/null +++ b/.typos.toml @@ -0,0 +1,13 @@ +# Configuration for the typos spell checker utility (). + +[files] +extend-exclude = [ + # "uefi/src/table/boot.rs" +] + +[default.extend-words] +Rela = "Rela" + +[default.extend-identifiers] +# FOOBAR = "FOOBAR" + diff --git a/Cargo.toml b/Cargo.toml index 366c05e8..6cc2b2ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,5 @@ [workspace] members = [ - # Multiboot2 Information Structure (MBI) "multiboot2", - # Multiboot2 headers "multiboot2-header", ] diff --git a/multiboot2-header/src/builder/traits.rs b/multiboot2-header/src/builder/traits.rs index 10a04acd..015f84b0 100644 --- a/multiboot2-header/src/builder/traits.rs +++ b/multiboot2-header/src/builder/traits.rs @@ -23,7 +23,7 @@ pub(crate) trait StructAsBytes: Sized { } /// Returns the structure as a vector of its bytes. - /// The length is determined by [`size`]. + /// The length is determined by [`Self::byte_size`]. fn struct_as_bytes(&self) -> alloc::vec::Vec { let ptr = self.as_ptr(); let mut vec = alloc::vec::Vec::with_capacity(self.byte_size()); diff --git a/multiboot2/Cargo.toml b/multiboot2/Cargo.toml index 47af6794..bca67ff8 100644 --- a/multiboot2/Cargo.toml +++ b/multiboot2/Cargo.toml @@ -6,7 +6,7 @@ Multiboot2-compliant bootloaders, like GRUB. It supports all tags from the speci including full support for the sections of ELF-64. This library is `no_std` and can be used in a Multiboot2-kernel. """ -version = "0.14.1" +version = "0.14.2" authors = [ "Philipp Oppermann ", "Calvin Lee ", @@ -31,5 +31,11 @@ homepage = "https://github.com/rust-osdev/multiboot2" repository = "https://github.com/rust-osdev/multiboot2" documentation = "https://docs.rs/multiboot2" +[features] +default = [] +# Nightly-only features that will eventually be stabilized. +unstable = [] + [dependencies] bitflags = "1" +derive_more = { version = "0.99.17", default-features = false, features = ["display"] } diff --git a/multiboot2/Changelog.md b/multiboot2/Changelog.md index 0bb28b8f..2e6cefbd 100644 --- a/multiboot2/Changelog.md +++ b/multiboot2/Changelog.md @@ -1,5 +1,12 @@ # CHANGELOG for crate `multiboot2` +## 0.14.2 (2023-03-17) +- documentation fixes +- `MbiLoadError` now implements `Display` +- Added the `unstable` feature, which enables nightly-only functionality. + With this feature, `MbiLoadError` now implements `core::error::Error` and can + be used with `anyhow::Result` for example. + ## 0.14.1 (2023-03-09) - fixed the calculation of the last area of the memory map tag ([#119](https://github.com/rust-osdev/multiboot2/pull/119)) (Previously, iterating the EFI Memory map resulted in a superfluous entry as it ran over the next tag) diff --git a/multiboot2/src/boot_loader_name.rs b/multiboot2/src/boot_loader_name.rs index 783c10dd..c9fc73bd 100644 --- a/multiboot2/src/boot_loader_name.rs +++ b/multiboot2/src/boot_loader_name.rs @@ -21,10 +21,10 @@ impl BootLoaderNameTag { /// /// # Examples /// - /// ```ignore + /// ```rust,no_run + /// # let boot_info = unsafe { multiboot2::load(0xdeadbeef).unwrap() }; /// if let Some(tag) = boot_info.boot_loader_name_tag() { - /// let name = tag.name(); - /// assert_eq!("GRUB 2.02~beta3-5", name); + /// assert_eq!(Ok("GRUB 2.02~beta3-5"), tag.name()); /// } /// ``` pub fn name(&self) -> Result<&str, Utf8Error> { diff --git a/multiboot2/src/command_line.rs b/multiboot2/src/command_line.rs index 99321b86..80ddf70b 100644 --- a/multiboot2/src/command_line.rs +++ b/multiboot2/src/command_line.rs @@ -25,10 +25,11 @@ impl CommandLineTag { /// /// # Examples /// - /// ```ignore + /// ```rust,no_run + /// # let boot_info = unsafe { multiboot2::load(0xdeadbeef).unwrap() }; /// if let Some(tag) = boot_info.command_line_tag() { /// let command_line = tag.command_line(); - /// assert_eq!("/bootarg", command_line); + /// assert_eq!(Ok("/bootarg"), command_line); /// } /// ``` pub fn command_line(&self) -> Result<&str, str::Utf8Error> { diff --git a/multiboot2/src/elf_sections.rs b/multiboot2/src/elf_sections.rs index dd6ba821..c89a37e4 100644 --- a/multiboot2/src/elf_sections.rs +++ b/multiboot2/src/elf_sections.rs @@ -33,7 +33,8 @@ impl ElfSectionsTag { /// /// # Examples /// - /// ```ignore + /// ```rust,no_run + /// # let boot_info = unsafe { multiboot2::load(0xdeadbeef).unwrap() }; /// if let Some(elf_tag) = boot_info.elf_sections_tag() { /// let mut total = 0; /// for section in elf_tag.sections() { diff --git a/multiboot2/src/lib.rs b/multiboot2/src/lib.rs index 4546d695..923cff2b 100644 --- a/multiboot2/src/lib.rs +++ b/multiboot2/src/lib.rs @@ -1,13 +1,12 @@ -// this crate can use `std` in tests only -#![cfg_attr(not(test), no_std)] +#![no_std] +#![cfg_attr(feature = "unstable", feature(error_in_core))] #![deny(missing_debug_implementations)] // --- BEGIN STYLE CHECKS --- // These checks are optional in CI for PRs, as discussed in // https://github.com/rust-osdev/multiboot2/pull/92 #![deny(clippy::all)] #![deny(rustdoc::all)] -// Forcing this would be a little bit ridiculous, because it would require code examples for -// each getter and each trivial trait implementation (like Debug). +#![allow(rustdoc::private_doc_tests)] #![allow(rustdoc::missing_doc_code_examples)] // --- END STYLE CHECKS --- @@ -40,6 +39,7 @@ extern crate std; use core::fmt; +use derive_more::Display; pub use boot_loader_name::BootLoaderNameTag; pub use command_line::CommandLineTag; @@ -88,7 +88,7 @@ pub const MULTIBOOT2_BOOTLOADER_MAGIC: u32 = 0x36d76289; /// Load the multiboot boot information struct from an address. /// -/// This is the same as `load_with_offset` but the offset is omitted and set +/// This is the same as [`load_with_offset`] but the offset is omitted and set /// to zero. /// /// ## Example @@ -108,7 +108,7 @@ pub const MULTIBOOT2_BOOTLOADER_MAGIC: u32 = 0x36d76289; /// environment (segfault) but also in UEFI-applications, where the referenced /// memory is not (identity) mapped (UEFI does only identity mapping). /// * The memory at `address` must not be modified after calling `load` or the -/// program may observe unsychronized mutation. +/// program may observe unsynchronized mutation. pub unsafe fn load(address: usize) -> Result { load_with_offset(address, 0) } @@ -117,7 +117,7 @@ pub unsafe fn load(address: usize) -> Result { /// /// ## Example /// -/// ```ignore +/// ```rust,no_run /// use multiboot2::load_with_offset; /// /// let ptr = 0xDEADBEEF as *const u32; @@ -131,7 +131,7 @@ pub unsafe fn load(address: usize) -> Result { /// environment (segfault) but also in UEFI-applications, where the referenced /// memory is not (identity) mapped (UEFI does only identity mapping). /// * The memory at `address` must not be modified after calling `load` or the -/// program may observe unsychronized mutation. +/// program may observe unsynchronized mutation. pub unsafe fn load_with_offset( address: usize, offset: usize, @@ -161,19 +161,25 @@ pub unsafe fn load_with_offset( /// Error type that describes errors while loading/parsing a multiboot2 information structure /// from a given address. -#[derive(Debug)] +#[derive(Debug, Display)] pub enum MbiLoadError { /// The address is invalid. Make sure that the address is 8-byte aligned, /// according to the spec. + #[display(fmt = "The address is invalid")] IllegalAddress, /// The total size of the multiboot2 information structure must be a multiple of 8. /// (Not in spec, but it is implicitly the case, because the begin of MBI /// and all tags are 8-byte aligned and the end tag is exactly 8 byte long). + #[display(fmt = "The size of the MBI is unexpected")] IllegalTotalSize(u32), /// End tag missing. Each multiboot2 header requires to have an end tag. + #[display(fmt = "There is no end tag")] NoEndTag, } +#[cfg(feature = "unstable")] +impl core::error::Error for MbiLoadError {} + /// A Multiboot 2 Boot Information struct. pub struct BootInformation { inner: *const BootInformationInner, @@ -197,8 +203,9 @@ impl BootInformation { /// /// This is the same as doing: /// - /// ```ignore - /// let end_addr = boot_info.start_address() + boot_info.size(); + /// ```rust,no_run + /// # let boot_info = unsafe { multiboot2::load(0xdeadbeef).unwrap() }; + /// let end_addr = boot_info.start_address() + boot_info.total_size(); /// ``` pub fn end_address(&self) -> usize { self.start_address() + self.total_size() @@ -1434,4 +1441,12 @@ mod tests { core::mem::transmute::<[u8; 16], EFIMemoryMapTag>([0u8; 16]); } } + + #[test] + #[cfg(feature = "unstable")] + /// This test succeeds if it compiles. + fn mbi_load_error_implements_error() { + fn consumer(_e: E) {} + consumer(MbiLoadError::IllegalAddress) + } } diff --git a/multiboot2/src/rsdp.rs b/multiboot2/src/rsdp.rs index 511804c3..9188f204 100644 --- a/multiboot2/src/rsdp.rs +++ b/multiboot2/src/rsdp.rs @@ -29,7 +29,7 @@ pub struct RsdpV1Tag { } impl RsdpV1Tag { - /// The "RSD PTR " marker singature. + /// The "RSD PTR " marker signature. /// /// This is originally a 8-byte C string (not null terminated!) that must contain "RSD PTR " pub fn signature(&self) -> Result<&str, Utf8Error> { diff --git a/multiboot2/src/vbe_info.rs b/multiboot2/src/vbe_info.rs index e91971b7..d441137a 100644 --- a/multiboot2/src/vbe_info.rs +++ b/multiboot2/src/vbe_info.rs @@ -233,7 +233,7 @@ impl fmt::Debug for VBEModeInfo { /// A VBE colour field. /// -/// Descirbes the size and position of some colour capability. +/// Describes the size and position of some colour capability. #[derive(Debug, PartialEq, Eq, Copy, Clone)] #[repr(C, packed)] pub struct VBEField {