diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-07-03 08:00:50 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-07-03 08:00:50 -0600 |
commit | 1d5a211e1ae3645e9c13163b76fea0a3c87f46f1 (patch) | |
tree | 610128434e35b9b6028609d7cb5d67bcd13b3379 /flashimg | |
parent | 1be02f3e2379b2cd06dbae775504948ff37bf89a (diff) | |
parent | ad2ef1642096665be998e83f9b6c4b7de308b644 (diff) |
Diffstat (limited to 'flashimg')
-rw-r--r-- | flashimg/cpu_main/CMakeLists.txt | 2 | ||||
-rw-r--r-- | flashimg/cpu_main/config/config.h | 1 | ||||
-rw-r--r-- | flashimg/cpu_main/flash_static.c | 128 | ||||
-rw-r--r-- | flashimg/cpu_main/flash_static.h | 21 | ||||
-rw-r--r-- | flashimg/cpu_main/flashio.c | 130 | ||||
-rw-r--r-- | flashimg/cpu_main/flashio.h | 29 | ||||
-rw-r--r-- | flashimg/cpu_main/fs_harness_flash_bin.c | 179 | ||||
-rw-r--r-- | flashimg/cpu_main/fs_harness_flash_bin.h | 16 | ||||
-rw-r--r-- | flashimg/cpu_main/main.c | 112 |
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); |