From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A5D84C433F5 for ; Wed, 2 Mar 2022 10:54:30 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 10DAC83C60; Wed, 2 Mar 2022 11:53:45 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="MQhCMieP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C013C83C6C; Wed, 2 Mar 2022 11:53:21 +0100 (CET) Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2F32683C99 for ; Wed, 2 Mar 2022 11:52:49 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=pali@kernel.org Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 770D661744; Wed, 2 Mar 2022 10:52:47 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89373C340EF; Wed, 2 Mar 2022 10:52:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1646218366; bh=D7Fz0FJhetRKGwz0oDpWEuFvlFsagbICIvslr8GDMMI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MQhCMiePHcrvN5uovD5aGLqNctVsQS3d3xcumGtLADyteTTJ8uzVBgoovfuq1ljBx vFdHxTq5VHeDwDGAm3FujXGyNsMjeqG/nKS0ARn4d+oghL8idb8x7RL/Oi+4Sawdkb ANuAdSl7HKcvFO69RAnnZHd6BfvBrOWdXeuCyKPgI1I2u4DW+kecA6BNT+9UGrZ1dT +gOiGHpMAEdfic4m1twLWJYVMpmSQCCf/VUH443g83LJxaVFlEQnsYp61iku7qPsFe 1iH4G049/HgsJzPisss4EIyHbofWpBfuRC9gFQyy6tS4BQe7FP5cbo4ptsWLTJiYpA JHEa+v8/0Pvbw== Received: by pali.im (Postfix) id 3F92A677; Wed, 2 Mar 2022 11:52:46 +0100 (CET) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Stefan Roese , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Tony Dinh Cc: u-boot@lists.denx.de Subject: [PATCH u-boot-marvell 05/10] tools: kwboot: Fix sending and processing debug message pattern (-d option) Date: Wed, 2 Mar 2022 11:49:22 +0100 Message-Id: <20220302104927.18607-6-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220302104927.18607-1-pali@kernel.org> References: <20220302104927.18607-1-pali@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean -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 --- 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) -- 2.20.1