gbl: efi: add "fastboot boot" command Add fastboot boot implementation. Change-Id: I2625ee349f3d4addced105985e7c38f7335b3c10 Signed-off-by: Ying-Chun Liu (PaulLiu) <liupa@google.com>
diff --git a/gbl/efi/src/android_boot.rs b/gbl/efi/src/android_boot.rs index 8c48ac6..5a02b95 100644 --- a/gbl/efi/src/android_boot.rs +++ b/gbl/efi/src/android_boot.rs
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{efi_blocks::find_block_devices, fastboot::fastboot, ops::Ops}; +use crate::{efi_blocks::find_block_devices, fastboot::fastboot, ops::Ops, ops::RambootOps}; use efi::{exit_boot_services, EfiEntry}; use libgbl::{android_boot::load_android_simple, gbl_print, gbl_println, GblOps, Os, Result}; @@ -32,16 +32,15 @@ pub fn android_boot_demo(entry: EfiEntry) -> Result<()> { let blks = find_block_devices(&entry)?; let mut ops = Ops::new(&entry, &blks[..], Some(Os::Android)); + let mut bootimg_buffer = &mut vec![0u8; 128 * 1024 * 1024][..]; // 128 MB match ops.should_stop_in_fastboot() { - Ok(true) => { - fastboot(&mut ops)?; - } - Ok(false) => {} + Ok(true) => fastboot(&mut ops, &mut bootimg_buffer)?, Err(e) => { gbl_println!(ops, "Warning: error while checking fastboot trigger ({:?})", e); gbl_println!(ops, "Ignoring error and continuing with normal boot"); } + _ => {} } gbl_println!(ops, "Try booting as Android"); @@ -49,7 +48,12 @@ // Allocate buffer for load. let mut load_buffer = vec![0u8; 128 * 1024 * 1024]; // 128MB - let (ramdisk, fdt, kernel, remains) = load_android_simple(&mut ops, &mut load_buffer[..])?; + let (ramdisk, fdt, kernel, remains) = if bootimg_buffer.starts_with(b"ANDROID!") { + let mut ramboot_ops = RambootOps { ops: &mut ops, bootimg_buffer }; + load_android_simple(&mut ramboot_ops, &mut load_buffer[..])? + } else { + load_android_simple(&mut ops, &mut load_buffer[..])? + }; gbl_println!(ops, ""); gbl_println!(
diff --git a/gbl/efi/src/fastboot.rs b/gbl/efi/src/fastboot.rs index b9a70b0..485e3ab 100644 --- a/gbl/efi/src/fastboot.rs +++ b/gbl/efi/src/fastboot.rs
@@ -199,7 +199,7 @@ } } -pub fn fastboot(efi_gbl_ops: &mut Ops) -> Result<()> { +pub fn fastboot(efi_gbl_ops: &mut Ops, bootimg_buf: &mut [u8]) -> Result<()> { let efi_entry = efi_gbl_ops.efi_entry; efi_println!(efi_entry, "Entering fastboot mode..."); @@ -224,6 +224,16 @@ let tcp = tcp.as_mut().map(|v| EfiFastbootTcpTransport::new(v)); let download_buffers = vec![vec![0u8; 512 * 1024 * 1024]; 2].into(); - block_on(run_gbl_fastboot(efi_gbl_ops, &download_buffers, VecPinFut::default(), usb, tcp)); + block_on(run_gbl_fastboot( + efi_gbl_ops, + &download_buffers, + VecPinFut::default(), + usb, + tcp, + bootimg_buf, + )); + + efi_println!(efi_entry, "Leaving fastboot mode..."); + Ok(()) }
diff --git a/gbl/efi/src/fuchsia_boot.rs b/gbl/efi/src/fuchsia_boot.rs index 3b10f89..44254e1 100644 --- a/gbl/efi/src/fuchsia_boot.rs +++ b/gbl/efi/src/fuchsia_boot.rs
@@ -67,7 +67,7 @@ let mut ops = Ops::new(&efi_entry, &blks[..], Some(Os::Fuchsia)); // Checks whether to enter fastboot mode. if zircon_check_enter_fastboot(&mut ops) { - fastboot(&mut ops)?; + fastboot(&mut ops, &mut [])?; } zircon_load_verify_abr(&mut ops)? };
diff --git a/gbl/efi/src/ops.rs b/gbl/efi/src/ops.rs index 6c0d957..112f3ab 100644 --- a/gbl/efi/src/ops.rs +++ b/gbl/efi/src/ops.rs
@@ -25,7 +25,7 @@ }; use arrayvec::ArrayVec; use core::{ - ffi::CStr, fmt::Write, mem::MaybeUninit, num::NonZeroUsize, ops::DerefMut, ptr::null, + cmp::min, ffi::CStr, fmt::Write, mem::MaybeUninit, num::NonZeroUsize, ops::DerefMut, ptr::null, slice::from_raw_parts_mut, str::Split, }; use efi::{ @@ -42,7 +42,7 @@ GblEfiImageInfo, GblEfiVerifiedDeviceTree, PARTITION_NAME_LEN_U16, }; use fdt::Fdt; -use gbl_storage::{BlockIo, Disk, Gpt}; +use gbl_storage::{BlockIo, Disk, Gpt, SliceMaybeUninit}; use liberror::{Error, Result}; use libgbl::{ constants::{ImageName, BOOTCMD_SIZE}, @@ -563,6 +563,180 @@ } } +/// Inherits everything from `ops` but override a few such as read boot_a from +/// bootimg_buffer, +/// avb_write_rollback_index(), slot operation etc +pub struct RambootOps<'b, T> { + pub ops: &'b mut T, + pub bootimg_buffer: &'b mut [u8], +} + +impl<'a, 'd, T: GblOps<'a, 'd>> GblOps<'a, 'd> for RambootOps<'_, T> { + fn console_out(&mut self) -> Option<&mut dyn Write> { + self.ops.console_out() + } + + fn should_stop_in_fastboot(&mut self) -> Result<bool> { + self.ops.should_stop_in_fastboot() + } + + fn reboot(&mut self) { + self.ops.reboot() + } + + fn disks( + &self, + ) -> &'a [GblDisk< + Disk<impl BlockIo + 'a, impl DerefMut<Target = [u8]> + 'a>, + Gpt<impl DerefMut<Target = [u8]> + 'a>, + >] { + self.ops.disks() + } + + fn expected_os(&mut self) -> Result<Option<Os>> { + self.ops.expected_os() + } + + fn zircon_add_device_zbi_items( + &mut self, + container: &mut ZbiContainer<&mut [u8]>, + ) -> Result<()> { + self.ops.zircon_add_device_zbi_items(container) + } + + fn get_zbi_bootloader_files_buffer(&mut self) -> Option<&mut [u8]> { + self.ops.get_zbi_bootloader_files_buffer() + } + + fn load_slot_interface<'c>( + &'c mut self, + _fnmut: &'c mut dyn FnMut(&mut [u8]) -> Result<()>, + _boot_token: BootToken, + ) -> GblResult<Cursor<'c>> { + self.ops.load_slot_interface(_fnmut, _boot_token) + } + + fn avb_read_is_device_unlocked(&mut self) -> AvbIoResult<bool> { + self.ops.avb_read_is_device_unlocked() + } + + fn avb_read_rollback_index(&mut self, _rollback_index_location: usize) -> AvbIoResult<u64> { + self.ops.avb_read_rollback_index(_rollback_index_location) + } + + fn avb_write_rollback_index(&mut self, _: usize, _: u64) -> AvbIoResult<()> { + // We don't want to persist AVB related data such as updating antirollback indices. + Ok(()) + } + + fn avb_cert_read_permanent_attributes( + &mut self, + attributes: &mut CertPermanentAttributes, + ) -> AvbIoResult<()> { + self.ops.avb_cert_read_permanent_attributes(attributes) + } + + fn avb_cert_read_permanent_attributes_hash(&mut self) -> AvbIoResult<[u8; SHA256_DIGEST_SIZE]> { + self.ops.avb_cert_read_permanent_attributes_hash() + } + + fn get_image_buffer( + &mut self, + image_name: &str, + size: NonZeroUsize, + ) -> GblResult<ImageBuffer<'d>> { + self.ops.get_image_buffer(image_name, size) + } + + fn get_custom_device_tree(&mut self) -> Option<&'a [u8]> { + self.ops.get_custom_device_tree() + } + + fn fixup_os_commandline<'c>( + &mut self, + commandline: &CStr, + fixup_buffer: &'c mut [u8], + ) -> Result<Option<&'c str>> { + self.ops.fixup_os_commandline(commandline, fixup_buffer) + } + + fn fixup_bootconfig<'c>( + &mut self, + bootconfig: &[u8], + fixup_buffer: &'c mut [u8], + ) -> Result<Option<&'c [u8]>> { + self.ops.fixup_bootconfig(bootconfig, fixup_buffer) + } + + fn fixup_device_tree(&mut self, device_tree: &mut [u8]) -> Result<()> { + self.ops.fixup_device_tree(device_tree) + } + + fn select_device_trees( + &mut self, + components_registry: &mut DeviceTreeComponentsRegistry, + ) -> Result<()> { + self.ops.select_device_trees(components_registry) + } + + fn read_from_partition_sync( + &mut self, + part: &str, + off: u64, + out: &mut (impl SliceMaybeUninit + ?Sized), + ) -> Result<()> { + if part == "boot_a" { + let len = min(self.bootimg_buffer.len() - off as usize, out.len()); + out.clone_from_slice(&self.bootimg_buffer[off as usize..off as usize + len]); + Ok(()) + } else { + self.ops.read_from_partition_sync(part, off, out) + } + } + + fn avb_handle_verification_result( + &mut self, + color: BootStateColor, + 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<()> { + self.ops.avb_handle_verification_result( + color, + boot_os_version, + boot_security_patch, + system_os_version, + system_security_patch, + vendor_os_version, + vendor_security_patch, + ) + } + + fn fastboot_variable( + &mut self, + name: &str, + args: Split<'_, char>, + out: &mut [u8], + ) -> Result<usize> { + self.ops.fastboot_variable(name, args, out) + } + + async fn fastboot_send_all_variables(&mut self, sender: &mut impl VarInfoSender) -> Result<()> { + self.ops.fastboot_send_all_variables(sender).await + } + + fn avb_validate_vbmeta_public_key( + &self, + public_key: &[u8], + public_key_metadata: Option<&[u8]>, + ) -> AvbIoResult<KeyValidationStatus> { + self.ops.avb_validate_vbmeta_public_key(public_key, public_key_metadata) + } +} + #[cfg(test)] mod test { use super::*;
diff --git a/gbl/libfastboot/src/lib.rs b/gbl/libfastboot/src/lib.rs index ebe575f..70b54fa 100644 --- a/gbl/libfastboot/src/lib.rs +++ b/gbl/libfastboot/src/lib.rs
@@ -386,6 +386,20 @@ /// Backend for `fastboot set_active`. async fn set_active(&mut self, slot: &str, responder: impl InfoSender) -> CommandResult<()>; + /// Backend for `fastboot boot` + /// + /// # Args + /// + /// * `responder`: An instance of `InfoSender + OkaySender`. Implementation should call + /// `responder.send_okay("")` right before boot to notify the remote host that the + /// operation is successful. + /// + /// # Returns + /// + /// * The method is always return OK to let fastboot continue. + /// * Returns `Err(e)` on error. + async fn boot(&mut self, responder: impl InfoSender + OkaySender) -> CommandResult<()>; + /// Backend for `fastboot oem ...`. /// /// # Args @@ -854,6 +868,19 @@ reply_fail!(resp, "{}", e.to_str()) } +// Handles `fastboot boot` +async fn boot( + transport: &mut impl Transport, + fb_impl: &mut impl FastbootImplementation, +) -> Result<()> { + let mut resp = Responder::new(transport); + let boot_res = async { fb_impl.boot(&mut resp).await }.await; + match boot_res { + Err(e) => reply_fail!(resp, "{}", e.to_str()), + _ => reply_okay!(resp, "boot_command"), + } +} + // Handles `fastboot continue` async fn r#continue( transport: &mut impl Transport, @@ -926,6 +953,10 @@ return transport.send_packet(fastboot_fail!(packet, "No command")).await.map(|_| false); }; match cmd { + "boot" => { + boot(transport, fb_impl).await?; + return Ok(true); + } "continue" => { r#continue(transport, fb_impl).await?; return Ok(true); @@ -1154,6 +1185,10 @@ .await?) } + async fn boot(&mut self, mut responder: impl InfoSender + OkaySender) -> CommandResult<()> { + Ok(responder.send_info("Boot to boot.img...").await?) + } + async fn reboot( &mut self, mode: RebootMode, @@ -1256,6 +1291,19 @@ } #[test] + fn test_boot() { + let mut fastboot_impl: FastbootTest = Default::default(); + fastboot_impl.download_buffer = vec![0u8; 1024]; + let mut transport = TestTransport::new(); + transport.add_input(b"boot"); + let _ = block_on(run(&mut transport, &mut fastboot_impl)); + assert_eq!( + transport.out_queue, + VecDeque::<Vec<u8>>::from([b"INFOBoot to boot.img...".into()]) + ); + } + + #[test] fn test_non_exist_command() { let mut fastboot_impl: FastbootTest = Default::default(); fastboot_impl.download_buffer = vec![0u8; 1024];
diff --git a/gbl/libgbl/src/fastboot/mod.rs b/gbl/libgbl/src/fastboot/mod.rs index 85bd189..81b15df 100644 --- a/gbl/libgbl/src/fastboot/mod.rs +++ b/gbl/libgbl/src/fastboot/mod.rs
@@ -135,6 +135,7 @@ current_download_size: usize, enable_async_task: bool, default_block: Option<usize>, + bootimg_buf: &'b mut [u8], // Introduces marker type so that we can enforce constraint 'd <= min('b, 'c). // The constraint is expressed in the implementation block for the `FastbootImplementation` // trait. @@ -179,6 +180,7 @@ task_mapper: fn(Task<'a, 'b, B, P>) -> F, tasks: &'d Shared<C>, buffer_pool: &'b Shared<P>, + bootimg_buf: &'b mut [u8], ) -> Self { Self { gbl_ops, @@ -190,6 +192,7 @@ current_download_size: 0, enable_async_task: false, default_block: None, + bootimg_buf, _tasks_context_lifetime: PhantomData, _get_image_buffer_lifetime: PhantomData, } @@ -685,6 +688,16 @@ _ => Err("Unknown oem command".into()), } } + + async fn boot(&mut self, mut resp: impl InfoSender + OkaySender) -> CommandResult<()> { + let len = core::cmp::min(self.bootimg_buf.len(), self.current_download_size); + let data = self.current_download_buffer.as_mut().ok_or("No file staged")?; + let data = &mut data[..self.current_download_size]; + + self.bootimg_buf[..len].copy_from_slice(&data[..len]); + resp.send_info("Boot into boot.img").await?; + Ok(()) + } } /// `GblUsbTransport` defines transport interfaces for running GBL fastboot over USB. @@ -723,10 +736,13 @@ tasks: impl PinFutContainer<'c> + 'c, usb: Option<impl GblUsbTransport>, tcp: Option<impl GblTcpStream>, + bootimg_buf: &'b mut [u8], ) { let tasks = tasks.into(); let disks = gbl_ops.disks(); - GblFastboot::new(gbl_ops, disks, Task::run, &tasks, buffer_pool).run(usb, tcp).await; + GblFastboot::new(gbl_ops, disks, Task::run, &tasks, buffer_pool, bootimg_buf) + .run(usb, tcp) + .await; } /// Runs GBL fastboot on the given USB/TCP channels with N stack allocated worker tasks. @@ -750,6 +766,7 @@ buffer_pool: impl BufferPool, usb: Option<impl GblUsbTransport>, tcp: Option<impl GblTcpStream>, + bootimg_buf: &mut [u8], ) { let buffer_pool = buffer_pool.into(); // Creates N worker tasks. @@ -771,7 +788,9 @@ let mut tasks: [_; N] = tasks.each_mut().map(|v| unsafe { Pin::new_unchecked(v) }); let tasks = PinFutSlice::new(&mut tasks[..]).into(); let disks = gbl_ops.disks(); - GblFastboot::new(gbl_ops, disks, Task::run, &tasks, &buffer_pool).run(usb, tcp).await; + GblFastboot::new(gbl_ops, disks, Task::run, &tasks, &buffer_pool, bootimg_buf) + .run(usb, tcp) + .await; } /// Pre-generates a Fuchsia Fastboot MDNS service broadcast packet. @@ -910,7 +929,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); check_var( &mut gbl_fb, FakeGblOps::GBL_TEST_VAR, @@ -930,7 +950,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); // Check different semantics check_var(&mut gbl_fb, "partition-size", "boot_a", "0x2000"); @@ -988,7 +1009,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let mut logger = TestVarSender(vec![]); block_on(gbl_fb.get_var_all(&mut logger)).unwrap(); @@ -1055,7 +1077,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); // Missing mandatory block device ID for raw block partition. assert!(fetch(&mut gbl_fb, "//0/0".into(), 0, 0).is_err()); @@ -1104,7 +1127,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let off = 512; let size = 512; @@ -1145,7 +1169,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let expect_boot_a = include_bytes!("../../../libstorage/test/boot_a.bin"); let expect_boot_b = include_bytes!("../../../libstorage/test/boot_b.bin"); @@ -1207,7 +1232,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let expect_boot_a = include_bytes!("../../../libstorage/test/boot_a.bin"); let expect_boot_b = include_bytes!("../../../libstorage/test/boot_b.bin"); @@ -1237,7 +1263,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let download = sparse.to_vec(); let resp: TestResponder = Default::default(); @@ -1274,7 +1301,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let tasks = gbl_fb.tasks(); let resp: TestResponder = Default::default(); @@ -1325,7 +1353,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let tasks = gbl_fb.tasks(); let resp: TestResponder = Default::default(); @@ -1378,7 +1407,8 @@ liberror::Error::Other(None).into(); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let tasks = gbl_fb.tasks(); let resp: TestResponder = Default::default(); @@ -1406,7 +1436,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let tasks = gbl_fb.tasks(); let resp: TestResponder = Default::default(); @@ -1457,7 +1488,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let resp: TestResponder = Default::default(); let boot_a = include_bytes!("../../../libstorage/test/boot_a.bin"); @@ -1513,7 +1545,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let resp: TestResponder = Default::default(); // Missing block device ID. assert!(block_on(oem(&mut gbl_fb, "gbl-set-default-block ", &resp)).is_err()); @@ -1531,7 +1564,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let tasks = gbl_fb.tasks(); let resp: TestResponder = Default::default(); @@ -1565,7 +1599,8 @@ let mut gbl_ops = FakeGblOps::new(&storage); let tasks = vec![].into(); let parts = gbl_ops.disks(); - let mut gbl_fb = GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers); + let mut gbl_fb = + GblFastboot::new(&mut gbl_ops, parts, Task::run, &tasks, &dl_buffers, &mut []); let tasks = gbl_fb.tasks(); let resp: TestResponder = Default::default(); @@ -1726,7 +1761,7 @@ listener.add_tcp_input(b"FB01"); listener.add_tcp_length_prefixed_input(b"getvar:max-download-size"); listener.add_tcp_length_prefixed_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -1753,7 +1788,7 @@ let listener: SharedTestListener = Default::default(); let (usb, tcp) = (&listener, &listener); let mut fb_fut = - pin!(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + pin!(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); listener.add_usb_input(b"oem gbl-enable-async-task"); listener.add_usb_input(format!("download:{:#x}", 4 * 1024).as_bytes()); @@ -1817,7 +1852,7 @@ listener.add_usb_input(b"oem add-staged-bootloader-file file_2"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); let buffer = gbl_ops.get_zbi_bootloader_files_buffer_aligned().unwrap(); let container = ZbiContainer::parse(&buffer[..]).unwrap(); @@ -1840,7 +1875,7 @@ listener.add_usb_input(b"oem add-staged-bootloader-file"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -1867,7 +1902,7 @@ listener.add_usb_input(b"oem add-staged-bootloader-file file1"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -1945,7 +1980,7 @@ listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2036,7 +2071,7 @@ listener.add_usb_input(b"getvar:partition-size:boot_b"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2070,7 +2105,7 @@ listener.add_usb_input(b"flash:gpt/0"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2097,7 +2132,7 @@ listener.add_usb_input(b"flash:gpt/0"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2135,7 +2170,7 @@ // Invalid option. listener.add_usb_input(b"flash:gpt/0/invalid-arg"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2168,7 +2203,7 @@ listener.add_usb_input(gpt); listener.add_usb_input(b"flash:gpt/0"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2205,7 +2240,7 @@ listener.add_usb_input(b"getvar:partition-size:vendor_boot_b"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2234,7 +2269,7 @@ listener.add_usb_input(b"erase:gpt/0"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2271,7 +2306,7 @@ // Issues set_active commands listener.add_usb_input(cmd.as_bytes()); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2319,7 +2354,7 @@ listener.add_usb_input(b"set_active:r"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2345,7 +2380,7 @@ listener.add_usb_input(b"reboot-bootloader"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2376,7 +2411,7 @@ listener.add_usb_input(b"reboot-recovery"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(), @@ -2411,7 +2446,7 @@ listener.add_usb_input(&[0xaau8; 4 * 1024]); listener.add_usb_input(b"flash:fvm"); listener.add_usb_input(b"continue"); - block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp))); + block_on(run_gbl_fastboot_stack::<2>(&mut gbl_ops, buffers, Some(usb), Some(tcp), &mut [])); assert_eq!( listener.usb_out_queue(),