summaryrefslogtreecommitdiff
path: root/flashimg/cpu_main/flash_static.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-07-03 08:00:50 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-07-03 08:00:50 -0600
commit1d5a211e1ae3645e9c13163b76fea0a3c87f46f1 (patch)
tree610128434e35b9b6028609d7cb5d67bcd13b3379 /flashimg/cpu_main/flash_static.c
parent1be02f3e2379b2cd06dbae775504948ff37bf89a (diff)
parentad2ef1642096665be998e83f9b6c4b7de308b644 (diff)
Merge branch 'lukeshu/flash-file'HEADmain
Diffstat (limited to 'flashimg/cpu_main/flash_static.c')
-rw-r--r--flashimg/cpu_main/flash_static.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/flashimg/cpu_main/flash_static.c b/flashimg/cpu_main/flash_static.c
new file mode 100644
index 0000000..4529ab2
--- /dev/null
+++ b/flashimg/cpu_main/flash_static.c
@@ -0,0 +1,128 @@
+/* flashimg/cpu_main/flash_static.c - Serve static files from flash over 9P
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <hardware/flash.h>
+
+#include <libmisc/assert.h>
+
+#include "flashio.h"
+
+#include "flash_static.h"
+
+LO_IMPLEMENTATION_C(lib9p_srv_file, struct flash_static_file, flash_static_file);
+LO_IMPLEMENTATION_STATIC(lib9p_srv_fio, struct flash_static_file, flash_static_fio);
+
+/******************************************************************************/
+
+#ifdef NDEBUG
+#define flash_static_assert(self) ((void)0)
+#else
+static void flash_static_assert(struct flash_static_file *self) {
+ assert(self);
+ assert(self->io);
+ assert(XIP_BASE <= (uintptr_t)self->data_start);
+ assert((uintptr_t)self->data_start <= (uintptr_t)self->data_end);
+ assert((uintptr_t)self->data_end <= XIP_BASE+PICO_FLASH_SIZE_BYTES);
+}
+#endif
+
+static inline size_t flash_static_size(struct flash_static_file *file) {
+ flash_static_assert(file);
+
+ return (size_t)((uintptr_t)file->data_end - (uintptr_t)file->data_start);
+}
+
+/******************************************************************************/
+
+void flash_static_file_free(struct flash_static_file *self) {
+ flash_static_assert(self);
+}
+struct lib9p_qid flash_static_file_qid(struct flash_static_file *self) {
+ flash_static_assert(self);
+
+ return (struct lib9p_qid){
+ .type = LIB9P_QT_FILE,
+ .vers = 1,
+ .path = self->c.pathnum,
+ };
+}
+error flash_static_file_stat(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat *out) {
+ flash_static_assert(self);
+ assert(ctx);
+ assert(out);
+
+ *out = ((struct lib9p_srv_stat){
+ .qid = flash_static_file_qid(self),
+ .mode = self->c.perm & 0444,
+ .atime_sec = self->c.atime,
+ .mtime_sec = self->c.mtime,
+ .size = (uint64_t)flash_static_size(self),
+ .name = lib9p_str(self->c.name),
+ .owner_uid = { .name = lib9p_str(self->c.u_name), .num = self->c.u_num },
+ .owner_gid = { .name = lib9p_str(self->c.g_name), .num = self->c.g_num },
+ .last_modifier_uid = { .name = lib9p_str(self->c.m_name), .num = self->c.m_num },
+ .extension = lib9p_str(NULL),
+ });
+ return ERROR_NULL;
+}
+error flash_static_file_wstat(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) {
+ flash_static_assert(self);
+ assert(ctx);
+
+ return error_new(E_POSIX_EROFS, "read-only part of filesystem");
+}
+error flash_static_file_remove(struct flash_static_file *self, struct lib9p_srv_ctx *ctx) {
+ flash_static_assert(self);
+ assert(ctx);
+
+ return error_new(E_POSIX_EROFS, "read-only part of filesystem");
+}
+
+LIB9P_SRV_NOTDIR(, struct flash_static_file, flash_static_file);
+
+lib9p_srv_fio_or_error flash_static_file_fopen(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, bool rd, bool wr, bool trunc) {
+ flash_static_assert(self);
+ assert(ctx);
+ assert(rd);
+ assert(!wr);
+ assert(!trunc);
+ return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, self));
+}
+
+/******************************************************************************/
+
+static struct lib9p_qid flash_static_fio_ioqid(struct flash_static_file *self) {
+ return flash_static_file_qid(self);
+}
+static void flash_static_fio_iofree(struct flash_static_file *self) {
+ flash_static_assert(self);
+}
+static uint32_t flash_static_fio_iounit(struct flash_static_file *self) {
+ flash_static_assert(self);
+ return 0;
+}
+static error flash_static_fio_pread(struct flash_static_file *self, struct lib9p_srv_ctx *ctx, lo_interface io_writer dst, uint64_t byte_offset, uint32_t byte_count) {
+ flash_static_assert(self);
+ assert(ctx);
+
+ size_t data_size = flash_static_size(self);
+ if (byte_offset > (uint64_t)data_size)
+ return error_new(E_POSIX_EINVAL, "offset is past end-of-file length");
+
+ if (byte_count > data_size - byte_offset)
+ byte_count = data_size - byte_offset;
+
+ return flashio_pread_to(self->io, dst, ((uintptr_t)self->data_start - XIP_BASE) + byte_offset, byte_count).err;
+}
+static uint32_t_or_error flash_static_fio_pwrite(struct flash_static_file *self, struct lib9p_srv_ctx *ctx,
+ const void *LM_UNUSED(buf),
+ uint32_t LM_UNUSED(byte_count),
+ uint64_t LM_UNUSED(byte_offset)) {
+ flash_static_assert(self);
+ assert(ctx);
+
+ return ERROR_NEW_ERR(uint32_t, error_new(E_POSIX_EROFS, "read-only part of filesystem"));
+}