firmware_uefi_resources/
lib.rs1#![forbid(unsafe_code)]
13#![expect(missing_docs)]
14
15pub use firmware_uefi_custom_vars::BaseTemplate;
16pub use firmware_uefi_custom_vars::UefiVarsDeltaJson;
17pub use hcl_compat_uefi_nvram_resources::HclCompatNvramQuirks;
18pub use hyperv_secure_boot_templates::aarch64 as aarch64_secure_boot_templates;
19pub use hyperv_secure_boot_templates::x64 as x64_secure_boot_templates;
20
21use chipset_resources::CmosRtcTimeSourceHandleKind;
22use inspect::Inspect;
23use mesh::MeshPayload;
24use mesh_protobuf::Protobuf;
25use std::borrow::Cow;
26use uefi_specs::hyperv::debug_level::DEBUG_ERROR;
27use uefi_specs::hyperv::debug_level::DEBUG_FLAG_NAMES;
28use uefi_specs::hyperv::debug_level::DEBUG_INFO;
29use uefi_specs::hyperv::debug_level::DEBUG_WARN;
30use vm_resource::CanResolveTo;
31use vm_resource::Resource;
32use vm_resource::ResourceId;
33use vm_resource::ResourceKind;
34use vm_resource::kind::ChipsetDeviceHandleKind;
35use vm_resource::kind::NonVolatileStoreKind;
36use watchdog_core::platform::WatchdogPlatform;
37
38pub mod platform {
46 #[derive(Debug)]
48 pub enum UefiEvent {
49 BootSuccess(BootInfo),
50 BootFailure(BootInfo),
51 NoBootDevice,
52 }
53
54 #[derive(Debug)]
56 pub struct BootInfo {
57 pub secure_boot_succeeded: bool,
58 }
59
60 pub trait UefiLogger: Send {
62 fn log_event(&self, event: UefiEvent);
63 }
64
65 pub trait VsmConfig: Send {
68 fn revoke_guest_vsm(&self);
69 }
70}
71
72#[derive(Debug, Inspect, PartialEq, Clone, Protobuf)]
74pub enum UefiCommandSet {
75 X64,
76 Aarch64,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Protobuf)]
82#[mesh(transparent)]
83pub struct LogLevel(u32);
84
85impl LogLevel {
86 pub const fn make_default() -> Self {
88 Self(DEBUG_ERROR | DEBUG_WARN)
89 }
90
91 pub const fn make_info() -> Self {
93 Self(DEBUG_ERROR | DEBUG_WARN | DEBUG_INFO)
94 }
95
96 pub const fn make_full() -> Self {
98 Self(u32::MAX)
99 }
100
101 pub fn should_log(self, raw_debug_level: u32) -> bool {
104 if self.0 == u32::MAX {
105 true
106 } else {
107 (raw_debug_level & self.0) != 0
108 }
109 }
110
111 pub fn as_u32(self) -> u32 {
113 self.0
114 }
115}
116
117impl Default for LogLevel {
118 fn default() -> Self {
119 Self::make_default()
120 }
121}
122
123impl Inspect for LogLevel {
124 fn inspect(&self, req: inspect::Request<'_>) {
125 let human_readable = debug_level_to_string(self.0);
126 req.respond()
127 .field("raw_value", self.0)
128 .field("debug_levels", human_readable.as_ref());
129 }
130}
131
132pub fn debug_level_to_string(debug_level: u32) -> Cow<'static, str> {
134 if debug_level.count_ones() == 1 {
135 if let Some(&(_, name)) = DEBUG_FLAG_NAMES
136 .iter()
137 .find(|&&(flag, _)| flag == debug_level)
138 {
139 return Cow::Borrowed(name);
140 }
141 }
142
143 let flags: Vec<&str> = DEBUG_FLAG_NAMES
144 .iter()
145 .filter(|&&(flag, _)| debug_level & flag != 0)
146 .map(|&(_, name)| name)
147 .collect();
148
149 if flags.is_empty() {
150 Cow::Borrowed("UNKNOWN")
151 } else {
152 Cow::Owned(flags.join("+"))
153 }
154}
155
156#[derive(Clone, Protobuf)]
158pub struct UefiConfig {
159 pub base_template: Option<BaseTemplate>,
160 pub custom_uefi_json: Option<UefiVarsDeltaJson>,
161 pub secure_boot: bool,
162 pub initial_generation_id: [u8; 16],
163 pub use_mmio: bool,
164 pub command_set: UefiCommandSet,
165 pub diagnostics_log_level: LogLevel,
166 pub diagnostics_rate_limit: Option<u32>,
167}
168
169pub enum UefiLoggerHandleKind {}
171
172impl ResourceKind for UefiLoggerHandleKind {
173 const NAME: &'static str = "uefi_logger";
174}
175
176pub struct ResolvedUefiLogger(pub Box<dyn platform::UefiLogger>);
178
179impl CanResolveTo<ResolvedUefiLogger> for UefiLoggerHandleKind {
180 type Input<'a> = ();
181}
182
183pub enum UefiWatchdogPlatformHandleKind {}
185
186impl ResourceKind for UefiWatchdogPlatformHandleKind {
187 const NAME: &'static str = "uefi_watchdog_platform";
188}
189
190pub struct ResolvedUefiWatchdogPlatform {
193 pub platform: Box<dyn WatchdogPlatform>,
194 pub watchdog_recv: mesh::Receiver<()>,
195}
196
197impl CanResolveTo<ResolvedUefiWatchdogPlatform> for UefiWatchdogPlatformHandleKind {
198 type Input<'a> = &'a ();
199}
200
201pub enum UefiVsmConfigHandleKind {}
203
204impl ResourceKind for UefiVsmConfigHandleKind {
205 const NAME: &'static str = "uefi_vsm_config";
206}
207
208pub struct ResolvedUefiVsmConfig(pub Box<dyn platform::VsmConfig>);
210
211impl CanResolveTo<ResolvedUefiVsmConfig> for UefiVsmConfigHandleKind {
212 type Input<'a> = ();
213}
214
215#[derive(MeshPayload)]
217pub struct UefiDeviceHandle {
218 pub config: UefiConfig,
220 pub storage_quirks: Option<HclCompatNvramQuirks>,
222 pub generation_id_recv: mesh::Receiver<[u8; 16]>,
224 pub logger: Resource<UefiLoggerHandleKind>,
226 pub nvram_storage: Resource<NonVolatileStoreKind>,
228 pub watchdog_platform: Resource<UefiWatchdogPlatformHandleKind>,
231 pub vsm_config: Option<Resource<UefiVsmConfigHandleKind>>,
234 pub time_source: Resource<CmosRtcTimeSourceHandleKind>,
236}
237
238impl ResourceId<ChipsetDeviceHandleKind> for UefiDeviceHandle {
239 const ID: &'static str = "hyperv_firmware_uefi";
240}