libfdt: Create Rust wrapper

libfdt is the industry standard library for parsing and generating
DeviceTree format. Create a wrapper around it for use in bare-metal Rust
projects. The low-level functions are not exposed directly but rather
wrapper by an Fdt object that exposes information parsed from the DT
using high-level constructs.

Only parsing of '/memory' entries is implemented for now and tested in
the vmbase example kernel. Other information and FDT generation will be
added at a later time.

Bug: 255521657
Test: atest vmbase_example.integration_test
Change-Id: If095ff3c4534d18bdf8ee5ebb072dde7a6e6efab
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index 03f0603..3d74168 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -27,9 +27,13 @@
     bionic_tls, dtb_range, print_addresses, rodata_range, stack_chk_guard, text_range,
     writable_region, DEVICE_REGION,
 };
-use aarch64_paging::{idmap::IdMap, paging::Attributes};
+use aarch64_paging::{
+    idmap::IdMap,
+    paging::{Attributes, MemoryRegion},
+};
 use alloc::{vec, vec::Vec};
 use buddy_system_allocator::LockedHeap;
+use libfdt::Fdt;
 use log::{info, LevelFilter};
 use vmbase::{logger, main, println};
 
@@ -57,6 +61,7 @@
     assert_eq!(arg0, dtb_range().start.0 as u64);
     check_data();
     check_stack_guard();
+    check_fdt();
 
     unsafe {
         HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
@@ -138,6 +143,20 @@
     info!("Data looks good");
 }
 
+fn check_fdt() {
+    info!("Checking FDT...");
+    let fdt = MemoryRegion::from(layout::dtb_range());
+    let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start().0 as *mut u8, fdt.len()) };
+
+    let reader = Fdt::from_slice(fdt).unwrap();
+    info!("FDT passed verification.");
+    for reg in reader.memory().unwrap() {
+        info!("memory @ {reg:#x?}");
+    }
+
+    info!("FDT checks done.");
+}
+
 fn check_alloc() {
     info!("Allocating a Vec...");
     let mut vector: Vec<u32> = vec![1, 2, 3, 4];