blob: d4313baf5da676d26061590cfa0397584572f4fe [file]
// Copyright 2023, 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.
//! This EFI application implements a demo for booting Android/Fuchsia from disk. See
//! bootable/libbootloader/gbl/README.md for how to run the demo. See comments of
//! `android_boot:android_boot_demo()` and `fuchsia_boot:fuchsia_boot_demo()` for
//! supported/unsupported features at the moment.
#![cfg_attr(not(test), no_std)]
// For the `vec!` macro
#[macro_use]
extern crate alloc;
mod efi_blocks;
mod error;
mod ops;
#[macro_use]
mod utils;
// Currently un-testable modules.
//
// The libefi API surface is large and complex; rather than trying to mock it all out at once, we
// will selectively enable modules for test as they become mockable.
#[cfg(not(test))]
mod android_boot;
#[cfg(not(test))]
mod fastboot;
#[cfg(not(test))]
mod fuchsia_boot;
#[cfg(not(test))]
mod net;
// In tests, map the `efi_mocks` module as `efi`. This allows other modules to `use crate::efi`
// and automatically pick up the correct one.
#[cfg(not(test))]
pub(crate) use efi;
#[cfg(test)]
pub(crate) use efi_mocks as efi;
#[cfg(not(test))]
use {
core::fmt::Write,
efi::{efi_print, efi_println, EfiEntry},
libgbl::Result,
utils::loaded_image_path,
};
#[cfg(not(test))]
enum TargetOs {
Android,
Fuchsia,
}
#[cfg(not(test))]
fn get_target_os(entry: &EfiEntry) -> TargetOs {
let mut buf = [0u8; 1];
if entry
.system_table()
.runtime_services()
.get_variable(&efi::GBL_EFI_VENDOR_GUID, efi::GBL_EFI_OS_BOOT_TARGET_VARNAME, &mut buf)
.is_ok()
{
efi_println!(
entry,
"`{}` is set. Proceeding as Fuchsia.",
efi::GBL_EFI_OS_BOOT_TARGET_VARNAME
);
TargetOs::Fuchsia
} else if fuchsia_boot::is_fuchsia_gpt(&entry).is_ok() {
efi_println!(entry, "Partition layout looks like Fuchsia. Proceeding as Fuchsia");
TargetOs::Fuchsia
} else {
efi_println!(entry, "Proceeding as Android");
TargetOs::Android
}
}
/// GBL EFI application logic entry point.
#[cfg(not(test))]
pub fn app_main(entry: EfiEntry) -> Result<()> {
efi_println!(entry, "****Generic Bootloader Application****");
if let Ok(v) = loaded_image_path(&entry) {
efi_println!(entry, "Image path: {}", v);
}
match get_target_os(&entry) {
TargetOs::Fuchsia => fuchsia_boot::fuchsia_boot_demo(entry)?,
TargetOs::Android => android_boot::android_boot_demo(entry)?,
}
Ok(())
}