Skip to content

multiboot2: Ord for TagType #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion multiboot2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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.13.1"
version = "0.13.2"
authors = [
"Philipp Oppermann <[email protected]>",
"Calvin Lee <[email protected]>",
Expand Down
4 changes: 4 additions & 0 deletions multiboot2/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG for crate `multiboot2`

## 0.13.2
- `TagType` now implements `Ord` so that it can be used in `BTreeSet`
- small internal improvements and restructuring of the code (no breaking changes to public API)

## 0.13.1
- minor fix

Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/boot_loader_name.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::TagType;

/// This Tag contains the name of the bootloader that is booting the kernel.
/// This tag contains the name of the bootloader that is booting the kernel.
///
/// The name is a normal C-style UTF-8 zero-terminated string that can be
/// obtained via the `name` method.
Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/command_line.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::TagType;

/// This Tag contains the command line string.
/// This tag contains the command line string.
///
/// The string is a normal C-style UTF-8 zero-terminated string that can be
/// obtained via the `command_line` method.
Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/elf_sections.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::header::Tag;
use crate::tag_type::Tag;
use core::fmt::{Debug, Formatter};

/// This tag contains section header table from an ELF kernel.
Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/framebuffer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::header::Tag;
use crate::tag_type::Tag;
use crate::Reader;
use core::slice;

Expand Down
16 changes: 12 additions & 4 deletions multiboot2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,15 @@ pub use elf_sections::{
ElfSection, ElfSectionFlags, ElfSectionIter, ElfSectionType, ElfSectionsTag,
};
pub use framebuffer::{FramebufferColor, FramebufferField, FramebufferTag, FramebufferType};
pub use header::TagType;
pub use header::MULTIBOOT2_BOOTLOADER_MAGIC;
use header::{Tag, TagIter};
pub use image_load_addr::ImageLoadPhysAddr;
pub use memory_map::{
EFIMemoryAreaType, EFIMemoryDesc, EFIMemoryMapTag, MemoryArea, MemoryAreaIter, MemoryAreaType,
MemoryMapTag,
};
pub use module::{ModuleIter, ModuleTag};
pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
pub use tag_type::TagType;
use tag_type::{Tag, TagIter};
pub use vbe_info::{
VBECapabilities, VBEControlInfo, VBEDirectColorAttributes, VBEField, VBEInfoTag,
VBEMemoryModel, VBEModeAttributes, VBEModeInfo, VBEWindowAttributes,
Expand All @@ -68,13 +67,22 @@ mod command_line;
mod efi;
mod elf_sections;
mod framebuffer;
mod header;
mod image_load_addr;
mod memory_map;
mod module;
mod rsdp;
mod tag_type;
mod vbe_info;

/// Magic number that a multiboot2-compliant boot loader will store in `eax` register
/// right before handoff to the payload (the kernel). This value can be used to check,
/// that the kernel was indeed booted via multiboot2.
///
/// Caution: You might need some assembly code (e.g. GAS or NASM) first, which
/// moves `eax` to another register, like `edi`. Otherwise it probably happens,
/// that the Rust compiler output changes `eax` before you can access it.
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
Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/memory_map.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::TagType;
use core::marker::PhantomData;

/// This Tag provides an initial host memory map.
/// This tag provides an initial host memory map.
///
/// The map provided is guaranteed to list all standard RAM that should be
/// available for normal use. This type however includes the regions occupied
Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::header::{Tag, TagIter, TagType};
use crate::tag_type::{Tag, TagIter, TagType};
use core::fmt::{Debug, Formatter};

/// This tag indicates to the kernel what boot module was loaded along with
Expand Down
68 changes: 35 additions & 33 deletions multiboot2/src/header.rs → multiboot2/src/tag_type.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
//! Module for [`TagType`].

use core::fmt::{Debug, Formatter};
use core::hash::{Hash, Hasher};
use core::hash::Hash;
use core::marker::PhantomData;

/// Magic number that a multiboot2-compliant boot loader will store in `eax` register
/// right before handoff to the payload (the kernel). This value can be used to check,
/// that the kernel was indeed booted via multiboot2.
///
/// Caution: You might need some assembly code (e.g. GAS or NASM) first, which
/// moves `eax` to another register, like `edi`. Otherwise it probably happens,
/// that the Rust compiler output changes `eax` before you can access it.
pub const MULTIBOOT2_BOOTLOADER_MAGIC: u32 = 0x36d76289;

/// Possible types of a Tag in the Multiboot2 Information Structure (MBI), therefore the value
/// of the the `typ` property. The names and values are taken from the example C code
/// at the bottom of the Multiboot2 specification.
#[repr(u32)]
#[derive(Copy, Clone, Debug, Eq)]
#[derive(Copy, Clone, Debug, Eq, Ord, PartialOrd, PartialEq, Hash)]
pub enum TagType {
/// Marks the end of the tags.
End = 0,
Expand Down Expand Up @@ -110,19 +103,6 @@ impl PartialEq<TagType> for u32 {
}
}

impl PartialEq<TagType> for TagType {
fn eq(&self, other: &TagType) -> bool {
*self as u32 == *other as u32
}
}

// impl required because this type is used in a hashmap in `multiboot2-header`
impl Hash for TagType {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u32(*self as u32);
}
}

/// All tags that could passed via the Multiboot2 information structure to a payload/program/kernel.
/// Better not confuse this with the Multiboot2 header tags. They are something different.
#[derive(Clone, Copy)]
Expand Down Expand Up @@ -185,14 +165,36 @@ mod tests {
use super::*;

#[test]
fn test_hash() {
let mut hashset = std::collections::HashSet::new();
hashset.insert(TagType::Cmdline);
hashset.insert(TagType::ElfSections);
hashset.insert(TagType::BootLoaderName);
hashset.insert(TagType::LoadBaseAddr);
hashset.insert(TagType::LoadBaseAddr);
assert_eq!(hashset.len(), 4);
println!("{:#?}", hashset);
fn test_hashset() {
let mut set = std::collections::HashSet::new();
set.insert(TagType::Cmdline);
set.insert(TagType::ElfSections);
set.insert(TagType::BootLoaderName);
set.insert(TagType::LoadBaseAddr);
set.insert(TagType::LoadBaseAddr);
assert_eq!(set.len(), 4);
println!("{:#?}", set);
}

#[test]
fn test_btreeset() {
let mut set = std::collections::BTreeSet::new();
set.insert(TagType::Cmdline);
set.insert(TagType::ElfSections);
set.insert(TagType::BootLoaderName);
set.insert(TagType::LoadBaseAddr);
set.insert(TagType::LoadBaseAddr);
assert_eq!(set.len(), 4);
for (current, next) in set.iter().zip(set.iter().skip(1)) {
assert!(current < next);
}
println!("{:#?}", set);
}

/// Tests for equality when one type is u32 and the other the enum representation.
#[test]
fn test_partial_eq_u32() {
assert_eq!(21, TagType::LoadBaseAddr);
assert_eq!(TagType::LoadBaseAddr, 21);
}
}