summaryrefslogtreecommitdiff
path: root/cmd/sbc_harness/fs_harness_flash_bin.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-06-12 02:32:54 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-06-12 02:32:54 -0600
commit0474953ab2600ee3b6bc17ba605b8e7877e181fe (patch)
tree5d3d4499d81d6a9f5422caf0694051272a1f6335 /cmd/sbc_harness/fs_harness_flash_bin.c
parent8ce568bae1cc9a77996f16b859482992d27e0b37 (diff)
parent43cacf95462588de0ab3125bdea7a37f10ebf8fc (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.c96
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);