libfdt: Use zerocopy for safe fdt_header wrapper

Provide a way to get a safe &(mut) fdt_header from any <T: Libfdt(Mut)>.

Instead of manually doing the conversion from the BE-encoded DT fields,
use zerocopy to implement a zero-cost wrapper where each field has a
getter and setter function that transparently handles the endianness.

Combine those to remove the need for unsafe code in Fdt.

Test: m pvmfw
Test: atest liblibfdt.integration_test
Change-Id: I5ccaf49b48c13855d80ad386d41be3abbf3fdfe8
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 1961232..6328f4c 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -27,7 +27,7 @@
     PropertyIterator, RangesIterator, Reg, RegIterator, SubnodeIterator,
 };
 pub use result::{FdtError, Result};
-pub use safe_types::{NodeOffset, Phandle, PropOffset, StringOffset};
+pub use safe_types::{FdtHeader, NodeOffset, Phandle, PropOffset, StringOffset};
 
 use core::ffi::{c_void, CStr};
 use core::ops::Range;
@@ -778,13 +778,14 @@
         self.buffer.as_ptr().cast()
     }
 
-    fn header(&self) -> &libfdt_bindgen::fdt_header {
-        let p = self.as_ptr().cast();
+    fn header(&self) -> &FdtHeader {
+        let p = self.as_ptr().cast::<libfdt_bindgen::fdt_header>();
         // SAFETY: A valid FDT (verified by constructor) must contain a valid fdt_header.
-        unsafe { &*p }
+        let header = unsafe { &*p };
+        header.as_ref()
     }
 
     fn totalsize(&self) -> usize {
-        u32::from_be(self.header().totalsize) as usize
+        self.header().totalsize.get().try_into().unwrap()
     }
 }