[vmbase][pci] Decouple Hal impl from PciTransportIterator

This cl decouples the specific implementation of the
virtio_drivers::Hal trait from the PciTransportIterator struct,
enabling it to be used in a wider range of scenarios. This
also allows the iterator to be tested in the vmbase integration
test.

Test: m pvmfw_img
Test: atest vmbase_example.integration_test
Bug: 284462758
Change-Id: I0bee834e8db534cbdc49be84d5b4cdda30b8288a
diff --git a/pvmfw/src/gpt.rs b/pvmfw/src/gpt.rs
index b553705..892850c 100644
--- a/pvmfw/src/gpt.rs
+++ b/pvmfw/src/gpt.rs
@@ -24,9 +24,11 @@
 use uuid::Uuid;
 use virtio_drivers::device::blk::SECTOR_SIZE;
 use vmbase::util::ceiling_div;
-use vmbase::virtio::pci::VirtIOBlk;
+use vmbase::virtio::{pci, HalImpl};
 use zerocopy::FromBytes;
 
+type VirtIOBlk = pci::VirtIOBlk<HalImpl>;
+
 pub enum Error {
     /// VirtIO error during read operation.
     FailedRead(virtio_drivers::Error),
diff --git a/pvmfw/src/instance.rs b/pvmfw/src/instance.rs
index 1035559..f2b34da 100644
--- a/pvmfw/src/instance.rs
+++ b/pvmfw/src/instance.rs
@@ -32,6 +32,7 @@
 use vmbase::rand;
 use vmbase::util::ceiling_div;
 use vmbase::virtio::pci::{PciTransportIterator, VirtIOBlk};
+use vmbase::virtio::HalImpl;
 use zerocopy::AsBytes;
 use zerocopy::FromBytes;
 
@@ -183,10 +184,11 @@
 }
 
 fn find_instance_img(pci_root: &mut PciRoot) -> Result<Partition> {
-    for transport in
-        PciTransportIterator::new(pci_root).filter(|t| DeviceType::Block == t.device_type())
+    for transport in PciTransportIterator::<HalImpl>::new(pci_root)
+        .filter(|t| DeviceType::Block == t.device_type())
     {
-        let device = VirtIOBlk::new(transport).map_err(Error::VirtIOBlkCreationFailed)?;
+        let device =
+            VirtIOBlk::<HalImpl>::new(transport).map_err(Error::VirtIOBlkCreationFailed)?;
         match Partition::get_by_name(device, "vm-instance") {
             Ok(Some(p)) => return Ok(p),
             Ok(None) => {}
diff --git a/vmbase/example/src/pci.rs b/vmbase/example/src/pci.rs
index 6abe66e..7188cde 100644
--- a/vmbase/example/src/pci.rs
+++ b/vmbase/example/src/pci.rs
@@ -20,13 +20,14 @@
 use fdtpci::PciInfo;
 use log::{debug, info};
 use virtio_drivers::{
-    device::{blk::VirtIOBlk, console::VirtIOConsole},
+    device::console::VirtIOConsole,
     transport::{
-        pci::{bus::PciRoot, virtio_device_type, PciTransport},
+        pci::{bus::PciRoot, PciTransport},
         DeviceType, Transport,
     },
     BufferDirection, Error, Hal, PhysAddr, PAGE_SIZE,
 };
+use vmbase::virtio::pci::{self, PciTransportIterator};
 
 /// The standard sector size of a VirtIO block device, in bytes.
 const SECTOR_SIZE_BYTES: usize = 512;
@@ -37,29 +38,23 @@
 pub fn check_pci(pci_root: &mut PciRoot) {
     let mut checked_virtio_device_count = 0;
     let mut block_device_count = 0;
-    for (device_function, info) in pci_root.enumerate_bus(0) {
-        let (status, command) = pci_root.get_status_command(device_function);
-        info!("Found {} at {}, status {:?} command {:?}", info, device_function, status, command);
-        if let Some(virtio_type) = virtio_device_type(&info) {
-            info!("  VirtIO {:?}", virtio_type);
-            let mut transport = PciTransport::new::<HalImpl>(pci_root, device_function).unwrap();
-            info!(
-                "Detected virtio PCI device with device type {:?}, features {:#018x}",
-                transport.device_type(),
-                transport.read_device_features(),
-            );
-            match virtio_type {
-                DeviceType::Block => {
-                    check_virtio_block_device(transport, block_device_count);
-                    block_device_count += 1;
-                    checked_virtio_device_count += 1;
-                }
-                DeviceType::Console => {
-                    check_virtio_console_device(transport);
-                    checked_virtio_device_count += 1;
-                }
-                _ => {}
+    for mut transport in PciTransportIterator::<HalImpl>::new(pci_root) {
+        info!(
+            "Detected virtio PCI device with device type {:?}, features {:#018x}",
+            transport.device_type(),
+            transport.read_device_features(),
+        );
+        match transport.device_type() {
+            DeviceType::Block => {
+                check_virtio_block_device(transport, block_device_count);
+                block_device_count += 1;
+                checked_virtio_device_count += 1;
             }
+            DeviceType::Console => {
+                check_virtio_console_device(transport);
+                checked_virtio_device_count += 1;
+            }
+            _ => {}
         }
     }
 
@@ -68,8 +63,8 @@
 }
 
 /// Checks the given VirtIO block device.
-fn check_virtio_block_device(transport: impl Transport, index: usize) {
-    let mut blk = VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
+fn check_virtio_block_device(transport: PciTransport, index: usize) {
+    let mut blk = pci::VirtIOBlk::<HalImpl>::new(transport).expect("failed to create blk driver");
     info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
     match index {
         0 => {
@@ -94,8 +89,8 @@
 }
 
 /// Checks the given VirtIO console device.
-fn check_virtio_console_device(transport: impl Transport) {
-    let mut console = VirtIOConsole::<HalImpl, _>::new(transport)
+fn check_virtio_console_device(transport: PciTransport) {
+    let mut console = VirtIOConsole::<HalImpl, PciTransport>::new(transport)
         .expect("Failed to create VirtIO console driver");
     info!("Found console device: {:?}", console.info());
     for &c in b"Hello VirtIO console\n" {
diff --git a/vmbase/src/virtio/mod.rs b/vmbase/src/virtio/mod.rs
index df916bc..fbe41e3 100644
--- a/vmbase/src/virtio/mod.rs
+++ b/vmbase/src/virtio/mod.rs
@@ -16,3 +16,5 @@
 
 mod hal;
 pub mod pci;
+
+pub use hal::HalImpl;
diff --git a/vmbase/src/virtio/pci.rs b/vmbase/src/virtio/pci.rs
index 534d91a..a75f0e2 100644
--- a/vmbase/src/virtio/pci.rs
+++ b/vmbase/src/virtio/pci.rs
@@ -14,10 +14,10 @@
 
 //! Functions to scan the PCI bus for VirtIO devices.
 
-use super::hal::HalImpl;
 use crate::memory::{MemoryTracker, MemoryTrackerError};
 use alloc::boxed::Box;
 use core::fmt;
+use core::marker::PhantomData;
 use fdtpci::PciInfo;
 use log::debug;
 use once_cell::race::OnceBox;
@@ -27,6 +27,7 @@
         bus::{BusDeviceIterator, PciRoot},
         virtio_device_type, PciTransport,
     },
+    Hal,
 };
 
 pub(super) static PCI_INFO: OnceBox<PciInfo> = OnceBox::new();
@@ -76,23 +77,24 @@
 }
 
 /// Virtio Block device.
-pub type VirtIOBlk = blk::VirtIOBlk<HalImpl, PciTransport>;
+pub type VirtIOBlk<T> = blk::VirtIOBlk<T, PciTransport>;
 
 /// An iterator that iterates over the PCI transport for each device.
-pub struct PciTransportIterator<'a> {
+pub struct PciTransportIterator<'a, T: Hal> {
     pci_root: &'a mut PciRoot,
     bus: BusDeviceIterator,
+    _hal: PhantomData<T>,
 }
 
-impl<'a> PciTransportIterator<'a> {
+impl<'a, T: Hal> PciTransportIterator<'a, T> {
     /// Creates a new iterator.
     pub fn new(pci_root: &'a mut PciRoot) -> Self {
         let bus = pci_root.enumerate_bus(0);
-        Self { pci_root, bus }
+        Self { pci_root, bus, _hal: PhantomData }
     }
 }
 
-impl<'a> Iterator for PciTransportIterator<'a> {
+impl<'a, T: Hal> Iterator for PciTransportIterator<'a, T> {
     type Item = PciTransport;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -109,7 +111,7 @@
             };
             debug!("  VirtIO {:?}", virtio_type);
 
-            return PciTransport::new::<HalImpl>(self.pci_root, device_function).ok();
+            return PciTransport::new::<T>(self.pci_root, device_function).ok();
         }
     }
 }