[PATCH u-boot-marvell 05/10] tools: kwboot: Fix sending and processing debug message pattern (-d option)

Stefan Roese sr at denx.de
Fri Mar 4 08:49:28 CET 2022


On 3/2/22 11:49, Pali Rohár wrote:
> -d option is currently broken. In most cases BootROM does not detect this
> message pattern. For sending debug message pattern it is needed to do same
> steps as for boot message pattern.
> 
> Implement sending debug message pattern via same separate thread like it is
> for boot message pattern.
> 
> Checking if BootROM entered into UART debug mode is different than
> detecting UART boot mode. When in boot mode, BootROM sends xmodem NAK
> bytes. When in debug mode, BootROM activates console echo and reply back
> every written byte (extept \r\n which is interpreted as executing command
> and \b which is interpreting as removing the last sent byte).
> 
> So in kwboot, check that BootROM send back at least 4 debug message
> patterns as a echo reply for debug message patterns which kwboot is sending
> in the loop.
> 
> Then there is another observation, if host writes too many bytes (as
> command) then BootROM command line buffer may overflow after trying to
> execute such long command. To workaround this overflow, it is enough to
> remove bytes from the input line buffer by sending 3 \b bytes for every
> sent character. So do it.
> 
> With this change, it is possbile to enter into the UART debug mode with
> kwboot -d option.
> 
> Signed-off-by: Pali Rohár <pali at kernel.org>

Reviewed-by: Stefan Roese <sr at denx.de>
Tested-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan

> ---
>   tools/kwboot.c | 139 +++++++++++++++++++++++++++++++++++++++++++------
>   1 file changed, 123 insertions(+), 16 deletions(-)
> 
> diff --git a/tools/kwboot.c b/tools/kwboot.c
> index 9fd90b9bec71..3ab49e74bb67 100644
> --- a/tools/kwboot.c
> +++ b/tools/kwboot.c
> @@ -881,30 +881,139 @@ kwboot_bootmsg(int tty)
>   static int
>   kwboot_debugmsg(int tty)
>   {
> -	int rc;
> +	unsigned char buf[8192];
> +	pthread_t write_thread;
> +	int rc, err, i, pos;
> +	size_t off;
>   
> -	kwboot_printv("Sending debug message. Please reboot the target...");
> +	/* flush input and output queue */
> +	tcflush(tty, TCIOFLUSH);
>   
> -	do {
> -		char buf[16];
> +	rc = kwboot_msg_start_thread(&write_thread, &tty, kwboot_msg_debug);
> +	if (rc) {
> +		perror("Failed to start write thread");
> +		return rc;
> +	}
>   
> -		rc = tcflush(tty, TCIOFLUSH);
> -		if (rc)
> -			break;
> +	kwboot_printv("Sending debug message. Please reboot the target...");
> +	kwboot_spinner();
>   
> -		rc = kwboot_tty_send(tty, kwboot_msg_debug, sizeof(kwboot_msg_debug), 0);
> -		if (rc)
> +	err = 0;
> +	off = 0;
> +	while (1) {
> +		/* Read immediately all bytes in queue without waiting */
> +		rc = read(tty, buf + off, sizeof(buf) - off);
> +		if ((rc < 0 && errno == EINTR) || rc == 0) {
> +			continue;
> +		} else if (rc < 0) {
> +			err = errno;
>   			break;
> -
> -		rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo);
> +		}
> +		off += rc - 1;
>   
>   		kwboot_spinner();
>   
> -	} while (rc);
> +		/*
> +		 * Check if we received at least 4 debug message patterns
> +		 * (console echo from BootROM) in cyclic buffer
> +		 */
> +
> +		for (pos = 0; pos < sizeof(kwboot_msg_debug); pos++)
> +			if (buf[off] == kwboot_msg_debug[(pos + off) % sizeof(kwboot_msg_debug)])
> +				break;
> +
> +		for (i = off; i >= 0; i--)
> +			if (buf[i] != kwboot_msg_debug[(pos + i) % sizeof(kwboot_msg_debug)])
> +				break;
> +
> +		off -= i;
> +
> +		if (off >= 4 * sizeof(kwboot_msg_debug))
> +			break;
> +
> +		/* If not move valid suffix from end of the buffer to the beginning of buffer */
> +		memmove(buf, buf + i + 1, off);
> +	}
>   
>   	kwboot_printv("\n");
>   
> -	return rc;
> +	rc = kwboot_msg_stop_thread(write_thread);
> +	if (rc) {
> +		perror("Failed to stop write thread");
> +		return rc;
> +	}
> +
> +	if (err) {
> +		errno = err;
> +		perror("Failed to read response for debug message pattern");
> +		return -1;
> +	}
> +
> +	/* flush output queue with remaining debug message patterns */
> +	rc = tcflush(tty, TCOFLUSH);
> +	if (rc) {
> +		perror("Failed to flush output queue");
> +		return rc;
> +	}
> +
> +	kwboot_printv("Clearing input buffer...\n");
> +
> +	/*
> +	 * Wait until BootROM transmit all remaining echo characters.
> +	 * Experimentally it was measured that for Armada 385 BootROM
> +	 * it is required to wait at least 0.415s. So wait 0.5s.
> +	 */
> +	usleep(500 * 1000);
> +
> +	/*
> +	 * In off variable is stored number of characters received after the
> +	 * successful detection of echo reply. So these characters are console
> +	 * echo for other following debug message patterns. BootROM may have in
> +	 * its output queue other echo characters which were being transmitting
> +	 * before above sleep call. So read remaining number of echo characters
> +	 * sent by the BootROM now.
> +	 */
> +	while ((rc = kwboot_tty_recv(tty, &buf[0], 1, 0)) == 0)
> +		off++;
> +	if (errno != ETIMEDOUT) {
> +		perror("Failed to read response");
> +		return rc;
> +	}
> +
> +	/*
> +	 * Clear every echo character set by the BootROM by backspace byte.
> +	 * This is required prior writing any command to the BootROM debug
> +	 * because BootROM command line buffer has limited size. If length
> +	 * of the command is larger than buffer size then it looks like
> +	 * that Armada 385 BootROM crashes after sending ENTER. So erase it.
> +	 * Experimentally it was measured that for Armada 385 BootROM it is
> +	 * required to send at least 3 backspace bytes for one echo character.
> +	 * This is unknown why. But lets do it.
> +	 */
> +	off *= 3;
> +	memset(buf, '\x08', sizeof(buf));
> +	while (off > sizeof(buf)) {
> +		rc = kwboot_tty_send(tty, buf, sizeof(buf), 1);
> +		if (rc) {
> +			perror("Failed to send clear sequence");
> +			return rc;
> +		}
> +		off -= sizeof(buf);
> +	}
> +	rc = kwboot_tty_send(tty, buf, off, 0);
> +	if (rc) {
> +		perror("Failed to send clear sequence");
> +		return rc;
> +	}
> +
> +	usleep(msg_rsp_timeo * 1000);
> +	rc = tcflush(tty, TCIFLUSH);
> +	if (rc) {
> +		perror("Failed to flush input queue");
> +		return rc;
> +	}
> +
> +	return 0;
>   }
>   
>   static size_t
> @@ -1951,10 +2060,8 @@ main(int argc, char **argv)
>   
>   	if (debugmsg) {
>   		rc = kwboot_debugmsg(tty);
> -		if (rc) {
> -			perror("debugmsg");
> +		if (rc)
>   			goto out;
> -		}
>   	} else if (bootmsg) {
>   		rc = kwboot_bootmsg(tty);
>   		if (rc)

Viele Grüße,
Stefan Roese

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list