blob: cfcbed9ca23b406f72f9c66215b5510730a46dad [file]
// Copyright 2024, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Mock protocols.
//!
//! The structure of these sub-modules must match the libefi structure so that the code can refer
//! to either one using the same path.
use crate::{DeviceHandle, MOCK_EFI};
use core::ffi::CStr;
use core::fmt::Write;
use efi::protocol::gbl_efi_image_loading::EfiImageBuffer;
use efi_types::{
EfiInputKey, GblEfiAvbVerificationResult, GblEfiImageInfo, GblEfiPartitionName,
GblEfiVerifiedDeviceTree,
};
use liberror::Result;
use mockall::mock;
/// Mock device_path module.
pub mod device_path {
use super::*;
mock! {
/// Mock [efi::DevicePathProtocol].
pub DevicePathProtocol {}
}
/// Map to the libefi name so code under test can just use one name.
pub type DevicePathProtocol = MockDevicePathProtocol;
mock! {
/// Mock [efi::DevicePathToTextProtocol].
pub DevicePathToTextProtocol {
/// Returns a [MockDevicePathText].
///
/// Lifetimes are a little difficult to mock perfectly, so here we can only allow a
/// `'static` return value.
pub fn convert_device_path_to_text(
&self,
device_path: &MockDevicePathProtocol,
display_only: bool,
allow_shortcuts: bool,
) -> Result<MockDevicePathText<'static>>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type DevicePathToTextProtocol = MockDevicePathToTextProtocol;
mock! {
/// Mock [efi::DevicePathText].
pub DevicePathText<'a> {
/// Returns the text, which is data-only so isn't mocked.
pub fn text(&self) -> Option<&'a [u16]>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type DevicePathText<'a> = MockDevicePathText<'a>;
}
/// Mock loaded_image protocol.
pub mod loaded_image {
use super::*;
mock! {
/// Mock [efi::LoadedImageProtocol].
pub LoadedImageProtocol {
/// Returns a real [efi::DeviceHandle], which is data-only so isn't mocked.
pub fn device_handle(&self) -> Result<DeviceHandle>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type LoadedImageProtocol = MockLoadedImageProtocol;
}
/// Mock simple_text_input module.
pub mod simple_text_input {
use super::*;
mock! {
/// Mock [efi::SimpleTextInputProtocol].
pub SimpleTextInputProtocol {
/// Returns an [EfiInputKey], which is data-only so isn't mocked.
pub fn read_key_stroke(&self) -> Result<Option<EfiInputKey>>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type SimpleTextInputProtocol = MockSimpleTextInputProtocol;
}
/// Mock simple_text_output module.
pub mod simple_text_output {
use super::*;
mock! {
/// Mock [efi::SimpleTextOutputProtocol].
pub SimpleTextOutputProtocol {}
impl Write for SimpleTextOutputProtocol {
fn write_str(&mut self, s: &str) -> core::fmt::Result;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type SimpleTextOutputProtocol = MockSimpleTextOutputProtocol;
/// Returns a [MockSimpleTextOutputProtocol] that forwards all calls to `MOCK_EFI`.
pub fn passthrough_con_out() -> MockSimpleTextOutputProtocol {
let mut con_out = MockSimpleTextOutputProtocol::default();
con_out.expect_write_str().returning(|s| {
MOCK_EFI.with_borrow_mut(|efi| efi.as_mut().unwrap().con_out.write_str(s))
});
con_out
}
/// While this mock itself isn't necessarily thread-local, passing through to the thread-local
/// state is our primary use case, so we just disallow [Send] entirely.
impl !Send for MockSimpleTextOutputProtocol {}
}
/// Mock image_loading protocol.
pub mod gbl_efi_image_loading {
use super::*;
mock! {
/// Mock [efi::ImageLoadingProtocol].
pub GblImageLoadingProtocol {
/// Returns [EfiImageBuffer] matching `gbl_image_info`
pub fn get_buffer(&self, gbl_image_info: &GblEfiImageInfo) -> Result<EfiImageBuffer>;
/// Returns number of partitions to be provided via `get_verify_partitions()`, and thus
/// expected size of `partition_name` slice.
pub fn get_verify_partitions_count(&self) -> Result<usize>;
/// Returns number of partition names written to `partition_name` slice.
pub fn get_verify_partitions(
&self,
partition_names: &mut [GblEfiPartitionName]
) -> Result<usize>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type GblImageLoadingProtocol = MockGblImageLoadingProtocol;
}
/// Mock os_configuration protocol.
pub mod gbl_efi_os_configuration {
use super::*;
mock! {
/// Mock [efi::OsConfigurationProtocol].
pub GblOsConfigurationProtocol {
/// Wraps `GBL_EFI_OS_CONFIGURATION_PROTOCOL.fixup_kernel_commandline()`
pub fn fixup_kernel_commandline(
&self,
commandline: &CStr,
fixup: &[u8],
) -> Result<()>;
/// Wraps `GBL_EFI_OS_CONFIGURATION_PROTOCOL.fixup_bootconfig()`
pub fn fixup_bootconfig(
&self,
bootconfig: &[u8],
fixup: &mut [u8],
) -> Result<usize>;
/// Wraps `GBL_EFI_OS_CONFIGURATION_PROTOCOL.select_device_trees()`
pub fn select_device_trees(
&self,
components: &mut [GblEfiVerifiedDeviceTree],
) -> Result<()>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type GblOsConfigurationProtocol = MockGblOsConfigurationProtocol;
}
/// Mock dt_fixup protocol.
pub mod dt_fixup {
use super::*;
mock! {
/// Mock [efi::DtFixupProtocol].
pub DtFixupProtocol {
/// Wraps `EFI_DT_FIXUP_PROTOCOL.fixup()`
pub fn fixup(&self, device_tree: &mut [u8]) -> Result<()>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type DtFixupProtocol = MockDtFixupProtocol;
}
/// Mock avb protocol.
pub mod gbl_efi_avb {
use super::*;
mock! {
/// Mock [efi::GblAvbProtocol].
pub GblAvbProtocol {
/// Wraps `GBL_EFI_AVB_PROTOCOL.handle_verification_result()`.
pub fn handle_verification_result(
&self,
verification_result: &GblEfiAvbVerificationResult,
) -> Result<()>;
}
}
/// Map to the libefi name so code under test can just use one name.
pub type GblAvbProtocol = MockGblAvbProtocol;
}