summaryrefslogtreecommitdiff
path: root/util/brescue.sh
blob: 163f6ed6b8b0df9971dea88a9372db181d69539d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/bin/bash
# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# A script to facilitate rescue update of GSC targets, supports both Cr50 and
# Ti50.
#
# The two input parameters are the file name of the full binary mage (both ROs
# and both RWs) and the name of the UART device connected to the GSC console.
#
# The script carves out the RW_A from the binary, converts it into hex format
# and starts the rescue utility to send the RW to the chip. The user is
# supposed to reset the chip to trigger the rescue session.
#
# In invoked with nonempty NOCLEAN environment variable the script preserves
# the hex RW image it creates.

TMPD="$(mktemp -d "/tmp/$(basename "$0").XXXXX")"

RESCUE=
for r in rescue cr50-rescue; do
  if type "${r}" > /dev/null 2>&1; then
    RESCUE="${r}"
    break
  fi
done

if [[ -z ${RESCUE} ]]; then
  echo "rescue utility is not found, can not continue" >&2
  exit 1
fi
if [[ -z "${NOCLEAN}" ]]; then
  trap 'rm -rf "${TMPD}"' EXIT
fi

dest_hex="${TMPD}/rw.hex"
dest_bin="${TMPD}/rw.bin"
errorf="${TMPD}/error"

usage() {
  cat >&2 <<EOF
Two parameters are required, the name of the valid GSC binary image
and the name of the H1 console tty device
EOF
  exit 1
}

# Determine RW_A offset of the Ti50 image. The header magic pattern is used to
# find headers in the binary.
rw_offset() {
  local src
  local base

  src="$1"
  base=$(/usr/bin/od -Ax -t x1 -v "${src}" |
    grep -E '^....00 fd ff ff ff' |
    head -2 |
    tail -1 |
    sed 's/ .*//')
  printf '%d' "0x${base}"
}

if [[ $# != 2 ]]; then
  usage
fi

source="$1"
device="$2"

if [[ ! -f ${source} ]]; then
  usage
fi

if [[ ${device} != /dev/*  || ! -e ${device} ]]; then
  usage
fi

if [[ -n $(lsof "${device}" 2>/dev/null) ]]; then
  echo "${device} is in use, make sure it is available" >&2
  exit 1
fi

# Use Cr50 or Ti50 options base on the file size.
case "$(stat -c '%s' "${source}")" in
  (524288)
    skip=16384
    count=233472
    chip_extension=''
    addr=0x44000
    ;;
  (1048576)
    skip=$(rw_offset "${source}")
    count=$(( 1048576/2 - "${skip}" ))
    chip_extension='--dauntless'
    addr="$(printf '0x%x' $(( 0x80000 + "${skip}" )))"
    ;;
  (*)
    echo "Unrecognized input file" >&2
    exit 1
    ;;
esac

# Carve out RW_A in binary form.
if ! dd if="${source}" of="${dest_bin}" skip="${skip}" count="${count}" bs=1 \
  2>"${errorf}"; then
  echo "Failed to carve out the RW bin:" >&2
  cat "${errorf}" >&2
  exit 1
fi
echo "carved out binary ${dest_bin} mapped to ${addr}"

# Convert binary to hex.
if ! objcopy -I binary -O ihex --change-addresses "${addr}" \
  "${dest_bin}" "${dest_hex}"; then
  echo "Failed to convert to hex" >&2
  exit 1
fi
echo "converted to ${dest_hex}, waiting for target reset"

"${RESCUE}"  "${chip_extension}" -d "${device}" -v -i "${dest_hex}"