Use C string literals not cstr!

Since Rust 1.77.0 the language has supported C string literals, so the
`cstr!` macro is no longer needed. Replace existing usages with the
equivalent literal.

See https://doc.rust-lang.org/reference/tokens.html#c-string-literals.

I believe that the two are equivalent:
- Escapes are handled the same way;
- Both allow arbitrary Unicode, which is mapped to UTF-8 (I don't
  think we made any use of this);
- Both treat any embedded NUL character as a compile time error.

This is of no significance whatsoever, but it does make the code a
tiny bit simpler. It should not change the compiled code at all, so
no flagging should be needed.

I'm not deleting the macro in this CL; I'll do a follow-up for that,
since there may be usages I can't see, and it has greater chance of
accidental conflict.

Test: TH
Change-Id: I4354b3b0a0c53fbec0c2d78b4182786e4e2d0ce8
diff --git a/guest/derive_microdroid_vendor_dice_node/Android.bp b/guest/derive_microdroid_vendor_dice_node/Android.bp
index 8b79aad..7a3ccbe 100644
--- a/guest/derive_microdroid_vendor_dice_node/Android.bp
+++ b/guest/derive_microdroid_vendor_dice_node/Android.bp
@@ -10,7 +10,6 @@
     rustlibs: [
         "libanyhow",
         "libclap",
-        "libcstr",
         "libdice_driver",
         "libdiced_open_dice",
         "libdm_rust",
diff --git a/guest/derive_microdroid_vendor_dice_node/src/main.rs b/guest/derive_microdroid_vendor_dice_node/src/main.rs
index 0f0631e..4ec91ad 100644
--- a/guest/derive_microdroid_vendor_dice_node/src/main.rs
+++ b/guest/derive_microdroid_vendor_dice_node/src/main.rs
@@ -16,7 +16,6 @@
 
 use anyhow::{bail, Context, Result};
 use clap::Parser;
-use cstr::cstr;
 use dice_driver::DiceDriver;
 use diced_open_dice::{
     hash, retry_bcc_format_config_descriptor, DiceConfigValues, OwnedDiceArtifacts, HIDDEN_SIZE,
@@ -50,7 +49,7 @@
 // See dice_for_avf_guest.cddl for CDDL of Configuration Descriptor of VM components.
 fn build_descriptor(vbmeta: &VbMetaImage) -> Result<Vec<u8>> {
     let values = DiceConfigValues {
-        component_name: Some(cstr!("Microdroid vendor")),
+        component_name: Some(c"Microdroid vendor"),
         security_version: Some(vbmeta.rollback_index()),
         ..Default::default()
     };
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index 793204d..da056d6 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -17,7 +17,6 @@
         "libciborium_nostd",
         "libciborium_io_nostd",
         "libcoset_nostd",
-        "libcstr",
         "libdiced_open_dice_nostd",
         "libhypervisor_backends",
         "liblibfdt_nostd",
@@ -52,9 +51,6 @@
         unit_test: true,
     },
     prefer_rlib: true,
-    rustlibs: [
-        "libcstr",
-    ],
 }
 
 rust_test {
diff --git a/guest/pvmfw/src/bootargs.rs b/guest/pvmfw/src/bootargs.rs
index aacd8e0..0a5697f 100644
--- a/guest/pvmfw/src/bootargs.rs
+++ b/guest/pvmfw/src/bootargs.rs
@@ -108,7 +108,6 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use cstr::cstr;
 
     fn check(raw: &CStr, expected: Result<&[(&str, Option<&str>)], ()>) {
         let actual = BootArgsIterator::new(raw);
@@ -136,35 +135,35 @@
 
     #[test]
     fn empty() {
-        check(cstr!(""), Ok(&[]));
-        check(cstr!("    "), Ok(&[]));
-        check(cstr!("  \n  "), Ok(&[]));
+        check(c"", Ok(&[]));
+        check(c"    ", Ok(&[]));
+        check(c"  \n  ", Ok(&[]));
     }
 
     #[test]
     fn single() {
-        check(cstr!("foo"), Ok(&[("foo", None)]));
-        check(cstr!("   foo"), Ok(&[("foo", None)]));
-        check(cstr!("foo   "), Ok(&[("foo", None)]));
-        check(cstr!("   foo   "), Ok(&[("foo", None)]));
+        check(c"foo", Ok(&[("foo", None)]));
+        check(c"   foo", Ok(&[("foo", None)]));
+        check(c"foo   ", Ok(&[("foo", None)]));
+        check(c"   foo   ", Ok(&[("foo", None)]));
     }
 
     #[test]
     fn single_with_value() {
-        check(cstr!("foo=bar"), Ok(&[("foo", Some("=bar"))]));
-        check(cstr!("   foo=bar"), Ok(&[("foo", Some("=bar"))]));
-        check(cstr!("foo=bar   "), Ok(&[("foo", Some("=bar"))]));
-        check(cstr!("   foo=bar   "), Ok(&[("foo", Some("=bar"))]));
+        check(c"foo=bar", Ok(&[("foo", Some("=bar"))]));
+        check(c"   foo=bar", Ok(&[("foo", Some("=bar"))]));
+        check(c"foo=bar   ", Ok(&[("foo", Some("=bar"))]));
+        check(c"   foo=bar   ", Ok(&[("foo", Some("=bar"))]));
 
-        check(cstr!("foo="), Ok(&[("foo", Some("="))]));
-        check(cstr!("   foo="), Ok(&[("foo", Some("="))]));
-        check(cstr!("foo=   "), Ok(&[("foo", Some("="))]));
-        check(cstr!("   foo=   "), Ok(&[("foo", Some("="))]));
+        check(c"foo=", Ok(&[("foo", Some("="))]));
+        check(c"   foo=", Ok(&[("foo", Some("="))]));
+        check(c"foo=   ", Ok(&[("foo", Some("="))]));
+        check(c"   foo=   ", Ok(&[("foo", Some("="))]));
     }
 
     #[test]
     fn single_with_quote() {
-        check(cstr!("foo=hello\" \"world"), Ok(&[("foo", Some("=hello\" \"world"))]));
+        check(c"foo=hello\" \"world", Ok(&[("foo", Some("=hello\" \"world"))]));
     }
 
     #[test]
@@ -175,32 +174,32 @@
     #[test]
     fn multiple() {
         check(
-            cstr!(" a=b   c=d   e=  f g  "),
+            c" a=b   c=d   e=  f g  ",
             Ok(&[("a", Some("=b")), ("c", Some("=d")), ("e", Some("=")), ("f", None), ("g", None)]),
         );
         check(
-            cstr!("   a=b  \n c=d      e=  f g"),
+            c"   a=b  \n c=d      e=  f g",
             Ok(&[("a", Some("=b")), ("c", Some("=d")), ("e", Some("=")), ("f", None), ("g", None)]),
         );
     }
 
     #[test]
     fn incomplete_quote() {
-        check(
-            cstr!("foo=incomplete\" quote bar=y"),
-            Ok(&[("foo", Some("=incomplete\" quote bar=y"))]),
-        );
+        check(c"foo=incomplete\" quote bar=y", Ok(&[("foo", Some("=incomplete\" quote bar=y"))]));
     }
 
     #[test]
     fn complex() {
-        check(cstr!("  a  a1=  b=c d=e,f,g x=\"value with quote\" y=val\"ue with \"multiple\" quo\"te  "), Ok(&[
-            ("a", None),
-            ("a1", Some("=")),
-            ("b", Some("=c")),
-            ("d", Some("=e,f,g")),
-            ("x", Some("=\"value with quote\"")),
-            ("y", Some("=val\"ue with \"multiple\" quo\"te")),
-        ]));
+        check(
+            c"  a  a1=  b=c d=e,f,g x=\"value with quote\" y=val\"ue with \"multiple\" quo\"te  ",
+            Ok(&[
+                ("a", None),
+                ("a1", Some("=")),
+                ("b", Some("=c")),
+                ("d", Some("=e,f,g")),
+                ("x", Some("=\"value with quote\"")),
+                ("y", Some("=val\"ue with \"multiple\" quo\"te")),
+            ]),
+        );
     }
 }
diff --git a/guest/pvmfw/src/device_assignment.rs b/guest/pvmfw/src/device_assignment.rs
index f37f443..bb2e6ce 100644
--- a/guest/pvmfw/src/device_assignment.rs
+++ b/guest/pvmfw/src/device_assignment.rs
@@ -37,18 +37,6 @@
 use zerocopy::byteorder::big_endian::U32;
 use zerocopy::FromBytes as _;
 
-// TODO(b/308694211): Use cstr! from vmbase instead.
-macro_rules! cstr {
-    ($str:literal) => {{
-        const S: &str = concat!($str, "\0");
-        const C: &::core::ffi::CStr = match ::core::ffi::CStr::from_bytes_with_nul(S.as_bytes()) {
-            Ok(v) => v,
-            Err(_) => panic!("string contains interior NUL"),
-        };
-        C
-    }};
-}
-
 // TODO(b/277993056): Keep constants derived from platform.dts in one place.
 const CELLS_PER_INTERRUPT: usize = 3; // from /intc node in platform.dts
 
@@ -332,7 +320,7 @@
     //       };
     //    };
     //
-    // Then locate_overlay_target_path(cstr!("/fragment@rng/__overlay__/rng")) is Ok("/rng")
+    // Then locate_overlay_target_path(c"/fragment@rng/__overlay__/rng") is Ok("/rng")
     //
     // Contrary to fdt_overlay_target_offset(), this API enforces overlay target property
     // 'target-path = "/"', so the overlay doesn't modify and/or append platform DT's existing
@@ -343,10 +331,9 @@
         dtbo_node: &FdtNode,
     ) -> Result<CString> {
         let fragment_node = dtbo_node.supernode_at_depth(1)?;
-        let target_path = fragment_node
-            .getprop_str(cstr!("target-path"))?
-            .ok_or(DeviceAssignmentError::InvalidDtbo)?;
-        if target_path != cstr!("/") {
+        let target_path =
+            fragment_node.getprop_str(c"target-path")?.ok_or(DeviceAssignmentError::InvalidDtbo)?;
+        if target_path != c"/" {
             return Err(DeviceAssignmentError::UnsupportedOverlayTarget);
         }
 
@@ -415,7 +402,7 @@
 
     /// Parses Physical devices in VM DTBO
     fn parse_physical_devices(&self) -> Result<BTreeMap<Phandle, PhysicalDeviceInfo>> {
-        let Some(physical_node) = self.as_ref().node(cstr!("/host"))? else {
+        let Some(physical_node) = self.as_ref().node(c"/host")? else {
             return Ok(BTreeMap::new());
         };
 
@@ -459,7 +446,7 @@
         let vm_dtbo = self.as_ref();
 
         let mut phandle_map = BTreeMap::new();
-        let Some(local_fixups) = vm_dtbo.node(cstr!("/__local_fixups__"))? else {
+        let Some(local_fixups) = vm_dtbo.node(c"/__local_fixups__")? else {
             return Ok(phandle_map);
         };
 
@@ -615,15 +602,14 @@
 
 impl PvIommu {
     fn parse(node: &FdtNode) -> Result<Self> {
-        let iommu_cells = node
-            .getprop_u32(cstr!("#iommu-cells"))?
-            .ok_or(DeviceAssignmentError::InvalidPvIommu)?;
+        let iommu_cells =
+            node.getprop_u32(c"#iommu-cells")?.ok_or(DeviceAssignmentError::InvalidPvIommu)?;
         // Ensures #iommu-cells = <1>. It means that `<iommus>` entry contains pair of
         // (pvIOMMU ID, vSID)
         if iommu_cells != 1 {
             return Err(DeviceAssignmentError::InvalidPvIommu);
         }
-        let id = node.getprop_u32(cstr!("id"))?.ok_or(DeviceAssignmentError::InvalidPvIommu)?;
+        let id = node.getprop_u32(c"id")?.ok_or(DeviceAssignmentError::InvalidPvIommu)?;
         Ok(Self { id })
     }
 }
@@ -687,10 +673,10 @@
 
 impl PhysIommu {
     fn parse(node: &FdtNode) -> Result<Option<Self>> {
-        let Some(token) = node.getprop_u64(cstr!("android,pvmfw,token"))? else {
+        let Some(token) = node.getprop_u64(c"android,pvmfw,token")? else {
             return Ok(None);
         };
-        let Some(iommu_cells) = node.getprop_u32(cstr!("#iommu-cells"))? else {
+        let Some(iommu_cells) = node.getprop_u32(c"#iommu-cells")? else {
             return Err(DeviceAssignmentError::InvalidPhysIommu);
         };
         // Currently only supports #iommu-cells = <1>.
@@ -715,7 +701,7 @@
         phys_iommus: &BTreeMap<Phandle, PhysIommu>,
     ) -> Result<Vec<(PhysIommu, Sid)>> {
         let mut iommus = vec![];
-        let Some(mut cells) = node.getprop_cells(cstr!("iommus"))? else {
+        let Some(mut cells) = node.getprop_cells(c"iommus")? else {
             return Ok(iommus);
         };
         while let Some(cell) = cells.next() {
@@ -735,7 +721,7 @@
     }
 
     fn parse(node: &FdtNode, phys_iommus: &BTreeMap<Phandle, PhysIommu>) -> Result<Option<Self>> {
-        let Some(phandle) = node.getprop_u32(cstr!("android,pvmfw,target"))? else {
+        let Some(phandle) = node.getprop_u32(c"android,pvmfw,target")? else {
             return Ok(None);
         };
         let target = Phandle::try_from(phandle)?;
@@ -812,7 +798,7 @@
         // Validation: Validate if interrupts cell numbers are multiple of #interrupt-cells.
         // We can't know how many interrupts would exist.
         let interrupts_cells = node
-            .getprop_cells(cstr!("interrupts"))?
+            .getprop_cells(c"interrupts")?
             .ok_or(DeviceAssignmentError::InvalidInterrupts)?
             .count();
         if interrupts_cells % CELLS_PER_INTERRUPT != 0 {
@@ -820,7 +806,7 @@
         }
 
         // Once validated, keep the raw bytes so patch can be done with setprop()
-        Ok(node.getprop(cstr!("interrupts")).unwrap().unwrap().into())
+        Ok(node.getprop(c"interrupts").unwrap().unwrap().into())
     }
 
     // TODO(b/277993056): Also validate /__local_fixups__ to ensure that <iommus> has phandle.
@@ -829,7 +815,7 @@
         pviommus: &BTreeMap<Phandle, PvIommu>,
     ) -> Result<Vec<(PvIommu, Vsid)>> {
         let mut iommus = vec![];
-        let Some(mut cells) = node.getprop_cells(cstr!("iommus"))? else {
+        let Some(mut cells) = node.getprop_cells(c"iommus")? else {
             return Ok(iommus);
         };
         while let Some(cell) = cells.next() {
@@ -917,15 +903,15 @@
 
     fn patch(&self, fdt: &mut Fdt, pviommu_phandles: &BTreeMap<PvIommu, Phandle>) -> Result<()> {
         let mut dst = fdt.node_mut(&self.node_path)?.unwrap();
-        dst.setprop(cstr!("reg"), &to_be_bytes(&self.reg))?;
-        dst.setprop(cstr!("interrupts"), &self.interrupts)?;
+        dst.setprop(c"reg", &to_be_bytes(&self.reg))?;
+        dst.setprop(c"interrupts", &self.interrupts)?;
         let mut iommus = Vec::with_capacity(8 * self.iommus.len());
         for (pviommu, vsid) in &self.iommus {
             let phandle = pviommu_phandles.get(pviommu).unwrap();
             iommus.extend_from_slice(&u32::from(*phandle).to_be_bytes());
             iommus.extend_from_slice(&vsid.0.to_be_bytes());
         }
-        dst.setprop(cstr!("iommus"), &iommus)?;
+        dst.setprop(c"iommus", &iommus)?;
 
         Ok(())
     }
@@ -939,7 +925,7 @@
 }
 
 impl DeviceAssignmentInfo {
-    const PVIOMMU_COMPATIBLE: &'static CStr = cstr!("pkvm,pviommu");
+    const PVIOMMU_COMPATIBLE: &'static CStr = c"pkvm,pviommu";
 
     /// Parses pvIOMMUs in fdt
     // Note: This will validate pvIOMMU ids' uniqueness, even when unassigned.
@@ -1046,8 +1032,8 @@
         Self::validate_pviommu_topology(&assigned_devices)?;
 
         let mut vm_dtbo_mask = vm_dtbo.build_mask(assigned_device_paths)?;
-        vm_dtbo_mask.mask_all(&DtPathTokens::new(cstr!("/__local_fixups__"))?);
-        vm_dtbo_mask.mask_all(&DtPathTokens::new(cstr!("/__symbols__"))?);
+        vm_dtbo_mask.mask_all(&DtPathTokens::new(c"/__local_fixups__")?);
+        vm_dtbo_mask.mask_all(&DtPathTokens::new(c"/__symbols__")?);
 
         // Note: Any node without __overlay__ will be ignored by fdt_apply_overlay,
         // so doesn't need to be filtered.
@@ -1060,7 +1046,7 @@
         let vm_dtbo = vm_dtbo.as_mut();
 
         // Filter unused references in /__local_fixups__
-        if let Some(local_fixups) = vm_dtbo.node_mut(cstr!("/__local_fixups__"))? {
+        if let Some(local_fixups) = vm_dtbo.node_mut(c"/__local_fixups__")? {
             filter_with_mask(local_fixups, &self.vm_dtbo_mask)?;
         }
 
@@ -1078,7 +1064,7 @@
         for pviommu in &self.pviommus {
             let mut node = compatible.ok_or(DeviceAssignmentError::TooManyPvIommu)?;
             let phandle = node.as_node().get_phandle()?.ok_or(DeviceAssignmentError::Internal)?;
-            node.setprop_inplace(cstr!("id"), &pviommu.id.to_be_bytes())?;
+            node.setprop_inplace(c"id", &pviommu.id.to_be_bytes())?;
             if pviommu_phandles.insert(*pviommu, phandle).is_some() {
                 return Err(DeviceAssignmentError::Internal);
             }
@@ -1108,10 +1094,10 @@
 
 /// Cleans device trees not to contain any pre-populated nodes/props for device assignment.
 pub fn clean(fdt: &mut Fdt) -> Result<()> {
-    let mut compatible = fdt.root_mut().next_compatible(cstr!("pkvm,pviommu"))?;
+    let mut compatible = fdt.root_mut().next_compatible(c"pkvm,pviommu")?;
     // Filters pre-populated
     while let Some(filtered_pviommu) = compatible {
-        compatible = filtered_pviommu.delete_and_next_compatible(cstr!("pkvm,pviommu"))?;
+        compatible = filtered_pviommu.delete_and_next_compatible(c"pkvm,pviommu")?;
     }
 
     // Removes any dangling references in __symbols__ (e.g. removed pvIOMMUs)
@@ -1239,24 +1225,23 @@
                 return Err(FdtError::NotFound.into());
             };
 
-            let reg = node.getprop(cstr!("reg"))?.ok_or(DeviceAssignmentError::MalformedReg)?;
-            let interrupts = node
-                .getprop(cstr!("interrupts"))?
-                .ok_or(DeviceAssignmentError::InvalidInterrupts)?;
+            let reg = node.getprop(c"reg")?.ok_or(DeviceAssignmentError::MalformedReg)?;
+            let interrupts =
+                node.getprop(c"interrupts")?.ok_or(DeviceAssignmentError::InvalidInterrupts)?;
             let mut iommus = vec![];
-            if let Some(mut cells) = node.getprop_cells(cstr!("iommus"))? {
+            if let Some(mut cells) = node.getprop_cells(c"iommus")? {
                 while let Some(pviommu_id) = cells.next() {
                     // pvIOMMU id
                     let phandle = Phandle::try_from(pviommu_id)?;
                     let pviommu = fdt
                         .node_with_phandle(phandle)?
                         .ok_or(DeviceAssignmentError::MalformedIommus)?;
-                    let compatible = pviommu.getprop_str(cstr!("compatible"));
-                    if compatible != Ok(Some(cstr!("pkvm,pviommu"))) {
+                    let compatible = pviommu.getprop_str(c"compatible");
+                    if compatible != Ok(Some(c"pkvm,pviommu")) {
                         return Err(DeviceAssignmentError::MalformedIommus);
                     }
                     let id = pviommu
-                        .getprop_u32(cstr!("id"))?
+                        .getprop_u32(c"id")?
                         .ok_or(DeviceAssignmentError::MalformedIommus)?;
                     iommus.push(id);
 
@@ -1273,8 +1258,8 @@
 
     fn collect_pviommus(fdt: &Fdt) -> Result<Vec<u32>> {
         let mut pviommus = BTreeSet::new();
-        for pviommu in fdt.compatible_nodes(cstr!("pkvm,pviommu"))? {
-            if let Ok(Some(id)) = pviommu.getprop_u32(cstr!("id")) {
+        for pviommu in fdt.compatible_nodes(c"pkvm,pviommu")? {
+            if let Ok(Some(id)) = pviommu.getprop_u32(c"id") {
                 pviommus.insert(id);
             }
         }
@@ -1395,24 +1380,24 @@
 
         let symbols = vm_dtbo.symbols().unwrap().unwrap();
 
-        let rng = vm_dtbo.node(cstr!("/fragment@0/__overlay__/rng")).unwrap();
+        let rng = vm_dtbo.node(c"/fragment@0/__overlay__/rng").unwrap();
         assert_ne!(rng, None);
-        let rng_symbol = symbols.getprop_str(cstr!("rng")).unwrap();
-        assert_eq!(Some(cstr!("/fragment@0/__overlay__/rng")), rng_symbol);
+        let rng_symbol = symbols.getprop_str(c"rng").unwrap();
+        assert_eq!(Some(c"/fragment@0/__overlay__/rng"), rng_symbol);
 
-        let light = vm_dtbo.node(cstr!("/fragment@0/__overlay__/light")).unwrap();
+        let light = vm_dtbo.node(c"/fragment@0/__overlay__/light").unwrap();
         assert_eq!(light, None);
-        let light_symbol = symbols.getprop_str(cstr!("light")).unwrap();
+        let light_symbol = symbols.getprop_str(c"light").unwrap();
         assert_eq!(None, light_symbol);
 
-        let led = vm_dtbo.node(cstr!("/fragment@0/__overlay__/led")).unwrap();
+        let led = vm_dtbo.node(c"/fragment@0/__overlay__/led").unwrap();
         assert_eq!(led, None);
-        let led_symbol = symbols.getprop_str(cstr!("led")).unwrap();
+        let led_symbol = symbols.getprop_str(c"led").unwrap();
         assert_eq!(None, led_symbol);
 
-        let backlight = vm_dtbo.node(cstr!("/fragment@0/__overlay__/bus0/backlight")).unwrap();
+        let backlight = vm_dtbo.node(c"/fragment@0/__overlay__/bus0/backlight").unwrap();
         assert_eq!(backlight, None);
-        let backlight_symbol = symbols.getprop_str(cstr!("backlight")).unwrap();
+        let backlight_symbol = symbols.getprop_str(c"backlight").unwrap();
         assert_eq!(None, backlight_symbol);
     }
 
@@ -1440,19 +1425,19 @@
         }
         device_info.patch(platform_dt).unwrap();
 
-        let rng_node = platform_dt.node(cstr!("/bus0/backlight")).unwrap().unwrap();
-        let phandle = rng_node.getprop_u32(cstr!("phandle")).unwrap();
+        let rng_node = platform_dt.node(c"/bus0/backlight").unwrap().unwrap();
+        let phandle = rng_node.getprop_u32(c"phandle").unwrap();
         assert_ne!(None, phandle);
 
         // Note: Intentionally not using AssignedDeviceNode for matching all props.
         type FdtResult<T> = libfdt::Result<T>;
         let expected: Vec<(FdtResult<&CStr>, FdtResult<Vec<u8>>)> = vec![
-            (Ok(cstr!("android,backlight,ignore-gctrl-reset")), Ok(Vec::new())),
-            (Ok(cstr!("compatible")), Ok(Vec::from(*b"android,backlight\0"))),
-            (Ok(cstr!("interrupts")), Ok(into_fdt_prop(vec![0x0, 0xF, 0x4]))),
-            (Ok(cstr!("iommus")), Ok(Vec::new())),
-            (Ok(cstr!("phandle")), Ok(into_fdt_prop(vec![phandle.unwrap()]))),
-            (Ok(cstr!("reg")), Ok(into_fdt_prop(vec![0x0, 0x9, 0x0, 0xFF]))),
+            (Ok(c"android,backlight,ignore-gctrl-reset"), Ok(Vec::new())),
+            (Ok(c"compatible"), Ok(Vec::from(*b"android,backlight\0"))),
+            (Ok(c"interrupts"), Ok(into_fdt_prop(vec![0x0, 0xF, 0x4]))),
+            (Ok(c"iommus"), Ok(Vec::new())),
+            (Ok(c"phandle"), Ok(into_fdt_prop(vec![phandle.unwrap()]))),
+            (Ok(c"reg"), Ok(into_fdt_prop(vec![0x0, 0x9, 0x0, 0xFF]))),
         ];
 
         let mut properties: Vec<_> = rng_node
@@ -1493,7 +1478,7 @@
         }
         device_info.patch(platform_dt).unwrap();
 
-        let compatible = platform_dt.root().next_compatible(cstr!("pkvm,pviommu")).unwrap();
+        let compatible = platform_dt.root().next_compatible(c"pkvm,pviommu").unwrap();
         assert_eq!(None, compatible);
 
         if let Some(symbols) = platform_dt.symbols().unwrap() {
@@ -1794,12 +1779,12 @@
         let mut platform_dt_data = pvmfw_fdt_template::RAW.to_vec();
         let platform_dt = Fdt::from_mut_slice(&mut platform_dt_data).unwrap();
 
-        let compatible = platform_dt.root().next_compatible(cstr!("pkvm,pviommu"));
+        let compatible = platform_dt.root().next_compatible(c"pkvm,pviommu");
         assert_ne!(None, compatible.unwrap());
 
         clean(platform_dt).unwrap();
 
-        let compatible = platform_dt.root().next_compatible(cstr!("pkvm,pviommu"));
+        let compatible = platform_dt.root().next_compatible(c"pkvm,pviommu");
         assert_eq!(Ok(None), compatible);
     }
 
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 4370675..29212f9 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -28,7 +28,6 @@
 use core::fmt;
 use core::mem::size_of;
 use core::ops::Range;
-use cstr::cstr;
 use hypervisor_backends::get_device_assigner;
 use hypervisor_backends::get_mem_sharer;
 use libfdt::AddressRange;
@@ -83,10 +82,10 @@
 /// Extract from /config the address range containing the pre-loaded kernel. Absence of /config is
 /// not an error.
 pub fn read_kernel_range_from(fdt: &Fdt) -> libfdt::Result<Option<Range<usize>>> {
-    let addr = cstr!("kernel-address");
-    let size = cstr!("kernel-size");
+    let addr = c"kernel-address";
+    let size = c"kernel-size";
 
-    if let Some(config) = fdt.node(cstr!("/config"))? {
+    if let Some(config) = fdt.node(c"/config")? {
         if let (Some(addr), Some(size)) = (config.getprop_u32(addr)?, config.getprop_u32(size)?) {
             let addr = addr as usize;
             let size = size as usize;
@@ -101,8 +100,8 @@
 /// Extract from /chosen the address range containing the pre-loaded ramdisk. Absence is not an
 /// error as there can be initrd-less VM.
 pub fn read_initrd_range_from(fdt: &Fdt) -> libfdt::Result<Option<Range<usize>>> {
-    let start = cstr!("linux,initrd-start");
-    let end = cstr!("linux,initrd-end");
+    let start = c"linux,initrd-start";
+    let end = c"linux,initrd-end";
 
     if let Some(chosen) = fdt.chosen()? {
         if let (Some(start), Some(end)) = (chosen.getprop_u32(start)?, chosen.getprop_u32(end)?) {
@@ -118,14 +117,14 @@
     let end = u32::try_from(initrd_range.end).unwrap();
 
     let mut node = fdt.chosen_mut()?.ok_or(FdtError::NotFound)?;
-    node.setprop(cstr!("linux,initrd-start"), &start.to_be_bytes())?;
-    node.setprop(cstr!("linux,initrd-end"), &end.to_be_bytes())?;
+    node.setprop(c"linux,initrd-start", &start.to_be_bytes())?;
+    node.setprop(c"linux,initrd-end", &end.to_be_bytes())?;
     Ok(())
 }
 
 fn read_bootargs_from(fdt: &Fdt) -> libfdt::Result<Option<CString>> {
     if let Some(chosen) = fdt.chosen()? {
-        if let Some(bootargs) = chosen.getprop_str(cstr!("bootargs"))? {
+        if let Some(bootargs) = chosen.getprop_str(c"bootargs")? {
             // We need to copy the string to heap because the original fdt will be invalidated
             // by the templated DT
             let copy = CString::new(bootargs.to_bytes()).map_err(|_| FdtError::BadValue)?;
@@ -140,7 +139,7 @@
     // This function is called before the verification is done. So, we just copy the bootargs to
     // the new FDT unmodified. This will be filtered again in the modify_for_next_stage function
     // if the VM is not debuggable.
-    node.setprop(cstr!("bootargs"), bootargs.to_bytes_with_nul())
+    node.setprop(c"bootargs", bootargs.to_bytes_with_nul())
 }
 
 /// Reads and validates the memory range in the DT.
@@ -186,9 +185,9 @@
 fn patch_memory_range(fdt: &mut Fdt, memory_range: &Range<usize>) -> libfdt::Result<()> {
     let addr = u64::try_from(MEM_START).unwrap();
     let size = u64::try_from(memory_range.len()).unwrap();
-    fdt.node_mut(cstr!("/memory"))?
+    fdt.node_mut(c"/memory")?
         .ok_or(FdtError::NotFound)?
-        .setprop_inplace(cstr!("reg"), [addr.to_be(), size.to_be()].as_bytes())
+        .setprop_inplace(c"reg", [addr.to_be(), size.to_be()].as_bytes())
 }
 
 #[derive(Debug, Default)]
@@ -207,7 +206,7 @@
     let mut table = ArrayVec::new();
     let mut opp_nodes = opp_node.subnodes()?;
     for subnode in opp_nodes.by_ref().take(table.capacity()) {
-        let prop = subnode.getprop_u64(cstr!("opp-hz"))?.ok_or(FdtError::NotFound)?;
+        let prop = subnode.getprop_u64(c"opp-hz")?.ok_or(FdtError::NotFound)?;
         table.push(prop);
     }
 
@@ -239,7 +238,7 @@
 }
 
 fn read_cpu_map_from(fdt: &Fdt) -> libfdt::Result<Option<BTreeMap<Phandle, (usize, usize)>>> {
-    let Some(cpu_map) = fdt.node(cstr!("/cpus/cpu-map"))? else {
+    let Some(cpu_map) = fdt.node(c"/cpus/cpu-map")? else {
         return Ok(None);
     };
 
@@ -254,7 +253,7 @@
             let Some(core) = cluster.subnode(&name)? else {
                 break;
             };
-            let cpu = core.getprop_u32(cstr!("cpu"))?.ok_or(FdtError::NotFound)?;
+            let cpu = core.getprop_u32(c"cpu")?.ok_or(FdtError::NotFound)?;
             let prev = topology.insert(cpu.try_into()?, (n, m));
             if prev.is_some() {
                 return Err(FdtError::BadValue);
@@ -273,10 +272,10 @@
     let cpu_map = read_cpu_map_from(fdt)?;
     let mut topology: CpuTopology = Default::default();
 
-    let mut cpu_nodes = fdt.compatible_nodes(cstr!("arm,armv8"))?;
+    let mut cpu_nodes = fdt.compatible_nodes(c"arm,armv8")?;
     for (idx, cpu) in cpu_nodes.by_ref().take(cpus.capacity()).enumerate() {
-        let cpu_capacity = cpu.getprop_u32(cstr!("capacity-dmips-mhz"))?;
-        let opp_phandle = cpu.getprop_u32(cstr!("operating-points-v2"))?;
+        let cpu_capacity = cpu.getprop_u32(c"capacity-dmips-mhz")?;
+        let opp_phandle = cpu.getprop_u32(c"operating-points-v2")?;
         let opptable_info = if let Some(phandle) = opp_phandle {
             let phandle = phandle.try_into()?;
             let node = fdt.node_with_phandle(phandle)?.ok_or(FdtError::NotFound)?;
@@ -313,7 +312,7 @@
 }
 
 fn read_vcpufreq_info(fdt: &Fdt) -> libfdt::Result<Option<VcpufreqInfo>> {
-    let mut nodes = fdt.compatible_nodes(cstr!("virtual,android-v-only-cpufreq"))?;
+    let mut nodes = fdt.compatible_nodes(c"virtual,android-v-only-cpufreq")?;
     let Some(node) = nodes.next() else {
         return Ok(None);
     };
@@ -351,7 +350,7 @@
     node: FdtNodeMut,
     opptable: Option<ArrayVec<[u64; CpuInfo::MAX_OPPTABLES]>>,
 ) -> libfdt::Result<()> {
-    let oppcompat = cstr!("operating-points-v2");
+    let oppcompat = c"operating-points-v2";
     let next = node.next_compatible(oppcompat)?.ok_or(FdtError::NoSpace)?;
 
     let Some(opptable) = opptable else {
@@ -362,7 +361,7 @@
 
     for entry in opptable {
         let mut subnode = next_subnode.ok_or(FdtError::NoSpace)?;
-        subnode.setprop_inplace(cstr!("opp-hz"), &entry.to_be_bytes())?;
+        subnode.setprop_inplace(c"opp-hz", &entry.to_be_bytes())?;
         next_subnode = subnode.next_subnode()?;
     }
 
@@ -391,14 +390,14 @@
     cpus: &[CpuInfo],
     topology: &Option<CpuTopology>,
 ) -> libfdt::Result<()> {
-    const COMPAT: &CStr = cstr!("arm,armv8");
+    const COMPAT: &CStr = c"arm,armv8";
     let mut cpu_phandles = Vec::new();
     for (idx, cpu) in cpus.iter().enumerate() {
         let mut cur = get_nth_compatible(fdt, idx, COMPAT)?.ok_or(FdtError::NoSpace)?;
         let phandle = cur.as_node().get_phandle()?.unwrap();
         cpu_phandles.push(phandle);
         if let Some(cpu_capacity) = cpu.cpu_capacity {
-            cur.setprop_inplace(cstr!("capacity-dmips-mhz"), &cpu_capacity.to_be_bytes())?;
+            cur.setprop_inplace(c"capacity-dmips-mhz", &cpu_capacity.to_be_bytes())?;
         }
         patch_opptable(cur, cpu.opptable_info)?;
     }
@@ -418,7 +417,7 @@
                     iter = if let Some(core_idx) = core {
                         let phandle = *cpu_phandles.get(core_idx).unwrap();
                         let value = u32::from(phandle).to_be_bytes();
-                        core_node.setprop_inplace(cstr!("cpu"), &value)?;
+                        core_node.setprop_inplace(c"cpu", &value)?;
                         core_node.next_subnode()?
                     } else {
                         core_node.delete_and_next_subnode()?
@@ -430,7 +429,7 @@
             }
         }
     } else {
-        fdt.node_mut(cstr!("/cpus/cpu-map"))?.unwrap().nop()?;
+        fdt.node_mut(c"/cpus/cpu-map")?.unwrap().nop()?;
     }
 
     Ok(())
@@ -440,7 +439,7 @@
 /// the guest that don't require being validated by pvmfw.
 fn parse_untrusted_props(fdt: &Fdt) -> libfdt::Result<BTreeMap<CString, Vec<u8>>> {
     let mut props = BTreeMap::new();
-    if let Some(node) = fdt.node(cstr!("/avf/untrusted"))? {
+    if let Some(node) = fdt.node(c"/avf/untrusted")? {
         for property in node.properties()? {
             let name = property.name()?;
             let value = property.value()?;
@@ -457,7 +456,7 @@
 /// Read candidate properties' names from DT which could be overlaid
 fn parse_vm_ref_dt(fdt: &Fdt) -> libfdt::Result<BTreeMap<CString, Vec<u8>>> {
     let mut property_map = BTreeMap::new();
-    if let Some(avf_node) = fdt.node(cstr!("/avf"))? {
+    if let Some(avf_node) = fdt.node(c"/avf")? {
         for property in avf_node.properties()? {
             let name = property.name()?;
             let value = property.value()?;
@@ -471,8 +470,7 @@
 }
 
 fn validate_untrusted_props(props: &BTreeMap<CString, Vec<u8>>) -> Result<(), FdtValidationError> {
-    const FORBIDDEN_PROPS: &[&CStr] =
-        &[cstr!("compatible"), cstr!("linux,phandle"), cstr!("phandle")];
+    const FORBIDDEN_PROPS: &[&CStr] = &[c"compatible", c"linux,phandle", c"phandle"];
 
     for name in FORBIDDEN_PROPS {
         if props.contains_key(*name) {
@@ -491,9 +489,9 @@
     props_info: &BTreeMap<CString, Vec<u8>>,
 ) -> libfdt::Result<()> {
     let root_vm_dt = vm_dt.root_mut();
-    let mut avf_vm_dt = root_vm_dt.add_subnode(cstr!("avf"))?;
+    let mut avf_vm_dt = root_vm_dt.add_subnode(c"avf")?;
     // TODO(b/318431677): Validate nodes beyond /avf.
-    let avf_node = vm_ref_dt.node(cstr!("/avf"))?.ok_or(FdtError::NotFound)?;
+    let avf_node = vm_ref_dt.node(c"/avf")?.ok_or(FdtError::NotFound)?;
     for (name, value) in props_info.iter() {
         if let Some(ref_value) = avf_node.getprop(name)? {
             if value != ref_value {
@@ -551,14 +549,13 @@
 
 /// Read pci host controller ranges, irq maps, and irq map masks from DT
 fn read_pci_info_from(fdt: &Fdt) -> libfdt::Result<PciInfo> {
-    let node =
-        fdt.compatible_nodes(cstr!("pci-host-cam-generic"))?.next().ok_or(FdtError::NotFound)?;
+    let node = fdt.compatible_nodes(c"pci-host-cam-generic")?.next().ok_or(FdtError::NotFound)?;
 
     let mut ranges = node.ranges::<(u32, u64), u64, u64>()?.ok_or(FdtError::NotFound)?;
     let range0 = ranges.next().ok_or(FdtError::NotFound)?;
     let range1 = ranges.next().ok_or(FdtError::NotFound)?;
 
-    let irq_masks = node.getprop_cells(cstr!("interrupt-map-mask"))?.ok_or(FdtError::NotFound)?;
+    let irq_masks = node.getprop_cells(c"interrupt-map-mask")?.ok_or(FdtError::NotFound)?;
     let mut chunks = CellChunkIterator::<{ PciInfo::IRQ_MASK_CELLS }>::new(irq_masks);
     let irq_masks = (&mut chunks).take(PciInfo::MAX_IRQS).collect();
 
@@ -567,7 +564,7 @@
         return Err(FdtError::NoSpace);
     }
 
-    let irq_maps = node.getprop_cells(cstr!("interrupt-map"))?.ok_or(FdtError::NotFound)?;
+    let irq_maps = node.getprop_cells(c"interrupt-map")?.ok_or(FdtError::NotFound)?;
     let mut chunks = CellChunkIterator::<{ PciInfo::IRQ_MAP_CELLS }>::new(irq_maps);
     let irq_maps = (&mut chunks).take(PciInfo::MAX_IRQS).collect();
 
@@ -721,16 +718,16 @@
 
 fn patch_pci_info(fdt: &mut Fdt, pci_info: &PciInfo) -> libfdt::Result<()> {
     let mut node =
-        fdt.root_mut().next_compatible(cstr!("pci-host-cam-generic"))?.ok_or(FdtError::NotFound)?;
+        fdt.root_mut().next_compatible(c"pci-host-cam-generic")?.ok_or(FdtError::NotFound)?;
 
     let irq_masks_size = pci_info.irq_masks.len() * size_of::<PciIrqMask>();
-    node.trimprop(cstr!("interrupt-map-mask"), irq_masks_size)?;
+    node.trimprop(c"interrupt-map-mask", irq_masks_size)?;
 
     let irq_maps_size = pci_info.irq_maps.len() * size_of::<PciIrqMap>();
-    node.trimprop(cstr!("interrupt-map"), irq_maps_size)?;
+    node.trimprop(c"interrupt-map", irq_maps_size)?;
 
     node.setprop_inplace(
-        cstr!("ranges"),
+        c"ranges",
         [pci_info.ranges[0].to_cells(), pci_info.ranges[1].to_cells()].as_flattened(),
     )
 }
@@ -747,7 +744,7 @@
 fn read_serial_info_from(fdt: &Fdt) -> libfdt::Result<SerialInfo> {
     let mut addrs = ArrayVec::new();
 
-    let mut serial_nodes = fdt.compatible_nodes(cstr!("ns16550a"))?;
+    let mut serial_nodes = fdt.compatible_nodes(c"ns16550a")?;
     for node in serial_nodes.by_ref().take(addrs.capacity()) {
         let reg = node.first_reg()?;
         addrs.push(reg.addr);
@@ -793,7 +790,7 @@
 }
 
 fn read_wdt_info_from(fdt: &Fdt) -> libfdt::Result<WdtInfo> {
-    let mut node_iter = fdt.compatible_nodes(cstr!("qemu,vcpu-stall-detector"))?;
+    let mut node_iter = fdt.compatible_nodes(c"qemu,vcpu-stall-detector")?;
     let node = node_iter.next().ok_or(FdtError::NotFound)?;
     let mut ranges = node.reg()?.ok_or(FdtError::NotFound)?;
 
@@ -803,7 +800,7 @@
         warn!("Discarding extra vmwdt <reg> entries.");
     }
 
-    let interrupts = node.getprop_cells(cstr!("interrupts"))?.ok_or(FdtError::NotFound)?;
+    let interrupts = node.getprop_cells(c"interrupts")?.ok_or(FdtError::NotFound)?;
     let mut chunks = CellChunkIterator::<{ WdtInfo::IRQ_CELLS }>::new(interrupts);
     let irq = chunks.next().ok_or(FdtError::NotFound)?;
 
@@ -831,15 +828,15 @@
 
     let mut node = fdt
         .root_mut()
-        .next_compatible(cstr!("qemu,vcpu-stall-detector"))?
+        .next_compatible(c"qemu,vcpu-stall-detector")?
         .ok_or(libfdt::FdtError::NotFound)?;
-    node.setprop_inplace(cstr!("interrupts"), interrupts.as_bytes())?;
+    node.setprop_inplace(c"interrupts", interrupts.as_bytes())?;
     Ok(())
 }
 
 /// Patch the DT by deleting the ns16550a compatible nodes whose address are unknown
 fn patch_serial_info(fdt: &mut Fdt, serial_info: &SerialInfo) -> libfdt::Result<()> {
-    let name = cstr!("ns16550a");
+    let name = c"ns16550a";
     let mut next = fdt.root_mut().next_compatible(name);
     while let Some(current) = next? {
         let reg =
@@ -889,27 +886,27 @@
 
 fn patch_swiotlb_info(fdt: &mut Fdt, swiotlb_info: &SwiotlbInfo) -> libfdt::Result<()> {
     let mut node =
-        fdt.root_mut().next_compatible(cstr!("restricted-dma-pool"))?.ok_or(FdtError::NotFound)?;
+        fdt.root_mut().next_compatible(c"restricted-dma-pool")?.ok_or(FdtError::NotFound)?;
 
     if let Some(range) = swiotlb_info.fixed_range() {
         node.setprop_addrrange_inplace(
-            cstr!("reg"),
+            c"reg",
             range.start.try_into().unwrap(),
             range.len().try_into().unwrap(),
         )?;
-        node.nop_property(cstr!("size"))?;
-        node.nop_property(cstr!("alignment"))?;
+        node.nop_property(c"size")?;
+        node.nop_property(c"alignment")?;
     } else {
-        node.nop_property(cstr!("reg"))?;
-        node.setprop_inplace(cstr!("size"), &swiotlb_info.size.to_be_bytes())?;
-        node.setprop_inplace(cstr!("alignment"), &swiotlb_info.align.unwrap().to_be_bytes())?;
+        node.nop_property(c"reg")?;
+        node.setprop_inplace(c"size", &swiotlb_info.size.to_be_bytes())?;
+        node.setprop_inplace(c"alignment", &swiotlb_info.align.unwrap().to_be_bytes())?;
     }
 
     Ok(())
 }
 
 fn patch_gic(fdt: &mut Fdt, num_cpus: usize) -> libfdt::Result<()> {
-    let node = fdt.compatible_nodes(cstr!("arm,gic-v3"))?.next().ok_or(FdtError::NotFound)?;
+    let node = fdt.compatible_nodes(c"arm,gic-v3")?.next().ok_or(FdtError::NotFound)?;
     let mut ranges = node.reg()?.ok_or(FdtError::NotFound)?;
     let range0 = ranges.next().ok_or(FdtError::NotFound)?;
     let mut range1 = ranges.next().ok_or(FdtError::NotFound)?;
@@ -927,16 +924,15 @@
     let (addr1, size1) = range1.to_cells();
     let value = [addr0, size0.unwrap(), addr1, size1.unwrap()];
 
-    let mut node =
-        fdt.root_mut().next_compatible(cstr!("arm,gic-v3"))?.ok_or(FdtError::NotFound)?;
-    node.setprop_inplace(cstr!("reg"), value.as_flattened())
+    let mut node = fdt.root_mut().next_compatible(c"arm,gic-v3")?.ok_or(FdtError::NotFound)?;
+    node.setprop_inplace(c"reg", value.as_flattened())
 }
 
 fn patch_timer(fdt: &mut Fdt, num_cpus: usize) -> libfdt::Result<()> {
     const NUM_INTERRUPTS: usize = 4;
     const CELLS_PER_INTERRUPT: usize = 3;
-    let node = fdt.compatible_nodes(cstr!("arm,armv8-timer"))?.next().ok_or(FdtError::NotFound)?;
-    let interrupts = node.getprop_cells(cstr!("interrupts"))?.ok_or(FdtError::NotFound)?;
+    let node = fdt.compatible_nodes(c"arm,armv8-timer")?.next().ok_or(FdtError::NotFound)?;
+    let interrupts = node.getprop_cells(c"interrupts")?.ok_or(FdtError::NotFound)?;
     let mut value: ArrayVec<[u32; NUM_INTERRUPTS * CELLS_PER_INTERRUPT]> =
         interrupts.take(NUM_INTERRUPTS * CELLS_PER_INTERRUPT).collect();
 
@@ -953,20 +949,19 @@
 
     let value = value.into_inner();
 
-    let mut node =
-        fdt.root_mut().next_compatible(cstr!("arm,armv8-timer"))?.ok_or(FdtError::NotFound)?;
-    node.setprop_inplace(cstr!("interrupts"), value.as_bytes())
+    let mut node = fdt.root_mut().next_compatible(c"arm,armv8-timer")?.ok_or(FdtError::NotFound)?;
+    node.setprop_inplace(c"interrupts", value.as_bytes())
 }
 
 fn patch_untrusted_props(fdt: &mut Fdt, props: &BTreeMap<CString, Vec<u8>>) -> libfdt::Result<()> {
-    let avf_node = if let Some(node) = fdt.node_mut(cstr!("/avf"))? {
+    let avf_node = if let Some(node) = fdt.node_mut(c"/avf")? {
         node
     } else {
-        fdt.root_mut().add_subnode(cstr!("avf"))?
+        fdt.root_mut().add_subnode(c"avf")?
     };
 
     // The node shouldn't already be present; if it is, return the error.
-    let mut node = avf_node.add_subnode(cstr!("untrusted"))?;
+    let mut node = avf_node.add_subnode(c"untrusted")?;
 
     for (name, value) in props {
         node.setprop(name, value)?;
@@ -982,9 +977,9 @@
 }
 
 fn patch_vcpufreq(fdt: &mut Fdt, vcpufreq_info: &Option<VcpufreqInfo>) -> libfdt::Result<()> {
-    let mut node = fdt.node_mut(cstr!("/cpufreq"))?.unwrap();
+    let mut node = fdt.node_mut(c"/cpufreq")?.unwrap();
     if let Some(info) = vcpufreq_info {
-        node.setprop_addrrange_inplace(cstr!("reg"), info.addr, info.size)
+        node.setprop_addrrange_inplace(c"reg", info.addr, info.size)
     } else {
         node.nop()
     }
@@ -1304,9 +1299,9 @@
     patch_dice_node(fdt, bcc.as_ptr() as usize, bcc.len())?;
 
     if let Some(mut chosen) = fdt.chosen_mut()? {
-        empty_or_delete_prop(&mut chosen, cstr!("avf,strict-boot"), strict_boot)?;
-        empty_or_delete_prop(&mut chosen, cstr!("avf,new-instance"), new_instance)?;
-        chosen.setprop_inplace(cstr!("kaslr-seed"), &kaslr_seed.to_be_bytes())?;
+        empty_or_delete_prop(&mut chosen, c"avf,strict-boot", strict_boot)?;
+        empty_or_delete_prop(&mut chosen, c"avf,new-instance", new_instance)?;
+        chosen.setprop_inplace(c"kaslr-seed", &kaslr_seed.to_be_bytes())?;
     };
     if !debuggable {
         if let Some(bootargs) = read_bootargs_from(fdt)? {
@@ -1323,13 +1318,13 @@
 fn patch_dice_node(fdt: &mut Fdt, addr: usize, size: usize) -> libfdt::Result<()> {
     // We reject DTs with missing reserved-memory node as validation should have checked that the
     // "swiotlb" subnode (compatible = "restricted-dma-pool") was present.
-    let node = fdt.node_mut(cstr!("/reserved-memory"))?.ok_or(libfdt::FdtError::NotFound)?;
+    let node = fdt.node_mut(c"/reserved-memory")?.ok_or(libfdt::FdtError::NotFound)?;
 
-    let mut node = node.next_compatible(cstr!("google,open-dice"))?.ok_or(FdtError::NotFound)?;
+    let mut node = node.next_compatible(c"google,open-dice")?.ok_or(FdtError::NotFound)?;
 
     let addr: u64 = addr.try_into().unwrap();
     let size: u64 = size.try_into().unwrap();
-    node.setprop_inplace(cstr!("reg"), [addr.to_be_bytes(), size.to_be_bytes()].as_flattened())
+    node.setprop_inplace(c"reg", [addr.to_be_bytes(), size.to_be_bytes()].as_flattened())
 }
 
 fn empty_or_delete_prop(
@@ -1376,7 +1371,7 @@
 }
 
 fn has_common_debug_policy(fdt: &Fdt, debug_feature_name: &CStr) -> libfdt::Result<bool> {
-    if let Some(node) = fdt.node(cstr!("/avf/guest/common"))? {
+    if let Some(node) = fdt.node(c"/avf/guest/common")? {
         if let Some(value) = node.getprop_u32(debug_feature_name)? {
             return Ok(value == 1);
         }
@@ -1385,8 +1380,8 @@
 }
 
 fn filter_out_dangerous_bootargs(fdt: &mut Fdt, bootargs: &CStr) -> libfdt::Result<()> {
-    let has_crashkernel = has_common_debug_policy(fdt, cstr!("ramdump"))?;
-    let has_console = has_common_debug_policy(fdt, cstr!("log"))?;
+    let has_crashkernel = has_common_debug_policy(fdt, c"ramdump")?;
+    let has_console = has_common_debug_policy(fdt, c"log")?;
 
     let accepted: &[(&str, Box<dyn Fn(Option<&str>) -> bool>)] = &[
         ("panic", Box::new(|v| if let Some(v) = v { v == "=-1" } else { false })),
@@ -1417,5 +1412,5 @@
     new_bootargs.push(b'\0');
 
     let mut node = fdt.chosen_mut()?.ok_or(FdtError::NotFound)?;
-    node.setprop(cstr!("bootargs"), new_bootargs.as_slice())
+    node.setprop(c"bootargs", new_bootargs.as_slice())
 }
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index a28a039..5ff9c4c 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -40,7 +40,6 @@
 use alloc::borrow::Cow;
 use alloc::boxed::Box;
 use bssl_avf::Digester;
-use cstr::cstr;
 use diced_open_dice::{bcc_handover_parse, DiceArtifacts, DiceContext, Hidden, VM_KEY_ALGORITHM};
 use libfdt::{Fdt, FdtNode};
 use log::{debug, error, info, trace, warn};
@@ -220,7 +219,7 @@
 
 fn instance_id(fdt: &Fdt) -> Result<&[u8], RebootReason> {
     let node = avf_untrusted_node(fdt)?;
-    let id = node.getprop(cstr!("instance-id")).map_err(|e| {
+    let id = node.getprop(c"instance-id").map_err(|e| {
         error!("Failed to get instance-id in DT: {e}");
         RebootReason::InvalidFdt
     })?;
@@ -231,7 +230,7 @@
 }
 
 fn avf_untrusted_node(fdt: &Fdt) -> Result<FdtNode, RebootReason> {
-    let node = fdt.node(cstr!("/avf/untrusted")).map_err(|e| {
+    let node = fdt.node(c"/avf/untrusted").map_err(|e| {
         error!("Failed to get /avf/untrusted node: {e}");
         RebootReason::InvalidFdt
     })?;
diff --git a/guest/pvmfw/src/rollback.rs b/guest/pvmfw/src/rollback.rs
index bc16332..15d22b3 100644
--- a/guest/pvmfw/src/rollback.rs
+++ b/guest/pvmfw/src/rollback.rs
@@ -19,7 +19,6 @@
 use crate::instance::EntryBody;
 use crate::instance::Error as InstanceError;
 use crate::instance::{get_recorded_entry, record_instance_entry};
-use cstr::cstr;
 use diced_open_dice::Hidden;
 use libfdt::{Fdt, FdtNode};
 use log::{error, info};
@@ -138,7 +137,7 @@
 fn should_defer_rollback_protection(fdt: &Fdt) -> Result<bool, RebootReason> {
     let node = avf_untrusted_node(fdt)?;
     let defer_rbp = node
-        .getprop(cstr!("defer-rollback-protection"))
+        .getprop(c"defer-rollback-protection")
         .map_err(|e| {
             error!("Failed to get defer-rollback-protection property in DT: {e}");
             RebootReason::InvalidFdt
@@ -148,7 +147,7 @@
 }
 
 fn avf_untrusted_node(fdt: &Fdt) -> Result<FdtNode, RebootReason> {
-    let node = fdt.node(cstr!("/avf/untrusted")).map_err(|e| {
+    let node = fdt.node(c"/avf/untrusted").map_err(|e| {
         error!("Failed to get /avf/untrusted node: {e}");
         RebootReason::InvalidFdt
     })?;
diff --git a/guest/rialto/Android.bp b/guest/rialto/Android.bp
index a525168..35ede7a 100644
--- a/guest/rialto/Android.bp
+++ b/guest/rialto/Android.bp
@@ -12,7 +12,6 @@
         "libbssl_avf_nostd",
         "libciborium_io_nostd",
         "libciborium_nostd",
-        "libcstr",
         "libdiced_open_dice_nostd",
         "libhypervisor_backends",
         "liblibfdt_nostd",
diff --git a/guest/rialto/src/fdt.rs b/guest/rialto/src/fdt.rs
index e97a262..06879d0 100644
--- a/guest/rialto/src/fdt.rs
+++ b/guest/rialto/src/fdt.rs
@@ -15,24 +15,23 @@
 //! High-level FDT functions.
 
 use core::ops::Range;
-use cstr::cstr;
 use libfdt::{Fdt, FdtError};
 
 /// Reads the DICE data range from the given `fdt`.
 pub fn read_dice_range_from(fdt: &Fdt) -> libfdt::Result<Range<usize>> {
-    let node = fdt.node(cstr!("/reserved-memory"))?.ok_or(FdtError::NotFound)?;
-    let node = node.next_compatible(cstr!("google,open-dice"))?.ok_or(FdtError::NotFound)?;
+    let node = fdt.node(c"/reserved-memory")?.ok_or(FdtError::NotFound)?;
+    let node = node.next_compatible(c"google,open-dice")?.ok_or(FdtError::NotFound)?;
     node.first_reg()?.try_into()
 }
 
 pub(crate) fn read_vendor_hashtree_root_digest(fdt: &Fdt) -> libfdt::Result<Option<&[u8]>> {
-    let node = fdt.node(cstr!("/avf"))?.ok_or(FdtError::NotFound)?;
-    node.getprop(cstr!("vendor_hashtree_descriptor_root_digest"))
+    let node = fdt.node(c"/avf")?.ok_or(FdtError::NotFound)?;
+    node.getprop(c"vendor_hashtree_descriptor_root_digest")
 }
 
 pub(crate) fn read_is_strict_boot(fdt: &Fdt) -> libfdt::Result<bool> {
     match fdt.chosen()? {
-        Some(node) => Ok(node.getprop(cstr!("avf,strict-boot"))?.is_some()),
+        Some(node) => Ok(node.getprop(c"avf,strict-boot")?.is_some()),
         None => Ok(false),
     }
 }
diff --git a/guest/vmbase_example/Android.bp b/guest/vmbase_example/Android.bp
index 09bd77c..ab21191 100644
--- a/guest/vmbase_example/Android.bp
+++ b/guest/vmbase_example/Android.bp
@@ -9,7 +9,6 @@
     srcs: ["src/main.rs"],
     rustlibs: [
         "libaarch64_paging",
-        "libcstr",
         "libdiced_open_dice_nostd",
         "liblibfdt_nostd",
         "liblog_rust_nostd",
diff --git a/guest/vmbase_example/src/main.rs b/guest/vmbase_example/src/main.rs
index 4c5e880..f5b41bd 100644
--- a/guest/vmbase_example/src/main.rs
+++ b/guest/vmbase_example/src/main.rs
@@ -27,7 +27,6 @@
 use crate::pci::check_pci;
 use alloc::{vec, vec::Vec};
 use core::ptr::addr_of_mut;
-use cstr::cstr;
 use libfdt::Fdt;
 use log::{debug, error, info, trace, warn, LevelFilter};
 use vmbase::{
@@ -147,7 +146,7 @@
         info!("memory @ {reg:#x?}");
     }
 
-    let compatible = cstr!("ns16550a");
+    let compatible = c"ns16550a";
 
     for c in reader.compatible_nodes(compatible).unwrap() {
         let reg = c.reg().unwrap().unwrap().next().unwrap();
@@ -159,17 +158,17 @@
     writer.unpack().unwrap();
     info!("FDT successfully unpacked.");
 
-    let path = cstr!("/memory");
+    let path = c"/memory";
     let node = writer.node_mut(path).unwrap().unwrap();
-    let name = cstr!("child");
+    let name = c"child";
     let mut child = node.add_subnode(name).unwrap();
     info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
 
-    let name = cstr!("str-property");
+    let name = c"str-property";
     child.appendprop(name, b"property-value\0").unwrap();
     info!("Appended property '{}'.", name.to_str().unwrap());
 
-    let name = cstr!("pair-property");
+    let name = c"pair-property";
     let addr = 0x0123_4567u64;
     let size = 0x89ab_cdefu64;
     child.appendprop_addrrange(name, addr, size).unwrap();