pci_core/capabilities/
read_only.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! A generic, read-only PCI Capability (backed by an [`IntoBytes`] type).
5
6use super::PciCapability;
7use inspect::Inspect;
8use std::fmt::Debug;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11use zerocopy::KnownLayout;
12
13/// Helper to define a read-only [`PciCapability`] from an [`IntoBytes`] type.
14#[derive(Debug)]
15pub struct ReadOnlyCapability<T> {
16    label: String,
17    data: T,
18}
19
20impl<T: IntoBytes + Immutable + KnownLayout> ReadOnlyCapability<T> {
21    /// Create a new [`ReadOnlyCapability`]
22    pub fn new(label: impl Into<String>, data: T) -> Self {
23        Self {
24            label: label.into(),
25            data,
26        }
27    }
28}
29
30impl<T: Debug> Inspect for ReadOnlyCapability<T> {
31    fn inspect(&self, req: inspect::Request<'_>) {
32        req.respond()
33            .field("label", &self.label)
34            .display_debug("data", &self.data);
35    }
36}
37
38impl<T> PciCapability for ReadOnlyCapability<T>
39where
40    T: IntoBytes + Send + Sync + Debug + Immutable + KnownLayout,
41{
42    fn label(&self) -> &str {
43        &self.label
44    }
45
46    fn len(&self) -> usize {
47        size_of::<T>()
48    }
49
50    fn read_u32(&self, offset: u16) -> u32 {
51        if offset as usize + 4 <= self.len() {
52            let offset = offset.into();
53            u32::from_ne_bytes(self.data.as_bytes()[offset..offset + 4].try_into().unwrap())
54        } else {
55            !0
56        }
57    }
58
59    fn write_u32(&mut self, offset: u16, val: u32) {
60        tracelimit::warn_ratelimited!(
61            label = ?self.label,
62            ?offset,
63            ?val,
64            "write to read-only capability"
65        );
66    }
67
68    fn reset(&mut self) {}
69}
70
71mod save_restore {
72    use super::*;
73    use vmcore::save_restore::NoSavedState;
74    use vmcore::save_restore::RestoreError;
75    use vmcore::save_restore::SaveError;
76    use vmcore::save_restore::SaveRestore;
77
78    // This is a noop impl, as the capability is (by definition) read only.
79    impl<T> SaveRestore for ReadOnlyCapability<T> {
80        type SavedState = NoSavedState;
81
82        fn save(&mut self) -> Result<Self::SavedState, SaveError> {
83            Ok(NoSavedState)
84        }
85
86        fn restore(&mut self, NoSavedState: Self::SavedState) -> Result<(), RestoreError> {
87            Ok(())
88        }
89    }
90}