From 4486c14218a81425fbd86e1f4516ff8dec8f8db6 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Thu, 3 May 2018 23:26:24 +0100 Subject: [PATCH 1/2] Add support for RSDP tags --- src/lib.rs | 19 +++++++++++ src/rsdp.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/rsdp.rs diff --git a/src/lib.rs b/src/lib.rs index 3e7daa0b..9be69cf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; @@ -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) { @@ -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 } } @@ -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()); diff --git a/src/rsdp.rs b/src/rsdp.rs new file mode 100644 index 00000000..643a1127 --- /dev/null +++ b/src/rsdp.rs @@ -0,0 +1,90 @@ +/// 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 + _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 + } +} From 48db281fa3b7969020711d83cd21e14c8ea6f10e Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Sat, 5 May 2018 13:20:39 +0100 Subject: [PATCH 2/2] Fix RsdpV2Tag representation --- src/rsdp.rs | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/rsdp.rs b/src/rsdp.rs index 643a1127..ca45a953 100644 --- a/src/rsdp.rs +++ b/src/rsdp.rs @@ -21,28 +21,23 @@ pub struct RsdpV1Tag { } impl RsdpV1Tag { - pub fn signature<'a>(&'a self) -> Option<&'a str> - { + pub fn signature<'a>(&'a self) -> Option<&'a str> { str::from_utf8(&self.signature).ok() } - pub fn checksum(&self) -> u8 - { + pub fn checksum(&self) -> u8 { self.checksum } - pub fn oem_id<'a>(&'a self) -> Option<&'a str> - { + pub fn oem_id<'a>(&'a self) -> Option<&'a str> { str::from_utf8(&self.oem_id).ok() } - pub fn revision(&self) -> u8 - { + pub fn revision(&self) -> u8 { self.revision } - pub fn rsdt_address(&self) -> usize - { + pub fn rsdt_address(&self) -> usize { self.rsdt_address as usize } } @@ -59,32 +54,32 @@ pub struct RsdpV2Tag { _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> - { + pub fn signature<'a>(&'a self) -> Option<&'a str> { str::from_utf8(&self.signature).ok() } - pub fn checksum(&self) -> u8 - { + pub fn checksum(&self) -> u8 { self.checksum } - pub fn oem_id<'a>(&'a self) -> Option<&'a str> - { + pub fn oem_id<'a>(&'a self) -> Option<&'a str> { str::from_utf8(&self.oem_id).ok() } - pub fn revision(&self) -> u8 - { + pub fn revision(&self) -> u8 { self.revision } - pub fn xsdt_address(&self) -> usize - { + pub fn xsdt_address(&self) -> usize { self.xsdt_address as usize } + + pub fn ext_checksum(&self) -> u8 { + self.ext_checksum + } }