diff options
author | Milosz Wasilewski <milosz.wasilewski@linaro.org> | 2019-01-09 12:47:04 +0000 |
---|---|---|
committer | Milosz Wasilewski <milosz.wasilewski@linaro.org> | 2019-01-09 12:47:04 +0000 |
commit | 6426fde4a468f9b6c779e054575261465eaa3d16 (patch) | |
tree | 8010342a2145e36963bd5509101e3e6fa2565286 |
initial commit
Signed-off-by: Milosz Wasilewski <milosz.wasilewski@linaro.org>
-rw-r--r-- | README | 12 | ||||
-rwxr-xr-x | serial-boot.pl | 441 | ||||
-rwxr-xr-x | serial-download | 94 | ||||
-rwxr-xr-x | u-boot-recovery.sh | 184 | ||||
-rw-r--r-- | u-boot-recovery.yaml | 26 | ||||
-rw-r--r-- | u-boot-spl.bin | bin | 0 -> 79754 bytes | |||
-rwxr-xr-x | u-boot_fastboot.expect | 27 |
7 files changed, 784 insertions, 0 deletions
@@ -0,0 +1,12 @@ +Scripts for sending u-boot to TI boards over serial connection. + +Settings for GPEVM X15 board (AM57xx): + - J3: 1-2 closed + - J4: 1-2 closed + - J6: 1-2 closed + +In addition to the above settings, in order to prevent board +powering down, J5 has to be closed before powering board up. + +Serial cable has to be connected. When updating u-boot in eMMC +micro USB cable also has to be connected. diff --git a/serial-boot.pl b/serial-boot.pl new file mode 100755 index 0000000..97d34ce --- /dev/null +++ b/serial-boot.pl @@ -0,0 +1,441 @@ +#!/usr/bin/perl +##################################################################### +# serial-boot.pl +# +# OMAP Flashing Alternative perl script +# Serial module usage copied from http://ttime.no/dev.shtml +# +# Copyright (C) 2007 Texas Instruments, Inc. +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +# INSTALLATION NOTES: +# ------------------- +# WIN32: +# This package depends on Win32::SerialPort if using windows +# Download from http://www.bribes.org/perl/ppm/ +# PPD file and tgz to c:\perl, open a cmd and cd c:\perl +# run ppm install Win32-SerialPort.ppd +# +# Linux/Other OS: +# This package depends on Device::SerialPort if using any other OS. +# Download this using cpan -> cpan install Device::SerialPort +# +# The perl script by itself requires only r/w permission to serial port +# +# History +# ------- +# 0.01 2007-11-08 Nishanth Menon Created initial version +# 0.02 2013-08-07 Minal Shah Reading 69-bytes ASIC Id instead of 58-bytes +# Updated printing the ASIC Id in hex +# Changed name of this script file from +# omap_flash.pl to serial-boot.pl +##################################################################### +use strict; +use File::stat; +use Getopt::Std; +use IO::Handle; +use Time::HiRes qw(usleep); + +################# MAIN ############################################## +# get options +my %options = (); +getopt( "tpsd", \%options ); + +my $portId = "$options{p}"; +my $second_file = "$options{s}"; + +my $max_timeout = "$options{t}"; +my $debug = "$options{d}"; + +#portId should be number only.. +#if ( ( ( $portId == '' ) && ( "$portId" != "0" ) ) +# || ( "$portId" =~ /[^0-9]/ ) ) +#{ +# print "'$portId' port is invalid\n"; +# help_message(); +# exit(1); +#} + +#debug should be 0 or 1 +if ( ( "$debug" != '' ) && ( "$debug" != "0" ) && ( "$debug" != "1" ) ) { + print "'$debug' debug is invalid\n"; + help_message(); + exit(1); +} +if ( "$debug" == '' ) { + $debug = 0; +} +if ( ( "$max_timeout" =~ /[^0-9]/ ) ) { + print "'$portId' Timeout Period is invalid\n"; + help_message(); + exit(1); +} +if ( !$max_timeout ) { + $max_timeout = 30; +} + +if ( ( !$second_file ) || ( !file_size($second_file) ) ) { + print "MLO file '$second_file' is invalid\n"; + help_message(); + exit(1); +} + +#my $port = ( $^O eq 'MSWin32' ? "COM$portId" : "/dev/ttyS$portId" ); +my $port = $portId; + +STDOUT->autoflush(1); +my $chunk_count = 0; + +# open the port +my $handler = openPort($port, 'even') || die "could not open port $port:$!\n"; + +#################################################################### + +############ DOWNLOAD 2ND FILE ALONE CONNECT WITH CSST ############ + +##### FORMAT MY FILE SIZE +my $file_size = file_size($second_file); +my $file_bytes = pack( "L", $file_size ); +my $prefix_bytes = pack( "L", 0xF0030002 ); +my $string_bytes = "$prefix_bytes" . "$file_bytes"; +if (1) { +#$debug) { + print "BYTES=$file_size file_bytes=" + . unpack( "H*", $file_bytes ) + . " prefix_bytes=" + . unpack( "H*", $prefix_bytes ) + . " string bytes=" + . unpack( "H*", $string_bytes ) . "\n"; +} + +print "----Please reset the Board NOW (timeout=$max_timeout sec)----\n"; + +# Read the 69 bytes of ASIC ID +read_asicID( $handler, 69 ) + || die "Timedout while waiting for read asic id ($max_timeout sec)."; + +print "Board Detected\n"; + +#Send File Size +writePort( $handler, $string_bytes ) || die "Unable To send File Size"; + +# Send the file +send_file( $handler, $second_file ) || die "Could Not Send $second_file File"; + +print "\n$second_file file download completed\n"; + +#$debug = 1; +#read_text( $handler, 200 ); + +closePort($handler); + +my $handler = openPort($port, 'none') || die "could not open port $port:$!\n"; +read_text( $handler, 300 ) || die "\nUART boot message not found\n"; +print "\nUART Ymodem download has started on target\n"; +closePort($handler); + +exit(0); + +################################################################### +######## HELPERS ########### +################################################################### + +################################################################### +sub help_message() { +################################################################### + print "serial-boot.pl: Flashing Utility\n" + . "Syntax:\n" + . "serial-boot.pl -p <device> -s <second_file> [-d <dbg_lvl>] [-t <timeout>]\n" + . " port - Port ID as a device (i.e. /dev/ttyS0 || COM1)\n" + . " second_file - MLO File or the inital software\n" + . " dbg_lvl - Debug Level 0-silent, 1-verbose (optional)\n" + . " timeout - timeout period in seconds (optional)\n"; +} + +############## OMAP/FILE FUNCTIONS ############################### + +################################################################## +sub read_asicID() { +################################################################## + my ( $handler, $asic_id_length ) = @_; + my $char_count = 0; + my $timer = 0; + + my $string_in_hex; + + do { + my ( $count_in, $string_in ) = $handler->read(1); + $string_in_hex = unpack( "H*", $string_in ); + if ( $count_in > 0 ) { + $char_count++; + if ($debug) { + print "$string_in_hex\t"; + } + + # reset the timer + $timer = 0; + } + else { + $timer++; + + #r/w const timeout is in terms of 10 ms + return 0 if ( $timer > ( $max_timeout * 100 ) ); + } + } while ( $char_count < $asic_id_length ); + print "\n"; + return 1; +} + +################################################################## +sub read_text() { +################################################################## + my ( $handler, $asic_id_length ) = @_; + my $char_count = 0; + my $timer = 0; + my $pattern = 'Trying to boot from UART'; + my $pattern_idx = 0; + + my $string_in_hex; + + do { + my ( $count_in, $string_in ) = $handler->read(1); + $string_in_hex = unpack( "H*", $string_in ); + if ( $count_in > 0 ) { + $char_count++; + #print "$string_in_hex ($string_in)\t"; + print "$string_in"; + + if ( $string_in eq substr($pattern, $pattern_idx, 1) ) { + $pattern_idx++; + print "*"; + if ( $pattern_idx >= length($pattern) ) { + return 1; + } + } + else { + $pattern_idx = 0; + } + + # reset the timer + $timer = 0; + } + else { + $timer++; + + #r/w const timeout is in terms of 10 ms + return 0 if ( $timer > ( $max_timeout * 100 ) ); + } + } while ( $char_count < $asic_id_length ); + print "\n"; + return 0; +} + +################################################################## +sub file_size() { +################################################################## + my ($file) = @_; + my $FILE = stat("$file"); + if ( !$FILE ) { + return 0; + } + my $filesize = $FILE->size; + + return "$filesize"; +} + +################################################################## +sub send_file() { +################################################################## + my ( $handler, $file ) = @_; + my $buffer; + my $len; + my $total_len = 0; + my $chunk_size = 2048; + open FILE, "<$file" or die "can't open $file $!"; + binmode(FILE); + do { + $len = read( FILE, $buffer, $chunk_size ); + if ($len) { + my $ret = writePort( $handler, $buffer ); + if ( !$ret ) { + print "write port failed: $chunk_size $total_len $ret\n"; + return 0; + } + } + $total_len += $chunk_size; + } while ( $len != 0 ); + close(FILE); + return 1; +} + +############# SERIAL PORT FUNCTIONS ############################## + +################################################################## +sub openPort { +################################################################## + my ($port, $parity) = @_; + + my $quiet; + my $ob = undef; + if ( $^O eq 'MSWin32' ) { + require Win32::SerialPort; + Win32::SerialPort->import(); + $ob = Win32::SerialPort->new( "\\\\.\\$port", $quiet ); + } + else { + eval ' require Device::SerialPort; '; + if ( !$@ ) { + require Device::SerialPort; + Device::SerialPort->import(); + $ob = Device::SerialPort->new( "$port", $quiet ); + } + else { + print "Unable to find required Perl module Device::SerialPort\n"; + } + } + my $ok = 0; + + if ($ob) { + # OMAP PARAMETERS + my $omap_baud = 115200; + my $omap_partiy = $parity; + my $omap_data_bits = 8; + my $omap_stop_bits = 1; + my $omap_handshake = 'none'; + + #$ob->debug(0); + my @baud_opt = $ob->baudrate; + my @parity_opt = $ob->parity; + my @data_opt = $ob->databits; + my @stop_opt = $ob->stopbits; + my @hshake_opt = $ob->handshake; + + foreach $a (@baud_opt) { + if ( $a == $omap_baud ) { + $ok++; + last; + } + } + foreach $a (@parity_opt) { + if ( $a eq $omap_partiy ) { + $ok++; + last; + } + } + foreach $a (@data_opt) { + if ( $a == $omap_data_bits ) { + $ok++; + last; + } + } + foreach $a (@stop_opt) { + if ( $a == $omap_stop_bits ) { + $ok++; + last; + } + } + foreach $a (@hshake_opt) { + if ( $a eq $omap_handshake ) { + $ok++; + last; + } + } + $ok++ if ( $ob->is_rs232 ); + + $ob->baudrate($omap_baud); + $ob->parity($omap_partiy); + $ob->databits($omap_data_bits); + $ob->stopbits($omap_stop_bits); + $ob->handshake($omap_handshake); + $ob->buffers( 1024 * 10, 1024 * 30 ); + $ob->read_interval(0) if ( $^O eq 'MSWin32' ); + $ob->read_char_time(0); + $ob->read_const_time(10); + $ob->write_char_time(0) if ( $^O eq 'MSWin32' ); + $ob->write_const_time(0) if ( $^O eq 'MSWin32' ); + $ob->write_drain if ( $^O ne 'MSWin32' ); # drain if not win + $ok++ if ( $ob->write_settings ); + + $ob->close if ( $ok < 6 ); + } + undef $ob if ( $ok < 6 ); + return $ob; +} + +################################################################## +sub closePort { +################################################################## + my ($ob) = @_; + if ($ob) { + $ob->close; + undef $ob; + } +} + +################################################################## +sub readPort { +################################################################## + my ($ob) = @_; + return -1 unless ($ob); + my ( $count_in, $string_in ) = $ob->read(1); + return ( $count_in > 0 ? ord($string_in) : -1 ); +} +################################################################## +sub flush_read { +################################################################## + my ($port) = @_; + my $count_in; + my $string_in; + do { + ( $count_in, $string_in ) = $port->read(1); + } while ( $count_in != 0 ); +} +################################################################## +sub writePort { +################################################################## + my ( $ob, $wbuf ) = @_; + if ( !$ob ) { + print "invalid ob\n"; + return 0; + } + my $n = $ob->write("$wbuf"); + my $timer_count = 4000; # 4000 ms delay + my $done = 0; + my $count_out; + + $chunk_count++; + + print "."; #Show some life + # Wait to ensure that the data did flow out + # This is required for Linux esp since it does a background operation + do { + ( $done, $count_out ) = $ob->write_done(0); + if ($debug) { + print "?"; + } + $timer_count--; + if (!$done ) { + usleep(10000); + } + if ( !$timer_count ) { + print "\nTimedout waiting for draining"; + return 0; + } + } while ( !$done ); + if ($debug) { + my ( $done, $count_out ) = $ob->write_done(0); + print( "\n-->$chunk_count $n " . length($wbuf) . " $done $count_out\n" ); + print "write failed\n" unless ($n); + warn "write incomplete\n" if ( $n != length($wbuf) ); + } + return ( $n == length($wbuf) ); +} + +########### END OF FILE ######################################## diff --git a/serial-download b/serial-download new file mode 100755 index 0000000..c771b92 --- /dev/null +++ b/serial-download @@ -0,0 +1,94 @@ +#!/bin/bash + +MY_DIR=$(dirname $0) + +abort() { + echo "$@" + exit 2 +} + +if [ -z "$1" ]; then + echo "usage: $0 TTY [dir]" + echo "where:" + echo " TTY is serial device connected to the board (i.e. /dev/ttyUSB0" + echo " dir is the directory where the u-boot files come from" + echo " will look for dir/u-boot.img " + echo " and either dir/u-boot-spl.bin or dir/spl/u-boot-spl.bin" + echo " if dir is not specified the current directory is used" + echo "Additionally ROM_UART_BOOT env variable is used to decide which" + echo "method to use for sending u-boot-spl to the board. Available options:" + echo " asic_id_raw - suitable for AM57xx (default)" + echo " xmodem - suitable for AM335x" + exit 1 +fi + +DUT_TTY=$1 + +if [ -z "$ROM_UART_BOOT" ]; then + ROM_UART_BOOT=asic_id_raw +fi + +if [ -n "$2" ]; then + U_BOOT_DIR=$2 +else + U_BOOT_DIR=. +fi + +FILE2=$U_BOOT_DIR/u-boot.img + +if [ ! -f $FILE2 ]; then + echo "Can't find $FILE2" + exit 1 +fi + +FILE1=$U_BOOT_DIR/u-boot-spl.bin + +if [ ! -f $FILE1 ]; then + FILE1=$U_BOOT_DIR/spl/u-boot-spl.bin + if [ ! -f $FILE1 ]; then + echo "Can't find $FILE1" + exit 1 + fi +fi + +# SPL download for AM335x +spl_download_xmodem() { + stty -F $DUT_TTY 115200 cs8 -parenb -cstopb + sx $FILE1 <$DUT_TTY >$DUT_TTY || abort "SPL download failed" +} + +# SPL download for AM57x +spl_download_asic_id_raw() { + stty -F $DUT_TTY 115200 cs8 -parenb -cstopb + $MY_DIR/serial-boot.pl -p $DUT_TTY -d0 -t40 -s $FILE1 || abort "SPL download failed" +} + +# download u-boot image to SPL +uboot_download() { + sx -kb --ymodem $FILE2 <$DUT_TTY >$DUT_TTY || abort "U-boot download failed" +} + +# stop U-boot autoboot using expect +stop_auto_boot() { + { cat <<- EOF + send_user "waiting for U-boot autoboot prompt\n" + spawn -noecho -open [open $DUT_TTY w+] + expect "Hit any key" + send " \r" + send_user "\nstopped auto boot\n" + sleep 1 + send "\r" + sleep 0.1 + expect "=>" +EOF + } | expect - +} + +if [ x"$ROM_UART_BOOT" == x"asic_id_raw" ]; then + spl_download_asic_id_raw +else + spl_download_xmodem +fi + +uboot_download +stop_auto_boot diff --git a/u-boot-recovery.sh b/u-boot-recovery.sh new file mode 100755 index 0000000..2555897 --- /dev/null +++ b/u-boot-recovery.sh @@ -0,0 +1,184 @@ +#!/bin/sh + +set -u + +check_root() { + if [ "$(id -ru)" -eq 0 ]; then + return 0 + else + return 1 + fi +} + +error_fatal() { + # shellcheck disable=SC2039 + local msg="$1" + [ -z "${msg}" ] && msg="Unknown error" + if which lava-test-raise;then + lava-test-raise "${msg}" + else + printf "FATAL ERROR: %s\n" "${msg}" >&2 + fi + exit 1 +} + +error_msg() { + # shellcheck disable=SC2039 + local msg="$1" + [ -z "${msg}" ] && msg="Unknown error" + printf "ERROR: %s\n" "${msg}" >&2 + exit 1 +} + +info_msg() { + # shellcheck disable=SC2039 + local msg="$1" + [ -z "${msg}" ] && msg="Unknown info" + printf "INFO: %s\n" "${msg}" >&1 +} + +report_pass() { + [ "$#" -ne 1 ] && error_msg "Usage: report_pass test_case" + # shellcheck disable=SC2039 + local test_case="$1" + echo "${test_case} pass" | tee -a "${RESULT_FILE}" +} + +dist_name() { + if [ -f /etc/os-release ]; then + # shellcheck disable=SC1091 + dist=$(. /etc/os-release && echo "${ID}") + elif [ -x /usr/bin/lsb_release ]; then + dist="$(lsb_release -si)" + elif [ -f /etc/lsb-release ]; then + # shellcheck disable=SC1091 + dist="$(. /etc/lsb-release && echo "${DISTRIB_ID}")" + elif [ -f /etc/debian_version ]; then + dist="debian" + elif [ -f /etc/fedora-release ]; then + dist="fedora" + elif [ -f /etc/centos-release ]; then + dist="centos" + else + dist="unknown" + warn_msg "Unsupported distro: cannot determine distribution name" + fi + + # convert dist to lower case + dist=$(echo ${dist} | tr '[:upper:]' '[:lower:]') + case "${dist}" in + rpb*) dist="oe-rpb" ;; + esac +} + +install_deps() { + # shellcheck disable=SC2039 + local pkgs="$1" + [ -z "${pkgs}" ] && error_msg "Usage: install_deps pkgs" + # skip_install parmater is optional. + # shellcheck disable=SC2039 + local skip_install="${2:-false}" + + if [ "${skip_install}" = "True" ] || [ "${skip_install}" = "true" ]; then + info_msg "install_deps skipped" + else + ! check_root && \ + error_msg "About to install packages, please run this script as root." + info_msg "Installing ${pkgs}" + dist_name + case "${dist}" in + debian|ubuntu) + last_apt_time=/tmp/apt-get-updated.last + apt_cache_time=21600 # 6 hours + # Only run apt-get update if it hasn't been run in $apt_cache_time seconds + if [ ! -e ${last_apt_time} ] || \ + [ "$(stat --format=%Y ${last_apt_time})" -lt $(( $(date +%s) - apt_cache_time )) ]; then + DEBIAN_FRONTEND=noninteractive apt-get update -q -y && touch ${last_apt_time} + fi + # shellcheck disable=SC2086 + DEBIAN_FRONTEND=noninteractive apt-get install -q -y ${pkgs} + ;; + centos) + # shellcheck disable=SC2086 + yum -e 0 -y install ${pkgs} + ;; + fedora) + # shellcheck disable=SC2086 + dnf -e 0 -y install ${pkgs} + ;; + *) + warn_msg "Unsupported distro: ${dist}! Package installation skipped." + ;; + esac + # shellcheck disable=SC2181 + if [ $? -ne 0 ]; then + error_msg "Failed to install dependencies, exiting..." + fi + fi +} + +create_out_dir() { + [ -z "$1" ] && error_msg "Usage: create_out_dir output_dir" + # shellcheck disable=SC2039 + local OUTPUT=$1 + [ -d "${OUTPUT}" ] && + mv "${OUTPUT}" "${OUTPUT}_$(date -r "${OUTPUT}" +%Y%m%d%H%M%S)" + mkdir -p "${OUTPUT}" + [ -d "${OUTPUT}" ] || error_msg "Could not create output directory ${OUTPUT}" +} + +OUTPUT="$(pwd)/output" +RESULT_FILE="${OUTPUT}/result.txt" +export RESULT_FILE +IMAGE="aarch64/ubuntu" + +usage() { + echo "$0 [-d <directory with u-boot binaries>] [-u <u-boot.img>] [-m <MLO>]" 1>&2 + exit 1 +} + +while getopts "u:m:d:h" o; do + case "$o" in + u) UBOOT_IMAGE="${OPTARG}" ;; + m) MLO_IMAGE="${OPTARG}" ;; + d) UBOOT_DIR="${OPTARG}" ;; + h|*) usage ;; + esac +done + +! check_root && error_msg "You need to be root to run this script." +create_out_dir "${OUTPUT}" + +install() { + dist_name + # shellcheck disable=SC2154 + case "${dist}" in + debian|ubuntu) + install_deps lrzsz libdevice-serialport-perl expect fastboot + ;; + *) + warn_msg "No package installation support on ${dist}" + ;; + esac +} + +if [ ! -d "${UBOOT_DIR}" ]; then + error_fatal "${UBOOT_DIR} doesn't exist" +fi + +TTY=$(find /dev/ -xdev -name "ttyUSB*" -type c -print -quit) + +if [ "${UBOOT_DIR}" != "${PWD}" ]; then + cp "${UBOOT_DIR}/${UBOOT_IMAGE}" . +fi +./serial-download "${TTY}" || error_fatal "recovery failure" +report_pass "download_uboot_to_memory" +./u-boot_fastboot.expect "${TTY}" +report_pass "start_fastboot" +fastboot devices +fastboot oem format || error_fatal "oem format failed" +report_pass "format_emmc" +fastboot flash xloader "${UBOOT_DIR}/${MLO_IMAGE}" || error_fatal "xloader flash failed" +report_pass "flash_xloader" +fastboot flash bootloader "${UBOOT_DIR}/${MLO_IMAGE}" || error_fatal "bootloader flash failed" +report_pass "flash_bootloader" diff --git a/u-boot-recovery.yaml b/u-boot-recovery.yaml new file mode 100644 index 0000000..8ff1806 --- /dev/null +++ b/u-boot-recovery.yaml @@ -0,0 +1,26 @@ +metadata: + name: u-boot-recovery + format: "Lava-Test-Shell Test Definition 1.0" + description: "u-boot recovery for TI boards. u-boot is loaded + from serial device." + maintainer: + - milosz.wasilewski@linaro.org + os: + - debian + - ubuntu + scope: + - functional + environment: + - lava-test-shell + devices: + - x15-bl + +params: + # u-boot image + UBOOT_IMAGE: "/lava-lxc/u-boot.img" + UBOOT_MLO: "/lava-lxc/MLO" + +run: + steps: + - ./u-boot-recovery.sh -u "${UBOOT_IMAGE}" -m "${UBOOT_MLO}" -d "/lava-lxc/" + - ../../utils/send-to-lava.sh ./output/result.txt diff --git a/u-boot-spl.bin b/u-boot-spl.bin Binary files differnew file mode 100644 index 0000000..15c8873 --- /dev/null +++ b/u-boot-spl.bin diff --git a/u-boot_fastboot.expect b/u-boot_fastboot.expect new file mode 100755 index 0000000..141b7e4 --- /dev/null +++ b/u-boot_fastboot.expect @@ -0,0 +1,27 @@ +#!/usr/bin/expect +set tty [lindex $argv 0] +send_user "interact with u-boot, ctrl-C to exit\n" +spawn -open [open $tty w+] +send "\r" +sleep 0.1 +expect "=>" +sleep 0.1 +send "env default -f -a\r" +sleep 0.1 +expect "=>" +sleep 0.1 +send "setenv partitions \$partitions_android\r" +sleep 0.1 +expect "=>" +sleep 0.1 +send "env save\r" +sleep 0.1 +expect "=>" +sleep 0.1 +send "fastboot 1\r" +expect { + timeout { + puts "Fastboot Running..." + exit + } +} |