Skip to content

Commit 3522768

Browse files
committed
uefi: Make PciIoAddress orderable
1 parent 70a63b8 commit 3522768

File tree

1 file changed

+53
-2
lines changed

1 file changed

+53
-2
lines changed

uefi/src/proto/pci/mod.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
//! PCI Bus specific protocols.
44
5+
use core::cmp::Ordering;
6+
57
use uefi_raw::protocol::pci::root_bridge::PciRootBridgeIoProtocolWidth;
68

79
pub mod root_bridge;
810

911
/// IO Address for PCI/register IO operations
1012
#[repr(C, packed)]
11-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1214
pub struct PciIoAddress {
1315
/// Register number within the PCI device.
1416
pub reg: u8,
@@ -54,9 +56,37 @@ impl PciIoAddress {
5456
}
5557
}
5658

59+
impl From<u64> for PciIoAddress {
60+
fn from(value: u64) -> Self {
61+
let raw = value.to_ne_bytes();
62+
Self {
63+
reg: raw[0],
64+
fun: raw[1],
65+
dev: raw[2],
66+
bus: raw[3],
67+
ext_reg: u32::from_ne_bytes([raw[4], raw[5], raw[6], raw[7]]),
68+
}
69+
}
70+
}
71+
5772
impl From<PciIoAddress> for u64 {
5873
fn from(value: PciIoAddress) -> Self {
59-
unsafe { core::mem::transmute(value) }
74+
let ereg = value.ext_reg.to_ne_bytes();
75+
u64::from_ne_bytes([
76+
value.reg, value.fun, value.dev, value.bus, ereg[0], ereg[1], ereg[2], ereg[3],
77+
])
78+
}
79+
}
80+
81+
impl PartialOrd for PciIoAddress {
82+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
83+
Some(self.cmp(other))
84+
}
85+
}
86+
87+
impl Ord for PciIoAddress {
88+
fn cmp(&self, other: &Self) -> Ordering {
89+
u64::from(*self).cmp(&u64::from(*other))
6090
}
6191
}
6292

@@ -95,3 +125,24 @@ fn encode_io_mode_and_unit<U: PciIoUnit>(mode: PciIoMode) -> PciRootBridgeIoProt
95125
_ => unreachable!("Illegal PCI IO-Mode / Unit combination"),
96126
}
97127
}
128+
129+
#[cfg(test)]
130+
mod tests {
131+
use super::PciIoAddress;
132+
use core::mem;
133+
134+
#[test]
135+
fn test_pci_ioaddr_raw_conversion() {
136+
assert_eq!(mem::size_of::<u64>(), mem::size_of::<PciIoAddress>());
137+
let srcaddr = PciIoAddress {
138+
reg: 0x11,
139+
fun: 0x33,
140+
dev: 0x55,
141+
bus: 0x77,
142+
ext_reg: 0x99bbddff,
143+
};
144+
let rawaddr: u64 = srcaddr.into();
145+
let dstaddr = PciIoAddress::from(rawaddr);
146+
assert_eq!(srcaddr, dstaddr);
147+
}
148+
}

0 commit comments

Comments
 (0)