Skip to content

Commit 80cf2f8

Browse files
seijikuntmvkrpxl0
authored andcommitted
uefi: Make PciIoAddress orderable
1 parent 048e27d commit 80cf2f8

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

uefi/src/proto/pci/mod.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
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 buffer;
@@ -10,7 +12,7 @@ pub mod root_bridge;
1012

1113
/// IO Address for PCI/register IO operations
1214
#[repr(C, packed)]
13-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1416
pub struct PciIoAddress {
1517
/// Register number within the PCI device.
1618
pub reg: u8,
@@ -56,9 +58,37 @@ impl PciIoAddress {
5658
}
5759
}
5860

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

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

0 commit comments

Comments
 (0)