pvmfw: Support com.android.virt.page_size

Replace the assumption that guests run with 4KiB page tables by adding
support for a new VBMeta descriptor property describing the size in use.
When absent, default to the previous assumption of 4KiB.

Set the property for the Micrdroid kernels with 16KiB PAGE_SIZE.

Add test coverage & document this in the README.

Bug: 339779843
Bug: 339782511
Test: atest libpvmfw_avb.integration_test
Change-Id: Ib3c2b87fd507046578cc95d892d01fa9b04bc5c7
diff --git a/guest/pvmfw/avb/src/verify.rs b/guest/pvmfw/avb/src/verify.rs
index 2a7eed2..8810696 100644
--- a/guest/pvmfw/avb/src/verify.rs
+++ b/guest/pvmfw/avb/src/verify.rs
@@ -22,6 +22,7 @@
     Descriptor, DescriptorError, DescriptorResult, HashDescriptor, PartitionData, SlotVerifyError,
     SlotVerifyNoDataResult, VbmetaData,
 };
+use core::str;
 
 // We use this for the rollback_index field if SlotVerifyData has empty rollback_indexes
 const DEFAULT_ROLLBACK_INDEX: u64 = 0;
@@ -220,6 +221,23 @@
     Ok(digest)
 }
 
+/// Returns the indicated payload page size, if present.
+fn read_page_size(vbmeta_data: &VbmetaData) -> Result<Option<usize>, PvmfwVerifyError> {
+    let Some(property) = vbmeta_data.get_property_value("com.android.virt.page_size") else {
+        return Ok(None);
+    };
+    let size = str::from_utf8(property)
+        .or(Err(PvmfwVerifyError::InvalidPageSize))?
+        .parse::<usize>()
+        .or(Err(PvmfwVerifyError::InvalidPageSize))?
+        .checked_mul(1024)
+        // TODO(stable(unsigned_is_multiple_of)): use .is_multiple_of()
+        .filter(|sz| sz % (4 << 10) == 0 && *sz != 0)
+        .ok_or(PvmfwVerifyError::InvalidPageSize)?;
+
+    Ok(Some(size))
+}
+
 /// Verifies the given initrd partition, and checks that the resulting contents looks like expected.
 fn verify_initrd(
     ops: &mut Ops,
@@ -256,7 +274,7 @@
     let descriptors = vbmeta_image.descriptors()?;
     let hash_descriptors = HashDescriptors::get(&descriptors)?;
     let capabilities = Capability::get_capabilities(vbmeta_image)?;
-    let page_size = None; // TODO(ptosi): Read from payload.
+    let page_size = read_page_size(vbmeta_image)?;
 
     if initrd.is_none() {
         hash_descriptors.verify_no_initrd()?;