From ea49b5b3f435bce0a301111fad0738efb0b39e0d Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 29 Jan 2011 18:34:54 -0800 Subject: Adding some romfs support. --- Makefile | 9 +++- arch/arm/lpc17xx/ldscript | 17 ++++--- os/Makefile | 2 + os/include/fio.h | 1 + os/include/romfs.h | 9 ++++ os/src/fio.c | 5 ++ os/src/fread.c | 5 ++ os/src/lseek.c | 22 +++++++- os/src/read.c | 21 ++++++-- os/src/romfs.c | 94 ++++++++++++++++++++++++++++++++++ os/src/write.c | 2 +- tools/Makefile | 15 ++++++ tools/mkromfs.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++ tools/romfs.txt | 6 +++ 14 files changed, 320 insertions(+), 15 deletions(-) create mode 100644 os/include/romfs.h create mode 100644 os/src/fread.c create mode 100644 os/src/romfs.c create mode 100644 tools/Makefile create mode 100644 tools/mkromfs.c create mode 100644 tools/romfs.txt diff --git a/Makefile b/Makefile index 370bd08..d2b5619 100644 --- a/Makefile +++ b/Makefile @@ -6,14 +6,15 @@ export ROOTDIR = $(CURDIR) include common.mk -all: libs $(TARGET) +all: tools libs $(TARGET) clean: clean-generic $(Q)$(MAKE) $(MAKE_OPTS) -C FreeRTOS clean $(Q)$(MAKE) $(MAKE_OPTS) -C arch clean $(Q)$(MAKE) $(MAKE_OPTS) -C os clean + $(Q)$(MAKE) $(MAKE_OPTS) -C tools clean -.PHONY: libs FreeRTOS arch os +.PHONY: libs FreeRTOS arch os tools FreeRTOS/libFreeRTOS.a: FreeRTOS arch/libarch.a: arch @@ -33,6 +34,10 @@ os: $(E) "[MAKE] Entering os" $(Q)$(MAKE) $(MAKE_OPTS) -C os +tools: + $(E) "[MAKE] Entering tools" + $(Q)$(MAKE) $(MAKE_OPTS) -C tools + include FreeRTOS/config.mk include arch/config.mk include os/config.mk diff --git a/arch/arm/lpc17xx/ldscript b/arch/arm/lpc17xx/ldscript index 2468d12..b8ca0b7 100644 --- a/arch/arm/lpc17xx/ldscript +++ b/arch/arm/lpc17xx/ldscript @@ -101,30 +101,30 @@ SECTIONS *(.eh_frame_hdr) *(.eh_frame) - . = ALIGN(4); + . = ALIGN(16); KEEP(*(.init)) - . = ALIGN(4); + . = ALIGN(16); __preinit_array_start = .; KEEP (*(.preinit_array)) __preinit_array_end = .; - . = ALIGN(4); + . = ALIGN(16); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; - . = ALIGN(0x4); + . = ALIGN(16); KEEP (*crtbegin.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*crtend.o(.ctors)) - . = ALIGN(4); + . = ALIGN(16); KEEP(*(.fini)) - . = ALIGN(4); + . = ALIGN(16); __fini_array_start = .; KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) @@ -135,13 +135,16 @@ SECTIONS KEEP (*(SORT(.dtors.*))) KEEP (*crtend.o(.dtors)) - . = ALIGN(4); + . = ALIGN(16); __cs3_regions = .; LONG (0) LONG (__cs3_region_init_ram) LONG (__cs3_region_start_ram) LONG (__cs3_region_init_size_ram) LONG (__cs3_region_zero_size_ram) + + . = ALIGN(16); + *(.romfs.data) } /* .ARM.exidx is sorted, so has to go in its own output section. */ diff --git a/os/Makefile b/os/Makefile index 75bc575..cfc6e33 100644 --- a/os/Makefile +++ b/os/Makefile @@ -14,6 +14,7 @@ src/filesystem.c \ src/fio.c \ src/hash-djb2.c \ src/osdebug.c \ +src/romfs.c \ \ src/close.c \ src/fstat.c \ @@ -28,6 +29,7 @@ src/fclose.c \ src/fflush.c \ src/fopen.c \ src/fprintf.c \ +src/fread.c \ src/free.c \ src/fwrite.c \ src/malloc.c \ diff --git a/os/include/fio.h b/os/include/fio.h index e4ba659..c57b293 100644 --- a/os/include/fio.h +++ b/os/include/fio.h @@ -24,6 +24,7 @@ ssize_t fio_read(int fd, void * buf, size_t count); ssize_t fio_write(int fd, const void * buf, size_t count); off_t fio_seek(int fd, off_t offset, int whence); int fio_close(int fd); +void fio_set_opaque(int fd, void * opaque); void register_devfs(); diff --git a/os/include/romfs.h b/os/include/romfs.h new file mode 100644 index 0000000..b227baa --- /dev/null +++ b/os/include/romfs.h @@ -0,0 +1,9 @@ +#ifndef __ROMFS_H__ +#define __ROMFS_H__ + +#include + +void register_romfs(const char * mountpoint, const uint8_t * romfs); + +#endif + diff --git a/os/src/fio.c b/os/src/fio.c index b7e225a..9fe5038 100644 --- a/os/src/fio.c +++ b/os/src/fio.c @@ -146,6 +146,11 @@ int fio_close(int fd) { return r; } +void fio_set_opaque(int fd, void * opaque) { + if (fio_is_open_int(fd)) + fio_fds[fd].opaque = opaque; +} + #define stdin_hash 0x0BA00421 #define stdout_hash 0x7FA08308 #define stderr_hash 0x7FA058A3 diff --git a/os/src/fread.c b/os/src/fread.c new file mode 100644 index 0000000..b003d33 --- /dev/null +++ b/os/src/fread.c @@ -0,0 +1,5 @@ +#include + +size_t fread(void * ptr, size_t size, size_t nmemb, FILE * file) { + return _fread_r(_impure_ptr, ptr, size, nmemb, file); +} diff --git a/os/src/lseek.c b/os/src/lseek.c index fdd0b94..1cb0234 100644 --- a/os/src/lseek.c +++ b/os/src/lseek.c @@ -1,7 +1,25 @@ #include #include +#include +#include "fio.h" _off_t _lseek_r(struct _reent * reent, int fd, _off_t seek, int wheel) { - DBGOUT("_lseek_r(%p, %d, %d, %d)\r\n", reent, fd, (int) seek, wheel); - return 0; + off_t r; + + if ((wheel != SEEK_SET) && (wheel != SEEK_CUR) && (wheel != SEEK_END)) { + reent->_errno = EINVAL; + return -1; + } + + if (!fio_is_open(fd)) { + reent->_errno = EBADF; + return -1; + } + + r = fio_seek(fd, seek, wheel); + + if (r < 0) + reent->_errno = EINVAL; + + return r; } diff --git a/os/src/read.c b/os/src/read.c index 4850c9c..f848812 100644 --- a/os/src/read.c +++ b/os/src/read.c @@ -1,7 +1,22 @@ #include #include +#include +#include "fio.h" -_ssize_t _read_r(struct _reent * reent, int fd, void * ptr, size_t size) { - DBGOUT("_read_r(%p, %d, %p, %u)\r\n", reent, fd, ptr, size); - return 0; +_ssize_t _read_r(struct _reent * reent, int fd, void * buf, size_t size) { + _ssize_t r; + + if (!fio_is_open(fd)) { + reent->_errno = EBADF; + return -1; + } + + r = fio_read(fd, buf, size); + + if (r < 0) { + reent->_errno = EINVAL; + return -1; + } + + return r; } diff --git a/os/src/romfs.c b/os/src/romfs.c new file mode 100644 index 0000000..403bef9 --- /dev/null +++ b/os/src/romfs.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#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) { + register_fs(mountpoint, romfs_open, (void *) romfs); +} diff --git a/os/src/write.c b/os/src/write.c index 268c0f1..14e26d6 100644 --- a/os/src/write.c +++ b/os/src/write.c @@ -4,7 +4,7 @@ #include "fio.h" _ssize_t _write_r(struct _reent * reent, int fd, const void * buf, size_t size) { - int r; + _ssize_t r; if (!fio_is_open(fd)) { reent->_errno = EBADF; diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 0000000..65ff73f --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,15 @@ +CC = gcc +LD = gcc +CPPFLAGS = -O3 + +TARGETS = mkromfs +MKROMFS_SRCS = mkromfs.c +MKROMFS_OBJS = $(addsuffix .o, $(basename $(MKROMFS_SRCS))) + +all: $(TARGETS) + +mkromfs: $(MKROMFS_OBJS) + $(LD) -o mkromfs $(MKROMFS_OBJS) + +clean: + rm -rf $(MKROMFS_OBJS) $(TARGETS) diff --git a/tools/mkromfs.c b/tools/mkromfs.c new file mode 100644 index 0000000..be46a44 --- /dev/null +++ b/tools/mkromfs.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include + +#define hash_init 5381 + +uint32_t hash_djb2(const uint8_t * str, uint32_t hash) { + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) ^ c; + + return hash; +} + +void usage(const char * binname) { + printf("Usage: %s [-d ] [outfile]\n", binname); + exit(-1); +} + +void processdir(DIR * dirp, const char * curpath, FILE * outfile) { + char fullpath[1024]; + char buf[16 * 1024]; + struct dirent * ent; + DIR * rec_dirp; + uint32_t cur_hash = hash_djb2(curpath, hash_init); + uint32_t size, w, hash; + uint8_t b; + FILE * infile; + + while ((ent = readdir(dirp))) { + strcpy(fullpath, curpath); + strcat(fullpath, ent->d_name); + switch(ent->d_type) { + case DT_DIR: + if (strcmp(ent->d_name, ".") == 0) + continue; + if (strcmp(ent->d_name, "..") == 0) + continue; + strcat(fullpath, "/"); + rec_dirp = opendir(fullpath); + processdir(rec_dirp, fullpath, outfile); + closedir(rec_dirp); + break; + case DT_REG: + case DT_LNK: + hash = hash_djb2(ent->d_name, cur_hash); + infile = fopen(fullpath, "rb"); + if (!infile) { + perror("opening file"); + exit(-1); + } + b = (hash >> 0) & 0xff; fwrite(&b, 1, 1, outfile); + b = (hash >> 8) & 0xff; fwrite(&b, 1, 1, outfile); + b = (hash >> 16) & 0xff; fwrite(&b, 1, 1, outfile); + b = (hash >> 24) & 0xff; fwrite(&b, 1, 1, outfile); + fseek(infile, 0, SEEK_END); + size = ftell(infile); + fseek(infile, 0, SEEK_SET); + b = (size >> 0) & 0xff; fwrite(&b, 1, 1, outfile); + b = (size >> 8) & 0xff; fwrite(&b, 1, 1, outfile); + b = (size >> 16) & 0xff; fwrite(&b, 1, 1, outfile); + b = (size >> 24) & 0xff; fwrite(&b, 1, 1, outfile); + while (size) { + w = size > 16 * 1024 ? 16 * 1024 : size; + fread(buf, 1, w, infile); + fwrite(buf, 1, w, outfile); + size -= w; + } + fclose(infile); + break; + } + } +} + +int main(int argc, char ** argv) { + char * binname = *argv++; + char * o; + char * outname = NULL; + char * dirname = "."; + uint64_t z = 0; + FILE * outfile; + DIR * dirp; + + while ((o = *argv++)) { + if (*o == '-') { + o++; + switch (*o) { + case 'd': + dirname = o; + break; + default: + usage(binname); + break; + } + } else { + if (outname) + usage(binname); + outname = o; + } + } + + if (!outname) + outfile = stdout; + else + outfile = fopen(outname, "wb"); + + if (!outfile) { + perror("opening file"); + exit(-1); + } + + dirp = opendir(dirname); + if (!dirp) { + perror("opening directory"); + exit(-1); + } + + processdir(dirp, "", outfile); + fwrite(&z, 1, 8, outfile); + if (outname) + fclose(outfile); + closedir(dirp); +} diff --git a/tools/romfs.txt b/tools/romfs.txt new file mode 100644 index 0000000..bf184e5 --- /dev/null +++ b/tools/romfs.txt @@ -0,0 +1,6 @@ +Format is excessively simple and short. Read the source for help. + +Converting to an object: + +$ arm-none-eabi-objcopy -I binary -O elf32-littlearm \ +--prefix-sections '.romfs' --binary-architecture arm my-romfs.bin my-romfs.o -- cgit v1.2.3