guest_ram: add custom iterator

Add a function that initialises ram with a
custom iterator. This is used for mapping vm
memory onto a dataport.
diff --git a/libsel4vm/include/sel4vm/guest_ram.h b/libsel4vm/include/sel4vm/guest_ram.h
index f2a4c5f..be8cf5e 100644
--- a/libsel4vm/include/sel4vm/guest_ram.h
+++ b/libsel4vm/include/sel4vm/guest_ram.h
@@ -102,6 +102,19 @@
 int vm_ram_register_at(vm_t *vm, uintptr_t start, size_t bytes, bool untyped);
 
 /***
+ * @function vm_ram_register_at(vm, start, bytes, untyped)
+ * Reserve a region of memory for RAM in the guest VM at a starting guest physical address with a custom memory iterator
+ * @param {vm_t *} vm                           A handle to the VM that ram needs to be allocated for
+ * @param {uintptr_t} start                     Starting guest physical address of the ram region being allocated
+ * @param {size_t} size                         The size of the RAM region to be allocated
+ * @param {memory_map_iterator_fn} map_iterator Iterator function
+ * @param {void *} cookie                       Iterator cookie
+ * @return                      0 on success, -1 on error
+ */
+int vm_ram_register_at_custom_iterator(vm_t *vm, uintptr_t start, size_t bytes, memory_map_iterator_fn map_iterator,
+                                       void *cookie);
+
+/***
  * @function vm_ram_mark_allocated(vm, start, bytes)
  * Mark a registered region of RAM as allocated
  * @param {vm_t *} vm               A handle to the VM
diff --git a/libsel4vm/src/guest_ram.c b/libsel4vm/src/guest_ram.c
index 22d0da4..9b7887b 100644
--- a/libsel4vm/src/guest_ram.c
+++ b/libsel4vm/src/guest_ram.c
@@ -375,6 +375,32 @@
     return 0;
 }
 
+int vm_ram_register_at_custom_iterator(vm_t *vm, uintptr_t start, size_t bytes, memory_map_iterator_fn map_iterator,
+                                       void *cookie)
+{
+    vm_memory_reservation_t *ram_reservation;
+    int err;
+
+    ram_reservation = vm_reserve_memory_at(vm, start, bytes, default_ram_fault_callback,
+                                           NULL);
+    if (!ram_reservation) {
+        ZF_LOGE("Unable to reserve ram region at addr 0x%x of size 0x%x", start, bytes);
+        return -1;
+    }
+    err = map_vm_memory_reservation(vm, ram_reservation, map_iterator, cookie);
+    if (err) {
+        ZF_LOGE("failed to map vm memory reservation to dataport\n");
+        return -1;
+    }
+    err = expand_guest_ram_region(vm, start, bytes);
+    if (err) {
+        ZF_LOGE("Failed to register new ram region");
+        vm_free_reserved_memory(vm, ram_reservation);
+        return -1;
+    }
+    return 0;
+}
+
 void vm_ram_free(vm_t *vm, uintptr_t start, size_t bytes)
 {
     return;