uefi_std/
proto.rs

1use core::mem;
2use uefi::boot::LocateSearchType;
3
4use crate::prelude::*;
5use crate::system_table;
6
7pub trait Protocol<T: 'static> {
8    fn guid() -> Guid;
9
10    fn new(fs: &'static mut T) -> Self
11    where
12        Self: Sized;
13
14    fn locate_protocol() -> Result<Self>
15    where
16        Self: Sized,
17    {
18        let guid = Self::guid();
19        let mut interface = 0;
20        let status = (system_table().BootServices.LocateProtocol)(&guid, 0, &mut interface);
21
22        match status {
23            Status::SUCCESS => Ok(Self::new(unsafe { &mut *(interface as *mut T) })),
24            _ => Err(status),
25        }
26    }
27
28    fn handle_protocol(handle: Handle) -> Result<Self>
29    where
30        Self: Sized,
31    {
32        let guid = Self::guid();
33        let mut interface = 0;
34        let status = (system_table().BootServices.HandleProtocol)(handle, &guid, &mut interface);
35
36        match status {
37            Status::SUCCESS => Ok(Self::new(unsafe { &mut *(interface as *mut T) })),
38            _ => Err(status),
39        }
40    }
41
42    fn locate_handle() -> Result<Vec<Handle>> {
43        let guid = Self::guid();
44        let mut handles = Vec::with_capacity(256);
45        let mut len = handles.capacity() * mem::size_of::<Handle>();
46        let status = (system_table().BootServices.LocateHandle)(
47            LocateSearchType::ByProtocol,
48            &guid,
49            core::ptr::null(),
50            &mut len,
51            handles.as_mut_ptr(),
52        );
53
54        match status {
55            Status::SUCCESS => {
56                unsafe {
57                    handles.set_len(len / mem::size_of::<Handle>());
58                }
59                Ok(handles)
60            }
61            _ => Err(status),
62        }
63    }
64
65    fn one() -> Result<Self>
66    where
67        Self: Sized,
68    {
69        Self::locate_protocol()
70    }
71
72    fn all() -> Vec<Self>
73    where
74        Self: Sized,
75    {
76        let mut instances = Vec::new();
77        for handle in Self::locate_handle().unwrap_or_default() {
78            if let Ok(instance) = Self::handle_protocol(handle) {
79                instances.push(instance);
80            }
81        }
82        instances
83    }
84}