From c4efb530cfad0bc0a970c2f5189216d47b889571 Mon Sep 17 00:00:00 2001
From: Piotr Dymacz <pepe2k@gmail.com>
Date: Sat, 17 Jun 2017 21:30:09 +0200
Subject: [PATCH] host_util: add helper script for U-Boot flashing over serial

This script helps with flashing U-Boot image over serial line (kermit
protocol, 'loadb' command) which can be useful on devices with only
serial interface available. Script requires C-Kermit and includes some
basic checks (start it without any argument to see short usage help).

Tested on C-Kermit 9.0.302

Example run:

$ host_util/u-boot-serial-flash bin/mr3020.bin - - - - -
[INFO]: File to send:  'bin/mr3020.bin'
[INFO]: Serial device: '/dev/ttyUSB0'
[INFO]: Baudrate:      '115200'
[INFO]: CLI prompt:    'u-boot> '
[INFO]: Wait string:   'Hit any key to stop booting'

[INFO]: File size:   '125952'
[INFO]: Backup size: '131072' (rounded up to 64K block)
[INFO]: Erase size:  '0x020000' (hex)

>>>>>>  Do you want to continue (type 'y' to continue)? y

[INFO]: Power on device now...
[INFO]: Backuping data in RAM...
[INFO]: Sending command: 'cp.b 0x9f000000 0x80800000 0x020000'
[INFO]: Sending command: 'loadb 0x80800000'
[INFO]: Sending selected file to RAM at 0x80800000 (this may take a while)...

>>>>>>  File sent successfully, do you want to write it to FLASH (type 'y' to continue)? y

[INFO]: Erasing FLASH, copying data from RAM to FLASH...
[INFO]: Sending command: 'erase 0x9f000000 +0x020000 && cp.b 0x80800000 0x9f000000 0x020000'
[ OK ]: Done!

>>>>>>  Reset board now or switch to U-Boot CLI (type 'y' for reset)? y

[INFO]: Resetting the board...
[INFO]: Sending command: 'reset'
[ OK ]: U-Boot flashed successfully!

>>>>>>  Exit now or switch to U-Boot CLI (type 'y' to exit)? y
---
 host_util/u-boot-serial-flash | 277 ++++++++++++++++++++++++++++++++++
 1 file changed, 277 insertions(+)
 create mode 100755 host_util/u-boot-serial-flash

diff --git a/host_util/u-boot-serial-flash b/host_util/u-boot-serial-flash
new file mode 100755
index 0000000..1f7db8b
--- /dev/null
+++ b/host_util/u-boot-serial-flash
@@ -0,0 +1,277 @@
+#!/usr/bin/kermit +
+
+# Disable input echo
+# (change this to 'on' for debug)
+set input echo off
+
+assign prog    "\fbasename(\%0)"
+assign dev     "/dev/ttyUSB0"
+assign brate   "115200"
+assign flaaddr "0x9f000000"
+assign ramaddr "0x80800000"
+assign waitstr "Hit any key to stop booting"
+assign stopstr " \10"
+assign prompt  "u-boot> "
+assign skipopt "(use '-' to skip and use default)"
+
+assign filesz  0
+assign bckpsz  0
+assign eraseszhex 0x0
+
+# =============
+# Custom macros
+# =============
+def usage {
+	echo "Usage:"
+	echo "  \m(prog) <file> [dev] [brate] [waitstr] [stopstr] [prompt]"
+	echo
+	echo "Arguments:"
+	echo "  file       image file to send (required)"
+	echo "  dev        serial device (optional, default: '\m(dev)')"
+	echo "  brate      baudrate (optional, default: '\m(brate)')"
+	echo "  waitstr    string to wait for before sending 'stopstr' (optional, default: '\m(waitstr)')"
+	echo "  stopstr    auto boot interrupt string (optional, default: '<SPACE><LF>')"
+	echo "             for special characters, use \\x, where x is ASCII code (e.g. for <ESC> use \\27)"
+	echo "  prompt     command line prompt string in U-Boot (optional, default: '\m(prompt)')"
+	echo
+	echo "Skip optional argument with '-', example:"
+	echo "  \m(prog) u-boot.bin - - - 'tpl' 'ar7240>'"
+	echo
+}
+
+def echo_err {
+	if defined \%1 echo "[ERRO]: \%1!"
+	exit 1
+}
+
+def echo_info {
+	if defined \%1 echo "[INFO]: \%1"
+}
+
+def echo_ok {
+	if defined \%1 echo "[ OK ]: \%1"
+}
+
+def askuser {
+	echo
+	ask \%m ">>>>>>  \%1 (type 'y' to continue)? "
+	if not defined \%m exit 0
+	else if not equal \%m "y" exit 0
+	echo
+}
+
+def argsummary {
+	echo_info "File to send:  '\m(file)'"
+	echo_info "Serial device: '\m(dev)'"
+	echo_info "Baudrate:      '\m(brate)'"
+	echo_info "CLI prompt:    '\m(prompt)'"
+	echo_info "Wait string:   '\m(waitstr)'"
+
+	echo
+
+	echo_info "File size:   '\m(filesz)'"
+	echo_info "Backup size: '\m(bckpsz)' (rounded up to 64K block)"
+	echo_info "Erase size:  '\m(eraseszhex)' (hex)"
+
+	askuser "Do you want to continue"
+}
+
+def waitpromt {
+	assign tout 3
+	if defined \%1 assign tout \%1
+
+	input \m(tout) "\m(prompt)"
+	if fail echo_err "Timeout occurred waiting for prompt string"
+}
+
+def interrupt {
+	input 15 "\m(waitstr)"
+	if fail echo_err "Timeout occurred waiting for wait string"
+
+	out "\m(stopstr)"
+	waitpromt
+}
+
+def cmdtest {
+	lineout "?"
+
+	input 2 "\fpattern(\%1*-*\10)"
+	if fail echo_err "Command '\%1' is not available"
+
+	waitpromt
+}
+
+def checkretval {
+	lineout "echo $?"
+
+	input 3 "\fpattern(0*\10)"
+	if fail echo_err "\%1"
+
+	waitpromt
+}
+
+def sendcmd {
+	echo_info "Sending command: '\%1'"
+	lineout "\%1"
+}
+
+# =====================
+# Execution begins here
+# =====================
+
+# We need 7 args
+if < \v(argc) 7 {
+	usage
+	exit 1
+}
+
+# File to send
+if not defined \%1 {
+	usage
+	echo_err "U-Boot image file not specified"
+}
+assign file \%1
+
+if not exist \m(file) {
+	usage
+	echo_err "Specified file: '\m(file)' does not exist"
+}
+
+assign filesz \fsize(\m(file))
+if fail {
+	usage
+	echo_err "Incorrect file specified: '\m(file)'"
+}
+
+assign i \Feval(\m(filesz) / 65536)
+assign bckpsz \Feval(\m(i) * 65536)
+
+if > \m(filesz) \m(bckpsz) {
+	assign i \Feval((\m(filesz) / 65536) + 1)
+	assign bckpsz \Feval(\m(i) * 65536)
+}
+
+assign eraseszhex "0x\fn2hex(\m(bckpsz))"
+if fail echo_err "Could not convert erase size to hex"
+
+# Serial device
+if not defined \%2 {
+	usage
+	echo_err "Serial device not specified \m(skipopt)"
+} else if not equal \%2 "-" assign dev \%2
+
+set line \m(dev)
+if fail {
+	usage
+	echo_err "Incorrect serial device specified: '\m(dev)'"
+}
+
+# Baudrate
+if not defined \%3 {
+	usage
+	echo_err "Baudrate not specified \m(skipopt)"
+} else if not equal \%3 "-" assign brate \%3
+
+set speed \m(brate)
+if fail {
+	usage
+	echo_err "Incorrect baudrate specified: '\m(brate)'"
+}
+
+# Wait for string
+if not defined \%4 {
+	usage
+	echo_err "Wait string not specified \m(skipopt)"
+} else if not equal \%4 "-" assign waitstr \%4
+
+# Stop string
+if not defined \%5 {
+	usage
+	echo_err "Stop string not specified \m(skipopt)"
+} else if not equal \%5 "-" assign stopstr \%5
+
+# CLI prompt
+if not defined \%6 {
+	usage
+	echo_err "U-Boot CLI prompt not specified \m(skipopt)"
+} else if not equal \%6 "-" assign prompt \%6
+
+argsummary
+
+# Default configuration
+robust
+set serial        8n1
+set file type     bin
+set carrier-watch off
+set prefixing     all
+set flow-control  none
+set handshake     none
+set modem         none
+
+set window 10
+set send packet-length 1000
+
+echo_info "Power on device now..."
+
+interrupt
+
+# Check if we have 'echo' and 'loadb' commands
+cmdtest "echo"
+cmdtest "loadb"
+
+# Backup existing image in RAM (round up to 64K block)
+echo_info "Backuping data in RAM..."
+sendcmd "cp.b \m(flaaddr) \m(ramaddr) \m(eraseszhex)"
+
+waitpromt 5
+checkretval "Could not backup data in RAM"
+
+# Start loadb
+sendcmd "loadb \m(ramaddr)"
+input 3 "\fpattern(Ready for binary*download*\10)"
+if fail echo_err "Timeout occurred waiting for binary download ready"
+
+# Send file to RAM
+echo_info "Sending selected file to RAM at \m(ramaddr) (this may take a while)..."
+send /quiet "\m(file)"
+
+if = \v(status) 1 echo_err "File send failed"
+
+waitpromt
+checkretval "File send failed"
+
+askuser "File sent successfully, do you want to write it to FLASH"
+
+# Erase flash and copy data from RAM to flash
+echo_info "Erasing FLASH, copying data from RAM to FLASH..."
+sendcmd "erase \m(flaaddr) +\m(eraseszhex) && cp.b \m(ramaddr) \m(flaaddr) \m(eraseszhex)"
+
+waitpromt 15
+checkretval "Erase/copy commands failed, do not reset the board"
+echo_ok "Done!"
+
+echo
+ask \%m ">>>>>>  Reset board now or switch to U-Boot CLI (type 'y' for reset)? "
+if not defined \%m {
+	connect
+	quit
+} else if not equal \%m "y" {
+	connect
+	quit
+} else {
+	echo
+	# Reset board and check if it's alive
+	echo_info "Resetting the board..."
+	sendcmd "reset"
+}
+
+interrupt
+echo_ok "U-Boot flashed successfully!"
+
+echo
+ask \%m ">>>>>>  Exit now or switch to U-Boot CLI (type 'y' to exit)? "
+if not defined \%m connect
+else if not equal \%m "y" connect
+else quit
+
+quit
-- 
2.25.1