summaryrefslogtreecommitdiff
path: root/flashimg
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
parent1be02f3e2379b2cd06dbae775504948ff37bf89a (diff)
parentad2ef1642096665be998e83f9b6c4b7de308b644 (diff)
Merge branch 'lukeshu/flash-file'HEADmain
Diffstat (limited to 'flashimg')
-rw-r--r--flashimg/cpu_main/CMakeLists.txt2
-rw-r--r--flashimg/cpu_main/config/config.h1
-rw-r--r--flashimg/cpu_main/flash_static.c128
-rw-r--r--flashimg/cpu_main/flash_static.h21
-rw-r--r--flashimg/cpu_main/flashio.c130
-rw-r--r--flashimg/cpu_main/flashio.h29
-rw-r--r--flashimg/cpu_main/fs_harness_flash_bin.c179
-rw-r--r--flashimg/cpu_main/fs_harness_flash_bin.h16
-rw-r--r--flashimg/cpu_main/main.c112
9 files changed, 409 insertions, 209 deletions
diff --git a/flashimg/cpu_main/CMakeLists.txt b/flashimg/cpu_main/CMakeLists.txt
index ba47e88..4bf70ab 100644
--- a/flashimg/cpu_main/CMakeLists.txt
+++ b/flashimg/cpu_main/CMakeLists.txt
@@ -15,6 +15,8 @@ add_library(cpu_main_objs OBJECT
fs_harness_flash_bin.c
fs_harness_uptime_txt.c
+ flash_static.c
+ flashio.c
ihex.c
)
target_include_directories(cpu_main_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config)
diff --git a/flashimg/cpu_main/config/config.h b/flashimg/cpu_main/config/config.h
index 700b77b..0c378c2 100644
--- a/flashimg/cpu_main/config/config.h
+++ b/flashimg/cpu_main/config/config.h
@@ -17,6 +17,7 @@
/* RP2040 *********************************************************************/
#define CONFIG_RP2040_SPI_DEBUG 1 /* bool */
+#define CONFIG_RP2040_SPI_MAX_DMABUF 64 /* non-negative integer */
/* W5500 **********************************************************************/
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"));
+}
diff --git a/flashimg/cpu_main/flash_static.h b/flashimg/cpu_main/flash_static.h
new file mode 100644
index 0000000..b2eeaa9
--- /dev/null
+++ b/flashimg/cpu_main/flash_static.h
@@ -0,0 +1,21 @@
+/* flashimg/cpu_main/flash_static.h - 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
+ */
+
+#ifndef _FLASHIMG_CPU_MAIN_FLASH_STATIC_H_
+#define _FLASHIMG_CPU_MAIN_FLASH_STATIC_H_
+
+#include <util9p/static.h>
+
+struct flash_static_file {
+ struct _util9p_static_common c;
+
+ struct flashio *io;
+ char *data_start; /* must not be NULL */
+ char *data_end; /* must not be NULL */
+};
+LO_IMPLEMENTATION_H(lib9p_srv_file, struct flash_static_file, flash_static_file);
+
+#endif /* _FLASHIMG_CPU_MAIN_FLASH_STATIC_H_ */
diff --git a/flashimg/cpu_main/flashio.c b/flashimg/cpu_main/flashio.c
new file mode 100644
index 0000000..1a082c1
--- /dev/null
+++ b/flashimg/cpu_main/flashio.c
@@ -0,0 +1,130 @@
+/* flashimg/cpu_main/flashio.c - DMA-safe flash storage
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <string.h>
+
+#include <libcr/coroutine.h>
+
+#define LOG_NAME FLASH
+#include <libmisc/log.h>
+
+#define IMPLEMENTATION_FOR_FLASHIO_H YES
+#include "flashio.h"
+
+LO_IMPLEMENTATION_C(io_preader_to, struct flashio, flashio);
+LO_IMPLEMENTATION_C(io_pwriter, struct flashio, flashio);
+LO_IMPLEMENTATION_C(io_flusher, struct flashio, flashio);
+
+#define DATA_START ((const char *)(XIP_NOALLOC_BASE))
+#define DATA_SIZE PICO_FLASH_SIZE_BYTES
+static_assert(DATA_SIZE % FLASH_SECTOR_SIZE == 0);
+
+/* There are some memcpy()s (and memcmp()s?) in here that maybe should
+ * be replaced with SSI DMA. */
+
+static void flashio_buffer_flush(struct flashio *self) {
+ if (!self->dat_dirty)
+ return;
+ self->dat_dirty = false;
+ if (memcmp(self->dat, DATA_START+self->dat_pos, FLASH_SECTOR_SIZE) == 0)
+ return;
+ log_infoln("write flash sector @ ", (base16_u32_, self->dat_pos), "...");
+ bool saved = cr_save_and_disable_interrupts();
+ flash_range_erase(self->dat_pos, FLASH_SECTOR_SIZE);
+ flash_range_program(self->dat_pos, self->dat, FLASH_SECTOR_SIZE);
+ cr_restore_interrupts(saved);
+ log_debugln("... written");
+}
+
+static void flashio_buffer_load(struct flashio *self, size_t sector_base, bool noinit) {
+ if (self->dat_ok && self->dat_pos == sector_base)
+ return;
+ flashio_buffer_flush(self);
+ self->dat_ok = true;
+ self->dat_pos = sector_base;
+ if (!noinit)
+ memcpy(self->dat, DATA_START+sector_base, FLASH_SECTOR_SIZE);
+}
+
+size_t_and_error flashio_pread_to(struct flashio *self, lo_interface io_writer dst, uoff_t _src_offset, size_t count) {
+ assert(self);
+ assert(!LO_IS_NULL(dst));
+
+ if (_src_offset > DATA_SIZE)
+ return ERROR_AND(size_t, 0, error_new(E_POSIX_EINVAL, "offset is past the chip size"));
+ size_t src_offset = (size_t) _src_offset;
+
+ if (src_offset == DATA_SIZE)
+ return ERROR_AND(size_t, 0, error_new(E_EOF));
+
+ /* Assume that somewhere down the line the pointer we pass to
+ * io_write() will be passed to DMA. We don't want the DMA
+ * engine to hit (slow) XIP (for instance, this can cause
+ * reads/writes to the SSP to get out of sync with eachother).
+ * So, copy the data to a buffer in (fast) RAM first. It's
+ * lame that the DMA engine can only have a DREQ on one side
+ * of the channel.
+ */
+ size_t sector_base = LM_ROUND_DOWN(src_offset, FLASH_SECTOR_SIZE);
+ if (src_offset + count > sector_base + FLASH_SECTOR_SIZE)
+ count = (sector_base + FLASH_SECTOR_SIZE) - src_offset;
+ assert(src_offset + count <= DATA_SIZE);
+
+ cr_mutex_lock(&self->mu);
+ flashio_buffer_load(self, sector_base, false);
+ size_t_and_error ret = io_write(dst, &self->dat[src_offset-sector_base], count);
+ cr_mutex_unlock(&self->mu);
+
+ return ret;
+}
+
+size_t_and_error flashio_pwritev(struct flashio *self, const struct wr_iovec *iov, int iovcnt, uoff_t _offset) {
+ assert(self);
+ assert(iov);
+ assert(iovcnt > 0);
+
+ size_t total_count = 0;
+ for (int i = 0; i < iovcnt; i++)
+ total_count += iov[i].iov_len;
+ assert(total_count > 0);
+
+ if (_offset >= DATA_SIZE)
+ return ERROR_AND(size_t, 0, error_new(E_POSIX_ENOSPC, "cannot write past the chip size"));
+ size_t offset = (size_t) _offset;
+
+ cr_mutex_lock(&self->mu);
+ size_t total_done = 0;
+ for (int i = 0; i < iovcnt; i++) {
+ for (size_t iov_done = 0; iov_done < iov[i].iov_len;) {
+ if (offset >= DATA_SIZE)
+ cr_mutex_unlock(&self->mu);
+ return ERROR_AND(size_t, total_done, error_new(E_POSIX_ENOSPC, "cannot write past the chip size"));
+ size_t sector_base = LM_ROUND_DOWN(offset, FLASH_SECTOR_SIZE);
+ size_t count = iov[i].iov_len - iov_done;
+ if (offset + count > sector_base + FLASH_SECTOR_SIZE)
+ count = (sector_base + FLASH_SECTOR_SIZE) - offset;
+ assert(offset + count <= DATA_SIZE);
+
+ flashio_buffer_load(self, sector_base, count != FLASH_SECTOR_SIZE);
+ memcpy(&self->dat[offset-sector_base], iov[i].iov_write_from+iov_done, count);
+ total_done += count;
+ iov_done += count;
+ offset += count;
+ }
+ }
+ cr_mutex_unlock(&self->mu);
+ return ERROR_AND(size_t, total_done, ERROR_NULL);
+}
+
+error flashio_flush(struct flashio *self) {
+ assert(self);
+
+ cr_mutex_lock(&self->mu);
+ flashio_buffer_flush(self);
+ cr_mutex_unlock(&self->mu);
+
+ return ERROR_NULL;
+}
diff --git a/flashimg/cpu_main/flashio.h b/flashimg/cpu_main/flashio.h
new file mode 100644
index 0000000..c109739
--- /dev/null
+++ b/flashimg/cpu_main/flashio.h
@@ -0,0 +1,29 @@
+/* flashimg/cpu_main/flashio.h - DMA-safe flash storage
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _FLASHIMG_CPU_MAIN_FLASHIO_H_
+#define _FLASHIMG_CPU_MAIN_FLASHIO_H_
+
+#include <hardware/flash.h> /* for FLASH_SECTOR_SIZE */
+
+#include <libcr_ipc/mutex.h>
+#include <libhw/generic/io.h>
+#include <libmisc/private.h>
+
+struct flashio {
+ BEGIN_PRIVATE(FLASHIO_H);
+ uint8_t dat[FLASH_SECTOR_SIZE];
+ size_t dat_pos;
+ bool dat_dirty;
+ bool dat_ok;
+ cr_mutex_t mu;
+ END_PRIVATE(FLASHIO_H);
+};
+LO_IMPLEMENTATION_H(io_preader_to, struct flashio, flashio);
+LO_IMPLEMENTATION_H(io_pwriter, struct flashio, flashio);
+LO_IMPLEMENTATION_H(io_flusher, struct flashio, flashio);
+
+#endif /* _FLASHIMG_CPU_MAIN_FLASHIO_H_ */
diff --git a/flashimg/cpu_main/fs_harness_flash_bin.c b/flashimg/cpu_main/fs_harness_flash_bin.c
index 7b41c86..0fa674a 100644
--- a/flashimg/cpu_main/fs_harness_flash_bin.c
+++ b/flashimg/cpu_main/fs_harness_flash_bin.c
@@ -14,7 +14,10 @@
#include <util9p/static.h>
-#define IMPLEMENTATION_FOR_FS_HARNESS_FLASH_BIN YES
+#define IMPLEMENTATION_FOR_FLASHIO_H YES /* so we can reuse the buffer */
+#include "flashio.h"
+
+#define IMPLEMENTATION_FOR_FS_HARNESS_FLASH_BIN_H YES
#include "fs_harness_flash_bin.h"
LO_IMPLEMENTATION_C(lib9p_srv_file, struct flash_file, flash_file);
@@ -64,15 +67,9 @@ static_assert(DATA_HSIZE % FLASH_SECTOR_SIZE == 0);
*
* @param buf : a scratch buffer that is at least FLASH_SECTOR_SIZE
*/
-static void ab_flash_initialize(void *buf) {
- assert(buf);
-
- memset(buf, 0xFF, FLASH_SECTOR_SIZE);
-
+static void ab_flash_initialize(void) {
log_infoln("erasing upper flash...");
for (size_t off = DATA_HSIZE; off < DATA_SIZE; off += FLASH_SECTOR_SIZE) {
- if (memcmp(buf, DATA_START+off, FLASH_SECTOR_SIZE) == 0)
- continue;
bool saved = cr_save_and_disable_interrupts();
flash_range_erase(off, FLASH_SECTOR_SIZE);
cr_restore_interrupts(saved);
@@ -80,134 +77,23 @@ static void ab_flash_initialize(void *buf) {
log_debugln("... erased");
}
-/**
- * Write `dat` to flash sector `pos`+(DATA_SIZE/2) (i.e. `pos` is a
- * sector in the lower half, but this function writes to the upper
- * half).
- *
- * @param pos : start-position of the sector to write to
- * @param dat : the FLASH_SECTOR_SIZE bytes to write
- */
-static void ab_flash_write_sector(size_t pos, uint8_t *dat) {
- assert(pos < DATA_HSIZE);
- assert(pos % FLASH_SECTOR_SIZE == 0);
- assert(dat);
-
- pos += DATA_HSIZE;
-
- log_infoln("write flash sector @ ", (base16_u32_, pos), "...");
- if (memcmp(dat, DATA_START+pos, FLASH_SECTOR_SIZE) != 0) {
- bool saved = cr_save_and_disable_interrupts();
- flash_range_erase(pos, FLASH_SECTOR_SIZE);
- flash_range_program(pos, dat, FLASH_SECTOR_SIZE);
- cr_restore_interrupts(saved);
- }
- log_debugln("... written");
-}
-
-/* io_preader_to, io_pwriter, io_closer ***************************************/
-
-LO_IMPLEMENTATION_STATIC(io_preader_to, struct flashio, flashio);
-LO_IMPLEMENTATION_STATIC(io_pwriter, struct flashio, flashio);
-LO_IMPLEMENTATION_STATIC(io_closer, struct flashio, flashio);
-
-/** read from anywhere on the chip */
-static size_t_and_error flashio_pread_to(struct flashio *self, lo_interface io_writer dst, uoff_t _src_offset, size_t count) {
- assert(self);
-
- if (_src_offset > DATA_SIZE)
- return ERROR_AND(size_t, 0, error_new(E_POSIX_EINVAL, "offset is past the chip size"));
- size_t src_offset = (size_t) _src_offset;
-
- if (src_offset == DATA_SIZE)
- return ERROR_AND(size_t, 0, error_new(E_EOF));
-
- /* Assume that somewhere down the line the pointer we pass to
- * io_write() will be passed to DMA. We don't want the DMA
- * engine to hit (slow) XIP (for instance, this can cause
- * reads/writes to the SSP to get out of sync with eachother).
- * So, copy the data to a buffer in (fast) RAM first. It's
- * lame that the DMA engine can only have a DREQ on one side
- * of the channel.
- */
- size_t sector_base = LM_ROUND_DOWN(src_offset, FLASH_SECTOR_SIZE);
- if (src_offset + count > sector_base + FLASH_SECTOR_SIZE)
- count = (sector_base + FLASH_SECTOR_SIZE) - src_offset;
- assert(src_offset + count <= DATA_SIZE);
-
- if (!self->rbuf.ok || self->rbuf.pos != sector_base) {
- self->rbuf.ok = true;
- self->rbuf.pos = sector_base;
- memcpy(self->rbuf.dat, DATA_START+sector_base, FLASH_SECTOR_SIZE);
- }
-
- return io_write(dst, &self->rbuf.dat[src_offset-sector_base], count);
-}
-
-/** takes offsets in the lower half, writes to the upper half */
-static size_t_and_error flashio_pwritev(struct flashio *self, const struct wr_iovec *iov, int iovcnt, uoff_t _offset) {
- assert(self);
- assert(iov);
- assert(iovcnt > 0);
-
- size_t total_count = 0;
- for (int i = 0; i < iovcnt; i++)
- total_count += iov[i].iov_len;
- assert(total_count > 0);
-
- if (_offset >= DATA_HSIZE)
- return ERROR_AND(size_t, 0, error_new(E_POSIX_ENOSPC, "cannot write past half the chip size"));
- size_t offset = (size_t) _offset;
-
- size_t total_done = 0;
- for (int i = 0; i < iovcnt; i++) {
- size_t iov_done = 0;
- while (iov_done < iov[i].iov_len) {
- if (offset >= DATA_HSIZE)
- return ERROR_AND(size_t, total_done, error_new(E_POSIX_ENOSPC, "cannot write past half the chip size"));
- size_t sector_base = LM_ROUND_DOWN(offset, FLASH_SECTOR_SIZE);
- size_t len = iov[i].iov_len - iov_done;
- if (offset + len > sector_base + FLASH_SECTOR_SIZE)
- len = (sector_base + FLASH_SECTOR_SIZE) - offset;
- assert(offset + len <= DATA_HSIZE);
-
- if (self->wbuf.ok && self->wbuf.pos != sector_base)
- ab_flash_write_sector(self->wbuf.pos, self->wbuf.dat);
- if (!self->wbuf.ok || self->wbuf.pos != sector_base) {
- self->wbuf.ok = true;
- self->wbuf.pos = sector_base;
- if (len != FLASH_SECTOR_SIZE)
- /* Don't bother with a read if we're just going to overwrite it. */
- memcpy(self->wbuf.dat, DATA_START+DATA_HSIZE+sector_base, FLASH_SECTOR_SIZE);
- }
- memcpy(&self->wbuf.dat[offset-sector_base], iov[i].iov_write_from+iov_done, len);
- total_done += len;
- iov_done += len;
- offset += len;
- }
- }
- return ERROR_AND(size_t, total_done, ERROR_NULL);
-}
+/* srv_file *******************************************************************/
-static error flashio_close(struct flashio *self) {
+#ifdef NDEBUG
+#define flash_file_assert(self) ((void)0)
+#else
+void flash_file_assert(struct flash_file *self) {
assert(self);
-
- if (self->finalize) {
- if (self->wbuf.ok)
- ab_flash_write_sector(self->wbuf.pos, self->wbuf.dat);
- ab_flash_finalize(self->wbuf.dat);
- }
-
- return ERROR_NULL;
+ assert(self->name);
+ assert(self->io);
}
-
-/* srv_file *******************************************************************/
+#endif
void flash_file_free(struct flash_file *self) {
- assert(self);
+ flash_file_assert(self);
}
struct lib9p_qid flash_file_qid(struct flash_file *self) {
- assert(self);
+ flash_file_assert(self);
return (struct lib9p_qid){
.type = LIB9P_QT_FILE|LIB9P_QT_EXCL|LIB9P_QT_APPEND,
@@ -217,7 +103,7 @@ struct lib9p_qid flash_file_qid(struct flash_file *self) {
}
error flash_file_stat(struct flash_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat *out) {
- assert(self);
+ flash_file_assert(self);
assert(ctx);
assert(out);
@@ -236,13 +122,13 @@ error flash_file_stat(struct flash_file *self, struct lib9p_srv_ctx *ctx, struct
return ERROR_NULL;
}
error flash_file_wstat(struct flash_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) {
- assert(self);
+ flash_file_assert(self);
assert(ctx);
return error_new(E_POSIX_EROFS, "read-only part of filesystem");
}
error flash_file_remove(struct flash_file *self, struct lib9p_srv_ctx *ctx) {
- assert(self);
+ flash_file_assert(self);
assert(ctx);
return error_new(E_POSIX_EROFS, "read-only part of filesystem");
@@ -255,13 +141,11 @@ static error flash_handle_ihex_eof(void *);
lib9p_srv_fio_or_error flash_file_fopen(struct flash_file *self, struct lib9p_srv_ctx *ctx,
bool LM_UNUSED(rd), bool wr, bool LM_UNUSED(trunc)) {
- assert(self);
+ flash_file_assert(self);
assert(ctx);
- memset(&self->io, 0, sizeof(self->io));
- if (wr) {
- ab_flash_initialize(self->io.wbuf.dat);
- }
+ if (wr)
+ ab_flash_initialize();
memset(&self->ihex, 0, sizeof(self->ihex));
self->ihex.handle_arg = self;
@@ -277,26 +161,29 @@ static struct lib9p_qid flash_file_ioqid(struct flash_file *self) {
return flash_file_qid(self);
}
static uint32_t flash_file_iounit(struct flash_file *self) {
- assert(self);
+ flash_file_assert(self);
return FLASH_SECTOR_SIZE;
}
static void flash_file_iofree(struct flash_file *self) {
- assert(self);
+ flash_file_assert(self);
- error err = flashio_close(&self->io);
+ error err = flashio_flush(self->io);
assert(ERROR_IS_NULL(err));
err = ihex_decoder_close(&self->ihex);
assert(ERROR_IS_NULL(err));
+
+ if (self->finalize)
+ ab_flash_finalize(self->io->dat);
}
static error flash_file_pread(struct flash_file *self, struct lib9p_srv_ctx *ctx,
lo_interface io_writer dst, uint64_t byte_offset, uint32_t byte_count) {
- assert(self);
+ flash_file_assert(self);
assert(ctx);
- return flashio_pread_to(&self->io, dst, byte_offset, byte_count).err;
+ return flashio_pread_to(self->io, dst, byte_offset, byte_count).err;
}
static error flash_handle_ihex_data(void *_self, uint32_t off, uint8_t count, uint8_t *dat) {
@@ -306,13 +193,13 @@ static error flash_handle_ihex_data(void *_self, uint32_t off, uint8_t count, ui
return error_new(E_POSIX_ENOSPC, "cannot write outside of the first half of the chip: ",
(base16_u32_, off), " is outside of [", (base16_u32_, XIP_BASE), ",", (base16_u32_, XIP_BASE + DATA_HSIZE), ")");
- return flashio_pwritev(&self->io,
+ return flashio_pwritev(self->io,
&((struct wr_iovec){.iov_write_from = dat, .iov_len = count}), 1,
- off - XIP_BASE).err;
+ off - XIP_BASE + DATA_HSIZE).err;
}
static error flash_handle_ihex_eof(void *_self) {
struct flash_file *self = _self;
- self->io.finalize = true;
+ self->finalize = true;
return ERROR_NULL;
}
@@ -321,7 +208,7 @@ static uint32_t_or_error flash_file_pwrite(struct flash_file *self, struct lib9p
const void *buf,
uint32_t byte_count,
uint64_t LM_UNUSED(byte_offset)) {
- assert(self);
+ flash_file_assert(self);
assert(ctx);
size_t_and_error r = ihex_decoder_writev(&self->ihex,
diff --git a/flashimg/cpu_main/fs_harness_flash_bin.h b/flashimg/cpu_main/fs_harness_flash_bin.h
index 68cc953..e5e1ef6 100644
--- a/flashimg/cpu_main/fs_harness_flash_bin.h
+++ b/flashimg/cpu_main/fs_harness_flash_bin.h
@@ -13,23 +13,15 @@
#include "ihex.h"
-struct flashio {
- bool finalize;
- struct {
- bool ok;
- size_t pos;
- uint8_t dat[FLASH_SECTOR_SIZE];
- } wbuf, rbuf;
-};
-
struct flash_file {
char *name;
uint64_t pathnum;
+ struct flashio *io;
- BEGIN_PRIVATE(FS_HARNESS_FLASH_BIN);
- struct flashio io;
+ BEGIN_PRIVATE(FS_HARNESS_FLASH_BIN_H);
struct ihex_decoder ihex;
- END_PRIVATE(FS_HARNESS_FLASH_BIN);
+ bool finalize;
+ END_PRIVATE(FS_HARNESS_FLASH_BIN_H);
};
LO_IMPLEMENTATION_H(lib9p_srv_file, struct flash_file, flash_file);
diff --git a/flashimg/cpu_main/main.c b/flashimg/cpu_main/main.c
index 812dbc1..af52cca 100644
--- a/flashimg/cpu_main/main.c
+++ b/flashimg/cpu_main/main.c
@@ -30,11 +30,13 @@
#include <libmisc/log.h>
/* local headers */
+#include "flashio.h"
#include "static.h"
#include "usb_keyboard.h"
/* 9P files */
#include <util9p/static.h>
+#include "flash_static.h"
#include "fs_harness_flash_bin.h"
#include <fs_harness_uptime_txt.h>
@@ -57,6 +59,13 @@ enum { PATH_BASE = __COUNTER__ };
#define STATIC_FILE(STRNAME, ...) UTIL9P_STATIC_FILE(PATH_COUNTER, STRNAME, __VA_ARGS__)
#define STATIC_DIR(STRNAME, ...) UTIL9P_STATIC_DIR(PATH_COUNTER, STRNAME, __VA_ARGS__)
+#define STATIC_FLASH_FILE(STRNAME, ...) \
+ lo_box_flash_static_file_as_lib9p_srv_file(&((struct flash_static_file){ \
+ .c = UTIL9P_STATIC_COMMON(PATH_COUNTER, STRNAME, 0444), \
+ .io = &flashio, \
+ __VA_ARGS__ \
+ }))
+
#define API_FILE(STRNAME, SYMNAME, ...) \
lo_box_##SYMNAME##_file_as_lib9p_srv_file(&((struct SYMNAME##_file){ \
.name = STRNAME, \
@@ -64,58 +73,59 @@ enum { PATH_BASE = __COUNTER__ };
__VA_OPT__(,) __VA_ARGS__ \
}))
+struct flashio flashio = {};
+
static struct lib9p_srv_file root =
- STATIC_DIR("",
- STATIC_DIR("Documentation",
- STATIC_FILE("YOUR_RIGHTS_AND_OBLIGATIONS.md",
- .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_md_start,
- .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_md_end),
- STATIC_DIR("YOUR_RIGHTS_AND_OBLIGATIONS",
- STATIC_FILE("agpl-3.0.txt",
- .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_agpl_3_0_txt_start,
- .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_agpl_3_0_txt_end),
- STATIC_FILE("dhcp.bsd3-mit.txt",
- .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_dhcp_bsd3_mit_txt_start,
- .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_dhcp_bsd3_mit_txt_end),
- STATIC_FILE("newlib.txt",
- .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_newlib_txt_start,
- .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_newlib_txt_end),
- STATIC_FILE("pico-sdk.bsd3.txt",
- .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_pico_sdk_bsd3_txt_start,
- .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_pico_sdk_bsd3_txt_end),
- STATIC_FILE("tinyusb.mit.txt",
- .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_tinyusb_mit_txt_start,
- .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_tinyusb_mit_txt_end),
- ),
- STATIC_FILE("harness_rom_bin.txt",
- .data_start = _binary_static_Documentation_harness_rom_bin_txt_start,
- .data_end = _binary_static_Documentation_harness_rom_bin_txt_end),
- STATIC_FILE("harness_flash_bin.txt",
- .data_start = _binary_static_Documentation_harness_flash_bin_txt_start,
- .data_end = _binary_static_Documentation_harness_flash_bin_txt_end),
- STATIC_FILE("harness_uptime_txt.txt",
- .data_start = _binary_static_Documentation_harness_uptime_txt_txt_start,
- .data_end = _binary_static_Documentation_harness_uptime_txt_txt_end),
- ),
- STATIC_DIR("harness",
- API_FILE("flash.bin",
- flash),
- STATIC_FILE("rom.bin",
- .data_start = (void*)0x00000000,
- .data_size = 16*1024),
- API_FILE("uptime.txt",
- uptime),
- // TODO: system.log
- // TODO: proc.txt
- // TODO: cpuinfo.txt
- // TODO: ctl
- ),
- STATIC_DIR("dut",
- // TODO: hdmi.nut
- // TODO: uart.txt
- // TODO: usb-keyboard.txt
- ),
- );
+ STATIC_DIR("",
+ STATIC_DIR("Documentation",
+ STATIC_FLASH_FILE("YOUR_RIGHTS_AND_OBLIGATIONS.md",
+ .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_md_start,
+ .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_md_end),
+ STATIC_DIR("YOUR_RIGHTS_AND_OBLIGATIONS",
+ STATIC_FLASH_FILE("agpl-3.0.txt",
+ .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_agpl_3_0_txt_start,
+ .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_agpl_3_0_txt_end),
+ STATIC_FLASH_FILE("dhcp.bsd3-mit.txt",
+ .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_dhcp_bsd3_mit_txt_start,
+ .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_dhcp_bsd3_mit_txt_end),
+ STATIC_FLASH_FILE("newlib.txt",
+ .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_newlib_txt_start,
+ .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_newlib_txt_end),
+ STATIC_FLASH_FILE("pico-sdk.bsd3.txt",
+ .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_pico_sdk_bsd3_txt_start,
+ .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_pico_sdk_bsd3_txt_end),
+ STATIC_FLASH_FILE("tinyusb.mit.txt",
+ .data_start = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_tinyusb_mit_txt_start,
+ .data_end = _binary_static_Documentation_YOUR_RIGHTS_AND_OBLIGATIONS_tinyusb_mit_txt_end),
+ ),
+ STATIC_FLASH_FILE("harness_rom_bin.txt",
+ .data_start = _binary_static_Documentation_harness_rom_bin_txt_start,
+ .data_end = _binary_static_Documentation_harness_rom_bin_txt_end),
+ STATIC_FLASH_FILE("harness_flash_bin.txt",
+ .data_start = _binary_static_Documentation_harness_flash_bin_txt_start,
+ .data_end = _binary_static_Documentation_harness_flash_bin_txt_end),
+ STATIC_FLASH_FILE("harness_uptime_txt.txt",
+ .data_start = _binary_static_Documentation_harness_uptime_txt_txt_start,
+ .data_end = _binary_static_Documentation_harness_uptime_txt_txt_end),
+ ),
+ STATIC_DIR("harness",
+ API_FILE("flash.bin", flash,
+ .io = &flashio),
+ STATIC_FILE("rom.bin",
+ .data_start = (void*)0x00000000,
+ .data_size = 16*1024),
+ API_FILE("uptime.txt", uptime),
+ // TODO: system.log
+ // TODO: proc.txt
+ // TODO: cpuinfo.txt
+ // TODO: ctl
+ ),
+ STATIC_DIR("dut",
+ // TODO: hdmi.nut
+ // TODO: uart.txt
+ // TODO: usb-keyboard.txt
+ ),
+ );
static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) {
return ERROR_NEW_VAL(lib9p_srv_file, root);