[PATCH u-boot-marvell v2 11/39] tools: kwboot: Split sending image into header and data stages

Marek Behún marek.behun at nic.cz
Tue Sep 7 11:58:09 CEST 2021


From: Pali Rohár <pali at kernel.org>

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 at kernel.org>
[ refactored ]
Signed-off-by: Marek Behún <marek.behun at nic.cz>
---
 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 e063e3e41e..074bdfbe46 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
-- 
2.32.0



More information about the U-Boot mailing list