pvmfw: Make template Fdt const

Make Fdt::unchecked_from_slice() const so that the template &Fdt can
also be const, making it slightly clearer in the code using it that the
template DT is immutable.

Test: m pvmfw_bin
Bug: 377276983
Change-Id: Ic667d52bf9fb72bea611b0af1749693dae07600a
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 0d934a6..d75e84e 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -53,6 +53,9 @@
 use vmbase::util::RangeExt as _;
 use zerocopy::AsBytes as _;
 
+// SAFETY: The template DT is automatically generated through DTC, which should produce valid DTBs.
+const FDT_TEMPLATE: &Fdt = unsafe { Fdt::unchecked_from_slice(pvmfw_fdt_template::RAW) };
+
 /// An enumeration of errors that can occur during the FDT validation.
 #[derive(Clone, Debug)]
 pub enum FdtValidationError {
@@ -1031,9 +1034,7 @@
 
     let info = parse_device_tree(fdt, vm_dtbo.as_deref())?;
 
-    // SAFETY: We trust that the template (hardcoded in our RO data) is a valid DT.
-    let fdt_template = unsafe { Fdt::unchecked_from_slice(pvmfw_fdt_template::RAW) };
-    fdt.clone_from(fdt_template).map_err(|e| {
+    fdt.clone_from(FDT_TEMPLATE).map_err(|e| {
         error!("Failed to instantiate FDT from the template DT: {e}");
         RebootReason::InvalidFdt
     })?;
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 8ea9cd9..5883567 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -624,7 +624,7 @@
     /// # Safety
     ///
     /// It is undefined to call this function on a slice that does not contain a valid device tree.
-    pub unsafe fn unchecked_from_slice(fdt: &[u8]) -> &Self {
+    pub const unsafe fn unchecked_from_slice(fdt: &[u8]) -> &Self {
         let self_ptr = fdt as *const _ as *const _;
         // SAFETY: The pointer is non-null, dereferenceable, and points to allocated memory.
         unsafe { &*self_ptr }