vmm_obj_service: Handle mapping of physical memory.

Updates share_buffer to handle physical memory outside of Trusty's
default mapped address space. Additionally sets the size of the source
data in the first usize of the buffer since full pages must be mapped.

Bug: 359345227
Test: Map desktop boot params into gsc_service TA.
Change-Id: I2dcd5fc1d114ab783e5f74e547731ef55c9c86bf
diff --git a/lib/vmm_obj_service/rust/rules.mk b/lib/vmm_obj_service/rust/rules.mk
index d4122b8..1f28729 100644
--- a/lib/vmm_obj_service/rust/rules.mk
+++ b/lib/vmm_obj_service/rust/rules.mk
@@ -9,6 +9,7 @@
 
 MODULE_LIBRARY_DEPS += \
 	$(call FIND_CRATE,log) \
+	$(call FIND_CRATE,zerocopy) \
 	packages/modules/Virtualization/libs/libfdt \
 	trusty/user/base/lib/trusty-std \
 
diff --git a/lib/vmm_obj_service/rust/src/lib.rs b/lib/vmm_obj_service/rust/src/lib.rs
index abee1d5..8c0968f 100644
--- a/lib/vmm_obj_service/rust/src/lib.rs
+++ b/lib/vmm_obj_service/rust/src/lib.rs
@@ -22,8 +22,6 @@
  */
 
 #![no_std]
-#![feature(new_uninit)]
-#![feature(raw_ref_op)]
 
 use core::ffi::CStr;
 use core::marker::PhantomPinned;
@@ -39,6 +37,15 @@
     Error,
 };
 use trusty_std::boxed::Box;
+use zerocopy::{Immutable, IntoBytes};
+
+#[derive(Immutable, IntoBytes)]
+#[repr(C)]
+pub struct VmmObjServiceHeader {
+    data_start: u32,
+    size: u32,
+}
+const HDR_SIZE: usize = core::mem::size_of::<VmmObjServiceHeader>();
 
 fn create_obj_service_ro(
     port: &'static CStr,
@@ -95,24 +102,42 @@
     }
 }
 
-/// Shares a buffer with the TAs specified in acl.
+/// Shares a buffer with the TAs specified in acl. The buffer is copied to new pages and prefixed
+/// with size of the passed in data as a usize. This size will differ from that provided by
+/// vmm_obj_service_create_ro and vmm_obj_map_ro as those function operate in increments of
+/// PAGE_SIZE.
 ///
 /// # Arguments
 ///
 /// * `buffer` - a buffer to share with TAs.
+/// * `size` - size of buffer.
+/// * `align_log2` - alignment to use for the start of the destination data.
 /// * `port` - a tipc port name for TAs to request the mapped buffer.
 /// * `acl` - a ktipc_port_acl specifying which trust zones may connect and which apps may connect.
 ///     If uuids is empty, any app may connect.
 ///
-pub fn share_buffer(
-    buffer: &[u8],
+pub fn share_sized_buffer(
+    buffer: *const u8,
+    size: usize,
+    align_log2: u8,
     port: &'static CStr,
     acl: &'static ktipc_port_acl,
 ) -> Result<(), Error> {
-    let aligned_size = buffer.len().next_multiple_of(PAGE_SIZE as usize);
+    let aligned_ptr: usize = buffer as usize & !(PAGE_SIZE as usize - 1);
+    let offset = buffer as usize - aligned_ptr;
+    let aligned_size = (size + offset).next_multiple_of(PAGE_SIZE as usize);
 
-    let mut page_array = VmmPageArray::new(port, aligned_size, 0, 0)?;
-    page_array.as_mut_slice()[..buffer.len()].copy_from_slice(buffer);
+    let mut phys_page_array = VmmPageArray::new_physical(port, aligned_ptr, aligned_size, 0, 0)?;
+
+    let align = 1usize << align_log2;
+    let dst_data_start = HDR_SIZE.next_multiple_of(align);
+    let dst_size = (size + dst_data_start).next_multiple_of(PAGE_SIZE as usize);
+
+    let mut page_array = VmmPageArray::new(port, dst_size, 0, 0)?;
+    let header = VmmObjServiceHeader { data_start: dst_data_start as u32, size: size as u32 };
+    page_array.as_mut_slice()[..HDR_SIZE].copy_from_slice(header.as_bytes());
+    page_array.as_mut_slice()[dst_data_start..size + dst_data_start]
+        .copy_from_slice(&phys_page_array.as_mut_slice()[offset..offset + size]);
 
     let slice = VmmObj::new(page_array)?;
 
@@ -128,7 +153,7 @@
         Error::from_lk(rc)?;
     }
 
-    let mut svc = create_obj_service_ro(port, acl, &slice.slice, aligned_size)?;
+    let mut svc = create_obj_service_ro(port, acl, &slice.slice, dst_size)?;
 
     // SAFETY: vmm_obj_service_add add a new service (svc) to the ktipc server (srv). srv has
     // already been moved to its own thread and svc now becomes owned by srv.