diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-06-12 02:32:54 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-06-12 02:32:54 -0600 |
commit | 0474953ab2600ee3b6bc17ba605b8e7877e181fe (patch) | |
tree | 5d3d4499d81d6a9f5422caf0694051272a1f6335 /cmd/sbc_harness/fs_harness_flash_bin.c | |
parent | 8ce568bae1cc9a77996f16b859482992d27e0b37 (diff) | |
parent | 43cacf95462588de0ab3125bdea7a37f10ebf8fc (diff) |
Merge branch 'lukeshu/better-net-flash'
Diffstat (limited to 'cmd/sbc_harness/fs_harness_flash_bin.c')
-rw-r--r-- | cmd/sbc_harness/fs_harness_flash_bin.c | 96 |
1 files changed, 43 insertions, 53 deletions
diff --git a/cmd/sbc_harness/fs_harness_flash_bin.c b/cmd/sbc_harness/fs_harness_flash_bin.c index 07675d1..6ae9e77 100644 --- a/cmd/sbc_harness/fs_harness_flash_bin.c +++ b/cmd/sbc_harness/fs_harness_flash_bin.c @@ -60,50 +60,24 @@ static_assert(DATA_HSIZE % FLASH_SECTOR_SIZE == 0); } /** - * Set the upper half of flash to all zero bytes. + * Set the upper half of flash to all "1" bits. * * @param buf : a scratch buffer that is at least FLASH_SECTOR_SIZE */ -static void ab_flash_initialize_zero(uint8_t *buf) { +static void ab_flash_initialize(void *buf) { assert(buf); - memset(buf, 0, FLASH_SECTOR_SIZE); + memset(buf, 0xFF, FLASH_SECTOR_SIZE); - log_infoln("zeroing upper flash..."); + 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(); - /* No need to `flash_range_erase()`; the way the flash - * works is that _erase() sets all bits to 1, and - * _program() sets some bits to 0. If we don't need - * any bits to be 1, then we can skip the - * _erase(). */ - flash_range_program(off, buf, FLASH_SECTOR_SIZE); - cr_restore_interrupts(saved); - } - log_debugln("... zeroed"); -} - -/** - * Copy the lower half of flash to the upper half of flash. - * - * @param buf : a scratch buffer that is at least FLASH_SECTOR_SIZE - */ -static void ab_flash_initialize(uint8_t *buf) { - assert(buf); - - log_infoln("initializing upper flash..."); - for (size_t off = 0; off < DATA_HSIZE; off += FLASH_SECTOR_SIZE) { - memcpy(buf, DATA_START+off, FLASH_SECTOR_SIZE); - if (memcmp(buf, DATA_START+DATA_HSIZE+off, FLASH_SECTOR_SIZE) == 0) - continue; - bool saved = cr_save_and_disable_interrupts(); - flash_range_erase(DATA_HSIZE+off, FLASH_SECTOR_SIZE); - flash_range_program(DATA_HSIZE+off, buf, FLASH_SECTOR_SIZE); + flash_range_erase(off, FLASH_SECTOR_SIZE); cr_restore_interrupts(saved); } - log_debugln("... initialized"); + log_debugln("... erased"); } /** @@ -210,7 +184,6 @@ static size_t_and_error flashio_pwritev(struct flashio *self, const struct iovec total_done += len; iov_done += len; offset += len; - self->written = true; } } return ERROR_AND(size_t, total_done, ERROR_NULL); @@ -219,11 +192,11 @@ static size_t_and_error flashio_pwritev(struct flashio *self, const struct iovec static error flashio_close(struct flashio *self) { assert(self); - if (self->wbuf.ok) - ab_flash_write_sector(self->wbuf.pos, self->wbuf.dat); - - if (self->written) + 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; } @@ -237,7 +210,7 @@ struct lib9p_qid flash_file_qid(struct flash_file *self) { assert(self); return (struct lib9p_qid){ - .type = LIB9P_QT_FILE|LIB9P_QT_EXCL, + .type = LIB9P_QT_FILE|LIB9P_QT_EXCL|LIB9P_QT_APPEND, .vers = 1, .path = self->pathnum, }; @@ -249,7 +222,7 @@ lib9p_srv_stat_or_error flash_file_stat(struct flash_file *self, struct lib9p_sr return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = flash_file_qid(self), - .mode = LIB9P_DM_EXCL|0666, + .mode = LIB9P_DM_EXCL|LIB9P_DM_APPEND|0666, .atime_sec = UTIL9P_ATIME, .mtime_sec = UTIL9P_MTIME, .size = DATA_SIZE, @@ -275,21 +248,24 @@ error flash_file_remove(struct flash_file *self, struct lib9p_srv_ctx *ctx) { LIB9P_SRV_NOTDIR(, struct flash_file, flash_file); +static error flash_handle_ihex_data(void *, uint32_t off, uint8_t count, uint8_t *dat); +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 trunc) { + bool LM_UNUSED(rd), bool wr, bool LM_UNUSED(trunc)) { assert(self); assert(ctx); memset(&self->io, 0, sizeof(self->io)); if (wr) { - if (trunc) { - ab_flash_initialize_zero(self->io.wbuf.dat); - self->io.written = true; - } else { - ab_flash_initialize(self->io.wbuf.dat); - } + ab_flash_initialize(self->io.wbuf.dat); } + memset(&self->ihex, 0, sizeof(self->ihex)); + self->ihex.handle_arg = self; + self->ihex.handle_data = flash_handle_ihex_data; + self->ihex.handle_eof = flash_handle_ihex_eof; + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, self)); } @@ -318,19 +294,33 @@ static error flash_file_pread(struct flash_file *self, struct lib9p_srv_ctx *ctx return flashio_pread_to(&self->io, dst, byte_offset, byte_count).err; } -/* TODO: Short/corrupt writes are dangerous. This should either (1) - * check a checksum, (2) use uf2 instead of verbatim data, or (3) use - * ihex instead of verbatim data. */ +static error flash_handle_ihex_data(void *_self, uint32_t off, uint8_t count, uint8_t *dat) { + struct flash_file *self = _self; + + if (off < XIP_BASE || off >= XIP_BASE + DATA_HSIZE) + 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, + &((struct iovec){.iov_base = dat, .iov_len = count}), 1, + off - XIP_BASE).err; +} +static error flash_handle_ihex_eof(void *_self) { + struct flash_file *self = _self; + self->io.finalize = true; + return ERROR_NULL; +} + +/* TODO: Also support uf2, not just ihex. */ static uint32_t_or_error flash_file_pwrite(struct flash_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, - uint64_t byte_offset) { + uint64_t LM_UNUSED(byte_offset)) { assert(self); assert(ctx); - size_t_and_error r = flashio_pwritev(&self->io, - &((struct iovec){.iov_base = buf, .iov_len = byte_count}), 1, - byte_offset); + size_t_and_error r = ihex_decoder_writev(&self->ihex, + &((struct iovec){.iov_base = buf, .iov_len = byte_count}), 1); if (r.size_t == 0 && !ERROR_IS_NULL(r.err)) return ERROR_NEW_ERR(uint32_t, r.err); return ERROR_NEW_VAL(uint32_t, (uint32_t) r.size_t); |