Merge changes I6a3a4e02,I3630a713,I29413609

* changes:
  pvmfw: README: Document BCC integration
  pvmfw: README: Document loading
  pvmfw: README: Add pvmfw context
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 7c72fab..c6d6c2c 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -508,6 +508,19 @@
         fdt_err_expect_zero(ret)
     }
 
+    /// Applies a DT overlay on the base DT.
+    ///
+    /// # Safety
+    ///
+    /// On failure, the library corrupts the DT and overlay so both must be discarded.
+    pub unsafe fn apply_overlay<'a>(&'a mut self, overlay: &'a mut Fdt) -> Result<&'a mut Self> {
+        fdt_err_expect_zero(libfdt_bindgen::fdt_overlay_apply(
+            self.as_mut_ptr(),
+            overlay.as_mut_ptr(),
+        ))?;
+        Ok(self)
+    }
+
     /// Return an iterator of memory banks specified the "/memory" node.
     ///
     /// NOTE: This does not support individual "/memory@XXXX" banks.
diff --git a/pvmfw/avb/src/utils.rs b/pvmfw/avb/src/utils.rs
index bb27497..1b35c22 100644
--- a/pvmfw/avb/src/utils.rs
+++ b/pvmfw/avb/src/utils.rs
@@ -16,8 +16,11 @@
 
 use crate::error::AvbIOError;
 use core::ptr::NonNull;
+use core::result;
 
-pub(crate) fn write<T>(ptr: *mut T, value: T) -> Result<(), AvbIOError> {
+pub(crate) type Result<T> = result::Result<T, AvbIOError>;
+
+pub(crate) fn write<T>(ptr: *mut T, value: T) -> Result<()> {
     let ptr = to_nonnull(ptr)?;
     // SAFETY: It is safe as the raw pointer `ptr` is a nonnull pointer.
     unsafe {
@@ -26,17 +29,17 @@
     Ok(())
 }
 
-pub(crate) fn as_ref<'a, T>(ptr: *mut T) -> Result<&'a T, AvbIOError> {
+pub(crate) fn as_ref<'a, T>(ptr: *mut T) -> Result<&'a T> {
     let ptr = to_nonnull(ptr)?;
     // SAFETY: It is safe as the raw pointer `ptr` is a nonnull pointer.
     unsafe { Ok(ptr.as_ref()) }
 }
 
-pub(crate) fn to_nonnull<T>(ptr: *mut T) -> Result<NonNull<T>, AvbIOError> {
+pub(crate) fn to_nonnull<T>(ptr: *mut T) -> Result<NonNull<T>> {
     NonNull::new(ptr).ok_or(AvbIOError::NoSuchValue)
 }
 
-pub(crate) fn is_not_null<T>(ptr: *const T) -> Result<(), AvbIOError> {
+pub(crate) fn is_not_null<T>(ptr: *const T) -> Result<()> {
     if ptr.is_null() {
         Err(AvbIOError::NoSuchValue)
     } else {
@@ -44,10 +47,10 @@
     }
 }
 
-pub(crate) fn to_usize<T: TryInto<usize>>(num: T) -> Result<usize, AvbIOError> {
+pub(crate) fn to_usize<T: TryInto<usize>>(num: T) -> Result<usize> {
     num.try_into().map_err(|_| AvbIOError::InvalidValueSize)
 }
 
-pub(crate) fn usize_checked_add(x: usize, y: usize) -> Result<usize, AvbIOError> {
+pub(crate) fn usize_checked_add(x: usize, y: usize) -> Result<usize> {
     x.checked_add(y).ok_or(AvbIOError::InvalidValueSize)
 }
diff --git a/pvmfw/avb/tests/utils.rs b/pvmfw/avb/tests/utils.rs
index 0d9657e..0a2eac6 100644
--- a/pvmfw/avb/tests/utils.rs
+++ b/pvmfw/avb/tests/utils.rs
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-//! Utility methods used by API tests.
+//! Utility functions used by API tests.
 
 use anyhow::Result;
 use avb_bindgen::{
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index bfcb423..4f30902 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -178,6 +178,37 @@
     }
 }
 
+/// Applies the debug policy device tree overlay to the pVM DT.
+///
+/// # Safety
+///
+/// When an error is returned by this function, the input `Fdt` should be discarded as it may have
+/// have been partially corrupted during the overlay application process.
+unsafe fn apply_debug_policy(
+    fdt: &mut libfdt::Fdt,
+    debug_policy: &mut [u8],
+) -> Result<(), RebootReason> {
+    let overlay = libfdt::Fdt::from_mut_slice(debug_policy).map_err(|e| {
+        error!("Failed to load the debug policy overlay: {e}");
+        RebootReason::InvalidConfig
+    })?;
+
+    fdt.unpack().map_err(|e| {
+        error!("Failed to unpack DT for debug policy: {e}");
+        RebootReason::InternalError
+    })?;
+
+    let fdt = fdt.apply_overlay(overlay).map_err(|e| {
+        error!("Failed to apply the debug policy overlay: {e}");
+        RebootReason::InvalidConfig
+    })?;
+
+    fdt.pack().map_err(|e| {
+        error!("Failed to re-pack DT after debug policy: {e}");
+        RebootReason::InternalError
+    })
+}
+
 /// Sets up the environment for main() and wraps its result for start().
 ///
 /// Provide the abstractions necessary for start() to abort the pVM boot and for main() to run with
@@ -252,6 +283,11 @@
     helpers::flushed_zeroize(bcc_slice);
     helpers::flush(slices.fdt.as_slice());
 
+    if let Some(debug_policy) = appended.get_debug_policy() {
+        // SAFETY - As we `?` the result, there is no risk of re-using a bad `slices.fdt`.
+        unsafe { apply_debug_policy(slices.fdt, debug_policy) }?;
+    }
+
     info!("Expecting a bug making MMIO_GUARD_UNMAP return NOT_SUPPORTED on success");
     memory.mmio_unmap_all().map_err(|e| {
         error!("Failed to unshare MMIO ranges: {e}");