summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-19 20:10:05 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-06-12 02:46:38 -0600
commitf71e032b6d32c0ac4f8ef5ea6e298aca89c59282 (patch)
tree66d149ad1f47a317c3359acbec1b4ec66adb7f87 /cmd
parent0474953ab2600ee3b6bc17ba605b8e7877e181fe (diff)
Diffstat (limited to 'cmd')
-rw-r--r--cmd/sbc_harness/CMakeLists.txt1
-rw-r--r--cmd/sbc_harness/uf2.c82
-rw-r--r--cmd/sbc_harness/uf2.h27
3 files changed, 110 insertions, 0 deletions
diff --git a/cmd/sbc_harness/CMakeLists.txt b/cmd/sbc_harness/CMakeLists.txt
index 7656ab6..4cf39a6 100644
--- a/cmd/sbc_harness/CMakeLists.txt
+++ b/cmd/sbc_harness/CMakeLists.txt
@@ -16,6 +16,7 @@ add_library(sbc_harness_objs OBJECT
fs_harness_uptime_txt.c
ihex.c
+ uf2.c
)
target_include_directories(sbc_harness_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config)
target_include_directories(sbc_harness_objs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/cmd/sbc_harness/uf2.c b/cmd/sbc_harness/uf2.c
new file mode 100644
index 0000000..30b3694
--- /dev/null
+++ b/cmd/sbc_harness/uf2.c
@@ -0,0 +1,82 @@
+/* sbc_harness/uf2.h - Universal Flashing Format
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <string.h> /* for memcpy(), memcmp() */
+
+#include <libmisc/endian.h>
+
+#define IMPLEMENTATION_FOR_UF2_H YES
+#include "uf2.h"
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define UF2_FLAG_NOTMAIN 0x00000001
+#define UF2_FLAG_CONTAINER 0x00001000
+#define UF2_FLAG_FAMILYID 0x00002000
+#define UF2_FLAG_MD5SUM 0x00004000
+#define UF2_FLAG_EXTENSION 0x00008000
+
+static const uint8_t uf2_magic_beg[8] = { 'U', 'F', '2', '\n', 0x57, 0x51, 0x5D, 0x9E };
+static const uint8_t uf2_magic_end[4] = { 0x30, 0x6F, 0xB1, '\n' };
+
+static size_t_and_error uf2_decoder_write(struct uf2_decoder *self, const char *dat, size_t len_in) {
+ assert(self);
+ assert(ctx);
+ if (!len_in)
+ return ERROR_AND(size_t, 0, ERROR_NULL);
+ assert(dat);
+
+ if (self->seen_err)
+ return ERROR_AND(size_t, 0, error_new(E_POSIX_ESPIPE, "write after error"));
+
+ size_t len_consumed = 0;
+
+ while (len_consumed < len_in) {
+ size_t n = MIN(512 - self->len_dat, /* how much we're willing to take */
+ len_in - len_consumed); /* how much we're being offered */
+ memcpy(&self->dat[self->dat_len], &dat[len_consumed], n);
+ self->dat_len += n;
+ len_consumed += n;
+
+ if (self->dat_len != 512)
+ continue;
+
+ if (memcmp(&self->dat[0], uf2_magic_beg, 8)) {
+ self->seen_err = true;
+ return ERROR_AND(size_t, len_consumed, error_new(E_POSIX_EPROTO, "block does not begin with magic"));
+ }
+ if (memcmp(&self->dat[512-4], uf2_magic_end, 4)) {
+ self->seen_err = true;
+ return ERROR_AND(size_t, len_consumed, error_new(E_POSIX_EPROTO, "block does not end with magic"));
+ }
+ uint32_t flag = uint32le_decode(&self->dat[8]);
+ uint32_t addr = uint32le_decode(&self->dat[12]);
+ uint32_t size = uint32le_decode(&self->dat[16]);
+ uint32_t bnum = uint32le_decode(&self->dat[20]);
+ uint32_t bcnt = uint32le_decode(&self->dat[24]);
+ uint32_t famid = uint32le_decode(&self->dat[28]);
+ uint8_t *data = &self->dat[32];
+ // TODO
+ }
+
+ assert(len_consumed == len_in);
+ return ERROR_AND(size_t, len_in, ERROR_NULL);
+}
+
+size_t_and_error uf2_decoder_writev(struct uf2_decoder *self, const struct iovec *iov, int iovcnt) {
+ assert(self);
+ assert(iov);
+ assert(iovcnt);
+
+ size_t total = 0;
+ for (int i = 0; i < iovcnt; i++) {
+ size_t_and_error r = uf2_decoder_write(self, iov[i].iov_base, iov[i].iov_len);
+ total += r.size_t;
+ if (!ERROR_IS_NULL(r.err))
+ return ERROR_AND(size_t, total, r.err);
+ }
+ return ERROR_AND(size_t, total, ERROR_NULL);
+}
diff --git a/cmd/sbc_harness/uf2.h b/cmd/sbc_harness/uf2.h
new file mode 100644
index 0000000..bf9e032
--- /dev/null
+++ b/cmd/sbc_harness/uf2.h
@@ -0,0 +1,27 @@
+/* sbc_harness/uf2.h - Universal Flashing Format
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _SBC_HARNESS_FS_HARNESS_UF2_H_
+#define _SBC_HARNESS_FS_HARNESS_UF2_H_
+
+#include <stddef.h> /* for size_t */
+#include <stdint.h> /* for uint{n}_t */
+
+#include <libhw/generic/io.h>
+#include <libmisc/private.h>
+
+struct uf2_decoder {
+ BEGIN_PRIVATE(UF2_H);
+ bool seen_err;
+ size_t dat_len;
+ uint8_t dat[512];
+ uint32_t bnum;
+ uint32_t bcnt;
+ END_PRIVATE(UF2_H);
+};
+LO_IMPLEMENTATION_H(io_writer, struct uf2_decoder, uf2_decoder);
+
+#endif /* _SBC_HARNESS_FS_HARNESS_UF2_H_ */