#include #include #include #include #ifdef USE_NEWLIB #include #include #include #endif #include "fio.h" #include "filesystem.h" #include "romfs.h" #include "osdebug.h" #include "hash-djb2.h" struct romfs_fds_t { const uint8_t * file; uint32_t cursor; }; static struct romfs_fds_t romfs_fds[MAX_FDS]; static uint32_t get_unaligned(const uint32_t * _d) { const uint8_t * d = (const uint8_t *) _d; return ((uint32_t) d[0]) | ((uint32_t) (d[1] << 8)) | ((uint32_t) (d[2] << 16)) | ((uint32_t) (d[3] << 24)); } static ssize_t romfs_read(void * opaque, void * buf, size_t count) { struct romfs_fds_t * f = (struct romfs_fds_t *) opaque; const uint8_t * size_p = f->file - 4; uint32_t size = get_unaligned((uint32_t *) size_p); if ((f->cursor + count) > size) count = size - f->cursor; memcpy(buf, f->file + f->cursor, count); f->cursor += count; return count; } static off_t romfs_seek(void * opaque, off_t offset, int whence) { struct romfs_fds_t * f = (struct romfs_fds_t *) opaque; const uint8_t * size_p = f->file - 4; uint32_t size = get_unaligned((uint32_t *) size_p); uint32_t origin; switch (whence) { case SEEK_SET: origin = 0; break; case SEEK_CUR: origin = f->cursor; break; case SEEK_END: origin = size; break; default: return -1; } offset = origin + offset; if (offset < 0) return -1; if (offset > size) offset = size; f->cursor = offset; return offset; } static int romfs_open(void * opaque, const char * path, int flags, int mode) { uint32_t h = hash_djb2((const uint8_t *) path, -1); const uint8_t * romfs = (const uint8_t *) opaque; const uint32_t * meta; int r = -1; for (meta = (uint32_t *) romfs; get_unaligned(meta) && get_unaligned(meta + 1); romfs = romfs + meta[1], meta = (uint32_t *) romfs) { if (meta[0] == h) { r = fio_open(romfs_read, NULL, romfs_seek, NULL, NULL); if (r > 0) { romfs_fds[r].file = romfs + 8; romfs_fds[r].cursor = 0; fio_set_opaque(r, romfs_fds + r); } break; } } return r; } void register_romfs(const char * mountpoint, const uint8_t * romfs) { // DBGOUT("Registering romfs `%s' @ %p\r\n", mountpoint, romfs); register_fs(mountpoint, romfs_open, (void *) romfs); }