Merge "Include early_virtmgr only to 64bit builds" into main
diff --git a/guest/pvmfw/README.md b/guest/pvmfw/README.md
index 7a03f0b..cc5ae71 100644
--- a/guest/pvmfw/README.md
+++ b/guest/pvmfw/README.md
@@ -291,6 +291,19 @@
 `/reserved-memory` device tree node marked as
 [`compatible=”google,open-dice”`][dice-dt].
 
+#### Testing
+
+To verify that the DICE handover is successful in pvmfw and eventually the pVM
+has a valid DICE chain, you can run the VSR test
+`MicrodroidTests#protectedVmHasValidDiceChain`. The test retrieves the DICE
+chain from within a Microdroid VM in protected mode and checks the following
+properties using the [hwtrust][hwtrust] library:
+
+1. All the fields in the DICE chain conform to
+   [Android Profile for DICE][android-open-dice].
+2. The DICE chain is a valid certificate chain, where the subject public key in
+   each certificate can be used to verify the signature of the next certificate.
+
 [AVB]: https://source.android.com/docs/security/features/verifiedboot/boot-flow
 [AndroidDiceHandover]: https://pigweed.googlesource.com/open-dice/+/42ae7760023/src/android.c#212
 [DiceAndroidHandoverMainFlow]: https://pigweed.googlesource.com/open-dice/+/42ae7760023/src/android.c#221
@@ -299,6 +312,8 @@
 [dice-dt]: https://www.kernel.org/doc/Documentation/devicetree/bindings/reserved-memory/google%2Copen-dice.yaml
 [Layering]: https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#layering-details
 [Trusty-BCC]: https://android.googlesource.com/trusty/lib/+/1696be0a8f3a7103/lib/hwbcc/common/swbcc.c#554
+[hwtrust]: https://cs.android.com/android/platform/superproject/main/+/main:tools/security/remote_provisioning/hwtrust/
+[android-open-dice]: https://android.googlesource.com/platform/external/open-dice/+/refs/heads/main/docs/android.md
 
 ### Platform Requirements
 
diff --git a/guest/pvmfw/src/entry.rs b/guest/pvmfw/src/entry.rs
index 0ff7270..ce04317 100644
--- a/guest/pvmfw/src/entry.rs
+++ b/guest/pvmfw/src/entry.rs
@@ -256,7 +256,7 @@
     )?;
 
     // This wrapper allows main() to be blissfully ignorant of platform details.
-    let next_bcc = crate::main(
+    let (next_bcc, debuggable_payload) = crate::main(
         slices.fdt,
         slices.kernel,
         slices.ramdisk,
@@ -274,11 +274,15 @@
     })?;
     // Call unshare_all_memory here (instead of relying on the dtor) while UART is still mapped.
     MEMORY.lock().as_mut().unwrap().unshare_all_memory();
+
     if let Some(mmio_guard) = get_mmio_guard() {
-        mmio_guard.unmap(UART_PAGE_ADDR).map_err(|e| {
-            error!("Failed to unshare the UART: {e}");
-            RebootReason::InternalError
-        })?;
+        // Keep UART MMIO_GUARD-ed for debuggable payloads, to enable earlycon.
+        if !debuggable_payload {
+            mmio_guard.unmap(UART_PAGE_ADDR).map_err(|e| {
+                error!("Failed to unshare the UART: {e}");
+                RebootReason::InternalError
+            })?;
+        }
     }
 
     // Drop MemoryTracker and deactivate page table.
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 247aa6a..10f8549 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -67,7 +67,7 @@
     ramdisk: Option<&[u8]>,
     current_bcc_handover: &[u8],
     mut debug_policy: Option<&[u8]>,
-) -> Result<Range<usize>, RebootReason> {
+) -> Result<(Range<usize>, bool), RebootReason> {
     info!("pVM firmware");
     debug!("FDT: {:?}", fdt.as_ptr());
     debug!("Signed kernel: {:?} ({:#x} bytes)", signed_kernel.as_ptr(), signed_kernel.len());
@@ -240,7 +240,7 @@
         (r.start as usize)..(r.end as usize)
     };
 
-    Ok(bcc_range)
+    Ok((bcc_range, debuggable))
 }
 
 fn check_dice_measurements_match_entry(