-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpack_firmware.sh
executable file
·243 lines (203 loc) · 6.98 KB
/
pack_firmware.sh
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/bin/bash
# Copyright 2019 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.
CURRENT_DIR="$(dirname "$(readlink -f "$0")")"
SCRIPT_ROOT="${CURRENT_DIR}/../../scripts"
. "${SCRIPT_ROOT}/common.sh" || exit 1
# Lookup table for default firmware version for RO.
# Should give 2.2.64 for nocturne, 2.2.144 for nami.
BOARD_TO_FACTORY_RO_VERSION="\
nocturne 10984.21.0
nami 10984.82.0"
DEFINE_string board "" "The board name. e.g. nocturne" b
DEFINE_string ro_version "" \
"The firmware version of the target file for RO part. e.g. 10984.88.0" r
DEFINE_string rw_version "" \
"The firmware version of the target file for RW part. e.g. 10984.88.0" w
DEFINE_string channel "dev" \
"The channel of the target file. One of canary, dev, beta, or stable" c
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
set -e
# The temporary working directory.
TMP=""
# The base URL of the downloaded files (RO version).
GS_URL_BASE_RO=""
# The base URL of the downloaded files (RW version).
GS_URL_BASE_RW=""
# The directory on gs containing the required firmware binaries.
# This can be different from the board name, e.g. board "nami" is in directory
# "nocturne".
DIRECTORY_NAME=""
# Version number of RO part of FP firmware
FP_RO_VERSION_NUMBER=""
# Version number of RW part of FP firmware
FP_RW_VERSION_NUMBER=""
# Name of final output file
OUTPUT_TAR=""
get_fw_version_for_RO() {
local board_name="${1}"
local key
local value
echo "${BOARD_TO_FACTORY_RO_VERSION}" | while read key value; do
if [[ "${key}" == "${board_name}" ]]; then
echo "${value}"
fi
done
}
# verify_mp (file): Verify that |file| is signed by mp key.
verify_mp() {
local file="$1"
local version="$(futility verify "${file}" \
| grep "Version:" \
| grep -o "0x0000000[0-9]")"
local expected
# Key versions for nocturne were different but it was a 1-off and should not
# happen again.
if [[ "${FLAGS_board}" == "nocturne" ]]; then
expected="0x00000002"
else
expected="0x00000003"
fi
if [[ "${version}" != "${expected}" ]]; then
die "${file} may not be signed with mp key! Key version: ${version}."
fi
}
init() {
TMP="$(mktemp -d)"
echo "Create temp work directory: ${TMP}"
cd "${TMP}"
if [[ -z "${FLAGS_board}" ]]; then
die_notrace "Please specify the board name using -b"
fi
if [[ -z "${FLAGS_ro_version}" ]]; then
FLAGS_ro_version="$(get_fw_version_for_RO "${FLAGS_board}")"
if [[ -z "${FLAGS_ro_version}" ]]; then
die_notrace \
"Please specify a firmware version for RO part using -r, e.g. 10984.88.0"
fi
fi
if [[ -z "${FLAGS_rw_version}" ]]; then
die_notrace \
"Please specify a firmware version for RW part using -w, e.g. 10984.88.0"
fi
if [[ -z "${FLAGS_channel}" ]]; then
die_notrace "Please specify a channel using -c, e.g. canary"
fi
# Due to historical reasons, the nami_fp firmware are put in nocturne
# directory.
if [[ "${FLAGS_board}" == "nami" ]]; then
DIRECTORY_NAME="nocturne"
else
DIRECTORY_NAME="${FLAGS_board}"
fi
local gs_url_base="gs://chromeos-releases/${FLAGS_channel}-channel/"\
"${DIRECTORY_NAME}"
GS_URL_BASE_RO="${gs_url_base}/${FLAGS_ro_version}"
echo "Looking for RO part at URL: ${GS_URL_BASE_RO}"
if ! gsutil ls "${GS_URL_BASE_RO}" > /dev/null; then
die_notrace \
"${GS_URL_BASE_RO} is not a valid URL. Please check the argument."
fi
GS_URL_BASE_RW="${gs_url_base}/${FLAGS_rw_version}"
echo "Looking for RW part at URL: ${GS_URL_BASE_RW}"
if ! gsutil ls "${GS_URL_BASE_RW}" > /dev/null; then
die_notrace \
"${GS_URL_BASE_RW} is not a valid URL. Please check the argument."
fi
}
cleanup() {
cd "${CURRENT_DIR}"
if [[ ( -n "${TMP}" ) && ( -d "${TMP}" ) ]]; then
rm -rf "${TMP}"
fi
}
# get_ec_file_path (ro|rw): Get the full path to latest mp signed fp binary.
get_ec_file_path() {
local image_type="$1"
local version
local url
if [[ "${image_type}" == "ro" ]]; then
version="${FLAGS_ro_version}"
url="${GS_URL_BASE_RO}"
else
version="${FLAGS_rw_version}"
url="${GS_URL_BASE_RW}"
fi
# Normally there should be only one mp signed fp firmware, but in case there
# are more, sort by version.
local file_name="$(gsutil ls "${url}" \
| grep -E "chromeos_${version}_${FLAGS_board}-fp_mp(-v[0-9]+)?.bin$" \
| sort -V \
| tail -n1)"
if [[ -z "${file_name}" ]]; then
die_notrace \
"Cannot find any mp signed FP firmware for board ${FLAGS_board} at ${url}"
fi
echo "${file_name}"
}
process_ec_file() {
local ec_ro="ec_ro.bin"
local ec_rw="ec_rw.bin"
# Download the two binaries as ec_ro.bin and ec_rw.bin.
gsutil cp "$(get_ec_file_path ro)" "${ec_ro}" &> /dev/null
gsutil cp "$(get_ec_file_path rw)" "${ec_rw}" &> /dev/null
verify_mp "${ec_ro}"
verify_mp "${ec_rw}"
# Print RO and RW versions.
local fmap_frid=($(dump_fmap -p "${ec_ro}" RO_FRID))
local fmap_fwid=($(dump_fmap -p "${ec_rw}" RW_FWID))
# fmap_frid[0]="RO_FRID" fmap_frid[1]=offset fmap_frid[2]=size (decimal)
# Same for fmap_fwid.
local ro_version_string="$(dd bs=1 skip="${fmap_frid[1]}" \
count="${fmap_frid[2]}" if="${ec_ro}" 2>/dev/null; echo)"
local rw_version_string="$(dd bs=1 skip="${fmap_fwid[1]}" \
count="${fmap_fwid[2]}" if="${ec_rw}" 2>/dev/null; echo)"
echo "Using FP firmware RO version: ${ro_version_string}"
echo "Using FP firmware RW version: ${rw_version_string}"
FP_RO_VERSION_NUMBER="$(echo "${ro_version_string}" \
| grep -o -E "[0-9]+\.[0-9]+\.[0-9]+")"
FP_RW_VERSION_NUMBER="$(echo "${rw_version_string}" \
| grep -o -E "[0-9]+\.[0-9]+\.[0-9]+")"
# Use RW firmware version as file name.
local new_file="${rw_version_string}.bin"
# fmap_rw_section[0]="EC_RW"
# fmap_rw_section[1]=offset
# fmap_rw_section[2]=size (decimal)
local fmap_rw_section=($(dump_fmap -p "${ec_ro}" EC_RW))
# Inject RW into the existing RO file.
echo "Merging files..."
cp "${ec_ro}" "${new_file}"
dd if="${ec_rw}" of="${new_file}" \
bs=1 skip="${fmap_rw_section[1]}" seek="${fmap_rw_section[1]}" \
count="${fmap_rw_section[2]}" conv=notrunc &> /dev/null
# Verify the resulting image is signed properly.
echo "Verifiying output file..."
verify_mp "${new_file}"
if ! futility verify --strict "${new_file}" >&2; then
die "Cannot verify ${new_file}."
fi
echo "Merged into new binary: ${new_file}"
OUTPUT_TAR="${FLAGS_board}_fp_${FP_RW_VERSION_NUMBER}.tbz2"
tar jcf "${OUTPUT_TAR}" "${new_file}"
echo "Generating the FP firmware tarball: ${OUTPUT_TAR}"
mv "${OUTPUT_TAR}" "${CURRENT_DIR}"
}
main() {
TMP=""
trap cleanup EXIT
assert_inside_chroot
init
# Download and extract EC firmware.
process_ec_file
# Print out the update instruction.
cat <<EOF
${V_BOLD_GREEN}Successfully generated the FPMCU EC tarball with RO version \
${FP_RO_VERSION_NUMBER} and RW version ${FP_RW_VERSION_NUMBER}.
Please upload the tarball ${OUTPUT_TAR} to CPFE and update the corresponding \
ebuild.
${V_VIDOFF}
EOF
}
main "$@"