summaryrefslogtreecommitdiff
path: root/cmd/sbc_harness/uf2.c
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/sbc_harness/uf2.c
parent0474953ab2600ee3b6bc17ba605b8e7877e181fe (diff)
Diffstat (limited to 'cmd/sbc_harness/uf2.c')
-rw-r--r--cmd/sbc_harness/uf2.c82
1 files changed, 82 insertions, 0 deletions
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);
+}