summaryrefslogtreecommitdiff
path: root/util/signer/create_released_image.sh
blob: 430f58168b0c30920b738867c1c2085887f0dab7 (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/bin/bash

#
# Copyright 2017 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.
#
# This script is a utility which allows to sign dev and prod CR50 images for
# release and place them in a tarball suitable for uploading to the BCS.
#
# Manifests present in the EC directory at the time of signing are used for
# both prod and dev images.
#

set -u

# A very crude RO verification function. The key signature found at a fixed
# offset into the RO blob must match the RO type. Prod keys have bit D2 set to
# one, dev keys have this bit set to zero.
verify_ro() {
  local ro_bin="${1}"
  local type_expected="${2}"
  local key_byte

  if [ ! -f "${ro_bin}" ]; then
    echo "${ro_bin} not a file!" >&2
    exit 1
  fi

  # Key signature's lowest byte is byte #5 in the line at offset 0001a0.
  key_byte="$(od -Ax -t x1 -v "${ro_bin}" | awk '/0001a0/ {print $6};')"
  case "${key_byte}" in
    (?[4567cdef])
      if [ "${type_expected}" == "prod" ]; then
        return 0
      fi
      ;;
    (?[012389ab])
      if [ "${type_expected}" == "dev" ]; then
        return 0
      fi
      ;;
  esac

  echo "RO key in ${ro_bin} does not match type ${type_expected}" >&2
  exit 1
}

# This function prepares a full CR50 image, consisting of two ROs and two RWs
# placed at their respective offsets into the resulting blob. It invokes the
# bs (binary signer) script to actually convert elf versions of RWs into
# binaries and sign them.
#
# The signed image is placed in the directory named as concatenation of RO and
# RW version numbers, which is where eventually the ebuild downloading the
# tarball from the BCS expects the dev and prod images be.
prepare_image() {
  local count=0
  local extra_param=
  local image_type="${1}"
  local ro_a_hex="$(readlink -f "${2}")"
  local ro_b_hex="$(readlink -f "${3}")"
  local rw_a="$(readlink -f "${4}")"
  local rw_b="$(readlink -f "${5}")"
  local version

  for f in "${ro_a_hex}" "${ro_b_hex}"; do
    if ! objcopy -I ihex "${f}" -O binary "${TMPD}/${count}.bin"; then
      echo "failed to convert ${f} from hex to bin" >&2
      exit 1
    fi
    verify_ro "${TMPD}/${count}.bin" "${image_type}"
    : $(( count += 1 ))
  done

  if [ "${image_type}" == "prod" ]; then
    extra_param+=' prod'
  fi

  if ! "${EC_ROOT}/util/signer/bs" ${extra_param} elves \
    "${rw_a}" "${rw_b}" > /dev/null;
  then
    echo "Failed invoking ${EC_ROOT}/util/signer/bs ${extra_param} " \
      "elves ${rw_a} ${rw_b}" >&2
    exit 1
  fi

  dd if="${TMPD}/0.bin" of="${RESULT_FILE}" conv=notrunc
  dd if="${TMPD}/1.bin" of="${RESULT_FILE}" seek=262144 bs=1 conv=notrunc

  version="$("${USB_UPDATER}" -b "${RESULT_FILE}" |
     awk '/^RO_A:/ {gsub(/R[OW]_A:/, ""); print "r" $1 ".w" $2}')"

  if [ -z "${dest_dir}" ]; then
    # Note that this is a global variable
    dest_dir="cr50.${version}"
    if [ ! -d "${dest_dir}" ]; then
      mkdir "${dest_dir}"
    else
      echo "${dest_dir} already exists, will overwrite" >&2
    fi
  elif [ "${dest_dir}" != "cr50.${version}" ]; then
    echo "dev and prod versions mismatch!" >&2
    exit 1
  fi

  cp "${RESULT_FILE}" "${dest_dir}/cr50.bin.${image_type}"
  echo "saved ${image_type} binary in ${dest_dir}/cr50.bin.${image_type}"
}

# Execution starts here ===========================
ME="$(basename $0)"

if [ -z "${CROS_WORKON_SRCROOT}" ]; then
 echo "${ME}: This script must run inside Chrome OS chroot" >&2
  exit 1
fi

SCRIPT_ROOT="${CROS_WORKON_SRCROOT}/src/scripts"
. "${SCRIPT_ROOT}/build_library/build_common.sh" || exit 1

TMPD="$(mktemp -d /tmp/${ME}.XXXXX)"
trap "/bin/rm -rf ${TMPD}" SIGINT SIGTERM EXIT

EC_ROOT="${CROS_WORKON_SRCROOT}/src/platform/ec"
RESULT_FILE="${TMPD}/release.bin"
dest_dir=
IMAGE_SIZE='524288'
export RESULT_FILE

USB_UPDATER="${EC_ROOT}/extra/usb_updater/usb_updater"
if [[ ! -x "${USB_UPDATER}" ]]; then
  echo "${ME}: usb_updater not found, run \"make -C extra/usb_updater\"" >&2
  exit 1
fi

DEFINE_string cr50_board_id "" \
  "Optional string representing Board ID field of the Cr50 RW header.
Consists of three fields separated by colon: <RLZ>:<hex mask>:<hex flags>"

# Do not put this before the DEFINE_ invocations - they routinely experience
# error return values.
set -e

FLAGS_HELP="usage: ${ME} [flags] <blobs>

blobs are:
  <prod RO A>.hex <prod RO B>.hex <dev RO A>.hex <dev RO B>.hex \
 <RW.elf> <RW_B.elf>"

# Parse command line.
FLAGS "$@" || exit 1

eval set -- "${FLAGS_ARGV}"
if [ "${#*}" != "6" ]; then
  flags_help
  exit 1
fi

dd if=/dev/zero bs="${IMAGE_SIZE}" count=1  2>/dev/null |
  tr \\000 \\377 > "${RESULT_FILE}"
if [ "$(stat -c '%s' "${RESULT_FILE}")" != "${IMAGE_SIZE}" ]; then
  echo "Failed creating ${RESULT_FILE}" >&2
  exit 1
fi

prod_ro_a="${1}"
prod_ro_b="${2}"
dev_ro_a="${3}"
dev_ro_b="${4}"
rw_a="${5}"
rw_b="${6}"

# Used by the bs script.
export CR50_BOARD_ID="${FLAGS_cr50_board_id}"

prepare_image 'dev' "${dev_ro_a}" "${dev_ro_b}" "${rw_a}" "${rw_b}"
prepare_image 'prod' "${prod_ro_a}" "${prod_ro_b}" "${rw_a}" "${rw_b}"
tarball="${dest_dir}.tbz2"
tar jcf  "${tarball}" "${dest_dir}"
rm -rf "${dest_dir}"

bcs_path="gs://chromeos-localmirror/distfiles"
echo "SUCCESS!!!!!!"
echo "use the below commands to copy the new image to the BCS"
echo "gsutil cp ${tarball} ${bcs_path}"
echo "gsutil acl ch -u AllUsers:R ${bcs_path}/${tarball}"