1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // This EFI application implements a demo for booting Android/Fuchsia from disk. See
16 // bootable/libbootloader/gbl/README.md for how to run the demo. See comments of
17 // `android_boot:android_boot_demo()` and `fuchsia_boot:fuchsia_boot_demo()` for
18 // supported/unsupported features at the moment.
19 
20 #![no_std]
21 #![no_main]
22 
23 // For the `vec!` macro
24 #[macro_use]
25 extern crate alloc;
26 use core::fmt::Write;
27 
28 use efi::defs::EfiSystemTable;
29 use efi::protocol::android_boot::AndroidBootProtocol;
30 use efi::{efi_print, efi_println, initialize};
31 
32 #[macro_use]
33 mod utils;
34 use error::Result;
35 use utils::{loaded_image_path, wait_key_stroke};
36 
37 #[cfg(target_arch = "riscv64")]
38 mod riscv64;
39 
40 mod android_boot;
41 mod avb;
42 mod error;
43 mod fastboot;
44 mod fuchsia_boot;
45 mod net;
46 
main(image_handle: *mut core::ffi::c_void, systab_ptr: *mut EfiSystemTable) -> Result<()>47 fn main(image_handle: *mut core::ffi::c_void, systab_ptr: *mut EfiSystemTable) -> Result<()> {
48     // SAFETY: Called only once here upon EFI app entry.
49     let entry = unsafe { initialize(image_handle, systab_ptr)? };
50 
51     efi_println!(entry, "****Rust EFI Application****");
52     if let Ok(v) = loaded_image_path(&entry) {
53         efi_println!(entry, "Image path: {}", v);
54     }
55 
56     efi_println!(entry, "Press 'f' to enter fastboot.");
57     match wait_key_stroke(&entry, 'f', 2000) {
58         Ok(true) => {
59             efi_println!(entry, "'f' pressed.");
60             let android_boot_protocol = entry
61                 .system_table()
62                 .boot_services()
63                 .find_first_and_open::<AndroidBootProtocol>()
64                 .ok();
65             fastboot::run_fastboot(&entry, android_boot_protocol.as_ref())?;
66         }
67         _ => {}
68     }
69 
70     // For simplicity, we pick bootflow based on GPT layout.
71     if fuchsia_boot::is_fuchsia_gpt(&entry).is_ok() {
72         fuchsia_boot::fuchsia_boot_demo(entry)?;
73     } else {
74         android_boot::android_boot_demo(entry)?;
75     }
76 
77     Ok(())
78 }
79 
80 #[no_mangle]
efi_main(image_handle: *mut core::ffi::c_void, systab_ptr: *mut EfiSystemTable)81 pub extern "C" fn efi_main(image_handle: *mut core::ffi::c_void, systab_ptr: *mut EfiSystemTable) {
82     main(image_handle, systab_ptr).unwrap();
83     loop {}
84 }
85