openhcl_boot/host_params/
shim_params.rs1use crate::arch::get_isolation_type;
7use core::slice;
8use loader_defs::paravisor::ImportedRegionDescriptor;
9use loader_defs::paravisor::ParavisorCommandLine;
10use loader_defs::shim::ShimParamsRaw;
11use memory_range::MemoryRange;
12
13#[derive(Debug, PartialEq, Eq, Copy, Clone)]
15pub enum IsolationType {
16 None,
17 Vbs,
18 #[cfg_attr(target_arch = "aarch64", expect(dead_code))]
19 Snp,
20 #[cfg_attr(target_arch = "aarch64", expect(dead_code))]
21 Tdx,
22 #[expect(dead_code)]
24 Cca,
25}
26
27impl IsolationType {
28 pub fn is_hardware_isolated(&self) -> bool {
29 match self {
30 IsolationType::None => false,
31 IsolationType::Vbs => false,
32 IsolationType::Snp => true,
33 IsolationType::Tdx => true,
34 IsolationType::Cca => true,
35 }
36 }
37}
38
39pub struct ImportedRegionIter<'a> {
42 imported_regions: &'a [ImportedRegionDescriptor],
43}
44
45impl Iterator for ImportedRegionIter<'_> {
46 type Item = (MemoryRange, bool);
47
48 fn next(&mut self) -> Option<Self::Item> {
49 if self.imported_regions.is_empty() {
50 None
51 } else {
52 let element = self.imported_regions[0]
53 .pages()
54 .map(|(base_page, count, accepted)| {
55 let base_address = base_page * hvdef::HV_PAGE_SIZE;
56 let end_address = base_address + (count * hvdef::HV_PAGE_SIZE);
57 (MemoryRange::try_new(base_address..end_address).expect(
58 "page number conversion into addresses results in a valid address range",
59 ), accepted)
60 });
61
62 if element.is_some() {
63 self.imported_regions = &self.imported_regions[1..];
64 } else {
65 self.imported_regions = &[];
66 }
67
68 element
69 }
70 }
71}
72
73#[derive(Debug)]
77pub struct ShimParams {
78 pub kernel_entry_address: u64,
81 pub cmdline_base: u64,
83 pub initrd_base: u64,
85 pub initrd_size: u64,
87 pub initrd_crc: u32,
89 pub memory_start_address: u64,
91 pub memory_size: u64,
93 pub parameter_region_start: u64,
95 pub parameter_region_size: u64,
97 pub vtl2_reserved_region_start: u64,
99 pub vtl2_reserved_region_size: u64,
101 pub isolation_type: IsolationType,
103 pub sidecar_entry_address: u64,
104 pub sidecar_base: u64,
105 pub sidecar_size: u64,
106 pub used: MemoryRange,
108 pub bounce_buffer: Option<MemoryRange>,
109 pub log_buffer: MemoryRange,
111 pub heap: MemoryRange,
113 pub persisted_state: MemoryRange,
115}
116
117impl ShimParams {
118 pub fn new(shim_base_address: u64, raw: &ShimParamsRaw) -> Self {
121 let &ShimParamsRaw {
122 kernel_entry_offset,
123 cmdline_offset,
124 initrd_offset,
125 initrd_size,
126 initrd_crc,
127 supported_isolation_type,
128 memory_start_offset,
129 memory_size,
130 parameter_region_offset,
131 parameter_region_size,
132 vtl2_reserved_region_offset,
133 vtl2_reserved_region_size,
134 sidecar_offset,
135 sidecar_size,
136 sidecar_entry_offset,
137 used_start,
138 used_end,
139 bounce_buffer_start,
140 bounce_buffer_size,
141 log_buffer_start,
142 log_buffer_size,
143 heap_start_offset,
144 heap_size,
145 persisted_state_region_offset,
146 persisted_state_region_size,
147 } = raw;
148
149 let isolation_type = get_isolation_type(supported_isolation_type);
150
151 let bounce_buffer = if bounce_buffer_size == 0 {
152 None
153 } else {
154 let base = shim_base_address.wrapping_add_signed(bounce_buffer_start);
155 Some(MemoryRange::new(base..base + bounce_buffer_size))
156 };
157
158 let log_buffer = {
159 let base = shim_base_address.wrapping_add_signed(log_buffer_start);
160 MemoryRange::new(base..base + log_buffer_size)
161 };
162
163 let heap = {
164 let base = shim_base_address.wrapping_add_signed(heap_start_offset);
165 MemoryRange::new(base..base + heap_size)
166 };
167
168 let persisted_state = {
169 let base = shim_base_address.wrapping_add_signed(persisted_state_region_offset);
170 MemoryRange::new(base..base + persisted_state_region_size)
171 };
172
173 Self {
174 kernel_entry_address: shim_base_address.wrapping_add_signed(kernel_entry_offset),
175 cmdline_base: shim_base_address.wrapping_add_signed(cmdline_offset),
176 initrd_base: shim_base_address.wrapping_add_signed(initrd_offset),
177 initrd_size,
178 initrd_crc,
179 memory_start_address: shim_base_address.wrapping_add_signed(memory_start_offset),
180 memory_size,
181 parameter_region_start: shim_base_address.wrapping_add_signed(parameter_region_offset),
182 parameter_region_size,
183 vtl2_reserved_region_start: shim_base_address
184 .wrapping_add_signed(vtl2_reserved_region_offset),
185 vtl2_reserved_region_size,
186 isolation_type,
187 sidecar_entry_address: shim_base_address.wrapping_add_signed(sidecar_entry_offset),
188 sidecar_base: shim_base_address.wrapping_add_signed(sidecar_offset),
189 sidecar_size,
190 used: MemoryRange::new(
191 shim_base_address.wrapping_add_signed(used_start)
192 ..shim_base_address.wrapping_add_signed(used_end),
193 ),
194 bounce_buffer,
195 log_buffer,
196 heap,
197 persisted_state,
198 }
199 }
200
201 #[cfg(target_arch = "x86_64")]
203 pub fn secrets_start(&self) -> u64 {
204 self.vtl2_reserved_region_start
205 + loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_SECRETS_PAGE_INDEX
206 * hvdef::HV_PAGE_SIZE
207 }
208
209 #[cfg(target_arch = "x86_64")]
211 pub fn cpuid_start(&self) -> u64 {
212 self.vtl2_reserved_region_start
213 + loader_defs::paravisor::PARAVISOR_RESERVED_VTL2_SNP_CPUID_PAGE_INDEX
214 * hvdef::HV_PAGE_SIZE
215 }
216
217 pub fn dt_start(&self) -> u64 {
219 self.parameter_region_start
220 + loader_defs::paravisor::PARAVISOR_CONFIG_DEVICE_TREE_PAGE_INDEX * hvdef::HV_PAGE_SIZE
221 }
222
223 pub fn dt_size(&self) -> u64 {
225 loader_defs::paravisor::PARAVISOR_CONFIG_DEVICE_TREE_SIZE_PAGES * hvdef::HV_PAGE_SIZE
226 }
227
228 pub fn initrd(&self) -> &'static [u8] {
230 unsafe { slice::from_raw_parts(self.initrd_base as *const u8, self.initrd_size as usize) }
233 }
234
235 pub fn command_line(&self) -> &'static ParavisorCommandLine {
238 unsafe {
241 (self.cmdline_base as *const ParavisorCommandLine)
242 .as_ref()
243 .expect("should always be non null")
244 }
245 }
246
247 pub fn device_tree(&self) -> &'static [u8] {
251 unsafe { slice::from_raw_parts(self.dt_start() as *const u8, self.dt_size() as usize) }
254 }
255
256 pub fn imported_regions(&self) -> ImportedRegionIter<'_> {
260 use loader_defs::paravisor::ImportedRegionsPageHeader;
261
262 let imported_region_page_address = self.parameter_region_start
263 + (loader_defs::paravisor::PARAVISOR_MEASURED_VTL2_CONFIG_ACCEPTED_MEMORY_PAGE_INDEX
264 * hvdef::HV_PAGE_SIZE);
265
266 assert!(
267 imported_region_page_address + hvdef::HV_PAGE_SIZE
268 <= self.parameter_region_start + self.parameter_region_size
269 );
270
271 let imported_region_start =
272 imported_region_page_address + size_of::<ImportedRegionsPageHeader>() as u64;
273
274 unsafe {
277 ImportedRegionIter {
278 imported_regions: slice::from_raw_parts(
279 imported_region_start as *const ImportedRegionDescriptor,
280 (hvdef::HV_PAGE_SIZE as usize - size_of::<ImportedRegionsPageHeader>())
281 / size_of::<ImportedRegionDescriptor>(),
282 ),
283 }
284 }
285 }
286
287 #[cfg(target_arch = "x86_64")]
288 pub fn imported_regions_hash(&self) -> &'static [u8] {
289 let header_start = self.parameter_region_start
290 + (loader_defs::paravisor::PARAVISOR_MEASURED_VTL2_CONFIG_ACCEPTED_MEMORY_PAGE_INDEX
291 * hvdef::HV_PAGE_SIZE);
292
293 unsafe {
296 let header =
297 &*(header_start as *const loader_defs::paravisor::ImportedRegionsPageHeader);
298 &header.sha384_hash
299 }
300 }
301}