use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P10, P3, P4, P5, P9};
use super::CapabilityDataError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FlatteningPortalBridge {
pub reserved: u16,
pub fpb_capabilities: FpbCapabilities,
pub fpb_rid_vector_control: FpbRidVectorControl,
pub fpb_mem_low_vector_control: FpbMemLowVectorControl,
pub fpb_mem_high_vector_control: FpbMemHighVectorControl,
pub fpb_vector_access_control: FpbVectorAccessControl,
pub fpb_vector_access_data: u32,
}
impl FlatteningPortalBridge {
pub const SIZE: usize = 2 + 8 * 4;
}
impl TryFrom<&[u8]> for FlatteningPortalBridge {
type Error = CapabilityDataError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
slice
.try_into()
.map(|Seq { head, .. }| From::<[u8; Self::SIZE]>::from(head))
.map_err(|_| CapabilityDataError {
name: "Flattening Portal Bridge",
size: Self::SIZE,
})
}
}
impl From<[u8; Self::SIZE]> for FlatteningPortalBridge {
fn from(bytes: [u8; Self::SIZE]) -> Self {
let Le((
reserved,
capabilities,
rid_vector_control_1,
rid_vector_control_2,
mem_low_vector_control,
mem_high_vector_control_1,
mem_high_vector_control_2,
vector_access_control,
fpb_vector_access_data,
)) = P9(bytes).into();
Self {
reserved,
fpb_capabilities: From::<u32>::from(capabilities),
fpb_rid_vector_control: FpbRidVectorControl::new(
rid_vector_control_1,
rid_vector_control_2,
),
fpb_mem_low_vector_control: From::<u32>::from(mem_low_vector_control),
fpb_mem_high_vector_control: FpbMemHighVectorControl::new(
mem_high_vector_control_1,
mem_high_vector_control_2,
),
fpb_vector_access_control: From::<u32>::from(vector_access_control),
fpb_vector_access_data,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FpbCapabilities {
pub fpb_rid_decode_mechanism_supported: bool,
pub fpb_mem_low_decode_mechanism_supported: bool,
pub fpb_mem_high_decode_mechanism_supported: bool,
pub fpb_num_sec_dev: u8,
pub fpb_rid_vector_size_supported: FpbRidVectorSizeSupported,
pub fpb_mem_low_vector_size_supported: FpbMemLowVectorSizeSupported,
pub fpb_mem_high_vector_size_supported: FpbMemHighVectorSizeSupported,
}
impl From<u32> for FpbCapabilities {
fn from(dword: u32) -> Self {
let Lsb((
fpb_rid_decode_mechanism_supported,
fpb_mem_low_decode_mechanism_supported,
fpb_mem_high_decode_mechanism_supported,
fpb_num_sec_dev,
rid,
(),
mem_low,
(),
mem_high,
(),
)) = P10::<_, 1, 1, 1, 5, 3, 5, 3, 5, 3, 5>(dword).into();
Self {
fpb_rid_decode_mechanism_supported,
fpb_mem_low_decode_mechanism_supported,
fpb_mem_high_decode_mechanism_supported,
fpb_num_sec_dev,
fpb_rid_vector_size_supported: From::<u8>::from(rid),
fpb_mem_low_vector_size_supported: From::<u8>::from(mem_low),
fpb_mem_high_vector_size_supported: From::<u8>::from(mem_high),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbRidVectorSizeSupported {
Size256bits,
Size1Kbits,
Size8kbits,
Reserved(u8),
}
impl From<u8> for FpbRidVectorSizeSupported {
fn from(byte: u8) -> Self {
match byte {
0b000 => Self::Size256bits,
0b010 => Self::Size1Kbits,
0b101 => Self::Size8kbits,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbMemLowVectorSizeSupported {
Size256bits,
Size512bits,
Size1Kbits,
Size2Kbits,
Size4Kbits,
Reserved(u8),
}
impl From<u8> for FpbMemLowVectorSizeSupported {
fn from(byte: u8) -> Self {
match byte {
0b000 => Self::Size256bits,
0b001 => Self::Size512bits,
0b010 => Self::Size1Kbits,
0b011 => Self::Size2Kbits,
0b100 => Self::Size4Kbits,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbMemHighVectorSizeSupported {
Size256bits,
Size512bits,
Size1Kbits,
Size2Kbits,
Size4Kbits,
Size8Kbits,
Reserved(u8),
}
impl From<u8> for FpbMemHighVectorSizeSupported {
fn from(byte: u8) -> Self {
match byte {
0b000 => Self::Size256bits,
0b001 => Self::Size512bits,
0b010 => Self::Size1Kbits,
0b011 => Self::Size2Kbits,
0b100 => Self::Size4Kbits,
0b101 => Self::Size8Kbits,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FpbRidVectorControl {
pub fpb_rid_decode_mechanism_enable: bool,
pub fpb_rid_vector_granularity: FpbRidVectorGranularity,
pub fpb_rid_vector_start: u16,
pub rid_secondary_start: u16,
}
impl FpbRidVectorControl {
fn new(control_1: u32, control_2: u32) -> Self {
let Lsb((fpb_rid_decode_mechanism_enable, (), granularity, (), start)) =
P5::<_, 1, 3, 4, 11, 13>(control_1).into();
let _: u16 = start;
let Lsb(((), rid_secondary_start, ())) = P3::<_, 3, 13, 16>(control_2).into();
Self {
fpb_rid_decode_mechanism_enable,
fpb_rid_vector_granularity: From::<u8>::from(granularity),
fpb_rid_vector_start: (start << 3) & u16::MAX.wrapping_shl(3 + granularity as u32),
rid_secondary_start,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbRidVectorGranularity {
Granularity8RIDs,
Granularity64RIDs,
Granularity256RIDs,
Reserved(u8),
}
impl From<u8> for FpbRidVectorGranularity {
fn from(byte: u8) -> Self {
match byte {
0b0000 => Self::Granularity8RIDs,
0b0011 => Self::Granularity64RIDs,
0b0101 => Self::Granularity256RIDs,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FpbMemLowVectorControl {
pub fpb_mem_low_decode_mechanism_enable: bool,
pub fpb_mem_low_vector_granularity: FpbMemLowVectorGranularity,
pub fpb_mem_low_vector_start: u32,
}
impl From<u32> for FpbMemLowVectorControl {
fn from(dword: u32) -> Self {
let Lsb((fpb_mem_low_decode_mechanism_enable, (), granularity, (), start)) =
P5::<_, 1, 3, 4, 12, 12>(dword).into();
let _: u32 = start;
Self {
fpb_mem_low_decode_mechanism_enable,
fpb_mem_low_vector_granularity: From::<u8>::from(granularity),
fpb_mem_low_vector_start: (start << 20)
& u32::MAX.wrapping_shl(20 + granularity as u32),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbMemLowVectorGranularity {
Granularity1MB,
Granularity2MB,
Granularity4MB,
Granularity8MB,
Granularity16MB,
Reserved(u8),
}
impl From<u8> for FpbMemLowVectorGranularity {
fn from(byte: u8) -> Self {
match byte {
0b0000 => Self::Granularity1MB,
0b0001 => Self::Granularity2MB,
0b0010 => Self::Granularity4MB,
0b0011 => Self::Granularity8MB,
0b0100 => Self::Granularity16MB,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FpbMemHighVectorControl {
pub fpb_mem_high_decode_mechanism_enable: bool,
pub fpb_mem_high_vector_granularity: FpbMemHighVectorGranularity,
pub fpb_mem_high_vector_start: u64,
}
impl FpbMemHighVectorControl {
pub fn new(control_1: u32, control_2: u32) -> Self {
let Lsb((fpb_mem_high_decode_mechanism_enable, (), granularity, (), start)) =
P5::<_, 1, 3, 4, 20, 4>(control_1).into();
let _: u64 = start;
let start_low = start << 28;
let start_high = (control_2 as u64) << 32;
let mask = u64::MAX.wrapping_shl(28 + granularity as u32);
Self {
fpb_mem_high_decode_mechanism_enable,
fpb_mem_high_vector_granularity: From::<u8>::from(granularity),
fpb_mem_high_vector_start: (start_low | start_high) & mask,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbMemHighVectorGranularity {
Granularity256MB,
Granularity512MB,
Granularity1GB,
Granularity2GB,
Granularity4GB,
Granularity8GB,
Granularity16GB,
Granularity32GB,
Reserved(u8),
}
impl From<u8> for FpbMemHighVectorGranularity {
fn from(byte: u8) -> Self {
match byte {
0b0000 => Self::Granularity256MB,
0b0001 => Self::Granularity512MB,
0b0010 => Self::Granularity1GB,
0b0011 => Self::Granularity2GB,
0b0100 => Self::Granularity4GB,
0b0101 => Self::Granularity8GB,
0b0110 => Self::Granularity16GB,
0b0111 => Self::Granularity32GB,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FpbVectorAccessControl {
pub fpb_vector_access_offset: u8,
pub fpb_vector_select: FpbVectorSelect,
}
impl From<u32> for FpbVectorAccessControl {
fn from(dword: u32) -> Self {
let Lsb((fpb_vector_access_offset, (), select, ())) = P4::<_, 8, 6, 2, 16>(dword).into();
Self {
fpb_vector_access_offset,
fpb_vector_select: From::<u8>::from(select),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FpbVectorSelect {
Rid,
MemLow,
MemHigh,
Reserved,
}
impl From<u8> for FpbVectorSelect {
fn from(byte: u8) -> Self {
match byte {
0b00 => Self::Rid,
0b01 => Self::MemLow,
0b10 => Self::MemHigh,
0b11 => Self::Reserved,
_ => unreachable!(),
}
}
}