1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2017 National Institute of Advanced Industrial Science
3*1c60b9acSAndroid Build Coastguard Worker * and Technology (AIST)
4*1c60b9acSAndroid Build Coastguard Worker *
5*1c60b9acSAndroid Build Coastguard Worker * All rights reserved.
6*1c60b9acSAndroid Build Coastguard Worker *
7*1c60b9acSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
8*1c60b9acSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
9*1c60b9acSAndroid Build Coastguard Worker *
10*1c60b9acSAndroid Build Coastguard Worker * Redistributions of source code must retain the above copyright notice, this
11*1c60b9acSAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * Redistributions in binary form must reproduce the above copyright notice,
14*1c60b9acSAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
15*1c60b9acSAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
16*1c60b9acSAndroid Build Coastguard Worker *
17*1c60b9acSAndroid Build Coastguard Worker * Neither the name of AIST nor the names of its contributors may be used
18*1c60b9acSAndroid Build Coastguard Worker * to endorse or promote products derived from this software without specific
19*1c60b9acSAndroid Build Coastguard Worker * prior written permission.
20*1c60b9acSAndroid Build Coastguard Worker *
21*1c60b9acSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*1c60b9acSAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*1c60b9acSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*1c60b9acSAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25*1c60b9acSAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*1c60b9acSAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*1c60b9acSAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*1c60b9acSAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*1c60b9acSAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30*1c60b9acSAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31*1c60b9acSAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
32*1c60b9acSAndroid Build Coastguard Worker */
33*1c60b9acSAndroid Build Coastguard Worker
34*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
35*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
36*1c60b9acSAndroid Build Coastguard Worker #include <stdint.h>
37*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
38*1c60b9acSAndroid Build Coastguard Worker #include "romfs.h"
39*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_ESP32)
40*1c60b9acSAndroid Build Coastguard Worker #include "esp_spi_flash.h"
41*1c60b9acSAndroid Build Coastguard Worker #endif
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker #define RFS_STRING_MAX 96
44*1c60b9acSAndroid Build Coastguard Worker
45*1c60b9acSAndroid Build Coastguard Worker static u32_be_t cache[(RFS_STRING_MAX + 32) / 4];
46*1c60b9acSAndroid Build Coastguard Worker static romfs_inode_t ci = (romfs_inode_t)cache;
47*1c60b9acSAndroid Build Coastguard Worker static romfs_t cr = (romfs_t)cache;
48*1c60b9acSAndroid Build Coastguard Worker
49*1c60b9acSAndroid Build Coastguard Worker static void
set_cache(romfs_inode_t inode,size_t len)50*1c60b9acSAndroid Build Coastguard Worker set_cache(romfs_inode_t inode, size_t len)
51*1c60b9acSAndroid Build Coastguard Worker {
52*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_ESP32)
53*1c60b9acSAndroid Build Coastguard Worker spi_flash_read((uint32_t)inode, cache, len);
54*1c60b9acSAndroid Build Coastguard Worker #endif
55*1c60b9acSAndroid Build Coastguard Worker }
56*1c60b9acSAndroid Build Coastguard Worker
57*1c60b9acSAndroid Build Coastguard Worker static uint32_t
untohl(const u32_be_t be)58*1c60b9acSAndroid Build Coastguard Worker untohl(const u32_be_t be)
59*1c60b9acSAndroid Build Coastguard Worker {
60*1c60b9acSAndroid Build Coastguard Worker return ((be >> 24) & 0xff) |
61*1c60b9acSAndroid Build Coastguard Worker ((be >> 16) & 0xff) << 8 |
62*1c60b9acSAndroid Build Coastguard Worker ((be >> 8) & 0xff) << 16 |
63*1c60b9acSAndroid Build Coastguard Worker (be & 0xff) << 24;
64*1c60b9acSAndroid Build Coastguard Worker }
65*1c60b9acSAndroid Build Coastguard Worker static romfs_inode_t
66*1c60b9acSAndroid Build Coastguard Worker romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path);
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker static int
plus_padding(const uint8_t * s)69*1c60b9acSAndroid Build Coastguard Worker plus_padding(const uint8_t *s)
70*1c60b9acSAndroid Build Coastguard Worker {
71*1c60b9acSAndroid Build Coastguard Worker int n;
72*1c60b9acSAndroid Build Coastguard Worker
73*1c60b9acSAndroid Build Coastguard Worker set_cache((romfs_inode_t)s, RFS_STRING_MAX);
74*1c60b9acSAndroid Build Coastguard Worker n = strlen((const char *)cache);
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard Worker if (!(n & 15))
77*1c60b9acSAndroid Build Coastguard Worker n += 0x10;
78*1c60b9acSAndroid Build Coastguard Worker
79*1c60b9acSAndroid Build Coastguard Worker return (n + 15) & ~15;
80*1c60b9acSAndroid Build Coastguard Worker }
81*1c60b9acSAndroid Build Coastguard Worker
82*1c60b9acSAndroid Build Coastguard Worker static romfs_inode_t
skip_and_pad(romfs_inode_t ri)83*1c60b9acSAndroid Build Coastguard Worker skip_and_pad(romfs_inode_t ri)
84*1c60b9acSAndroid Build Coastguard Worker {
85*1c60b9acSAndroid Build Coastguard Worker const uint8_t *p = ((const uint8_t *)ri) + sizeof(*ri);
86*1c60b9acSAndroid Build Coastguard Worker
87*1c60b9acSAndroid Build Coastguard Worker return (romfs_inode_t)(p + plus_padding(p));
88*1c60b9acSAndroid Build Coastguard Worker }
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker size_t
romfs_mount_check(romfs_t romfs)91*1c60b9acSAndroid Build Coastguard Worker romfs_mount_check(romfs_t romfs)
92*1c60b9acSAndroid Build Coastguard Worker {
93*1c60b9acSAndroid Build Coastguard Worker set_cache((romfs_inode_t)romfs, sizeof(*romfs));
94*1c60b9acSAndroid Build Coastguard Worker
95*1c60b9acSAndroid Build Coastguard Worker if (cr->magic1 != 0x6d6f722d ||
96*1c60b9acSAndroid Build Coastguard Worker cr->magic2 != 0x2d736631)
97*1c60b9acSAndroid Build Coastguard Worker return 0;
98*1c60b9acSAndroid Build Coastguard Worker
99*1c60b9acSAndroid Build Coastguard Worker return untohl(cr->size);
100*1c60b9acSAndroid Build Coastguard Worker }
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard Worker static romfs_inode_t
romfs_symlink(romfs_t romfs,romfs_inode_t level,romfs_inode_t i)103*1c60b9acSAndroid Build Coastguard Worker romfs_symlink(romfs_t romfs, romfs_inode_t level, romfs_inode_t i)
104*1c60b9acSAndroid Build Coastguard Worker {
105*1c60b9acSAndroid Build Coastguard Worker const char *p = (const char *)skip_and_pad(i);
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker if (*p == '/') {
108*1c60b9acSAndroid Build Coastguard Worker level = skip_and_pad((romfs_inode_t)romfs);
109*1c60b9acSAndroid Build Coastguard Worker p++;
110*1c60b9acSAndroid Build Coastguard Worker }
111*1c60b9acSAndroid Build Coastguard Worker
112*1c60b9acSAndroid Build Coastguard Worker return romfs_lookup(romfs, level, p);
113*1c60b9acSAndroid Build Coastguard Worker }
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker static romfs_inode_t
dir_link(romfs_t romfs,romfs_inode_t i)116*1c60b9acSAndroid Build Coastguard Worker dir_link(romfs_t romfs, romfs_inode_t i)
117*1c60b9acSAndroid Build Coastguard Worker {
118*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
119*1c60b9acSAndroid Build Coastguard Worker return (romfs_inode_t)((const uint8_t *)romfs +
120*1c60b9acSAndroid Build Coastguard Worker untohl(ci->dir_start));
121*1c60b9acSAndroid Build Coastguard Worker }
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker static romfs_inode_t
romfs_lookup(romfs_t romfs,romfs_inode_t start,const char * path)124*1c60b9acSAndroid Build Coastguard Worker romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path)
125*1c60b9acSAndroid Build Coastguard Worker {
126*1c60b9acSAndroid Build Coastguard Worker romfs_inode_t level, i = start, i_in;
127*1c60b9acSAndroid Build Coastguard Worker const char *p, *cp;
128*1c60b9acSAndroid Build Coastguard Worker uint32_t next_be;
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker if (start == (romfs_inode_t)romfs)
131*1c60b9acSAndroid Build Coastguard Worker i = skip_and_pad((romfs_inode_t)romfs);
132*1c60b9acSAndroid Build Coastguard Worker level = i;
133*1c60b9acSAndroid Build Coastguard Worker while (i != (romfs_inode_t)romfs) {
134*1c60b9acSAndroid Build Coastguard Worker const char *n = ((const char *)i) + sizeof(*i);
135*1c60b9acSAndroid Build Coastguard Worker
136*1c60b9acSAndroid Build Coastguard Worker p = path;
137*1c60b9acSAndroid Build Coastguard Worker i_in = i;
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
140*1c60b9acSAndroid Build Coastguard Worker next_be = ci->next;
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker cp = (const char *)cache;
143*1c60b9acSAndroid Build Coastguard Worker set_cache((romfs_inode_t)n, RFS_STRING_MAX);
144*1c60b9acSAndroid Build Coastguard Worker
145*1c60b9acSAndroid Build Coastguard Worker while (*p && *p != '/' && *cp && *p == *cp &&
146*1c60b9acSAndroid Build Coastguard Worker (p - path) < RFS_STRING_MAX) {
147*1c60b9acSAndroid Build Coastguard Worker p++;
148*1c60b9acSAndroid Build Coastguard Worker n++;
149*1c60b9acSAndroid Build Coastguard Worker cp++;
150*1c60b9acSAndroid Build Coastguard Worker }
151*1c60b9acSAndroid Build Coastguard Worker
152*1c60b9acSAndroid Build Coastguard Worker while (*p == '/' && p[1] == '/')
153*1c60b9acSAndroid Build Coastguard Worker p++;
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker if (!*cp && (!*p || *p == '/') &&
156*1c60b9acSAndroid Build Coastguard Worker (untohl(next_be) & 7) == RFST_HARDLINK) {
157*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
158*1c60b9acSAndroid Build Coastguard Worker return (romfs_inode_t)
159*1c60b9acSAndroid Build Coastguard Worker ((const uint8_t *)romfs +
160*1c60b9acSAndroid Build Coastguard Worker (untohl(ci->dir_start) & ~15));
161*1c60b9acSAndroid Build Coastguard Worker }
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker if (!*p && !*cp) {
164*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
165*1c60b9acSAndroid Build Coastguard Worker if ((untohl(ci->next) & 7) == RFST_SYMLINK) {
166*1c60b9acSAndroid Build Coastguard Worker i = romfs_symlink(romfs, level, i);
167*1c60b9acSAndroid Build Coastguard Worker continue;
168*1c60b9acSAndroid Build Coastguard Worker }
169*1c60b9acSAndroid Build Coastguard Worker return i;
170*1c60b9acSAndroid Build Coastguard Worker }
171*1c60b9acSAndroid Build Coastguard Worker
172*1c60b9acSAndroid Build Coastguard Worker if (!*p && *cp == '/')
173*1c60b9acSAndroid Build Coastguard Worker return NULL;
174*1c60b9acSAndroid Build Coastguard Worker
175*1c60b9acSAndroid Build Coastguard Worker while (*p == '/' && p[1] == '/')
176*1c60b9acSAndroid Build Coastguard Worker p++;
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker if (*p == '/' && !*cp) {
179*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
180*1c60b9acSAndroid Build Coastguard Worker switch (untohl(ci->next) & 7) {
181*1c60b9acSAndroid Build Coastguard Worker case RFST_SYMLINK:
182*1c60b9acSAndroid Build Coastguard Worker i = romfs_symlink(romfs, level, i);
183*1c60b9acSAndroid Build Coastguard Worker if (!i)
184*1c60b9acSAndroid Build Coastguard Worker return NULL;
185*1c60b9acSAndroid Build Coastguard Worker i = dir_link(romfs, i);
186*1c60b9acSAndroid Build Coastguard Worker while (*path != '/' && *path)
187*1c60b9acSAndroid Build Coastguard Worker path++;
188*1c60b9acSAndroid Build Coastguard Worker if (!*path)
189*1c60b9acSAndroid Build Coastguard Worker return NULL;
190*1c60b9acSAndroid Build Coastguard Worker path++;
191*1c60b9acSAndroid Build Coastguard Worker continue;
192*1c60b9acSAndroid Build Coastguard Worker case RFST_DIR:
193*1c60b9acSAndroid Build Coastguard Worker path = p + 1;
194*1c60b9acSAndroid Build Coastguard Worker i = dir_link(romfs, i);
195*1c60b9acSAndroid Build Coastguard Worker break;
196*1c60b9acSAndroid Build Coastguard Worker default:
197*1c60b9acSAndroid Build Coastguard Worker path = p + 1;
198*1c60b9acSAndroid Build Coastguard Worker i = skip_and_pad(i);
199*1c60b9acSAndroid Build Coastguard Worker break;
200*1c60b9acSAndroid Build Coastguard Worker }
201*1c60b9acSAndroid Build Coastguard Worker level = i;
202*1c60b9acSAndroid Build Coastguard Worker continue;
203*1c60b9acSAndroid Build Coastguard Worker }
204*1c60b9acSAndroid Build Coastguard Worker
205*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
206*1c60b9acSAndroid Build Coastguard Worker if (!(untohl(ci->next) & ~15))
207*1c60b9acSAndroid Build Coastguard Worker return NULL;
208*1c60b9acSAndroid Build Coastguard Worker
209*1c60b9acSAndroid Build Coastguard Worker i = (romfs_inode_t)((const uint8_t *)romfs +
210*1c60b9acSAndroid Build Coastguard Worker (untohl(ci->next) & ~15));
211*1c60b9acSAndroid Build Coastguard Worker if (i == i_in)
212*1c60b9acSAndroid Build Coastguard Worker return NULL;
213*1c60b9acSAndroid Build Coastguard Worker }
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker return NULL;
216*1c60b9acSAndroid Build Coastguard Worker }
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker const void *
romfs_get_info(romfs_t romfs,const char * path,size_t * len,size_t * csum)219*1c60b9acSAndroid Build Coastguard Worker romfs_get_info(romfs_t romfs, const char *path, size_t *len, size_t *csum)
220*1c60b9acSAndroid Build Coastguard Worker {
221*1c60b9acSAndroid Build Coastguard Worker romfs_inode_t i;
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker if (*path == '/')
224*1c60b9acSAndroid Build Coastguard Worker path++;
225*1c60b9acSAndroid Build Coastguard Worker
226*1c60b9acSAndroid Build Coastguard Worker i = romfs_lookup(romfs, (romfs_inode_t)romfs, path);
227*1c60b9acSAndroid Build Coastguard Worker
228*1c60b9acSAndroid Build Coastguard Worker if (!i)
229*1c60b9acSAndroid Build Coastguard Worker return NULL;
230*1c60b9acSAndroid Build Coastguard Worker
231*1c60b9acSAndroid Build Coastguard Worker set_cache(i, sizeof(*i));
232*1c60b9acSAndroid Build Coastguard Worker *len = untohl(ci->size);
233*1c60b9acSAndroid Build Coastguard Worker if (csum)
234*1c60b9acSAndroid Build Coastguard Worker *csum = untohl(ci->checksum);
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker return (void *)skip_and_pad(i);
237*1c60b9acSAndroid Build Coastguard Worker }
238