use crate::TagType;
use crate::tag::TagHeader;
#[cfg(feature = "builder")]
use core::mem::size_of;
use core::slice;
use core::str;
use core::str::Utf8Error;
use multiboot2_common::{MaybeDynSized, Tag};
const RSDPV1_LENGTH: usize = 20;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, align(8))]
pub struct RsdpV1Tag {
header: TagHeader,
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
rsdt_address: u32, }
impl RsdpV1Tag {
pub const SIGNATURE: [u8; 8] = *b"RSD PTR ";
const BASE_SIZE: usize = size_of::<TagHeader>() + 16 + 4;
#[must_use]
pub fn new(checksum: u8, oem_id: [u8; 6], revision: u8, rsdt_address: u32) -> Self {
Self {
header: TagHeader::new(Self::ID, Self::BASE_SIZE as u32),
signature: Self::SIGNATURE,
checksum,
oem_id,
revision,
rsdt_address,
}
}
pub const fn signature(&self) -> Result<&str, Utf8Error> {
str::from_utf8(&self.signature)
}
#[must_use]
pub fn checksum_is_valid(&self) -> bool {
let bytes =
unsafe { slice::from_raw_parts(self as *const _ as *const u8, RSDPV1_LENGTH + 8) };
bytes[8..]
.iter()
.fold(0u8, |acc, val| acc.wrapping_add(*val))
== 0
}
pub const fn oem_id(&self) -> Result<&str, Utf8Error> {
str::from_utf8(&self.oem_id)
}
#[must_use]
pub const fn revision(&self) -> u8 {
self.revision
}
#[must_use]
pub const fn rsdt_address(&self) -> usize {
self.rsdt_address as usize
}
}
impl MaybeDynSized for RsdpV1Tag {
type Header = TagHeader;
const BASE_SIZE: usize = size_of::<Self>();
fn dst_len(_: &TagHeader) {}
}
impl Tag for RsdpV1Tag {
type IDType = TagType;
const ID: TagType = TagType::AcpiV1;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, align(8))]
pub struct RsdpV2Tag {
header: TagHeader,
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
rsdt_address: u32,
length: u32,
xsdt_address: u64,
ext_checksum: u8,
_reserved: [u8; 3],
}
impl RsdpV2Tag {
pub const SIGNATURE: [u8; 8] = *b"RSD PTR ";
const BASE_SIZE: usize =
size_of::<TagHeader>() + 16 + 2 * size_of::<u32>() + size_of::<u64>() + 4;
#[allow(clippy::too_many_arguments)]
#[must_use]
pub fn new(
checksum: u8,
oem_id: [u8; 6],
revision: u8,
rsdt_address: u32,
length: u32,
xsdt_address: u64,
ext_checksum: u8,
) -> Self {
Self {
header: TagHeader::new(Self::ID, Self::BASE_SIZE as u32),
signature: Self::SIGNATURE,
checksum,
oem_id,
revision,
rsdt_address,
length,
xsdt_address,
ext_checksum,
_reserved: [0; 3],
}
}
pub const fn signature(&self) -> Result<&str, Utf8Error> {
str::from_utf8(&self.signature)
}
#[must_use]
pub fn checksum_is_valid(&self) -> bool {
let bytes = unsafe {
slice::from_raw_parts(self as *const _ as *const u8, self.length as usize + 8)
};
bytes[8..]
.iter()
.fold(0u8, |acc, val| acc.wrapping_add(*val))
== 0
}
pub const fn oem_id(&self) -> Result<&str, Utf8Error> {
str::from_utf8(&self.oem_id)
}
#[must_use]
pub const fn revision(&self) -> u8 {
self.revision
}
#[must_use]
pub const fn xsdt_address(&self) -> usize {
self.xsdt_address as usize
}
#[must_use]
pub const fn ext_checksum(&self) -> u8 {
self.ext_checksum
}
}
impl MaybeDynSized for RsdpV2Tag {
type Header = TagHeader;
const BASE_SIZE: usize = size_of::<Self>();
fn dst_len(_: &TagHeader) {}
}
impl Tag for RsdpV2Tag {
type IDType = TagType;
const ID: TagType = TagType::AcpiV2;
}