uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
romfs.c
Go to the documentation of this file.
1 #include <string.h>
2 #include <FreeRTOS.h>
3 #include <semphr.h>
4 #include <unistd.h>
5 #ifdef USE_NEWLIB
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #endif
10 #include "fio.h"
11 #include "filesystem.h"
12 #include "romfs.h"
13 #include "osdebug.h"
14 #include "hash-djb2.h"
15 
16 struct romfs_fds_t {
17  const uint8_t * file;
18  uint32_t cursor;
19 };
20 
21 static struct romfs_fds_t romfs_fds[MAX_FDS];
22 
23 static uint32_t get_unaligned(const uint8_t * d) {
24  return ((uint32_t) d[0]) | ((uint32_t) (d[1] << 8)) | ((uint32_t) (d[2] << 16)) | ((uint32_t) (d[3] << 24));
25 }
26 
27 static ssize_t romfs_read(void * opaque, void * buf, size_t count) {
28  struct romfs_fds_t * f = (struct romfs_fds_t *) opaque;
29  const uint8_t * size_p = f->file - 4;
30  uint32_t size = get_unaligned(size_p);
31 
32  if ((f->cursor + count) > size)
33  count = size - f->cursor;
34 
35  memcpy(buf, f->file + f->cursor, count);
36  f->cursor += count;
37 
38  return count;
39 }
40 
41 static off_t romfs_seek(void * opaque, off_t offset, int whence) {
42  struct romfs_fds_t * f = (struct romfs_fds_t *) opaque;
43  const uint8_t * size_p = f->file - 4;
44  uint32_t size = get_unaligned(size_p);
45  uint32_t origin;
46 
47  switch (whence) {
48  case SEEK_SET:
49  origin = 0;
50  break;
51  case SEEK_CUR:
52  origin = f->cursor;
53  break;
54  case SEEK_END:
55  origin = size;
56  break;
57  default:
58  return -1;
59  }
60 
61  offset = origin + offset;
62 
63  if (offset < 0)
64  return -1;
65  if (offset > size)
66  offset = size;
67 
68  f->cursor = offset;
69 
70  return offset;
71 }
72 
73 const uint8_t * romfs_get_file_by_hash(const uint8_t * romfs, uint32_t h, uint32_t * len) {
74  const uint8_t * meta;
75 
76  for (meta = romfs; get_unaligned(meta) && get_unaligned(meta + 4); meta += get_unaligned(meta + 4) + 8) {
77  if (get_unaligned(meta) == h) {
78  if (len) {
79  *len = get_unaligned(meta + 4);
80  }
81  return meta + 8;
82  }
83  }
84 
85  return NULL;
86 }
87 
88 static int romfs_open(void * opaque, const char * path, int flags, int mode) {
89  uint32_t h = hash_djb2((const uint8_t *) path, -1);
90  const uint8_t * romfs = (const uint8_t *) opaque;
91  const uint8_t * file;
92  int r = -1;
93 
94  file = romfs_get_file_by_hash(romfs, h, NULL);
95 
96  if (file) {
97  r = fio_open(romfs_read, NULL, romfs_seek, NULL, NULL);
98  if (r > 0) {
99  romfs_fds[r].file = file;
100  romfs_fds[r].cursor = 0;
101  fio_set_opaque(r, romfs_fds + r);
102  }
103  }
104  return r;
105 }
106 
107 void register_romfs(const char * mountpoint, const uint8_t * romfs) {
108 // DBGOUT("Registering romfs `%s' @ %p\r\n", mountpoint, romfs);
109  register_fs(mountpoint, romfs_open, (void *) romfs);
110 }