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}