[mxio][bootfs] mmap directory, provide bootfs_open() api

Change-Id: Ia2d3a896dc4455df8a22da7f50fcc02f1b8d3d7f
Esse commit está contido em:
Brian Swetland
2017-09-08 13:38:32 -07:00
commit 1b5c38f23d
3 arquivos alterados com 102 adições e 27 exclusões
+5 -1
Ver Arquivo
@@ -160,7 +160,11 @@ static ssize_t setup_bootfs_vmo(uint32_t n, uint32_t type, mx_handle_t vmo) {
has_secondary_bootfs = true;
memfs_mount(vfs_create_global_root(), systemfs_get_root());
}
bootfs_parse(vmo, size, callback, &cd);
bootfs_t bfs;
if (bootfs_create(&bfs, vmo) == MX_OK) {
bootfs_parse(&bfs, callback, &cd);
bootfs_destroy(&bfs);
}
return cd.file_count;
}
+86 -25
Ver Arquivo
@@ -8,55 +8,116 @@
#include <string.h>
#include <magenta/boot/bootdata.h>
#include <magenta/process.h>
#include <magenta/syscalls.h>
#include <magenta/types.h>
mx_status_t bootfs_parse(mx_handle_t vmo, size_t len,
mx_status_t (*cb)(void* cookie, const bootfs_entry_t* entry),
void* cookie) {
#include <mxio/util.h>
mx_status_t bootfs_create(bootfs_t* bfs, mx_handle_t vmo) {
bootfs_header_t hdr;
size_t rlen;
mx_status_t r = mx_vmo_read(vmo, &hdr, 0, sizeof(hdr), &rlen);
if ((r < 0) || (rlen < sizeof(hdr))) {
printf("bootfs_parse: couldn't read boot_data - %#zx\n", rlen);
return MX_ERR_IO;
printf("bootfs_create: couldn't read boot_data - %d\n", r);
return r;
}
if (hdr.magic != BOOTFS_MAGIC) {
printf("bootfs_parse: incorrect bootdata header: %08x\n", hdr.magic);
printf("bootfs_create: incorrect bootdata header: %x\n", hdr.magic);
return MX_ERR_IO;
}
//TODO: mmap instead
if (hdr.dirsize > 65536) {
printf("bootfs_parse: directory too large\n");
return MX_ERR_OUT_OF_RANGE;
if ((r = mx_handle_duplicate(vmo, MX_RIGHT_SAME_RIGHTS, &bfs->vmo)) < 0) {
return r;
}
char buffer[hdr.dirsize];
r = mx_vmo_read(vmo, buffer, sizeof(bootfs_header_t), hdr.dirsize, &rlen);
if ((r < 0) || (rlen < hdr.dirsize)) {
printf("bootfs_parse: could not read directory\n");
uintptr_t addr;
if ((r = mx_vmar_map(mx_vmar_root_self(), 0, vmo, 0,
sizeof(hdr) + hdr.dirsize,
MX_VM_FLAG_PERM_READ, &addr)) < 0) {
printf("boofts_create: couldn't map directory: %d\n", r);
mx_handle_close(bfs->vmo);
return r;
}
bfs->dirsize = hdr.dirsize;
bfs->dir = (void*)addr + sizeof(hdr);
return MX_OK;
}
size_t avail = hdr.dirsize;
void* p = buffer;
void bootfs_destroy(bootfs_t* bfs) {
mx_handle_close(bfs->vmo);
mx_vmar_unmap(mx_vmar_root_self(),
(uintptr_t)bfs->dir - sizeof(bootfs_header_t),
bfs->dirsize);
}
mx_status_t bootfs_parse(bootfs_t* bfs,
mx_status_t (*cb)(void* cookie, const bootfs_entry_t* entry),
void* cookie) {
size_t avail = bfs->dirsize;
void* p = bfs->dir;
mx_status_t r;
while (avail > sizeof(bootfs_entry_t)) {
bootfs_entry_t* e = p;
size_t sz = BOOTFS_RECSIZE(e);
if ((e->name_len < 1) || (e->name_len > BOOTFS_MAX_NAME_LEN) || (sz > avail)) {
if ((e->name_len < 1) || (e->name_len > BOOTFS_MAX_NAME_LEN) ||
(e->name[e->name_len - 1] != 0) || (sz > avail)) {
printf("bootfs: bogus entry!\n");
return MX_ERR_IO;
}
e->name[e->name_len - 1] = 0;
if ((r = cb(cookie, e)) != MX_OK) {
return r;
}
p += sz;
avail -= sz;
}
return MX_OK;
}
mx_status_t bootfs_open(bootfs_t* bfs, const char* name, mx_handle_t* vmo_out) {
size_t name_len = strlen(name) + 1;
size_t avail = bfs->dirsize;
void* p = bfs->dir;
bootfs_entry_t* e;
while (avail > sizeof(bootfs_entry_t)) {
e = p;
size_t sz = BOOTFS_RECSIZE(e);
if ((e->name_len < 1) || (e->name_len > BOOTFS_MAX_NAME_LEN) ||
(e->name[e->name_len - 1] != 0) || (sz > avail)) {
printf("bootfs: bogus entry!\n");
return MX_ERR_IO;
}
if ((name_len == e->name_len) && (memcmp(name, e->name, name_len) == 0)) {
goto found;
}
p += sz;
avail -= sz;
}
printf("bootfs_open: '%s' not found\n", name);
return MX_ERR_NOT_FOUND;
found:;
mx_handle_t vmo;
mx_status_t r;
// Clone a private copy of the file's subset of the bootfs VMO.
// TODO(mcgrathr): Create a plain read-only clone when the feature
// is implemented in the VM.
if ((r = mx_vmo_clone(bfs->vmo, MX_VMO_CLONE_COPY_ON_WRITE,
e->data_off, e->data_len, &vmo)) != MX_OK) {
return r;
}
mx_object_set_property(vmo, MX_PROP_NAME, name, name_len - 1);
// Drop unnecessary MX_RIGHT_WRITE rights.
// TODO(mcgrathr): Should be superfluous with read-only mx_vmo_clone.
if ((r = mx_handle_replace(vmo,
MX_RIGHT_READ | MX_RIGHT_EXECUTE |
MX_RIGHT_MAP | MX_RIGHT_TRANSFER |
MX_RIGHT_DUPLICATE | MX_RIGHT_GET_PROPERTY,
&vmo)) != MX_OK) {
return r;
}
*vmo_out = vmo;
return MX_OK;
}
+11 -1
Ver Arquivo
@@ -37,7 +37,17 @@ mx_status_t mxio_transfer_fd(int fd, int newfd, mx_handle_t* handles, uint32_t*
mx_status_t mxio_create_fd(mx_handle_t* handles, uint32_t* types, size_t hcount, int* fd_out);
typedef struct bootfs_entry bootfs_entry_t;
mx_status_t bootfs_parse(mx_handle_t vmo, size_t len,
typedef struct bootfs {
mx_handle_t vmo;
uint32_t dirsize;
void* dir;
} bootfs_t;
mx_status_t bootfs_create(bootfs_t* bfs, mx_handle_t vmo);
void bootfs_destroy(bootfs_t* bfs);
mx_status_t bootfs_open(bootfs_t* bfs, const char* name, mx_handle_t* vmo);
mx_status_t bootfs_parse(bootfs_t* bfs,
mx_status_t (*cb)(void* cookie, const bootfs_entry_t* entry),
void* cookie);