summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2021-09-25 00:06:48 +0300
committerStefan Roese <sr@denx.de>2021-10-01 12:07:13 +0300
commit2ef87f75d16bcdc2a29e7339b8f2c2508985fe12 (patch)
tree01fcfbd97cc28372efe214104b9f39cf18a20465 /tools
parentd5ba8dbd75c1b3f45c341341a1259114d894c45f (diff)
downloadu-boot-2ef87f75d16bcdc2a29e7339b8f2c2508985fe12.tar.xz
tools: kwboot: Split sending image into header and data stages
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 <pali@kernel.org> [ refactored ] Signed-off-by: Marek Behún <marek.behun@nic.cz> Reviewed-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'tools')
-rw-r--r--tools/kwbimage.h8
-rw-r--r--tools/kwboot.c84
2 files changed, 61 insertions, 31 deletions
diff --git a/tools/kwbimage.h b/tools/kwbimage.h
index 10e3254a58..73da950d86 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 0e533e3698..7f231c0823 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