Add cstr! macro

cstr!("X") is a shorthand for CStr::from_bytes_with_nul(b"X\0").unwrap()

Bug: 249054080
Test: TH

Change-Id: Iefdaa07179fe3b556fc9bc17595919ac93b7e569
diff --git a/pvmfw/src/crypto.rs b/pvmfw/src/crypto.rs
index 85dc6c9..275de7a 100644
--- a/pvmfw/src/crypto.rs
+++ b/pvmfw/src/crypto.rs
@@ -14,6 +14,8 @@
 
 //! Wrapper around BoringSSL/OpenSSL symbols.
 
+use crate::cstr;
+
 use core::convert::AsRef;
 use core::ffi::{c_char, c_int, CStr};
 use core::fmt;
@@ -81,14 +83,10 @@
 
 impl fmt::Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let unknown_library = CStr::from_bytes_with_nul(b"{unknown library}\0").unwrap();
-        let unknown_reason = CStr::from_bytes_with_nul(b"{unknown reason}\0").unwrap();
-        let unknown_file = CStr::from_bytes_with_nul(b"??\0").unwrap();
-
         let packed = self.packed_value();
-        let library = self.library_name().unwrap_or(unknown_library).to_str().unwrap();
-        let reason = self.reason().unwrap_or(unknown_reason).to_str().unwrap();
-        let file = self.file.unwrap_or(unknown_file).to_str().unwrap();
+        let library = self.library_name().unwrap_or(cstr!("{unknown library}")).to_str().unwrap();
+        let reason = self.reason().unwrap_or(cstr!("{unknown reason}")).to_str().unwrap();
+        let file = self.file.unwrap_or(cstr!("??")).to_str().unwrap();
         let line = self.line;
 
         write!(f, "{file}:{line}: {library}: {reason} ({packed:#x})")
diff --git a/pvmfw/src/debug_policy.rs b/pvmfw/src/debug_policy.rs
index 23d3e1d..15efa1c 100644
--- a/pvmfw/src/debug_policy.rs
+++ b/pvmfw/src/debug_policy.rs
@@ -14,6 +14,7 @@
 
 //! Support for the debug policy overlay in pvmfw
 
+use crate::cstr;
 use alloc::{vec, vec::Vec};
 use core::ffi::CStr;
 use core::fmt;
@@ -65,11 +66,8 @@
 
 /// Disables ramdump by removing crashkernel from bootargs in /chosen.
 fn disable_ramdump(fdt: &mut libfdt::Fdt) -> Result<(), DebugPolicyError> {
-    let chosen_path = CStr::from_bytes_with_nul(b"/chosen\0").unwrap();
-    let bootargs_name = CStr::from_bytes_with_nul(b"bootargs\0").unwrap();
-
     let chosen = match fdt
-        .node(chosen_path)
+        .node(cstr!("/chosen"))
         .map_err(|e| DebugPolicyError::Fdt("Failed to find /chosen", e))?
     {
         Some(node) => node,
@@ -77,7 +75,7 @@
     };
 
     let bootargs = match chosen
-        .getprop_str(bootargs_name)
+        .getprop_str(cstr!("bootargs"))
         .map_err(|e| DebugPolicyError::Fdt("Failed to find bootargs prop", e))?
     {
         Some(value) if !value.to_bytes().is_empty() => value,
@@ -100,8 +98,8 @@
     new_bootargs.push(b'\0');
 
     // We've checked existence of /chosen node at the beginning.
-    let mut chosen_mut = fdt.node_mut(chosen_path).unwrap().unwrap();
-    chosen_mut.setprop(bootargs_name, new_bootargs.as_slice()).map_err(|e| {
+    let mut chosen_mut = fdt.node_mut(cstr!("/chosen")).unwrap().unwrap();
+    chosen_mut.setprop(cstr!("bootargs"), new_bootargs.as_slice()).map_err(|e| {
         DebugPolicyError::OverlaidFdt("Failed to remove crashkernel. FDT might be corrupted", e)
     })
 }
@@ -109,7 +107,7 @@
 /// Returns true only if fdt has ramdump prop in the /avf/guest/common node with value <1>
 fn is_ramdump_enabled(fdt: &libfdt::Fdt) -> Result<bool, DebugPolicyError> {
     let common = match fdt
-        .node(CStr::from_bytes_with_nul(b"/avf/guest/common\0").unwrap())
+        .node(cstr!("/avf/guest/common"))
         .map_err(|e| DebugPolicyError::DebugPolicyFdt("Failed to find /avf/guest/common node", e))?
     {
         Some(node) => node,
@@ -117,7 +115,7 @@
     };
 
     match common
-        .getprop_u32(CStr::from_bytes_with_nul(b"ramdump\0").unwrap())
+        .getprop_u32(cstr!("ramdump"))
         .map_err(|e| DebugPolicyError::DebugPolicyFdt("Failed to find ramdump prop", e))?
     {
         Some(1) => Ok(true),
@@ -128,11 +126,8 @@
 /// Enables console output by adding kernel.printk.devkmsg and kernel.console to bootargs.
 /// This uses hardcoded console name 'hvc0' and it should be match with microdroid's bootconfig.debuggable.
 fn enable_console_output(fdt: &mut libfdt::Fdt) -> Result<(), DebugPolicyError> {
-    let chosen_path = CStr::from_bytes_with_nul(b"/chosen\0").unwrap();
-    let bootargs_name = CStr::from_bytes_with_nul(b"bootargs\0").unwrap();
-
     let chosen = match fdt
-        .node(chosen_path)
+        .node(cstr!("/chosen"))
         .map_err(|e| DebugPolicyError::Fdt("Failed to find /chosen", e))?
     {
         Some(node) => node,
@@ -140,7 +135,7 @@
     };
 
     let bootargs = match chosen
-        .getprop_str(bootargs_name)
+        .getprop_str(cstr!("bootargs"))
         .map_err(|e| DebugPolicyError::Fdt("Failed to find bootargs prop", e))?
     {
         Some(value) if !value.to_bytes().is_empty() => value,
@@ -154,8 +149,8 @@
     fdt.unpack().map_err(|e| DebugPolicyError::OverlaidFdt("Failed to unpack", e))?;
 
     // We've checked existence of /chosen node at the beginning.
-    let mut chosen_mut = fdt.node_mut(chosen_path).unwrap().unwrap();
-    chosen_mut.setprop(bootargs_name, new_bootargs.as_slice()).map_err(|e| {
+    let mut chosen_mut = fdt.node_mut(cstr!("/chosen")).unwrap().unwrap();
+    chosen_mut.setprop(cstr!("bootargs"), new_bootargs.as_slice()).map_err(|e| {
         DebugPolicyError::OverlaidFdt("Failed to enabled console output. FDT might be corrupted", e)
     })?;
 
@@ -166,7 +161,7 @@
 /// Returns true only if fdt has log prop in the /avf/guest/common node with value <1>
 fn is_console_output_enabled(fdt: &libfdt::Fdt) -> Result<bool, DebugPolicyError> {
     let common = match fdt
-        .node(CStr::from_bytes_with_nul(b"/avf/guest/common\0").unwrap())
+        .node(cstr!("/avf/guest/common"))
         .map_err(|e| DebugPolicyError::DebugPolicyFdt("Failed to find /avf/guest/common node", e))?
     {
         Some(node) => node,
@@ -174,7 +169,7 @@
     };
 
     match common
-        .getprop_u32(CStr::from_bytes_with_nul(b"log\0").unwrap())
+        .getprop_u32(cstr!("log"))
         .map_err(|e| DebugPolicyError::DebugPolicyFdt("Failed to find log prop", e))?
     {
         Some(1) => Ok(true),
diff --git a/pvmfw/src/dice.rs b/pvmfw/src/dice.rs
index 3ceb8ef..bad3453 100644
--- a/pvmfw/src/dice.rs
+++ b/pvmfw/src/dice.rs
@@ -14,6 +14,7 @@
 
 //! Support for DICE derivation and BCC generation.
 
+use crate::cstr;
 use crate::helpers::flushed_zeroize;
 use core::ffi::c_void;
 use core::ffi::CStr;
@@ -60,10 +61,9 @@
         self,
         salt: &[u8; HIDDEN_SIZE],
     ) -> diced_open_dice::Result<InputValues> {
-        let component_name = CStr::from_bytes_with_nul(b"vm_entry\0").unwrap();
         let mut config_descriptor_buffer = [0; 128];
         let config_descriptor_size = bcc_format_config_descriptor(
-            Some(component_name),
+            Some(cstr!("vm_entry")),
             None,  // component_version
             false, // resettable
             &mut config_descriptor_buffer,
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index f4b0244..f56d6e0 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -14,6 +14,7 @@
 
 //! High-level FDT functions.
 
+use crate::cstr;
 use crate::helpers::GUEST_PAGE_SIZE;
 use crate::RebootReason;
 use core::ffi::CStr;
@@ -30,11 +31,10 @@
 
 /// Extract from /config the address range containing the pre-loaded kernel.
 pub fn kernel_range(fdt: &libfdt::Fdt) -> libfdt::Result<Option<Range<usize>>> {
-    let config = CStr::from_bytes_with_nul(b"/config\0").unwrap();
-    let addr = CStr::from_bytes_with_nul(b"kernel-address\0").unwrap();
-    let size = CStr::from_bytes_with_nul(b"kernel-size\0").unwrap();
+    let addr = cstr!("kernel-address");
+    let size = cstr!("kernel-size");
 
-    if let Some(config) = fdt.node(config)? {
+    if let Some(config) = fdt.node(cstr!("/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;
@@ -48,8 +48,8 @@
 
 /// Extract from /chosen the address range containing the pre-loaded ramdisk.
 pub fn initrd_range(fdt: &libfdt::Fdt) -> libfdt::Result<Option<Range<usize>>> {
-    let start = CStr::from_bytes_with_nul(b"linux,initrd-start\0").unwrap();
-    let end = CStr::from_bytes_with_nul(b"linux,initrd-end\0").unwrap();
+    let start = cstr!("linux,initrd-start");
+    let end = cstr!("linux,initrd-end");
 
     if let Some(chosen) = fdt.chosen()? {
         if let (Some(start), Some(end)) = (chosen.getprop_u32(start)?, chosen.getprop_u32(end)?) {
@@ -106,7 +106,7 @@
 /// Read the number of CPUs
 fn parse_cpu_nodes(fdt: &libfdt::Fdt) -> Result<NonZeroUsize, RebootReason> {
     let num = fdt
-        .compatible_nodes(CStr::from_bytes_with_nul(b"arm,arm-v8\0").unwrap())
+        .compatible_nodes(cstr!("arm,arm-v8"))
         .map_err(|e| {
             error!("Failed to read compatible nodes \"arm,arm-v8\" from DT: {e}");
             RebootReason::InvalidFdt
@@ -128,7 +128,7 @@
 /// Read and validate PCI node
 fn parse_pci_nodes(fdt: &libfdt::Fdt) -> Result<PciInfo, RebootReason> {
     let node = fdt
-        .compatible_nodes(CStr::from_bytes_with_nul(b"pci-host-cam-generic\0").unwrap())
+        .compatible_nodes(cstr!("pci-host-cam-generic"))
         .map_err(|e| {
             error!("Failed to read compatible node \"pci-host-cam-generic\" from DT: {e}");
             RebootReason::InvalidFdt
@@ -230,11 +230,11 @@
     const IRQ_MASK_ANY_IRQ: u32 = 0x7;
     const EXPECTED: [u32; IRQ_MASK_CELLS] =
         [IRQ_MASK_ADDR_HI, IRQ_MASK_ADDR_ME, IRQ_MASK_ADDR_LO, IRQ_MASK_ANY_IRQ];
-    let name = CStr::from_bytes_with_nul(b"interrupt-map-mask\0").unwrap();
+
     let mut irq_count: usize = 0;
     for irq_mask in CellChunkIterator::<IRQ_MASK_CELLS>::new(
         pci_node
-            .getprop_cells(name)
+            .getprop_cells(cstr!("interrupt-map-mask"))
             .map_err(|e| {
                 error!("Failed to read interrupt-map-mask property: {e}");
                 RebootReason::InvalidFdt
@@ -266,10 +266,9 @@
     let mut phys_hi: u32 = 0;
     let mut irq_nr = AARCH64_IRQ_BASE;
 
-    let name = CStr::from_bytes_with_nul(b"interrupt-map\0").unwrap();
     for irq_map in CellChunkIterator::<IRQ_MAP_CELLS>::new(
         pci_node
-            .getprop_cells(name)
+            .getprop_cells(cstr!("interrupt-map"))
             .map_err(|e| {
                 error!("Failed to read interrupt-map property: {e}");
                 RebootReason::InvalidFdt
@@ -350,7 +349,7 @@
 fn parse_serial_nodes(fdt: &libfdt::Fdt) -> Result<SerialInfo, RebootReason> {
     let mut ret: SerialInfo = Default::default();
     for (i, node) in fdt
-        .compatible_nodes(CStr::from_bytes_with_nul(b"ns16550a\0").unwrap())
+        .compatible_nodes(cstr!("ns16550a"))
         .map_err(|e| {
             error!("Failed to read compatible nodes \"ns16550a\" from DT: {e}");
             RebootReason::InvalidFdt
@@ -390,7 +389,7 @@
 
 fn parse_swiotlb_nodes(fdt: &libfdt::Fdt) -> Result<SwiotlbInfo, RebootReason> {
     let node = fdt
-        .compatible_nodes(CStr::from_bytes_with_nul(b"restricted-dma-pool\0").unwrap())
+        .compatible_nodes(cstr!("restricted-dma-pool"))
         .map_err(|e| {
             error!("Failed to read compatible nodes \"restricted-dma-pool\" from DT: {e}");
             RebootReason::InvalidFdt
@@ -401,7 +400,7 @@
             RebootReason::InvalidFdt
         })?;
     let size = node
-        .getprop_u64(CStr::from_bytes_with_nul(b"size\0").unwrap())
+        .getprop_u64(cstr!("size"))
         .map_err(|e| {
             error!("Failed to read \"size\" property of \"restricted-dma-pool\": {e}");
             RebootReason::InvalidFdt
@@ -412,7 +411,7 @@
         })?;
 
     let align = node
-        .getprop_u64(CStr::from_bytes_with_nul(b"alignment\0").unwrap())
+        .getprop_u64(cstr!("alignment"))
         .map_err(|e| {
             error!("Failed to read \"alignment\" property of \"restricted-dma-pool\": {e}");
             RebootReason::InvalidFdt
@@ -470,16 +469,8 @@
 
     add_dice_node(fdt, bcc.as_ptr() as usize, bcc.len())?;
 
-    set_or_clear_chosen_flag(
-        fdt,
-        CStr::from_bytes_with_nul(b"avf,strict-boot\0").unwrap(),
-        strict_boot,
-    )?;
-    set_or_clear_chosen_flag(
-        fdt,
-        CStr::from_bytes_with_nul(b"avf,new-instance\0").unwrap(),
-        new_instance,
-    )?;
+    set_or_clear_chosen_flag(fdt, cstr!("avf,strict-boot"), strict_boot)?;
+    set_or_clear_chosen_flag(fdt, cstr!("avf,new-instance"), new_instance)?;
 
     fdt.pack()?;
 
@@ -488,24 +479,20 @@
 
 /// Add a "google,open-dice"-compatible reserved-memory node to the tree.
 fn add_dice_node(fdt: &mut Fdt, addr: usize, size: usize) -> libfdt::Result<()> {
-    let reserved_memory = CStr::from_bytes_with_nul(b"/reserved-memory\0").unwrap();
     // We reject DTs with missing reserved-memory node as validation should have checked that the
     // "swiotlb" subnode (compatible = "restricted-dma-pool") was present.
-    let mut reserved_memory = fdt.node_mut(reserved_memory)?.ok_or(libfdt::FdtError::NotFound)?;
+    let mut reserved_memory =
+        fdt.node_mut(cstr!("/reserved-memory"))?.ok_or(libfdt::FdtError::NotFound)?;
 
-    let dice = CStr::from_bytes_with_nul(b"dice\0").unwrap();
-    let mut dice = reserved_memory.add_subnode(dice)?;
+    let mut dice = reserved_memory.add_subnode(cstr!("dice"))?;
 
-    let compatible = CStr::from_bytes_with_nul(b"compatible\0").unwrap();
-    dice.appendprop(compatible, b"google,open-dice\0")?;
+    dice.appendprop(cstr!("compatible"), b"google,open-dice\0")?;
 
-    let no_map = CStr::from_bytes_with_nul(b"no-map\0").unwrap();
-    dice.appendprop(no_map, &[])?;
+    dice.appendprop(cstr!("no-map"), &[])?;
 
     let addr = addr.try_into().unwrap();
     let size = size.try_into().unwrap();
-    let reg = CStr::from_bytes_with_nul(b"reg\0").unwrap();
-    dice.appendprop_addrrange(reg, addr, size)?;
+    dice.appendprop_addrrange(cstr!("reg"), addr, size)?;
 
     Ok(())
 }
diff --git a/pvmfw/src/helpers.rs b/pvmfw/src/helpers.rs
index e6e3406..fddd8c3 100644
--- a/pvmfw/src/helpers.rs
+++ b/pvmfw/src/helpers.rs
@@ -113,3 +113,11 @@
     reg.zeroize();
     flush(reg)
 }
+
+/// Create &CStr out of &str literal
+#[macro_export]
+macro_rules! cstr {
+    ($str:literal) => {{
+        CStr::from_bytes_with_nul(concat!($str, "\0").as_bytes()).unwrap()
+    }};
+}