Convert cpio to use memiter.
diff --git a/inc/cpio.h b/inc/cpio.h
index a563ae6..ad6f4b7 100644
--- a/inc/cpio.h
+++ b/inc/cpio.h
@@ -4,19 +4,9 @@
 #include <stdbool.h>
 #include <stddef.h>
 
-struct cpio {
-	const struct cpio_header *first;
-	size_t total_size;
-};
+#include "memiter.h"
 
-struct cpio_iter {
-	const struct cpio_header *cur;
-	size_t size_left;
-};
-
-void cpio_init(struct cpio *c, const void *buf, size_t size);
-void cpio_init_iter(struct cpio *c, struct cpio_iter *iter);
-bool cpio_next(struct cpio_iter *iter, const char **name, const void **contents,
+bool cpio_next(struct memiter *iter, const char **name, const void **contents,
 	       size_t *size);
 
 #endif /* _CPIO_H */
diff --git a/inc/load.h b/inc/load.h
index 93aa535..7a41b9a 100644
--- a/inc/load.h
+++ b/inc/load.h
@@ -7,7 +7,9 @@
 #include "cpio.h"
 #include "memiter.h"
 
-bool load_primary(struct cpio *c, size_t kernel_arg, struct memiter *initrd);
-bool load_secondary(struct cpio *c, uint64_t mem_begin, uint64_t *mem_end);
+bool load_primary(const struct memiter *cpio, size_t kernel_arg,
+		  struct memiter *initrd);
+bool load_secondary(const struct memiter *cpio, uint64_t mem_begin,
+		    uint64_t *mem_end);
 
 #endif /* _LOAD_H */
diff --git a/inc/memiter.h b/inc/memiter.h
index ffaa822..9e066da 100644
--- a/inc/memiter.h
+++ b/inc/memiter.h
@@ -14,5 +14,6 @@
 bool memiter_parse_uint(struct memiter *it, uint64_t *value);
 bool memiter_parse_str(struct memiter *it, struct memiter *str);
 bool memiter_iseq(const struct memiter *it, const char *str);
+bool memiter_advance(struct memiter *it, size_t v);
 
 #endif /* _MEMITER_H */
diff --git a/src/cpio.c b/src/cpio.c
index 2a00837..c6db268 100644
--- a/src/cpio.c
+++ b/src/cpio.c
@@ -20,63 +20,47 @@
 };
 #pragma pack(pop)
 
-void cpio_init(struct cpio *c, const void *buf, size_t size)
-{
-	c->first = buf;
-	c->total_size = size;
-}
-
-void cpio_init_iter(struct cpio *c, struct cpio_iter *iter)
-{
-	iter->cur = c->first;
-	iter->size_left = c->total_size;
-}
-
-bool cpio_next(struct cpio_iter *iter, const char **name, const void **contents,
+/**
+ * Retrieves the next file stored in the cpio archive stored in the cpio, and
+ * advances the iterator such that another call to this function would return
+ * the following file.
+ */
+bool cpio_next(struct memiter *iter, const char **name, const void **contents,
 	       size_t *size)
 {
-	const struct cpio_header *h = iter->cur;
-	size_t size_left;
-	size_t filelen;
-	size_t namelen;
+	size_t len;
+	struct memiter lit = *iter;
+	const struct cpio_header *h = (const struct cpio_header *)lit.next;
 
-	size_left = iter->size_left;
-	if (size_left < sizeof(struct cpio_header)) {
+	if (!memiter_advance(&lit, sizeof(struct cpio_header))) {
 		return false;
 	}
 
+	*name = lit.next;
+
 	/* TODO: Check magic. */
 
-	size_left -= sizeof(struct cpio_header);
-	namelen = (h->namesize + 1) & ~1;
-	if (size_left < namelen) {
+	len = (h->namesize + 1) & ~1;
+	if (!memiter_advance(&lit, len)) {
 		return false;
 	}
 
-	size_left -= namelen;
-	filelen = (size_t)h->filesize[0] << 16 | h->filesize[1];
-	if (size_left < filelen) {
+	*contents = lit.next;
+
+	len = (size_t)h->filesize[0] << 16 | h->filesize[1];
+	if (!memiter_advance(&lit, (len + 1) & ~1)) {
 		return false;
 	}
 
 	/* TODO: Check that string is null-terminated. */
-	/* TODO: Check that trailler is not returned. */
 
 	/* Stop enumerating files when we hit the end marker. */
-	if (!strcmp((const char *)(iter->cur + 1), "TRAILER!!!")) {
+	if (!strcmp(*name, "TRAILER!!!")) {
 		return false;
 	}
 
-	size_left -= filelen;
-
-	*name = (const char *)(iter->cur + 1);
-	*contents = *name + namelen;
-	*size = filelen;
-
-	iter->cur = (struct cpio_header *)((char *)*contents + filelen);
-	iter->cur =
-		(struct cpio_header *)(char *)(((size_t)iter->cur + 1) & ~1);
-	iter->size_left = size_left;
+	*size = len;
+	*iter = lit;
 
 	return true;
 }
diff --git a/src/load.c b/src/load.c
index e0949d6..39de7d1 100644
--- a/src/load.c
+++ b/src/load.c
@@ -44,15 +44,14 @@
  * null-terminated, so we use a memory iterator to represent it. The file, if
  * found, is returned in the "it" argument.
  */
-static bool memiter_find_file(struct cpio *c, const struct memiter *filename,
+static bool memiter_find_file(const struct memiter *cpio,
+			      const struct memiter *filename,
 			      struct memiter *it)
 {
 	const char *fname;
 	const void *fcontents;
 	size_t fsize;
-	struct cpio_iter iter;
-
-	cpio_init_iter(c, &iter);
+	struct memiter iter = *cpio;
 
 	while (cpio_next(&iter, &fname, &fcontents, &fsize)) {
 		if (memiter_iseq(filename, fname)) {
@@ -68,14 +67,13 @@
  * Looks for a file in the given cpio archive. The file, if found, is returned
  * in the "it" argument.
  */
-static bool find_file(struct cpio *c, const char *name, struct memiter *it)
+static bool find_file(const struct memiter *cpio, const char *name,
+		      struct memiter *it)
 {
 	const char *fname;
 	const void *fcontents;
 	size_t fsize;
-	struct cpio_iter iter;
-
-	cpio_init_iter(c, &iter);
+	struct memiter iter = *cpio;
 
 	while (cpio_next(&iter, &fname, &fcontents, &fsize)) {
 		if (!strcmp(fname, name)) {
@@ -90,11 +88,12 @@
 /**
  * Loads the primary VM.
  */
-bool load_primary(struct cpio *c, size_t kernel_arg, struct memiter *initrd)
+bool load_primary(const struct memiter *cpio, size_t kernel_arg,
+		  struct memiter *initrd)
 {
 	struct memiter it;
 
-	if (!find_file(c, "vmlinuz", &it)) {
+	if (!find_file(cpio, "vmlinuz", &it)) {
 		dlog("Unable to find vmlinuz\n");
 		return false;
 	}
@@ -104,7 +103,7 @@
 		return false;
 	}
 
-	if (!find_file(c, "initrd.img", initrd)) {
+	if (!find_file(cpio, "initrd.img", initrd)) {
 		dlog("Unable to find initrd.img\n");
 		return false;
 	}
@@ -126,7 +125,8 @@
  * reflect the fact that some of the memory isn't available to the primary VM
  * anymore.
  */
-bool load_secondary(struct cpio *c, uint64_t mem_begin, uint64_t *mem_end)
+bool load_secondary(const struct memiter *cpio, uint64_t mem_begin,
+		    uint64_t *mem_end)
 {
 	struct memiter it;
 	struct memiter str;
@@ -134,7 +134,7 @@
 	uint64_t cpu;
 	uint32_t count;
 
-	if (!find_file(c, "vms.txt", &it)) {
+	if (!find_file(cpio, "vms.txt", &it)) {
 		dlog("vms.txt is missing\n");
 		return true;
 	}
@@ -145,7 +145,7 @@
 	     count++) {
 		struct memiter kernel;
 
-		if (!memiter_find_file(c, &str, &kernel)) {
+		if (!memiter_find_file(cpio, &str, &kernel)) {
 			dlog("Unable to load kernel for vm %u\n", count);
 			continue;
 		}
diff --git a/src/main.c b/src/main.c
index 7792c8a..8362a6d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,7 +47,7 @@
 	struct boot_params_update update;
 	uint64_t new_mem_end;
 	struct memiter primary_initrd;
-	struct cpio c;
+	struct memiter cpio;
 
 	dlog("Initialising hafnium\n");
 
@@ -73,13 +73,13 @@
 		panic("unable to map initrd in");
 	}
 
-	cpio_init(&c, (void *)params.initrd_begin,
-		  params.initrd_end - params.initrd_begin);
+	memiter_init(&cpio, (void *)params.initrd_begin,
+		     params.initrd_end - params.initrd_begin);
 
 	/* Load all VMs. */
 	new_mem_end = params.mem_end;
-	load_secondary(&c, params.mem_begin, &new_mem_end);
-	if (!load_primary(&c, params.kernel_arg, &primary_initrd)) {
+	load_secondary(&cpio, params.mem_begin, &new_mem_end);
+	if (!load_primary(&cpio, params.kernel_arg, &primary_initrd)) {
 		panic("unable to load primary VM");
 	}
 
diff --git a/src/memiter.c b/src/memiter.c
index d3d37d2..6dd9d8c 100644
--- a/src/memiter.c
+++ b/src/memiter.c
@@ -101,3 +101,18 @@
 
 	return true;
 }
+
+/**
+ * Advances the iterator by the given number of bytes. Returns true if the
+ * iterator was advanced without going over its limit; returns false and leaves
+ * the iterator unmodified otherwise.
+ */
+bool memiter_advance(struct memiter *it, size_t v)
+{
+	const char *p = it->next + v;
+	if (p < it->next || p > it->limit) {
+		return false;
+	}
+	it->next = p;
+	return true;
+}