Skip to content
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
19 changes: 19 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use elf_sections::{ElfSectionsTag, ElfSection, ElfSectionIter, ElfSectionTyp
pub use memory_map::{MemoryMapTag, MemoryArea, MemoryAreaIter};
pub use module::{ModuleTag, ModuleIter};
pub use command_line::CommandLineTag;
pub use rsdp::{RsdpV1Tag, RsdpV2Tag};

#[macro_use]
extern crate bitflags;
Expand All @@ -20,6 +21,7 @@ mod elf_sections;
mod memory_map;
mod module;
mod command_line;
mod rsdp;

pub unsafe fn load(address: usize) -> BootInformation {
if !cfg!(test) {
Expand Down Expand Up @@ -74,6 +76,14 @@ impl BootInformation {
self.get_tag(1).map(|tag| unsafe { &*(tag as *const Tag as *const CommandLineTag) })
}

pub fn rsdp_v1_tag(&self) -> Option<&'static RsdpV1Tag> {
self.get_tag(14).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV1Tag) })
}

pub fn rsdp_v2_tag(&self) -> Option<&'static RsdpV2Tag> {
self.get_tag(15).map(|tag| unsafe { &*(tag as *const Tag as *const RsdpV2Tag) })
}

fn get(&self) -> &BootInformationInner {
unsafe { &*self.inner }
}
Expand Down Expand Up @@ -568,6 +578,15 @@ mod tests {
assert_eq!(0x7FE_0000, mm2.end_address());
assert_eq!(0x7EE_0000, mm2.size());
assert!(mm.next().is_none());

// Test the RSDP tag
let rsdp_old = bi.rsdp_v1_tag().unwrap();
assert_eq!("RSD PTR ", rsdp_old.signature().unwrap());
assert_eq!(89, rsdp_old.checksum());
assert_eq!("BOCHS ", rsdp_old.oem_id().unwrap());
assert_eq!(0, rsdp_old.revision());
assert_eq!(0x7FE18DC, rsdp_old.rsdt_address());

assert!(bi.module_tags().next().is_none());
assert_eq!("GRUB 2.02~beta3-5", bi.boot_loader_name_tag().unwrap().name());
assert_eq!("", bi.command_line_tag().unwrap().command_line());
Expand Down
85 changes: 85 additions & 0 deletions src/rsdp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/// The tag that the bootloader passes will depend on the ACPI version the hardware supports.
/// For ACPI Version 1.0, a `RsdpV1Tag` will be provided, which can be accessed from
/// `BootInformation` using the `rsdp_v1_tag` function. For subsequent versions of ACPI, a
/// `RsdpV2Tag` will be provided, which can be accessed with `rsdp_v2_tag`.
///
/// Even though the bootloader should give the address of the real RSDP/XSDT, the checksum and
/// signature should be manually verified.

use core::str;

#[derive(Debug)]
#[repr(C, packed)]
pub struct RsdpV1Tag {
typ: u32,
size: u32,
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
rsdt_address: u32, // This is the PHYSICAL address of the RSDT
}

impl RsdpV1Tag {
pub fn signature<'a>(&'a self) -> Option<&'a str> {
str::from_utf8(&self.signature).ok()
}

pub fn checksum(&self) -> u8 {
self.checksum
}

pub fn oem_id<'a>(&'a self) -> Option<&'a str> {
str::from_utf8(&self.oem_id).ok()
}

pub fn revision(&self) -> u8 {
self.revision
}

pub fn rsdt_address(&self) -> usize {
self.rsdt_address as usize
}
}

#[derive(Debug)]
#[repr(C, packed)]
pub struct RsdpV2Tag {
typ: u32,
size: u32,
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
_rsdt_address: u32,
length: u32,
xsdt_address: u64, // This is the PHYSICAL address of the XSDT
ext_checksum: u8,
_reserved: [u8; 3],
}

impl RsdpV2Tag {
pub fn signature<'a>(&'a self) -> Option<&'a str> {
str::from_utf8(&self.signature).ok()
}

pub fn checksum(&self) -> u8 {
self.checksum
}

pub fn oem_id<'a>(&'a self) -> Option<&'a str> {
str::from_utf8(&self.oem_id).ok()
}

pub fn revision(&self) -> u8 {
self.revision
}

pub fn xsdt_address(&self) -> usize {
self.xsdt_address as usize
}

pub fn ext_checksum(&self) -> u8 {
self.ext_checksum
}
}