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