pci_core/capabilities/
read_only.rs1use super::PciCapability;
7use crate::spec::caps::CapabilityId;
8use chipset_device::pci::ByteEnabledDwordRead;
9use chipset_device::pci::ByteEnabledDwordWrite;
10use inspect::Inspect;
11use std::fmt::Debug;
12use zerocopy::Immutable;
13use zerocopy::IntoBytes;
14use zerocopy::KnownLayout;
15
16#[derive(Debug)]
18pub struct ReadOnlyCapability<T> {
19 label: String,
20 capability_id: CapabilityId,
21 data: T,
22}
23
24impl<T: IntoBytes + Immutable + KnownLayout> ReadOnlyCapability<T> {
25 pub fn new(label: impl Into<String>, data: T) -> Self {
27 Self {
28 label: label.into(),
29 capability_id: CapabilityId::VENDOR_SPECIFIC,
30 data,
31 }
32 }
33
34 pub fn new_with_capability_id(
36 label: impl Into<String>,
37 capability_id: CapabilityId,
38 data: T,
39 ) -> Self {
40 Self {
41 label: label.into(),
42 capability_id,
43 data,
44 }
45 }
46}
47
48impl<T: Debug> Inspect for ReadOnlyCapability<T> {
49 fn inspect(&self, req: inspect::Request<'_>) {
50 req.respond()
51 .field("label", &self.label)
52 .field("capability_id", format!("0x{:02X}", self.capability_id.0))
53 .display_debug("data", &self.data);
54 }
55}
56
57impl<T> PciCapability for ReadOnlyCapability<T>
58where
59 T: IntoBytes + Send + Sync + Debug + Immutable + KnownLayout + 'static,
60{
61 fn label(&self) -> &str {
62 &self.label
63 }
64
65 fn capability_id(&self) -> CapabilityId {
66 self.capability_id
67 }
68
69 fn len(&self) -> usize {
70 size_of::<T>()
71 }
72
73 fn read(&self, offset: u16, mut value: ByteEnabledDwordRead<'_>) {
74 let dword_value = if offset as usize + 4 <= self.len() {
75 let offset = offset.into();
76 u32::from_ne_bytes(self.data.as_bytes()[offset..offset + 4].try_into().unwrap())
77 } else {
78 !0
79 };
80 value.set(dword_value);
81 }
82
83 fn write(&mut self, offset: u16, val: ByteEnabledDwordWrite) {
84 tracelimit::warn_ratelimited!(
85 label = ?self.label,
86 ?offset,
87 ?val,
88 "write to read-only capability"
89 );
90 }
91
92 fn reset(&mut self) {}
93}
94
95mod save_restore {
96 use super::*;
97 use vmcore::save_restore::NoSavedState;
98 use vmcore::save_restore::RestoreError;
99 use vmcore::save_restore::SaveError;
100 use vmcore::save_restore::SaveRestore;
101
102 impl<T> SaveRestore for ReadOnlyCapability<T> {
104 type SavedState = NoSavedState;
105
106 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
107 Ok(NoSavedState)
108 }
109
110 fn restore(&mut self, NoSavedState: Self::SavedState) -> Result<(), RestoreError> {
111 Ok(())
112 }
113 }
114}