From 2ef87f75d16bcdc2a29e7339b8f2c2508985fe12 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pali=20Roh=C3=A1r?= Date: Fri, 24 Sep 2021 23:06:48 +0200 Subject: [PATCH] tools: kwboot: Split sending image into header and data stages MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This change is required to implement other features in kwboot. Split sending header and data parts of the image into two stages. Signed-off-by: Pali Rohár [ refactored ] Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- tools/kwbimage.h | 8 ++++-- tools/kwboot.c | 84 +++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 10e3254..73da950 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -195,6 +195,10 @@ struct register_set_hdr_v1 { #define OPT_HDR_V1_BINARY_TYPE 0x2 #define OPT_HDR_V1_REGISTER_TYPE 0x3 +#define KWBHEADER_V0_SIZE(hdr) \ + (((hdr)->ext & 0x1) ? sizeof(struct kwb_header) : \ + sizeof(struct main_hdr_v0)) + #define KWBHEADER_V1_SIZE(hdr) \ (((hdr)->headersz_msb << 16) | le16_to_cpu((hdr)->headersz_lsb)) @@ -225,9 +229,9 @@ void init_kwb_image_type (void); * header, byte 8 was reserved, and always set to 0. In the v1 header, * byte 8 has been changed to a proper field, set to 1. */ -static inline unsigned int image_version(void *header) +static inline unsigned int image_version(const void *header) { - unsigned char *ptr = header; + const unsigned char *ptr = header; return ptr[8]; } diff --git a/tools/kwboot.c b/tools/kwboot.c index 0e533e3..7f231c0 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -57,11 +57,13 @@ static unsigned char kwboot_msg_debug[] = { #define NAK 21 /* target block negative ack */ #define CAN 24 /* target/sender transfer cancellation */ +#define KWBOOT_XM_BLKSZ 128 /* xmodem block size */ + struct kwboot_block { uint8_t soh; uint8_t pnum; uint8_t _pnum; - uint8_t data[128]; + uint8_t data[KWBOOT_XM_BLKSZ]; uint8_t csum; } __packed; @@ -356,16 +358,15 @@ static size_t kwboot_xm_makeblock(struct kwboot_block *block, const void *data, size_t size, int pnum) { - const size_t blksz = sizeof(block->data); size_t i, n; block->soh = SOH; block->pnum = pnum; block->_pnum = ~block->pnum; - n = size < blksz ? size : blksz; + n = size < KWBOOT_XM_BLKSZ ? size : KWBOOT_XM_BLKSZ; memcpy(&block->data[0], data, n); - memset(&block->data[n], 0, blksz - n); + memset(&block->data[n], 0, KWBOOT_XM_BLKSZ - n); block->csum = 0; for (i = 0; i < n; i++) @@ -425,48 +426,73 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block) } static int -kwboot_xmodem(int tty, const void *_data, size_t size) +kwboot_xmodem_one(int tty, int *pnum, int header, const uint8_t *data, + size_t size) { - const uint8_t *data = _data; - int rc, pnum, N, err; - - pnum = 1; - N = 0; + size_t sent, left; + int rc; - kwboot_printv("Sending boot image...\n"); + kwboot_printv("Sending boot image %s (%zu bytes)...\n", + header ? "header" : "data", size); - sleep(2); /* flush isn't effective without it */ - tcflush(tty, TCIOFLUSH); + left = size; + sent = 0; - do { + while (sent < size) { struct kwboot_block block; - int n; + size_t blksz; - n = kwboot_xm_makeblock(&block, - data + N, size - N, - pnum++); - if (!n) - break; + blksz = kwboot_xm_makeblock(&block, data, left, (*pnum)++); + data += blksz; rc = kwboot_xm_sendblock(tty, &block); if (rc) goto out; - N += n; - kwboot_progress(N * 100 / size, '.'); - } while (1); + sent += blksz; + left -= blksz; + + kwboot_progress(sent * 100 / size, '.'); + } - rc = kwboot_tty_send_char(tty, EOT); + kwboot_printv("Done\n"); + return 0; out: kwboot_printv("\n"); return rc; +} -can: - err = errno; - kwboot_tty_send_char(tty, CAN); - errno = err; - goto out; +static int +kwboot_xmodem(int tty, const void *_img, size_t size) +{ + const uint8_t *img = _img; + int rc, pnum; + size_t hdrsz; + + if (image_version(img) == 0) + hdrsz = KWBHEADER_V0_SIZE((struct main_hdr_v0 *)img); + else + hdrsz = KWBHEADER_V1_SIZE((struct main_hdr_v1 *)img); + + kwboot_printv("Waiting 2s and flushing tty\n"); + sleep(2); /* flush isn't effective without it */ + tcflush(tty, TCIOFLUSH); + + pnum = 1; + + rc = kwboot_xmodem_one(tty, &pnum, 1, img, hdrsz); + if (rc) + return rc; + + img += hdrsz; + size -= hdrsz; + + rc = kwboot_xmodem_one(tty, &pnum, 0, img, size); + if (rc) + return rc; + + return kwboot_tty_send_char(tty, EOT); } static int -- 2.7.4