1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Memory Device Mapped Address (Type 20)
//!
//! This structure maps memory address space usually to a device-level granularity.\
//! One structure is present for each contiguous address range described.
use crate::{
InfoType,
MalformedStructureError::{self, InvalidFormattedSectionLength},
RawStructure,
};
/// Main struct for *Memory Device Mapped Address (Type 20)*
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct MemoryDeviceMappedAddress {
/// Specifies the structure’s handle
pub handle: u16,
/// Physical address, in kilobytes, of a range of memory mapped to the referenced Memory
/// Device.\
/// When the field value is FFFF FFFFh the actual address is stored in the Extended Starting
/// Address field. When this field contains a valid address, Ending Address must also contain a
/// valid address. When this field contains FFFF FFFFh, Ending Address must also contain FFFF
/// FFFFh.
pub starting_address: u32,
/// Physical ending address of the last kilobyte of a range of addresses mapped to the
/// referenced Memory Device.\
/// When the field value is FFFF FFFFh the actual address is stored in the Extended Ending
/// Address field. When this field contains a valid address, Starting Address must also contain
/// a valid address.
pub ending_address: u32,
/// Handle, or instance number, associated with the Memory Device structure to which this
/// address range is mapped.\
/// Multiple address ranges can be mapped to a single Memory Device.
pub memory_device_handle: u16,
/// Handle, or instance number, associated with the Memory Array Mapped Address structure to
/// which this device address range is mapped.\
/// Multiple address ranges can be mapped to a single Memory Array Mapped Address.
pub memory_array_mapped_address_handle: u16,
/// Position of the referenced Memory Device in a row of the address partition.\
/// For example, if two 8-bit devices form a 16-bit row, this field’s value is either 1 or 2.\
/// The value 0 is reserved. If the position is unknown, the field contains FFh.
pub partition_row_position: u8,
/// Position of the referenced Memory Device in an interleave.\
/// The value 0 indicates non-interleaved, 1 indicates first interleave position, 2 the second
/// interleave position, and so on. If the position is unknown, the field contains FFh.
pub interleave_position: u8,
/// Maximum number of consecutive rows from the referenced Memory Device that are accessed in a
/// single interleaved transfer.\
/// If the device is not part of an interleave, the field contains 0; if the interleave
/// configuration is unknown, the value is FFh.
pub interleaved_data_depth: u8,
/// Physical address, in bytes, of a range of memory mapped to the referenced Memory Device.\
/// This field is valid when Starting Address contains the value FFFF FFFFh. If Starting
/// Address contains a value other than FFFF FFFFh, this field contains zeros. When this field
/// contains a valid address, Extended Ending Address must also contain a valid address.
pub extended_starting_address: Option<u64>,
/// Physical ending address, in bytes, of the last of a range of addresses mapped to the
/// referenced Memory Device.\
/// This field is valid when both Starting Address and Ending Address contain the value FFFF
/// FFFFh. If Ending Address contains a value other than FFFF FFFFh, this field contains zeros.
/// When this field contains a valid address, Extended Starting Address must also contain a
/// valid address.
pub extended_ending_address: Option<u64>,
}
impl<'a> MemoryDeviceMappedAddress {
pub(crate) fn try_from(structure: RawStructure<'a>) -> Result<Self, MalformedStructureError> {
let handle = structure.handle;
match (structure.version.major, structure.version.minor) {
v if ((2, 1)..(2, 7)).contains(&v) && structure.length != 0x13 => Err(InvalidFormattedSectionLength(
InfoType::MemoryDeviceMappedAddress,
handle,
"",
0x13,
)),
v if v >= (2, 7) && structure.length != 0x23 => Err(InvalidFormattedSectionLength(
InfoType::MemoryDeviceMappedAddress,
handle,
"",
0x23,
)),
_ => Ok(Self {
handle,
starting_address: structure.get::<u32>(0x04)?,
ending_address: structure.get::<u32>(0x08)?,
memory_device_handle: structure.get::<u16>(0x0C)?,
memory_array_mapped_address_handle: structure.get::<u16>(0x0E)?,
partition_row_position: structure.get::<u8>(0x10)?,
interleave_position: structure.get::<u8>(0x11)?,
interleaved_data_depth: structure.get::<u8>(0x12)?,
extended_starting_address: structure.get::<u64>(0x13).ok(),
extended_ending_address: structure.get::<u64>(0x1B).ok(),
}),
}
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq as pretty_assert_eq;
use std::prelude::v1::*;
#[test]
fn memory_device_mapped_address() {
use super::*;
use crate::{InfoType, RawStructure};
let length = 35;
let (data, strings) =
include_bytes!("../../tests/data/02daadcd/entries/20-0/bin")[4..].split_at(length as usize - 4);
let structure = RawStructure {
version: (2, 7).into(),
info: InfoType::MemoryDeviceMappedAddress,
length,
handle: 0x0029,
data,
strings,
};
let sample = MemoryDeviceMappedAddress {
handle: 0x0029,
starting_address: 0,
ending_address: 0xFFFFFF,
memory_device_handle: 0x0028,
memory_array_mapped_address_handle: 0x0027,
partition_row_position: 0,
interleave_position: 0xFF,
interleaved_data_depth: 0xFF,
extended_starting_address: Some(0),
extended_ending_address: Some(0),
};
let result = MemoryDeviceMappedAddress::try_from(structure).unwrap();
pretty_assert_eq!(sample, result, "MemoryDeviceMappedAddress");
}
}