* [PATCH/RFT] scripts: kwboot: improve reliability on Armada XP
@ 2016-09-26 8:15 Uwe Kleine-König
2016-09-26 11:12 ` [PATCH v2] " Uwe Kleine-König
0 siblings, 1 reply; 2+ messages in thread
From: Uwe Kleine-König @ 2016-09-26 8:15 UTC (permalink / raw)
To: barebox; +Cc: Thomas Petazzoni, Kevin Smith, Stefan Roese
This introduces several changes that improve pushing a boot image via
UART to an Armada XP based machine (Netgear RN 2120 with BootROM 1.20).
They were found by inspecting the source, the actual communication and
disassembling the boot ROM.
The changes are:
- Don't use non-blocking open. This prevents trying to read the answer
from the SoC before the magic sequence was sent.
- Don't flush the input after each sending of the boot sequence as this
might discard the SoC's reply.
- A likely reason for a NAK is that sender and receiver are not synced
on xmodem packet boundary. This happens easily when the host sends to
many boot sequences. So on a NAK send 0xff to resync.
Unfortunately this doesn't make sending reliable yet. I can enter UART
boot mode, but it is aborted after several packets, which I failed to
debug up to now.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,
I have an Armada 370 based machine here, but didn't manage to test a
resync and also didn't find the bootrom yet to verify it supports that
0xff resync.
So testing and bootrom images welcome :-)
Best regards
Uwe
scripts/kwboot.c | 72 ++++++++++++++++++++++++++++++++++------
1 file changed, 62 insertions(+), 10 deletions(-)
diff --git a/scripts/kwboot.c b/scripts/kwboot.c
index 9b0d1d0602a0..1db4ab0faba1 100644
--- a/scripts/kwboot.c
+++ b/scripts/kwboot.c
@@ -35,7 +35,7 @@ static unsigned char kwboot_msg_debug[] = {
};
#define KWBOOT_MSG_REQ_DELAY 1000 /* ms */
-#define KWBOOT_MSG_RSP_TIMEO 1000 /* ms */
+#define KWBOOT_MSG_RSP_TIMEO 1 /* ms */
/*
* Xmodem Transfers
@@ -233,7 +233,7 @@ kwboot_open_tty(const char *path, speed_t speed)
rc = -1;
- fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY);
+ fd = open(path, O_RDWR | O_NOCTTY);
if (fd < 0)
goto out;
@@ -273,11 +273,11 @@ kwboot_bootmsg(int tty, void *msg)
else
kwboot_printv("Sending boot message. Please reboot the target...");
- do {
- rc = tcflush(tty, TCIOFLUSH);
- if (rc)
- break;
+ rc = tcflush(tty, TCIOFLUSH);
+ if (rc)
+ return rc;
+ do {
rc = kwboot_tty_send(tty, msg, 8);
if (rc) {
usleep(KWBOOT_MSG_REQ_DELAY * 1000);
@@ -285,12 +285,20 @@ kwboot_bootmsg(int tty, void *msg)
}
rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO);
-
- kwboot_spinner();
+ while (!rc && c != NAK) {
+ if (c == '\\')
+ kwboot_printv("\\\\", c);
+ else if (isprint(c))
+ kwboot_printv("%c", c);
+ else
+ kwboot_printv("\\x%02hhx", c);
+
+ rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO);
+ }
} while (rc || c != NAK);
- kwboot_printv("\n");
+ kwboot_printv("\nGot expected NAK\n");
return rc;
}
@@ -349,6 +357,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 +421,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@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH v2] scripts: kwboot: improve reliability on Armada XP
2016-09-26 8:15 [PATCH/RFT] scripts: kwboot: improve reliability on Armada XP Uwe Kleine-König
@ 2016-09-26 11:12 ` Uwe Kleine-König
0 siblings, 0 replies; 2+ messages in thread
From: Uwe Kleine-König @ 2016-09-26 11:12 UTC (permalink / raw)
To: barebox; +Cc: Thomas Petazzoni, Kevin Smith, Stefan Roese
This introduces several changes that improve pushing a boot image via
UART to an Armada XP based machine (Netgear RN 2120 with BootROM 1.20).
They were found by inspecting the source, the actual communication and
disassembling the boot ROM.
The changes are:
- Don't use non-blocking open. This prevents trying to read the answer
from the SoC before the magic sequence was sent.
- Don't flush the input after each sending of the boot sequence as this
might discard the SoC's reply.
- A likely reason for a NAK is that sender and receiver are not synced
on xmodem packet boundary. This happens easily when the host sends to
many boot sequences. So on a NAK send 0xff to resync.
- Shorten the time between two tries to send the magic string.
This greatly improves the probabilty the string is sent while the SoC
listens for it. This only works because of the previous changes.
Unfortunately this doesn't make sending reliable yet. I can enter UART
boot mode, but it is aborted after several packets, which I failed to
debug up to now.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Changes since (implict) v1 sent with
Message-Id: 20160926081543.16088-1-u.kleine-koenig@pengutronix.de
- mention that KWBOOT_MSG_RSP_TIMEO was made smaller
- fix build warning about isprint()
Testing is still welcome of course.
scripts/kwboot.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 63 insertions(+), 10 deletions(-)
diff --git a/scripts/kwboot.c b/scripts/kwboot.c
index 9b0d1d0602a0..943e800fd928 100644
--- a/scripts/kwboot.c
+++ b/scripts/kwboot.c
@@ -9,6 +9,7 @@
* 2008. Chapter 24.2 "BootROM Firmware".
*/
+#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -35,7 +36,7 @@ static unsigned char kwboot_msg_debug[] = {
};
#define KWBOOT_MSG_REQ_DELAY 1000 /* ms */
-#define KWBOOT_MSG_RSP_TIMEO 1000 /* ms */
+#define KWBOOT_MSG_RSP_TIMEO 1 /* ms */
/*
* Xmodem Transfers
@@ -233,7 +234,7 @@ kwboot_open_tty(const char *path, speed_t speed)
rc = -1;
- fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY);
+ fd = open(path, O_RDWR | O_NOCTTY);
if (fd < 0)
goto out;
@@ -273,11 +274,11 @@ kwboot_bootmsg(int tty, void *msg)
else
kwboot_printv("Sending boot message. Please reboot the target...");
- do {
- rc = tcflush(tty, TCIOFLUSH);
- if (rc)
- break;
+ rc = tcflush(tty, TCIOFLUSH);
+ if (rc)
+ return rc;
+ do {
rc = kwboot_tty_send(tty, msg, 8);
if (rc) {
usleep(KWBOOT_MSG_REQ_DELAY * 1000);
@@ -285,12 +286,20 @@ kwboot_bootmsg(int tty, void *msg)
}
rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO);
-
- kwboot_spinner();
+ while (!rc && c != NAK) {
+ if (c == '\\')
+ kwboot_printv("\\\\", c);
+ else if (isprint(c))
+ kwboot_printv("%c", c);
+ else
+ kwboot_printv("\\x%02hhx", c);
+
+ rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO);
+ }
} while (rc || c != NAK);
- kwboot_printv("\n");
+ kwboot_printv("\nGot expected NAK\n");
return rc;
}
@@ -349,6 +358,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 +422,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@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-09-26 11:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-26 8:15 [PATCH/RFT] scripts: kwboot: improve reliability on Armada XP Uwe Kleine-König
2016-09-26 11:12 ` [PATCH v2] " Uwe Kleine-König
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox