xref: /aosp_15_r20/external/gsc-utils/util/re-sign-gsc.sh (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1*4f2df630SAndroid Build Coastguard Worker#!/bin/bash
2*4f2df630SAndroid Build Coastguard Worker# Copyright 2023 The ChromiumOS Authors
3*4f2df630SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*4f2df630SAndroid Build Coastguard Worker# found in the LICENSE file.
5*4f2df630SAndroid Build Coastguard Worker
6*4f2df630SAndroid Build Coastguard Worker# This script allows to quickly re-sign a GSC image to a different set of
7*4f2df630SAndroid Build Coastguard Worker# Device IDs. The script works with both Cr50 and Ti50, it must be run in the
8*4f2df630SAndroid Build Coastguard Worker# appropriate top level directory, and the respective GSC binary has to be
9*4f2df630SAndroid Build Coastguard Worker# present in the respective ./build directory.
10*4f2df630SAndroid Build Coastguard Worker#
11*4f2df630SAndroid Build Coastguard Worker# Two command line parameters are required, the device IDs of the GSC.
12*4f2df630SAndroid Build Coastguard Worker#
13*4f2df630SAndroid Build Coastguard Worker# The generated binary is saved in {cr,ti}50.<sha>.<devid0>.<devid1>.bin where
14*4f2df630SAndroid Build Coastguard Worker# <sha> is the git sha of the current source tree. The suffix '-dirty' is
15*4f2df630SAndroid Build Coastguard Worker# added to the <sha> component in case there are changes in any of the files
16*4f2df630SAndroid Build Coastguard Worker# under git control.
17*4f2df630SAndroid Build Coastguard Worker
18*4f2df630SAndroid Build Coastguard Workerset -ue
19*4f2df630SAndroid Build Coastguard Worker
20*4f2df630SAndroid Build Coastguard WorkerSCRIPT_NAME="$(basename "$0")"
21*4f2df630SAndroid Build Coastguard WorkerTMPD="$(mktemp -d "/tmp/${SCRIPT_NAME}.XXXXX")"
22*4f2df630SAndroid Build Coastguard WorkerNOCLEAN="${NOCLEAN:-}"
23*4f2df630SAndroid Build Coastguard Workerif [[ -z ${NOCLEAN} ]]; then
24*4f2df630SAndroid Build Coastguard Worker  trap 'rm -rf "${TMPD}"' EXIT
25*4f2df630SAndroid Build Coastguard Workerfi
26*4f2df630SAndroid Build Coastguard Worker
27*4f2df630SAndroid Build Coastguard Worker# Make sure there is a codesigner in the path.
28*4f2df630SAndroid Build Coastguard WorkerCODESIGNER=""
29*4f2df630SAndroid Build Coastguard Workerfor f in  cr50-codesigner \
30*4f2df630SAndroid Build Coastguard Worker            ../../cr50-utils/software/tools/codesigner/codesigner \
31*4f2df630SAndroid Build Coastguard Worker            codesigner; do
32*4f2df630SAndroid Build Coastguard Worker  if command -v "${f}" > /dev/null 2>&1; then
33*4f2df630SAndroid Build Coastguard Worker    CODESIGNER="${f}"
34*4f2df630SAndroid Build Coastguard Worker    break
35*4f2df630SAndroid Build Coastguard Worker  fi
36*4f2df630SAndroid Build Coastguard Workerdone
37*4f2df630SAndroid Build Coastguard Workerif [[ -z ${CODESIGNER} ]]; then
38*4f2df630SAndroid Build Coastguard Worker  echo "SCRIPT_NAME error: can't find codesigner" >&2
39*4f2df630SAndroid Build Coastguard Worker  exit 1
40*4f2df630SAndroid Build Coastguard Workerfi
41*4f2df630SAndroid Build Coastguard Worker
42*4f2df630SAndroid Build Coastguard Worker# Re-sign a single RW section.
43*4f2df630SAndroid Build Coastguard Workerre_sign_rw() {
44*4f2df630SAndroid Build Coastguard Worker  local tmp_file="$1"
45*4f2df630SAndroid Build Coastguard Worker  local flash_base="$2"
46*4f2df630SAndroid Build Coastguard Worker  local rw_base="$3"
47*4f2df630SAndroid Build Coastguard Worker  local codesigner_params
48*4f2df630SAndroid Build Coastguard Worker  local rw_size
49*4f2df630SAndroid Build Coastguard Worker  local rw_bin_base
50*4f2df630SAndroid Build Coastguard Worker  local rw_bin_size
51*4f2df630SAndroid Build Coastguard Worker  local skip
52*4f2df630SAndroid Build Coastguard Worker
53*4f2df630SAndroid Build Coastguard Worker  codesigner_params=()
54*4f2df630SAndroid Build Coastguard Worker
55*4f2df630SAndroid Build Coastguard Worker  # Retrieve the rest of the codesigner command line arguments, which are this
56*4f2df630SAndroid Build Coastguard Worker  # function's arguments after the three fixed ones.
57*4f2df630SAndroid Build Coastguard Worker  shift 3
58*4f2df630SAndroid Build Coastguard Worker  while [[ $# != 0 ]]; do
59*4f2df630SAndroid Build Coastguard Worker    codesigner_params+=( "$1" )
60*4f2df630SAndroid Build Coastguard Worker    shift
61*4f2df630SAndroid Build Coastguard Worker  done
62*4f2df630SAndroid Build Coastguard Worker
63*4f2df630SAndroid Build Coastguard Worker  # Determine RW size. It is 4 bytes at offset 808 into the signed header.
64*4f2df630SAndroid Build Coastguard Worker  skip=$(( rw_base + 808 ))
65*4f2df630SAndroid Build Coastguard Worker  rw_size="$(hexdump -s "${skip}" -n4 -e '1/4 "%d"' "${tmp_file}")"
66*4f2df630SAndroid Build Coastguard Worker
67*4f2df630SAndroid Build Coastguard Worker  # Extract the RW section to re-sign, dropping the existing header.
68*4f2df630SAndroid Build Coastguard Worker  rw_bin_base=$(( rw_base + 1024  ))
69*4f2df630SAndroid Build Coastguard Worker  rw_bin_size=$(( rw_size - 1024 ))
70*4f2df630SAndroid Build Coastguard Worker  dd if="${full_bin}" of="${TMPD}/rw.bin" skip="${rw_bin_base}" bs=1 \
71*4f2df630SAndroid Build Coastguard Worker     count="${rw_bin_size}" status="none"
72*4f2df630SAndroid Build Coastguard Worker
73*4f2df630SAndroid Build Coastguard Worker  # Convert it to hex for signing
74*4f2df630SAndroid Build Coastguard Worker  objcopy -I binary -O ihex --change-addresses $(( rw_bin_base + flash_base )) \
75*4f2df630SAndroid Build Coastguard Worker          "${TMPD}/rw.bin" "${TMPD}/rw.hex"
76*4f2df630SAndroid Build Coastguard Worker
77*4f2df630SAndroid Build Coastguard Worker  # Sign.
78*4f2df630SAndroid Build Coastguard Worker  "${CODESIGNER}" "${codesigner_params[@]}" --input="${TMPD}/rw.hex" \
79*4f2df630SAndroid Build Coastguard Worker                  --output="${TMPD}/rw.signed"
80*4f2df630SAndroid Build Coastguard Worker
81*4f2df630SAndroid Build Coastguard Worker  # Paste the result back into the original binary.
82*4f2df630SAndroid Build Coastguard Worker  dd if="${TMPD}/rw.signed" of="${tmp_file}" seek="${rw_base}" conv="notrunc" \
83*4f2df630SAndroid Build Coastguard Worker     status="none" bs=1
84*4f2df630SAndroid Build Coastguard Worker}
85*4f2df630SAndroid Build Coastguard Worker
86*4f2df630SAndroid Build Coastguard Workermain () {
87*4f2df630SAndroid Build Coastguard Worker  local bin_size
88*4f2df630SAndroid Build Coastguard Worker  local dev_id0
89*4f2df630SAndroid Build Coastguard Worker  local dev_id1
90*4f2df630SAndroid Build Coastguard Worker  local flash_base
91*4f2df630SAndroid Build Coastguard Worker  local full_bin
92*4f2df630SAndroid Build Coastguard Worker  local manifest
93*4f2df630SAndroid Build Coastguard Worker  local output
94*4f2df630SAndroid Build Coastguard Worker  local prefix
95*4f2df630SAndroid Build Coastguard Worker  local rw_a_base
96*4f2df630SAndroid Build Coastguard Worker  local rw_b_base
97*4f2df630SAndroid Build Coastguard Worker  local rw_key
98*4f2df630SAndroid Build Coastguard Worker  local sha
99*4f2df630SAndroid Build Coastguard Worker  local tmp_file
100*4f2df630SAndroid Build Coastguard Worker  local xml
101*4f2df630SAndroid Build Coastguard Worker
102*4f2df630SAndroid Build Coastguard Worker  if [[ $# -ne 2 ]]; then
103*4f2df630SAndroid Build Coastguard Worker    echo "${SCRIPT_NAME} error:" >&2
104*4f2df630SAndroid Build Coastguard Worker    echo " Two command line arguments are required, dev_id0 and dev_id1" >&2
105*4f2df630SAndroid Build Coastguard Worker    exit 1
106*4f2df630SAndroid Build Coastguard Worker  fi
107*4f2df630SAndroid Build Coastguard Worker
108*4f2df630SAndroid Build Coastguard Worker  dev_id0="$1"
109*4f2df630SAndroid Build Coastguard Worker  dev_id1="$2"
110*4f2df630SAndroid Build Coastguard Worker
111*4f2df630SAndroid Build Coastguard Worker  full_bin=""
112*4f2df630SAndroid Build Coastguard Worker  for f in  build/ti50/dauntless/dauntless/full_image.signed.bin \
113*4f2df630SAndroid Build Coastguard Worker    build/cr50/ec.bin; do
114*4f2df630SAndroid Build Coastguard Worker    if [[ -f ${f} ]]; then
115*4f2df630SAndroid Build Coastguard Worker      full_bin="${f}"
116*4f2df630SAndroid Build Coastguard Worker      break
117*4f2df630SAndroid Build Coastguard Worker    fi
118*4f2df630SAndroid Build Coastguard Worker  done
119*4f2df630SAndroid Build Coastguard Worker
120*4f2df630SAndroid Build Coastguard Worker  if [[ -z ${full_bin} ]]; then
121*4f2df630SAndroid Build Coastguard Worker    echo "${SCRIPT_NAME} error: GSC binary not found" >&2
122*4f2df630SAndroid Build Coastguard Worker    exit 1
123*4f2df630SAndroid Build Coastguard Worker  fi
124*4f2df630SAndroid Build Coastguard Worker
125*4f2df630SAndroid Build Coastguard Worker  codesigner_params=(
126*4f2df630SAndroid Build Coastguard Worker    --dev_id0="${dev_id0}"
127*4f2df630SAndroid Build Coastguard Worker    --dev_id1="${dev_id1}"
128*4f2df630SAndroid Build Coastguard Worker    --format=bin
129*4f2df630SAndroid Build Coastguard Worker    --ihex
130*4f2df630SAndroid Build Coastguard Worker    --no-icache
131*4f2df630SAndroid Build Coastguard Worker    --override-keyid
132*4f2df630SAndroid Build Coastguard Worker    --padbank
133*4f2df630SAndroid Build Coastguard Worker  )
134*4f2df630SAndroid Build Coastguard Worker
135*4f2df630SAndroid Build Coastguard Worker  bin_size="$(stat -c '%s' "${full_bin}")"
136*4f2df630SAndroid Build Coastguard Worker  case "${bin_size}" in
137*4f2df630SAndroid Build Coastguard Worker    (524288) rw_a_base=16384 # RO area size is fixed at 16K
138*4f2df630SAndroid Build Coastguard Worker             rw_b_base=$(( bin_size / 2 + rw_a_base ))
139*4f2df630SAndroid Build Coastguard Worker             rw_key="util/signer/cr50_rom0-dev-blsign.pem.pub"
140*4f2df630SAndroid Build Coastguard Worker             manifest="util/signer/ec_RW-manifest-dev.json"
141*4f2df630SAndroid Build Coastguard Worker             xml="util/signer/fuses.xml"
142*4f2df630SAndroid Build Coastguard Worker             codesigner_params+=( --b )
143*4f2df630SAndroid Build Coastguard Worker             flash_base=262144
144*4f2df630SAndroid Build Coastguard Worker             prefix="cr50"
145*4f2df630SAndroid Build Coastguard Worker             ;;
146*4f2df630SAndroid Build Coastguard Worker    (1048576) local rw_bases
147*4f2df630SAndroid Build Coastguard Worker              # Third and sixths lines showing signed header magic are base
148*4f2df630SAndroid Build Coastguard Worker              # addresses of RW_A and RW_B.
149*4f2df630SAndroid Build Coastguard Worker              mapfile -t rw_bases < <(od -Ax -t x1 "${full_bin}" |awk '
150*4f2df630SAndroid Build Coastguard Worker                    /^....00 fd ff ff ff/ {
151*4f2df630SAndroid Build Coastguard Worker                       line = line + 1;
152*4f2df630SAndroid Build Coastguard Worker                       if (line % 3 == 0) {
153*4f2df630SAndroid Build Coastguard Worker                               print strtonum("0x"$1)
154*4f2df630SAndroid Build Coastguard Worker                       }
155*4f2df630SAndroid Build Coastguard Worker                   }')
156*4f2df630SAndroid Build Coastguard Worker              rw_a_base="${rw_bases[0]}"
157*4f2df630SAndroid Build Coastguard Worker              rw_b_base="${rw_bases[1]}"
158*4f2df630SAndroid Build Coastguard Worker              rw_key="ports/dauntless/signing/ti50_dev.key"
159*4f2df630SAndroid Build Coastguard Worker              manifest="ports/dauntless/signing/manifest.TOT.json"
160*4f2df630SAndroid Build Coastguard Worker              xml="ports/dauntless/signing/fuses.xml"
161*4f2df630SAndroid Build Coastguard Worker              codesigner_params+=( --dauntless )
162*4f2df630SAndroid Build Coastguard Worker              flash_base=524288
163*4f2df630SAndroid Build Coastguard Worker              prefix="ti50"
164*4f2df630SAndroid Build Coastguard Worker              ;;
165*4f2df630SAndroid Build Coastguard Worker    (*) echo "What is ${full_bin}?" >&2
166*4f2df630SAndroid Build Coastguard Worker        exit 1
167*4f2df630SAndroid Build Coastguard Worker        ;;
168*4f2df630SAndroid Build Coastguard Worker  esac
169*4f2df630SAndroid Build Coastguard Worker
170*4f2df630SAndroid Build Coastguard Worker  # Determine the current git tree state. This would match the binary image's
171*4f2df630SAndroid Build Coastguard Worker  # version string if it was built from this tree.
172*4f2df630SAndroid Build Coastguard Worker  sha="$(git rev-parse --short HEAD)"
173*4f2df630SAndroid Build Coastguard Worker  if git status --porcelain 2>&1 | grep -qv '^ *?'; then
174*4f2df630SAndroid Build Coastguard Worker    sha="${sha}-dirty"
175*4f2df630SAndroid Build Coastguard Worker  fi
176*4f2df630SAndroid Build Coastguard Worker
177*4f2df630SAndroid Build Coastguard Worker  #  Check if the output file already exists.
178*4f2df630SAndroid Build Coastguard Worker  output="$(printf "${prefix}.${sha}.%08x-%08x.bin" "${dev_id0}" "${dev_id1}")"
179*4f2df630SAndroid Build Coastguard Worker  if [[ -f ${output} ]]; then
180*4f2df630SAndroid Build Coastguard Worker    echo "${output} is already there"
181*4f2df630SAndroid Build Coastguard Worker    exit 0
182*4f2df630SAndroid Build Coastguard Worker  fi
183*4f2df630SAndroid Build Coastguard Worker
184*4f2df630SAndroid Build Coastguard Worker  # Make sure all necessary files are present.
185*4f2df630SAndroid Build Coastguard Worker  for f in "${rw_key}" "${manifest}" "${xml}"; do
186*4f2df630SAndroid Build Coastguard Worker    if [[ ! -f ${f} ]]; then
187*4f2df630SAndroid Build Coastguard Worker      echo "File ${f} not found" >&2
188*4f2df630SAndroid Build Coastguard Worker      exit 1
189*4f2df630SAndroid Build Coastguard Worker    fi
190*4f2df630SAndroid Build Coastguard Worker  done
191*4f2df630SAndroid Build Coastguard Worker
192*4f2df630SAndroid Build Coastguard Worker  # Clean up the manifest.
193*4f2df630SAndroid Build Coastguard Worker  sed -zE 's/"board_[^,]+,\s*//g;s/"info"[^}]+},\s*/"info": { },/' \
194*4f2df630SAndroid Build Coastguard Worker      "${manifest}" > "${TMPD}/manifest.json"
195*4f2df630SAndroid Build Coastguard Worker
196*4f2df630SAndroid Build Coastguard Worker  tmp_file="${TMPD}/full.bin"
197*4f2df630SAndroid Build Coastguard Worker  cp "${full_bin}" "${tmp_file}"
198*4f2df630SAndroid Build Coastguard Worker
199*4f2df630SAndroid Build Coastguard Worker  codesigner_params+=(
200*4f2df630SAndroid Build Coastguard Worker      --json "${TMPD}/manifest.json"
201*4f2df630SAndroid Build Coastguard Worker    --key "${rw_key}"
202*4f2df630SAndroid Build Coastguard Worker      -x "${xml}"
203*4f2df630SAndroid Build Coastguard Worker  )
204*4f2df630SAndroid Build Coastguard Worker
205*4f2df630SAndroid Build Coastguard Worker  echo "Re-signing a ${prefix} image"
206*4f2df630SAndroid Build Coastguard Worker
207*4f2df630SAndroid Build Coastguard Worker  re_sign_rw "${tmp_file}" "${flash_base}" "${rw_a_base}" \
208*4f2df630SAndroid Build Coastguard Worker             "${codesigner_params[@]}"
209*4f2df630SAndroid Build Coastguard Worker  re_sign_rw "${tmp_file}" "${flash_base}" "${rw_b_base}" \
210*4f2df630SAndroid Build Coastguard Worker             "${codesigner_params[@]}"
211*4f2df630SAndroid Build Coastguard Worker
212*4f2df630SAndroid Build Coastguard Worker  cp "${tmp_file}" "${output}"
213*4f2df630SAndroid Build Coastguard Worker}
214*4f2df630SAndroid Build Coastguard Worker
215*4f2df630SAndroid Build Coastguard Workermain "$@"
216