If we sent the boot message too often the CPU might already have started to interpret this as an xmodem packet. As sender and receiver are not in sync it's impossible to transfer a packet successfully. After inspecting the bootROM of an Armada XP machine (version 1.20) I found that on sending 0xff the CPU replies with a NAK when waiting for a packet and allows to start a new packet with the next byte. This can be used to resync sender and receiver. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> --- scripts/kwboot.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/scripts/kwboot.c b/scripts/kwboot.c index 9b0d1d0602a0..9d680dc576a7 100644 --- a/scripts/kwboot.c +++ b/scripts/kwboot.c @@ -349,6 +349,48 @@ kwboot_xm_makeblock(struct kwboot_block *block, const void *data, return n; } +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static int +kwboot_xm_resync(int fd) +{ + /* + * When the SoC has a different perception of where the package boundary + * is, just resending the packet doesn't help. To resync send 0xff until + * we get another NAK. + * The BootROM code (of the Armada XP at least) doesn't interpret 0xff + * as a start of a package and sends a NAK for each 0xff when waiting + * for SOH, so it's possible to send >1 byte without the SoC starting a + * new frame. + * When there is no response after sizeof(struct kwboot_block) bytes, + * there is another problem. + */ + int rc; + char buf[sizeof(struct kwboot_block)]; + unsigned interval = 1; + unsigned len; + char *p = buf; + + memset(buf, 0xff, sizeof(buf)); + + while (interval <= sizeof(buf)) { + len = min(interval, buf + sizeof(buf) - p); + rc = kwboot_tty_send(fd, p, len); + if (rc) + return rc; + + kwboot_tty_recv(fd, p, len, KWBOOT_BLK_RSP_TIMEO); + if (*p != 0xff) + /* got at least one char, if it's a NAK we're synced. */ + return (*p == NAK); + + p += len; + interval *= 2; + } + + return 0; +} + static int kwboot_xm_sendblock(int fd, struct kwboot_block *block) { @@ -371,7 +413,9 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block) } while (c != ACK && c != NAK && c != CAN); - if (c != ACK) + if (c == NAK && kwboot_xm_resync(fd)) + kwboot_progress(-1, 'S'); + else if (c != ACK) kwboot_progress(-1, '+'); } while (c == NAK && retries-- > 0); -- 2.9.3 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox