1 //! UEFI services available at runtime, even after the OS boots.
2 
3 use crate::capsule::CapsuleHeader;
4 use crate::table::boot::MemoryDescriptor;
5 use crate::table::Header;
6 use crate::time::Time;
7 use crate::{guid, Char16, Guid, PhysicalAddress, Status};
8 use bitflags::bitflags;
9 use core::ffi::c_void;
10 
11 /// Table of pointers to all the runtime services.
12 ///
13 /// This table, and the function pointers it contains are valid even after the
14 /// UEFI OS loader and OS have taken control of the platform.
15 #[derive(Debug)]
16 #[repr(C)]
17 pub struct RuntimeServices {
18     pub header: Header,
19     pub get_time:
20         unsafe extern "efiapi" fn(time: *mut Time, capabilities: *mut TimeCapabilities) -> Status,
21     pub set_time: unsafe extern "efiapi" fn(time: *const Time) -> Status,
22     pub get_wakeup_time:
23         unsafe extern "efiapi" fn(enabled: *mut u8, pending: *mut u8, time: *mut Time) -> Status,
24     pub set_wakeup_time: unsafe extern "efiapi" fn(enable: u8, time: *const Time) -> Status,
25     pub set_virtual_address_map: unsafe extern "efiapi" fn(
26         map_size: usize,
27         desc_size: usize,
28         desc_version: u32,
29         virtual_map: *mut MemoryDescriptor,
30     ) -> Status,
31     pub convert_pointer:
32         unsafe extern "efiapi" fn(debug_disposition: usize, address: *mut *const c_void) -> Status,
33     pub get_variable: unsafe extern "efiapi" fn(
34         variable_name: *const Char16,
35         vendor_guid: *const Guid,
36         attributes: *mut VariableAttributes,
37         data_size: *mut usize,
38         data: *mut u8,
39     ) -> Status,
40     pub get_next_variable_name: unsafe extern "efiapi" fn(
41         variable_name_size: *mut usize,
42         variable_name: *mut u16,
43         vendor_guid: *mut Guid,
44     ) -> Status,
45     pub set_variable: unsafe extern "efiapi" fn(
46         variable_name: *const Char16,
47         vendor_guid: *const Guid,
48         attributes: VariableAttributes,
49         data_size: usize,
50         data: *const u8,
51     ) -> Status,
52     pub get_next_high_monotonic_count: unsafe extern "efiapi" fn(high_count: *mut u32) -> Status,
53     pub reset_system: unsafe extern "efiapi" fn(
54         rt: ResetType,
55         status: Status,
56         data_size: usize,
57         data: *const u8,
58     ) -> !,
59 
60     // UEFI 2.0 Capsule Services.
61     pub update_capsule: unsafe extern "efiapi" fn(
62         capsule_header_array: *const *const CapsuleHeader,
63         capsule_count: usize,
64         scatter_gather_list: PhysicalAddress,
65     ) -> Status,
66     pub query_capsule_capabilities: unsafe extern "efiapi" fn(
67         capsule_header_array: *const *const CapsuleHeader,
68         capsule_count: usize,
69         maximum_capsule_size: *mut u64,
70         reset_type: *mut ResetType,
71     ) -> Status,
72 
73     // Miscellaneous UEFI 2.0 Service.
74     pub query_variable_info: unsafe extern "efiapi" fn(
75         attributes: VariableAttributes,
76         maximum_variable_storage_size: *mut u64,
77         remaining_variable_storage_size: *mut u64,
78         maximum_variable_size: *mut u64,
79     ) -> Status,
80 }
81 
82 newtype_enum! {
83     #[derive(Default)]
84     /// The type of system reset.
85     pub enum ResetType: u32 => {
86         /// System-wide reset.
87         ///
88         /// This is analogous to power cycling the device.
89         COLD = 0,
90 
91         /// System-wide re-initialization.
92         ///
93         /// If the system doesn't support a warm reset, this will trigger a cold
94         /// reset.
95         WARM = 1,
96 
97         /// The system is powered off.
98         SHUTDOWN = 2,
99 
100         /// A platform-specific reset type.
101         PLATFORM_SPECIFIC = 3,
102     }
103 }
104 
105 /// Real time clock capabilities.
106 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
107 #[repr(C)]
108 pub struct TimeCapabilities {
109     /// Reporting resolution of the clock in counts per second. 1 for a normal
110     /// PC-AT CMOS RTC device, which reports the time with 1-second resolution.
111     pub resolution: u32,
112 
113     /// Timekeeping accuracy in units of 1e-6 parts per million.
114     pub accuracy: u32,
115 
116     /// Whether a time set operation clears the device's time below the
117     /// "resolution" reporting level. False for normal PC-AT CMOS RTC devices.
118     pub sets_to_zero: bool,
119 }
120 
121 bitflags! {
122     /// Flags describing the attributes of a variable.
123     #[repr(transparent)]
124     #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
125     pub struct VariableAttributes: u32 {
126         /// Variable is maintained across a power cycle.
127         const NON_VOLATILE = 0x01;
128 
129         /// Variable is accessible during the time that boot services are
130         /// accessible.
131         const BOOTSERVICE_ACCESS = 0x02;
132 
133         /// Variable is accessible during the time that runtime services are
134         /// accessible.
135         const RUNTIME_ACCESS = 0x04;
136 
137         /// Variable is stored in the portion of NVR allocated for error
138         /// records.
139         const HARDWARE_ERROR_RECORD = 0x08;
140 
141         /// Deprecated.
142         const AUTHENTICATED_WRITE_ACCESS = 0x10;
143 
144         /// Variable payload begins with an EFI_VARIABLE_AUTHENTICATION_2
145         /// structure.
146         const TIME_BASED_AUTHENTICATED_WRITE_ACCESS = 0x20;
147 
148         /// This is never set in the attributes returned by
149         /// `get_variable`. When passed to `set_variable`, the variable payload
150         /// will be appended to the current value of the variable if supported
151         /// by the firmware.
152         const APPEND_WRITE = 0x40;
153 
154         /// Variable payload begins with an EFI_VARIABLE_AUTHENTICATION_3
155         /// structure.
156         const ENHANCED_AUTHENTICATED_ACCESS = 0x80;
157     }
158 }
159 
160 newtype_enum! {
161     /// Variable vendor GUID. This serves as a namespace for variables to
162     /// avoid naming conflicts between vendors. The UEFI specification
163     /// defines some special values, and vendors will define their own.
164     pub enum VariableVendor: Guid => {
165         /// Used to access global variables.
166         GLOBAL_VARIABLE = guid!("8be4df61-93ca-11d2-aa0d-00e098032b8c"),
167 
168         /// Used to access EFI signature database variables.
169         IMAGE_SECURITY_DATABASE = guid!("d719b2cb-3d3a-4596-a3bc-dad00e67656f"),
170     }
171 }
172