ICARUS OS (Intelligent Cooperative Architecture for Real-time Unified Systems) 0.1.0
Preemptive Real-Time Operating System for ARM Cortex-M7
Loading...
Searching...
No Matches
fs.c
Go to the documentation of this file.
1
23#include "icarus/icarus.h"
24#include "icarus/svc.h"
25#include <string.h>
26
27/* ---- Internal file table entry ----------------------------------------- */
28
29typedef struct {
30 char name[FS_MAX_NAME_LEN];
31 uint16_t size;
32 bool used;
34
35#ifndef SKIP_STATIC_ASSERTS
36_Static_assert(sizeof(fs_entry_t) == (FS_MAX_NAME_LEN + 2 + 1 + 1 /* pad */),
37 "fs_entry_t unexpected size");
38#endif
39
40/* ---- Storage ----------------------------------------------------------- */
41
44
45/* ---- Internal helpers -------------------------------------------------- */
46
48static int16_t fs_find(const char *name) {
49 for (uint8_t i = 0u; i < (uint8_t)FS_MAX_FILES; i++) {
50 if (fs_table[i].used &&
51 (strncmp(fs_table[i].name, name, FS_MAX_NAME_LEN) == 0)) {
52 return (int16_t)i;
53 }
54 }
55 return -1;
56}
57
59static int16_t fs_free_slot(void) {
60 for (uint8_t i = 0u; i < (uint8_t)FS_MAX_FILES; i++) {
61 if (!fs_table[i].used) {
62 return (int16_t)i;
63 }
64 }
65 return -1;
66}
67
68/* ============================================================================
69 * PRIVILEGED IMPLEMENTATIONS (called from SVC handler)
70 * ========================================================================= */
71
76ITCM_FUNC void __fs_init(void) {
77 (void)memset(fs_table, 0, sizeof(fs_table));
78 (void)memset(fs_data, 0, sizeof(fs_data));
79}
80
88ITCM_FUNC bool __fs_create(const char *name, fs_file_t *out) {
89 if ((name == NULL) || (out == NULL) || (name[0] == '\0')) {
90 return false;
91 }
92 if (strnlen(name, FS_MAX_NAME_LEN) >= (size_t)FS_MAX_NAME_LEN) {
93 return false;
94 }
95
96 if (fs_find(name) >= 0) {
97 return false;
98 }
99
100 int16_t slot = fs_free_slot();
101 if (slot < 0) {
102 return false;
103 }
104
105 (void)strncpy(fs_table[slot].name, name, (size_t)FS_MAX_NAME_LEN - 1u);
106 fs_table[slot].name[FS_MAX_NAME_LEN - 1] = '\0';
107 fs_table[slot].size = 0u;
108 fs_table[slot].used = true;
109 (void)memset(fs_data[slot], 0, FS_MAX_FILE_SIZE);
110
111 out->slot = (uint8_t)slot;
112 out->valid = true;
113
114 return true;
115}
116
124ITCM_FUNC bool __fs_open(const char *name, fs_file_t *out) {
125 if ((name == NULL) || (out == NULL) || (name[0] == '\0')) {
126 return false;
127 }
128
129 int16_t slot = fs_find(name);
130 if (slot < 0) {
131 return false;
132 }
133 out->slot = (uint8_t)slot;
134 out->valid = true;
135 return true;
136}
137
146ITCM_FUNC bool __fs_write(fs_file_t *f, const uint8_t *data, uint16_t len) {
147 if ((f == NULL) || (!f->valid) || (data == NULL) || (len == 0u)) {
148 return false;
149 }
150
151 uint8_t slot = f->slot;
152 if ((slot >= (uint8_t)FS_MAX_FILES) || (!fs_table[slot].used)) {
153 return false;
154 }
155
156 uint16_t current = fs_table[slot].size;
157 if (((uint32_t)current + (uint32_t)len) > (uint32_t)FS_MAX_FILE_SIZE) {
158 return false;
159 }
160
161 (void)memcpy(&fs_data[slot][current], data, len);
162 fs_table[slot].size = (uint16_t)(current + len);
163
164 return true;
165}
166
175ITCM_FUNC uint16_t __fs_read(fs_file_t *f, uint8_t *buf, uint16_t len,
176 uint16_t offset) {
177 if ((f == NULL) || (!f->valid) || (buf == NULL) || (len == 0u)) {
178 return 0u;
179 }
180
181 uint8_t slot = f->slot;
182 if ((slot >= (uint8_t)FS_MAX_FILES) || (!fs_table[slot].used)) {
183 return 0u;
184 }
185
186 uint16_t file_size = fs_table[slot].size;
187 if (offset >= file_size) {
188 return 0;
189 }
190
191 uint16_t available = (uint16_t)(file_size - offset);
192 uint16_t to_read = (len < available) ? len : available;
193
194 (void)memcpy(buf, &fs_data[slot][offset], to_read);
195
196 return to_read;
197}
198
205ITCM_FUNC bool __fs_delete(const char *name) {
206 if ((name == NULL) || (name[0] == '\0')) {
207 return false;
208 }
209
210 int16_t slot = fs_find(name);
211 if (slot < 0) {
212 return false;
213 }
214
215 (void)memset(&fs_table[slot], 0, sizeof(fs_entry_t));
216 (void)memset(fs_data[slot], 0, FS_MAX_FILE_SIZE);
217
218 return true;
219}
220
227ITCM_FUNC uint8_t __fs_list(fs_file_info_t *out, uint8_t max) {
228 if ((out == NULL) || (max == 0u)) {
229 return 0u;
230 }
231
232 uint8_t count = 0u;
233 for (uint8_t i = 0u; (i < (uint8_t)FS_MAX_FILES) && (count < max); i++) {
234 if (fs_table[i].used) {
235 (void)strncpy(out[count].name, fs_table[i].name, FS_MAX_NAME_LEN);
236 out[count].name[FS_MAX_NAME_LEN - 1] = '\0';
237 out[count].size = fs_table[i].size;
238 count++;
239 }
240 }
241
242 return count;
243}
244
250 if (out == NULL) {
251 return;
252 }
253
254 uint32_t used = 0u;
255 uint8_t count = 0u;
256 for (uint8_t i = 0u; i < (uint8_t)FS_MAX_FILES; i++) {
257 if (fs_table[i].used) {
258 used += fs_table[i].size;
259 count++;
260 }
261 }
262
263 const uint32_t total = (uint32_t)((uint32_t)FS_MAX_FILES * (uint32_t)FS_MAX_FILE_SIZE);
264 out->total_bytes = total;
265 out->used_bytes = used;
266 out->free_bytes = total - used;
267 out->file_count = count;
268}
269
270/* ============================================================================
271 * PUBLIC API (SVC call gates — privileged access to filesystem data)
272 * ========================================================================= */
273
277void fs_init(void) {
278#ifndef HOST_TEST
279 __asm__ volatile ("svc %0\n" : : "I" (SVC_FS_INIT));
280#else
281 __fs_init();
282#endif
283}
284
292bool fs_create(const char *name, fs_file_t *out) {
293#ifndef HOST_TEST
294 uint32_t result;
295 __asm__ volatile (
296 "mov r0, %1\n"
297 "mov r1, %2\n"
298 "svc %3\n"
299 "mov %0, r0\n"
300 : "=r" (result)
301 : "r" ((uint32_t)(uintptr_t)name), "r" ((uint32_t)(uintptr_t)out),
302 "I" (SVC_FS_CREATE)
303 : "r0", "r1"
304 );
305 return (bool)result;
306#else
307 return __fs_create(name, out);
308#endif
309}
310
318bool fs_open(const char *name, fs_file_t *out) {
319#ifndef HOST_TEST
320 uint32_t result;
321 __asm__ volatile (
322 "mov r0, %1\n"
323 "mov r1, %2\n"
324 "svc %3\n"
325 "mov %0, r0\n"
326 : "=r" (result)
327 : "r" ((uint32_t)(uintptr_t)name), "r" ((uint32_t)(uintptr_t)out),
328 "I" (SVC_FS_OPEN)
329 : "r0", "r1"
330 );
331 return (bool)result;
332#else
333 return __fs_open(name, out);
334#endif
335}
336
345bool fs_write(fs_file_t *f, const uint8_t *data, uint16_t len) {
346#ifndef HOST_TEST
347 uint32_t result;
348 __asm__ volatile (
349 "mov r0, %1\n"
350 "mov r1, %2\n"
351 "mov r2, %3\n"
352 "svc %4\n"
353 "mov %0, r0\n"
354 : "=r" (result)
355 : "r" ((uint32_t)(uintptr_t)f), "r" ((uint32_t)(uintptr_t)data),
356 "r" ((uint32_t)len), "I" (SVC_FS_WRITE)
357 : "r0", "r1", "r2"
358 );
359 return (bool)result;
360#else
361 return __fs_write(f, data, len);
362#endif
363}
364
373uint16_t fs_read(fs_file_t *f, uint8_t *buf, uint16_t len, uint16_t offset) {
374#ifndef HOST_TEST
375 uint32_t result;
376 __asm__ volatile (
377 "mov r0, %1\n"
378 "mov r1, %2\n"
379 "mov r2, %3\n"
380 "mov r3, %4\n"
381 "svc %5\n"
382 "mov %0, r0\n"
383 : "=r" (result)
384 : "r" ((uint32_t)(uintptr_t)f), "r" ((uint32_t)(uintptr_t)buf),
385 "r" ((uint32_t)len), "r" ((uint32_t)offset),
386 "I" (SVC_FS_READ)
387 : "r0", "r1", "r2", "r3"
388 );
389 return (uint16_t)result;
390#else
391 return __fs_read(f, buf, len, offset);
392#endif
393}
394
401bool fs_delete(const char *name) {
402#ifndef HOST_TEST
403 uint32_t result;
404 __asm__ volatile (
405 "mov r0, %1\n"
406 "svc %2\n"
407 "mov %0, r0\n"
408 : "=r" (result)
409 : "r" ((uint32_t)(uintptr_t)name), "I" (SVC_FS_DELETE)
410 : "r0"
411 );
412 return (bool)result;
413#else
414 return __fs_delete(name);
415#endif
416}
417
424uint8_t fs_list(fs_file_info_t *out, uint8_t max) {
425#ifndef HOST_TEST
426 uint32_t result;
427 __asm__ volatile (
428 "mov r0, %1\n"
429 "mov r1, %2\n"
430 "svc %3\n"
431 "mov %0, r0\n"
432 : "=r" (result)
433 : "r" ((uint32_t)(uintptr_t)out), "r" ((uint32_t)max),
434 "I" (SVC_FS_LIST)
435 : "r0", "r1"
436 );
437 return (uint8_t)result;
438#else
439 return __fs_list(out, max);
440#endif
441}
442
448#ifndef HOST_TEST
449 __asm__ volatile (
450 "mov r0, %0\n"
451 "svc %1\n"
452 :
453 : "r" ((uint32_t)(uintptr_t)out), "I" (SVC_FS_STATS)
454 : "r0"
455 );
456#else
457 __fs_stats(out);
458#endif
459}
bool __fs_write(fs_file_t *f, const uint8_t *data, uint16_t len)
Privileged implementation of fs_write().
Definition fs.c:146
bool fs_write(fs_file_t *f, const uint8_t *data, uint16_t len)
Append data to an open file via SVC gate.
Definition fs.c:345
bool fs_create(const char *name, fs_file_t *out)
Create a new file via SVC gate.
Definition fs.c:292
bool fs_delete(const char *name)
Delete a file by name via SVC gate.
Definition fs.c:401
void __fs_init(void)
Privileged implementation of fs_init().
Definition fs.c:76
static int16_t fs_free_slot(void)
Find first free slot, or -1 if full.
Definition fs.c:59
uint8_t __fs_list(fs_file_info_t *out, uint8_t max)
Privileged implementation of fs_list().
Definition fs.c:227
bool __fs_open(const char *name, fs_file_t *out)
Privileged implementation of fs_open().
Definition fs.c:124
uint16_t fs_read(fs_file_t *f, uint8_t *buf, uint16_t len, uint16_t offset)
Read bytes from an open file at a given offset via SVC gate.
Definition fs.c:373
bool __fs_create(const char *name, fs_file_t *out)
Privileged implementation of fs_create().
Definition fs.c:88
void fs_stats(fs_stats_t *out)
Return aggregate filesystem statistics via SVC gate.
Definition fs.c:447
uint8_t fs_list(fs_file_info_t *out, uint8_t max)
Enumerate all files via SVC gate.
Definition fs.c:424
static fs_entry_t fs_table[16]
Definition fs.c:42
bool fs_open(const char *name, fs_file_t *out)
Open an existing file by name via SVC gate.
Definition fs.c:318
void fs_init(void)
Clear all file table entries and zero the data store via SVC gate.
Definition fs.c:277
void __fs_stats(fs_stats_t *out)
Privileged implementation of fs_stats().
Definition fs.c:249
static uint8_t fs_data[16][2048]
Definition fs.c:43
static int16_t fs_find(const char *name)
Find slot index for name, or -1 if not found.
Definition fs.c:48
uint16_t __fs_read(fs_file_t *f, uint8_t *buf, uint16_t len, uint16_t offset)
Privileged implementation of fs_read().
Definition fs.c:175
bool __fs_delete(const char *name)
Privileged implementation of fs_delete().
Definition fs.c:205
#define FS_MAX_NAME_LEN
Definition fs.h:33
#define FS_MAX_FILES
Definition fs.h:32
#define FS_MAX_FILE_SIZE
Definition fs.h:34
#define ITCM_FUNC
Definition config.h:155
ICARUS OS - Main API Header.
Definition fs.c:29
bool used
Slot is occupied.
Definition fs.c:32
char name[12]
Null-terminated file name.
Definition fs.c:30
uint16_t size
Bytes written so far.
Definition fs.c:31
Per-file metadata returned by fs_list().
Definition fs.h:46
uint16_t size
Current number of bytes written.
Definition fs.h:48
char name[12]
Null-terminated file name.
Definition fs.h:47
Opaque file handle — callers hold one of these per open file.
Definition fs.h:40
uint8_t slot
Index into internal file table (0-based).
Definition fs.h:41
bool valid
True if handle references a live file entry.
Definition fs.h:42
Aggregate filesystem statistics.
Definition fs.h:52
uint32_t free_bytes
Bytes available for new data.
Definition fs.h:55
uint32_t used_bytes
Bytes occupied by all file data.
Definition fs.h:54
uint32_t total_bytes
Total storage capacity in bytes.
Definition fs.h:53
uint8_t file_count
Number of files currently stored.
Definition fs.h:56
ICARUS Supervisor Call (SVC) Definitions.
#define SVC_FS_DELETE
Definition svc.h:149
#define SVC_FS_LIST
Definition svc.h:150
#define SVC_FS_OPEN
Definition svc.h:146
#define SVC_FS_INIT
Definition svc.h:144
#define SVC_FS_WRITE
Definition svc.h:147
#define SVC_FS_READ
Definition svc.h:148
#define SVC_FS_CREATE
Definition svc.h:145
#define SVC_FS_STATS
Definition svc.h:151