xref: /aosp_15_r20/bootable/libbootloader/gbl/efi/src/ops.rs (revision 5225e6b173e52d2efc6bcf950c27374fd72adabc)
1*5225e6b1SAndroid Build Coastguard Worker // Copyright 2024, The Android Open Source Project
2*5225e6b1SAndroid Build Coastguard Worker //
3*5225e6b1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*5225e6b1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*5225e6b1SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*5225e6b1SAndroid Build Coastguard Worker //
7*5225e6b1SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*5225e6b1SAndroid Build Coastguard Worker //
9*5225e6b1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*5225e6b1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*5225e6b1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5225e6b1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*5225e6b1SAndroid Build Coastguard Worker // limitations under the License.
14*5225e6b1SAndroid Build Coastguard Worker 
15*5225e6b1SAndroid Build Coastguard Worker //! Implements [Gbl::Ops] for the EFI environment.
16*5225e6b1SAndroid Build Coastguard Worker 
17*5225e6b1SAndroid Build Coastguard Worker use crate::{
18*5225e6b1SAndroid Build Coastguard Worker     efi,
19*5225e6b1SAndroid Build Coastguard Worker     efi_blocks::EfiGblDisk,
20*5225e6b1SAndroid Build Coastguard Worker     utils::{get_efi_fdt, wait_key_stroke},
21*5225e6b1SAndroid Build Coastguard Worker };
22*5225e6b1SAndroid Build Coastguard Worker use alloc::{
23*5225e6b1SAndroid Build Coastguard Worker     alloc::{alloc, handle_alloc_error, Layout},
24*5225e6b1SAndroid Build Coastguard Worker     vec::Vec,
25*5225e6b1SAndroid Build Coastguard Worker };
26*5225e6b1SAndroid Build Coastguard Worker use arrayvec::ArrayVec;
27*5225e6b1SAndroid Build Coastguard Worker use core::{
28*5225e6b1SAndroid Build Coastguard Worker     cmp::min, ffi::CStr, fmt::Write, mem::MaybeUninit, num::NonZeroUsize, ops::DerefMut, ptr::null,
29*5225e6b1SAndroid Build Coastguard Worker     slice::from_raw_parts_mut,
30*5225e6b1SAndroid Build Coastguard Worker };
31*5225e6b1SAndroid Build Coastguard Worker use efi::{
32*5225e6b1SAndroid Build Coastguard Worker     efi_print, efi_println,
33*5225e6b1SAndroid Build Coastguard Worker     protocol::{
34*5225e6b1SAndroid Build Coastguard Worker         dt_fixup::DtFixupProtocol, gbl_efi_ab_slot::GblSlotProtocol, gbl_efi_avb::GblAvbProtocol,
35*5225e6b1SAndroid Build Coastguard Worker         gbl_efi_fastboot::GblFastbootProtocol, gbl_efi_image_loading::GblImageLoadingProtocol,
36*5225e6b1SAndroid Build Coastguard Worker         gbl_efi_os_configuration::GblOsConfigurationProtocol,
37*5225e6b1SAndroid Build Coastguard Worker     },
38*5225e6b1SAndroid Build Coastguard Worker     EfiEntry,
39*5225e6b1SAndroid Build Coastguard Worker };
40*5225e6b1SAndroid Build Coastguard Worker use efi_types::{
41*5225e6b1SAndroid Build Coastguard Worker     GblEfiAvbKeyValidationStatus, GblEfiAvbVerificationResult, GblEfiBootReason,
42*5225e6b1SAndroid Build Coastguard Worker     GblEfiDeviceTreeMetadata, GblEfiImageInfo, GblEfiVerifiedDeviceTree,
43*5225e6b1SAndroid Build Coastguard Worker     GBL_EFI_BOOT_REASON_BOOTLOADER, GBL_EFI_BOOT_REASON_COLD, GBL_EFI_BOOT_REASON_FASTBOOTD,
44*5225e6b1SAndroid Build Coastguard Worker     GBL_EFI_BOOT_REASON_RECOVERY, PARTITION_NAME_LEN_U16,
45*5225e6b1SAndroid Build Coastguard Worker };
46*5225e6b1SAndroid Build Coastguard Worker use fdt::Fdt;
47*5225e6b1SAndroid Build Coastguard Worker use gbl_storage::{BlockIo, Disk, Gpt, SliceMaybeUninit};
48*5225e6b1SAndroid Build Coastguard Worker use liberror::{Error, Result};
49*5225e6b1SAndroid Build Coastguard Worker use libgbl::{
50*5225e6b1SAndroid Build Coastguard Worker     constants::{ImageName, BOOTCMD_SIZE},
51*5225e6b1SAndroid Build Coastguard Worker     device_tree::{
52*5225e6b1SAndroid Build Coastguard Worker         DeviceTreeComponent, DeviceTreeComponentSource, DeviceTreeComponentsRegistry,
53*5225e6b1SAndroid Build Coastguard Worker         MAXIMUM_DEVICE_TREE_COMPONENTS,
54*5225e6b1SAndroid Build Coastguard Worker     },
55*5225e6b1SAndroid Build Coastguard Worker     gbl_avb::state::{BootStateColor, KeyValidationStatus},
56*5225e6b1SAndroid Build Coastguard Worker     ops::{
57*5225e6b1SAndroid Build Coastguard Worker         AvbIoError, AvbIoResult, CertPermanentAttributes, ImageBuffer, RebootReason, Slot,
58*5225e6b1SAndroid Build Coastguard Worker         SlotsMetadata, SHA256_DIGEST_SIZE,
59*5225e6b1SAndroid Build Coastguard Worker     },
60*5225e6b1SAndroid Build Coastguard Worker     partition::GblDisk,
61*5225e6b1SAndroid Build Coastguard Worker     slots::{BootToken, Cursor},
62*5225e6b1SAndroid Build Coastguard Worker     GblOps, Os, Result as GblResult,
63*5225e6b1SAndroid Build Coastguard Worker };
64*5225e6b1SAndroid Build Coastguard Worker use safemath::SafeNum;
65*5225e6b1SAndroid Build Coastguard Worker use zbi::ZbiContainer;
66*5225e6b1SAndroid Build Coastguard Worker use zerocopy::AsBytes;
67*5225e6b1SAndroid Build Coastguard Worker 
to_avb_validation_status_or_panic(status: GblEfiAvbKeyValidationStatus) -> KeyValidationStatus68*5225e6b1SAndroid Build Coastguard Worker fn to_avb_validation_status_or_panic(status: GblEfiAvbKeyValidationStatus) -> KeyValidationStatus {
69*5225e6b1SAndroid Build Coastguard Worker     match status {
70*5225e6b1SAndroid Build Coastguard Worker         efi_types::GBL_EFI_AVB_KEY_VALIDATION_STATUS_VALID => KeyValidationStatus::Valid,
71*5225e6b1SAndroid Build Coastguard Worker         efi_types::GBL_EFI_AVB_KEY_VALIDATION_STATUS_VALID_CUSTOM_KEY => {
72*5225e6b1SAndroid Build Coastguard Worker             KeyValidationStatus::ValidCustomKey
73*5225e6b1SAndroid Build Coastguard Worker         }
74*5225e6b1SAndroid Build Coastguard Worker         efi_types::GBL_EFI_AVB_KEY_VALIDATION_STATUS_INVALID => KeyValidationStatus::Invalid,
75*5225e6b1SAndroid Build Coastguard Worker         _ => panic!("Unrecognized avb key validation status: {}", status),
76*5225e6b1SAndroid Build Coastguard Worker     }
77*5225e6b1SAndroid Build Coastguard Worker }
78*5225e6b1SAndroid Build Coastguard Worker 
avb_color_to_efi_color(color: BootStateColor) -> u3279*5225e6b1SAndroid Build Coastguard Worker fn avb_color_to_efi_color(color: BootStateColor) -> u32 {
80*5225e6b1SAndroid Build Coastguard Worker     match color {
81*5225e6b1SAndroid Build Coastguard Worker         BootStateColor::Green => efi_types::GBL_EFI_AVB_BOOT_STATE_COLOR_GREEN,
82*5225e6b1SAndroid Build Coastguard Worker         BootStateColor::Yellow => efi_types::GBL_EFI_AVB_BOOT_STATE_COLOR_YELLOW,
83*5225e6b1SAndroid Build Coastguard Worker         BootStateColor::Orange => efi_types::GBL_EFI_AVB_BOOT_STATE_COLOR_ORANGE,
84*5225e6b1SAndroid Build Coastguard Worker         BootStateColor::RedEio => efi_types::GBL_EFI_AVB_BOOT_STATE_COLOR_RED_EIO,
85*5225e6b1SAndroid Build Coastguard Worker         BootStateColor::Red => efi_types::GBL_EFI_AVB_BOOT_STATE_COLOR_RED,
86*5225e6b1SAndroid Build Coastguard Worker     }
87*5225e6b1SAndroid Build Coastguard Worker }
88*5225e6b1SAndroid Build Coastguard Worker 
dt_component_to_efi_dt(component: &DeviceTreeComponent) -> GblEfiVerifiedDeviceTree89*5225e6b1SAndroid Build Coastguard Worker fn dt_component_to_efi_dt(component: &DeviceTreeComponent) -> GblEfiVerifiedDeviceTree {
90*5225e6b1SAndroid Build Coastguard Worker     let metadata = match component.source {
91*5225e6b1SAndroid Build Coastguard Worker         DeviceTreeComponentSource::Dtb(m) | DeviceTreeComponentSource::Dtbo(m) => m,
92*5225e6b1SAndroid Build Coastguard Worker         _ => Default::default(),
93*5225e6b1SAndroid Build Coastguard Worker     };
94*5225e6b1SAndroid Build Coastguard Worker 
95*5225e6b1SAndroid Build Coastguard Worker     GblEfiVerifiedDeviceTree {
96*5225e6b1SAndroid Build Coastguard Worker         metadata: GblEfiDeviceTreeMetadata {
97*5225e6b1SAndroid Build Coastguard Worker             source: match component.source {
98*5225e6b1SAndroid Build Coastguard Worker                 DeviceTreeComponentSource::Boot => efi_types::GBL_EFI_DEVICE_TREE_SOURCE_BOOT,
99*5225e6b1SAndroid Build Coastguard Worker                 DeviceTreeComponentSource::VendorBoot => {
100*5225e6b1SAndroid Build Coastguard Worker                     efi_types::GBL_EFI_DEVICE_TREE_SOURCE_VENDOR_BOOT
101*5225e6b1SAndroid Build Coastguard Worker                 }
102*5225e6b1SAndroid Build Coastguard Worker                 DeviceTreeComponentSource::Dtb(_) => efi_types::GBL_EFI_DEVICE_TREE_SOURCE_DTB,
103*5225e6b1SAndroid Build Coastguard Worker                 DeviceTreeComponentSource::Dtbo(_) => efi_types::GBL_EFI_DEVICE_TREE_SOURCE_DTBO,
104*5225e6b1SAndroid Build Coastguard Worker             },
105*5225e6b1SAndroid Build Coastguard Worker             id: metadata.id,
106*5225e6b1SAndroid Build Coastguard Worker             rev: metadata.rev,
107*5225e6b1SAndroid Build Coastguard Worker             custom: metadata.custom,
108*5225e6b1SAndroid Build Coastguard Worker             reserved: Default::default(),
109*5225e6b1SAndroid Build Coastguard Worker         },
110*5225e6b1SAndroid Build Coastguard Worker         device_tree: component.dt.as_ptr() as _,
111*5225e6b1SAndroid Build Coastguard Worker         selected: component.selected,
112*5225e6b1SAndroid Build Coastguard Worker     }
113*5225e6b1SAndroid Build Coastguard Worker }
114*5225e6b1SAndroid Build Coastguard Worker 
efi_error_to_avb_error(error: Error) -> AvbIoError115*5225e6b1SAndroid Build Coastguard Worker fn efi_error_to_avb_error(error: Error) -> AvbIoError {
116*5225e6b1SAndroid Build Coastguard Worker     match error {
117*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_OUT_OF_RESOURCES
118*5225e6b1SAndroid Build Coastguard Worker         Error::OutOfResources => AvbIoError::Oom,
119*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_DEVICE_ERROR
120*5225e6b1SAndroid Build Coastguard Worker         Error::DeviceError => AvbIoError::Io,
121*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_NOT_FOUND
122*5225e6b1SAndroid Build Coastguard Worker         Error::NotFound => AvbIoError::NoSuchValue,
123*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_END_OF_FILE
124*5225e6b1SAndroid Build Coastguard Worker         Error::EndOfFile => AvbIoError::RangeOutsidePartition,
125*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_INVALID_PARAMETER
126*5225e6b1SAndroid Build Coastguard Worker         Error::InvalidInput => AvbIoError::InvalidValueSize,
127*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_BUFFER_TOO_SMALL
128*5225e6b1SAndroid Build Coastguard Worker         Error::BufferTooSmall(required) => {
129*5225e6b1SAndroid Build Coastguard Worker             AvbIoError::InsufficientSpace(required.unwrap_or_default())
130*5225e6b1SAndroid Build Coastguard Worker         }
131*5225e6b1SAndroid Build Coastguard Worker         // EFI_STATUS_UNSUPPORTED
132*5225e6b1SAndroid Build Coastguard Worker         Error::Unsupported => AvbIoError::NotImplemented,
133*5225e6b1SAndroid Build Coastguard Worker         _ => AvbIoError::NotImplemented,
134*5225e6b1SAndroid Build Coastguard Worker     }
135*5225e6b1SAndroid Build Coastguard Worker }
136*5225e6b1SAndroid Build Coastguard Worker 
137*5225e6b1SAndroid Build Coastguard Worker pub struct Ops<'a, 'b> {
138*5225e6b1SAndroid Build Coastguard Worker     pub efi_entry: &'a EfiEntry,
139*5225e6b1SAndroid Build Coastguard Worker     pub disks: &'b [EfiGblDisk<'a>],
140*5225e6b1SAndroid Build Coastguard Worker     pub zbi_bootloader_files_buffer: Vec<u8>,
141*5225e6b1SAndroid Build Coastguard Worker     pub os: Option<Os>,
142*5225e6b1SAndroid Build Coastguard Worker }
143*5225e6b1SAndroid Build Coastguard Worker 
144*5225e6b1SAndroid Build Coastguard Worker impl<'a, 'b> Ops<'a, 'b> {
145*5225e6b1SAndroid Build Coastguard Worker     /// Creates a new instance of [Ops]
new(efi_entry: &'a EfiEntry, disks: &'b [EfiGblDisk<'a>], os: Option<Os>) -> Self146*5225e6b1SAndroid Build Coastguard Worker     pub fn new(efi_entry: &'a EfiEntry, disks: &'b [EfiGblDisk<'a>], os: Option<Os>) -> Self {
147*5225e6b1SAndroid Build Coastguard Worker         Self { efi_entry, disks, zbi_bootloader_files_buffer: Default::default(), os }
148*5225e6b1SAndroid Build Coastguard Worker     }
149*5225e6b1SAndroid Build Coastguard Worker 
150*5225e6b1SAndroid Build Coastguard Worker     /// Gets the property of an FDT node from EFI FDT.
151*5225e6b1SAndroid Build Coastguard Worker     ///
152*5225e6b1SAndroid Build Coastguard Worker     /// Returns `None` if fail to get the node
get_efi_fdt_prop(&self, path: &str, prop: &CStr) -> Option<&'a [u8]>153*5225e6b1SAndroid Build Coastguard Worker     fn get_efi_fdt_prop(&self, path: &str, prop: &CStr) -> Option<&'a [u8]> {
154*5225e6b1SAndroid Build Coastguard Worker         let (_, fdt_bytes) = get_efi_fdt(&self.efi_entry)?;
155*5225e6b1SAndroid Build Coastguard Worker         let fdt = Fdt::new(fdt_bytes).ok()?;
156*5225e6b1SAndroid Build Coastguard Worker         fdt.get_property(path, prop).ok()
157*5225e6b1SAndroid Build Coastguard Worker     }
158*5225e6b1SAndroid Build Coastguard Worker 
159*5225e6b1SAndroid Build Coastguard Worker     /// Get buffer for partition loading and verification.
160*5225e6b1SAndroid Build Coastguard Worker     /// Uses GBL EFI ImageLoading protocol.
161*5225e6b1SAndroid Build Coastguard Worker     ///
162*5225e6b1SAndroid Build Coastguard Worker     /// # Arguments
163*5225e6b1SAndroid Build Coastguard Worker     /// * `image_name` - image name to differentiate the buffer properties. Processing is limited
164*5225e6b1SAndroid Build Coastguard Worker     /// to first [PARTITION_NAME_LEN_U16] symbols, and the remaining will be ignored.
165*5225e6b1SAndroid Build Coastguard Worker     /// * `size` - requested buffer size
166*5225e6b1SAndroid Build Coastguard Worker     ///
167*5225e6b1SAndroid Build Coastguard Worker     /// # Return
168*5225e6b1SAndroid Build Coastguard Worker     /// * Ok(ImageBuffer) - Return buffer for partition loading and verification.
169*5225e6b1SAndroid Build Coastguard Worker     /// * Err(_) - on error
get_buffer_image_loading( &mut self, image_name: &str, size: NonZeroUsize, ) -> GblResult<ImageBuffer<'static>>170*5225e6b1SAndroid Build Coastguard Worker     fn get_buffer_image_loading(
171*5225e6b1SAndroid Build Coastguard Worker         &mut self,
172*5225e6b1SAndroid Build Coastguard Worker         image_name: &str,
173*5225e6b1SAndroid Build Coastguard Worker         size: NonZeroUsize,
174*5225e6b1SAndroid Build Coastguard Worker     ) -> GblResult<ImageBuffer<'static>> {
175*5225e6b1SAndroid Build Coastguard Worker         let mut image_type = [0u16; PARTITION_NAME_LEN_U16];
176*5225e6b1SAndroid Build Coastguard Worker         image_type.iter_mut().zip(image_name.encode_utf16()).for_each(|(dst, src)| {
177*5225e6b1SAndroid Build Coastguard Worker             *dst = src;
178*5225e6b1SAndroid Build Coastguard Worker         });
179*5225e6b1SAndroid Build Coastguard Worker         let image_info = GblEfiImageInfo { ImageType: image_type, SizeBytes: size.get() };
180*5225e6b1SAndroid Build Coastguard Worker         let efi_image_buffer = self
181*5225e6b1SAndroid Build Coastguard Worker             .efi_entry
182*5225e6b1SAndroid Build Coastguard Worker             .system_table()
183*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
184*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblImageLoadingProtocol>()?
185*5225e6b1SAndroid Build Coastguard Worker             .get_buffer(&image_info)?;
186*5225e6b1SAndroid Build Coastguard Worker 
187*5225e6b1SAndroid Build Coastguard Worker         // EfiImageBuffer -> ImageBuffer
188*5225e6b1SAndroid Build Coastguard Worker         // Make sure not to drop efi_image_buffer since we transferred ownership to ImageBuffer
189*5225e6b1SAndroid Build Coastguard Worker         let buffer = efi_image_buffer.take();
190*5225e6b1SAndroid Build Coastguard Worker         Ok(ImageBuffer::new(buffer))
191*5225e6b1SAndroid Build Coastguard Worker     }
192*5225e6b1SAndroid Build Coastguard Worker 
193*5225e6b1SAndroid Build Coastguard Worker     /// Get buffer for partition loading and verification.
194*5225e6b1SAndroid Build Coastguard Worker     /// Uses provided allocator.
195*5225e6b1SAndroid Build Coastguard Worker     ///
196*5225e6b1SAndroid Build Coastguard Worker     /// # Arguments
197*5225e6b1SAndroid Build Coastguard Worker     /// * `image_name` - image name to differentiate the buffer properties
198*5225e6b1SAndroid Build Coastguard Worker     /// * `size` - requested buffer size
199*5225e6b1SAndroid Build Coastguard Worker     ///
200*5225e6b1SAndroid Build Coastguard Worker     /// # Return
201*5225e6b1SAndroid Build Coastguard Worker     /// * Ok(ImageBuffer) - Return buffer for partition loading and verification.
202*5225e6b1SAndroid Build Coastguard Worker     /// * Err(_) - on error
203*5225e6b1SAndroid Build Coastguard Worker     // SAFETY:
204*5225e6b1SAndroid Build Coastguard Worker     // Allocated buffer is leaked intentionally. ImageBuffer is assumed to reference static memory.
205*5225e6b1SAndroid Build Coastguard Worker     // ImageBuffer is not expected to be released, and is allocated to hold data necessary for next
206*5225e6b1SAndroid Build Coastguard Worker     // boot stage (kernel boot). All allocated buffers are expected to be used by kernel.
allocate_image_buffer(image_name: &str, size: NonZeroUsize) -> Result<ImageBuffer<'static>>207*5225e6b1SAndroid Build Coastguard Worker     fn allocate_image_buffer(image_name: &str, size: NonZeroUsize) -> Result<ImageBuffer<'static>> {
208*5225e6b1SAndroid Build Coastguard Worker         let size = match image_name {
209*5225e6b1SAndroid Build Coastguard Worker             "ramdisk" => (SafeNum::from(size.get()) + BOOTCMD_SIZE).try_into()?,
210*5225e6b1SAndroid Build Coastguard Worker             _ => size.get(),
211*5225e6b1SAndroid Build Coastguard Worker         };
212*5225e6b1SAndroid Build Coastguard Worker         // Check for `from_raw_parts_mut()` safety requirements.
213*5225e6b1SAndroid Build Coastguard Worker         assert!(size < isize::MAX.try_into().unwrap());
214*5225e6b1SAndroid Build Coastguard Worker         let align = ImageName::try_from(image_name).map(|i| i.alignment()).unwrap_or(1);
215*5225e6b1SAndroid Build Coastguard Worker 
216*5225e6b1SAndroid Build Coastguard Worker         let layout = Layout::from_size_align(size, align).or(Err(Error::InvalidAlignment))?;
217*5225e6b1SAndroid Build Coastguard Worker         // SAFETY:
218*5225e6b1SAndroid Build Coastguard Worker         // `layout.size()` is checked to be not zero.
219*5225e6b1SAndroid Build Coastguard Worker         let ptr = unsafe { alloc(layout) } as *mut MaybeUninit<u8>;
220*5225e6b1SAndroid Build Coastguard Worker         if ptr.is_null() {
221*5225e6b1SAndroid Build Coastguard Worker             handle_alloc_error(layout);
222*5225e6b1SAndroid Build Coastguard Worker         }
223*5225e6b1SAndroid Build Coastguard Worker 
224*5225e6b1SAndroid Build Coastguard Worker         // SAFETY:
225*5225e6b1SAndroid Build Coastguard Worker         // `ptr` is checked to be not Null.
226*5225e6b1SAndroid Build Coastguard Worker         // `ptr` is a valid pointer to start of a single memory region of `size`-bytes because it
227*5225e6b1SAndroid Build Coastguard Worker         // was just returned by alloc. Buffer alignment requirement for u8 is 1-byte which is
228*5225e6b1SAndroid Build Coastguard Worker         // always the case.
229*5225e6b1SAndroid Build Coastguard Worker         // `alloc()` makes sure there is no other allocation of the same memory region until
230*5225e6b1SAndroid Build Coastguard Worker         // current one is released.
231*5225e6b1SAndroid Build Coastguard Worker         // `size` is a valid size of the memory region since `alloc()` succeeded.
232*5225e6b1SAndroid Build Coastguard Worker         //
233*5225e6b1SAndroid Build Coastguard Worker         // Total size of buffer is not greater than `isize::MAX` since it is checked at the
234*5225e6b1SAndroid Build Coastguard Worker         // beginning of the function.
235*5225e6b1SAndroid Build Coastguard Worker         //
236*5225e6b1SAndroid Build Coastguard Worker         // `ptr + size` doesn't wrap since it is returned from alloc and it didn't fail.
237*5225e6b1SAndroid Build Coastguard Worker         let buf = unsafe { from_raw_parts_mut(ptr, size) };
238*5225e6b1SAndroid Build Coastguard Worker 
239*5225e6b1SAndroid Build Coastguard Worker         Ok(ImageBuffer::new(buf))
240*5225e6b1SAndroid Build Coastguard Worker     }
241*5225e6b1SAndroid Build Coastguard Worker }
242*5225e6b1SAndroid Build Coastguard Worker 
243*5225e6b1SAndroid Build Coastguard Worker impl Write for Ops<'_, '_> {
write_str(&mut self, s: &str) -> core::fmt::Result244*5225e6b1SAndroid Build Coastguard Worker     fn write_str(&mut self, s: &str) -> core::fmt::Result {
245*5225e6b1SAndroid Build Coastguard Worker         efi_print!(self.efi_entry, "{}", s);
246*5225e6b1SAndroid Build Coastguard Worker         Ok(())
247*5225e6b1SAndroid Build Coastguard Worker     }
248*5225e6b1SAndroid Build Coastguard Worker }
249*5225e6b1SAndroid Build Coastguard Worker 
250*5225e6b1SAndroid Build Coastguard Worker impl<'a, 'b, 'd> GblOps<'b, 'd> for Ops<'a, 'b> {
console_out(&mut self) -> Option<&mut dyn Write>251*5225e6b1SAndroid Build Coastguard Worker     fn console_out(&mut self) -> Option<&mut dyn Write> {
252*5225e6b1SAndroid Build Coastguard Worker         Some(self)
253*5225e6b1SAndroid Build Coastguard Worker     }
254*5225e6b1SAndroid Build Coastguard Worker 
255*5225e6b1SAndroid Build Coastguard Worker     /// UEFI console uses \r\n newline.
console_newline(&self) -> &'static str256*5225e6b1SAndroid Build Coastguard Worker     fn console_newline(&self) -> &'static str {
257*5225e6b1SAndroid Build Coastguard Worker         "\r\n"
258*5225e6b1SAndroid Build Coastguard Worker     }
259*5225e6b1SAndroid Build Coastguard Worker 
should_stop_in_fastboot(&mut self) -> Result<bool>260*5225e6b1SAndroid Build Coastguard Worker     fn should_stop_in_fastboot(&mut self) -> Result<bool> {
261*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/349829690): also query GblSlotProtocol.get_boot_reason() for board-specific
262*5225e6b1SAndroid Build Coastguard Worker         // fastboot triggers.
263*5225e6b1SAndroid Build Coastguard Worker 
264*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/366520234): Switch to use GblSlotProtocol.should_stop_in_fastboot once available.
265*5225e6b1SAndroid Build Coastguard Worker         match self.get_efi_fdt_prop("gbl", c"stop-in-fastboot") {
266*5225e6b1SAndroid Build Coastguard Worker             Some(v) => return Ok(*v.get(0).unwrap_or(&0) == 1),
267*5225e6b1SAndroid Build Coastguard Worker             _ => {}
268*5225e6b1SAndroid Build Coastguard Worker         }
269*5225e6b1SAndroid Build Coastguard Worker 
270*5225e6b1SAndroid Build Coastguard Worker         efi_println!(self.efi_entry, "Press Backspace to enter fastboot");
271*5225e6b1SAndroid Build Coastguard Worker         let found = wait_key_stroke(
272*5225e6b1SAndroid Build Coastguard Worker             self.efi_entry,
273*5225e6b1SAndroid Build Coastguard Worker             |key| key.unicode_char == 0x08 || (key.unicode_char == 0x0 && key.scan_code == 0x08),
274*5225e6b1SAndroid Build Coastguard Worker             2000,
275*5225e6b1SAndroid Build Coastguard Worker         );
276*5225e6b1SAndroid Build Coastguard Worker         if matches!(found, Ok(true)) {
277*5225e6b1SAndroid Build Coastguard Worker             efi_println!(self.efi_entry, "Backspace pressed, entering fastboot");
278*5225e6b1SAndroid Build Coastguard Worker         }
279*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/358377120): pass the UEFI error when liberror::Error support lands.
280*5225e6b1SAndroid Build Coastguard Worker         found.or(Err(Error::Other(Some("wait for key stroke error"))))
281*5225e6b1SAndroid Build Coastguard Worker     }
282*5225e6b1SAndroid Build Coastguard Worker 
283*5225e6b1SAndroid Build Coastguard Worker     /// Reboots the system into the last set boot mode.
reboot(&mut self)284*5225e6b1SAndroid Build Coastguard Worker     fn reboot(&mut self) {
285*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry.system_table().runtime_services().cold_reset();
286*5225e6b1SAndroid Build Coastguard Worker     }
287*5225e6b1SAndroid Build Coastguard Worker 
disks( &self, ) -> &'b [GblDisk< Disk<impl BlockIo + 'b, impl DerefMut<Target = [u8]> + 'b>, Gpt<impl DerefMut<Target = [u8]> + 'b>, >]288*5225e6b1SAndroid Build Coastguard Worker     fn disks(
289*5225e6b1SAndroid Build Coastguard Worker         &self,
290*5225e6b1SAndroid Build Coastguard Worker     ) -> &'b [GblDisk<
291*5225e6b1SAndroid Build Coastguard Worker         Disk<impl BlockIo + 'b, impl DerefMut<Target = [u8]> + 'b>,
292*5225e6b1SAndroid Build Coastguard Worker         Gpt<impl DerefMut<Target = [u8]> + 'b>,
293*5225e6b1SAndroid Build Coastguard Worker     >] {
294*5225e6b1SAndroid Build Coastguard Worker         self.disks
295*5225e6b1SAndroid Build Coastguard Worker     }
296*5225e6b1SAndroid Build Coastguard Worker 
expected_os(&mut self) -> Result<Option<Os>>297*5225e6b1SAndroid Build Coastguard Worker     fn expected_os(&mut self) -> Result<Option<Os>> {
298*5225e6b1SAndroid Build Coastguard Worker         Ok(self.os)
299*5225e6b1SAndroid Build Coastguard Worker     }
300*5225e6b1SAndroid Build Coastguard Worker 
zircon_add_device_zbi_items( &mut self, container: &mut ZbiContainer<&mut [u8]>, ) -> Result<()>301*5225e6b1SAndroid Build Coastguard Worker     fn zircon_add_device_zbi_items(
302*5225e6b1SAndroid Build Coastguard Worker         &mut self,
303*5225e6b1SAndroid Build Coastguard Worker         container: &mut ZbiContainer<&mut [u8]>,
304*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<()> {
305*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/353272981): Switch to use OS configuration protocol once it is implemented on
306*5225e6b1SAndroid Build Coastguard Worker         // existing platforms such as VIM3.
307*5225e6b1SAndroid Build Coastguard Worker         Ok(match self.get_efi_fdt_prop("zircon", c"zbi-blob") {
308*5225e6b1SAndroid Build Coastguard Worker             Some(blob) => container.extend_unaligned(blob).map_err(|_| "Failed to append ZBI")?,
309*5225e6b1SAndroid Build Coastguard Worker             _ => efi_println!(self.efi_entry, "No device ZBI items.\r\n"),
310*5225e6b1SAndroid Build Coastguard Worker         })
311*5225e6b1SAndroid Build Coastguard Worker     }
312*5225e6b1SAndroid Build Coastguard Worker 
get_zbi_bootloader_files_buffer(&mut self) -> Option<&mut [u8]>313*5225e6b1SAndroid Build Coastguard Worker     fn get_zbi_bootloader_files_buffer(&mut self) -> Option<&mut [u8]> {
314*5225e6b1SAndroid Build Coastguard Worker         // Switches to use get_image_buffer once available.
315*5225e6b1SAndroid Build Coastguard Worker         const DEFAULT_SIZE: usize = 4096;
316*5225e6b1SAndroid Build Coastguard Worker         if self.zbi_bootloader_files_buffer.is_empty() {
317*5225e6b1SAndroid Build Coastguard Worker             self.zbi_bootloader_files_buffer.resize(DEFAULT_SIZE, 0);
318*5225e6b1SAndroid Build Coastguard Worker         }
319*5225e6b1SAndroid Build Coastguard Worker         Some(self.zbi_bootloader_files_buffer.as_mut_slice())
320*5225e6b1SAndroid Build Coastguard Worker     }
321*5225e6b1SAndroid Build Coastguard Worker 
load_slot_interface<'c>( &'c mut self, _: &'c mut dyn FnMut(&mut [u8]) -> Result<()>, _: BootToken, ) -> GblResult<Cursor<'c>>322*5225e6b1SAndroid Build Coastguard Worker     fn load_slot_interface<'c>(
323*5225e6b1SAndroid Build Coastguard Worker         &'c mut self,
324*5225e6b1SAndroid Build Coastguard Worker         _: &'c mut dyn FnMut(&mut [u8]) -> Result<()>,
325*5225e6b1SAndroid Build Coastguard Worker         _: BootToken,
326*5225e6b1SAndroid Build Coastguard Worker     ) -> GblResult<Cursor<'c>> {
327*5225e6b1SAndroid Build Coastguard Worker         unimplemented!();
328*5225e6b1SAndroid Build Coastguard Worker     }
329*5225e6b1SAndroid Build Coastguard Worker 
avb_read_is_device_unlocked(&mut self) -> AvbIoResult<bool>330*5225e6b1SAndroid Build Coastguard Worker     fn avb_read_is_device_unlocked(&mut self) -> AvbIoResult<bool> {
331*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
332*5225e6b1SAndroid Build Coastguard Worker         {
333*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => protocol.read_is_device_unlocked().map_err(efi_error_to_avb_error),
334*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
335*5225e6b1SAndroid Build Coastguard Worker         }
336*5225e6b1SAndroid Build Coastguard Worker     }
337*5225e6b1SAndroid Build Coastguard Worker 
avb_read_rollback_index(&mut self, rollback_index_location: usize) -> AvbIoResult<u64>338*5225e6b1SAndroid Build Coastguard Worker     fn avb_read_rollback_index(&mut self, rollback_index_location: usize) -> AvbIoResult<u64> {
339*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
340*5225e6b1SAndroid Build Coastguard Worker         {
341*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => protocol
342*5225e6b1SAndroid Build Coastguard Worker                 .read_rollback_index(rollback_index_location)
343*5225e6b1SAndroid Build Coastguard Worker                 .map_err(efi_error_to_avb_error),
344*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
345*5225e6b1SAndroid Build Coastguard Worker         }
346*5225e6b1SAndroid Build Coastguard Worker     }
347*5225e6b1SAndroid Build Coastguard Worker 
avb_write_rollback_index( &mut self, rollback_index_location: usize, index: u64, ) -> AvbIoResult<()>348*5225e6b1SAndroid Build Coastguard Worker     fn avb_write_rollback_index(
349*5225e6b1SAndroid Build Coastguard Worker         &mut self,
350*5225e6b1SAndroid Build Coastguard Worker         rollback_index_location: usize,
351*5225e6b1SAndroid Build Coastguard Worker         index: u64,
352*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<()> {
353*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
354*5225e6b1SAndroid Build Coastguard Worker         {
355*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => protocol
356*5225e6b1SAndroid Build Coastguard Worker                 .write_rollback_index(rollback_index_location, index)
357*5225e6b1SAndroid Build Coastguard Worker                 .map_err(efi_error_to_avb_error),
358*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
359*5225e6b1SAndroid Build Coastguard Worker         }
360*5225e6b1SAndroid Build Coastguard Worker     }
361*5225e6b1SAndroid Build Coastguard Worker 
avb_read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> AvbIoResult<usize>362*5225e6b1SAndroid Build Coastguard Worker     fn avb_read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> AvbIoResult<usize> {
363*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
364*5225e6b1SAndroid Build Coastguard Worker         {
365*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => {
366*5225e6b1SAndroid Build Coastguard Worker                 protocol.read_persistent_value(name, value).map_err(efi_error_to_avb_error)
367*5225e6b1SAndroid Build Coastguard Worker             }
368*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
369*5225e6b1SAndroid Build Coastguard Worker         }
370*5225e6b1SAndroid Build Coastguard Worker     }
371*5225e6b1SAndroid Build Coastguard Worker 
avb_write_persistent_value(&mut self, name: &CStr, value: &[u8]) -> AvbIoResult<()>372*5225e6b1SAndroid Build Coastguard Worker     fn avb_write_persistent_value(&mut self, name: &CStr, value: &[u8]) -> AvbIoResult<()> {
373*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
374*5225e6b1SAndroid Build Coastguard Worker         {
375*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => {
376*5225e6b1SAndroid Build Coastguard Worker                 protocol.write_persistent_value(name, Some(value)).map_err(efi_error_to_avb_error)
377*5225e6b1SAndroid Build Coastguard Worker             }
378*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
379*5225e6b1SAndroid Build Coastguard Worker         }
380*5225e6b1SAndroid Build Coastguard Worker     }
381*5225e6b1SAndroid Build Coastguard Worker 
avb_erase_persistent_value(&mut self, name: &CStr) -> AvbIoResult<()>382*5225e6b1SAndroid Build Coastguard Worker     fn avb_erase_persistent_value(&mut self, name: &CStr) -> AvbIoResult<()> {
383*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
384*5225e6b1SAndroid Build Coastguard Worker         {
385*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => {
386*5225e6b1SAndroid Build Coastguard Worker                 protocol.write_persistent_value(name, None).map_err(efi_error_to_avb_error)
387*5225e6b1SAndroid Build Coastguard Worker             }
388*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
389*5225e6b1SAndroid Build Coastguard Worker         }
390*5225e6b1SAndroid Build Coastguard Worker     }
391*5225e6b1SAndroid Build Coastguard Worker 
avb_validate_vbmeta_public_key( &self, public_key: &[u8], public_key_metadata: Option<&[u8]>, ) -> AvbIoResult<KeyValidationStatus>392*5225e6b1SAndroid Build Coastguard Worker     fn avb_validate_vbmeta_public_key(
393*5225e6b1SAndroid Build Coastguard Worker         &self,
394*5225e6b1SAndroid Build Coastguard Worker         public_key: &[u8],
395*5225e6b1SAndroid Build Coastguard Worker         public_key_metadata: Option<&[u8]>,
396*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<KeyValidationStatus> {
397*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
398*5225e6b1SAndroid Build Coastguard Worker         {
399*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => protocol
400*5225e6b1SAndroid Build Coastguard Worker                 .validate_vbmeta_public_key(public_key, public_key_metadata)
401*5225e6b1SAndroid Build Coastguard Worker                 .map(to_avb_validation_status_or_panic)
402*5225e6b1SAndroid Build Coastguard Worker                 .map_err(efi_error_to_avb_error),
403*5225e6b1SAndroid Build Coastguard Worker             Err(_) => Err(AvbIoError::NotImplemented),
404*5225e6b1SAndroid Build Coastguard Worker         }
405*5225e6b1SAndroid Build Coastguard Worker     }
406*5225e6b1SAndroid Build Coastguard Worker 
avb_cert_read_permanent_attributes( &mut self, attributes: &mut CertPermanentAttributes, ) -> AvbIoResult<()>407*5225e6b1SAndroid Build Coastguard Worker     fn avb_cert_read_permanent_attributes(
408*5225e6b1SAndroid Build Coastguard Worker         &mut self,
409*5225e6b1SAndroid Build Coastguard Worker         attributes: &mut CertPermanentAttributes,
410*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<()> {
411*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/337846185): Switch to use GBL Verified Boot EFI protocol when available.
412*5225e6b1SAndroid Build Coastguard Worker         let perm_attr = self
413*5225e6b1SAndroid Build Coastguard Worker             .get_efi_fdt_prop("gbl", c"avb-cert-permanent-attributes")
414*5225e6b1SAndroid Build Coastguard Worker             .ok_or(AvbIoError::NotImplemented)?;
415*5225e6b1SAndroid Build Coastguard Worker         attributes.as_bytes_mut().clone_from_slice(perm_attr);
416*5225e6b1SAndroid Build Coastguard Worker         Ok(())
417*5225e6b1SAndroid Build Coastguard Worker     }
418*5225e6b1SAndroid Build Coastguard Worker 
avb_cert_read_permanent_attributes_hash(&mut self) -> AvbIoResult<[u8; SHA256_DIGEST_SIZE]>419*5225e6b1SAndroid Build Coastguard Worker     fn avb_cert_read_permanent_attributes_hash(&mut self) -> AvbIoResult<[u8; SHA256_DIGEST_SIZE]> {
420*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/337846185): Switch to use GBL Verified Boot EFI protocol when available.
421*5225e6b1SAndroid Build Coastguard Worker         let hash = self
422*5225e6b1SAndroid Build Coastguard Worker             .get_efi_fdt_prop("gbl", c"avb-cert-permanent-attributes-hash")
423*5225e6b1SAndroid Build Coastguard Worker             .ok_or(AvbIoError::NotImplemented)?;
424*5225e6b1SAndroid Build Coastguard Worker         Ok(hash.try_into().map_err(|_| AvbIoError::Io)?)
425*5225e6b1SAndroid Build Coastguard Worker     }
426*5225e6b1SAndroid Build Coastguard Worker 
avb_handle_verification_result( &mut self, color: BootStateColor, digest: Option<&CStr>, boot_os_version: Option<&[u8]>, boot_security_patch: Option<&[u8]>, system_os_version: Option<&[u8]>, system_security_patch: Option<&[u8]>, vendor_os_version: Option<&[u8]>, vendor_security_patch: Option<&[u8]>, ) -> AvbIoResult<()>427*5225e6b1SAndroid Build Coastguard Worker     fn avb_handle_verification_result(
428*5225e6b1SAndroid Build Coastguard Worker         &mut self,
429*5225e6b1SAndroid Build Coastguard Worker         color: BootStateColor,
430*5225e6b1SAndroid Build Coastguard Worker         digest: Option<&CStr>,
431*5225e6b1SAndroid Build Coastguard Worker         boot_os_version: Option<&[u8]>,
432*5225e6b1SAndroid Build Coastguard Worker         boot_security_patch: Option<&[u8]>,
433*5225e6b1SAndroid Build Coastguard Worker         system_os_version: Option<&[u8]>,
434*5225e6b1SAndroid Build Coastguard Worker         system_security_patch: Option<&[u8]>,
435*5225e6b1SAndroid Build Coastguard Worker         vendor_os_version: Option<&[u8]>,
436*5225e6b1SAndroid Build Coastguard Worker         vendor_security_patch: Option<&[u8]>,
437*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<()> {
438*5225e6b1SAndroid Build Coastguard Worker         match self.efi_entry.system_table().boot_services().find_first_and_open::<GblAvbProtocol>()
439*5225e6b1SAndroid Build Coastguard Worker         {
440*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => protocol
441*5225e6b1SAndroid Build Coastguard Worker                 .handle_verification_result(&GblEfiAvbVerificationResult {
442*5225e6b1SAndroid Build Coastguard Worker                     color: avb_color_to_efi_color(color),
443*5225e6b1SAndroid Build Coastguard Worker                     digest: digest.map_or(null(), |p| p.as_ptr() as _),
444*5225e6b1SAndroid Build Coastguard Worker                     boot_version: boot_os_version.map_or(null(), |p| p.as_ptr()),
445*5225e6b1SAndroid Build Coastguard Worker                     boot_security_patch: boot_security_patch.map_or(null(), |p| p.as_ptr()),
446*5225e6b1SAndroid Build Coastguard Worker                     system_version: system_os_version.map_or(null(), |p| p.as_ptr()),
447*5225e6b1SAndroid Build Coastguard Worker                     system_security_patch: system_security_patch.map_or(null(), |p| p.as_ptr()),
448*5225e6b1SAndroid Build Coastguard Worker                     vendor_version: vendor_os_version.map_or(null(), |p| p.as_ptr()),
449*5225e6b1SAndroid Build Coastguard Worker                     vendor_security_patch: vendor_security_patch.map_or(null(), |p| p.as_ptr()),
450*5225e6b1SAndroid Build Coastguard Worker                 })
451*5225e6b1SAndroid Build Coastguard Worker                 .map_err(efi_error_to_avb_error),
452*5225e6b1SAndroid Build Coastguard Worker             _ => Ok(()),
453*5225e6b1SAndroid Build Coastguard Worker         }
454*5225e6b1SAndroid Build Coastguard Worker     }
455*5225e6b1SAndroid Build Coastguard Worker 
get_image_buffer( &mut self, image_name: &str, size: NonZeroUsize, ) -> GblResult<ImageBuffer<'d>>456*5225e6b1SAndroid Build Coastguard Worker     fn get_image_buffer(
457*5225e6b1SAndroid Build Coastguard Worker         &mut self,
458*5225e6b1SAndroid Build Coastguard Worker         image_name: &str,
459*5225e6b1SAndroid Build Coastguard Worker         size: NonZeroUsize,
460*5225e6b1SAndroid Build Coastguard Worker     ) -> GblResult<ImageBuffer<'d>> {
461*5225e6b1SAndroid Build Coastguard Worker         self.get_buffer_image_loading(image_name, size)
462*5225e6b1SAndroid Build Coastguard Worker             .or(Self::allocate_image_buffer(image_name, size)
463*5225e6b1SAndroid Build Coastguard Worker                 .map_err(|e| libgbl::IntegrationError::UnificationError(e)))
464*5225e6b1SAndroid Build Coastguard Worker     }
465*5225e6b1SAndroid Build Coastguard Worker 
get_custom_device_tree(&mut self) -> Option<&'a [u8]>466*5225e6b1SAndroid Build Coastguard Worker     fn get_custom_device_tree(&mut self) -> Option<&'a [u8]> {
467*5225e6b1SAndroid Build Coastguard Worker         // On Cuttlefish, the device tree comes from the UEFI config tables.
468*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/353272981): once we've settled on the device tree UEFI protocol, use that
469*5225e6b1SAndroid Build Coastguard Worker         // instead to provide a Cuttlefish-specific backend.
470*5225e6b1SAndroid Build Coastguard Worker         Some(get_efi_fdt(&self.efi_entry)?.1)
471*5225e6b1SAndroid Build Coastguard Worker     }
472*5225e6b1SAndroid Build Coastguard Worker 
fixup_os_commandline<'c>( &mut self, commandline: &CStr, fixup_buffer: &'c mut [u8], ) -> Result<Option<&'c str>>473*5225e6b1SAndroid Build Coastguard Worker     fn fixup_os_commandline<'c>(
474*5225e6b1SAndroid Build Coastguard Worker         &mut self,
475*5225e6b1SAndroid Build Coastguard Worker         commandline: &CStr,
476*5225e6b1SAndroid Build Coastguard Worker         fixup_buffer: &'c mut [u8],
477*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<Option<&'c str>> {
478*5225e6b1SAndroid Build Coastguard Worker         Ok(
479*5225e6b1SAndroid Build Coastguard Worker             match self
480*5225e6b1SAndroid Build Coastguard Worker                 .efi_entry
481*5225e6b1SAndroid Build Coastguard Worker                 .system_table()
482*5225e6b1SAndroid Build Coastguard Worker                 .boot_services()
483*5225e6b1SAndroid Build Coastguard Worker                 .find_first_and_open::<GblOsConfigurationProtocol>()
484*5225e6b1SAndroid Build Coastguard Worker             {
485*5225e6b1SAndroid Build Coastguard Worker                 Ok(protocol) => {
486*5225e6b1SAndroid Build Coastguard Worker                     protocol.fixup_kernel_commandline(commandline, fixup_buffer)?;
487*5225e6b1SAndroid Build Coastguard Worker                     Some(CStr::from_bytes_until_nul(&fixup_buffer[..])?.to_str()?)
488*5225e6b1SAndroid Build Coastguard Worker                 }
489*5225e6b1SAndroid Build Coastguard Worker                 _ => None,
490*5225e6b1SAndroid Build Coastguard Worker             },
491*5225e6b1SAndroid Build Coastguard Worker         )
492*5225e6b1SAndroid Build Coastguard Worker     }
493*5225e6b1SAndroid Build Coastguard Worker 
fixup_bootconfig<'c>( &mut self, bootconfig: &[u8], fixup_buffer: &'c mut [u8], ) -> Result<Option<&'c [u8]>>494*5225e6b1SAndroid Build Coastguard Worker     fn fixup_bootconfig<'c>(
495*5225e6b1SAndroid Build Coastguard Worker         &mut self,
496*5225e6b1SAndroid Build Coastguard Worker         bootconfig: &[u8],
497*5225e6b1SAndroid Build Coastguard Worker         fixup_buffer: &'c mut [u8],
498*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<Option<&'c [u8]>> {
499*5225e6b1SAndroid Build Coastguard Worker         Ok(
500*5225e6b1SAndroid Build Coastguard Worker             match self
501*5225e6b1SAndroid Build Coastguard Worker                 .efi_entry
502*5225e6b1SAndroid Build Coastguard Worker                 .system_table()
503*5225e6b1SAndroid Build Coastguard Worker                 .boot_services()
504*5225e6b1SAndroid Build Coastguard Worker                 .find_first_and_open::<GblOsConfigurationProtocol>()
505*5225e6b1SAndroid Build Coastguard Worker             {
506*5225e6b1SAndroid Build Coastguard Worker                 Ok(protocol) => {
507*5225e6b1SAndroid Build Coastguard Worker                     let fixup_size = protocol.fixup_bootconfig(bootconfig, fixup_buffer)?;
508*5225e6b1SAndroid Build Coastguard Worker                     Some(&fixup_buffer[..fixup_size])
509*5225e6b1SAndroid Build Coastguard Worker                 }
510*5225e6b1SAndroid Build Coastguard Worker                 _ => None,
511*5225e6b1SAndroid Build Coastguard Worker             },
512*5225e6b1SAndroid Build Coastguard Worker         )
513*5225e6b1SAndroid Build Coastguard Worker     }
514*5225e6b1SAndroid Build Coastguard Worker 
fixup_device_tree(&mut self, device_tree: &mut [u8]) -> Result<()>515*5225e6b1SAndroid Build Coastguard Worker     fn fixup_device_tree(&mut self, device_tree: &mut [u8]) -> Result<()> {
516*5225e6b1SAndroid Build Coastguard Worker         if let Ok(protocol) =
517*5225e6b1SAndroid Build Coastguard Worker             self.efi_entry.system_table().boot_services().find_first_and_open::<DtFixupProtocol>()
518*5225e6b1SAndroid Build Coastguard Worker         {
519*5225e6b1SAndroid Build Coastguard Worker             protocol.fixup(device_tree)?;
520*5225e6b1SAndroid Build Coastguard Worker         }
521*5225e6b1SAndroid Build Coastguard Worker 
522*5225e6b1SAndroid Build Coastguard Worker         Ok(())
523*5225e6b1SAndroid Build Coastguard Worker     }
524*5225e6b1SAndroid Build Coastguard Worker 
select_device_trees( &mut self, components_registry: &mut DeviceTreeComponentsRegistry, ) -> Result<()>525*5225e6b1SAndroid Build Coastguard Worker     fn select_device_trees(
526*5225e6b1SAndroid Build Coastguard Worker         &mut self,
527*5225e6b1SAndroid Build Coastguard Worker         components_registry: &mut DeviceTreeComponentsRegistry,
528*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<()> {
529*5225e6b1SAndroid Build Coastguard Worker         match self
530*5225e6b1SAndroid Build Coastguard Worker             .efi_entry
531*5225e6b1SAndroid Build Coastguard Worker             .system_table()
532*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
533*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblOsConfigurationProtocol>()
534*5225e6b1SAndroid Build Coastguard Worker         {
535*5225e6b1SAndroid Build Coastguard Worker             Ok(protocol) => {
536*5225e6b1SAndroid Build Coastguard Worker                 // Protocol detected, convert to UEFI types.
537*5225e6b1SAndroid Build Coastguard Worker                 let mut uefi_components: ArrayVec<_, MAXIMUM_DEVICE_TREE_COMPONENTS> =
538*5225e6b1SAndroid Build Coastguard Worker                     components_registry
539*5225e6b1SAndroid Build Coastguard Worker                         .components()
540*5225e6b1SAndroid Build Coastguard Worker                         .map(|component| dt_component_to_efi_dt(component))
541*5225e6b1SAndroid Build Coastguard Worker                         .collect();
542*5225e6b1SAndroid Build Coastguard Worker 
543*5225e6b1SAndroid Build Coastguard Worker                 protocol.select_device_trees(&mut uefi_components[..])?;
544*5225e6b1SAndroid Build Coastguard Worker 
545*5225e6b1SAndroid Build Coastguard Worker                 // Propagate selections to the components_registry.
546*5225e6b1SAndroid Build Coastguard Worker                 components_registry
547*5225e6b1SAndroid Build Coastguard Worker                     .components_mut()
548*5225e6b1SAndroid Build Coastguard Worker                     .zip(uefi_components.iter_mut())
549*5225e6b1SAndroid Build Coastguard Worker                     .enumerate()
550*5225e6b1SAndroid Build Coastguard Worker                     .for_each(|(index, (component, uefi_component))| {
551*5225e6b1SAndroid Build Coastguard Worker                         if uefi_component.selected {
552*5225e6b1SAndroid Build Coastguard Worker                             efi_println!(
553*5225e6b1SAndroid Build Coastguard Worker                                 self.efi_entry,
554*5225e6b1SAndroid Build Coastguard Worker                                 "Device tree component at index {} got selected by UEFI call. \
555*5225e6b1SAndroid Build Coastguard Worker                                 Source: {}",
556*5225e6b1SAndroid Build Coastguard Worker                                 index,
557*5225e6b1SAndroid Build Coastguard Worker                                 component.source
558*5225e6b1SAndroid Build Coastguard Worker                             );
559*5225e6b1SAndroid Build Coastguard Worker                         }
560*5225e6b1SAndroid Build Coastguard Worker                         component.selected = uefi_component.selected;
561*5225e6b1SAndroid Build Coastguard Worker                     });
562*5225e6b1SAndroid Build Coastguard Worker 
563*5225e6b1SAndroid Build Coastguard Worker                 Ok(())
564*5225e6b1SAndroid Build Coastguard Worker             }
565*5225e6b1SAndroid Build Coastguard Worker             _ => components_registry.autoselect(),
566*5225e6b1SAndroid Build Coastguard Worker         }
567*5225e6b1SAndroid Build Coastguard Worker     }
568*5225e6b1SAndroid Build Coastguard Worker 
fastboot_variable<'arg>( &mut self, name: &CStr, args: impl Iterator<Item = &'arg CStr> + Clone, out: &mut [u8], ) -> Result<usize>569*5225e6b1SAndroid Build Coastguard Worker     fn fastboot_variable<'arg>(
570*5225e6b1SAndroid Build Coastguard Worker         &mut self,
571*5225e6b1SAndroid Build Coastguard Worker         name: &CStr,
572*5225e6b1SAndroid Build Coastguard Worker         args: impl Iterator<Item = &'arg CStr> + Clone,
573*5225e6b1SAndroid Build Coastguard Worker         out: &mut [u8],
574*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<usize> {
575*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
576*5225e6b1SAndroid Build Coastguard Worker             .system_table()
577*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
578*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblFastbootProtocol>()?
579*5225e6b1SAndroid Build Coastguard Worker             .get_var(name, args, out)
580*5225e6b1SAndroid Build Coastguard Worker     }
581*5225e6b1SAndroid Build Coastguard Worker 
fastboot_visit_all_variables(&mut self, cb: impl FnMut(&[&CStr], &CStr)) -> Result<()>582*5225e6b1SAndroid Build Coastguard Worker     fn fastboot_visit_all_variables(&mut self, cb: impl FnMut(&[&CStr], &CStr)) -> Result<()> {
583*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
584*5225e6b1SAndroid Build Coastguard Worker             .system_table()
585*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
586*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblFastbootProtocol>()?
587*5225e6b1SAndroid Build Coastguard Worker             .get_var_all(cb)
588*5225e6b1SAndroid Build Coastguard Worker     }
589*5225e6b1SAndroid Build Coastguard Worker 
slots_metadata(&mut self) -> Result<SlotsMetadata>590*5225e6b1SAndroid Build Coastguard Worker     fn slots_metadata(&mut self) -> Result<SlotsMetadata> {
591*5225e6b1SAndroid Build Coastguard Worker         Ok(SlotsMetadata {
592*5225e6b1SAndroid Build Coastguard Worker             slot_count: self
593*5225e6b1SAndroid Build Coastguard Worker                 .efi_entry
594*5225e6b1SAndroid Build Coastguard Worker                 .system_table()
595*5225e6b1SAndroid Build Coastguard Worker                 .boot_services()
596*5225e6b1SAndroid Build Coastguard Worker                 .find_first_and_open::<GblSlotProtocol>()?
597*5225e6b1SAndroid Build Coastguard Worker                 .load_boot_data()?
598*5225e6b1SAndroid Build Coastguard Worker                 .slot_count
599*5225e6b1SAndroid Build Coastguard Worker                 .try_into()
600*5225e6b1SAndroid Build Coastguard Worker                 .unwrap(),
601*5225e6b1SAndroid Build Coastguard Worker         })
602*5225e6b1SAndroid Build Coastguard Worker     }
603*5225e6b1SAndroid Build Coastguard Worker 
get_current_slot(&mut self) -> Result<Slot>604*5225e6b1SAndroid Build Coastguard Worker     fn get_current_slot(&mut self) -> Result<Slot> {
605*5225e6b1SAndroid Build Coastguard Worker         // TODO(b/363075013): Refactors the opening of slot protocol into a common helper once
606*5225e6b1SAndroid Build Coastguard Worker         // `MockBootServices::find_first_and_open` is updated to return Protocol<'_, T>.
607*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
608*5225e6b1SAndroid Build Coastguard Worker             .system_table()
609*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
610*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblSlotProtocol>()?
611*5225e6b1SAndroid Build Coastguard Worker             .get_current_slot()?
612*5225e6b1SAndroid Build Coastguard Worker             .try_into()
613*5225e6b1SAndroid Build Coastguard Worker     }
614*5225e6b1SAndroid Build Coastguard Worker 
get_next_slot(&mut self, mark_boot_attempt: bool) -> Result<Slot>615*5225e6b1SAndroid Build Coastguard Worker     fn get_next_slot(&mut self, mark_boot_attempt: bool) -> Result<Slot> {
616*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
617*5225e6b1SAndroid Build Coastguard Worker             .system_table()
618*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
619*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblSlotProtocol>()?
620*5225e6b1SAndroid Build Coastguard Worker             .get_next_slot(mark_boot_attempt)?
621*5225e6b1SAndroid Build Coastguard Worker             .try_into()
622*5225e6b1SAndroid Build Coastguard Worker     }
623*5225e6b1SAndroid Build Coastguard Worker 
set_active_slot(&mut self, slot: u8) -> Result<()>624*5225e6b1SAndroid Build Coastguard Worker     fn set_active_slot(&mut self, slot: u8) -> Result<()> {
625*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
626*5225e6b1SAndroid Build Coastguard Worker             .system_table()
627*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
628*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblSlotProtocol>()?
629*5225e6b1SAndroid Build Coastguard Worker             .set_active_slot(slot)
630*5225e6b1SAndroid Build Coastguard Worker     }
631*5225e6b1SAndroid Build Coastguard Worker 
set_reboot_reason(&mut self, reason: RebootReason) -> Result<()>632*5225e6b1SAndroid Build Coastguard Worker     fn set_reboot_reason(&mut self, reason: RebootReason) -> Result<()> {
633*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
634*5225e6b1SAndroid Build Coastguard Worker             .system_table()
635*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
636*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblSlotProtocol>()?
637*5225e6b1SAndroid Build Coastguard Worker             .set_boot_reason(gbl_to_efi_boot_reason(reason), b"")
638*5225e6b1SAndroid Build Coastguard Worker     }
639*5225e6b1SAndroid Build Coastguard Worker 
get_reboot_reason(&mut self) -> Result<RebootReason>640*5225e6b1SAndroid Build Coastguard Worker     fn get_reboot_reason(&mut self) -> Result<RebootReason> {
641*5225e6b1SAndroid Build Coastguard Worker         let mut subreason = [0u8; 128];
642*5225e6b1SAndroid Build Coastguard Worker         self.efi_entry
643*5225e6b1SAndroid Build Coastguard Worker             .system_table()
644*5225e6b1SAndroid Build Coastguard Worker             .boot_services()
645*5225e6b1SAndroid Build Coastguard Worker             .find_first_and_open::<GblSlotProtocol>()?
646*5225e6b1SAndroid Build Coastguard Worker             .get_boot_reason(&mut subreason[..])
647*5225e6b1SAndroid Build Coastguard Worker             .map(|(v, _)| efi_to_gbl_boot_reason(v))
648*5225e6b1SAndroid Build Coastguard Worker     }
649*5225e6b1SAndroid Build Coastguard Worker }
650*5225e6b1SAndroid Build Coastguard Worker 
651*5225e6b1SAndroid Build Coastguard Worker /// Converts a [GblEfiBootReason] to [RebootReason].
efi_to_gbl_boot_reason(reason: GblEfiBootReason) -> RebootReason652*5225e6b1SAndroid Build Coastguard Worker fn efi_to_gbl_boot_reason(reason: GblEfiBootReason) -> RebootReason {
653*5225e6b1SAndroid Build Coastguard Worker     match reason {
654*5225e6b1SAndroid Build Coastguard Worker         GBL_EFI_BOOT_REASON_RECOVERY => RebootReason::Recovery,
655*5225e6b1SAndroid Build Coastguard Worker         GBL_EFI_BOOT_REASON_BOOTLOADER => RebootReason::Bootloader,
656*5225e6b1SAndroid Build Coastguard Worker         GBL_EFI_BOOT_REASON_FASTBOOTD => RebootReason::FastbootD,
657*5225e6b1SAndroid Build Coastguard Worker         _ => RebootReason::Normal,
658*5225e6b1SAndroid Build Coastguard Worker     }
659*5225e6b1SAndroid Build Coastguard Worker }
660*5225e6b1SAndroid Build Coastguard Worker 
661*5225e6b1SAndroid Build Coastguard Worker /// Converts a [RebootReason] to [GblEfiBootReason].
gbl_to_efi_boot_reason(reason: RebootReason) -> GblEfiBootReason662*5225e6b1SAndroid Build Coastguard Worker fn gbl_to_efi_boot_reason(reason: RebootReason) -> GblEfiBootReason {
663*5225e6b1SAndroid Build Coastguard Worker     match reason {
664*5225e6b1SAndroid Build Coastguard Worker         RebootReason::Recovery => GBL_EFI_BOOT_REASON_RECOVERY,
665*5225e6b1SAndroid Build Coastguard Worker         RebootReason::Bootloader => GBL_EFI_BOOT_REASON_BOOTLOADER,
666*5225e6b1SAndroid Build Coastguard Worker         RebootReason::FastbootD => GBL_EFI_BOOT_REASON_FASTBOOTD,
667*5225e6b1SAndroid Build Coastguard Worker         RebootReason::Normal => GBL_EFI_BOOT_REASON_COLD,
668*5225e6b1SAndroid Build Coastguard Worker     }
669*5225e6b1SAndroid Build Coastguard Worker }
670*5225e6b1SAndroid Build Coastguard Worker 
671*5225e6b1SAndroid Build Coastguard Worker /// Inherits everything from `ops` but override a few such as read boot_a from
672*5225e6b1SAndroid Build Coastguard Worker /// bootimg_buffer, avb_write_rollback_index(), slot operation etc
673*5225e6b1SAndroid Build Coastguard Worker pub struct RambootOps<'b, T> {
674*5225e6b1SAndroid Build Coastguard Worker     pub ops: &'b mut T,
675*5225e6b1SAndroid Build Coastguard Worker     pub bootimg_buffer: &'b mut [u8],
676*5225e6b1SAndroid Build Coastguard Worker }
677*5225e6b1SAndroid Build Coastguard Worker 
678*5225e6b1SAndroid Build Coastguard Worker impl<'a, 'd, T: GblOps<'a, 'd>> GblOps<'a, 'd> for RambootOps<'_, T> {
console_out(&mut self) -> Option<&mut dyn Write>679*5225e6b1SAndroid Build Coastguard Worker     fn console_out(&mut self) -> Option<&mut dyn Write> {
680*5225e6b1SAndroid Build Coastguard Worker         self.ops.console_out()
681*5225e6b1SAndroid Build Coastguard Worker     }
682*5225e6b1SAndroid Build Coastguard Worker 
should_stop_in_fastboot(&mut self) -> Result<bool>683*5225e6b1SAndroid Build Coastguard Worker     fn should_stop_in_fastboot(&mut self) -> Result<bool> {
684*5225e6b1SAndroid Build Coastguard Worker         self.ops.should_stop_in_fastboot()
685*5225e6b1SAndroid Build Coastguard Worker     }
686*5225e6b1SAndroid Build Coastguard Worker 
reboot(&mut self)687*5225e6b1SAndroid Build Coastguard Worker     fn reboot(&mut self) {
688*5225e6b1SAndroid Build Coastguard Worker         self.ops.reboot()
689*5225e6b1SAndroid Build Coastguard Worker     }
690*5225e6b1SAndroid Build Coastguard Worker 
disks( &self, ) -> &'a [GblDisk< Disk<impl BlockIo + 'a, impl DerefMut<Target = [u8]> + 'a>, Gpt<impl DerefMut<Target = [u8]> + 'a>, >]691*5225e6b1SAndroid Build Coastguard Worker     fn disks(
692*5225e6b1SAndroid Build Coastguard Worker         &self,
693*5225e6b1SAndroid Build Coastguard Worker     ) -> &'a [GblDisk<
694*5225e6b1SAndroid Build Coastguard Worker         Disk<impl BlockIo + 'a, impl DerefMut<Target = [u8]> + 'a>,
695*5225e6b1SAndroid Build Coastguard Worker         Gpt<impl DerefMut<Target = [u8]> + 'a>,
696*5225e6b1SAndroid Build Coastguard Worker     >] {
697*5225e6b1SAndroid Build Coastguard Worker         self.ops.disks()
698*5225e6b1SAndroid Build Coastguard Worker     }
699*5225e6b1SAndroid Build Coastguard Worker 
expected_os(&mut self) -> Result<Option<Os>>700*5225e6b1SAndroid Build Coastguard Worker     fn expected_os(&mut self) -> Result<Option<Os>> {
701*5225e6b1SAndroid Build Coastguard Worker         self.ops.expected_os()
702*5225e6b1SAndroid Build Coastguard Worker     }
703*5225e6b1SAndroid Build Coastguard Worker 
zircon_add_device_zbi_items( &mut self, container: &mut ZbiContainer<&mut [u8]>, ) -> Result<()>704*5225e6b1SAndroid Build Coastguard Worker     fn zircon_add_device_zbi_items(
705*5225e6b1SAndroid Build Coastguard Worker         &mut self,
706*5225e6b1SAndroid Build Coastguard Worker         container: &mut ZbiContainer<&mut [u8]>,
707*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<()> {
708*5225e6b1SAndroid Build Coastguard Worker         self.ops.zircon_add_device_zbi_items(container)
709*5225e6b1SAndroid Build Coastguard Worker     }
710*5225e6b1SAndroid Build Coastguard Worker 
get_zbi_bootloader_files_buffer(&mut self) -> Option<&mut [u8]>711*5225e6b1SAndroid Build Coastguard Worker     fn get_zbi_bootloader_files_buffer(&mut self) -> Option<&mut [u8]> {
712*5225e6b1SAndroid Build Coastguard Worker         self.ops.get_zbi_bootloader_files_buffer()
713*5225e6b1SAndroid Build Coastguard Worker     }
714*5225e6b1SAndroid Build Coastguard Worker 
load_slot_interface<'c>( &'c mut self, _fnmut: &'c mut dyn FnMut(&mut [u8]) -> Result<()>, _boot_token: BootToken, ) -> GblResult<Cursor<'c>>715*5225e6b1SAndroid Build Coastguard Worker     fn load_slot_interface<'c>(
716*5225e6b1SAndroid Build Coastguard Worker         &'c mut self,
717*5225e6b1SAndroid Build Coastguard Worker         _fnmut: &'c mut dyn FnMut(&mut [u8]) -> Result<()>,
718*5225e6b1SAndroid Build Coastguard Worker         _boot_token: BootToken,
719*5225e6b1SAndroid Build Coastguard Worker     ) -> GblResult<Cursor<'c>> {
720*5225e6b1SAndroid Build Coastguard Worker         self.ops.load_slot_interface(_fnmut, _boot_token)
721*5225e6b1SAndroid Build Coastguard Worker     }
722*5225e6b1SAndroid Build Coastguard Worker 
avb_read_is_device_unlocked(&mut self) -> AvbIoResult<bool>723*5225e6b1SAndroid Build Coastguard Worker     fn avb_read_is_device_unlocked(&mut self) -> AvbIoResult<bool> {
724*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_read_is_device_unlocked()
725*5225e6b1SAndroid Build Coastguard Worker     }
726*5225e6b1SAndroid Build Coastguard Worker 
avb_read_rollback_index(&mut self, _rollback_index_location: usize) -> AvbIoResult<u64>727*5225e6b1SAndroid Build Coastguard Worker     fn avb_read_rollback_index(&mut self, _rollback_index_location: usize) -> AvbIoResult<u64> {
728*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_read_rollback_index(_rollback_index_location)
729*5225e6b1SAndroid Build Coastguard Worker     }
730*5225e6b1SAndroid Build Coastguard Worker 
avb_write_rollback_index(&mut self, _: usize, _: u64) -> AvbIoResult<()>731*5225e6b1SAndroid Build Coastguard Worker     fn avb_write_rollback_index(&mut self, _: usize, _: u64) -> AvbIoResult<()> {
732*5225e6b1SAndroid Build Coastguard Worker         // We don't want to persist AVB related data such as updating antirollback indices.
733*5225e6b1SAndroid Build Coastguard Worker         Ok(())
734*5225e6b1SAndroid Build Coastguard Worker     }
735*5225e6b1SAndroid Build Coastguard Worker 
avb_read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> AvbIoResult<usize>736*5225e6b1SAndroid Build Coastguard Worker     fn avb_read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> AvbIoResult<usize> {
737*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_read_persistent_value(name, value)
738*5225e6b1SAndroid Build Coastguard Worker     }
739*5225e6b1SAndroid Build Coastguard Worker 
avb_write_persistent_value(&mut self, _: &CStr, _: &[u8]) -> AvbIoResult<()>740*5225e6b1SAndroid Build Coastguard Worker     fn avb_write_persistent_value(&mut self, _: &CStr, _: &[u8]) -> AvbIoResult<()> {
741*5225e6b1SAndroid Build Coastguard Worker         // We don't want to persist AVB related data such as updating current VBH.
742*5225e6b1SAndroid Build Coastguard Worker         Ok(())
743*5225e6b1SAndroid Build Coastguard Worker     }
744*5225e6b1SAndroid Build Coastguard Worker 
avb_erase_persistent_value(&mut self, _: &CStr) -> AvbIoResult<()>745*5225e6b1SAndroid Build Coastguard Worker     fn avb_erase_persistent_value(&mut self, _: &CStr) -> AvbIoResult<()> {
746*5225e6b1SAndroid Build Coastguard Worker         // We don't want to persist AVB related data such as updating current VBH.
747*5225e6b1SAndroid Build Coastguard Worker         Ok(())
748*5225e6b1SAndroid Build Coastguard Worker     }
749*5225e6b1SAndroid Build Coastguard Worker 
avb_cert_read_permanent_attributes( &mut self, attributes: &mut CertPermanentAttributes, ) -> AvbIoResult<()>750*5225e6b1SAndroid Build Coastguard Worker     fn avb_cert_read_permanent_attributes(
751*5225e6b1SAndroid Build Coastguard Worker         &mut self,
752*5225e6b1SAndroid Build Coastguard Worker         attributes: &mut CertPermanentAttributes,
753*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<()> {
754*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_cert_read_permanent_attributes(attributes)
755*5225e6b1SAndroid Build Coastguard Worker     }
756*5225e6b1SAndroid Build Coastguard Worker 
avb_cert_read_permanent_attributes_hash(&mut self) -> AvbIoResult<[u8; SHA256_DIGEST_SIZE]>757*5225e6b1SAndroid Build Coastguard Worker     fn avb_cert_read_permanent_attributes_hash(&mut self) -> AvbIoResult<[u8; SHA256_DIGEST_SIZE]> {
758*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_cert_read_permanent_attributes_hash()
759*5225e6b1SAndroid Build Coastguard Worker     }
760*5225e6b1SAndroid Build Coastguard Worker 
get_image_buffer( &mut self, image_name: &str, size: NonZeroUsize, ) -> GblResult<ImageBuffer<'d>>761*5225e6b1SAndroid Build Coastguard Worker     fn get_image_buffer(
762*5225e6b1SAndroid Build Coastguard Worker         &mut self,
763*5225e6b1SAndroid Build Coastguard Worker         image_name: &str,
764*5225e6b1SAndroid Build Coastguard Worker         size: NonZeroUsize,
765*5225e6b1SAndroid Build Coastguard Worker     ) -> GblResult<ImageBuffer<'d>> {
766*5225e6b1SAndroid Build Coastguard Worker         self.ops.get_image_buffer(image_name, size)
767*5225e6b1SAndroid Build Coastguard Worker     }
768*5225e6b1SAndroid Build Coastguard Worker 
get_custom_device_tree(&mut self) -> Option<&'a [u8]>769*5225e6b1SAndroid Build Coastguard Worker     fn get_custom_device_tree(&mut self) -> Option<&'a [u8]> {
770*5225e6b1SAndroid Build Coastguard Worker         self.ops.get_custom_device_tree()
771*5225e6b1SAndroid Build Coastguard Worker     }
772*5225e6b1SAndroid Build Coastguard Worker 
fixup_os_commandline<'c>( &mut self, commandline: &CStr, fixup_buffer: &'c mut [u8], ) -> Result<Option<&'c str>>773*5225e6b1SAndroid Build Coastguard Worker     fn fixup_os_commandline<'c>(
774*5225e6b1SAndroid Build Coastguard Worker         &mut self,
775*5225e6b1SAndroid Build Coastguard Worker         commandline: &CStr,
776*5225e6b1SAndroid Build Coastguard Worker         fixup_buffer: &'c mut [u8],
777*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<Option<&'c str>> {
778*5225e6b1SAndroid Build Coastguard Worker         self.ops.fixup_os_commandline(commandline, fixup_buffer)
779*5225e6b1SAndroid Build Coastguard Worker     }
780*5225e6b1SAndroid Build Coastguard Worker 
fixup_bootconfig<'c>( &mut self, bootconfig: &[u8], fixup_buffer: &'c mut [u8], ) -> Result<Option<&'c [u8]>>781*5225e6b1SAndroid Build Coastguard Worker     fn fixup_bootconfig<'c>(
782*5225e6b1SAndroid Build Coastguard Worker         &mut self,
783*5225e6b1SAndroid Build Coastguard Worker         bootconfig: &[u8],
784*5225e6b1SAndroid Build Coastguard Worker         fixup_buffer: &'c mut [u8],
785*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<Option<&'c [u8]>> {
786*5225e6b1SAndroid Build Coastguard Worker         self.ops.fixup_bootconfig(bootconfig, fixup_buffer)
787*5225e6b1SAndroid Build Coastguard Worker     }
788*5225e6b1SAndroid Build Coastguard Worker 
fixup_device_tree(&mut self, device_tree: &mut [u8]) -> Result<()>789*5225e6b1SAndroid Build Coastguard Worker     fn fixup_device_tree(&mut self, device_tree: &mut [u8]) -> Result<()> {
790*5225e6b1SAndroid Build Coastguard Worker         self.ops.fixup_device_tree(device_tree)
791*5225e6b1SAndroid Build Coastguard Worker     }
792*5225e6b1SAndroid Build Coastguard Worker 
select_device_trees( &mut self, components_registry: &mut DeviceTreeComponentsRegistry, ) -> Result<()>793*5225e6b1SAndroid Build Coastguard Worker     fn select_device_trees(
794*5225e6b1SAndroid Build Coastguard Worker         &mut self,
795*5225e6b1SAndroid Build Coastguard Worker         components_registry: &mut DeviceTreeComponentsRegistry,
796*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<()> {
797*5225e6b1SAndroid Build Coastguard Worker         self.ops.select_device_trees(components_registry)
798*5225e6b1SAndroid Build Coastguard Worker     }
799*5225e6b1SAndroid Build Coastguard Worker 
read_from_partition_sync( &mut self, part: &str, off: u64, out: &mut (impl SliceMaybeUninit + ?Sized), ) -> Result<()>800*5225e6b1SAndroid Build Coastguard Worker     fn read_from_partition_sync(
801*5225e6b1SAndroid Build Coastguard Worker         &mut self,
802*5225e6b1SAndroid Build Coastguard Worker         part: &str,
803*5225e6b1SAndroid Build Coastguard Worker         off: u64,
804*5225e6b1SAndroid Build Coastguard Worker         out: &mut (impl SliceMaybeUninit + ?Sized),
805*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<()> {
806*5225e6b1SAndroid Build Coastguard Worker         if part == "boot_a" {
807*5225e6b1SAndroid Build Coastguard Worker             let len = min(self.bootimg_buffer.len() - off as usize, out.len());
808*5225e6b1SAndroid Build Coastguard Worker             out.clone_from_slice(&self.bootimg_buffer[off as usize..off as usize + len]);
809*5225e6b1SAndroid Build Coastguard Worker             Ok(())
810*5225e6b1SAndroid Build Coastguard Worker         } else {
811*5225e6b1SAndroid Build Coastguard Worker             self.ops.read_from_partition_sync(part, off, out)
812*5225e6b1SAndroid Build Coastguard Worker         }
813*5225e6b1SAndroid Build Coastguard Worker     }
814*5225e6b1SAndroid Build Coastguard Worker 
avb_handle_verification_result( &mut self, color: BootStateColor, digest: Option<&CStr>, boot_os_version: Option<&[u8]>, boot_security_patch: Option<&[u8]>, system_os_version: Option<&[u8]>, system_security_patch: Option<&[u8]>, vendor_os_version: Option<&[u8]>, vendor_security_patch: Option<&[u8]>, ) -> AvbIoResult<()>815*5225e6b1SAndroid Build Coastguard Worker     fn avb_handle_verification_result(
816*5225e6b1SAndroid Build Coastguard Worker         &mut self,
817*5225e6b1SAndroid Build Coastguard Worker         color: BootStateColor,
818*5225e6b1SAndroid Build Coastguard Worker         digest: Option<&CStr>,
819*5225e6b1SAndroid Build Coastguard Worker         boot_os_version: Option<&[u8]>,
820*5225e6b1SAndroid Build Coastguard Worker         boot_security_patch: Option<&[u8]>,
821*5225e6b1SAndroid Build Coastguard Worker         system_os_version: Option<&[u8]>,
822*5225e6b1SAndroid Build Coastguard Worker         system_security_patch: Option<&[u8]>,
823*5225e6b1SAndroid Build Coastguard Worker         vendor_os_version: Option<&[u8]>,
824*5225e6b1SAndroid Build Coastguard Worker         vendor_security_patch: Option<&[u8]>,
825*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<()> {
826*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_handle_verification_result(
827*5225e6b1SAndroid Build Coastguard Worker             color,
828*5225e6b1SAndroid Build Coastguard Worker             digest,
829*5225e6b1SAndroid Build Coastguard Worker             boot_os_version,
830*5225e6b1SAndroid Build Coastguard Worker             boot_security_patch,
831*5225e6b1SAndroid Build Coastguard Worker             system_os_version,
832*5225e6b1SAndroid Build Coastguard Worker             system_security_patch,
833*5225e6b1SAndroid Build Coastguard Worker             vendor_os_version,
834*5225e6b1SAndroid Build Coastguard Worker             vendor_security_patch,
835*5225e6b1SAndroid Build Coastguard Worker         )
836*5225e6b1SAndroid Build Coastguard Worker     }
837*5225e6b1SAndroid Build Coastguard Worker 
avb_validate_vbmeta_public_key( &self, public_key: &[u8], public_key_metadata: Option<&[u8]>, ) -> AvbIoResult<KeyValidationStatus>838*5225e6b1SAndroid Build Coastguard Worker     fn avb_validate_vbmeta_public_key(
839*5225e6b1SAndroid Build Coastguard Worker         &self,
840*5225e6b1SAndroid Build Coastguard Worker         public_key: &[u8],
841*5225e6b1SAndroid Build Coastguard Worker         public_key_metadata: Option<&[u8]>,
842*5225e6b1SAndroid Build Coastguard Worker     ) -> AvbIoResult<KeyValidationStatus> {
843*5225e6b1SAndroid Build Coastguard Worker         self.ops.avb_validate_vbmeta_public_key(public_key, public_key_metadata)
844*5225e6b1SAndroid Build Coastguard Worker     }
845*5225e6b1SAndroid Build Coastguard Worker 
slots_metadata(&mut self) -> Result<SlotsMetadata>846*5225e6b1SAndroid Build Coastguard Worker     fn slots_metadata(&mut self) -> Result<SlotsMetadata> {
847*5225e6b1SAndroid Build Coastguard Worker         // Ramboot is not suppose to call this interface.
848*5225e6b1SAndroid Build Coastguard Worker         unreachable!()
849*5225e6b1SAndroid Build Coastguard Worker     }
850*5225e6b1SAndroid Build Coastguard Worker 
get_current_slot(&mut self) -> Result<Slot>851*5225e6b1SAndroid Build Coastguard Worker     fn get_current_slot(&mut self) -> Result<Slot> {
852*5225e6b1SAndroid Build Coastguard Worker         // Ramboot is slotless
853*5225e6b1SAndroid Build Coastguard Worker         Err(Error::Unsupported)
854*5225e6b1SAndroid Build Coastguard Worker     }
855*5225e6b1SAndroid Build Coastguard Worker 
get_next_slot(&mut self, _: bool) -> Result<Slot>856*5225e6b1SAndroid Build Coastguard Worker     fn get_next_slot(&mut self, _: bool) -> Result<Slot> {
857*5225e6b1SAndroid Build Coastguard Worker         // Ramboot is not suppose to call this interface.
858*5225e6b1SAndroid Build Coastguard Worker         unreachable!()
859*5225e6b1SAndroid Build Coastguard Worker     }
860*5225e6b1SAndroid Build Coastguard Worker 
set_active_slot(&mut self, _: u8) -> Result<()>861*5225e6b1SAndroid Build Coastguard Worker     fn set_active_slot(&mut self, _: u8) -> Result<()> {
862*5225e6b1SAndroid Build Coastguard Worker         // Ramboot is not suppose to call this interface.
863*5225e6b1SAndroid Build Coastguard Worker         unreachable!()
864*5225e6b1SAndroid Build Coastguard Worker     }
865*5225e6b1SAndroid Build Coastguard Worker 
set_reboot_reason(&mut self, _: RebootReason) -> Result<()>866*5225e6b1SAndroid Build Coastguard Worker     fn set_reboot_reason(&mut self, _: RebootReason) -> Result<()> {
867*5225e6b1SAndroid Build Coastguard Worker         // Ramboot is not suppose to call this interface.
868*5225e6b1SAndroid Build Coastguard Worker         unreachable!()
869*5225e6b1SAndroid Build Coastguard Worker     }
870*5225e6b1SAndroid Build Coastguard Worker 
get_reboot_reason(&mut self) -> Result<RebootReason>871*5225e6b1SAndroid Build Coastguard Worker     fn get_reboot_reason(&mut self) -> Result<RebootReason> {
872*5225e6b1SAndroid Build Coastguard Worker         // Assumes that ramboot use normal boot mode. But we might consider supporting recovery
873*5225e6b1SAndroid Build Coastguard Worker         // if there is a usecase.
874*5225e6b1SAndroid Build Coastguard Worker         Ok(RebootReason::Normal)
875*5225e6b1SAndroid Build Coastguard Worker     }
876*5225e6b1SAndroid Build Coastguard Worker 
fastboot_variable<'arg>( &mut self, _: &CStr, _: impl Iterator<Item = &'arg CStr> + Clone, _: &mut [u8], ) -> Result<usize>877*5225e6b1SAndroid Build Coastguard Worker     fn fastboot_variable<'arg>(
878*5225e6b1SAndroid Build Coastguard Worker         &mut self,
879*5225e6b1SAndroid Build Coastguard Worker         _: &CStr,
880*5225e6b1SAndroid Build Coastguard Worker         _: impl Iterator<Item = &'arg CStr> + Clone,
881*5225e6b1SAndroid Build Coastguard Worker         _: &mut [u8],
882*5225e6b1SAndroid Build Coastguard Worker     ) -> Result<usize> {
883*5225e6b1SAndroid Build Coastguard Worker         // Ramboot should not need this.
884*5225e6b1SAndroid Build Coastguard Worker         unreachable!();
885*5225e6b1SAndroid Build Coastguard Worker     }
886*5225e6b1SAndroid Build Coastguard Worker 
fastboot_visit_all_variables(&mut self, _: impl FnMut(&[&CStr], &CStr)) -> Result<()>887*5225e6b1SAndroid Build Coastguard Worker     fn fastboot_visit_all_variables(&mut self, _: impl FnMut(&[&CStr], &CStr)) -> Result<()> {
888*5225e6b1SAndroid Build Coastguard Worker         // Ramboot should not need this.
889*5225e6b1SAndroid Build Coastguard Worker         unreachable!();
890*5225e6b1SAndroid Build Coastguard Worker     }
891*5225e6b1SAndroid Build Coastguard Worker }
892*5225e6b1SAndroid Build Coastguard Worker 
893*5225e6b1SAndroid Build Coastguard Worker #[cfg(test)]
894*5225e6b1SAndroid Build Coastguard Worker mod test {
895*5225e6b1SAndroid Build Coastguard Worker     use super::*;
896*5225e6b1SAndroid Build Coastguard Worker     use efi_mocks::{
897*5225e6b1SAndroid Build Coastguard Worker         protocol::{gbl_efi_ab_slot::GblSlotProtocol, gbl_efi_avb::GblAvbProtocol},
898*5225e6b1SAndroid Build Coastguard Worker         MockEfi,
899*5225e6b1SAndroid Build Coastguard Worker     };
900*5225e6b1SAndroid Build Coastguard Worker     use efi_types::GBL_EFI_BOOT_REASON;
901*5225e6b1SAndroid Build Coastguard Worker     use mockall::predicate::eq;
902*5225e6b1SAndroid Build Coastguard Worker 
903*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_write_trait()904*5225e6b1SAndroid Build Coastguard Worker     fn ops_write_trait() {
905*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
906*5225e6b1SAndroid Build Coastguard Worker 
907*5225e6b1SAndroid Build Coastguard Worker         mock_efi.con_out.expect_write_str().with(eq("foo bar")).return_const(Ok(()));
908*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
909*5225e6b1SAndroid Build Coastguard Worker 
910*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
911*5225e6b1SAndroid Build Coastguard Worker 
912*5225e6b1SAndroid Build Coastguard Worker         assert!(write!(&mut ops, "{} {}", "foo", "bar").is_ok());
913*5225e6b1SAndroid Build Coastguard Worker     }
914*5225e6b1SAndroid Build Coastguard Worker 
915*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_validate_vbmeta_public_key_returns_valid()916*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_validate_vbmeta_public_key_returns_valid() {
917*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
918*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
919*5225e6b1SAndroid Build Coastguard Worker         avb.validate_vbmeta_public_key_result =
920*5225e6b1SAndroid Build Coastguard Worker             Some(Ok(efi_types::GBL_EFI_AVB_KEY_VALIDATION_STATUS_VALID));
921*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
922*5225e6b1SAndroid Build Coastguard Worker 
923*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
924*5225e6b1SAndroid Build Coastguard Worker         let ops = Ops::new(installed.entry(), &[], None);
925*5225e6b1SAndroid Build Coastguard Worker 
926*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_validate_vbmeta_public_key(&[], None), Ok(KeyValidationStatus::Valid));
927*5225e6b1SAndroid Build Coastguard Worker     }
928*5225e6b1SAndroid Build Coastguard Worker 
929*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_validate_vbmeta_public_key_returns_valid_custom_key()930*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_validate_vbmeta_public_key_returns_valid_custom_key() {
931*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
932*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
933*5225e6b1SAndroid Build Coastguard Worker         avb.validate_vbmeta_public_key_result =
934*5225e6b1SAndroid Build Coastguard Worker             Some(Ok(efi_types::GBL_EFI_AVB_KEY_VALIDATION_STATUS_VALID_CUSTOM_KEY));
935*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
936*5225e6b1SAndroid Build Coastguard Worker 
937*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
938*5225e6b1SAndroid Build Coastguard Worker         let ops = Ops::new(installed.entry(), &[], None);
939*5225e6b1SAndroid Build Coastguard Worker 
940*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(
941*5225e6b1SAndroid Build Coastguard Worker             ops.avb_validate_vbmeta_public_key(&[], None),
942*5225e6b1SAndroid Build Coastguard Worker             Ok(KeyValidationStatus::ValidCustomKey)
943*5225e6b1SAndroid Build Coastguard Worker         );
944*5225e6b1SAndroid Build Coastguard Worker     }
945*5225e6b1SAndroid Build Coastguard Worker 
946*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_validate_vbmeta_public_key_returns_invalid()947*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_validate_vbmeta_public_key_returns_invalid() {
948*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
949*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
950*5225e6b1SAndroid Build Coastguard Worker         avb.validate_vbmeta_public_key_result =
951*5225e6b1SAndroid Build Coastguard Worker             Some(Ok(efi_types::GBL_EFI_AVB_KEY_VALIDATION_STATUS_INVALID));
952*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
953*5225e6b1SAndroid Build Coastguard Worker 
954*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
955*5225e6b1SAndroid Build Coastguard Worker         let ops = Ops::new(installed.entry(), &[], None);
956*5225e6b1SAndroid Build Coastguard Worker 
957*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_validate_vbmeta_public_key(&[], None), Ok(KeyValidationStatus::Invalid));
958*5225e6b1SAndroid Build Coastguard Worker     }
959*5225e6b1SAndroid Build Coastguard Worker 
960*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_validate_vbmeta_public_key_failed_error_mapped()961*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_validate_vbmeta_public_key_failed_error_mapped() {
962*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
963*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
964*5225e6b1SAndroid Build Coastguard Worker         avb.validate_vbmeta_public_key_result = Some(Err(Error::OutOfResources));
965*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
966*5225e6b1SAndroid Build Coastguard Worker 
967*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
968*5225e6b1SAndroid Build Coastguard Worker         let ops = Ops::new(installed.entry(), &[], None);
969*5225e6b1SAndroid Build Coastguard Worker 
970*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_validate_vbmeta_public_key(&[], None), Err(AvbIoError::Oom));
971*5225e6b1SAndroid Build Coastguard Worker     }
972*5225e6b1SAndroid Build Coastguard Worker 
973*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_validate_vbmeta_public_key_protocol_not_found_mapped_to_not_implemented()974*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_validate_vbmeta_public_key_protocol_not_found_mapped_to_not_implemented() {
975*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
976*5225e6b1SAndroid Build Coastguard Worker         mock_efi
977*5225e6b1SAndroid Build Coastguard Worker             .boot_services
978*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
979*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
980*5225e6b1SAndroid Build Coastguard Worker 
981*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
982*5225e6b1SAndroid Build Coastguard Worker         let ops = Ops::new(installed.entry(), &[], None);
983*5225e6b1SAndroid Build Coastguard Worker 
984*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_validate_vbmeta_public_key(&[], None), Err(AvbIoError::NotImplemented));
985*5225e6b1SAndroid Build Coastguard Worker     }
986*5225e6b1SAndroid Build Coastguard Worker 
987*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_is_device_unlocked_returns_true()988*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_is_device_unlocked_returns_true() {
989*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
990*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
991*5225e6b1SAndroid Build Coastguard Worker         avb.read_is_device_unlocked_result = Some(Ok(true));
992*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
993*5225e6b1SAndroid Build Coastguard Worker 
994*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
995*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
996*5225e6b1SAndroid Build Coastguard Worker 
997*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_is_device_unlocked(), Ok(true));
998*5225e6b1SAndroid Build Coastguard Worker     }
999*5225e6b1SAndroid Build Coastguard Worker 
1000*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_is_device_unlocked_returns_false()1001*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_is_device_unlocked_returns_false() {
1002*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1003*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1004*5225e6b1SAndroid Build Coastguard Worker         avb.read_is_device_unlocked_result = Some(Ok(false));
1005*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1006*5225e6b1SAndroid Build Coastguard Worker 
1007*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1008*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1009*5225e6b1SAndroid Build Coastguard Worker 
1010*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_is_device_unlocked(), Ok(false));
1011*5225e6b1SAndroid Build Coastguard Worker     }
1012*5225e6b1SAndroid Build Coastguard Worker 
1013*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_is_device_unlocked_protocol_not_found()1014*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_is_device_unlocked_protocol_not_found() {
1015*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1016*5225e6b1SAndroid Build Coastguard Worker         mock_efi
1017*5225e6b1SAndroid Build Coastguard Worker             .boot_services
1018*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
1019*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
1020*5225e6b1SAndroid Build Coastguard Worker 
1021*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1022*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1023*5225e6b1SAndroid Build Coastguard Worker 
1024*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_is_device_unlocked(), Err(AvbIoError::NotImplemented));
1025*5225e6b1SAndroid Build Coastguard Worker     }
1026*5225e6b1SAndroid Build Coastguard Worker 
1027*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_rollback_index_success()1028*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_rollback_index_success() {
1029*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1030*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1031*5225e6b1SAndroid Build Coastguard Worker         avb.read_rollback_index_result = Some(Ok(12345));
1032*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1033*5225e6b1SAndroid Build Coastguard Worker 
1034*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1035*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1036*5225e6b1SAndroid Build Coastguard Worker 
1037*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_rollback_index(0), Ok(12345));
1038*5225e6b1SAndroid Build Coastguard Worker     }
1039*5225e6b1SAndroid Build Coastguard Worker 
1040*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_rollback_index_error()1041*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_rollback_index_error() {
1042*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1043*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1044*5225e6b1SAndroid Build Coastguard Worker         avb.read_rollback_index_result = Some(Err(Error::OutOfResources));
1045*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1046*5225e6b1SAndroid Build Coastguard Worker 
1047*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1048*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1049*5225e6b1SAndroid Build Coastguard Worker 
1050*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_rollback_index(0), Err(AvbIoError::Oom));
1051*5225e6b1SAndroid Build Coastguard Worker     }
1052*5225e6b1SAndroid Build Coastguard Worker 
1053*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_rollback_index_protocol_not_found()1054*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_rollback_index_protocol_not_found() {
1055*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1056*5225e6b1SAndroid Build Coastguard Worker         mock_efi
1057*5225e6b1SAndroid Build Coastguard Worker             .boot_services
1058*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
1059*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
1060*5225e6b1SAndroid Build Coastguard Worker 
1061*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1062*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1063*5225e6b1SAndroid Build Coastguard Worker 
1064*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_rollback_index(0), Err(AvbIoError::NotImplemented));
1065*5225e6b1SAndroid Build Coastguard Worker     }
1066*5225e6b1SAndroid Build Coastguard Worker 
1067*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_write_rollback_index_success()1068*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_write_rollback_index_success() {
1069*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1070*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1071*5225e6b1SAndroid Build Coastguard Worker         avb.write_rollback_index_result = Some(Ok(()));
1072*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1073*5225e6b1SAndroid Build Coastguard Worker 
1074*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1075*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1076*5225e6b1SAndroid Build Coastguard Worker 
1077*5225e6b1SAndroid Build Coastguard Worker         assert!(ops.avb_write_rollback_index(0, 12345).is_ok());
1078*5225e6b1SAndroid Build Coastguard Worker     }
1079*5225e6b1SAndroid Build Coastguard Worker 
1080*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_write_rollback_index_error()1081*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_write_rollback_index_error() {
1082*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1083*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1084*5225e6b1SAndroid Build Coastguard Worker         avb.write_rollback_index_result = Some(Err(Error::InvalidInput));
1085*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1086*5225e6b1SAndroid Build Coastguard Worker 
1087*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1088*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1089*5225e6b1SAndroid Build Coastguard Worker 
1090*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_write_rollback_index(0, 12345), Err(AvbIoError::InvalidValueSize));
1091*5225e6b1SAndroid Build Coastguard Worker     }
1092*5225e6b1SAndroid Build Coastguard Worker 
1093*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_write_rollback_index_protocol_not_found()1094*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_write_rollback_index_protocol_not_found() {
1095*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1096*5225e6b1SAndroid Build Coastguard Worker         mock_efi
1097*5225e6b1SAndroid Build Coastguard Worker             .boot_services
1098*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
1099*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
1100*5225e6b1SAndroid Build Coastguard Worker 
1101*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1102*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1103*5225e6b1SAndroid Build Coastguard Worker 
1104*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_write_rollback_index(0, 12345), Err(AvbIoError::NotImplemented));
1105*5225e6b1SAndroid Build Coastguard Worker     }
1106*5225e6b1SAndroid Build Coastguard Worker 
1107*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_persistent_value_success()1108*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_persistent_value_success() {
1109*5225e6b1SAndroid Build Coastguard Worker         const EXPECTED_LEN: usize = 4;
1110*5225e6b1SAndroid Build Coastguard Worker 
1111*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1112*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1113*5225e6b1SAndroid Build Coastguard Worker         avb.read_persistent_value_result = Some(Ok(EXPECTED_LEN));
1114*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1115*5225e6b1SAndroid Build Coastguard Worker 
1116*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1117*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1118*5225e6b1SAndroid Build Coastguard Worker 
1119*5225e6b1SAndroid Build Coastguard Worker         let mut buffer = [0u8; EXPECTED_LEN];
1120*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_persistent_value(c"test", &mut buffer), Ok(EXPECTED_LEN));
1121*5225e6b1SAndroid Build Coastguard Worker     }
1122*5225e6b1SAndroid Build Coastguard Worker 
1123*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_persistent_value_error()1124*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_persistent_value_error() {
1125*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1126*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1127*5225e6b1SAndroid Build Coastguard Worker         avb.read_persistent_value_result = Some(Err(Error::OutOfResources));
1128*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1129*5225e6b1SAndroid Build Coastguard Worker 
1130*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1131*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1132*5225e6b1SAndroid Build Coastguard Worker 
1133*5225e6b1SAndroid Build Coastguard Worker         let mut buffer = [0u8; 0];
1134*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_read_persistent_value(c"test", &mut buffer), Err(AvbIoError::Oom));
1135*5225e6b1SAndroid Build Coastguard Worker     }
1136*5225e6b1SAndroid Build Coastguard Worker 
1137*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_read_persistent_value_protocol_not_found()1138*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_read_persistent_value_protocol_not_found() {
1139*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1140*5225e6b1SAndroid Build Coastguard Worker         mock_efi
1141*5225e6b1SAndroid Build Coastguard Worker             .boot_services
1142*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
1143*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
1144*5225e6b1SAndroid Build Coastguard Worker 
1145*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1146*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1147*5225e6b1SAndroid Build Coastguard Worker 
1148*5225e6b1SAndroid Build Coastguard Worker         let mut buffer = [0u8; 0];
1149*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(
1150*5225e6b1SAndroid Build Coastguard Worker             ops.avb_read_persistent_value(c"test", &mut buffer),
1151*5225e6b1SAndroid Build Coastguard Worker             Err(AvbIoError::NotImplemented)
1152*5225e6b1SAndroid Build Coastguard Worker         );
1153*5225e6b1SAndroid Build Coastguard Worker     }
1154*5225e6b1SAndroid Build Coastguard Worker 
1155*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_write_persistent_value_success()1156*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_write_persistent_value_success() {
1157*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1158*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1159*5225e6b1SAndroid Build Coastguard Worker         avb.write_persistent_value_result = Some(Ok(()));
1160*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1161*5225e6b1SAndroid Build Coastguard Worker 
1162*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1163*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1164*5225e6b1SAndroid Build Coastguard Worker 
1165*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_write_persistent_value(c"test", b""), Ok(()));
1166*5225e6b1SAndroid Build Coastguard Worker     }
1167*5225e6b1SAndroid Build Coastguard Worker 
1168*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_write_persistent_value_error()1169*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_write_persistent_value_error() {
1170*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1171*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1172*5225e6b1SAndroid Build Coastguard Worker         avb.write_persistent_value_result = Some(Err(Error::InvalidInput));
1173*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1174*5225e6b1SAndroid Build Coastguard Worker 
1175*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1176*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1177*5225e6b1SAndroid Build Coastguard Worker 
1178*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_write_persistent_value(c"test", b""), Err(AvbIoError::InvalidValueSize));
1179*5225e6b1SAndroid Build Coastguard Worker     }
1180*5225e6b1SAndroid Build Coastguard Worker 
1181*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_write_persistent_value_protocol_not_found()1182*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_write_persistent_value_protocol_not_found() {
1183*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1184*5225e6b1SAndroid Build Coastguard Worker         mock_efi
1185*5225e6b1SAndroid Build Coastguard Worker             .boot_services
1186*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
1187*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
1188*5225e6b1SAndroid Build Coastguard Worker 
1189*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1190*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1191*5225e6b1SAndroid Build Coastguard Worker 
1192*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_write_persistent_value(c"test", b""), Err(AvbIoError::NotImplemented));
1193*5225e6b1SAndroid Build Coastguard Worker     }
1194*5225e6b1SAndroid Build Coastguard Worker 
1195*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_erase_persistent_value_success()1196*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_erase_persistent_value_success() {
1197*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1198*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1199*5225e6b1SAndroid Build Coastguard Worker         avb.write_persistent_value_result = Some(Ok(()));
1200*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1201*5225e6b1SAndroid Build Coastguard Worker 
1202*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1203*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1204*5225e6b1SAndroid Build Coastguard Worker 
1205*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_erase_persistent_value(c"test"), Ok(()));
1206*5225e6b1SAndroid Build Coastguard Worker     }
1207*5225e6b1SAndroid Build Coastguard Worker 
1208*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_erase_persistent_value_error()1209*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_erase_persistent_value_error() {
1210*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1211*5225e6b1SAndroid Build Coastguard Worker         let mut avb = GblAvbProtocol::default();
1212*5225e6b1SAndroid Build Coastguard Worker         avb.write_persistent_value_result = Some(Err(Error::DeviceError));
1213*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblAvbProtocol>().return_const(Ok(avb));
1214*5225e6b1SAndroid Build Coastguard Worker 
1215*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1216*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1217*5225e6b1SAndroid Build Coastguard Worker 
1218*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_erase_persistent_value(c"test"), Err(AvbIoError::Io));
1219*5225e6b1SAndroid Build Coastguard Worker     }
1220*5225e6b1SAndroid Build Coastguard Worker 
1221*5225e6b1SAndroid Build Coastguard Worker     #[test]
ops_avb_erase_persistent_value_protocol_not_found()1222*5225e6b1SAndroid Build Coastguard Worker     fn ops_avb_erase_persistent_value_protocol_not_found() {
1223*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1224*5225e6b1SAndroid Build Coastguard Worker         mock_efi
1225*5225e6b1SAndroid Build Coastguard Worker             .boot_services
1226*5225e6b1SAndroid Build Coastguard Worker             .expect_find_first_and_open::<GblAvbProtocol>()
1227*5225e6b1SAndroid Build Coastguard Worker             .returning(|| Err(Error::NotFound));
1228*5225e6b1SAndroid Build Coastguard Worker 
1229*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1230*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1231*5225e6b1SAndroid Build Coastguard Worker 
1232*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.avb_erase_persistent_value(c"test"), Err(AvbIoError::NotImplemented));
1233*5225e6b1SAndroid Build Coastguard Worker     }
1234*5225e6b1SAndroid Build Coastguard Worker 
1235*5225e6b1SAndroid Build Coastguard Worker     /// Helper for testing `set_boot_reason`
test_set_reboot_reason(input: RebootReason, expect: GBL_EFI_BOOT_REASON)1236*5225e6b1SAndroid Build Coastguard Worker     fn test_set_reboot_reason(input: RebootReason, expect: GBL_EFI_BOOT_REASON) {
1237*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1238*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblSlotProtocol>().times(1).returning(
1239*5225e6b1SAndroid Build Coastguard Worker             move || {
1240*5225e6b1SAndroid Build Coastguard Worker                 let mut slot = GblSlotProtocol::default();
1241*5225e6b1SAndroid Build Coastguard Worker                 slot.expect_set_boot_reason().times(1).returning(move |reason, _| {
1242*5225e6b1SAndroid Build Coastguard Worker                     assert_eq!(reason, expect);
1243*5225e6b1SAndroid Build Coastguard Worker                     Ok(())
1244*5225e6b1SAndroid Build Coastguard Worker                 });
1245*5225e6b1SAndroid Build Coastguard Worker                 Ok(slot)
1246*5225e6b1SAndroid Build Coastguard Worker             },
1247*5225e6b1SAndroid Build Coastguard Worker         );
1248*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1249*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1250*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.set_reboot_reason(input), Ok(()));
1251*5225e6b1SAndroid Build Coastguard Worker     }
1252*5225e6b1SAndroid Build Coastguard Worker 
1253*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_set_reboot_reason_normal()1254*5225e6b1SAndroid Build Coastguard Worker     fn test_set_reboot_reason_normal() {
1255*5225e6b1SAndroid Build Coastguard Worker         test_set_reboot_reason(RebootReason::Normal, GBL_EFI_BOOT_REASON_COLD);
1256*5225e6b1SAndroid Build Coastguard Worker     }
1257*5225e6b1SAndroid Build Coastguard Worker 
1258*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_set_reboot_reason_recovery()1259*5225e6b1SAndroid Build Coastguard Worker     fn test_set_reboot_reason_recovery() {
1260*5225e6b1SAndroid Build Coastguard Worker         test_set_reboot_reason(RebootReason::Recovery, GBL_EFI_BOOT_REASON_RECOVERY);
1261*5225e6b1SAndroid Build Coastguard Worker     }
1262*5225e6b1SAndroid Build Coastguard Worker 
1263*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_set_reboot_reason_bootloader()1264*5225e6b1SAndroid Build Coastguard Worker     fn test_set_reboot_reason_bootloader() {
1265*5225e6b1SAndroid Build Coastguard Worker         test_set_reboot_reason(RebootReason::Bootloader, GBL_EFI_BOOT_REASON_BOOTLOADER);
1266*5225e6b1SAndroid Build Coastguard Worker     }
1267*5225e6b1SAndroid Build Coastguard Worker 
1268*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_set_reboot_reason_fastbootd()1269*5225e6b1SAndroid Build Coastguard Worker     fn test_set_reboot_reason_fastbootd() {
1270*5225e6b1SAndroid Build Coastguard Worker         test_set_reboot_reason(RebootReason::FastbootD, GBL_EFI_BOOT_REASON_FASTBOOTD);
1271*5225e6b1SAndroid Build Coastguard Worker     }
1272*5225e6b1SAndroid Build Coastguard Worker 
1273*5225e6b1SAndroid Build Coastguard Worker     /// Helper for testing `get_boot_reason`
test_get_reboot_reason(input: GBL_EFI_BOOT_REASON, expect: RebootReason)1274*5225e6b1SAndroid Build Coastguard Worker     fn test_get_reboot_reason(input: GBL_EFI_BOOT_REASON, expect: RebootReason) {
1275*5225e6b1SAndroid Build Coastguard Worker         let mut mock_efi = MockEfi::new();
1276*5225e6b1SAndroid Build Coastguard Worker         mock_efi.boot_services.expect_find_first_and_open::<GblSlotProtocol>().times(1).returning(
1277*5225e6b1SAndroid Build Coastguard Worker             move || {
1278*5225e6b1SAndroid Build Coastguard Worker                 let mut slot = GblSlotProtocol::default();
1279*5225e6b1SAndroid Build Coastguard Worker                 slot.expect_get_boot_reason().times(1).returning(move |_| Ok((input, 0)));
1280*5225e6b1SAndroid Build Coastguard Worker                 Ok(slot)
1281*5225e6b1SAndroid Build Coastguard Worker             },
1282*5225e6b1SAndroid Build Coastguard Worker         );
1283*5225e6b1SAndroid Build Coastguard Worker         let installed = mock_efi.install();
1284*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(installed.entry(), &[], None);
1285*5225e6b1SAndroid Build Coastguard Worker         assert_eq!(ops.get_reboot_reason().unwrap(), expect)
1286*5225e6b1SAndroid Build Coastguard Worker     }
1287*5225e6b1SAndroid Build Coastguard Worker 
1288*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_get_reboot_reason_normal()1289*5225e6b1SAndroid Build Coastguard Worker     fn test_get_reboot_reason_normal() {
1290*5225e6b1SAndroid Build Coastguard Worker         test_get_reboot_reason(GBL_EFI_BOOT_REASON_COLD, RebootReason::Normal);
1291*5225e6b1SAndroid Build Coastguard Worker     }
1292*5225e6b1SAndroid Build Coastguard Worker 
1293*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_get_reboot_reason_recovery()1294*5225e6b1SAndroid Build Coastguard Worker     fn test_get_reboot_reason_recovery() {
1295*5225e6b1SAndroid Build Coastguard Worker         test_get_reboot_reason(GBL_EFI_BOOT_REASON_RECOVERY, RebootReason::Recovery);
1296*5225e6b1SAndroid Build Coastguard Worker     }
1297*5225e6b1SAndroid Build Coastguard Worker 
1298*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_get_reboot_reason_bootloader()1299*5225e6b1SAndroid Build Coastguard Worker     fn test_get_reboot_reason_bootloader() {
1300*5225e6b1SAndroid Build Coastguard Worker         test_get_reboot_reason(GBL_EFI_BOOT_REASON_BOOTLOADER, RebootReason::Bootloader);
1301*5225e6b1SAndroid Build Coastguard Worker     }
1302*5225e6b1SAndroid Build Coastguard Worker 
1303*5225e6b1SAndroid Build Coastguard Worker     #[test]
test_get_reboot_reason_fastbootd()1304*5225e6b1SAndroid Build Coastguard Worker     fn test_get_reboot_reason_fastbootd() {
1305*5225e6b1SAndroid Build Coastguard Worker         test_get_reboot_reason(GBL_EFI_BOOT_REASON_FASTBOOTD, RebootReason::FastbootD);
1306*5225e6b1SAndroid Build Coastguard Worker     }
1307*5225e6b1SAndroid Build Coastguard Worker }
1308