diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-04-19 20:10:05 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-06-12 02:46:38 -0600 |
commit | f71e032b6d32c0ac4f8ef5ea6e298aca89c59282 (patch) | |
tree | 66d149ad1f47a317c3359acbec1b4ec66adb7f87 /cmd | |
parent | 0474953ab2600ee3b6bc17ba605b8e7877e181fe (diff) |
wip uf2lukeshu/uf2
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/sbc_harness/CMakeLists.txt | 1 | ||||
-rw-r--r-- | cmd/sbc_harness/uf2.c | 82 | ||||
-rw-r--r-- | cmd/sbc_harness/uf2.h | 27 |
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_ */ |