xref: /aosp_15_r20/external/libwebsockets/lib/misc/romfs.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
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