1 | // DO NOT EDIT |
2 | // |
3 | // This file was automatically generated with: |
4 | // `cargo xtask gen-code` |
5 | // |
6 | // See `/xtask/src/device_path/README.md` for more details. |
7 | |
8 | use crate::data_types::UnalignedSlice; |
9 | use crate::polyfill::maybe_uninit_slice_as_mut_ptr; |
10 | use crate::proto::device_path::{ |
11 | DevicePathHeader, DevicePathNode, DeviceSubType, DeviceType, NodeConversionError, |
12 | }; |
13 | use crate::proto::network::IpAddress; |
14 | use crate::table::boot::MemoryType; |
15 | use crate::{guid, Guid}; |
16 | use bitflags::bitflags; |
17 | use core::mem::{size_of, size_of_val}; |
18 | use core::ptr::addr_of; |
19 | use core::{fmt, slice}; |
20 | use ptr_meta::{Pointee, PtrExt}; |
21 | /// Device path nodes for [`DeviceType::END`]. |
22 | pub mod end { |
23 | use super::*; |
24 | /// Node that terminates a [`DevicePathInstance`]. |
25 | /// |
26 | /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance |
27 | #[repr (C, packed)] |
28 | pub struct Instance { |
29 | pub(super) header: DevicePathHeader, |
30 | } |
31 | |
32 | impl Instance {} |
33 | |
34 | impl fmt::Debug for Instance { |
35 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
36 | f.debug_struct("Instance" ).finish() |
37 | } |
38 | } |
39 | |
40 | impl TryFrom<&DevicePathNode> for &Instance { |
41 | type Error = NodeConversionError; |
42 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
43 | if size_of_val(node) != size_of::<Instance>() { |
44 | return Err(NodeConversionError::InvalidLength); |
45 | } |
46 | |
47 | let node: *const DevicePathNode = node; |
48 | let node: *const Instance = node.cast(); |
49 | Ok(unsafe { &*node }) |
50 | } |
51 | } |
52 | |
53 | /// Node that terminates an entire [`DevicePath`]. |
54 | /// |
55 | /// [`DevicePath`]: crate::proto::device_path::DevicePath |
56 | #[repr (C, packed)] |
57 | pub struct Entire { |
58 | pub(super) header: DevicePathHeader, |
59 | } |
60 | |
61 | impl Entire {} |
62 | |
63 | impl fmt::Debug for Entire { |
64 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
65 | f.debug_struct("Entire" ).finish() |
66 | } |
67 | } |
68 | |
69 | impl TryFrom<&DevicePathNode> for &Entire { |
70 | type Error = NodeConversionError; |
71 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
72 | if size_of_val(node) != size_of::<Entire>() { |
73 | return Err(NodeConversionError::InvalidLength); |
74 | } |
75 | |
76 | let node: *const DevicePathNode = node; |
77 | let node: *const Entire = node.cast(); |
78 | Ok(unsafe { &*node }) |
79 | } |
80 | } |
81 | } |
82 | |
83 | /// Device path nodes for [`DeviceType::HARDWARE`]. |
84 | pub mod hardware { |
85 | use super::*; |
86 | /// PCI hardware device path node. |
87 | #[repr (C, packed)] |
88 | pub struct Pci { |
89 | pub(super) header: DevicePathHeader, |
90 | pub(super) function: u8, |
91 | pub(super) device: u8, |
92 | } |
93 | |
94 | impl Pci { |
95 | /// PCI function number. |
96 | #[must_use ] |
97 | pub fn function(&self) -> u8 { |
98 | self.function |
99 | } |
100 | |
101 | /// PCI device number. |
102 | #[must_use ] |
103 | pub fn device(&self) -> u8 { |
104 | self.device |
105 | } |
106 | } |
107 | |
108 | impl fmt::Debug for Pci { |
109 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
110 | f.debug_struct("Pci" ) |
111 | .field("function" , &{ self.function }) |
112 | .field("device" , &{ self.device }) |
113 | .finish() |
114 | } |
115 | } |
116 | |
117 | impl TryFrom<&DevicePathNode> for &Pci { |
118 | type Error = NodeConversionError; |
119 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
120 | if size_of_val(node) != size_of::<Pci>() { |
121 | return Err(NodeConversionError::InvalidLength); |
122 | } |
123 | |
124 | let node: *const DevicePathNode = node; |
125 | let node: *const Pci = node.cast(); |
126 | Ok(unsafe { &*node }) |
127 | } |
128 | } |
129 | |
130 | /// PCCARD hardware device path node. |
131 | #[repr (C, packed)] |
132 | pub struct Pccard { |
133 | pub(super) header: DevicePathHeader, |
134 | pub(super) function: u8, |
135 | } |
136 | |
137 | impl Pccard { |
138 | /// Function number starting from 0. |
139 | #[must_use ] |
140 | pub fn function(&self) -> u8 { |
141 | self.function |
142 | } |
143 | } |
144 | |
145 | impl fmt::Debug for Pccard { |
146 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
147 | f.debug_struct("Pccard" ) |
148 | .field("function" , &{ self.function }) |
149 | .finish() |
150 | } |
151 | } |
152 | |
153 | impl TryFrom<&DevicePathNode> for &Pccard { |
154 | type Error = NodeConversionError; |
155 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
156 | if size_of_val(node) != size_of::<Pccard>() { |
157 | return Err(NodeConversionError::InvalidLength); |
158 | } |
159 | |
160 | let node: *const DevicePathNode = node; |
161 | let node: *const Pccard = node.cast(); |
162 | Ok(unsafe { &*node }) |
163 | } |
164 | } |
165 | |
166 | /// Memory mapped hardware device path node. |
167 | #[repr (C, packed)] |
168 | pub struct MemoryMapped { |
169 | pub(super) header: DevicePathHeader, |
170 | pub(super) memory_type: MemoryType, |
171 | pub(super) start_address: u64, |
172 | pub(super) end_address: u64, |
173 | } |
174 | |
175 | impl MemoryMapped { |
176 | /// Memory type. |
177 | #[must_use ] |
178 | pub fn memory_type(&self) -> MemoryType { |
179 | self.memory_type |
180 | } |
181 | |
182 | /// Starting memory address. |
183 | #[must_use ] |
184 | pub fn start_address(&self) -> u64 { |
185 | self.start_address |
186 | } |
187 | |
188 | /// Ending memory address. |
189 | #[must_use ] |
190 | pub fn end_address(&self) -> u64 { |
191 | self.end_address |
192 | } |
193 | } |
194 | |
195 | impl fmt::Debug for MemoryMapped { |
196 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
197 | f.debug_struct("MemoryMapped" ) |
198 | .field("memory_type" , &{ self.memory_type }) |
199 | .field("start_address" , &{ self.start_address }) |
200 | .field("end_address" , &{ self.end_address }) |
201 | .finish() |
202 | } |
203 | } |
204 | |
205 | impl TryFrom<&DevicePathNode> for &MemoryMapped { |
206 | type Error = NodeConversionError; |
207 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
208 | if size_of_val(node) != size_of::<MemoryMapped>() { |
209 | return Err(NodeConversionError::InvalidLength); |
210 | } |
211 | |
212 | let node: *const DevicePathNode = node; |
213 | let node: *const MemoryMapped = node.cast(); |
214 | Ok(unsafe { &*node }) |
215 | } |
216 | } |
217 | |
218 | /// Vendor-defined hardware device path node. |
219 | #[repr (C, packed)] |
220 | #[derive (Pointee)] |
221 | pub struct Vendor { |
222 | pub(super) header: DevicePathHeader, |
223 | pub(super) vendor_guid: Guid, |
224 | pub(super) vendor_defined_data: [u8], |
225 | } |
226 | |
227 | impl Vendor { |
228 | /// Vendor-assigned GUID that defines the data that follows. |
229 | #[must_use ] |
230 | pub fn vendor_guid(&self) -> Guid { |
231 | self.vendor_guid |
232 | } |
233 | |
234 | /// Vendor-defined data. |
235 | #[must_use ] |
236 | pub fn vendor_defined_data(&self) -> &[u8] { |
237 | &self.vendor_defined_data |
238 | } |
239 | } |
240 | |
241 | impl fmt::Debug for Vendor { |
242 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
243 | f.debug_struct("Vendor" ) |
244 | .field("vendor_guid" , &{ self.vendor_guid }) |
245 | .field("vendor_defined_data" , { |
246 | let ptr = addr_of!(self.vendor_defined_data); |
247 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
248 | let byte_len = size_of::<u8>() * len; |
249 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
250 | }) |
251 | .finish() |
252 | } |
253 | } |
254 | |
255 | impl TryFrom<&DevicePathNode> for &Vendor { |
256 | type Error = NodeConversionError; |
257 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
258 | let static_size = 20usize; |
259 | let dst_size = size_of_val(node) |
260 | .checked_sub(static_size) |
261 | .ok_or(NodeConversionError::InvalidLength)?; |
262 | let elem_size = size_of::<u8>(); |
263 | if dst_size % elem_size != 0 { |
264 | return Err(NodeConversionError::InvalidLength); |
265 | } |
266 | |
267 | let node: *const DevicePathNode = node; |
268 | let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
269 | Ok(unsafe { &*node }) |
270 | } |
271 | } |
272 | |
273 | /// Controller hardware device path node. |
274 | #[repr (C, packed)] |
275 | pub struct Controller { |
276 | pub(super) header: DevicePathHeader, |
277 | pub(super) controller_number: u32, |
278 | } |
279 | |
280 | impl Controller { |
281 | /// Controller number. |
282 | #[must_use ] |
283 | pub fn controller_number(&self) -> u32 { |
284 | self.controller_number |
285 | } |
286 | } |
287 | |
288 | impl fmt::Debug for Controller { |
289 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
290 | f.debug_struct("Controller" ) |
291 | .field("controller_number" , &{ self.controller_number }) |
292 | .finish() |
293 | } |
294 | } |
295 | |
296 | impl TryFrom<&DevicePathNode> for &Controller { |
297 | type Error = NodeConversionError; |
298 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
299 | if size_of_val(node) != size_of::<Controller>() { |
300 | return Err(NodeConversionError::InvalidLength); |
301 | } |
302 | |
303 | let node: *const DevicePathNode = node; |
304 | let node: *const Controller = node.cast(); |
305 | Ok(unsafe { &*node }) |
306 | } |
307 | } |
308 | |
309 | /// Baseboard Management Controller (BMC) host interface hardware |
310 | /// device path node. |
311 | #[repr (C, packed)] |
312 | pub struct Bmc { |
313 | pub(super) header: DevicePathHeader, |
314 | pub(super) interface_type: crate::proto::device_path::hardware::BmcInterfaceType, |
315 | pub(super) base_address: u64, |
316 | } |
317 | |
318 | impl Bmc { |
319 | /// Host interface type. |
320 | #[must_use ] |
321 | pub fn interface_type(&self) -> crate::proto::device_path::hardware::BmcInterfaceType { |
322 | self.interface_type |
323 | } |
324 | |
325 | /// Base address of the BMC. If the least-significant bit of the |
326 | /// field is a 1 then the address is in I/O space, otherwise the |
327 | /// address is memory-mapped. |
328 | #[must_use ] |
329 | pub fn base_address(&self) -> u64 { |
330 | self.base_address |
331 | } |
332 | } |
333 | |
334 | impl fmt::Debug for Bmc { |
335 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
336 | f.debug_struct("Bmc" ) |
337 | .field("interface_type" , &{ self.interface_type }) |
338 | .field("base_address" , &{ self.base_address }) |
339 | .finish() |
340 | } |
341 | } |
342 | |
343 | impl TryFrom<&DevicePathNode> for &Bmc { |
344 | type Error = NodeConversionError; |
345 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
346 | if size_of_val(node) != size_of::<Bmc>() { |
347 | return Err(NodeConversionError::InvalidLength); |
348 | } |
349 | |
350 | let node: *const DevicePathNode = node; |
351 | let node: *const Bmc = node.cast(); |
352 | Ok(unsafe { &*node }) |
353 | } |
354 | } |
355 | |
356 | newtype_enum! { # [doc = " Baseboard Management Controller (BMC) host interface type." ] pub enum BmcInterfaceType : u8 => { # [doc = " Unknown." ] UNKNOWN = 0x00 , # [doc = " Keyboard controller style." ] KEYBOARD_CONTROLLER_STYLE = 0x01 , # [doc = " Server management interface chip." ] SERVER_MANAGEMENT_INTERFACE_CHIP = 0x02 , # [doc = " Block transfer." ] BLOCK_TRANSFER = 0x03 , } |
357 | |
358 | } |
359 | } |
360 | |
361 | /// Device path nodes for [`DeviceType::ACPI`]. |
362 | pub mod acpi { |
363 | use super::*; |
364 | /// ACPI device path node. |
365 | #[repr (C, packed)] |
366 | pub struct Acpi { |
367 | pub(super) header: DevicePathHeader, |
368 | pub(super) hid: u32, |
369 | pub(super) uid: u32, |
370 | } |
371 | |
372 | impl Acpi { |
373 | /// Device's PnP hardware ID stored in a numeric 32-bit |
374 | /// compressed EISA-type ID. |
375 | #[must_use ] |
376 | pub fn hid(&self) -> u32 { |
377 | self.hid |
378 | } |
379 | |
380 | /// Unique ID that is required by ACPI if two devices have the |
381 | /// same HID. |
382 | #[must_use ] |
383 | pub fn uid(&self) -> u32 { |
384 | self.uid |
385 | } |
386 | } |
387 | |
388 | impl fmt::Debug for Acpi { |
389 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
390 | f.debug_struct("Acpi" ) |
391 | .field("hid" , &{ self.hid }) |
392 | .field("uid" , &{ self.uid }) |
393 | .finish() |
394 | } |
395 | } |
396 | |
397 | impl TryFrom<&DevicePathNode> for &Acpi { |
398 | type Error = NodeConversionError; |
399 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
400 | if size_of_val(node) != size_of::<Acpi>() { |
401 | return Err(NodeConversionError::InvalidLength); |
402 | } |
403 | |
404 | let node: *const DevicePathNode = node; |
405 | let node: *const Acpi = node.cast(); |
406 | Ok(unsafe { &*node }) |
407 | } |
408 | } |
409 | |
410 | /// Expanded ACPI device path node. |
411 | #[repr (C, packed)] |
412 | #[derive (Pointee)] |
413 | pub struct Expanded { |
414 | pub(super) header: DevicePathHeader, |
415 | pub(super) hid: u32, |
416 | pub(super) uid: u32, |
417 | pub(super) cid: u32, |
418 | pub(super) data: [u8], |
419 | } |
420 | |
421 | impl Expanded { |
422 | /// Device's PnP hardware ID stored in a numeric 32-bit compressed |
423 | /// EISA-type ID. |
424 | #[must_use ] |
425 | pub fn hid(&self) -> u32 { |
426 | self.hid |
427 | } |
428 | |
429 | /// Unique ID that is required by ACPI if two devices have the |
430 | /// same HID. |
431 | #[must_use ] |
432 | pub fn uid(&self) -> u32 { |
433 | self.uid |
434 | } |
435 | |
436 | /// Device's compatible PnP hardware ID stored in a numeric 32-bit |
437 | /// compressed EISA-type ID. |
438 | #[must_use ] |
439 | pub fn cid(&self) -> u32 { |
440 | self.cid |
441 | } |
442 | |
443 | /// Device's PnP hardware ID stored as a null-terminated ASCII |
444 | /// string. This value must match the corresponding HID in the |
445 | /// ACPI name space. If the length of this string not including |
446 | /// the null-terminator is 0, then the numeric HID is used. |
447 | #[must_use ] |
448 | pub fn hid_str(&self) -> &[u8] { |
449 | self.get_hid_str() |
450 | } |
451 | |
452 | /// Unique ID that is required by ACPI if two devices have the |
453 | /// same HID. This value is stored as a null-terminated ASCII |
454 | /// string. If the length of this string not including the |
455 | /// null-terminator is 0, then the numeric UID is used. |
456 | #[must_use ] |
457 | pub fn uid_str(&self) -> &[u8] { |
458 | self.get_uid_str() |
459 | } |
460 | |
461 | /// Device's compatible PnP hardware ID stored as a |
462 | /// null-terminated ASCII string. If the length of this string |
463 | /// not including the null-terminator is 0, then the numeric CID |
464 | /// is used. |
465 | #[must_use ] |
466 | pub fn cid_str(&self) -> &[u8] { |
467 | self.get_cid_str() |
468 | } |
469 | } |
470 | |
471 | impl fmt::Debug for Expanded { |
472 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
473 | f.debug_struct("Expanded" ) |
474 | .field("hid" , &{ self.hid }) |
475 | .field("uid" , &{ self.uid }) |
476 | .field("cid" , &{ self.cid }) |
477 | .field("data" , &&self.data) |
478 | .finish() |
479 | } |
480 | } |
481 | |
482 | impl TryFrom<&DevicePathNode> for &Expanded { |
483 | type Error = NodeConversionError; |
484 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
485 | let static_size = 16usize; |
486 | let dst_size = size_of_val(node) |
487 | .checked_sub(static_size) |
488 | .ok_or(NodeConversionError::InvalidLength)?; |
489 | let elem_size = size_of::<u8>(); |
490 | if dst_size % elem_size != 0 { |
491 | return Err(NodeConversionError::InvalidLength); |
492 | } |
493 | |
494 | let node: *const DevicePathNode = node; |
495 | let node: *const Expanded = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
496 | Ok(unsafe { &*node }) |
497 | } |
498 | } |
499 | |
500 | /// ADR ACPI device path node. |
501 | #[repr (C, packed)] |
502 | #[derive (Pointee)] |
503 | pub struct Adr { |
504 | pub(super) header: DevicePathHeader, |
505 | pub(super) adr: [u32], |
506 | } |
507 | |
508 | impl Adr { |
509 | /// ADR values. For video output devices the value of this field |
510 | /// comes from Table B-2 ACPI 3.0 specification. At least one |
511 | /// ADR value is required. |
512 | #[must_use ] |
513 | pub fn adr(&self) -> UnalignedSlice<u32> { |
514 | let ptr: *const [u32] = addr_of!(self.adr); |
515 | let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr); |
516 | unsafe { UnalignedSlice::new(ptr.cast::<u32>(), len) } |
517 | } |
518 | } |
519 | |
520 | impl fmt::Debug for Adr { |
521 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
522 | f.debug_struct("Adr" ) |
523 | .field("adr" , { |
524 | let ptr = addr_of!(self.adr); |
525 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
526 | let byte_len = size_of::<u32>() * len; |
527 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
528 | }) |
529 | .finish() |
530 | } |
531 | } |
532 | |
533 | impl TryFrom<&DevicePathNode> for &Adr { |
534 | type Error = NodeConversionError; |
535 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
536 | let static_size = 4usize; |
537 | let dst_size = size_of_val(node) |
538 | .checked_sub(static_size) |
539 | .ok_or(NodeConversionError::InvalidLength)?; |
540 | let elem_size = size_of::<u32>(); |
541 | if dst_size % elem_size != 0 { |
542 | return Err(NodeConversionError::InvalidLength); |
543 | } |
544 | |
545 | let node: *const DevicePathNode = node; |
546 | let node: *const Adr = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
547 | Ok(unsafe { &*node }) |
548 | } |
549 | } |
550 | |
551 | /// NVDIMM ACPI device path node. |
552 | #[repr (C, packed)] |
553 | pub struct Nvdimm { |
554 | pub(super) header: DevicePathHeader, |
555 | pub(super) nfit_device_handle: u32, |
556 | } |
557 | |
558 | impl Nvdimm { |
559 | /// NFIT device handle. |
560 | #[must_use ] |
561 | pub fn nfit_device_handle(&self) -> u32 { |
562 | self.nfit_device_handle |
563 | } |
564 | } |
565 | |
566 | impl fmt::Debug for Nvdimm { |
567 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
568 | f.debug_struct("Nvdimm" ) |
569 | .field("nfit_device_handle" , &{ self.nfit_device_handle }) |
570 | .finish() |
571 | } |
572 | } |
573 | |
574 | impl TryFrom<&DevicePathNode> for &Nvdimm { |
575 | type Error = NodeConversionError; |
576 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
577 | if size_of_val(node) != size_of::<Nvdimm>() { |
578 | return Err(NodeConversionError::InvalidLength); |
579 | } |
580 | |
581 | let node: *const DevicePathNode = node; |
582 | let node: *const Nvdimm = node.cast(); |
583 | Ok(unsafe { &*node }) |
584 | } |
585 | } |
586 | |
587 | impl Expanded { |
588 | fn get_hid_str(&self) -> &[u8] { |
589 | get_acpi_expanded_substr(&self.data, 0) |
590 | } |
591 | |
592 | fn get_uid_str(&self) -> &[u8] { |
593 | get_acpi_expanded_substr(&self.data, 1) |
594 | } |
595 | |
596 | fn get_cid_str(&self) -> &[u8] { |
597 | get_acpi_expanded_substr(&self.data, 2) |
598 | } |
599 | } |
600 | |
601 | /// Get the indices of the three nulls in the combined hid/uid/cid |
602 | /// string. This never fails; if some nulls are missing then `None` |
603 | /// is returned for those indices. If more than three nulls are |
604 | /// present then the extra ones are ignored. |
605 | fn acpi_expanded_null_indices(data: &[u8]) -> [Option<usize>; 3] { |
606 | let mut iter = data |
607 | .iter() |
608 | .copied() |
609 | .enumerate() |
610 | .filter_map(|(index, byte)| if byte == 0 { Some(index) } else { None }) |
611 | .fuse(); |
612 | [iter.next(), iter.next(), iter.next()] |
613 | } |
614 | |
615 | /// Get the hid, uid, or cid string from the combined string. The |
616 | /// returned string includes the trailing null if possible; if the |
617 | /// substring was not properly null terminated then it ends at the |
618 | /// end of `data`. |
619 | /// |
620 | /// This never fails; if there aren't enough nulls in the input |
621 | /// string then an empty slice may be returned. |
622 | fn get_acpi_expanded_substr(data: &[u8], string_index: usize) -> &[u8] { |
623 | let [n0, n1, n2] = acpi_expanded_null_indices(data); |
624 | let mut start = data.len(); |
625 | let mut end = start; |
626 | match string_index { |
627 | 0 => { |
628 | start = 0; |
629 | if let Some(n0) = n0 { |
630 | end = n0 + 1; |
631 | } |
632 | } |
633 | |
634 | 1 => { |
635 | if let Some(n0) = n0 { |
636 | start = n0 + 1; |
637 | if let Some(n1) = n1 { |
638 | end = n1 + 1; |
639 | } |
640 | } |
641 | } |
642 | |
643 | 2 => { |
644 | if let Some(n1) = n1 { |
645 | start = n1 + 1; |
646 | if let Some(n2) = n2 { |
647 | end = n2 + 1; |
648 | } |
649 | } |
650 | } |
651 | |
652 | _ => { |
653 | unreachable!("invalid string index" ) |
654 | } |
655 | } |
656 | |
657 | data.get(start..end).unwrap_or(&[]) |
658 | } |
659 | |
660 | #[cfg (test)] |
661 | mod tests { |
662 | use super::*; |
663 | #[test ] |
664 | fn test_get_acpi_expanded_substr() { |
665 | let s = b"ab \0cd \0ef \0" ; |
666 | assert_eq!(get_acpi_expanded_substr(s, 0), b"ab \0" ); |
667 | assert_eq!(get_acpi_expanded_substr(s, 1), b"cd \0" ); |
668 | assert_eq!(get_acpi_expanded_substr(s, 2), b"ef \0" ); |
669 | let s = b" \0\0\0" ; |
670 | assert_eq!(get_acpi_expanded_substr(s, 0), b" \0" ); |
671 | assert_eq!(get_acpi_expanded_substr(s, 1), b" \0" ); |
672 | assert_eq!(get_acpi_expanded_substr(s, 2), b" \0" ); |
673 | let s = b"ab \0cd \0" ; |
674 | assert_eq!(get_acpi_expanded_substr(s, 0), b"ab \0" ); |
675 | assert_eq!(get_acpi_expanded_substr(s, 1), b"cd \0" ); |
676 | assert_eq!(get_acpi_expanded_substr(s, 2), b"" ); |
677 | let s = b"ab \0" ; |
678 | assert_eq!(get_acpi_expanded_substr(s, 0), b"ab \0" ); |
679 | assert_eq!(get_acpi_expanded_substr(s, 1), b"" ); |
680 | assert_eq!(get_acpi_expanded_substr(s, 2), b"" ); |
681 | let s = b"ab \0cd \0ef" ; |
682 | assert_eq!(get_acpi_expanded_substr(s, 0), b"ab \0" ); |
683 | assert_eq!(get_acpi_expanded_substr(s, 1), b"cd \0" ); |
684 | assert_eq!(get_acpi_expanded_substr(s, 2), b"ef" ); |
685 | let s = b"ab \0cd" ; |
686 | assert_eq!(get_acpi_expanded_substr(s, 0), b"ab \0" ); |
687 | assert_eq!(get_acpi_expanded_substr(s, 1), b"cd" ); |
688 | assert_eq!(get_acpi_expanded_substr(s, 2), b"" ); |
689 | let s = b"ab" ; |
690 | assert_eq!(get_acpi_expanded_substr(s, 0), b"ab" ); |
691 | assert_eq!(get_acpi_expanded_substr(s, 1), b"" ); |
692 | assert_eq!(get_acpi_expanded_substr(s, 2), b"" ); |
693 | let s = b"" ; |
694 | assert_eq!(get_acpi_expanded_substr(s, 0), b"" ); |
695 | assert_eq!(get_acpi_expanded_substr(s, 1), b"" ); |
696 | assert_eq!(get_acpi_expanded_substr(s, 2), b"" ); |
697 | } |
698 | } |
699 | } |
700 | |
701 | /// Device path nodes for [`DeviceType::MESSAGING`]. |
702 | pub mod messaging { |
703 | use super::*; |
704 | /// ATAPI messaging device path node. |
705 | #[repr (C, packed)] |
706 | pub struct Atapi { |
707 | pub(super) header: DevicePathHeader, |
708 | pub(super) primary_secondary: crate::proto::device_path::messaging::PrimarySecondary, |
709 | pub(super) master_slave: crate::proto::device_path::messaging::MasterSlave, |
710 | pub(super) logical_unit_number: u16, |
711 | } |
712 | |
713 | impl Atapi { |
714 | /// Whether the ATAPI device is primary or secondary. |
715 | #[must_use ] |
716 | pub fn primary_secondary(&self) -> crate::proto::device_path::messaging::PrimarySecondary { |
717 | self.primary_secondary |
718 | } |
719 | |
720 | /// Whether the ATAPI device is master or slave. |
721 | #[must_use ] |
722 | pub fn master_slave(&self) -> crate::proto::device_path::messaging::MasterSlave { |
723 | self.master_slave |
724 | } |
725 | |
726 | /// Logical Unit Number (LUN). |
727 | #[must_use ] |
728 | pub fn logical_unit_number(&self) -> u16 { |
729 | self.logical_unit_number |
730 | } |
731 | } |
732 | |
733 | impl fmt::Debug for Atapi { |
734 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
735 | f.debug_struct("Atapi" ) |
736 | .field("primary_secondary" , &{ self.primary_secondary }) |
737 | .field("master_slave" , &{ self.master_slave }) |
738 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
739 | .finish() |
740 | } |
741 | } |
742 | |
743 | impl TryFrom<&DevicePathNode> for &Atapi { |
744 | type Error = NodeConversionError; |
745 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
746 | if size_of_val(node) != size_of::<Atapi>() { |
747 | return Err(NodeConversionError::InvalidLength); |
748 | } |
749 | |
750 | let node: *const DevicePathNode = node; |
751 | let node: *const Atapi = node.cast(); |
752 | Ok(unsafe { &*node }) |
753 | } |
754 | } |
755 | |
756 | /// SCSI messaging device path node. |
757 | #[repr (C, packed)] |
758 | pub struct Scsi { |
759 | pub(super) header: DevicePathHeader, |
760 | pub(super) target_id: u16, |
761 | pub(super) logical_unit_number: u16, |
762 | } |
763 | |
764 | impl Scsi { |
765 | /// Target ID on the SCSI bus. |
766 | #[must_use ] |
767 | pub fn target_id(&self) -> u16 { |
768 | self.target_id |
769 | } |
770 | |
771 | /// Logical Unit Number. |
772 | #[must_use ] |
773 | pub fn logical_unit_number(&self) -> u16 { |
774 | self.logical_unit_number |
775 | } |
776 | } |
777 | |
778 | impl fmt::Debug for Scsi { |
779 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
780 | f.debug_struct("Scsi" ) |
781 | .field("target_id" , &{ self.target_id }) |
782 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
783 | .finish() |
784 | } |
785 | } |
786 | |
787 | impl TryFrom<&DevicePathNode> for &Scsi { |
788 | type Error = NodeConversionError; |
789 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
790 | if size_of_val(node) != size_of::<Scsi>() { |
791 | return Err(NodeConversionError::InvalidLength); |
792 | } |
793 | |
794 | let node: *const DevicePathNode = node; |
795 | let node: *const Scsi = node.cast(); |
796 | Ok(unsafe { &*node }) |
797 | } |
798 | } |
799 | |
800 | /// Fibre channel messaging device path node. |
801 | #[repr (C, packed)] |
802 | pub struct FibreChannel { |
803 | pub(super) header: DevicePathHeader, |
804 | pub(super) _reserved: u32, |
805 | pub(super) world_wide_name: u64, |
806 | pub(super) logical_unit_number: u64, |
807 | } |
808 | |
809 | impl FibreChannel { |
810 | /// Fibre Channel World Wide Name. |
811 | #[must_use ] |
812 | pub fn world_wide_name(&self) -> u64 { |
813 | self.world_wide_name |
814 | } |
815 | |
816 | /// Fibre Channel Logical Unit Number. |
817 | #[must_use ] |
818 | pub fn logical_unit_number(&self) -> u64 { |
819 | self.logical_unit_number |
820 | } |
821 | } |
822 | |
823 | impl fmt::Debug for FibreChannel { |
824 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
825 | f.debug_struct("FibreChannel" ) |
826 | .field("_reserved" , &{ self._reserved }) |
827 | .field("world_wide_name" , &{ self.world_wide_name }) |
828 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
829 | .finish() |
830 | } |
831 | } |
832 | |
833 | impl TryFrom<&DevicePathNode> for &FibreChannel { |
834 | type Error = NodeConversionError; |
835 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
836 | if size_of_val(node) != size_of::<FibreChannel>() { |
837 | return Err(NodeConversionError::InvalidLength); |
838 | } |
839 | |
840 | let node: *const DevicePathNode = node; |
841 | let node: *const FibreChannel = node.cast(); |
842 | Ok(unsafe { &*node }) |
843 | } |
844 | } |
845 | |
846 | /// Fibre channel extended messaging device path node. |
847 | #[repr (C, packed)] |
848 | pub struct FibreChannelEx { |
849 | pub(super) header: DevicePathHeader, |
850 | pub(super) _reserved: u32, |
851 | pub(super) world_wide_name: [u8; 8usize], |
852 | pub(super) logical_unit_number: [u8; 8usize], |
853 | } |
854 | |
855 | impl FibreChannelEx { |
856 | /// Fibre Channel end device port name (aka World Wide Name). |
857 | #[must_use ] |
858 | pub fn world_wide_name(&self) -> [u8; 8usize] { |
859 | self.world_wide_name |
860 | } |
861 | |
862 | /// Fibre Channel Logical Unit Number. |
863 | #[must_use ] |
864 | pub fn logical_unit_number(&self) -> [u8; 8usize] { |
865 | self.logical_unit_number |
866 | } |
867 | } |
868 | |
869 | impl fmt::Debug for FibreChannelEx { |
870 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
871 | f.debug_struct("FibreChannelEx" ) |
872 | .field("_reserved" , &{ self._reserved }) |
873 | .field("world_wide_name" , &{ self.world_wide_name }) |
874 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
875 | .finish() |
876 | } |
877 | } |
878 | |
879 | impl TryFrom<&DevicePathNode> for &FibreChannelEx { |
880 | type Error = NodeConversionError; |
881 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
882 | if size_of_val(node) != size_of::<FibreChannelEx>() { |
883 | return Err(NodeConversionError::InvalidLength); |
884 | } |
885 | |
886 | let node: *const DevicePathNode = node; |
887 | let node: *const FibreChannelEx = node.cast(); |
888 | Ok(unsafe { &*node }) |
889 | } |
890 | } |
891 | |
892 | /// 1394 messaging device path node. |
893 | #[repr (C, packed)] |
894 | pub struct Ieee1394 { |
895 | pub(super) header: DevicePathHeader, |
896 | pub(super) _reserved: u32, |
897 | pub(super) guid: [u8; 8usize], |
898 | } |
899 | |
900 | impl Ieee1394 { |
901 | /// 1394 Global Unique ID. Note that this is not the same as a |
902 | /// UEFI GUID. |
903 | #[must_use ] |
904 | pub fn guid(&self) -> [u8; 8usize] { |
905 | self.guid |
906 | } |
907 | } |
908 | |
909 | impl fmt::Debug for Ieee1394 { |
910 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
911 | f.debug_struct("Ieee1394" ) |
912 | .field("_reserved" , &{ self._reserved }) |
913 | .field("guid" , &{ self.guid }) |
914 | .finish() |
915 | } |
916 | } |
917 | |
918 | impl TryFrom<&DevicePathNode> for &Ieee1394 { |
919 | type Error = NodeConversionError; |
920 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
921 | if size_of_val(node) != size_of::<Ieee1394>() { |
922 | return Err(NodeConversionError::InvalidLength); |
923 | } |
924 | |
925 | let node: *const DevicePathNode = node; |
926 | let node: *const Ieee1394 = node.cast(); |
927 | Ok(unsafe { &*node }) |
928 | } |
929 | } |
930 | |
931 | /// USB messaging device path node. |
932 | #[repr (C, packed)] |
933 | pub struct Usb { |
934 | pub(super) header: DevicePathHeader, |
935 | pub(super) parent_port_number: u8, |
936 | pub(super) interface: u8, |
937 | } |
938 | |
939 | impl Usb { |
940 | /// USB parent port number. |
941 | #[must_use ] |
942 | pub fn parent_port_number(&self) -> u8 { |
943 | self.parent_port_number |
944 | } |
945 | |
946 | /// USB interface number. |
947 | #[must_use ] |
948 | pub fn interface(&self) -> u8 { |
949 | self.interface |
950 | } |
951 | } |
952 | |
953 | impl fmt::Debug for Usb { |
954 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
955 | f.debug_struct("Usb" ) |
956 | .field("parent_port_number" , &{ self.parent_port_number }) |
957 | .field("interface" , &{ self.interface }) |
958 | .finish() |
959 | } |
960 | } |
961 | |
962 | impl TryFrom<&DevicePathNode> for &Usb { |
963 | type Error = NodeConversionError; |
964 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
965 | if size_of_val(node) != size_of::<Usb>() { |
966 | return Err(NodeConversionError::InvalidLength); |
967 | } |
968 | |
969 | let node: *const DevicePathNode = node; |
970 | let node: *const Usb = node.cast(); |
971 | Ok(unsafe { &*node }) |
972 | } |
973 | } |
974 | |
975 | /// SATA messaging device path node. |
976 | #[repr (C, packed)] |
977 | pub struct Sata { |
978 | pub(super) header: DevicePathHeader, |
979 | pub(super) hba_port_number: u16, |
980 | pub(super) port_multiplier_port_number: u16, |
981 | pub(super) logical_unit_number: u16, |
982 | } |
983 | |
984 | impl Sata { |
985 | /// The HBA port number that facilitates the connection to the |
986 | /// device or a port multiplier. The value 0xffff is reserved. |
987 | #[must_use ] |
988 | pub fn hba_port_number(&self) -> u16 { |
989 | self.hba_port_number |
990 | } |
991 | |
992 | /// the port multiplier port number that facilitates the |
993 | /// connection to the device. Must be set to 0xffff if the |
994 | /// device is directly connected to the HBA. |
995 | #[must_use ] |
996 | pub fn port_multiplier_port_number(&self) -> u16 { |
997 | self.port_multiplier_port_number |
998 | } |
999 | |
1000 | /// Logical unit number. |
1001 | #[must_use ] |
1002 | pub fn logical_unit_number(&self) -> u16 { |
1003 | self.logical_unit_number |
1004 | } |
1005 | } |
1006 | |
1007 | impl fmt::Debug for Sata { |
1008 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1009 | f.debug_struct("Sata" ) |
1010 | .field("hba_port_number" , &{ self.hba_port_number }) |
1011 | .field("port_multiplier_port_number" , &{ |
1012 | self.port_multiplier_port_number |
1013 | }) |
1014 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
1015 | .finish() |
1016 | } |
1017 | } |
1018 | |
1019 | impl TryFrom<&DevicePathNode> for &Sata { |
1020 | type Error = NodeConversionError; |
1021 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1022 | if size_of_val(node) != size_of::<Sata>() { |
1023 | return Err(NodeConversionError::InvalidLength); |
1024 | } |
1025 | |
1026 | let node: *const DevicePathNode = node; |
1027 | let node: *const Sata = node.cast(); |
1028 | Ok(unsafe { &*node }) |
1029 | } |
1030 | } |
1031 | |
1032 | /// USB World Wide ID (WWID) messaging device path node. |
1033 | #[repr (C, packed)] |
1034 | #[derive (Pointee)] |
1035 | pub struct UsbWwid { |
1036 | pub(super) header: DevicePathHeader, |
1037 | pub(super) interface_number: u16, |
1038 | pub(super) device_vendor_id: u16, |
1039 | pub(super) device_product_id: u16, |
1040 | pub(super) serial_number: [u16], |
1041 | } |
1042 | |
1043 | impl UsbWwid { |
1044 | /// USB interface number. |
1045 | #[must_use ] |
1046 | pub fn interface_number(&self) -> u16 { |
1047 | self.interface_number |
1048 | } |
1049 | |
1050 | /// USB vendor ID. |
1051 | #[must_use ] |
1052 | pub fn device_vendor_id(&self) -> u16 { |
1053 | self.device_vendor_id |
1054 | } |
1055 | |
1056 | /// USB product ID. |
1057 | #[must_use ] |
1058 | pub fn device_product_id(&self) -> u16 { |
1059 | self.device_product_id |
1060 | } |
1061 | |
1062 | /// Last 64 (or fewer) characters of the USB Serial number. |
1063 | #[must_use ] |
1064 | pub fn serial_number(&self) -> UnalignedSlice<u16> { |
1065 | let ptr: *const [u16] = addr_of!(self.serial_number); |
1066 | let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr); |
1067 | unsafe { UnalignedSlice::new(ptr.cast::<u16>(), len) } |
1068 | } |
1069 | } |
1070 | |
1071 | impl fmt::Debug for UsbWwid { |
1072 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1073 | f.debug_struct("UsbWwid" ) |
1074 | .field("interface_number" , &{ self.interface_number }) |
1075 | .field("device_vendor_id" , &{ self.device_vendor_id }) |
1076 | .field("device_product_id" , &{ self.device_product_id }) |
1077 | .field("serial_number" , { |
1078 | let ptr = addr_of!(self.serial_number); |
1079 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
1080 | let byte_len = size_of::<u16>() * len; |
1081 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
1082 | }) |
1083 | .finish() |
1084 | } |
1085 | } |
1086 | |
1087 | impl TryFrom<&DevicePathNode> for &UsbWwid { |
1088 | type Error = NodeConversionError; |
1089 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1090 | let static_size = 10usize; |
1091 | let dst_size = size_of_val(node) |
1092 | .checked_sub(static_size) |
1093 | .ok_or(NodeConversionError::InvalidLength)?; |
1094 | let elem_size = size_of::<u16>(); |
1095 | if dst_size % elem_size != 0 { |
1096 | return Err(NodeConversionError::InvalidLength); |
1097 | } |
1098 | |
1099 | let node: *const DevicePathNode = node; |
1100 | let node: *const UsbWwid = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
1101 | Ok(unsafe { &*node }) |
1102 | } |
1103 | } |
1104 | |
1105 | /// Device logical unit messaging device path node. |
1106 | #[repr (C, packed)] |
1107 | pub struct DeviceLogicalUnit { |
1108 | pub(super) header: DevicePathHeader, |
1109 | pub(super) logical_unit_number: u8, |
1110 | } |
1111 | |
1112 | impl DeviceLogicalUnit { |
1113 | /// Logical Unit Number. |
1114 | #[must_use ] |
1115 | pub fn logical_unit_number(&self) -> u8 { |
1116 | self.logical_unit_number |
1117 | } |
1118 | } |
1119 | |
1120 | impl fmt::Debug for DeviceLogicalUnit { |
1121 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1122 | f.debug_struct("DeviceLogicalUnit" ) |
1123 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
1124 | .finish() |
1125 | } |
1126 | } |
1127 | |
1128 | impl TryFrom<&DevicePathNode> for &DeviceLogicalUnit { |
1129 | type Error = NodeConversionError; |
1130 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1131 | if size_of_val(node) != size_of::<DeviceLogicalUnit>() { |
1132 | return Err(NodeConversionError::InvalidLength); |
1133 | } |
1134 | |
1135 | let node: *const DevicePathNode = node; |
1136 | let node: *const DeviceLogicalUnit = node.cast(); |
1137 | Ok(unsafe { &*node }) |
1138 | } |
1139 | } |
1140 | |
1141 | /// USB class messaging device path node. |
1142 | #[repr (C, packed)] |
1143 | pub struct UsbClass { |
1144 | pub(super) header: DevicePathHeader, |
1145 | pub(super) vendor_id: u16, |
1146 | pub(super) product_id: u16, |
1147 | pub(super) device_class: u8, |
1148 | pub(super) device_subclass: u8, |
1149 | pub(super) device_protocol: u8, |
1150 | } |
1151 | |
1152 | impl UsbClass { |
1153 | /// USB vendor ID. |
1154 | #[must_use ] |
1155 | pub fn vendor_id(&self) -> u16 { |
1156 | self.vendor_id |
1157 | } |
1158 | |
1159 | /// USB product ID. |
1160 | #[must_use ] |
1161 | pub fn product_id(&self) -> u16 { |
1162 | self.product_id |
1163 | } |
1164 | |
1165 | /// USB device class. |
1166 | #[must_use ] |
1167 | pub fn device_class(&self) -> u8 { |
1168 | self.device_class |
1169 | } |
1170 | |
1171 | /// USB device subclass. |
1172 | #[must_use ] |
1173 | pub fn device_subclass(&self) -> u8 { |
1174 | self.device_subclass |
1175 | } |
1176 | |
1177 | /// USB device protocol. |
1178 | #[must_use ] |
1179 | pub fn device_protocol(&self) -> u8 { |
1180 | self.device_protocol |
1181 | } |
1182 | } |
1183 | |
1184 | impl fmt::Debug for UsbClass { |
1185 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1186 | f.debug_struct("UsbClass" ) |
1187 | .field("vendor_id" , &{ self.vendor_id }) |
1188 | .field("product_id" , &{ self.product_id }) |
1189 | .field("device_class" , &{ self.device_class }) |
1190 | .field("device_subclass" , &{ self.device_subclass }) |
1191 | .field("device_protocol" , &{ self.device_protocol }) |
1192 | .finish() |
1193 | } |
1194 | } |
1195 | |
1196 | impl TryFrom<&DevicePathNode> for &UsbClass { |
1197 | type Error = NodeConversionError; |
1198 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1199 | if size_of_val(node) != size_of::<UsbClass>() { |
1200 | return Err(NodeConversionError::InvalidLength); |
1201 | } |
1202 | |
1203 | let node: *const DevicePathNode = node; |
1204 | let node: *const UsbClass = node.cast(); |
1205 | Ok(unsafe { &*node }) |
1206 | } |
1207 | } |
1208 | |
1209 | /// I2O messaging device path node. |
1210 | #[repr (C, packed)] |
1211 | pub struct I2o { |
1212 | pub(super) header: DevicePathHeader, |
1213 | pub(super) target_id: u32, |
1214 | } |
1215 | |
1216 | impl I2o { |
1217 | /// Target ID (TID). |
1218 | #[must_use ] |
1219 | pub fn target_id(&self) -> u32 { |
1220 | self.target_id |
1221 | } |
1222 | } |
1223 | |
1224 | impl fmt::Debug for I2o { |
1225 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1226 | f.debug_struct("I2o" ) |
1227 | .field("target_id" , &{ self.target_id }) |
1228 | .finish() |
1229 | } |
1230 | } |
1231 | |
1232 | impl TryFrom<&DevicePathNode> for &I2o { |
1233 | type Error = NodeConversionError; |
1234 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1235 | if size_of_val(node) != size_of::<I2o>() { |
1236 | return Err(NodeConversionError::InvalidLength); |
1237 | } |
1238 | |
1239 | let node: *const DevicePathNode = node; |
1240 | let node: *const I2o = node.cast(); |
1241 | Ok(unsafe { &*node }) |
1242 | } |
1243 | } |
1244 | |
1245 | /// MAC address messaging device path node. |
1246 | #[repr (C, packed)] |
1247 | pub struct MacAddress { |
1248 | pub(super) header: DevicePathHeader, |
1249 | pub(super) mac_address: [u8; 32usize], |
1250 | pub(super) interface_type: u8, |
1251 | } |
1252 | |
1253 | impl MacAddress { |
1254 | /// MAC address for a network interface, padded with zeros. |
1255 | #[must_use ] |
1256 | pub fn mac_address(&self) -> [u8; 32usize] { |
1257 | self.mac_address |
1258 | } |
1259 | |
1260 | /// Network interface type. See |
1261 | /// <https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-5> |
1262 | #[must_use ] |
1263 | pub fn interface_type(&self) -> u8 { |
1264 | self.interface_type |
1265 | } |
1266 | } |
1267 | |
1268 | impl fmt::Debug for MacAddress { |
1269 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1270 | f.debug_struct("MacAddress" ) |
1271 | .field("mac_address" , &{ self.mac_address }) |
1272 | .field("interface_type" , &{ self.interface_type }) |
1273 | .finish() |
1274 | } |
1275 | } |
1276 | |
1277 | impl TryFrom<&DevicePathNode> for &MacAddress { |
1278 | type Error = NodeConversionError; |
1279 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1280 | if size_of_val(node) != size_of::<MacAddress>() { |
1281 | return Err(NodeConversionError::InvalidLength); |
1282 | } |
1283 | |
1284 | let node: *const DevicePathNode = node; |
1285 | let node: *const MacAddress = node.cast(); |
1286 | Ok(unsafe { &*node }) |
1287 | } |
1288 | } |
1289 | |
1290 | /// IPv4 messaging device path node. |
1291 | #[repr (C, packed)] |
1292 | pub struct Ipv4 { |
1293 | pub(super) header: DevicePathHeader, |
1294 | pub(super) local_ip_address: [u8; 4usize], |
1295 | pub(super) remote_ip_address: [u8; 4usize], |
1296 | pub(super) local_port: u16, |
1297 | pub(super) remote_port: u16, |
1298 | pub(super) protocol: u16, |
1299 | pub(super) ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin, |
1300 | pub(super) gateway_ip_address: [u8; 4usize], |
1301 | pub(super) subnet_mask: [u8; 4usize], |
1302 | } |
1303 | |
1304 | impl Ipv4 { |
1305 | /// Local IPv4 address. |
1306 | #[must_use ] |
1307 | pub fn local_ip_address(&self) -> [u8; 4usize] { |
1308 | self.local_ip_address |
1309 | } |
1310 | |
1311 | /// Remote IPv4 address. |
1312 | #[must_use ] |
1313 | pub fn remote_ip_address(&self) -> [u8; 4usize] { |
1314 | self.remote_ip_address |
1315 | } |
1316 | |
1317 | /// Local port number. |
1318 | #[must_use ] |
1319 | pub fn local_port(&self) -> u16 { |
1320 | self.local_port |
1321 | } |
1322 | |
1323 | /// Remote port number. |
1324 | #[must_use ] |
1325 | pub fn remote_port(&self) -> u16 { |
1326 | self.remote_port |
1327 | } |
1328 | |
1329 | /// Network protocol. See |
1330 | /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml> |
1331 | #[must_use ] |
1332 | pub fn protocol(&self) -> u16 { |
1333 | self.protocol |
1334 | } |
1335 | |
1336 | /// Whether the source IP address is static or assigned via DHCP. |
1337 | #[must_use ] |
1338 | pub fn ip_address_origin(&self) -> crate::proto::device_path::messaging::Ipv4AddressOrigin { |
1339 | self.ip_address_origin |
1340 | } |
1341 | |
1342 | /// Gateway IP address. |
1343 | #[must_use ] |
1344 | pub fn gateway_ip_address(&self) -> [u8; 4usize] { |
1345 | self.gateway_ip_address |
1346 | } |
1347 | |
1348 | /// Subnet mask. |
1349 | #[must_use ] |
1350 | pub fn subnet_mask(&self) -> [u8; 4usize] { |
1351 | self.subnet_mask |
1352 | } |
1353 | } |
1354 | |
1355 | impl fmt::Debug for Ipv4 { |
1356 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1357 | f.debug_struct("Ipv4" ) |
1358 | .field("local_ip_address" , &{ self.local_ip_address }) |
1359 | .field("remote_ip_address" , &{ self.remote_ip_address }) |
1360 | .field("local_port" , &{ self.local_port }) |
1361 | .field("remote_port" , &{ self.remote_port }) |
1362 | .field("protocol" , &{ self.protocol }) |
1363 | .field("ip_address_origin" , &{ self.ip_address_origin }) |
1364 | .field("gateway_ip_address" , &{ self.gateway_ip_address }) |
1365 | .field("subnet_mask" , &{ self.subnet_mask }) |
1366 | .finish() |
1367 | } |
1368 | } |
1369 | |
1370 | impl TryFrom<&DevicePathNode> for &Ipv4 { |
1371 | type Error = NodeConversionError; |
1372 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1373 | if size_of_val(node) != size_of::<Ipv4>() { |
1374 | return Err(NodeConversionError::InvalidLength); |
1375 | } |
1376 | |
1377 | let node: *const DevicePathNode = node; |
1378 | let node: *const Ipv4 = node.cast(); |
1379 | Ok(unsafe { &*node }) |
1380 | } |
1381 | } |
1382 | |
1383 | /// IPv6 messaging device path node. |
1384 | #[repr (C, packed)] |
1385 | pub struct Ipv6 { |
1386 | pub(super) header: DevicePathHeader, |
1387 | pub(super) local_ip_address: [u8; 16usize], |
1388 | pub(super) remote_ip_address: [u8; 16usize], |
1389 | pub(super) local_port: u16, |
1390 | pub(super) remote_port: u16, |
1391 | pub(super) protocol: u16, |
1392 | pub(super) ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin, |
1393 | pub(super) prefix_length: u8, |
1394 | pub(super) gateway_ip_address: [u8; 16usize], |
1395 | } |
1396 | |
1397 | impl Ipv6 { |
1398 | /// Local Ipv6 address. |
1399 | #[must_use ] |
1400 | pub fn local_ip_address(&self) -> [u8; 16usize] { |
1401 | self.local_ip_address |
1402 | } |
1403 | |
1404 | /// Remote Ipv6 address. |
1405 | #[must_use ] |
1406 | pub fn remote_ip_address(&self) -> [u8; 16usize] { |
1407 | self.remote_ip_address |
1408 | } |
1409 | |
1410 | /// Local port number. |
1411 | #[must_use ] |
1412 | pub fn local_port(&self) -> u16 { |
1413 | self.local_port |
1414 | } |
1415 | |
1416 | /// Remote port number. |
1417 | #[must_use ] |
1418 | pub fn remote_port(&self) -> u16 { |
1419 | self.remote_port |
1420 | } |
1421 | |
1422 | /// Network protocol. See |
1423 | /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml> |
1424 | #[must_use ] |
1425 | pub fn protocol(&self) -> u16 { |
1426 | self.protocol |
1427 | } |
1428 | |
1429 | /// Origin of the local IP address. |
1430 | #[must_use ] |
1431 | pub fn ip_address_origin(&self) -> crate::proto::device_path::messaging::Ipv6AddressOrigin { |
1432 | self.ip_address_origin |
1433 | } |
1434 | |
1435 | /// Prefix length. |
1436 | #[must_use ] |
1437 | pub fn prefix_length(&self) -> u8 { |
1438 | self.prefix_length |
1439 | } |
1440 | |
1441 | /// Gateway IP address. |
1442 | #[must_use ] |
1443 | pub fn gateway_ip_address(&self) -> [u8; 16usize] { |
1444 | self.gateway_ip_address |
1445 | } |
1446 | } |
1447 | |
1448 | impl fmt::Debug for Ipv6 { |
1449 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1450 | f.debug_struct("Ipv6" ) |
1451 | .field("local_ip_address" , &{ self.local_ip_address }) |
1452 | .field("remote_ip_address" , &{ self.remote_ip_address }) |
1453 | .field("local_port" , &{ self.local_port }) |
1454 | .field("remote_port" , &{ self.remote_port }) |
1455 | .field("protocol" , &{ self.protocol }) |
1456 | .field("ip_address_origin" , &{ self.ip_address_origin }) |
1457 | .field("prefix_length" , &{ self.prefix_length }) |
1458 | .field("gateway_ip_address" , &{ self.gateway_ip_address }) |
1459 | .finish() |
1460 | } |
1461 | } |
1462 | |
1463 | impl TryFrom<&DevicePathNode> for &Ipv6 { |
1464 | type Error = NodeConversionError; |
1465 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1466 | if size_of_val(node) != size_of::<Ipv6>() { |
1467 | return Err(NodeConversionError::InvalidLength); |
1468 | } |
1469 | |
1470 | let node: *const DevicePathNode = node; |
1471 | let node: *const Ipv6 = node.cast(); |
1472 | Ok(unsafe { &*node }) |
1473 | } |
1474 | } |
1475 | |
1476 | /// VLAN messaging device path node. |
1477 | #[repr (C, packed)] |
1478 | pub struct Vlan { |
1479 | pub(super) header: DevicePathHeader, |
1480 | pub(super) vlan_id: u16, |
1481 | } |
1482 | |
1483 | impl Vlan { |
1484 | /// VLAN identifier (0-4094). |
1485 | #[must_use ] |
1486 | pub fn vlan_id(&self) -> u16 { |
1487 | self.vlan_id |
1488 | } |
1489 | } |
1490 | |
1491 | impl fmt::Debug for Vlan { |
1492 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1493 | f.debug_struct("Vlan" ) |
1494 | .field("vlan_id" , &{ self.vlan_id }) |
1495 | .finish() |
1496 | } |
1497 | } |
1498 | |
1499 | impl TryFrom<&DevicePathNode> for &Vlan { |
1500 | type Error = NodeConversionError; |
1501 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1502 | if size_of_val(node) != size_of::<Vlan>() { |
1503 | return Err(NodeConversionError::InvalidLength); |
1504 | } |
1505 | |
1506 | let node: *const DevicePathNode = node; |
1507 | let node: *const Vlan = node.cast(); |
1508 | Ok(unsafe { &*node }) |
1509 | } |
1510 | } |
1511 | |
1512 | /// InfiniBand messaging device path node. |
1513 | #[repr (C, packed)] |
1514 | pub struct Infiniband { |
1515 | pub(super) header: DevicePathHeader, |
1516 | pub(super) resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags, |
1517 | pub(super) port_gid: [u8; 16usize], |
1518 | pub(super) ioc_guid_or_service_id: u64, |
1519 | pub(super) target_port_id: u64, |
1520 | pub(super) device_id: u64, |
1521 | } |
1522 | |
1523 | impl Infiniband { |
1524 | /// Flags to identify/manage InfiniBand elements. |
1525 | #[must_use ] |
1526 | pub fn resource_flags( |
1527 | &self, |
1528 | ) -> crate::proto::device_path::messaging::InfinibandResourceFlags { |
1529 | self.resource_flags |
1530 | } |
1531 | |
1532 | /// 128-bit Global Identifier for remote fabric port. Note that |
1533 | /// this is not the same as a UEFI GUID. |
1534 | #[must_use ] |
1535 | pub fn port_gid(&self) -> [u8; 16usize] { |
1536 | self.port_gid |
1537 | } |
1538 | |
1539 | /// IOC GUID if bit 0 of `resource_flags` is unset, or Service |
1540 | /// ID if bit 0 of `resource_flags` is set. |
1541 | #[must_use ] |
1542 | pub fn ioc_guid_or_service_id(&self) -> u64 { |
1543 | self.ioc_guid_or_service_id |
1544 | } |
1545 | |
1546 | /// 64-bit persistent ID of remote IOC port. |
1547 | #[must_use ] |
1548 | pub fn target_port_id(&self) -> u64 { |
1549 | self.target_port_id |
1550 | } |
1551 | |
1552 | /// 64-bit persistent ID of remote device.. |
1553 | #[must_use ] |
1554 | pub fn device_id(&self) -> u64 { |
1555 | self.device_id |
1556 | } |
1557 | } |
1558 | |
1559 | impl fmt::Debug for Infiniband { |
1560 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1561 | f.debug_struct("Infiniband" ) |
1562 | .field("resource_flags" , &{ self.resource_flags }) |
1563 | .field("port_gid" , &{ self.port_gid }) |
1564 | .field("ioc_guid_or_service_id" , &{ self.ioc_guid_or_service_id }) |
1565 | .field("target_port_id" , &{ self.target_port_id }) |
1566 | .field("device_id" , &{ self.device_id }) |
1567 | .finish() |
1568 | } |
1569 | } |
1570 | |
1571 | impl TryFrom<&DevicePathNode> for &Infiniband { |
1572 | type Error = NodeConversionError; |
1573 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1574 | if size_of_val(node) != size_of::<Infiniband>() { |
1575 | return Err(NodeConversionError::InvalidLength); |
1576 | } |
1577 | |
1578 | let node: *const DevicePathNode = node; |
1579 | let node: *const Infiniband = node.cast(); |
1580 | Ok(unsafe { &*node }) |
1581 | } |
1582 | } |
1583 | |
1584 | /// UART messaging device path node. |
1585 | #[repr (C, packed)] |
1586 | pub struct Uart { |
1587 | pub(super) header: DevicePathHeader, |
1588 | pub(super) _reserved: u32, |
1589 | pub(super) baud_rate: u64, |
1590 | pub(super) data_bits: u8, |
1591 | pub(super) parity: crate::proto::device_path::messaging::Parity, |
1592 | pub(super) stop_bits: crate::proto::device_path::messaging::StopBits, |
1593 | } |
1594 | |
1595 | impl Uart { |
1596 | /// Baud rate setting, or 0 to use the device's default. |
1597 | #[must_use ] |
1598 | pub fn baud_rate(&self) -> u64 { |
1599 | self.baud_rate |
1600 | } |
1601 | |
1602 | /// Number of data bits, or 0 to use the device's default. |
1603 | #[must_use ] |
1604 | pub fn data_bits(&self) -> u8 { |
1605 | self.data_bits |
1606 | } |
1607 | |
1608 | /// Parity setting. |
1609 | #[must_use ] |
1610 | pub fn parity(&self) -> crate::proto::device_path::messaging::Parity { |
1611 | self.parity |
1612 | } |
1613 | |
1614 | /// Number of stop bits. |
1615 | #[must_use ] |
1616 | pub fn stop_bits(&self) -> crate::proto::device_path::messaging::StopBits { |
1617 | self.stop_bits |
1618 | } |
1619 | } |
1620 | |
1621 | impl fmt::Debug for Uart { |
1622 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1623 | f.debug_struct("Uart" ) |
1624 | .field("_reserved" , &{ self._reserved }) |
1625 | .field("baud_rate" , &{ self.baud_rate }) |
1626 | .field("data_bits" , &{ self.data_bits }) |
1627 | .field("parity" , &{ self.parity }) |
1628 | .field("stop_bits" , &{ self.stop_bits }) |
1629 | .finish() |
1630 | } |
1631 | } |
1632 | |
1633 | impl TryFrom<&DevicePathNode> for &Uart { |
1634 | type Error = NodeConversionError; |
1635 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1636 | if size_of_val(node) != size_of::<Uart>() { |
1637 | return Err(NodeConversionError::InvalidLength); |
1638 | } |
1639 | |
1640 | let node: *const DevicePathNode = node; |
1641 | let node: *const Uart = node.cast(); |
1642 | Ok(unsafe { &*node }) |
1643 | } |
1644 | } |
1645 | |
1646 | /// Vendor-defined messaging device path node. |
1647 | #[repr (C, packed)] |
1648 | #[derive (Pointee)] |
1649 | pub struct Vendor { |
1650 | pub(super) header: DevicePathHeader, |
1651 | pub(super) vendor_guid: Guid, |
1652 | pub(super) vendor_defined_data: [u8], |
1653 | } |
1654 | |
1655 | impl Vendor { |
1656 | /// Vendor-assigned GUID that defines the data that follows. |
1657 | #[must_use ] |
1658 | pub fn vendor_guid(&self) -> Guid { |
1659 | self.vendor_guid |
1660 | } |
1661 | |
1662 | /// Vendor-defined data. |
1663 | #[must_use ] |
1664 | pub fn vendor_defined_data(&self) -> &[u8] { |
1665 | &self.vendor_defined_data |
1666 | } |
1667 | } |
1668 | |
1669 | impl fmt::Debug for Vendor { |
1670 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1671 | f.debug_struct("Vendor" ) |
1672 | .field("vendor_guid" , &{ self.vendor_guid }) |
1673 | .field("vendor_defined_data" , { |
1674 | let ptr = addr_of!(self.vendor_defined_data); |
1675 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
1676 | let byte_len = size_of::<u8>() * len; |
1677 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
1678 | }) |
1679 | .finish() |
1680 | } |
1681 | } |
1682 | |
1683 | impl TryFrom<&DevicePathNode> for &Vendor { |
1684 | type Error = NodeConversionError; |
1685 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1686 | let static_size = 20usize; |
1687 | let dst_size = size_of_val(node) |
1688 | .checked_sub(static_size) |
1689 | .ok_or(NodeConversionError::InvalidLength)?; |
1690 | let elem_size = size_of::<u8>(); |
1691 | if dst_size % elem_size != 0 { |
1692 | return Err(NodeConversionError::InvalidLength); |
1693 | } |
1694 | |
1695 | let node: *const DevicePathNode = node; |
1696 | let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
1697 | Ok(unsafe { &*node }) |
1698 | } |
1699 | } |
1700 | |
1701 | /// Serial Attached SCSI (SAS) extended messaging device path node. |
1702 | #[repr (C, packed)] |
1703 | pub struct SasEx { |
1704 | pub(super) header: DevicePathHeader, |
1705 | pub(super) sas_address: [u8; 8usize], |
1706 | pub(super) logical_unit_number: [u8; 8usize], |
1707 | pub(super) info: u16, |
1708 | pub(super) relative_target_port: u16, |
1709 | } |
1710 | |
1711 | impl SasEx { |
1712 | /// SAS address. |
1713 | #[must_use ] |
1714 | pub fn sas_address(&self) -> [u8; 8usize] { |
1715 | self.sas_address |
1716 | } |
1717 | |
1718 | /// Logical Unit Number. |
1719 | #[must_use ] |
1720 | pub fn logical_unit_number(&self) -> [u8; 8usize] { |
1721 | self.logical_unit_number |
1722 | } |
1723 | |
1724 | /// Information about the device and its interconnect. |
1725 | #[must_use ] |
1726 | pub fn info(&self) -> u16 { |
1727 | self.info |
1728 | } |
1729 | |
1730 | /// Relative Target Port (RTP). |
1731 | #[must_use ] |
1732 | pub fn relative_target_port(&self) -> u16 { |
1733 | self.relative_target_port |
1734 | } |
1735 | } |
1736 | |
1737 | impl fmt::Debug for SasEx { |
1738 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1739 | f.debug_struct("SasEx" ) |
1740 | .field("sas_address" , &{ self.sas_address }) |
1741 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
1742 | .field("info" , &{ self.info }) |
1743 | .field("relative_target_port" , &{ self.relative_target_port }) |
1744 | .finish() |
1745 | } |
1746 | } |
1747 | |
1748 | impl TryFrom<&DevicePathNode> for &SasEx { |
1749 | type Error = NodeConversionError; |
1750 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1751 | if size_of_val(node) != size_of::<SasEx>() { |
1752 | return Err(NodeConversionError::InvalidLength); |
1753 | } |
1754 | |
1755 | let node: *const DevicePathNode = node; |
1756 | let node: *const SasEx = node.cast(); |
1757 | Ok(unsafe { &*node }) |
1758 | } |
1759 | } |
1760 | |
1761 | /// iSCSI messaging device path node. |
1762 | #[repr (C, packed)] |
1763 | #[derive (Pointee)] |
1764 | pub struct Iscsi { |
1765 | pub(super) header: DevicePathHeader, |
1766 | pub(super) protocol: crate::proto::device_path::messaging::IscsiProtocol, |
1767 | pub(super) options: crate::proto::device_path::messaging::IscsiLoginOptions, |
1768 | pub(super) logical_unit_number: [u8; 8usize], |
1769 | pub(super) target_portal_group_tag: u16, |
1770 | pub(super) iscsi_target_name: [u8], |
1771 | } |
1772 | |
1773 | impl Iscsi { |
1774 | /// Network protocol. |
1775 | #[must_use ] |
1776 | pub fn protocol(&self) -> crate::proto::device_path::messaging::IscsiProtocol { |
1777 | self.protocol |
1778 | } |
1779 | |
1780 | /// iSCSI login options (bitfield). |
1781 | #[must_use ] |
1782 | pub fn options(&self) -> crate::proto::device_path::messaging::IscsiLoginOptions { |
1783 | self.options |
1784 | } |
1785 | |
1786 | /// iSCSI Logical Unit Number. |
1787 | #[must_use ] |
1788 | pub fn logical_unit_number(&self) -> [u8; 8usize] { |
1789 | self.logical_unit_number |
1790 | } |
1791 | |
1792 | /// iSCSI Target Portal group tag the initiator intends to |
1793 | /// establish a session with. |
1794 | #[must_use ] |
1795 | pub fn target_portal_group_tag(&self) -> u16 { |
1796 | self.target_portal_group_tag |
1797 | } |
1798 | |
1799 | /// iSCSI Node Target name. |
1800 | /// |
1801 | /// The UEFI Specification does not specify how the string is |
1802 | /// encoded, but gives one example that appears to be |
1803 | /// null-terminated ASCII. |
1804 | #[must_use ] |
1805 | pub fn iscsi_target_name(&self) -> &[u8] { |
1806 | &self.iscsi_target_name |
1807 | } |
1808 | } |
1809 | |
1810 | impl fmt::Debug for Iscsi { |
1811 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1812 | f.debug_struct("Iscsi" ) |
1813 | .field("protocol" , &{ self.protocol }) |
1814 | .field("options" , &{ self.options }) |
1815 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
1816 | .field("target_portal_group_tag" , &{ self.target_portal_group_tag }) |
1817 | .field("iscsi_target_name" , { |
1818 | let ptr = addr_of!(self.iscsi_target_name); |
1819 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
1820 | let byte_len = size_of::<u8>() * len; |
1821 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
1822 | }) |
1823 | .finish() |
1824 | } |
1825 | } |
1826 | |
1827 | impl TryFrom<&DevicePathNode> for &Iscsi { |
1828 | type Error = NodeConversionError; |
1829 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1830 | let static_size = 18usize; |
1831 | let dst_size = size_of_val(node) |
1832 | .checked_sub(static_size) |
1833 | .ok_or(NodeConversionError::InvalidLength)?; |
1834 | let elem_size = size_of::<u8>(); |
1835 | if dst_size % elem_size != 0 { |
1836 | return Err(NodeConversionError::InvalidLength); |
1837 | } |
1838 | |
1839 | let node: *const DevicePathNode = node; |
1840 | let node: *const Iscsi = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
1841 | Ok(unsafe { &*node }) |
1842 | } |
1843 | } |
1844 | |
1845 | /// NVM Express namespace messaging device path node. |
1846 | #[repr (C, packed)] |
1847 | pub struct NvmeNamespace { |
1848 | pub(super) header: DevicePathHeader, |
1849 | pub(super) namespace_identifier: u32, |
1850 | pub(super) ieee_extended_unique_identifier: u64, |
1851 | } |
1852 | |
1853 | impl NvmeNamespace { |
1854 | /// Namespace identifier (NSID). The values 0 and 0xffff_ffff |
1855 | /// are invalid. |
1856 | #[must_use ] |
1857 | pub fn namespace_identifier(&self) -> u32 { |
1858 | self.namespace_identifier |
1859 | } |
1860 | |
1861 | /// IEEE Extended Unique Identifier (EUI-64), or 0 if the device |
1862 | /// does not have a EUI-64. |
1863 | #[must_use ] |
1864 | pub fn ieee_extended_unique_identifier(&self) -> u64 { |
1865 | self.ieee_extended_unique_identifier |
1866 | } |
1867 | } |
1868 | |
1869 | impl fmt::Debug for NvmeNamespace { |
1870 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1871 | f.debug_struct("NvmeNamespace" ) |
1872 | .field("namespace_identifier" , &{ self.namespace_identifier }) |
1873 | .field("ieee_extended_unique_identifier" , &{ |
1874 | self.ieee_extended_unique_identifier |
1875 | }) |
1876 | .finish() |
1877 | } |
1878 | } |
1879 | |
1880 | impl TryFrom<&DevicePathNode> for &NvmeNamespace { |
1881 | type Error = NodeConversionError; |
1882 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1883 | if size_of_val(node) != size_of::<NvmeNamespace>() { |
1884 | return Err(NodeConversionError::InvalidLength); |
1885 | } |
1886 | |
1887 | let node: *const DevicePathNode = node; |
1888 | let node: *const NvmeNamespace = node.cast(); |
1889 | Ok(unsafe { &*node }) |
1890 | } |
1891 | } |
1892 | |
1893 | /// Uniform Resource Identifier (URI) messaging device path node. |
1894 | #[repr (C, packed)] |
1895 | #[derive (Pointee)] |
1896 | pub struct Uri { |
1897 | pub(super) header: DevicePathHeader, |
1898 | pub(super) value: [u8], |
1899 | } |
1900 | |
1901 | impl Uri { |
1902 | /// URI as defined by [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986). |
1903 | #[must_use ] |
1904 | pub fn value(&self) -> &[u8] { |
1905 | &self.value |
1906 | } |
1907 | } |
1908 | |
1909 | impl fmt::Debug for Uri { |
1910 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1911 | f.debug_struct("Uri" ) |
1912 | .field("value" , { |
1913 | let ptr = addr_of!(self.value); |
1914 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
1915 | let byte_len = size_of::<u8>() * len; |
1916 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
1917 | }) |
1918 | .finish() |
1919 | } |
1920 | } |
1921 | |
1922 | impl TryFrom<&DevicePathNode> for &Uri { |
1923 | type Error = NodeConversionError; |
1924 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1925 | let static_size = 4usize; |
1926 | let dst_size = size_of_val(node) |
1927 | .checked_sub(static_size) |
1928 | .ok_or(NodeConversionError::InvalidLength)?; |
1929 | let elem_size = size_of::<u8>(); |
1930 | if dst_size % elem_size != 0 { |
1931 | return Err(NodeConversionError::InvalidLength); |
1932 | } |
1933 | |
1934 | let node: *const DevicePathNode = node; |
1935 | let node: *const Uri = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
1936 | Ok(unsafe { &*node }) |
1937 | } |
1938 | } |
1939 | |
1940 | /// Universal Flash Storage (UFS) messaging device path node. |
1941 | #[repr (C, packed)] |
1942 | pub struct Ufs { |
1943 | pub(super) header: DevicePathHeader, |
1944 | pub(super) target_id: u8, |
1945 | pub(super) logical_unit_number: u8, |
1946 | } |
1947 | |
1948 | impl Ufs { |
1949 | /// Target ID on the UFS interface (PUN). |
1950 | #[must_use ] |
1951 | pub fn target_id(&self) -> u8 { |
1952 | self.target_id |
1953 | } |
1954 | |
1955 | /// Logical Unit Number (LUN). |
1956 | #[must_use ] |
1957 | pub fn logical_unit_number(&self) -> u8 { |
1958 | self.logical_unit_number |
1959 | } |
1960 | } |
1961 | |
1962 | impl fmt::Debug for Ufs { |
1963 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1964 | f.debug_struct("Ufs" ) |
1965 | .field("target_id" , &{ self.target_id }) |
1966 | .field("logical_unit_number" , &{ self.logical_unit_number }) |
1967 | .finish() |
1968 | } |
1969 | } |
1970 | |
1971 | impl TryFrom<&DevicePathNode> for &Ufs { |
1972 | type Error = NodeConversionError; |
1973 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
1974 | if size_of_val(node) != size_of::<Ufs>() { |
1975 | return Err(NodeConversionError::InvalidLength); |
1976 | } |
1977 | |
1978 | let node: *const DevicePathNode = node; |
1979 | let node: *const Ufs = node.cast(); |
1980 | Ok(unsafe { &*node }) |
1981 | } |
1982 | } |
1983 | |
1984 | /// Secure Digital (SD) messaging device path node. |
1985 | #[repr (C, packed)] |
1986 | pub struct Sd { |
1987 | pub(super) header: DevicePathHeader, |
1988 | pub(super) slot_number: u8, |
1989 | } |
1990 | |
1991 | impl Sd { |
1992 | /// Slot number. |
1993 | #[must_use ] |
1994 | pub fn slot_number(&self) -> u8 { |
1995 | self.slot_number |
1996 | } |
1997 | } |
1998 | |
1999 | impl fmt::Debug for Sd { |
2000 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2001 | f.debug_struct("Sd" ) |
2002 | .field("slot_number" , &{ self.slot_number }) |
2003 | .finish() |
2004 | } |
2005 | } |
2006 | |
2007 | impl TryFrom<&DevicePathNode> for &Sd { |
2008 | type Error = NodeConversionError; |
2009 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2010 | if size_of_val(node) != size_of::<Sd>() { |
2011 | return Err(NodeConversionError::InvalidLength); |
2012 | } |
2013 | |
2014 | let node: *const DevicePathNode = node; |
2015 | let node: *const Sd = node.cast(); |
2016 | Ok(unsafe { &*node }) |
2017 | } |
2018 | } |
2019 | |
2020 | /// Bluetooth messaging device path node. |
2021 | #[repr (C, packed)] |
2022 | pub struct Bluetooth { |
2023 | pub(super) header: DevicePathHeader, |
2024 | pub(super) device_address: [u8; 6usize], |
2025 | } |
2026 | |
2027 | impl Bluetooth { |
2028 | /// 48-bit bluetooth device address. |
2029 | #[must_use ] |
2030 | pub fn device_address(&self) -> [u8; 6usize] { |
2031 | self.device_address |
2032 | } |
2033 | } |
2034 | |
2035 | impl fmt::Debug for Bluetooth { |
2036 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2037 | f.debug_struct("Bluetooth" ) |
2038 | .field("device_address" , &{ self.device_address }) |
2039 | .finish() |
2040 | } |
2041 | } |
2042 | |
2043 | impl TryFrom<&DevicePathNode> for &Bluetooth { |
2044 | type Error = NodeConversionError; |
2045 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2046 | if size_of_val(node) != size_of::<Bluetooth>() { |
2047 | return Err(NodeConversionError::InvalidLength); |
2048 | } |
2049 | |
2050 | let node: *const DevicePathNode = node; |
2051 | let node: *const Bluetooth = node.cast(); |
2052 | Ok(unsafe { &*node }) |
2053 | } |
2054 | } |
2055 | |
2056 | /// Wi-Fi messaging device path node. |
2057 | #[repr (C, packed)] |
2058 | pub struct Wifi { |
2059 | pub(super) header: DevicePathHeader, |
2060 | pub(super) ssid: [u8; 32usize], |
2061 | } |
2062 | |
2063 | impl Wifi { |
2064 | /// Service set identifier (SSID). |
2065 | #[must_use ] |
2066 | pub fn ssid(&self) -> [u8; 32usize] { |
2067 | self.ssid |
2068 | } |
2069 | } |
2070 | |
2071 | impl fmt::Debug for Wifi { |
2072 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2073 | f.debug_struct("Wifi" ) |
2074 | .field("ssid" , &{ self.ssid }) |
2075 | .finish() |
2076 | } |
2077 | } |
2078 | |
2079 | impl TryFrom<&DevicePathNode> for &Wifi { |
2080 | type Error = NodeConversionError; |
2081 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2082 | if size_of_val(node) != size_of::<Wifi>() { |
2083 | return Err(NodeConversionError::InvalidLength); |
2084 | } |
2085 | |
2086 | let node: *const DevicePathNode = node; |
2087 | let node: *const Wifi = node.cast(); |
2088 | Ok(unsafe { &*node }) |
2089 | } |
2090 | } |
2091 | |
2092 | /// Embedded Multi-Media Card (eMMC) messaging device path node. |
2093 | #[repr (C, packed)] |
2094 | pub struct Emmc { |
2095 | pub(super) header: DevicePathHeader, |
2096 | pub(super) slot_number: u8, |
2097 | } |
2098 | |
2099 | impl Emmc { |
2100 | /// Slot number. |
2101 | #[must_use ] |
2102 | pub fn slot_number(&self) -> u8 { |
2103 | self.slot_number |
2104 | } |
2105 | } |
2106 | |
2107 | impl fmt::Debug for Emmc { |
2108 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2109 | f.debug_struct("Emmc" ) |
2110 | .field("slot_number" , &{ self.slot_number }) |
2111 | .finish() |
2112 | } |
2113 | } |
2114 | |
2115 | impl TryFrom<&DevicePathNode> for &Emmc { |
2116 | type Error = NodeConversionError; |
2117 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2118 | if size_of_val(node) != size_of::<Emmc>() { |
2119 | return Err(NodeConversionError::InvalidLength); |
2120 | } |
2121 | |
2122 | let node: *const DevicePathNode = node; |
2123 | let node: *const Emmc = node.cast(); |
2124 | Ok(unsafe { &*node }) |
2125 | } |
2126 | } |
2127 | |
2128 | /// BluetoothLE messaging device path node. |
2129 | #[repr (C, packed)] |
2130 | pub struct BluetoothLe { |
2131 | pub(super) header: DevicePathHeader, |
2132 | pub(super) device_address: [u8; 6usize], |
2133 | pub(super) address_type: crate::proto::device_path::messaging::BluetoothLeAddressType, |
2134 | } |
2135 | |
2136 | impl BluetoothLe { |
2137 | /// 48-bit bluetooth device address. |
2138 | #[must_use ] |
2139 | pub fn device_address(&self) -> [u8; 6usize] { |
2140 | self.device_address |
2141 | } |
2142 | |
2143 | /// Address type. |
2144 | #[must_use ] |
2145 | pub fn address_type(&self) -> crate::proto::device_path::messaging::BluetoothLeAddressType { |
2146 | self.address_type |
2147 | } |
2148 | } |
2149 | |
2150 | impl fmt::Debug for BluetoothLe { |
2151 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2152 | f.debug_struct("BluetoothLe" ) |
2153 | .field("device_address" , &{ self.device_address }) |
2154 | .field("address_type" , &{ self.address_type }) |
2155 | .finish() |
2156 | } |
2157 | } |
2158 | |
2159 | impl TryFrom<&DevicePathNode> for &BluetoothLe { |
2160 | type Error = NodeConversionError; |
2161 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2162 | if size_of_val(node) != size_of::<BluetoothLe>() { |
2163 | return Err(NodeConversionError::InvalidLength); |
2164 | } |
2165 | |
2166 | let node: *const DevicePathNode = node; |
2167 | let node: *const BluetoothLe = node.cast(); |
2168 | Ok(unsafe { &*node }) |
2169 | } |
2170 | } |
2171 | |
2172 | /// DNS messaging device path node. |
2173 | #[repr (C, packed)] |
2174 | #[derive (Pointee)] |
2175 | pub struct Dns { |
2176 | pub(super) header: DevicePathHeader, |
2177 | pub(super) address_type: crate::proto::device_path::messaging::DnsAddressType, |
2178 | pub(super) addresses: [IpAddress], |
2179 | } |
2180 | |
2181 | impl Dns { |
2182 | /// Whether the addresses are IPv4 or IPv6. |
2183 | #[must_use ] |
2184 | pub fn address_type(&self) -> crate::proto::device_path::messaging::DnsAddressType { |
2185 | self.address_type |
2186 | } |
2187 | |
2188 | /// One or more instances of the DNS server address. |
2189 | #[must_use ] |
2190 | pub fn addresses(&self) -> UnalignedSlice<IpAddress> { |
2191 | let ptr: *const [IpAddress] = addr_of!(self.addresses); |
2192 | let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr); |
2193 | unsafe { UnalignedSlice::new(ptr.cast::<IpAddress>(), len) } |
2194 | } |
2195 | } |
2196 | |
2197 | impl fmt::Debug for Dns { |
2198 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2199 | f.debug_struct("Dns" ) |
2200 | .field("address_type" , &{ self.address_type }) |
2201 | .field("addresses" , { |
2202 | let ptr = addr_of!(self.addresses); |
2203 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2204 | let byte_len = size_of::<IpAddress>() * len; |
2205 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2206 | }) |
2207 | .finish() |
2208 | } |
2209 | } |
2210 | |
2211 | impl TryFrom<&DevicePathNode> for &Dns { |
2212 | type Error = NodeConversionError; |
2213 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2214 | let static_size = 5usize; |
2215 | let dst_size = size_of_val(node) |
2216 | .checked_sub(static_size) |
2217 | .ok_or(NodeConversionError::InvalidLength)?; |
2218 | let elem_size = size_of::<IpAddress>(); |
2219 | if dst_size % elem_size != 0 { |
2220 | return Err(NodeConversionError::InvalidLength); |
2221 | } |
2222 | |
2223 | let node: *const DevicePathNode = node; |
2224 | let node: *const Dns = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2225 | Ok(unsafe { &*node }) |
2226 | } |
2227 | } |
2228 | |
2229 | /// NVDIMM namespace messaging device path node. |
2230 | #[repr (C, packed)] |
2231 | pub struct NvdimmNamespace { |
2232 | pub(super) header: DevicePathHeader, |
2233 | pub(super) uuid: [u8; 16usize], |
2234 | } |
2235 | |
2236 | impl NvdimmNamespace { |
2237 | /// Namespace unique label identifier. |
2238 | #[must_use ] |
2239 | pub fn uuid(&self) -> [u8; 16usize] { |
2240 | self.uuid |
2241 | } |
2242 | } |
2243 | |
2244 | impl fmt::Debug for NvdimmNamespace { |
2245 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2246 | f.debug_struct("NvdimmNamespace" ) |
2247 | .field("uuid" , &{ self.uuid }) |
2248 | .finish() |
2249 | } |
2250 | } |
2251 | |
2252 | impl TryFrom<&DevicePathNode> for &NvdimmNamespace { |
2253 | type Error = NodeConversionError; |
2254 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2255 | if size_of_val(node) != size_of::<NvdimmNamespace>() { |
2256 | return Err(NodeConversionError::InvalidLength); |
2257 | } |
2258 | |
2259 | let node: *const DevicePathNode = node; |
2260 | let node: *const NvdimmNamespace = node.cast(); |
2261 | Ok(unsafe { &*node }) |
2262 | } |
2263 | } |
2264 | |
2265 | /// REST service messaging device path node. |
2266 | #[repr (C, packed)] |
2267 | #[derive (Pointee)] |
2268 | pub struct RestService { |
2269 | pub(super) header: DevicePathHeader, |
2270 | pub(super) service_type: crate::proto::device_path::messaging::RestServiceType, |
2271 | pub(super) access_mode: crate::proto::device_path::messaging::RestServiceAccessMode, |
2272 | pub(super) vendor_guid_and_data: [u8], |
2273 | } |
2274 | |
2275 | impl RestService { |
2276 | /// Type of REST service. |
2277 | #[must_use ] |
2278 | pub fn service_type(&self) -> crate::proto::device_path::messaging::RestServiceType { |
2279 | self.service_type |
2280 | } |
2281 | |
2282 | /// Whether the service is in-band or out-of-band. |
2283 | #[must_use ] |
2284 | pub fn access_mode(&self) -> crate::proto::device_path::messaging::RestServiceAccessMode { |
2285 | self.access_mode |
2286 | } |
2287 | } |
2288 | |
2289 | impl fmt::Debug for RestService { |
2290 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2291 | f.debug_struct("RestService" ) |
2292 | .field("service_type" , &{ self.service_type }) |
2293 | .field("access_mode" , &{ self.access_mode }) |
2294 | .field("vendor_guid_and_data" , { |
2295 | let ptr = addr_of!(self.vendor_guid_and_data); |
2296 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2297 | let byte_len = size_of::<u8>() * len; |
2298 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2299 | }) |
2300 | .finish() |
2301 | } |
2302 | } |
2303 | |
2304 | impl TryFrom<&DevicePathNode> for &RestService { |
2305 | type Error = NodeConversionError; |
2306 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2307 | let static_size = 6usize; |
2308 | let dst_size = size_of_val(node) |
2309 | .checked_sub(static_size) |
2310 | .ok_or(NodeConversionError::InvalidLength)?; |
2311 | let elem_size = size_of::<u8>(); |
2312 | if dst_size % elem_size != 0 { |
2313 | return Err(NodeConversionError::InvalidLength); |
2314 | } |
2315 | |
2316 | let node: *const DevicePathNode = node; |
2317 | let node: *const RestService = |
2318 | ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2319 | Ok(unsafe { &*node }) |
2320 | } |
2321 | } |
2322 | |
2323 | /// NVME over Fabric (NVMe-oF) namespace messaging device path node. |
2324 | #[repr (C, packed)] |
2325 | #[derive (Pointee)] |
2326 | pub struct NvmeOfNamespace { |
2327 | pub(super) header: DevicePathHeader, |
2328 | pub(super) nidt: u8, |
2329 | pub(super) nid: [u8; 16usize], |
2330 | pub(super) subsystem_nqn: [u8], |
2331 | } |
2332 | |
2333 | impl NvmeOfNamespace { |
2334 | /// Namespace Identifier Type (NIDT). |
2335 | #[must_use ] |
2336 | pub fn nidt(&self) -> u8 { |
2337 | self.nidt |
2338 | } |
2339 | |
2340 | /// Namespace Identifier (NID). |
2341 | #[must_use ] |
2342 | pub fn nid(&self) -> [u8; 16usize] { |
2343 | self.nid |
2344 | } |
2345 | |
2346 | /// Unique identifier of an NVM subsystem stored as a |
2347 | /// null-terminated UTF-8 string. Maximum length of 224 bytes. |
2348 | #[must_use ] |
2349 | pub fn subsystem_nqn(&self) -> &[u8] { |
2350 | &self.subsystem_nqn |
2351 | } |
2352 | } |
2353 | |
2354 | impl fmt::Debug for NvmeOfNamespace { |
2355 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2356 | f.debug_struct("NvmeOfNamespace" ) |
2357 | .field("nidt" , &{ self.nidt }) |
2358 | .field("nid" , &{ self.nid }) |
2359 | .field("subsystem_nqn" , { |
2360 | let ptr = addr_of!(self.subsystem_nqn); |
2361 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2362 | let byte_len = size_of::<u8>() * len; |
2363 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2364 | }) |
2365 | .finish() |
2366 | } |
2367 | } |
2368 | |
2369 | impl TryFrom<&DevicePathNode> for &NvmeOfNamespace { |
2370 | type Error = NodeConversionError; |
2371 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2372 | let static_size = 21usize; |
2373 | let dst_size = size_of_val(node) |
2374 | .checked_sub(static_size) |
2375 | .ok_or(NodeConversionError::InvalidLength)?; |
2376 | let elem_size = size_of::<u8>(); |
2377 | if dst_size % elem_size != 0 { |
2378 | return Err(NodeConversionError::InvalidLength); |
2379 | } |
2380 | |
2381 | let node: *const DevicePathNode = node; |
2382 | let node: *const NvmeOfNamespace = |
2383 | ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2384 | Ok(unsafe { &*node }) |
2385 | } |
2386 | } |
2387 | |
2388 | newtype_enum! { # [doc = " Whether the ATAPI device is primary or secondary." ] pub enum PrimarySecondary : u8 => { # [doc = " Primary." ] PRIMARY = 0x00 , # [doc = " Secondary." ] SECONDARY = 0x01 , } |
2389 | |
2390 | } |
2391 | |
2392 | newtype_enum! { # [doc = " Whether the ATAPI device is master or slave." ] pub enum MasterSlave : u8 => { # [doc = " Master mode." ] MASTER = 0x00 , # [doc = " Slave mode." ] SLAVE = 0x01 , } |
2393 | |
2394 | } |
2395 | |
2396 | newtype_enum! { # [doc = " Origin of the source IP address." ] pub enum Ipv4AddressOrigin : u8 => { # [doc = " Source IP address was assigned through DHCP." ] DHCP = 0x00 , # [doc = " Source IP address is statically bound." ] STATIC = 0x01 , } |
2397 | |
2398 | } |
2399 | |
2400 | newtype_enum! { # [doc = " Origin of the local IP address." ] pub enum Ipv6AddressOrigin : u8 => { # [doc = " Local IP address was manually configured." ] MANUAL = 0x00 , # [doc = " Local IP address assigned through IPv6 stateless" ] # [doc = " auto-configuration." ] STATELESS_AUTO_CONFIGURATION = 0x01 , # [doc = " Local IP address assigned through IPv6 stateful" ] # [doc = " configuration." ] STATEFUL_CONFIGURATION = 0x02 , } |
2401 | |
2402 | } |
2403 | |
2404 | bitflags! { # [doc = " Flags to identify/manage InfiniBand elements." ] # [repr (transparent)] pub struct InfinibandResourceFlags : u32 { # [doc = " Set = service, unset = IOC." ] const SERVICE = 0x0000_0001 ; # [doc = " Extended boot environment." ] const EXTENDED_BOOT_ENVIRONMENT = 0x0000_0002 ; # [doc = " Console protocol." ] const CONSOLE_PROTOCOL = 0x0000_0004 ; # [doc = " Storage protocol." ] const STORAGE_PROTOCOL = 0x0000_0008 ; # [doc = " Network protocol." ] const NETWORK_PROTOCOL = 0x0000_0010 ; } |
2405 | |
2406 | } |
2407 | |
2408 | newtype_enum! { # [doc = " UART parity setting." ] pub enum Parity : u8 => { # [doc = " Default parity." ] DEFAULT = 0x00 , # [doc = " No parity." ] NO = 0x01 , # [doc = " Even parity." ] EVEN = 0x02 , # [doc = " Odd parity." ] ODD = 0x03 , # [doc = " Mark parity." ] MARK = 0x04 , # [doc = " Space parity." ] SPACE = 0x05 , } |
2409 | |
2410 | } |
2411 | |
2412 | newtype_enum! { # [doc = " UART number of stop bits." ] pub enum StopBits : u8 => { # [doc = " Default number of stop bits." ] DEFAULT = 0x00 , # [doc = " 1 stop bit." ] ONE = 0x01 , # [doc = " 1.5 stop bits." ] ONE_POINT_FIVE = 0x02 , # [doc = " 2 stop bits." ] TWO = 0x03 , } |
2413 | |
2414 | } |
2415 | |
2416 | newtype_enum! { # [doc = " iSCSI network protocol." ] pub enum IscsiProtocol : u16 => { # [doc = " TCP." ] TCP = 0x0000 , } |
2417 | |
2418 | } |
2419 | |
2420 | bitflags! { # [doc = " iSCSI login options." ] # [repr (transparent)] pub struct IscsiLoginOptions : u16 { # [doc = " Header digest using CRC32. If not set, no header digest." ] const HEADER_DIGEST_USING_CRC32 = 0x0002 ; # [doc = " Data digest using CRC32. If not set, no data digest." ] const DATA_DIGEST_USING_CRC32 = 0x0008 ; # [doc = " Auth method none. If not set, auth method CHAP." ] const AUTH_METHOD_NONE = 0x0800 ; # [doc = " CHAP UNI. If not set, CHAP BI." ] const CHAP_UNI = 0x1000 ; } |
2421 | |
2422 | } |
2423 | |
2424 | newtype_enum! { # [doc = " BluetoothLE address type." ] pub enum BluetoothLeAddressType : u8 => { # [doc = " Public device address." ] PUBLIC = 0x00 , # [doc = " Random device address." ] RANDOM = 0x01 , } |
2425 | |
2426 | } |
2427 | |
2428 | newtype_enum! { # [doc = " Whether the address is IPv4 or IPv6." ] pub enum DnsAddressType : u8 => { # [doc = " DNS server address is IPv4." ] IPV4 = 0x00 , # [doc = " DNS server address is IPv6." ] IPV6 = 0x01 , } |
2429 | |
2430 | } |
2431 | |
2432 | impl RestService { |
2433 | /// Get the vendor GUID and vendor data. Only used if the |
2434 | /// service type is [`VENDOR`], otherwise returns None. |
2435 | /// |
2436 | /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType |
2437 | #[must_use ] |
2438 | pub fn vendor_guid_and_data(&self) -> Option<(Guid, &[u8])> { |
2439 | if self.service_type == RestServiceType::VENDOR |
2440 | && self.vendor_guid_and_data.len() >= size_of::<Guid>() |
2441 | { |
2442 | let (guid, data) = self.vendor_guid_and_data.split_at(size_of::<Guid>()); |
2443 | let guid: [u8; 16] = guid.try_into().unwrap(); |
2444 | Some((Guid::from_bytes(guid), data)) |
2445 | } else { |
2446 | None |
2447 | } |
2448 | } |
2449 | } |
2450 | |
2451 | newtype_enum! { # [doc = " Type of REST service." ] pub enum RestServiceType : u8 => { # [doc = " Redfish REST service." ] REDFISH = 0x01 , # [doc = " OData REST service." ] ODATA = 0x02 , # [doc = " Vendor-specific REST service." ] VENDOR = 0xff , } |
2452 | |
2453 | } |
2454 | |
2455 | newtype_enum! { # [doc = " Whether the service is in-band or out-of-band." ] pub enum RestServiceAccessMode : u8 => { # [doc = " In-band REST service." ] IN_BAND = 0x01 , # [doc = " Out-of-band REST service." ] OUT_OF_BAND = 0x02 , } |
2456 | |
2457 | } |
2458 | } |
2459 | |
2460 | /// Device path nodes for [`DeviceType::MEDIA`]. |
2461 | pub mod media { |
2462 | use super::*; |
2463 | /// Hard drive media device path node. |
2464 | #[repr (C, packed)] |
2465 | pub struct HardDrive { |
2466 | pub(super) header: DevicePathHeader, |
2467 | pub(super) partition_number: u32, |
2468 | pub(super) partition_start: u64, |
2469 | pub(super) partition_size: u64, |
2470 | pub(super) partition_signature: [u8; 16usize], |
2471 | pub(super) partition_format: crate::proto::device_path::media::PartitionFormat, |
2472 | pub(super) signature_type: u8, |
2473 | } |
2474 | |
2475 | impl HardDrive { |
2476 | /// Index of the partition, starting from 1. |
2477 | #[must_use ] |
2478 | pub fn partition_number(&self) -> u32 { |
2479 | self.partition_number |
2480 | } |
2481 | |
2482 | /// Starting LBA (logical block address) of the partition. |
2483 | #[must_use ] |
2484 | pub fn partition_start(&self) -> u64 { |
2485 | self.partition_start |
2486 | } |
2487 | |
2488 | /// Size of the partition in blocks. |
2489 | #[must_use ] |
2490 | pub fn partition_size(&self) -> u64 { |
2491 | self.partition_size |
2492 | } |
2493 | |
2494 | /// Partition format. |
2495 | #[must_use ] |
2496 | pub fn partition_format(&self) -> crate::proto::device_path::media::PartitionFormat { |
2497 | self.partition_format |
2498 | } |
2499 | } |
2500 | |
2501 | impl fmt::Debug for HardDrive { |
2502 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2503 | f.debug_struct("HardDrive" ) |
2504 | .field("partition_number" , &{ self.partition_number }) |
2505 | .field("partition_start" , &{ self.partition_start }) |
2506 | .field("partition_size" , &{ self.partition_size }) |
2507 | .field("partition_signature" , &{ self.partition_signature }) |
2508 | .field("partition_format" , &{ self.partition_format }) |
2509 | .field("signature_type" , &{ self.signature_type }) |
2510 | .finish() |
2511 | } |
2512 | } |
2513 | |
2514 | impl TryFrom<&DevicePathNode> for &HardDrive { |
2515 | type Error = NodeConversionError; |
2516 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2517 | if size_of_val(node) != size_of::<HardDrive>() { |
2518 | return Err(NodeConversionError::InvalidLength); |
2519 | } |
2520 | |
2521 | let node: *const DevicePathNode = node; |
2522 | let node: *const HardDrive = node.cast(); |
2523 | Ok(unsafe { &*node }) |
2524 | } |
2525 | } |
2526 | |
2527 | /// CD-ROM media device path node. |
2528 | #[repr (C, packed)] |
2529 | pub struct CdRom { |
2530 | pub(super) header: DevicePathHeader, |
2531 | pub(super) boot_entry: u32, |
2532 | pub(super) partition_start: u64, |
2533 | pub(super) partition_size: u64, |
2534 | } |
2535 | |
2536 | impl CdRom { |
2537 | /// Boot entry number from the boot catalog, or 0 for the |
2538 | /// default entry. |
2539 | #[must_use ] |
2540 | pub fn boot_entry(&self) -> u32 { |
2541 | self.boot_entry |
2542 | } |
2543 | |
2544 | /// Starting RBA (Relative logical Block Address). |
2545 | #[must_use ] |
2546 | pub fn partition_start(&self) -> u64 { |
2547 | self.partition_start |
2548 | } |
2549 | |
2550 | /// Size of the partition in blocks. |
2551 | #[must_use ] |
2552 | pub fn partition_size(&self) -> u64 { |
2553 | self.partition_size |
2554 | } |
2555 | } |
2556 | |
2557 | impl fmt::Debug for CdRom { |
2558 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2559 | f.debug_struct("CdRom" ) |
2560 | .field("boot_entry" , &{ self.boot_entry }) |
2561 | .field("partition_start" , &{ self.partition_start }) |
2562 | .field("partition_size" , &{ self.partition_size }) |
2563 | .finish() |
2564 | } |
2565 | } |
2566 | |
2567 | impl TryFrom<&DevicePathNode> for &CdRom { |
2568 | type Error = NodeConversionError; |
2569 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2570 | if size_of_val(node) != size_of::<CdRom>() { |
2571 | return Err(NodeConversionError::InvalidLength); |
2572 | } |
2573 | |
2574 | let node: *const DevicePathNode = node; |
2575 | let node: *const CdRom = node.cast(); |
2576 | Ok(unsafe { &*node }) |
2577 | } |
2578 | } |
2579 | |
2580 | /// Vendor-defined media device path node. |
2581 | #[repr (C, packed)] |
2582 | #[derive (Pointee)] |
2583 | pub struct Vendor { |
2584 | pub(super) header: DevicePathHeader, |
2585 | pub(super) vendor_guid: Guid, |
2586 | pub(super) vendor_defined_data: [u8], |
2587 | } |
2588 | |
2589 | impl Vendor { |
2590 | /// Vendor-assigned GUID that defines the data that follows. |
2591 | #[must_use ] |
2592 | pub fn vendor_guid(&self) -> Guid { |
2593 | self.vendor_guid |
2594 | } |
2595 | |
2596 | /// Vendor-defined data. |
2597 | #[must_use ] |
2598 | pub fn vendor_defined_data(&self) -> &[u8] { |
2599 | &self.vendor_defined_data |
2600 | } |
2601 | } |
2602 | |
2603 | impl fmt::Debug for Vendor { |
2604 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2605 | f.debug_struct("Vendor" ) |
2606 | .field("vendor_guid" , &{ self.vendor_guid }) |
2607 | .field("vendor_defined_data" , { |
2608 | let ptr = addr_of!(self.vendor_defined_data); |
2609 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2610 | let byte_len = size_of::<u8>() * len; |
2611 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2612 | }) |
2613 | .finish() |
2614 | } |
2615 | } |
2616 | |
2617 | impl TryFrom<&DevicePathNode> for &Vendor { |
2618 | type Error = NodeConversionError; |
2619 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2620 | let static_size = 20usize; |
2621 | let dst_size = size_of_val(node) |
2622 | .checked_sub(static_size) |
2623 | .ok_or(NodeConversionError::InvalidLength)?; |
2624 | let elem_size = size_of::<u8>(); |
2625 | if dst_size % elem_size != 0 { |
2626 | return Err(NodeConversionError::InvalidLength); |
2627 | } |
2628 | |
2629 | let node: *const DevicePathNode = node; |
2630 | let node: *const Vendor = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2631 | Ok(unsafe { &*node }) |
2632 | } |
2633 | } |
2634 | |
2635 | /// File path media device path node. |
2636 | #[repr (C, packed)] |
2637 | #[derive (Pointee)] |
2638 | pub struct FilePath { |
2639 | pub(super) header: DevicePathHeader, |
2640 | pub(super) path_name: [u16], |
2641 | } |
2642 | |
2643 | impl FilePath { |
2644 | /// Null-terminated path. |
2645 | #[must_use ] |
2646 | pub fn path_name(&self) -> UnalignedSlice<u16> { |
2647 | let ptr: *const [u16] = addr_of!(self.path_name); |
2648 | let (ptr, len): (*const (), usize) = PtrExt::to_raw_parts(ptr); |
2649 | unsafe { UnalignedSlice::new(ptr.cast::<u16>(), len) } |
2650 | } |
2651 | } |
2652 | |
2653 | impl fmt::Debug for FilePath { |
2654 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2655 | f.debug_struct("FilePath" ) |
2656 | .field("path_name" , { |
2657 | let ptr = addr_of!(self.path_name); |
2658 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2659 | let byte_len = size_of::<u16>() * len; |
2660 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2661 | }) |
2662 | .finish() |
2663 | } |
2664 | } |
2665 | |
2666 | impl TryFrom<&DevicePathNode> for &FilePath { |
2667 | type Error = NodeConversionError; |
2668 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2669 | let static_size = 4usize; |
2670 | let dst_size = size_of_val(node) |
2671 | .checked_sub(static_size) |
2672 | .ok_or(NodeConversionError::InvalidLength)?; |
2673 | let elem_size = size_of::<u16>(); |
2674 | if dst_size % elem_size != 0 { |
2675 | return Err(NodeConversionError::InvalidLength); |
2676 | } |
2677 | |
2678 | let node: *const DevicePathNode = node; |
2679 | let node: *const FilePath = ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2680 | Ok(unsafe { &*node }) |
2681 | } |
2682 | } |
2683 | |
2684 | /// Media protocol media device path node. |
2685 | #[repr (C, packed)] |
2686 | pub struct Protocol { |
2687 | pub(super) header: DevicePathHeader, |
2688 | pub(super) protocol_guid: Guid, |
2689 | } |
2690 | |
2691 | impl Protocol { |
2692 | /// The ID of the protocol. |
2693 | #[must_use ] |
2694 | pub fn protocol_guid(&self) -> Guid { |
2695 | self.protocol_guid |
2696 | } |
2697 | } |
2698 | |
2699 | impl fmt::Debug for Protocol { |
2700 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2701 | f.debug_struct("Protocol" ) |
2702 | .field("protocol_guid" , &{ self.protocol_guid }) |
2703 | .finish() |
2704 | } |
2705 | } |
2706 | |
2707 | impl TryFrom<&DevicePathNode> for &Protocol { |
2708 | type Error = NodeConversionError; |
2709 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2710 | if size_of_val(node) != size_of::<Protocol>() { |
2711 | return Err(NodeConversionError::InvalidLength); |
2712 | } |
2713 | |
2714 | let node: *const DevicePathNode = node; |
2715 | let node: *const Protocol = node.cast(); |
2716 | Ok(unsafe { &*node }) |
2717 | } |
2718 | } |
2719 | |
2720 | /// PIWG firmware file media device path node. |
2721 | #[repr (C, packed)] |
2722 | #[derive (Pointee)] |
2723 | pub struct PiwgFirmwareFile { |
2724 | pub(super) header: DevicePathHeader, |
2725 | pub(super) data: [u8], |
2726 | } |
2727 | |
2728 | impl PiwgFirmwareFile { |
2729 | /// Contents are defined in the UEFI PI Specification. |
2730 | #[must_use ] |
2731 | pub fn data(&self) -> &[u8] { |
2732 | &self.data |
2733 | } |
2734 | } |
2735 | |
2736 | impl fmt::Debug for PiwgFirmwareFile { |
2737 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2738 | f.debug_struct("PiwgFirmwareFile" ) |
2739 | .field("data" , { |
2740 | let ptr = addr_of!(self.data); |
2741 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2742 | let byte_len = size_of::<u8>() * len; |
2743 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2744 | }) |
2745 | .finish() |
2746 | } |
2747 | } |
2748 | |
2749 | impl TryFrom<&DevicePathNode> for &PiwgFirmwareFile { |
2750 | type Error = NodeConversionError; |
2751 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2752 | let static_size = 4usize; |
2753 | let dst_size = size_of_val(node) |
2754 | .checked_sub(static_size) |
2755 | .ok_or(NodeConversionError::InvalidLength)?; |
2756 | let elem_size = size_of::<u8>(); |
2757 | if dst_size % elem_size != 0 { |
2758 | return Err(NodeConversionError::InvalidLength); |
2759 | } |
2760 | |
2761 | let node: *const DevicePathNode = node; |
2762 | let node: *const PiwgFirmwareFile = |
2763 | ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2764 | Ok(unsafe { &*node }) |
2765 | } |
2766 | } |
2767 | |
2768 | /// PIWG firmware volume media device path node. |
2769 | #[repr (C, packed)] |
2770 | #[derive (Pointee)] |
2771 | pub struct PiwgFirmwareVolume { |
2772 | pub(super) header: DevicePathHeader, |
2773 | pub(super) data: [u8], |
2774 | } |
2775 | |
2776 | impl PiwgFirmwareVolume { |
2777 | /// Contents are defined in the UEFI PI Specification. |
2778 | #[must_use ] |
2779 | pub fn data(&self) -> &[u8] { |
2780 | &self.data |
2781 | } |
2782 | } |
2783 | |
2784 | impl fmt::Debug for PiwgFirmwareVolume { |
2785 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2786 | f.debug_struct("PiwgFirmwareVolume" ) |
2787 | .field("data" , { |
2788 | let ptr = addr_of!(self.data); |
2789 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
2790 | let byte_len = size_of::<u8>() * len; |
2791 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
2792 | }) |
2793 | .finish() |
2794 | } |
2795 | } |
2796 | |
2797 | impl TryFrom<&DevicePathNode> for &PiwgFirmwareVolume { |
2798 | type Error = NodeConversionError; |
2799 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2800 | let static_size = 4usize; |
2801 | let dst_size = size_of_val(node) |
2802 | .checked_sub(static_size) |
2803 | .ok_or(NodeConversionError::InvalidLength)?; |
2804 | let elem_size = size_of::<u8>(); |
2805 | if dst_size % elem_size != 0 { |
2806 | return Err(NodeConversionError::InvalidLength); |
2807 | } |
2808 | |
2809 | let node: *const DevicePathNode = node; |
2810 | let node: *const PiwgFirmwareVolume = |
2811 | ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
2812 | Ok(unsafe { &*node }) |
2813 | } |
2814 | } |
2815 | |
2816 | /// Relative offset range media device path node. |
2817 | #[repr (C, packed)] |
2818 | pub struct RelativeOffsetRange { |
2819 | pub(super) header: DevicePathHeader, |
2820 | pub(super) _reserved: u32, |
2821 | pub(super) starting_offset: u64, |
2822 | pub(super) ending_offset: u64, |
2823 | } |
2824 | |
2825 | impl RelativeOffsetRange { |
2826 | /// Offset of the first byte, relative to the parent device node. |
2827 | #[must_use ] |
2828 | pub fn starting_offset(&self) -> u64 { |
2829 | self.starting_offset |
2830 | } |
2831 | |
2832 | /// Offset of the last byte, relative to the parent device node. |
2833 | #[must_use ] |
2834 | pub fn ending_offset(&self) -> u64 { |
2835 | self.ending_offset |
2836 | } |
2837 | } |
2838 | |
2839 | impl fmt::Debug for RelativeOffsetRange { |
2840 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2841 | f.debug_struct("RelativeOffsetRange" ) |
2842 | .field("_reserved" , &{ self._reserved }) |
2843 | .field("starting_offset" , &{ self.starting_offset }) |
2844 | .field("ending_offset" , &{ self.ending_offset }) |
2845 | .finish() |
2846 | } |
2847 | } |
2848 | |
2849 | impl TryFrom<&DevicePathNode> for &RelativeOffsetRange { |
2850 | type Error = NodeConversionError; |
2851 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2852 | if size_of_val(node) != size_of::<RelativeOffsetRange>() { |
2853 | return Err(NodeConversionError::InvalidLength); |
2854 | } |
2855 | |
2856 | let node: *const DevicePathNode = node; |
2857 | let node: *const RelativeOffsetRange = node.cast(); |
2858 | Ok(unsafe { &*node }) |
2859 | } |
2860 | } |
2861 | |
2862 | /// RAM disk media device path node. |
2863 | #[repr (C, packed)] |
2864 | pub struct RamDisk { |
2865 | pub(super) header: DevicePathHeader, |
2866 | pub(super) starting_address: u64, |
2867 | pub(super) ending_address: u64, |
2868 | pub(super) disk_type: crate::proto::device_path::media::RamDiskType, |
2869 | pub(super) disk_instance: u16, |
2870 | } |
2871 | |
2872 | impl RamDisk { |
2873 | /// Starting memory address. |
2874 | #[must_use ] |
2875 | pub fn starting_address(&self) -> u64 { |
2876 | self.starting_address |
2877 | } |
2878 | |
2879 | /// Ending memory address. |
2880 | #[must_use ] |
2881 | pub fn ending_address(&self) -> u64 { |
2882 | self.ending_address |
2883 | } |
2884 | |
2885 | /// Type of RAM disk. |
2886 | #[must_use ] |
2887 | pub fn disk_type(&self) -> crate::proto::device_path::media::RamDiskType { |
2888 | self.disk_type |
2889 | } |
2890 | |
2891 | /// RAM disk instance number if supported, otherwise 0. |
2892 | #[must_use ] |
2893 | pub fn disk_instance(&self) -> u16 { |
2894 | self.disk_instance |
2895 | } |
2896 | } |
2897 | |
2898 | impl fmt::Debug for RamDisk { |
2899 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
2900 | f.debug_struct("RamDisk" ) |
2901 | .field("starting_address" , &{ self.starting_address }) |
2902 | .field("ending_address" , &{ self.ending_address }) |
2903 | .field("disk_type" , &{ self.disk_type }) |
2904 | .field("disk_instance" , &{ self.disk_instance }) |
2905 | .finish() |
2906 | } |
2907 | } |
2908 | |
2909 | impl TryFrom<&DevicePathNode> for &RamDisk { |
2910 | type Error = NodeConversionError; |
2911 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
2912 | if size_of_val(node) != size_of::<RamDisk>() { |
2913 | return Err(NodeConversionError::InvalidLength); |
2914 | } |
2915 | |
2916 | let node: *const DevicePathNode = node; |
2917 | let node: *const RamDisk = node.cast(); |
2918 | Ok(unsafe { &*node }) |
2919 | } |
2920 | } |
2921 | |
2922 | impl HardDrive { |
2923 | /// Signature unique to this partition. |
2924 | #[must_use ] |
2925 | pub fn partition_signature(&self) -> PartitionSignature { |
2926 | match self.signature_type { |
2927 | 0 => PartitionSignature::None, |
2928 | 1 => PartitionSignature::Mbr([ |
2929 | self.partition_signature[0], |
2930 | self.partition_signature[1], |
2931 | self.partition_signature[2], |
2932 | self.partition_signature[3], |
2933 | ]), |
2934 | 2 => PartitionSignature::Guid(Guid::from_bytes(self.partition_signature)), |
2935 | unknown => PartitionSignature::Unknown { |
2936 | signature_type: unknown, |
2937 | signature: self.partition_signature, |
2938 | }, |
2939 | } |
2940 | } |
2941 | } |
2942 | |
2943 | /// Hard drive partition signature. |
2944 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] |
2945 | pub enum PartitionSignature { |
2946 | /// No disk signature. |
2947 | None, |
2948 | /// 32-bit MBR partition signature. |
2949 | Mbr([u8; 4]), |
2950 | /// 128-bit GUID partition signature. |
2951 | Guid(Guid), |
2952 | /// Unknown signature type not listed in the UEFI Specification. |
2953 | Unknown { |
2954 | /// Signature type. |
2955 | signature_type: u8, |
2956 | /// Signature data. |
2957 | signature: [u8; 16], |
2958 | }, |
2959 | } |
2960 | |
2961 | newtype_enum! { # [doc = " Hard drive partition format." ] pub enum PartitionFormat : u8 => { # [doc = " MBR (PC-AT compatible Master Boot Record) format." ] MBR = 0x01 , # [doc = " GPT (GUID Partition Table) format." ] GPT = 0x02 , } |
2962 | |
2963 | } |
2964 | |
2965 | newtype_enum! { # [doc = " RAM disk type." ] pub enum RamDiskType : Guid => { # [doc = " RAM disk with a raw disk format in volatile memory." ] VIRTUAL_DISK = guid ! ("77ab535a-45fc-624b-5560-f7b281d1f96e" ) , # [doc = " RAM disk of an ISO image in volatile memory." ] VIRTUAL_CD = guid ! ("3d5abd30-4175-87ce-6d64-d2ade523c4bb" ) , # [doc = " RAM disk with a raw disk format in persistent memory." ] PERSISTENT_VIRTUAL_DISK = guid ! ("5cea02c9-4d07-69d3-269f-4496fbe096f9" ) , # [doc = " RAM disk of an ISO image in persistent memory." ] PERSISTENT_VIRTUAL_CD = guid ! ("08018188-42cd-bb48-100f-5387d53ded3d" ) , } |
2966 | |
2967 | } |
2968 | } |
2969 | |
2970 | /// Device path nodes for [`DeviceType::BIOS_BOOT_SPEC`]. |
2971 | pub mod bios_boot_spec { |
2972 | use super::*; |
2973 | /// BIOS Boot Specification device path node. |
2974 | #[repr (C, packed)] |
2975 | #[derive (Pointee)] |
2976 | pub struct BootSpecification { |
2977 | pub(super) header: DevicePathHeader, |
2978 | pub(super) device_type: u16, |
2979 | pub(super) status_flag: u16, |
2980 | pub(super) description_string: [u8], |
2981 | } |
2982 | |
2983 | impl BootSpecification { |
2984 | /// Device type as defined by the BIOS Boot Specification. |
2985 | #[must_use ] |
2986 | pub fn device_type(&self) -> u16 { |
2987 | self.device_type |
2988 | } |
2989 | |
2990 | /// Status flags as defined by the BIOS Boot Specification. |
2991 | #[must_use ] |
2992 | pub fn status_flag(&self) -> u16 { |
2993 | self.status_flag |
2994 | } |
2995 | |
2996 | /// Description of the boot device encoded as a null-terminated |
2997 | /// ASCII string. |
2998 | #[must_use ] |
2999 | pub fn description_string(&self) -> &[u8] { |
3000 | &self.description_string |
3001 | } |
3002 | } |
3003 | |
3004 | impl fmt::Debug for BootSpecification { |
3005 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
3006 | f.debug_struct("BootSpecification" ) |
3007 | .field("device_type" , &{ self.device_type }) |
3008 | .field("status_flag" , &{ self.status_flag }) |
3009 | .field("description_string" , { |
3010 | let ptr = addr_of!(self.description_string); |
3011 | let (ptr, len) = PtrExt::to_raw_parts(ptr); |
3012 | let byte_len = size_of::<u8>() * len; |
3013 | unsafe { &slice::from_raw_parts(ptr.cast::<u8>(), byte_len) } |
3014 | }) |
3015 | .finish() |
3016 | } |
3017 | } |
3018 | |
3019 | impl TryFrom<&DevicePathNode> for &BootSpecification { |
3020 | type Error = NodeConversionError; |
3021 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
3022 | let static_size = 8usize; |
3023 | let dst_size = size_of_val(node) |
3024 | .checked_sub(static_size) |
3025 | .ok_or(NodeConversionError::InvalidLength)?; |
3026 | let elem_size = size_of::<u8>(); |
3027 | if dst_size % elem_size != 0 { |
3028 | return Err(NodeConversionError::InvalidLength); |
3029 | } |
3030 | |
3031 | let node: *const DevicePathNode = node; |
3032 | let node: *const BootSpecification = |
3033 | ptr_meta::from_raw_parts(node.cast(), dst_size / elem_size); |
3034 | Ok(unsafe { &*node }) |
3035 | } |
3036 | } |
3037 | } |
3038 | |
3039 | /// Enum of references to all the different device path node |
3040 | /// types. Return type of [`DevicePathNode::as_enum`]. |
3041 | pub enum DevicePathNodeEnum<'a> { |
3042 | /// Node that terminates a [`DevicePathInstance`]. |
3043 | /// |
3044 | /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance |
3045 | EndInstance(&'a end::Instance), |
3046 | /// Node that terminates an entire [`DevicePath`]. |
3047 | /// |
3048 | /// [`DevicePath`]: crate::proto::device_path::DevicePath |
3049 | EndEntire(&'a end::Entire), |
3050 | /// PCI hardware device path node. |
3051 | HardwarePci(&'a hardware::Pci), |
3052 | /// PCCARD hardware device path node. |
3053 | HardwarePccard(&'a hardware::Pccard), |
3054 | /// Memory mapped hardware device path node. |
3055 | HardwareMemoryMapped(&'a hardware::MemoryMapped), |
3056 | /// Vendor-defined hardware device path node. |
3057 | HardwareVendor(&'a hardware::Vendor), |
3058 | /// Controller hardware device path node. |
3059 | HardwareController(&'a hardware::Controller), |
3060 | /// Baseboard Management Controller (BMC) host interface hardware |
3061 | /// device path node. |
3062 | HardwareBmc(&'a hardware::Bmc), |
3063 | /// ACPI device path node. |
3064 | AcpiAcpi(&'a acpi::Acpi), |
3065 | /// Expanded ACPI device path node. |
3066 | AcpiExpanded(&'a acpi::Expanded), |
3067 | /// ADR ACPI device path node. |
3068 | AcpiAdr(&'a acpi::Adr), |
3069 | /// NVDIMM ACPI device path node. |
3070 | AcpiNvdimm(&'a acpi::Nvdimm), |
3071 | /// ATAPI messaging device path node. |
3072 | MessagingAtapi(&'a messaging::Atapi), |
3073 | /// SCSI messaging device path node. |
3074 | MessagingScsi(&'a messaging::Scsi), |
3075 | /// Fibre channel messaging device path node. |
3076 | MessagingFibreChannel(&'a messaging::FibreChannel), |
3077 | /// Fibre channel extended messaging device path node. |
3078 | MessagingFibreChannelEx(&'a messaging::FibreChannelEx), |
3079 | /// 1394 messaging device path node. |
3080 | MessagingIeee1394(&'a messaging::Ieee1394), |
3081 | /// USB messaging device path node. |
3082 | MessagingUsb(&'a messaging::Usb), |
3083 | /// SATA messaging device path node. |
3084 | MessagingSata(&'a messaging::Sata), |
3085 | /// USB World Wide ID (WWID) messaging device path node. |
3086 | MessagingUsbWwid(&'a messaging::UsbWwid), |
3087 | /// Device logical unit messaging device path node. |
3088 | MessagingDeviceLogicalUnit(&'a messaging::DeviceLogicalUnit), |
3089 | /// USB class messaging device path node. |
3090 | MessagingUsbClass(&'a messaging::UsbClass), |
3091 | /// I2O messaging device path node. |
3092 | MessagingI2o(&'a messaging::I2o), |
3093 | /// MAC address messaging device path node. |
3094 | MessagingMacAddress(&'a messaging::MacAddress), |
3095 | /// IPv4 messaging device path node. |
3096 | MessagingIpv4(&'a messaging::Ipv4), |
3097 | /// IPv6 messaging device path node. |
3098 | MessagingIpv6(&'a messaging::Ipv6), |
3099 | /// VLAN messaging device path node. |
3100 | MessagingVlan(&'a messaging::Vlan), |
3101 | /// InfiniBand messaging device path node. |
3102 | MessagingInfiniband(&'a messaging::Infiniband), |
3103 | /// UART messaging device path node. |
3104 | MessagingUart(&'a messaging::Uart), |
3105 | /// Vendor-defined messaging device path node. |
3106 | MessagingVendor(&'a messaging::Vendor), |
3107 | /// Serial Attached SCSI (SAS) extended messaging device path node. |
3108 | MessagingSasEx(&'a messaging::SasEx), |
3109 | /// iSCSI messaging device path node. |
3110 | MessagingIscsi(&'a messaging::Iscsi), |
3111 | /// NVM Express namespace messaging device path node. |
3112 | MessagingNvmeNamespace(&'a messaging::NvmeNamespace), |
3113 | /// Uniform Resource Identifier (URI) messaging device path node. |
3114 | MessagingUri(&'a messaging::Uri), |
3115 | /// Universal Flash Storage (UFS) messaging device path node. |
3116 | MessagingUfs(&'a messaging::Ufs), |
3117 | /// Secure Digital (SD) messaging device path node. |
3118 | MessagingSd(&'a messaging::Sd), |
3119 | /// Bluetooth messaging device path node. |
3120 | MessagingBluetooth(&'a messaging::Bluetooth), |
3121 | /// Wi-Fi messaging device path node. |
3122 | MessagingWifi(&'a messaging::Wifi), |
3123 | /// Embedded Multi-Media Card (eMMC) messaging device path node. |
3124 | MessagingEmmc(&'a messaging::Emmc), |
3125 | /// BluetoothLE messaging device path node. |
3126 | MessagingBluetoothLe(&'a messaging::BluetoothLe), |
3127 | /// DNS messaging device path node. |
3128 | MessagingDns(&'a messaging::Dns), |
3129 | /// NVDIMM namespace messaging device path node. |
3130 | MessagingNvdimmNamespace(&'a messaging::NvdimmNamespace), |
3131 | /// REST service messaging device path node. |
3132 | MessagingRestService(&'a messaging::RestService), |
3133 | /// NVME over Fabric (NVMe-oF) namespace messaging device path node. |
3134 | MessagingNvmeOfNamespace(&'a messaging::NvmeOfNamespace), |
3135 | /// Hard drive media device path node. |
3136 | MediaHardDrive(&'a media::HardDrive), |
3137 | /// CD-ROM media device path node. |
3138 | MediaCdRom(&'a media::CdRom), |
3139 | /// Vendor-defined media device path node. |
3140 | MediaVendor(&'a media::Vendor), |
3141 | /// File path media device path node. |
3142 | MediaFilePath(&'a media::FilePath), |
3143 | /// Media protocol media device path node. |
3144 | MediaProtocol(&'a media::Protocol), |
3145 | /// PIWG firmware file media device path node. |
3146 | MediaPiwgFirmwareFile(&'a media::PiwgFirmwareFile), |
3147 | /// PIWG firmware volume media device path node. |
3148 | MediaPiwgFirmwareVolume(&'a media::PiwgFirmwareVolume), |
3149 | /// Relative offset range media device path node. |
3150 | MediaRelativeOffsetRange(&'a media::RelativeOffsetRange), |
3151 | /// RAM disk media device path node. |
3152 | MediaRamDisk(&'a media::RamDisk), |
3153 | /// BIOS Boot Specification device path node. |
3154 | BiosBootSpecBootSpecification(&'a bios_boot_spec::BootSpecification), |
3155 | } |
3156 | |
3157 | impl<'a> TryFrom<&DevicePathNode> for DevicePathNodeEnum<'a> { |
3158 | type Error = NodeConversionError; |
3159 | fn try_from(node: &DevicePathNode) -> Result<Self, Self::Error> { |
3160 | Ok(match node.full_type() { |
3161 | (DeviceType::END, DeviceSubType::END_INSTANCE) => Self::EndInstance(node.try_into()?), |
3162 | (DeviceType::END, DeviceSubType::END_ENTIRE) => Self::EndEntire(node.try_into()?), |
3163 | (DeviceType::HARDWARE, DeviceSubType::HARDWARE_PCI) => { |
3164 | Self::HardwarePci(node.try_into()?) |
3165 | } |
3166 | (DeviceType::HARDWARE, DeviceSubType::HARDWARE_PCCARD) => { |
3167 | Self::HardwarePccard(node.try_into()?) |
3168 | } |
3169 | (DeviceType::HARDWARE, DeviceSubType::HARDWARE_MEMORY_MAPPED) => { |
3170 | Self::HardwareMemoryMapped(node.try_into()?) |
3171 | } |
3172 | (DeviceType::HARDWARE, DeviceSubType::HARDWARE_VENDOR) => { |
3173 | Self::HardwareVendor(node.try_into()?) |
3174 | } |
3175 | (DeviceType::HARDWARE, DeviceSubType::HARDWARE_CONTROLLER) => { |
3176 | Self::HardwareController(node.try_into()?) |
3177 | } |
3178 | (DeviceType::HARDWARE, DeviceSubType::HARDWARE_BMC) => { |
3179 | Self::HardwareBmc(node.try_into()?) |
3180 | } |
3181 | (DeviceType::ACPI, DeviceSubType::ACPI) => Self::AcpiAcpi(node.try_into()?), |
3182 | (DeviceType::ACPI, DeviceSubType::ACPI_EXPANDED) => { |
3183 | Self::AcpiExpanded(node.try_into()?) |
3184 | } |
3185 | (DeviceType::ACPI, DeviceSubType::ACPI_ADR) => Self::AcpiAdr(node.try_into()?), |
3186 | (DeviceType::ACPI, DeviceSubType::ACPI_NVDIMM) => Self::AcpiNvdimm(node.try_into()?), |
3187 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_ATAPI) => { |
3188 | Self::MessagingAtapi(node.try_into()?) |
3189 | } |
3190 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SCSI) => { |
3191 | Self::MessagingScsi(node.try_into()?) |
3192 | } |
3193 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_FIBRE_CHANNEL) => { |
3194 | Self::MessagingFibreChannel(node.try_into()?) |
3195 | } |
3196 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_FIBRE_CHANNEL_EX) => { |
3197 | Self::MessagingFibreChannelEx(node.try_into()?) |
3198 | } |
3199 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_1394) => { |
3200 | Self::MessagingIeee1394(node.try_into()?) |
3201 | } |
3202 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB) => { |
3203 | Self::MessagingUsb(node.try_into()?) |
3204 | } |
3205 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SATA) => { |
3206 | Self::MessagingSata(node.try_into()?) |
3207 | } |
3208 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB_WWID) => { |
3209 | Self::MessagingUsbWwid(node.try_into()?) |
3210 | } |
3211 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_DEVICE_LOGICAL_UNIT) => { |
3212 | Self::MessagingDeviceLogicalUnit(node.try_into()?) |
3213 | } |
3214 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_USB_CLASS) => { |
3215 | Self::MessagingUsbClass(node.try_into()?) |
3216 | } |
3217 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_I2O) => { |
3218 | Self::MessagingI2o(node.try_into()?) |
3219 | } |
3220 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_MAC_ADDRESS) => { |
3221 | Self::MessagingMacAddress(node.try_into()?) |
3222 | } |
3223 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_IPV4) => { |
3224 | Self::MessagingIpv4(node.try_into()?) |
3225 | } |
3226 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_IPV6) => { |
3227 | Self::MessagingIpv6(node.try_into()?) |
3228 | } |
3229 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_VLAN) => { |
3230 | Self::MessagingVlan(node.try_into()?) |
3231 | } |
3232 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_INFINIBAND) => { |
3233 | Self::MessagingInfiniband(node.try_into()?) |
3234 | } |
3235 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_UART) => { |
3236 | Self::MessagingUart(node.try_into()?) |
3237 | } |
3238 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_VENDOR) => { |
3239 | Self::MessagingVendor(node.try_into()?) |
3240 | } |
3241 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SCSI_SAS_EX) => { |
3242 | Self::MessagingSasEx(node.try_into()?) |
3243 | } |
3244 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_ISCSI) => { |
3245 | Self::MessagingIscsi(node.try_into()?) |
3246 | } |
3247 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVME_NAMESPACE) => { |
3248 | Self::MessagingNvmeNamespace(node.try_into()?) |
3249 | } |
3250 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_URI) => { |
3251 | Self::MessagingUri(node.try_into()?) |
3252 | } |
3253 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_UFS) => { |
3254 | Self::MessagingUfs(node.try_into()?) |
3255 | } |
3256 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_SD) => { |
3257 | Self::MessagingSd(node.try_into()?) |
3258 | } |
3259 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_BLUETOOTH) => { |
3260 | Self::MessagingBluetooth(node.try_into()?) |
3261 | } |
3262 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_WIFI) => { |
3263 | Self::MessagingWifi(node.try_into()?) |
3264 | } |
3265 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_EMMC) => { |
3266 | Self::MessagingEmmc(node.try_into()?) |
3267 | } |
3268 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_BLUETOOTH_LE) => { |
3269 | Self::MessagingBluetoothLe(node.try_into()?) |
3270 | } |
3271 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_DNS) => { |
3272 | Self::MessagingDns(node.try_into()?) |
3273 | } |
3274 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVDIMM_NAMESPACE) => { |
3275 | Self::MessagingNvdimmNamespace(node.try_into()?) |
3276 | } |
3277 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_REST_SERVICE) => { |
3278 | Self::MessagingRestService(node.try_into()?) |
3279 | } |
3280 | (DeviceType::MESSAGING, DeviceSubType::MESSAGING_NVME_OF_NAMESPACE) => { |
3281 | Self::MessagingNvmeOfNamespace(node.try_into()?) |
3282 | } |
3283 | (DeviceType::MEDIA, DeviceSubType::MEDIA_HARD_DRIVE) => { |
3284 | Self::MediaHardDrive(node.try_into()?) |
3285 | } |
3286 | (DeviceType::MEDIA, DeviceSubType::MEDIA_CD_ROM) => Self::MediaCdRom(node.try_into()?), |
3287 | (DeviceType::MEDIA, DeviceSubType::MEDIA_VENDOR) => Self::MediaVendor(node.try_into()?), |
3288 | (DeviceType::MEDIA, DeviceSubType::MEDIA_FILE_PATH) => { |
3289 | Self::MediaFilePath(node.try_into()?) |
3290 | } |
3291 | (DeviceType::MEDIA, DeviceSubType::MEDIA_PROTOCOL) => { |
3292 | Self::MediaProtocol(node.try_into()?) |
3293 | } |
3294 | (DeviceType::MEDIA, DeviceSubType::MEDIA_PIWG_FIRMWARE_FILE) => { |
3295 | Self::MediaPiwgFirmwareFile(node.try_into()?) |
3296 | } |
3297 | (DeviceType::MEDIA, DeviceSubType::MEDIA_PIWG_FIRMWARE_VOLUME) => { |
3298 | Self::MediaPiwgFirmwareVolume(node.try_into()?) |
3299 | } |
3300 | (DeviceType::MEDIA, DeviceSubType::MEDIA_RELATIVE_OFFSET_RANGE) => { |
3301 | Self::MediaRelativeOffsetRange(node.try_into()?) |
3302 | } |
3303 | (DeviceType::MEDIA, DeviceSubType::MEDIA_RAM_DISK) => { |
3304 | Self::MediaRamDisk(node.try_into()?) |
3305 | } |
3306 | (DeviceType::BIOS_BOOT_SPEC, DeviceSubType::BIOS_BOOT_SPECIFICATION) => { |
3307 | Self::BiosBootSpecBootSpecification(node.try_into()?) |
3308 | } |
3309 | _ => return Err(NodeConversionError::UnsupportedType), |
3310 | }) |
3311 | } |
3312 | } |
3313 | |
3314 | /// Build device paths from their component nodes. |
3315 | pub mod build { |
3316 | use super::*; |
3317 | use crate::proto::device_path::build::{BuildError, BuildNode}; |
3318 | use crate::proto::device_path::{DeviceSubType, DeviceType}; |
3319 | use crate::CStr16; |
3320 | use core::mem::{size_of_val, MaybeUninit}; |
3321 | /// Device path build nodes for [`DeviceType::END`]. |
3322 | pub mod end { |
3323 | use super::*; |
3324 | /// Node that terminates a [`DevicePathInstance`]. |
3325 | /// |
3326 | /// [`DevicePathInstance`]: crate::proto::device_path::DevicePathInstance |
3327 | pub struct Instance; |
3328 | unsafe impl BuildNode for Instance { |
3329 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3330 | let size = 4usize; |
3331 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3332 | } |
3333 | |
3334 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3335 | let size = usize::from(self.size_in_bytes().unwrap()); |
3336 | assert_eq!(size, out.len()); |
3337 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3338 | unsafe { |
3339 | out_ptr |
3340 | .cast::<DevicePathHeader>() |
3341 | .write_unaligned(DevicePathHeader { |
3342 | device_type: DeviceType::END, |
3343 | sub_type: DeviceSubType::END_INSTANCE, |
3344 | length: u16::try_from(size).unwrap(), |
3345 | }); |
3346 | } |
3347 | } |
3348 | } |
3349 | |
3350 | /// Node that terminates an entire [`DevicePath`]. |
3351 | /// |
3352 | /// [`DevicePath`]: crate::proto::device_path::DevicePath |
3353 | pub struct Entire; |
3354 | unsafe impl BuildNode for Entire { |
3355 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3356 | let size = 4usize; |
3357 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3358 | } |
3359 | |
3360 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3361 | let size = usize::from(self.size_in_bytes().unwrap()); |
3362 | assert_eq!(size, out.len()); |
3363 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3364 | unsafe { |
3365 | out_ptr |
3366 | .cast::<DevicePathHeader>() |
3367 | .write_unaligned(DevicePathHeader { |
3368 | device_type: DeviceType::END, |
3369 | sub_type: DeviceSubType::END_ENTIRE, |
3370 | length: u16::try_from(size).unwrap(), |
3371 | }); |
3372 | } |
3373 | } |
3374 | } |
3375 | } |
3376 | |
3377 | /// Device path build nodes for [`DeviceType::HARDWARE`]. |
3378 | pub mod hardware { |
3379 | use super::*; |
3380 | /// PCI hardware device path node. |
3381 | pub struct Pci { |
3382 | /// PCI function number. |
3383 | pub function: u8, |
3384 | /// PCI device number. |
3385 | pub device: u8, |
3386 | } |
3387 | |
3388 | unsafe impl BuildNode for Pci { |
3389 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3390 | let size = 6usize; |
3391 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3392 | } |
3393 | |
3394 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3395 | let size = usize::from(self.size_in_bytes().unwrap()); |
3396 | assert_eq!(size, out.len()); |
3397 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3398 | unsafe { |
3399 | out_ptr |
3400 | .cast::<DevicePathHeader>() |
3401 | .write_unaligned(DevicePathHeader { |
3402 | device_type: DeviceType::HARDWARE, |
3403 | sub_type: DeviceSubType::HARDWARE_PCI, |
3404 | length: u16::try_from(size).unwrap(), |
3405 | }); |
3406 | out_ptr |
3407 | .add(4usize) |
3408 | .cast::<u8>() |
3409 | .write_unaligned(self.function); |
3410 | out_ptr |
3411 | .add(5usize) |
3412 | .cast::<u8>() |
3413 | .write_unaligned(self.device); |
3414 | } |
3415 | } |
3416 | } |
3417 | |
3418 | /// PCCARD hardware device path node. |
3419 | pub struct Pccard { |
3420 | /// Function number starting from 0. |
3421 | pub function: u8, |
3422 | } |
3423 | |
3424 | unsafe impl BuildNode for Pccard { |
3425 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3426 | let size = 5usize; |
3427 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3428 | } |
3429 | |
3430 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3431 | let size = usize::from(self.size_in_bytes().unwrap()); |
3432 | assert_eq!(size, out.len()); |
3433 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3434 | unsafe { |
3435 | out_ptr |
3436 | .cast::<DevicePathHeader>() |
3437 | .write_unaligned(DevicePathHeader { |
3438 | device_type: DeviceType::HARDWARE, |
3439 | sub_type: DeviceSubType::HARDWARE_PCCARD, |
3440 | length: u16::try_from(size).unwrap(), |
3441 | }); |
3442 | out_ptr |
3443 | .add(4usize) |
3444 | .cast::<u8>() |
3445 | .write_unaligned(self.function); |
3446 | } |
3447 | } |
3448 | } |
3449 | |
3450 | /// Memory mapped hardware device path node. |
3451 | pub struct MemoryMapped { |
3452 | /// Memory type. |
3453 | pub memory_type: MemoryType, |
3454 | /// Starting memory address. |
3455 | pub start_address: u64, |
3456 | /// Ending memory address. |
3457 | pub end_address: u64, |
3458 | } |
3459 | |
3460 | unsafe impl BuildNode for MemoryMapped { |
3461 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3462 | let size = 24usize; |
3463 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3464 | } |
3465 | |
3466 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3467 | let size = usize::from(self.size_in_bytes().unwrap()); |
3468 | assert_eq!(size, out.len()); |
3469 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3470 | unsafe { |
3471 | out_ptr |
3472 | .cast::<DevicePathHeader>() |
3473 | .write_unaligned(DevicePathHeader { |
3474 | device_type: DeviceType::HARDWARE, |
3475 | sub_type: DeviceSubType::HARDWARE_MEMORY_MAPPED, |
3476 | length: u16::try_from(size).unwrap(), |
3477 | }); |
3478 | out_ptr |
3479 | .add(4usize) |
3480 | .cast::<MemoryType>() |
3481 | .write_unaligned(self.memory_type); |
3482 | out_ptr |
3483 | .add(8usize) |
3484 | .cast::<u64>() |
3485 | .write_unaligned(self.start_address); |
3486 | out_ptr |
3487 | .add(16usize) |
3488 | .cast::<u64>() |
3489 | .write_unaligned(self.end_address); |
3490 | } |
3491 | } |
3492 | } |
3493 | |
3494 | /// Vendor-defined hardware device path node. |
3495 | pub struct Vendor<'a> { |
3496 | /// Vendor-assigned GUID that defines the data that follows. |
3497 | pub vendor_guid: Guid, |
3498 | /// Vendor-defined data. |
3499 | pub vendor_defined_data: &'a [u8], |
3500 | } |
3501 | |
3502 | unsafe impl<'a> BuildNode for Vendor<'a> { |
3503 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3504 | let size = 20usize + size_of_val(self.vendor_defined_data); |
3505 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3506 | } |
3507 | |
3508 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3509 | let size = usize::from(self.size_in_bytes().unwrap()); |
3510 | assert_eq!(size, out.len()); |
3511 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3512 | unsafe { |
3513 | out_ptr |
3514 | .cast::<DevicePathHeader>() |
3515 | .write_unaligned(DevicePathHeader { |
3516 | device_type: DeviceType::HARDWARE, |
3517 | sub_type: DeviceSubType::HARDWARE_VENDOR, |
3518 | length: u16::try_from(size).unwrap(), |
3519 | }); |
3520 | out_ptr |
3521 | .add(4usize) |
3522 | .cast::<Guid>() |
3523 | .write_unaligned(self.vendor_guid); |
3524 | self.vendor_defined_data |
3525 | .as_ptr() |
3526 | .cast::<u8>() |
3527 | .copy_to_nonoverlapping( |
3528 | out_ptr.add(20usize), |
3529 | size_of_val(self.vendor_defined_data), |
3530 | ); |
3531 | } |
3532 | } |
3533 | } |
3534 | |
3535 | /// Controller hardware device path node. |
3536 | pub struct Controller { |
3537 | /// Controller number. |
3538 | pub controller_number: u32, |
3539 | } |
3540 | |
3541 | unsafe impl BuildNode for Controller { |
3542 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3543 | let size = 8usize; |
3544 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3545 | } |
3546 | |
3547 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3548 | let size = usize::from(self.size_in_bytes().unwrap()); |
3549 | assert_eq!(size, out.len()); |
3550 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3551 | unsafe { |
3552 | out_ptr |
3553 | .cast::<DevicePathHeader>() |
3554 | .write_unaligned(DevicePathHeader { |
3555 | device_type: DeviceType::HARDWARE, |
3556 | sub_type: DeviceSubType::HARDWARE_CONTROLLER, |
3557 | length: u16::try_from(size).unwrap(), |
3558 | }); |
3559 | out_ptr |
3560 | .add(4usize) |
3561 | .cast::<u32>() |
3562 | .write_unaligned(self.controller_number); |
3563 | } |
3564 | } |
3565 | } |
3566 | |
3567 | /// Baseboard Management Controller (BMC) host interface hardware |
3568 | /// device path node. |
3569 | pub struct Bmc { |
3570 | /// Host interface type. |
3571 | pub interface_type: crate::proto::device_path::hardware::BmcInterfaceType, |
3572 | /// Base address of the BMC. If the least-significant bit of the |
3573 | /// field is a 1 then the address is in I/O space, otherwise the |
3574 | /// address is memory-mapped. |
3575 | pub base_address: u64, |
3576 | } |
3577 | |
3578 | unsafe impl BuildNode for Bmc { |
3579 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3580 | let size = 13usize; |
3581 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3582 | } |
3583 | |
3584 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3585 | let size = usize::from(self.size_in_bytes().unwrap()); |
3586 | assert_eq!(size, out.len()); |
3587 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3588 | unsafe { |
3589 | out_ptr |
3590 | .cast::<DevicePathHeader>() |
3591 | .write_unaligned(DevicePathHeader { |
3592 | device_type: DeviceType::HARDWARE, |
3593 | sub_type: DeviceSubType::HARDWARE_BMC, |
3594 | length: u16::try_from(size).unwrap(), |
3595 | }); |
3596 | out_ptr |
3597 | .add(4usize) |
3598 | .cast::<crate::proto::device_path::hardware::BmcInterfaceType>() |
3599 | .write_unaligned(self.interface_type); |
3600 | out_ptr |
3601 | .add(5usize) |
3602 | .cast::<u64>() |
3603 | .write_unaligned(self.base_address); |
3604 | } |
3605 | } |
3606 | } |
3607 | } |
3608 | |
3609 | /// Device path build nodes for [`DeviceType::ACPI`]. |
3610 | pub mod acpi { |
3611 | use super::*; |
3612 | /// ACPI device path node. |
3613 | pub struct Acpi { |
3614 | /// Device's PnP hardware ID stored in a numeric 32-bit |
3615 | /// compressed EISA-type ID. |
3616 | pub hid: u32, |
3617 | /// Unique ID that is required by ACPI if two devices have the |
3618 | /// same HID. |
3619 | pub uid: u32, |
3620 | } |
3621 | |
3622 | unsafe impl BuildNode for Acpi { |
3623 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3624 | let size = 12usize; |
3625 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3626 | } |
3627 | |
3628 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3629 | let size = usize::from(self.size_in_bytes().unwrap()); |
3630 | assert_eq!(size, out.len()); |
3631 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3632 | unsafe { |
3633 | out_ptr |
3634 | .cast::<DevicePathHeader>() |
3635 | .write_unaligned(DevicePathHeader { |
3636 | device_type: DeviceType::ACPI, |
3637 | sub_type: DeviceSubType::ACPI, |
3638 | length: u16::try_from(size).unwrap(), |
3639 | }); |
3640 | out_ptr.add(4usize).cast::<u32>().write_unaligned(self.hid); |
3641 | out_ptr.add(8usize).cast::<u32>().write_unaligned(self.uid); |
3642 | } |
3643 | } |
3644 | } |
3645 | |
3646 | /// Expanded ACPI device path node. |
3647 | pub struct Expanded<'a> { |
3648 | /// Device's PnP hardware ID stored in a numeric 32-bit compressed |
3649 | /// EISA-type ID. |
3650 | pub hid: u32, |
3651 | /// Unique ID that is required by ACPI if two devices have the |
3652 | /// same HID. |
3653 | pub uid: u32, |
3654 | /// Device's compatible PnP hardware ID stored in a numeric 32-bit |
3655 | /// compressed EISA-type ID. |
3656 | pub cid: u32, |
3657 | /// Device's PnP hardware ID stored as a null-terminated ASCII |
3658 | /// string. This value must match the corresponding HID in the |
3659 | /// ACPI name space. If the length of this string not including |
3660 | /// the null-terminator is 0, then the numeric HID is used. |
3661 | pub hid_str: &'a [u8], |
3662 | /// Unique ID that is required by ACPI if two devices have the |
3663 | /// same HID. This value is stored as a null-terminated ASCII |
3664 | /// string. If the length of this string not including the |
3665 | /// null-terminator is 0, then the numeric UID is used. |
3666 | pub uid_str: &'a [u8], |
3667 | /// Device's compatible PnP hardware ID stored as a |
3668 | /// null-terminated ASCII string. If the length of this string |
3669 | /// not including the null-terminator is 0, then the numeric CID |
3670 | /// is used. |
3671 | pub cid_str: &'a [u8], |
3672 | } |
3673 | |
3674 | unsafe impl<'a> BuildNode for Expanded<'a> { |
3675 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3676 | let size = 16usize |
3677 | + size_of_val(self.hid_str) |
3678 | + size_of_val(self.uid_str) |
3679 | + size_of_val(self.cid_str); |
3680 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3681 | } |
3682 | |
3683 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3684 | let size = usize::from(self.size_in_bytes().unwrap()); |
3685 | assert_eq!(size, out.len()); |
3686 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3687 | unsafe { |
3688 | out_ptr |
3689 | .cast::<DevicePathHeader>() |
3690 | .write_unaligned(DevicePathHeader { |
3691 | device_type: DeviceType::ACPI, |
3692 | sub_type: DeviceSubType::ACPI_EXPANDED, |
3693 | length: u16::try_from(size).unwrap(), |
3694 | }); |
3695 | let mut dst_group_offset = 0; |
3696 | out_ptr.add(4usize).cast::<u32>().write_unaligned(self.hid); |
3697 | out_ptr.add(8usize).cast::<u32>().write_unaligned(self.uid); |
3698 | out_ptr.add(12usize).cast::<u32>().write_unaligned(self.cid); |
3699 | self.hid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping( |
3700 | out_ptr.add(16usize + dst_group_offset), |
3701 | size_of_val(self.hid_str), |
3702 | ); |
3703 | dst_group_offset += size_of_val(self.hid_str); |
3704 | self.uid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping( |
3705 | out_ptr.add(16usize + dst_group_offset), |
3706 | size_of_val(self.uid_str), |
3707 | ); |
3708 | dst_group_offset += size_of_val(self.uid_str); |
3709 | self.cid_str.as_ptr().cast::<u8>().copy_to_nonoverlapping( |
3710 | out_ptr.add(16usize + dst_group_offset), |
3711 | size_of_val(self.cid_str), |
3712 | ); |
3713 | } |
3714 | } |
3715 | } |
3716 | |
3717 | /// ADR ACPI device path node. |
3718 | pub struct Adr<'a> { |
3719 | /// ADR values. For video output devices the value of this field |
3720 | /// comes from Table B-2 ACPI 3.0 specification. At least one |
3721 | /// ADR value is required. |
3722 | pub adr: &'a AdrSlice, |
3723 | } |
3724 | |
3725 | unsafe impl<'a> BuildNode for Adr<'a> { |
3726 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3727 | let size = 4usize + size_of_val(self.adr); |
3728 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3729 | } |
3730 | |
3731 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3732 | let size = usize::from(self.size_in_bytes().unwrap()); |
3733 | assert_eq!(size, out.len()); |
3734 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3735 | unsafe { |
3736 | out_ptr |
3737 | .cast::<DevicePathHeader>() |
3738 | .write_unaligned(DevicePathHeader { |
3739 | device_type: DeviceType::ACPI, |
3740 | sub_type: DeviceSubType::ACPI_ADR, |
3741 | length: u16::try_from(size).unwrap(), |
3742 | }); |
3743 | self.adr |
3744 | .as_ptr() |
3745 | .cast::<u8>() |
3746 | .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.adr)); |
3747 | } |
3748 | } |
3749 | } |
3750 | |
3751 | /// NVDIMM ACPI device path node. |
3752 | pub struct Nvdimm { |
3753 | /// NFIT device handle. |
3754 | pub nfit_device_handle: u32, |
3755 | } |
3756 | |
3757 | unsafe impl BuildNode for Nvdimm { |
3758 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3759 | let size = 8usize; |
3760 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3761 | } |
3762 | |
3763 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3764 | let size = usize::from(self.size_in_bytes().unwrap()); |
3765 | assert_eq!(size, out.len()); |
3766 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3767 | unsafe { |
3768 | out_ptr |
3769 | .cast::<DevicePathHeader>() |
3770 | .write_unaligned(DevicePathHeader { |
3771 | device_type: DeviceType::ACPI, |
3772 | sub_type: DeviceSubType::ACPI_NVDIMM, |
3773 | length: u16::try_from(size).unwrap(), |
3774 | }); |
3775 | out_ptr |
3776 | .add(4usize) |
3777 | .cast::<u32>() |
3778 | .write_unaligned(self.nfit_device_handle); |
3779 | } |
3780 | } |
3781 | } |
3782 | |
3783 | /// Wrapper for [`u32`] ADR values that enforces at least one |
3784 | /// element is present. |
3785 | #[repr (transparent)] |
3786 | pub struct AdrSlice([u32]); |
3787 | impl AdrSlice { |
3788 | /// Create a new `AdrSlice`. Returns `None` if the input slice |
3789 | /// is empty. |
3790 | #[must_use ] |
3791 | pub fn new(slice: &[u32]) -> Option<&Self> { |
3792 | if slice.is_empty() { |
3793 | None |
3794 | } else { |
3795 | let adr_slice: &Self = unsafe { core::mem::transmute(slice) }; |
3796 | Some(adr_slice) |
3797 | } |
3798 | } |
3799 | |
3800 | fn as_ptr(&self) -> *const u32 { |
3801 | self.0.as_ptr() |
3802 | } |
3803 | } |
3804 | } |
3805 | |
3806 | /// Device path build nodes for [`DeviceType::MESSAGING`]. |
3807 | pub mod messaging { |
3808 | use super::*; |
3809 | /// ATAPI messaging device path node. |
3810 | pub struct Atapi { |
3811 | /// Whether the ATAPI device is primary or secondary. |
3812 | pub primary_secondary: crate::proto::device_path::messaging::PrimarySecondary, |
3813 | /// Whether the ATAPI device is master or slave. |
3814 | pub master_slave: crate::proto::device_path::messaging::MasterSlave, |
3815 | /// Logical Unit Number (LUN). |
3816 | pub logical_unit_number: u16, |
3817 | } |
3818 | |
3819 | unsafe impl BuildNode for Atapi { |
3820 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3821 | let size = 8usize; |
3822 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3823 | } |
3824 | |
3825 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3826 | let size = usize::from(self.size_in_bytes().unwrap()); |
3827 | assert_eq!(size, out.len()); |
3828 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3829 | unsafe { |
3830 | out_ptr |
3831 | .cast::<DevicePathHeader>() |
3832 | .write_unaligned(DevicePathHeader { |
3833 | device_type: DeviceType::MESSAGING, |
3834 | sub_type: DeviceSubType::MESSAGING_ATAPI, |
3835 | length: u16::try_from(size).unwrap(), |
3836 | }); |
3837 | out_ptr |
3838 | .add(4usize) |
3839 | .cast::<crate::proto::device_path::messaging::PrimarySecondary>() |
3840 | .write_unaligned(self.primary_secondary); |
3841 | out_ptr |
3842 | .add(5usize) |
3843 | .cast::<crate::proto::device_path::messaging::MasterSlave>() |
3844 | .write_unaligned(self.master_slave); |
3845 | out_ptr |
3846 | .add(6usize) |
3847 | .cast::<u16>() |
3848 | .write_unaligned(self.logical_unit_number); |
3849 | } |
3850 | } |
3851 | } |
3852 | |
3853 | /// SCSI messaging device path node. |
3854 | pub struct Scsi { |
3855 | /// Target ID on the SCSI bus. |
3856 | pub target_id: u16, |
3857 | /// Logical Unit Number. |
3858 | pub logical_unit_number: u16, |
3859 | } |
3860 | |
3861 | unsafe impl BuildNode for Scsi { |
3862 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3863 | let size = 8usize; |
3864 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3865 | } |
3866 | |
3867 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3868 | let size = usize::from(self.size_in_bytes().unwrap()); |
3869 | assert_eq!(size, out.len()); |
3870 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3871 | unsafe { |
3872 | out_ptr |
3873 | .cast::<DevicePathHeader>() |
3874 | .write_unaligned(DevicePathHeader { |
3875 | device_type: DeviceType::MESSAGING, |
3876 | sub_type: DeviceSubType::MESSAGING_SCSI, |
3877 | length: u16::try_from(size).unwrap(), |
3878 | }); |
3879 | out_ptr |
3880 | .add(4usize) |
3881 | .cast::<u16>() |
3882 | .write_unaligned(self.target_id); |
3883 | out_ptr |
3884 | .add(6usize) |
3885 | .cast::<u16>() |
3886 | .write_unaligned(self.logical_unit_number); |
3887 | } |
3888 | } |
3889 | } |
3890 | |
3891 | /// Fibre channel messaging device path node. |
3892 | pub struct FibreChannel { |
3893 | /// Fibre Channel World Wide Name. |
3894 | pub world_wide_name: u64, |
3895 | /// Fibre Channel Logical Unit Number. |
3896 | pub logical_unit_number: u64, |
3897 | } |
3898 | |
3899 | unsafe impl BuildNode for FibreChannel { |
3900 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3901 | let size = 24usize; |
3902 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3903 | } |
3904 | |
3905 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3906 | let size = usize::from(self.size_in_bytes().unwrap()); |
3907 | assert_eq!(size, out.len()); |
3908 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3909 | unsafe { |
3910 | out_ptr |
3911 | .cast::<DevicePathHeader>() |
3912 | .write_unaligned(DevicePathHeader { |
3913 | device_type: DeviceType::MESSAGING, |
3914 | sub_type: DeviceSubType::MESSAGING_FIBRE_CHANNEL, |
3915 | length: u16::try_from(size).unwrap(), |
3916 | }); |
3917 | out_ptr.add(4usize).write_bytes(0, size_of::<u32>()); |
3918 | out_ptr |
3919 | .add(8usize) |
3920 | .cast::<u64>() |
3921 | .write_unaligned(self.world_wide_name); |
3922 | out_ptr |
3923 | .add(16usize) |
3924 | .cast::<u64>() |
3925 | .write_unaligned(self.logical_unit_number); |
3926 | } |
3927 | } |
3928 | } |
3929 | |
3930 | /// Fibre channel extended messaging device path node. |
3931 | pub struct FibreChannelEx { |
3932 | /// Fibre Channel end device port name (aka World Wide Name). |
3933 | pub world_wide_name: [u8; 8usize], |
3934 | /// Fibre Channel Logical Unit Number. |
3935 | pub logical_unit_number: [u8; 8usize], |
3936 | } |
3937 | |
3938 | unsafe impl BuildNode for FibreChannelEx { |
3939 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3940 | let size = 24usize; |
3941 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3942 | } |
3943 | |
3944 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3945 | let size = usize::from(self.size_in_bytes().unwrap()); |
3946 | assert_eq!(size, out.len()); |
3947 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3948 | unsafe { |
3949 | out_ptr |
3950 | .cast::<DevicePathHeader>() |
3951 | .write_unaligned(DevicePathHeader { |
3952 | device_type: DeviceType::MESSAGING, |
3953 | sub_type: DeviceSubType::MESSAGING_FIBRE_CHANNEL_EX, |
3954 | length: u16::try_from(size).unwrap(), |
3955 | }); |
3956 | out_ptr.add(4usize).write_bytes(0, size_of::<u32>()); |
3957 | out_ptr |
3958 | .add(8usize) |
3959 | .cast::<[u8; 8usize]>() |
3960 | .write_unaligned(self.world_wide_name); |
3961 | out_ptr |
3962 | .add(16usize) |
3963 | .cast::<[u8; 8usize]>() |
3964 | .write_unaligned(self.logical_unit_number); |
3965 | } |
3966 | } |
3967 | } |
3968 | |
3969 | /// 1394 messaging device path node. |
3970 | pub struct Ieee1394 { |
3971 | /// 1394 Global Unique ID. Note that this is not the same as a |
3972 | /// UEFI GUID. |
3973 | pub guid: [u8; 8usize], |
3974 | } |
3975 | |
3976 | unsafe impl BuildNode for Ieee1394 { |
3977 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
3978 | let size = 16usize; |
3979 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
3980 | } |
3981 | |
3982 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
3983 | let size = usize::from(self.size_in_bytes().unwrap()); |
3984 | assert_eq!(size, out.len()); |
3985 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
3986 | unsafe { |
3987 | out_ptr |
3988 | .cast::<DevicePathHeader>() |
3989 | .write_unaligned(DevicePathHeader { |
3990 | device_type: DeviceType::MESSAGING, |
3991 | sub_type: DeviceSubType::MESSAGING_1394, |
3992 | length: u16::try_from(size).unwrap(), |
3993 | }); |
3994 | out_ptr.add(4usize).write_bytes(0, size_of::<u32>()); |
3995 | out_ptr |
3996 | .add(8usize) |
3997 | .cast::<[u8; 8usize]>() |
3998 | .write_unaligned(self.guid); |
3999 | } |
4000 | } |
4001 | } |
4002 | |
4003 | /// USB messaging device path node. |
4004 | pub struct Usb { |
4005 | /// USB parent port number. |
4006 | pub parent_port_number: u8, |
4007 | /// USB interface number. |
4008 | pub interface: u8, |
4009 | } |
4010 | |
4011 | unsafe impl BuildNode for Usb { |
4012 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4013 | let size = 6usize; |
4014 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4015 | } |
4016 | |
4017 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4018 | let size = usize::from(self.size_in_bytes().unwrap()); |
4019 | assert_eq!(size, out.len()); |
4020 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4021 | unsafe { |
4022 | out_ptr |
4023 | .cast::<DevicePathHeader>() |
4024 | .write_unaligned(DevicePathHeader { |
4025 | device_type: DeviceType::MESSAGING, |
4026 | sub_type: DeviceSubType::MESSAGING_USB, |
4027 | length: u16::try_from(size).unwrap(), |
4028 | }); |
4029 | out_ptr |
4030 | .add(4usize) |
4031 | .cast::<u8>() |
4032 | .write_unaligned(self.parent_port_number); |
4033 | out_ptr |
4034 | .add(5usize) |
4035 | .cast::<u8>() |
4036 | .write_unaligned(self.interface); |
4037 | } |
4038 | } |
4039 | } |
4040 | |
4041 | /// SATA messaging device path node. |
4042 | pub struct Sata { |
4043 | /// The HBA port number that facilitates the connection to the |
4044 | /// device or a port multiplier. The value 0xffff is reserved. |
4045 | pub hba_port_number: u16, |
4046 | /// the port multiplier port number that facilitates the |
4047 | /// connection to the device. Must be set to 0xffff if the |
4048 | /// device is directly connected to the HBA. |
4049 | pub port_multiplier_port_number: u16, |
4050 | /// Logical unit number. |
4051 | pub logical_unit_number: u16, |
4052 | } |
4053 | |
4054 | unsafe impl BuildNode for Sata { |
4055 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4056 | let size = 10usize; |
4057 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4058 | } |
4059 | |
4060 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4061 | let size = usize::from(self.size_in_bytes().unwrap()); |
4062 | assert_eq!(size, out.len()); |
4063 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4064 | unsafe { |
4065 | out_ptr |
4066 | .cast::<DevicePathHeader>() |
4067 | .write_unaligned(DevicePathHeader { |
4068 | device_type: DeviceType::MESSAGING, |
4069 | sub_type: DeviceSubType::MESSAGING_SATA, |
4070 | length: u16::try_from(size).unwrap(), |
4071 | }); |
4072 | out_ptr |
4073 | .add(4usize) |
4074 | .cast::<u16>() |
4075 | .write_unaligned(self.hba_port_number); |
4076 | out_ptr |
4077 | .add(6usize) |
4078 | .cast::<u16>() |
4079 | .write_unaligned(self.port_multiplier_port_number); |
4080 | out_ptr |
4081 | .add(8usize) |
4082 | .cast::<u16>() |
4083 | .write_unaligned(self.logical_unit_number); |
4084 | } |
4085 | } |
4086 | } |
4087 | |
4088 | /// USB World Wide ID (WWID) messaging device path node. |
4089 | pub struct UsbWwid<'a> { |
4090 | /// USB interface number. |
4091 | pub interface_number: u16, |
4092 | /// USB vendor ID. |
4093 | pub device_vendor_id: u16, |
4094 | /// USB product ID. |
4095 | pub device_product_id: u16, |
4096 | /// Last 64 (or fewer) characters of the USB Serial number. |
4097 | pub serial_number: &'a [u16], |
4098 | } |
4099 | |
4100 | unsafe impl<'a> BuildNode for UsbWwid<'a> { |
4101 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4102 | let size = 10usize + size_of_val(self.serial_number); |
4103 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4104 | } |
4105 | |
4106 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4107 | let size = usize::from(self.size_in_bytes().unwrap()); |
4108 | assert_eq!(size, out.len()); |
4109 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4110 | unsafe { |
4111 | out_ptr |
4112 | .cast::<DevicePathHeader>() |
4113 | .write_unaligned(DevicePathHeader { |
4114 | device_type: DeviceType::MESSAGING, |
4115 | sub_type: DeviceSubType::MESSAGING_USB_WWID, |
4116 | length: u16::try_from(size).unwrap(), |
4117 | }); |
4118 | out_ptr |
4119 | .add(4usize) |
4120 | .cast::<u16>() |
4121 | .write_unaligned(self.interface_number); |
4122 | out_ptr |
4123 | .add(6usize) |
4124 | .cast::<u16>() |
4125 | .write_unaligned(self.device_vendor_id); |
4126 | out_ptr |
4127 | .add(8usize) |
4128 | .cast::<u16>() |
4129 | .write_unaligned(self.device_product_id); |
4130 | self.serial_number |
4131 | .as_ptr() |
4132 | .cast::<u8>() |
4133 | .copy_to_nonoverlapping( |
4134 | out_ptr.add(10usize), |
4135 | size_of_val(self.serial_number), |
4136 | ); |
4137 | } |
4138 | } |
4139 | } |
4140 | |
4141 | /// Device logical unit messaging device path node. |
4142 | pub struct DeviceLogicalUnit { |
4143 | /// Logical Unit Number. |
4144 | pub logical_unit_number: u8, |
4145 | } |
4146 | |
4147 | unsafe impl BuildNode for DeviceLogicalUnit { |
4148 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4149 | let size = 5usize; |
4150 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4151 | } |
4152 | |
4153 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4154 | let size = usize::from(self.size_in_bytes().unwrap()); |
4155 | assert_eq!(size, out.len()); |
4156 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4157 | unsafe { |
4158 | out_ptr |
4159 | .cast::<DevicePathHeader>() |
4160 | .write_unaligned(DevicePathHeader { |
4161 | device_type: DeviceType::MESSAGING, |
4162 | sub_type: DeviceSubType::MESSAGING_DEVICE_LOGICAL_UNIT, |
4163 | length: u16::try_from(size).unwrap(), |
4164 | }); |
4165 | out_ptr |
4166 | .add(4usize) |
4167 | .cast::<u8>() |
4168 | .write_unaligned(self.logical_unit_number); |
4169 | } |
4170 | } |
4171 | } |
4172 | |
4173 | /// USB class messaging device path node. |
4174 | pub struct UsbClass { |
4175 | /// USB vendor ID. |
4176 | pub vendor_id: u16, |
4177 | /// USB product ID. |
4178 | pub product_id: u16, |
4179 | /// USB device class. |
4180 | pub device_class: u8, |
4181 | /// USB device subclass. |
4182 | pub device_subclass: u8, |
4183 | /// USB device protocol. |
4184 | pub device_protocol: u8, |
4185 | } |
4186 | |
4187 | unsafe impl BuildNode for UsbClass { |
4188 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4189 | let size = 11usize; |
4190 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4191 | } |
4192 | |
4193 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4194 | let size = usize::from(self.size_in_bytes().unwrap()); |
4195 | assert_eq!(size, out.len()); |
4196 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4197 | unsafe { |
4198 | out_ptr |
4199 | .cast::<DevicePathHeader>() |
4200 | .write_unaligned(DevicePathHeader { |
4201 | device_type: DeviceType::MESSAGING, |
4202 | sub_type: DeviceSubType::MESSAGING_USB_CLASS, |
4203 | length: u16::try_from(size).unwrap(), |
4204 | }); |
4205 | out_ptr |
4206 | .add(4usize) |
4207 | .cast::<u16>() |
4208 | .write_unaligned(self.vendor_id); |
4209 | out_ptr |
4210 | .add(6usize) |
4211 | .cast::<u16>() |
4212 | .write_unaligned(self.product_id); |
4213 | out_ptr |
4214 | .add(8usize) |
4215 | .cast::<u8>() |
4216 | .write_unaligned(self.device_class); |
4217 | out_ptr |
4218 | .add(9usize) |
4219 | .cast::<u8>() |
4220 | .write_unaligned(self.device_subclass); |
4221 | out_ptr |
4222 | .add(10usize) |
4223 | .cast::<u8>() |
4224 | .write_unaligned(self.device_protocol); |
4225 | } |
4226 | } |
4227 | } |
4228 | |
4229 | /// I2O messaging device path node. |
4230 | pub struct I2o { |
4231 | /// Target ID (TID). |
4232 | pub target_id: u32, |
4233 | } |
4234 | |
4235 | unsafe impl BuildNode for I2o { |
4236 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4237 | let size = 8usize; |
4238 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4239 | } |
4240 | |
4241 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4242 | let size = usize::from(self.size_in_bytes().unwrap()); |
4243 | assert_eq!(size, out.len()); |
4244 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4245 | unsafe { |
4246 | out_ptr |
4247 | .cast::<DevicePathHeader>() |
4248 | .write_unaligned(DevicePathHeader { |
4249 | device_type: DeviceType::MESSAGING, |
4250 | sub_type: DeviceSubType::MESSAGING_I2O, |
4251 | length: u16::try_from(size).unwrap(), |
4252 | }); |
4253 | out_ptr |
4254 | .add(4usize) |
4255 | .cast::<u32>() |
4256 | .write_unaligned(self.target_id); |
4257 | } |
4258 | } |
4259 | } |
4260 | |
4261 | /// MAC address messaging device path node. |
4262 | pub struct MacAddress { |
4263 | /// MAC address for a network interface, padded with zeros. |
4264 | pub mac_address: [u8; 32usize], |
4265 | /// Network interface type. See |
4266 | /// <https://www.iana.org/assignments/smi-numbers/smi-numbers.xhtml#smi-numbers-5> |
4267 | pub interface_type: u8, |
4268 | } |
4269 | |
4270 | unsafe impl BuildNode for MacAddress { |
4271 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4272 | let size = 37usize; |
4273 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4274 | } |
4275 | |
4276 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4277 | let size = usize::from(self.size_in_bytes().unwrap()); |
4278 | assert_eq!(size, out.len()); |
4279 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4280 | unsafe { |
4281 | out_ptr |
4282 | .cast::<DevicePathHeader>() |
4283 | .write_unaligned(DevicePathHeader { |
4284 | device_type: DeviceType::MESSAGING, |
4285 | sub_type: DeviceSubType::MESSAGING_MAC_ADDRESS, |
4286 | length: u16::try_from(size).unwrap(), |
4287 | }); |
4288 | out_ptr |
4289 | .add(4usize) |
4290 | .cast::<[u8; 32usize]>() |
4291 | .write_unaligned(self.mac_address); |
4292 | out_ptr |
4293 | .add(36usize) |
4294 | .cast::<u8>() |
4295 | .write_unaligned(self.interface_type); |
4296 | } |
4297 | } |
4298 | } |
4299 | |
4300 | /// IPv4 messaging device path node. |
4301 | pub struct Ipv4 { |
4302 | /// Local IPv4 address. |
4303 | pub local_ip_address: [u8; 4usize], |
4304 | /// Remote IPv4 address. |
4305 | pub remote_ip_address: [u8; 4usize], |
4306 | /// Local port number. |
4307 | pub local_port: u16, |
4308 | /// Remote port number. |
4309 | pub remote_port: u16, |
4310 | /// Network protocol. See |
4311 | /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml> |
4312 | pub protocol: u16, |
4313 | /// Whether the source IP address is static or assigned via DHCP. |
4314 | pub ip_address_origin: crate::proto::device_path::messaging::Ipv4AddressOrigin, |
4315 | /// Gateway IP address. |
4316 | pub gateway_ip_address: [u8; 4usize], |
4317 | /// Subnet mask. |
4318 | pub subnet_mask: [u8; 4usize], |
4319 | } |
4320 | |
4321 | unsafe impl BuildNode for Ipv4 { |
4322 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4323 | let size = 27usize; |
4324 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4325 | } |
4326 | |
4327 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4328 | let size = usize::from(self.size_in_bytes().unwrap()); |
4329 | assert_eq!(size, out.len()); |
4330 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4331 | unsafe { |
4332 | out_ptr |
4333 | .cast::<DevicePathHeader>() |
4334 | .write_unaligned(DevicePathHeader { |
4335 | device_type: DeviceType::MESSAGING, |
4336 | sub_type: DeviceSubType::MESSAGING_IPV4, |
4337 | length: u16::try_from(size).unwrap(), |
4338 | }); |
4339 | out_ptr |
4340 | .add(4usize) |
4341 | .cast::<[u8; 4usize]>() |
4342 | .write_unaligned(self.local_ip_address); |
4343 | out_ptr |
4344 | .add(8usize) |
4345 | .cast::<[u8; 4usize]>() |
4346 | .write_unaligned(self.remote_ip_address); |
4347 | out_ptr |
4348 | .add(12usize) |
4349 | .cast::<u16>() |
4350 | .write_unaligned(self.local_port); |
4351 | out_ptr |
4352 | .add(14usize) |
4353 | .cast::<u16>() |
4354 | .write_unaligned(self.remote_port); |
4355 | out_ptr |
4356 | .add(16usize) |
4357 | .cast::<u16>() |
4358 | .write_unaligned(self.protocol); |
4359 | out_ptr |
4360 | .add(18usize) |
4361 | .cast::<crate::proto::device_path::messaging::Ipv4AddressOrigin>() |
4362 | .write_unaligned(self.ip_address_origin); |
4363 | out_ptr |
4364 | .add(19usize) |
4365 | .cast::<[u8; 4usize]>() |
4366 | .write_unaligned(self.gateway_ip_address); |
4367 | out_ptr |
4368 | .add(23usize) |
4369 | .cast::<[u8; 4usize]>() |
4370 | .write_unaligned(self.subnet_mask); |
4371 | } |
4372 | } |
4373 | } |
4374 | |
4375 | /// IPv6 messaging device path node. |
4376 | pub struct Ipv6 { |
4377 | /// Local Ipv6 address. |
4378 | pub local_ip_address: [u8; 16usize], |
4379 | /// Remote Ipv6 address. |
4380 | pub remote_ip_address: [u8; 16usize], |
4381 | /// Local port number. |
4382 | pub local_port: u16, |
4383 | /// Remote port number. |
4384 | pub remote_port: u16, |
4385 | /// Network protocol. See |
4386 | /// <https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml> |
4387 | pub protocol: u16, |
4388 | /// Origin of the local IP address. |
4389 | pub ip_address_origin: crate::proto::device_path::messaging::Ipv6AddressOrigin, |
4390 | /// Prefix length. |
4391 | pub prefix_length: u8, |
4392 | /// Gateway IP address. |
4393 | pub gateway_ip_address: [u8; 16usize], |
4394 | } |
4395 | |
4396 | unsafe impl BuildNode for Ipv6 { |
4397 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4398 | let size = 60usize; |
4399 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4400 | } |
4401 | |
4402 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4403 | let size = usize::from(self.size_in_bytes().unwrap()); |
4404 | assert_eq!(size, out.len()); |
4405 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4406 | unsafe { |
4407 | out_ptr |
4408 | .cast::<DevicePathHeader>() |
4409 | .write_unaligned(DevicePathHeader { |
4410 | device_type: DeviceType::MESSAGING, |
4411 | sub_type: DeviceSubType::MESSAGING_IPV6, |
4412 | length: u16::try_from(size).unwrap(), |
4413 | }); |
4414 | out_ptr |
4415 | .add(4usize) |
4416 | .cast::<[u8; 16usize]>() |
4417 | .write_unaligned(self.local_ip_address); |
4418 | out_ptr |
4419 | .add(20usize) |
4420 | .cast::<[u8; 16usize]>() |
4421 | .write_unaligned(self.remote_ip_address); |
4422 | out_ptr |
4423 | .add(36usize) |
4424 | .cast::<u16>() |
4425 | .write_unaligned(self.local_port); |
4426 | out_ptr |
4427 | .add(38usize) |
4428 | .cast::<u16>() |
4429 | .write_unaligned(self.remote_port); |
4430 | out_ptr |
4431 | .add(40usize) |
4432 | .cast::<u16>() |
4433 | .write_unaligned(self.protocol); |
4434 | out_ptr |
4435 | .add(42usize) |
4436 | .cast::<crate::proto::device_path::messaging::Ipv6AddressOrigin>() |
4437 | .write_unaligned(self.ip_address_origin); |
4438 | out_ptr |
4439 | .add(43usize) |
4440 | .cast::<u8>() |
4441 | .write_unaligned(self.prefix_length); |
4442 | out_ptr |
4443 | .add(44usize) |
4444 | .cast::<[u8; 16usize]>() |
4445 | .write_unaligned(self.gateway_ip_address); |
4446 | } |
4447 | } |
4448 | } |
4449 | |
4450 | /// VLAN messaging device path node. |
4451 | pub struct Vlan { |
4452 | /// VLAN identifier (0-4094). |
4453 | pub vlan_id: u16, |
4454 | } |
4455 | |
4456 | unsafe impl BuildNode for Vlan { |
4457 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4458 | let size = 6usize; |
4459 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4460 | } |
4461 | |
4462 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4463 | let size = usize::from(self.size_in_bytes().unwrap()); |
4464 | assert_eq!(size, out.len()); |
4465 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4466 | unsafe { |
4467 | out_ptr |
4468 | .cast::<DevicePathHeader>() |
4469 | .write_unaligned(DevicePathHeader { |
4470 | device_type: DeviceType::MESSAGING, |
4471 | sub_type: DeviceSubType::MESSAGING_VLAN, |
4472 | length: u16::try_from(size).unwrap(), |
4473 | }); |
4474 | out_ptr |
4475 | .add(4usize) |
4476 | .cast::<u16>() |
4477 | .write_unaligned(self.vlan_id); |
4478 | } |
4479 | } |
4480 | } |
4481 | |
4482 | /// InfiniBand messaging device path node. |
4483 | pub struct Infiniband { |
4484 | /// Flags to identify/manage InfiniBand elements. |
4485 | pub resource_flags: crate::proto::device_path::messaging::InfinibandResourceFlags, |
4486 | /// 128-bit Global Identifier for remote fabric port. Note that |
4487 | /// this is not the same as a UEFI GUID. |
4488 | pub port_gid: [u8; 16usize], |
4489 | /// IOC GUID if bit 0 of `resource_flags` is unset, or Service |
4490 | /// ID if bit 0 of `resource_flags` is set. |
4491 | pub ioc_guid_or_service_id: u64, |
4492 | /// 64-bit persistent ID of remote IOC port. |
4493 | pub target_port_id: u64, |
4494 | /// 64-bit persistent ID of remote device.. |
4495 | pub device_id: u64, |
4496 | } |
4497 | |
4498 | unsafe impl BuildNode for Infiniband { |
4499 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4500 | let size = 48usize; |
4501 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4502 | } |
4503 | |
4504 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4505 | let size = usize::from(self.size_in_bytes().unwrap()); |
4506 | assert_eq!(size, out.len()); |
4507 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4508 | unsafe { |
4509 | out_ptr |
4510 | .cast::<DevicePathHeader>() |
4511 | .write_unaligned(DevicePathHeader { |
4512 | device_type: DeviceType::MESSAGING, |
4513 | sub_type: DeviceSubType::MESSAGING_INFINIBAND, |
4514 | length: u16::try_from(size).unwrap(), |
4515 | }); |
4516 | out_ptr |
4517 | .add(4usize) |
4518 | .cast::<crate::proto::device_path::messaging::InfinibandResourceFlags>() |
4519 | .write_unaligned(self.resource_flags); |
4520 | out_ptr |
4521 | .add(8usize) |
4522 | .cast::<[u8; 16usize]>() |
4523 | .write_unaligned(self.port_gid); |
4524 | out_ptr |
4525 | .add(24usize) |
4526 | .cast::<u64>() |
4527 | .write_unaligned(self.ioc_guid_or_service_id); |
4528 | out_ptr |
4529 | .add(32usize) |
4530 | .cast::<u64>() |
4531 | .write_unaligned(self.target_port_id); |
4532 | out_ptr |
4533 | .add(40usize) |
4534 | .cast::<u64>() |
4535 | .write_unaligned(self.device_id); |
4536 | } |
4537 | } |
4538 | } |
4539 | |
4540 | /// UART messaging device path node. |
4541 | pub struct Uart { |
4542 | /// Baud rate setting, or 0 to use the device's default. |
4543 | pub baud_rate: u64, |
4544 | /// Number of data bits, or 0 to use the device's default. |
4545 | pub data_bits: u8, |
4546 | /// Parity setting. |
4547 | pub parity: crate::proto::device_path::messaging::Parity, |
4548 | /// Number of stop bits. |
4549 | pub stop_bits: crate::proto::device_path::messaging::StopBits, |
4550 | } |
4551 | |
4552 | unsafe impl BuildNode for Uart { |
4553 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4554 | let size = 19usize; |
4555 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4556 | } |
4557 | |
4558 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4559 | let size = usize::from(self.size_in_bytes().unwrap()); |
4560 | assert_eq!(size, out.len()); |
4561 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4562 | unsafe { |
4563 | out_ptr |
4564 | .cast::<DevicePathHeader>() |
4565 | .write_unaligned(DevicePathHeader { |
4566 | device_type: DeviceType::MESSAGING, |
4567 | sub_type: DeviceSubType::MESSAGING_UART, |
4568 | length: u16::try_from(size).unwrap(), |
4569 | }); |
4570 | out_ptr.add(4usize).write_bytes(0, size_of::<u32>()); |
4571 | out_ptr |
4572 | .add(8usize) |
4573 | .cast::<u64>() |
4574 | .write_unaligned(self.baud_rate); |
4575 | out_ptr |
4576 | .add(16usize) |
4577 | .cast::<u8>() |
4578 | .write_unaligned(self.data_bits); |
4579 | out_ptr |
4580 | .add(17usize) |
4581 | .cast::<crate::proto::device_path::messaging::Parity>() |
4582 | .write_unaligned(self.parity); |
4583 | out_ptr |
4584 | .add(18usize) |
4585 | .cast::<crate::proto::device_path::messaging::StopBits>() |
4586 | .write_unaligned(self.stop_bits); |
4587 | } |
4588 | } |
4589 | } |
4590 | |
4591 | /// Vendor-defined messaging device path node. |
4592 | pub struct Vendor<'a> { |
4593 | /// Vendor-assigned GUID that defines the data that follows. |
4594 | pub vendor_guid: Guid, |
4595 | /// Vendor-defined data. |
4596 | pub vendor_defined_data: &'a [u8], |
4597 | } |
4598 | |
4599 | unsafe impl<'a> BuildNode for Vendor<'a> { |
4600 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4601 | let size = 20usize + size_of_val(self.vendor_defined_data); |
4602 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4603 | } |
4604 | |
4605 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4606 | let size = usize::from(self.size_in_bytes().unwrap()); |
4607 | assert_eq!(size, out.len()); |
4608 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4609 | unsafe { |
4610 | out_ptr |
4611 | .cast::<DevicePathHeader>() |
4612 | .write_unaligned(DevicePathHeader { |
4613 | device_type: DeviceType::MESSAGING, |
4614 | sub_type: DeviceSubType::MESSAGING_VENDOR, |
4615 | length: u16::try_from(size).unwrap(), |
4616 | }); |
4617 | out_ptr |
4618 | .add(4usize) |
4619 | .cast::<Guid>() |
4620 | .write_unaligned(self.vendor_guid); |
4621 | self.vendor_defined_data |
4622 | .as_ptr() |
4623 | .cast::<u8>() |
4624 | .copy_to_nonoverlapping( |
4625 | out_ptr.add(20usize), |
4626 | size_of_val(self.vendor_defined_data), |
4627 | ); |
4628 | } |
4629 | } |
4630 | } |
4631 | |
4632 | /// Serial Attached SCSI (SAS) extended messaging device path node. |
4633 | pub struct SasEx { |
4634 | /// SAS address. |
4635 | pub sas_address: [u8; 8usize], |
4636 | /// Logical Unit Number. |
4637 | pub logical_unit_number: [u8; 8usize], |
4638 | /// Information about the device and its interconnect. |
4639 | pub info: u16, |
4640 | /// Relative Target Port (RTP). |
4641 | pub relative_target_port: u16, |
4642 | } |
4643 | |
4644 | unsafe impl BuildNode for SasEx { |
4645 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4646 | let size = 24usize; |
4647 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4648 | } |
4649 | |
4650 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4651 | let size = usize::from(self.size_in_bytes().unwrap()); |
4652 | assert_eq!(size, out.len()); |
4653 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4654 | unsafe { |
4655 | out_ptr |
4656 | .cast::<DevicePathHeader>() |
4657 | .write_unaligned(DevicePathHeader { |
4658 | device_type: DeviceType::MESSAGING, |
4659 | sub_type: DeviceSubType::MESSAGING_SCSI_SAS_EX, |
4660 | length: u16::try_from(size).unwrap(), |
4661 | }); |
4662 | out_ptr |
4663 | .add(4usize) |
4664 | .cast::<[u8; 8usize]>() |
4665 | .write_unaligned(self.sas_address); |
4666 | out_ptr |
4667 | .add(12usize) |
4668 | .cast::<[u8; 8usize]>() |
4669 | .write_unaligned(self.logical_unit_number); |
4670 | out_ptr |
4671 | .add(20usize) |
4672 | .cast::<u16>() |
4673 | .write_unaligned(self.info); |
4674 | out_ptr |
4675 | .add(22usize) |
4676 | .cast::<u16>() |
4677 | .write_unaligned(self.relative_target_port); |
4678 | } |
4679 | } |
4680 | } |
4681 | |
4682 | /// iSCSI messaging device path node. |
4683 | pub struct Iscsi<'a> { |
4684 | /// Network protocol. |
4685 | pub protocol: crate::proto::device_path::messaging::IscsiProtocol, |
4686 | /// iSCSI login options (bitfield). |
4687 | pub options: crate::proto::device_path::messaging::IscsiLoginOptions, |
4688 | /// iSCSI Logical Unit Number. |
4689 | pub logical_unit_number: [u8; 8usize], |
4690 | /// iSCSI Target Portal group tag the initiator intends to |
4691 | /// establish a session with. |
4692 | pub target_portal_group_tag: u16, |
4693 | /// iSCSI Node Target name. |
4694 | /// |
4695 | /// The UEFI Specification does not specify how the string is |
4696 | /// encoded, but gives one example that appears to be |
4697 | /// null-terminated ASCII. |
4698 | pub iscsi_target_name: &'a [u8], |
4699 | } |
4700 | |
4701 | unsafe impl<'a> BuildNode for Iscsi<'a> { |
4702 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4703 | let size = 18usize + size_of_val(self.iscsi_target_name); |
4704 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4705 | } |
4706 | |
4707 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4708 | let size = usize::from(self.size_in_bytes().unwrap()); |
4709 | assert_eq!(size, out.len()); |
4710 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4711 | unsafe { |
4712 | out_ptr |
4713 | .cast::<DevicePathHeader>() |
4714 | .write_unaligned(DevicePathHeader { |
4715 | device_type: DeviceType::MESSAGING, |
4716 | sub_type: DeviceSubType::MESSAGING_ISCSI, |
4717 | length: u16::try_from(size).unwrap(), |
4718 | }); |
4719 | out_ptr |
4720 | .add(4usize) |
4721 | .cast::<crate::proto::device_path::messaging::IscsiProtocol>() |
4722 | .write_unaligned(self.protocol); |
4723 | out_ptr |
4724 | .add(6usize) |
4725 | .cast::<crate::proto::device_path::messaging::IscsiLoginOptions>() |
4726 | .write_unaligned(self.options); |
4727 | out_ptr |
4728 | .add(8usize) |
4729 | .cast::<[u8; 8usize]>() |
4730 | .write_unaligned(self.logical_unit_number); |
4731 | out_ptr |
4732 | .add(16usize) |
4733 | .cast::<u16>() |
4734 | .write_unaligned(self.target_portal_group_tag); |
4735 | self.iscsi_target_name |
4736 | .as_ptr() |
4737 | .cast::<u8>() |
4738 | .copy_to_nonoverlapping( |
4739 | out_ptr.add(18usize), |
4740 | size_of_val(self.iscsi_target_name), |
4741 | ); |
4742 | } |
4743 | } |
4744 | } |
4745 | |
4746 | /// NVM Express namespace messaging device path node. |
4747 | pub struct NvmeNamespace { |
4748 | /// Namespace identifier (NSID). The values 0 and 0xffff_ffff |
4749 | /// are invalid. |
4750 | pub namespace_identifier: u32, |
4751 | /// IEEE Extended Unique Identifier (EUI-64), or 0 if the device |
4752 | /// does not have a EUI-64. |
4753 | pub ieee_extended_unique_identifier: u64, |
4754 | } |
4755 | |
4756 | unsafe impl BuildNode for NvmeNamespace { |
4757 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4758 | let size = 16usize; |
4759 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4760 | } |
4761 | |
4762 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4763 | let size = usize::from(self.size_in_bytes().unwrap()); |
4764 | assert_eq!(size, out.len()); |
4765 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4766 | unsafe { |
4767 | out_ptr |
4768 | .cast::<DevicePathHeader>() |
4769 | .write_unaligned(DevicePathHeader { |
4770 | device_type: DeviceType::MESSAGING, |
4771 | sub_type: DeviceSubType::MESSAGING_NVME_NAMESPACE, |
4772 | length: u16::try_from(size).unwrap(), |
4773 | }); |
4774 | out_ptr |
4775 | .add(4usize) |
4776 | .cast::<u32>() |
4777 | .write_unaligned(self.namespace_identifier); |
4778 | out_ptr |
4779 | .add(8usize) |
4780 | .cast::<u64>() |
4781 | .write_unaligned(self.ieee_extended_unique_identifier); |
4782 | } |
4783 | } |
4784 | } |
4785 | |
4786 | /// Uniform Resource Identifier (URI) messaging device path node. |
4787 | pub struct Uri<'a> { |
4788 | /// URI as defined by [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986). |
4789 | pub value: &'a [u8], |
4790 | } |
4791 | |
4792 | unsafe impl<'a> BuildNode for Uri<'a> { |
4793 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4794 | let size = 4usize + size_of_val(self.value); |
4795 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4796 | } |
4797 | |
4798 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4799 | let size = usize::from(self.size_in_bytes().unwrap()); |
4800 | assert_eq!(size, out.len()); |
4801 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4802 | unsafe { |
4803 | out_ptr |
4804 | .cast::<DevicePathHeader>() |
4805 | .write_unaligned(DevicePathHeader { |
4806 | device_type: DeviceType::MESSAGING, |
4807 | sub_type: DeviceSubType::MESSAGING_URI, |
4808 | length: u16::try_from(size).unwrap(), |
4809 | }); |
4810 | self.value |
4811 | .as_ptr() |
4812 | .cast::<u8>() |
4813 | .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.value)); |
4814 | } |
4815 | } |
4816 | } |
4817 | |
4818 | /// Universal Flash Storage (UFS) messaging device path node. |
4819 | pub struct Ufs { |
4820 | /// Target ID on the UFS interface (PUN). |
4821 | pub target_id: u8, |
4822 | /// Logical Unit Number (LUN). |
4823 | pub logical_unit_number: u8, |
4824 | } |
4825 | |
4826 | unsafe impl BuildNode for Ufs { |
4827 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4828 | let size = 6usize; |
4829 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4830 | } |
4831 | |
4832 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4833 | let size = usize::from(self.size_in_bytes().unwrap()); |
4834 | assert_eq!(size, out.len()); |
4835 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4836 | unsafe { |
4837 | out_ptr |
4838 | .cast::<DevicePathHeader>() |
4839 | .write_unaligned(DevicePathHeader { |
4840 | device_type: DeviceType::MESSAGING, |
4841 | sub_type: DeviceSubType::MESSAGING_UFS, |
4842 | length: u16::try_from(size).unwrap(), |
4843 | }); |
4844 | out_ptr |
4845 | .add(4usize) |
4846 | .cast::<u8>() |
4847 | .write_unaligned(self.target_id); |
4848 | out_ptr |
4849 | .add(5usize) |
4850 | .cast::<u8>() |
4851 | .write_unaligned(self.logical_unit_number); |
4852 | } |
4853 | } |
4854 | } |
4855 | |
4856 | /// Secure Digital (SD) messaging device path node. |
4857 | pub struct Sd { |
4858 | /// Slot number. |
4859 | pub slot_number: u8, |
4860 | } |
4861 | |
4862 | unsafe impl BuildNode for Sd { |
4863 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4864 | let size = 5usize; |
4865 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4866 | } |
4867 | |
4868 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4869 | let size = usize::from(self.size_in_bytes().unwrap()); |
4870 | assert_eq!(size, out.len()); |
4871 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4872 | unsafe { |
4873 | out_ptr |
4874 | .cast::<DevicePathHeader>() |
4875 | .write_unaligned(DevicePathHeader { |
4876 | device_type: DeviceType::MESSAGING, |
4877 | sub_type: DeviceSubType::MESSAGING_SD, |
4878 | length: u16::try_from(size).unwrap(), |
4879 | }); |
4880 | out_ptr |
4881 | .add(4usize) |
4882 | .cast::<u8>() |
4883 | .write_unaligned(self.slot_number); |
4884 | } |
4885 | } |
4886 | } |
4887 | |
4888 | /// Bluetooth messaging device path node. |
4889 | pub struct Bluetooth { |
4890 | /// 48-bit bluetooth device address. |
4891 | pub device_address: [u8; 6usize], |
4892 | } |
4893 | |
4894 | unsafe impl BuildNode for Bluetooth { |
4895 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4896 | let size = 10usize; |
4897 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4898 | } |
4899 | |
4900 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4901 | let size = usize::from(self.size_in_bytes().unwrap()); |
4902 | assert_eq!(size, out.len()); |
4903 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4904 | unsafe { |
4905 | out_ptr |
4906 | .cast::<DevicePathHeader>() |
4907 | .write_unaligned(DevicePathHeader { |
4908 | device_type: DeviceType::MESSAGING, |
4909 | sub_type: DeviceSubType::MESSAGING_BLUETOOTH, |
4910 | length: u16::try_from(size).unwrap(), |
4911 | }); |
4912 | out_ptr |
4913 | .add(4usize) |
4914 | .cast::<[u8; 6usize]>() |
4915 | .write_unaligned(self.device_address); |
4916 | } |
4917 | } |
4918 | } |
4919 | |
4920 | /// Wi-Fi messaging device path node. |
4921 | pub struct Wifi { |
4922 | /// Service set identifier (SSID). |
4923 | pub ssid: [u8; 32usize], |
4924 | } |
4925 | |
4926 | unsafe impl BuildNode for Wifi { |
4927 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4928 | let size = 36usize; |
4929 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4930 | } |
4931 | |
4932 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4933 | let size = usize::from(self.size_in_bytes().unwrap()); |
4934 | assert_eq!(size, out.len()); |
4935 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4936 | unsafe { |
4937 | out_ptr |
4938 | .cast::<DevicePathHeader>() |
4939 | .write_unaligned(DevicePathHeader { |
4940 | device_type: DeviceType::MESSAGING, |
4941 | sub_type: DeviceSubType::MESSAGING_WIFI, |
4942 | length: u16::try_from(size).unwrap(), |
4943 | }); |
4944 | out_ptr |
4945 | .add(4usize) |
4946 | .cast::<[u8; 32usize]>() |
4947 | .write_unaligned(self.ssid); |
4948 | } |
4949 | } |
4950 | } |
4951 | |
4952 | /// Embedded Multi-Media Card (eMMC) messaging device path node. |
4953 | pub struct Emmc { |
4954 | /// Slot number. |
4955 | pub slot_number: u8, |
4956 | } |
4957 | |
4958 | unsafe impl BuildNode for Emmc { |
4959 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4960 | let size = 5usize; |
4961 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4962 | } |
4963 | |
4964 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4965 | let size = usize::from(self.size_in_bytes().unwrap()); |
4966 | assert_eq!(size, out.len()); |
4967 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
4968 | unsafe { |
4969 | out_ptr |
4970 | .cast::<DevicePathHeader>() |
4971 | .write_unaligned(DevicePathHeader { |
4972 | device_type: DeviceType::MESSAGING, |
4973 | sub_type: DeviceSubType::MESSAGING_EMMC, |
4974 | length: u16::try_from(size).unwrap(), |
4975 | }); |
4976 | out_ptr |
4977 | .add(4usize) |
4978 | .cast::<u8>() |
4979 | .write_unaligned(self.slot_number); |
4980 | } |
4981 | } |
4982 | } |
4983 | |
4984 | /// BluetoothLE messaging device path node. |
4985 | pub struct BluetoothLe { |
4986 | /// 48-bit bluetooth device address. |
4987 | pub device_address: [u8; 6usize], |
4988 | /// Address type. |
4989 | pub address_type: crate::proto::device_path::messaging::BluetoothLeAddressType, |
4990 | } |
4991 | |
4992 | unsafe impl BuildNode for BluetoothLe { |
4993 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
4994 | let size = 11usize; |
4995 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
4996 | } |
4997 | |
4998 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
4999 | let size = usize::from(self.size_in_bytes().unwrap()); |
5000 | assert_eq!(size, out.len()); |
5001 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5002 | unsafe { |
5003 | out_ptr |
5004 | .cast::<DevicePathHeader>() |
5005 | .write_unaligned(DevicePathHeader { |
5006 | device_type: DeviceType::MESSAGING, |
5007 | sub_type: DeviceSubType::MESSAGING_BLUETOOTH_LE, |
5008 | length: u16::try_from(size).unwrap(), |
5009 | }); |
5010 | out_ptr |
5011 | .add(4usize) |
5012 | .cast::<[u8; 6usize]>() |
5013 | .write_unaligned(self.device_address); |
5014 | out_ptr |
5015 | .add(10usize) |
5016 | .cast::<crate::proto::device_path::messaging::BluetoothLeAddressType>() |
5017 | .write_unaligned(self.address_type); |
5018 | } |
5019 | } |
5020 | } |
5021 | |
5022 | /// DNS messaging device path node. |
5023 | pub struct Dns<'a> { |
5024 | /// Whether the addresses are IPv4 or IPv6. |
5025 | pub address_type: crate::proto::device_path::messaging::DnsAddressType, |
5026 | /// One or more instances of the DNS server address. |
5027 | pub addresses: &'a [IpAddress], |
5028 | } |
5029 | |
5030 | unsafe impl<'a> BuildNode for Dns<'a> { |
5031 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5032 | let size = 5usize + size_of_val(self.addresses); |
5033 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5034 | } |
5035 | |
5036 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5037 | let size = usize::from(self.size_in_bytes().unwrap()); |
5038 | assert_eq!(size, out.len()); |
5039 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5040 | unsafe { |
5041 | out_ptr |
5042 | .cast::<DevicePathHeader>() |
5043 | .write_unaligned(DevicePathHeader { |
5044 | device_type: DeviceType::MESSAGING, |
5045 | sub_type: DeviceSubType::MESSAGING_DNS, |
5046 | length: u16::try_from(size).unwrap(), |
5047 | }); |
5048 | out_ptr |
5049 | .add(4usize) |
5050 | .cast::<crate::proto::device_path::messaging::DnsAddressType>() |
5051 | .write_unaligned(self.address_type); |
5052 | self.addresses |
5053 | .as_ptr() |
5054 | .cast::<u8>() |
5055 | .copy_to_nonoverlapping(out_ptr.add(5usize), size_of_val(self.addresses)); |
5056 | } |
5057 | } |
5058 | } |
5059 | |
5060 | /// NVDIMM namespace messaging device path node. |
5061 | pub struct NvdimmNamespace { |
5062 | /// Namespace unique label identifier. |
5063 | pub uuid: [u8; 16usize], |
5064 | } |
5065 | |
5066 | unsafe impl BuildNode for NvdimmNamespace { |
5067 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5068 | let size = 20usize; |
5069 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5070 | } |
5071 | |
5072 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5073 | let size = usize::from(self.size_in_bytes().unwrap()); |
5074 | assert_eq!(size, out.len()); |
5075 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5076 | unsafe { |
5077 | out_ptr |
5078 | .cast::<DevicePathHeader>() |
5079 | .write_unaligned(DevicePathHeader { |
5080 | device_type: DeviceType::MESSAGING, |
5081 | sub_type: DeviceSubType::MESSAGING_NVDIMM_NAMESPACE, |
5082 | length: u16::try_from(size).unwrap(), |
5083 | }); |
5084 | out_ptr |
5085 | .add(4usize) |
5086 | .cast::<[u8; 16usize]>() |
5087 | .write_unaligned(self.uuid); |
5088 | } |
5089 | } |
5090 | } |
5091 | |
5092 | /// REST service messaging device path node. |
5093 | pub struct RestService<'a> { |
5094 | /// Type of REST service. |
5095 | pub service_type: crate::proto::device_path::messaging::RestServiceType, |
5096 | /// Whether the service is in-band or out-of-band. |
5097 | pub access_mode: crate::proto::device_path::messaging::RestServiceAccessMode, |
5098 | /// Vendor-specific data. Only used if the service type is [`VENDOR`]. |
5099 | /// |
5100 | /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType |
5101 | pub vendor_guid_and_data: Option<RestServiceVendorData<'a>>, |
5102 | } |
5103 | |
5104 | unsafe impl<'a> BuildNode for RestService<'a> { |
5105 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5106 | let size = 6usize + self.build_size_vendor_guid_and_data(); |
5107 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5108 | } |
5109 | |
5110 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5111 | let size = usize::from(self.size_in_bytes().unwrap()); |
5112 | assert_eq!(size, out.len()); |
5113 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5114 | unsafe { |
5115 | out_ptr |
5116 | .cast::<DevicePathHeader>() |
5117 | .write_unaligned(DevicePathHeader { |
5118 | device_type: DeviceType::MESSAGING, |
5119 | sub_type: DeviceSubType::MESSAGING_REST_SERVICE, |
5120 | length: u16::try_from(size).unwrap(), |
5121 | }); |
5122 | out_ptr |
5123 | .add(4usize) |
5124 | .cast::<crate::proto::device_path::messaging::RestServiceType>() |
5125 | .write_unaligned(self.service_type); |
5126 | out_ptr |
5127 | .add(5usize) |
5128 | .cast::<crate::proto::device_path::messaging::RestServiceAccessMode>() |
5129 | .write_unaligned(self.access_mode); |
5130 | self.build_vendor_guid_and_data(&mut out[6usize..]) |
5131 | } |
5132 | } |
5133 | } |
5134 | |
5135 | /// NVME over Fabric (NVMe-oF) namespace messaging device path node. |
5136 | pub struct NvmeOfNamespace<'a> { |
5137 | /// Namespace Identifier Type (NIDT). |
5138 | pub nidt: u8, |
5139 | /// Namespace Identifier (NID). |
5140 | pub nid: [u8; 16usize], |
5141 | /// Unique identifier of an NVM subsystem stored as a |
5142 | /// null-terminated UTF-8 string. Maximum length of 224 bytes. |
5143 | pub subsystem_nqn: &'a [u8], |
5144 | } |
5145 | |
5146 | unsafe impl<'a> BuildNode for NvmeOfNamespace<'a> { |
5147 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5148 | let size = 21usize + size_of_val(self.subsystem_nqn); |
5149 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5150 | } |
5151 | |
5152 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5153 | let size = usize::from(self.size_in_bytes().unwrap()); |
5154 | assert_eq!(size, out.len()); |
5155 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5156 | unsafe { |
5157 | out_ptr |
5158 | .cast::<DevicePathHeader>() |
5159 | .write_unaligned(DevicePathHeader { |
5160 | device_type: DeviceType::MESSAGING, |
5161 | sub_type: DeviceSubType::MESSAGING_NVME_OF_NAMESPACE, |
5162 | length: u16::try_from(size).unwrap(), |
5163 | }); |
5164 | out_ptr.add(4usize).cast::<u8>().write_unaligned(self.nidt); |
5165 | out_ptr |
5166 | .add(5usize) |
5167 | .cast::<[u8; 16usize]>() |
5168 | .write_unaligned(self.nid); |
5169 | self.subsystem_nqn |
5170 | .as_ptr() |
5171 | .cast::<u8>() |
5172 | .copy_to_nonoverlapping( |
5173 | out_ptr.add(21usize), |
5174 | size_of_val(self.subsystem_nqn), |
5175 | ); |
5176 | } |
5177 | } |
5178 | } |
5179 | |
5180 | /// Vendor-specific REST service data. Only used for service type [`VENDOR`]. |
5181 | /// |
5182 | /// [`VENDOR`]: uefi::proto::device_path::messaging::RestServiceType |
5183 | pub struct RestServiceVendorData<'a> { |
5184 | /// Vendor GUID. |
5185 | pub vendor_guid: Guid, |
5186 | /// Vendor-defined data. |
5187 | pub vendor_defined_data: &'a [u8], |
5188 | } |
5189 | |
5190 | impl<'a> RestService<'a> { |
5191 | fn build_size_vendor_guid_and_data(&self) -> usize { |
5192 | if let Some(src) = &self.vendor_guid_and_data { |
5193 | assert!( |
5194 | self.service_type |
5195 | == crate::proto::device_path::messaging::RestServiceType::VENDOR |
5196 | ); |
5197 | size_of::<Guid>() + size_of_val(src.vendor_defined_data) |
5198 | } else { |
5199 | 0 |
5200 | } |
5201 | } |
5202 | |
5203 | fn build_vendor_guid_and_data(&self, out: &mut [MaybeUninit<u8>]) { |
5204 | if let Some(src) = &self.vendor_guid_and_data { |
5205 | assert!( |
5206 | self.service_type |
5207 | == crate::proto::device_path::messaging::RestServiceType::VENDOR |
5208 | ); |
5209 | let (guid_out, data_out) = out.split_at_mut(size_of::<Guid>()); |
5210 | let guid_out_ptr: *mut Guid = maybe_uninit_slice_as_mut_ptr(guid_out).cast(); |
5211 | unsafe { |
5212 | guid_out_ptr.write_unaligned(src.vendor_guid); |
5213 | } |
5214 | |
5215 | let data_out_ptr = maybe_uninit_slice_as_mut_ptr(data_out); |
5216 | unsafe { |
5217 | src.vendor_defined_data |
5218 | .as_ptr() |
5219 | .copy_to_nonoverlapping(data_out_ptr, data_out.len()); |
5220 | } |
5221 | } |
5222 | } |
5223 | } |
5224 | } |
5225 | |
5226 | /// Device path build nodes for [`DeviceType::MEDIA`]. |
5227 | pub mod media { |
5228 | use super::*; |
5229 | /// Hard drive media device path node. |
5230 | pub struct HardDrive { |
5231 | /// Index of the partition, starting from 1. |
5232 | pub partition_number: u32, |
5233 | /// Starting LBA (logical block address) of the partition. |
5234 | pub partition_start: u64, |
5235 | /// Size of the partition in blocks. |
5236 | pub partition_size: u64, |
5237 | /// Partition signature. |
5238 | pub partition_signature: crate::proto::device_path::media::PartitionSignature, |
5239 | /// Partition format. |
5240 | pub partition_format: crate::proto::device_path::media::PartitionFormat, |
5241 | } |
5242 | |
5243 | unsafe impl BuildNode for HardDrive { |
5244 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5245 | let size = 42usize; |
5246 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5247 | } |
5248 | |
5249 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5250 | let size = usize::from(self.size_in_bytes().unwrap()); |
5251 | assert_eq!(size, out.len()); |
5252 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5253 | unsafe { |
5254 | out_ptr |
5255 | .cast::<DevicePathHeader>() |
5256 | .write_unaligned(DevicePathHeader { |
5257 | device_type: DeviceType::MEDIA, |
5258 | sub_type: DeviceSubType::MEDIA_HARD_DRIVE, |
5259 | length: u16::try_from(size).unwrap(), |
5260 | }); |
5261 | out_ptr |
5262 | .add(4usize) |
5263 | .cast::<u32>() |
5264 | .write_unaligned(self.partition_number); |
5265 | out_ptr |
5266 | .add(8usize) |
5267 | .cast::<u64>() |
5268 | .write_unaligned(self.partition_start); |
5269 | out_ptr |
5270 | .add(16usize) |
5271 | .cast::<u64>() |
5272 | .write_unaligned(self.partition_size); |
5273 | out_ptr |
5274 | .add(24usize) |
5275 | .cast::<[u8; 16usize]>() |
5276 | .write_unaligned(self.build_partition_signature()); |
5277 | out_ptr |
5278 | .add(40usize) |
5279 | .cast::<crate::proto::device_path::media::PartitionFormat>() |
5280 | .write_unaligned(self.partition_format); |
5281 | out_ptr |
5282 | .add(41usize) |
5283 | .cast::<u8>() |
5284 | .write_unaligned(self.build_signature_type()); |
5285 | } |
5286 | } |
5287 | } |
5288 | |
5289 | /// CD-ROM media device path node. |
5290 | pub struct CdRom { |
5291 | /// Boot entry number from the boot catalog, or 0 for the |
5292 | /// default entry. |
5293 | pub boot_entry: u32, |
5294 | /// Starting RBA (Relative logical Block Address). |
5295 | pub partition_start: u64, |
5296 | /// Size of the partition in blocks. |
5297 | pub partition_size: u64, |
5298 | } |
5299 | |
5300 | unsafe impl BuildNode for CdRom { |
5301 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5302 | let size = 24usize; |
5303 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5304 | } |
5305 | |
5306 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5307 | let size = usize::from(self.size_in_bytes().unwrap()); |
5308 | assert_eq!(size, out.len()); |
5309 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5310 | unsafe { |
5311 | out_ptr |
5312 | .cast::<DevicePathHeader>() |
5313 | .write_unaligned(DevicePathHeader { |
5314 | device_type: DeviceType::MEDIA, |
5315 | sub_type: DeviceSubType::MEDIA_CD_ROM, |
5316 | length: u16::try_from(size).unwrap(), |
5317 | }); |
5318 | out_ptr |
5319 | .add(4usize) |
5320 | .cast::<u32>() |
5321 | .write_unaligned(self.boot_entry); |
5322 | out_ptr |
5323 | .add(8usize) |
5324 | .cast::<u64>() |
5325 | .write_unaligned(self.partition_start); |
5326 | out_ptr |
5327 | .add(16usize) |
5328 | .cast::<u64>() |
5329 | .write_unaligned(self.partition_size); |
5330 | } |
5331 | } |
5332 | } |
5333 | |
5334 | /// Vendor-defined media device path node. |
5335 | pub struct Vendor<'a> { |
5336 | /// Vendor-assigned GUID that defines the data that follows. |
5337 | pub vendor_guid: Guid, |
5338 | /// Vendor-defined data. |
5339 | pub vendor_defined_data: &'a [u8], |
5340 | } |
5341 | |
5342 | unsafe impl<'a> BuildNode for Vendor<'a> { |
5343 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5344 | let size = 20usize + size_of_val(self.vendor_defined_data); |
5345 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5346 | } |
5347 | |
5348 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5349 | let size = usize::from(self.size_in_bytes().unwrap()); |
5350 | assert_eq!(size, out.len()); |
5351 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5352 | unsafe { |
5353 | out_ptr |
5354 | .cast::<DevicePathHeader>() |
5355 | .write_unaligned(DevicePathHeader { |
5356 | device_type: DeviceType::MEDIA, |
5357 | sub_type: DeviceSubType::MEDIA_VENDOR, |
5358 | length: u16::try_from(size).unwrap(), |
5359 | }); |
5360 | out_ptr |
5361 | .add(4usize) |
5362 | .cast::<Guid>() |
5363 | .write_unaligned(self.vendor_guid); |
5364 | self.vendor_defined_data |
5365 | .as_ptr() |
5366 | .cast::<u8>() |
5367 | .copy_to_nonoverlapping( |
5368 | out_ptr.add(20usize), |
5369 | size_of_val(self.vendor_defined_data), |
5370 | ); |
5371 | } |
5372 | } |
5373 | } |
5374 | |
5375 | /// File path media device path node. |
5376 | pub struct FilePath<'a> { |
5377 | /// Null-terminated path. |
5378 | pub path_name: &'a CStr16, |
5379 | } |
5380 | |
5381 | unsafe impl<'a> BuildNode for FilePath<'a> { |
5382 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5383 | let size = 4usize + size_of_val(self.path_name); |
5384 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5385 | } |
5386 | |
5387 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5388 | let size = usize::from(self.size_in_bytes().unwrap()); |
5389 | assert_eq!(size, out.len()); |
5390 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5391 | unsafe { |
5392 | out_ptr |
5393 | .cast::<DevicePathHeader>() |
5394 | .write_unaligned(DevicePathHeader { |
5395 | device_type: DeviceType::MEDIA, |
5396 | sub_type: DeviceSubType::MEDIA_FILE_PATH, |
5397 | length: u16::try_from(size).unwrap(), |
5398 | }); |
5399 | self.path_name |
5400 | .as_ptr() |
5401 | .cast::<u8>() |
5402 | .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.path_name)); |
5403 | } |
5404 | } |
5405 | } |
5406 | |
5407 | /// Media protocol media device path node. |
5408 | pub struct Protocol { |
5409 | /// The ID of the protocol. |
5410 | pub protocol_guid: Guid, |
5411 | } |
5412 | |
5413 | unsafe impl BuildNode for Protocol { |
5414 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5415 | let size = 20usize; |
5416 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5417 | } |
5418 | |
5419 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5420 | let size = usize::from(self.size_in_bytes().unwrap()); |
5421 | assert_eq!(size, out.len()); |
5422 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5423 | unsafe { |
5424 | out_ptr |
5425 | .cast::<DevicePathHeader>() |
5426 | .write_unaligned(DevicePathHeader { |
5427 | device_type: DeviceType::MEDIA, |
5428 | sub_type: DeviceSubType::MEDIA_PROTOCOL, |
5429 | length: u16::try_from(size).unwrap(), |
5430 | }); |
5431 | out_ptr |
5432 | .add(4usize) |
5433 | .cast::<Guid>() |
5434 | .write_unaligned(self.protocol_guid); |
5435 | } |
5436 | } |
5437 | } |
5438 | |
5439 | /// PIWG firmware file media device path node. |
5440 | pub struct PiwgFirmwareFile<'a> { |
5441 | /// Contents are defined in the UEFI PI Specification. |
5442 | pub data: &'a [u8], |
5443 | } |
5444 | |
5445 | unsafe impl<'a> BuildNode for PiwgFirmwareFile<'a> { |
5446 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5447 | let size = 4usize + size_of_val(self.data); |
5448 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5449 | } |
5450 | |
5451 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5452 | let size = usize::from(self.size_in_bytes().unwrap()); |
5453 | assert_eq!(size, out.len()); |
5454 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5455 | unsafe { |
5456 | out_ptr |
5457 | .cast::<DevicePathHeader>() |
5458 | .write_unaligned(DevicePathHeader { |
5459 | device_type: DeviceType::MEDIA, |
5460 | sub_type: DeviceSubType::MEDIA_PIWG_FIRMWARE_FILE, |
5461 | length: u16::try_from(size).unwrap(), |
5462 | }); |
5463 | self.data |
5464 | .as_ptr() |
5465 | .cast::<u8>() |
5466 | .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.data)); |
5467 | } |
5468 | } |
5469 | } |
5470 | |
5471 | /// PIWG firmware volume media device path node. |
5472 | pub struct PiwgFirmwareVolume<'a> { |
5473 | /// Contents are defined in the UEFI PI Specification. |
5474 | pub data: &'a [u8], |
5475 | } |
5476 | |
5477 | unsafe impl<'a> BuildNode for PiwgFirmwareVolume<'a> { |
5478 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5479 | let size = 4usize + size_of_val(self.data); |
5480 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5481 | } |
5482 | |
5483 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5484 | let size = usize::from(self.size_in_bytes().unwrap()); |
5485 | assert_eq!(size, out.len()); |
5486 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5487 | unsafe { |
5488 | out_ptr |
5489 | .cast::<DevicePathHeader>() |
5490 | .write_unaligned(DevicePathHeader { |
5491 | device_type: DeviceType::MEDIA, |
5492 | sub_type: DeviceSubType::MEDIA_PIWG_FIRMWARE_VOLUME, |
5493 | length: u16::try_from(size).unwrap(), |
5494 | }); |
5495 | self.data |
5496 | .as_ptr() |
5497 | .cast::<u8>() |
5498 | .copy_to_nonoverlapping(out_ptr.add(4usize), size_of_val(self.data)); |
5499 | } |
5500 | } |
5501 | } |
5502 | |
5503 | /// Relative offset range media device path node. |
5504 | pub struct RelativeOffsetRange { |
5505 | /// Offset of the first byte, relative to the parent device node. |
5506 | pub starting_offset: u64, |
5507 | /// Offset of the last byte, relative to the parent device node. |
5508 | pub ending_offset: u64, |
5509 | } |
5510 | |
5511 | unsafe impl BuildNode for RelativeOffsetRange { |
5512 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5513 | let size = 24usize; |
5514 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5515 | } |
5516 | |
5517 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5518 | let size = usize::from(self.size_in_bytes().unwrap()); |
5519 | assert_eq!(size, out.len()); |
5520 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5521 | unsafe { |
5522 | out_ptr |
5523 | .cast::<DevicePathHeader>() |
5524 | .write_unaligned(DevicePathHeader { |
5525 | device_type: DeviceType::MEDIA, |
5526 | sub_type: DeviceSubType::MEDIA_RELATIVE_OFFSET_RANGE, |
5527 | length: u16::try_from(size).unwrap(), |
5528 | }); |
5529 | out_ptr.add(4usize).write_bytes(0, size_of::<u32>()); |
5530 | out_ptr |
5531 | .add(8usize) |
5532 | .cast::<u64>() |
5533 | .write_unaligned(self.starting_offset); |
5534 | out_ptr |
5535 | .add(16usize) |
5536 | .cast::<u64>() |
5537 | .write_unaligned(self.ending_offset); |
5538 | } |
5539 | } |
5540 | } |
5541 | |
5542 | /// RAM disk media device path node. |
5543 | pub struct RamDisk { |
5544 | /// Starting memory address. |
5545 | pub starting_address: u64, |
5546 | /// Ending memory address. |
5547 | pub ending_address: u64, |
5548 | /// Type of RAM disk. |
5549 | pub disk_type: crate::proto::device_path::media::RamDiskType, |
5550 | /// RAM disk instance number if supported, otherwise 0. |
5551 | pub disk_instance: u16, |
5552 | } |
5553 | |
5554 | unsafe impl BuildNode for RamDisk { |
5555 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5556 | let size = 38usize; |
5557 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5558 | } |
5559 | |
5560 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5561 | let size = usize::from(self.size_in_bytes().unwrap()); |
5562 | assert_eq!(size, out.len()); |
5563 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5564 | unsafe { |
5565 | out_ptr |
5566 | .cast::<DevicePathHeader>() |
5567 | .write_unaligned(DevicePathHeader { |
5568 | device_type: DeviceType::MEDIA, |
5569 | sub_type: DeviceSubType::MEDIA_RAM_DISK, |
5570 | length: u16::try_from(size).unwrap(), |
5571 | }); |
5572 | out_ptr |
5573 | .add(4usize) |
5574 | .cast::<u64>() |
5575 | .write_unaligned(self.starting_address); |
5576 | out_ptr |
5577 | .add(12usize) |
5578 | .cast::<u64>() |
5579 | .write_unaligned(self.ending_address); |
5580 | out_ptr |
5581 | .add(20usize) |
5582 | .cast::<crate::proto::device_path::media::RamDiskType>() |
5583 | .write_unaligned(self.disk_type); |
5584 | out_ptr |
5585 | .add(36usize) |
5586 | .cast::<u16>() |
5587 | .write_unaligned(self.disk_instance); |
5588 | } |
5589 | } |
5590 | } |
5591 | |
5592 | impl HardDrive { |
5593 | fn build_partition_signature(&self) -> [u8; 16] { |
5594 | use crate::proto::device_path::media::PartitionSignature::*; |
5595 | match self.partition_signature { |
5596 | None => [0u8; 16], |
5597 | Mbr(mbr) => { |
5598 | let mut sig = [0u8; 16]; |
5599 | sig[0..4].copy_from_slice(&mbr); |
5600 | sig |
5601 | } |
5602 | |
5603 | Guid(guid) => guid.to_bytes(), |
5604 | Unknown { signature, .. } => signature, |
5605 | } |
5606 | } |
5607 | |
5608 | fn build_signature_type(&self) -> u8 { |
5609 | use crate::proto::device_path::media::PartitionSignature::*; |
5610 | match self.partition_signature { |
5611 | None => 0, |
5612 | Mbr(_) => 1, |
5613 | Guid(_) => 2, |
5614 | Unknown { signature_type, .. } => signature_type, |
5615 | } |
5616 | } |
5617 | } |
5618 | } |
5619 | |
5620 | /// Device path build nodes for [`DeviceType::BIOS_BOOT_SPEC`]. |
5621 | pub mod bios_boot_spec { |
5622 | use super::*; |
5623 | /// BIOS Boot Specification device path node. |
5624 | pub struct BootSpecification<'a> { |
5625 | /// Device type as defined by the BIOS Boot Specification. |
5626 | pub device_type: u16, |
5627 | /// Status flags as defined by the BIOS Boot Specification. |
5628 | pub status_flag: u16, |
5629 | /// Description of the boot device encoded as a null-terminated |
5630 | /// ASCII string. |
5631 | pub description_string: &'a [u8], |
5632 | } |
5633 | |
5634 | unsafe impl<'a> BuildNode for BootSpecification<'a> { |
5635 | fn size_in_bytes(&self) -> Result<u16, BuildError> { |
5636 | let size = 8usize + size_of_val(self.description_string); |
5637 | u16::try_from(size).map_err(|_| BuildError::NodeTooBig) |
5638 | } |
5639 | |
5640 | fn write_data(&self, out: &mut [MaybeUninit<u8>]) { |
5641 | let size = usize::from(self.size_in_bytes().unwrap()); |
5642 | assert_eq!(size, out.len()); |
5643 | let out_ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(out); |
5644 | unsafe { |
5645 | out_ptr |
5646 | .cast::<DevicePathHeader>() |
5647 | .write_unaligned(DevicePathHeader { |
5648 | device_type: DeviceType::BIOS_BOOT_SPEC, |
5649 | sub_type: DeviceSubType::BIOS_BOOT_SPECIFICATION, |
5650 | length: u16::try_from(size).unwrap(), |
5651 | }); |
5652 | out_ptr |
5653 | .add(4usize) |
5654 | .cast::<u16>() |
5655 | .write_unaligned(self.device_type); |
5656 | out_ptr |
5657 | .add(6usize) |
5658 | .cast::<u16>() |
5659 | .write_unaligned(self.status_flag); |
5660 | self.description_string |
5661 | .as_ptr() |
5662 | .cast::<u8>() |
5663 | .copy_to_nonoverlapping( |
5664 | out_ptr.add(8usize), |
5665 | size_of_val(self.description_string), |
5666 | ); |
5667 | } |
5668 | } |
5669 | } |
5670 | } |
5671 | } |
5672 | |