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;
+}