• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash -eux
2# Copyright 2018 The ChromiumOS Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6me=${0##*/}
7TMP="$me.tmp"
8
9# Test --sys_props (primitive test needed for future updating tests).
10test_sys_props() {
11  ! "${FUTILITY}" --debug update --sys_props "$*" 2>&1 |
12    sed -n 's/.*property\[\(.*\)].value = \(.*\)/\1,\2,/p' |
13    tr '\n' ' '
14}
15
16test "$(test_sys_props "1,2,3")" = "0,1, 1,2, 2,3, "
17test "$(test_sys_props "1 2 3")" = "0,1, 1,2, 2,3, "
18test "$(test_sys_props "1, 2,3 ")" = "0,1, 1,2, 2,3, "
19test "$(test_sys_props "   1,, 2")" = "0,1, 2,2, "
20test "$(test_sys_props " , 4,")" = "1,4, "
21
22test_quirks() {
23  ! "${FUTILITY}" --debug update --quirks "$*" 2>&1 |
24    sed -n 's/.*Set quirk \(.*\) to \(.*\)./\1,\2/p' |
25    tr '\n' ' '
26}
27
28test "$(test_quirks "enlarge_image")" = "enlarge_image,1 "
29test "$(test_quirks "enlarge_image=2")" = "enlarge_image,2 "
30test "$(test_quirks " enlarge_image, enlarge_image=2")" = \
31  "enlarge_image,1 enlarge_image,2 "
32
33# Test data files
34DATA_DIR="${SCRIPT_DIR}/futility/data"
35GERALT_BIOS="${DATA_DIR}/bios_geralt_cbfs.bin"
36LINK_BIOS="${DATA_DIR}/bios_link_mp.bin"
37PEPPY_BIOS="${DATA_DIR}/bios_peppy_mp.bin"
38VOXEL_BIOS="${DATA_DIR}/bios_voxel_dev.bin"
39RO_VPD_BLOB="${DATA_DIR}/ro_vpd.bin"
40SIGNER_CONFIG="${DATA_DIR}/signer_config.csv"
41
42# Work in scratch directory
43cd "${OUTDIR}"
44set -o pipefail
45
46# Re-create the temp folders
47TMP_FROM="${TMP}/from"
48TMP_TO="${TMP}/to"
49EXPECTED="${TMP}/expected"
50rm -rf "${TMP}"
51mkdir -p "${TMP_FROM}" "${TMP_TO}" "${EXPECTED}"
52
53# In all the test scenario, we want to test "updating from PEPPY to LINK".
54TO_IMAGE="${TMP}/src.link"
55FROM_IMAGE="${TMP}/src.peppy"
56TO_HWID="X86 LINK TEST 6638"
57FROM_HWID="X86 PEPPY TEST 4211"
58cp -f "${LINK_BIOS}" "${TO_IMAGE}"
59cp -f "${PEPPY_BIOS}" "${FROM_IMAGE}"
60"${FUTILITY}" load_fmap "${FROM_IMAGE}" \
61  RO_VPD:"${RO_VPD_BLOB}" RW_VPD:"${RO_VPD_BLOB}"
62cp -f "${FROM_IMAGE}" "${FROM_IMAGE}".unpatched
63
64patch_file() {
65  local file="$1"
66  local section="$2"
67  local section_offset="$3"
68  local data="$4"
69
70  # NAME OFFSET SIZE
71  local fmap_info
72  local base
73  local offset
74
75  fmap_info="$("${FUTILITY}" dump_fmap -p "${file}" "${section}")"
76  base="$(echo "${fmap_info}" | sed 's/^[^ ]* //; s/ [^ ]*$//')"
77  offset=$((base + section_offset))
78  echo "offset: ${offset}"
79  printf "%b" "${data}" | dd of="${file}" bs=1 seek="${offset}" \
80    conv=notrunc
81}
82
83# PEPPY and LINK have different platform element ("Google_Link" and
84# "Google_Peppy") in firmware ID so we want to hack them by changing
85# "Google_" to "Google.".
86patch_file "${TO_IMAGE}" RW_FWID_A 0 Google.
87patch_file "${TO_IMAGE}" RW_FWID_B 0 Google.
88patch_file "${TO_IMAGE}" RO_FRID 0 Google.
89patch_file "${FROM_IMAGE}" RW_FWID_A 0 Google.
90patch_file "${FROM_IMAGE}" RW_FWID_B 0 Google.
91patch_file "${FROM_IMAGE}" RO_FRID 0 Google.
92
93unpack_image() {
94  local folder="${TMP}/$1"
95  local image="$2"
96  mkdir -p "${folder}"
97  (cd "${folder}" && "${FUTILITY}" dump_fmap -x "../../${image}")
98  "${FUTILITY}" gbb -g --rootkey="${folder}/rootkey" "${image}"
99}
100
101# Unpack images so we can prepare expected results by individual sections.
102unpack_image "to" "${TO_IMAGE}"
103unpack_image "from" "${FROM_IMAGE}"
104
105# Hack FROM_IMAGE so it has same root key as TO_IMAGE (for RW update).
106FROM_DIFFERENT_ROOTKEY_IMAGE="${FROM_IMAGE}2"
107cp -f "${FROM_IMAGE}" "${FROM_DIFFERENT_ROOTKEY_IMAGE}"
108"${FUTILITY}" gbb -s --rootkey="${TMP_TO}/rootkey" "${FROM_IMAGE}"
109
110# Hack for quirks
111cp -f "${FROM_IMAGE}" "${FROM_IMAGE}.large"
112truncate -s $((8388608 * 2)) "${FROM_IMAGE}.large"
113
114# Create the FROM_SAME_RO_IMAGE using the RO from TO_IMAGE."
115FROM_SAME_RO_IMAGE="${FROM_IMAGE}.same_ro"
116cp -f "${FROM_IMAGE}" "${FROM_SAME_RO_IMAGE}"
117"${FUTILITY}" load_fmap "${FROM_SAME_RO_IMAGE}" \
118  "RO_SECTION:${TMP_TO}/RO_SECTION"
119
120# Create GBB v1.2 images (for checking digest)
121GBB_OUTPUT="$("${FUTILITY}" gbb --digest "${TO_IMAGE}")"
122[ "${GBB_OUTPUT}" = "digest: <none>" ]
123TO_IMAGE_GBB12="${TO_IMAGE}.gbb12"
124HWID_DIGEST="adf64d2a434b610506153da42440b0b498d7369c0e98b629ede65eb59f4784fa"
125cp -f "${TO_IMAGE}" "${TO_IMAGE_GBB12}"
126patch_file "${TO_IMAGE_GBB12}" GBB 6 "\x02"
127"${FUTILITY}" gbb -s --hwid="${TO_HWID}" "${TO_IMAGE_GBB12}"
128GBB_OUTPUT="$("${FUTILITY}" gbb --digest "${TO_IMAGE_GBB12}")"
129[ "${GBB_OUTPUT}" = "digest: ${HWID_DIGEST}   valid" ]
130
131# Create images with (empty) AP RO verification
132# (Patch FMAP to rename 'RO_UNUSED' to 'RO_GSCVD')
133cp -f "${FROM_IMAGE}" "${FROM_IMAGE}.locked"
134patch_file "${FROM_IMAGE}.locked" FMAP 0x0430 "RO_GSCVD\x00"
135cp -f "${FROM_IMAGE}.locked" "${FROM_IMAGE}.locked_same_desc"
136cp -f "${FROM_IMAGE}.locked" "${FROM_IMAGE}.unlocked"
137patch_file "${FROM_IMAGE}.unlocked" SI_DESC 0x60 \
138  "\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff"
139"${FUTILITY}" load_fmap "${FROM_IMAGE}.locked_same_desc" \
140  "SI_DESC:${TMP_TO}/SI_DESC"
141
142# Generate expected results.
143cp -f "${TO_IMAGE}" "${EXPECTED}/full"
144cp -f "${FROM_IMAGE}" "${EXPECTED}/rw"
145cp -f "${FROM_IMAGE}" "${EXPECTED}/a"
146cp -f "${FROM_IMAGE}" "${EXPECTED}/b"
147cp -f "${FROM_SAME_RO_IMAGE}" "${EXPECTED}/FROM_SAME_RO_IMAGE.b"
148cp -f "${FROM_IMAGE}" "${EXPECTED}/legacy"
149"${FUTILITY}" gbb -s --hwid="${FROM_HWID}" "${EXPECTED}/full"
150"${FUTILITY}" load_fmap "${EXPECTED}/full" \
151  "RW_VPD:${TMP_FROM}/RW_VPD" \
152  "RO_VPD:${TMP_FROM}/RO_VPD"
153"${FUTILITY}" load_fmap "${EXPECTED}/rw" \
154  "RW_SECTION_A:${TMP_TO}/RW_SECTION_A" \
155  "RW_SECTION_B:${TMP_TO}/RW_SECTION_B" \
156  "RW_SHARED:${TMP_TO}/RW_SHARED" \
157  "RW_LEGACY:${TMP_TO}/RW_LEGACY"
158"${FUTILITY}" load_fmap "${EXPECTED}/a" \
159  "RW_SECTION_A:${TMP_TO}/RW_SECTION_A"
160"${FUTILITY}" load_fmap "${EXPECTED}/b" \
161  "RW_SECTION_B:${TMP_TO}/RW_SECTION_B"
162"${FUTILITY}" load_fmap "${EXPECTED}/FROM_SAME_RO_IMAGE.b" \
163  "RW_SECTION_B:${TMP_TO}/RW_SECTION_B"
164"${FUTILITY}" load_fmap "${EXPECTED}/legacy" \
165  "RW_LEGACY:${TMP_TO}/RW_LEGACY"
166cp -f "${EXPECTED}/full" "${EXPECTED}/full.gbb12"
167patch_file "${EXPECTED}/full.gbb12" GBB 6 "\x02"
168"${FUTILITY}" gbb -s --hwid="${FROM_HWID}" "${EXPECTED}/full.gbb12"
169cp -f "${EXPECTED}/full" "${EXPECTED}/full.gbb0"
170"${FUTILITY}" gbb -s --flags=0 "${EXPECTED}/full.gbb0"
171cp -f "${FROM_IMAGE}" "${FROM_IMAGE}.gbb0"
172"${FUTILITY}" gbb -s --flags=0 "${FROM_IMAGE}.gbb0"
173cp -f "${EXPECTED}/full" "${EXPECTED}/full.gbb0x27"
174"${FUTILITY}" gbb -s --flags=0x27 "${EXPECTED}/full.gbb0x27"
175cp -f "${EXPECTED}/full" "${EXPECTED}/large"
176dd if=/dev/zero bs=8388608 count=1 | tr '\000' '\377' >>"${EXPECTED}/large"
177cp -f "${EXPECTED}/full" "${EXPECTED}/me_unlocked_eve"
178patch_file "${EXPECTED}/me_unlocked_eve" SI_DESC 0x60 \
179  "\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff"
180cp -f "${EXPECTED}/full" "${EXPECTED}/me_preserved"
181"${FUTILITY}" load_fmap "${EXPECTED}/me_preserved" \
182  "SI_ME:${TMP_FROM}/SI_ME"
183cp -f "${EXPECTED}/rw" "${EXPECTED}/rw.locked"
184patch_file "${EXPECTED}/rw.locked" FMAP 0x0430 "RO_GSCVD\x00"
185
186# A special set of images that only RO_VPD is preserved (RW_VPD is wiped) using
187# FMAP_AREA_PRESERVE (\010=0x08).
188TO_IMAGE_WIPE_RW_VPD="${TO_IMAGE}.wipe_rw_vpd"
189cp -f "${TO_IMAGE}" "${TO_IMAGE_WIPE_RW_VPD}"
190patch_file "${TO_IMAGE_WIPE_RW_VPD}" FMAP 0x3fc "$(printf '\010')"
191cp -f "${EXPECTED}/full" "${EXPECTED}/full.empty_rw_vpd"
192"${FUTILITY}" load_fmap "${EXPECTED}/full.empty_rw_vpd" \
193  RW_VPD:"${TMP_TO}/RW_VPD"
194patch_file "${EXPECTED}/full.empty_rw_vpd" FMAP 0x3fc "$(printf '\010')"
195
196# Generate images for testing --unlock_me.
197# There are two ways to detect the platform:
198#  - Read CONFIG_IFD_CHIPSET from config file in CBFS
199#  - Fallback for nissa: check if CONFIG_IFD_BIN_PATH contains 'nissa'
200
201# Rename BOOT_STUB to COREBOOT, which is the default region used by cbfstool.
202rename_boot_stub() {
203  local image="$1"
204  local fmap_file="${TMP}/fmap"
205
206  "${FUTILITY}" dump_fmap "${image}" -x "FMAP:${fmap_file}"
207  sed -i 's/BOOT_STUB/COREBOOT\x00/g' "${fmap_file}"
208  "${FUTILITY}" load_fmap "${image}" "FMAP:${fmap_file}"
209}
210
211# Add the given line to the config file in CBFS.
212add_config() {
213  local image="$1"
214  local config_line="$2"
215  local config_file="${TMP}/config"
216
217  rename_boot_stub "${image}"
218
219  cbfstool "${image}" extract -n config -f "${config_file}"
220  echo "${config_line}" >>"${config_file}"
221  cbfstool "${image}" remove -n config
222  cbfstool "${image}" add -n config -f "${config_file}" -t raw
223}
224
225unlock_me() {
226  local image="$1"
227
228  patch_file "${image}" SI_DESC 0x60 \
229    "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
230  patch_file "${image}" SI_DESC 0x154 \
231    "\x00\x00\x00\x00"
232}
233
234IFD_CHIPSET='CONFIG_IFD_CHIPSET="adl"'
235IFD_PATH='CONFIG_IFD_BIN_PATH="3rdparty/blobs/mainboard/google/nissa/descriptor-craask.bin"'
236cp -f "${TO_IMAGE}" "${TO_IMAGE}.ifd_chipset"
237cp -f "${TO_IMAGE}" "${TO_IMAGE}.ifd_path"
238cp -f "${EXPECTED}/full" "${EXPECTED}/ifd_chipset"
239cp -f "${EXPECTED}/full" "${EXPECTED}/ifd_path"
240add_config "${TO_IMAGE}.ifd_chipset" "${IFD_CHIPSET}"
241add_config "${TO_IMAGE}.ifd_path" "${IFD_PATH}"
242add_config "${EXPECTED}/ifd_chipset" "${IFD_CHIPSET}"
243add_config "${EXPECTED}/ifd_path" "${IFD_PATH}"
244
245cp -f "${EXPECTED}/ifd_chipset" "${EXPECTED}/me_unlocked.ifd_chipset"
246cp -f "${EXPECTED}/ifd_path" "${EXPECTED}/me_unlocked.ifd_path"
247unlock_me "${EXPECTED}/me_unlocked.ifd_chipset"
248unlock_me "${EXPECTED}/me_unlocked.ifd_path"
249
250# Has 3 modes:
251# 1. $3 = "!something", run command, expect failure,
252#    grep for something in log, fail if it is not present
253# 2. $3 = "something", run command, expect success,
254#    cmp output to file named $3, fail if they are not the same
255# 3. $3 = "!", run command, expect success, fail to find a file named !
256test_update() {
257  local test_name="$1"
258  local emu_src="$2"
259  local expected="$3"
260  local error_msg="${expected#!}"
261  local emu="${TMP}/emu"
262  local msg
263
264  shift 3
265  cp -f "${emu_src}" "${emu}"
266  echo "*** Test Item: ${test_name}"
267  if [ "${error_msg}" != "${expected}" ] && [ -n "${error_msg}" ]; then
268    msg="$(! "${FUTILITY}" update --emulate "${emu}" "$@" 2>&1)"
269    grep -qF -- "${error_msg}" <<<"${msg}"
270  else
271    "${FUTILITY}" update --emulate "${emu}" "$@"
272    cmp "${emu}" "${expected}"
273  fi
274}
275
276# --sys_props: mainfw_act, tpm_fwver, platform_ver, [wp_hw, wp_sw]
277# tpm_fwver = <data key version:16><firmware version:16>.
278# TO_IMAGE is signed with data key version = 1, firmware version = 4 => 0x10004.
279
280# Test Full update.
281test_update "Full update" \
282  "${FROM_IMAGE}" "${EXPECTED}/full" \
283  -i "${TO_IMAGE}" --wp=0
284
285test_update "Full update (incompatible platform)" \
286  "${FROM_IMAGE}" "!platform is not compatible" \
287  -i "${LINK_BIOS}" --wp=0
288
289test_update "Full update (TPM Anti-rollback: data key)" \
290  "${FROM_IMAGE}" "!Data key version rollback detected (2->1)" \
291  -i "${TO_IMAGE}" --wp=0 --sys_props 1,0x20001
292
293test_update "Full update (TPM Anti-rollback: kernel key)" \
294  "${FROM_IMAGE}" "!Firmware version rollback detected (5->4)" \
295  -i "${TO_IMAGE}" --wp=0 --sys_props 1,0x10005
296
297test_update "Full update (TPM Anti-rollback: 0 as tpm_fwver)" \
298  "${FROM_IMAGE}" "${EXPECTED}/full" \
299  -i "${TO_IMAGE}" --wp=0 --sys_props ,0x0
300
301test_update "Full update (TPM check failure due to invalid tpm_fwver)" \
302  "${FROM_IMAGE}" "!Invalid tpm_fwver: -1" \
303  -i "${TO_IMAGE}" --wp=0 --sys_props ,-1
304
305test_update "Full update (Skip TPM check with --force)" \
306  "${FROM_IMAGE}" "${EXPECTED}/full" \
307  -i "${TO_IMAGE}" --wp=0 --sys_props ,-1 --force
308
309test_update "Full update (from stdin)" \
310  "${FROM_IMAGE}" "${EXPECTED}/full" \
311  -i - --wp=0 --sys_props ,-1 --force <"${TO_IMAGE}"
312
313test_update "Full update (GBB=0 -> 0)" \
314  "${FROM_IMAGE}.gbb0" "${EXPECTED}/full.gbb0" \
315  -i "${TO_IMAGE}" --wp=0
316
317test_update "Full update (GBB flags -> 0x27)" \
318  "${FROM_IMAGE}" "${EXPECTED}/full.gbb0x27" \
319  -i "${TO_IMAGE}" --gbb_flags=0x27 --wp=0
320
321test_update "Full update (--host_only)" \
322  "${FROM_IMAGE}" "${EXPECTED}/full" \
323  -i "${TO_IMAGE}" --wp=0 --host_only --ec_image non-exist.bin
324
325test_update "Full update (GBB1.2 hwid digest)" \
326  "${FROM_IMAGE}" "${EXPECTED}/full.gbb12" \
327  -i "${TO_IMAGE_GBB12}" --wp=0
328
329test_update "Full update (Preserve VPD using FMAP_AREA_PRESERVE)" \
330  "${FROM_IMAGE}" "${EXPECTED}/full.empty_rw_vpd" \
331  -i "${TO_IMAGE_WIPE_RW_VPD}" --wp=0
332
333
334# Test RW-only update.
335test_update "RW update" \
336  "${FROM_IMAGE}" "${EXPECTED}/rw" \
337  -i "${TO_IMAGE}" --wp=1
338
339test_update "RW update (incompatible platform)" \
340  "${FROM_IMAGE}" "!platform is not compatible" \
341  -i "${LINK_BIOS}" --wp=1
342
343test_update "RW update (incompatible rootkey)" \
344  "${FROM_DIFFERENT_ROOTKEY_IMAGE}" "!RW signed by incompatible root key" \
345  -i "${TO_IMAGE}" --wp=1
346
347test_update "RW update (TPM Anti-rollback: data key)" \
348  "${FROM_IMAGE}" "!Data key version rollback detected (2->1)" \
349  -i "${TO_IMAGE}" --wp=1 --sys_props 1,0x20001
350
351test_update "RW update (TPM Anti-rollback: kernel key)" \
352  "${FROM_IMAGE}" "!Firmware version rollback detected (5->4)" \
353  -i "${TO_IMAGE}" --wp=1 --sys_props 1,0x10005
354
355# Test Try-RW update (vboot2).
356test_update "RW update (A->B)" \
357  "${FROM_IMAGE}" "${EXPECTED}/b" \
358  -i "${TO_IMAGE}" -t --wp=1 --sys_props 0
359
360test_update "RW update (B->A)" \
361  "${FROM_IMAGE}" "${EXPECTED}/a" \
362  -i "${TO_IMAGE}" -t --wp=1 --sys_props 1
363
364test_update "RW update, same RO, wp=0 (A->B)" \
365  "${FROM_SAME_RO_IMAGE}" "${EXPECTED}/FROM_SAME_RO_IMAGE.b" \
366  -i "${TO_IMAGE}" -t --wp=0 --sys_props 0
367
368test_update "RW update, same RO, wp=1 (A->B)" \
369  "${FROM_SAME_RO_IMAGE}" "${EXPECTED}/FROM_SAME_RO_IMAGE.b" \
370  -i "${TO_IMAGE}" -t --wp=1 --sys_props 0
371
372test_update "RW update -> fallback to RO+RW Full update" \
373  "${FROM_IMAGE}" "${EXPECTED}/full" \
374  -i "${TO_IMAGE}" -t --wp=0 --sys_props 1,0x10002
375test_update "RW update (incompatible platform)" \
376  "${FROM_IMAGE}" "!platform is not compatible" \
377  -i "${LINK_BIOS}" -t --wp=1
378
379test_update "RW update (incompatible rootkey)" \
380  "${FROM_DIFFERENT_ROOTKEY_IMAGE}" "!RW signed by incompatible root key" \
381  -i "${TO_IMAGE}" -t --wp=1
382
383test_update "RW update (TPM Anti-rollback: data key)" \
384  "${FROM_IMAGE}" "!Data key version rollback detected (2->1)" \
385  -i "${TO_IMAGE}" -t --wp=1 --sys_props 1,0x20001
386
387test_update "RW update (TPM Anti-rollback: kernel key)" \
388  "${FROM_IMAGE}" "!Firmware version rollback detected (5->4)" \
389  -i "${TO_IMAGE}" -t --wp=1 --sys_props 1,0x10005
390
391test_update "RW update -> fallback to RO+RW Full update (TPM Anti-rollback)" \
392  "${FROM_IMAGE}" "!Firmware version rollback detected (6->4)" \
393  -i "${TO_IMAGE}" -t --wp=0 --sys_props 1,0x10006
394
395# Test 'factory mode'
396test_update "Factory mode update (WP=0)" \
397  "${FROM_IMAGE}" "${EXPECTED}/full" \
398  -i "${TO_IMAGE}" --wp=0 --mode=factory
399
400test_update "Factory mode update (WP=0)" \
401  "${FROM_IMAGE}" "${EXPECTED}/full" \
402  --factory -i "${TO_IMAGE}" --wp=0
403
404test_update "Factory mode update (WP=1)" \
405  "${FROM_IMAGE}" "!remove write protection for factory mode" \
406  -i "${TO_IMAGE}" --wp=1 --mode=factory
407
408test_update "Factory mode update (WP=1)" \
409  "${FROM_IMAGE}" "!remove write protection for factory mode" \
410  --factory -i "${TO_IMAGE}" --wp=1
411
412test_update "Factory mode update (GBB=0 -> 0x39)" \
413  "${FROM_IMAGE}.gbb0" "${EXPECTED}/full" \
414  --factory -i "${TO_IMAGE}" --wp=0
415
416# Test 'AP RO locked with verification turned on'
417test_update "AP RO locked update (locked, SI_DESC is different)" \
418  "${FROM_IMAGE}.locked" "${EXPECTED}/rw.locked" \
419  -i "${TO_IMAGE}" --wp=0 --debug
420
421test_update "AP RO locked update (locked, SI_DESC is the same)" \
422  "${FROM_IMAGE}.locked_same_desc" "${EXPECTED}/full" \
423  -i "${TO_IMAGE}" --wp=0 --debug
424
425test_update "AP RO locked update (unlocked)" \
426  "${FROM_IMAGE}.unlocked" "${EXPECTED}/full" \
427  -i "${TO_IMAGE}" --wp=0 --debug
428
429# Test legacy update
430test_update "Legacy update" \
431  "${FROM_IMAGE}" "${EXPECTED}/legacy" \
432  -i "${TO_IMAGE}" --mode=legacy
433
434# Test quirks
435test_update "Full update (wrong size)" \
436  "${FROM_IMAGE}.large" "!Failed writing firmware" \
437  -i "${TO_IMAGE}" --wp=0 \
438  --quirks unlock_csme_eve,eve_smm_store
439
440test_update "Full update (--quirks enlarge_image)" \
441  "${FROM_IMAGE}.large" "${EXPECTED}/large" --quirks enlarge_image \
442  -i "${TO_IMAGE}" --wp=0
443
444test_update "Full update (multi-line --quirks enlarge_image)" \
445  "${FROM_IMAGE}.large" "${EXPECTED}/large" --quirks '
446  enlarge_image
447  ' -i "${TO_IMAGE}" --wp=0
448
449test_update "Full update (--quirks unlock_csme_eve)" \
450  "${FROM_IMAGE}" "${EXPECTED}/me_unlocked_eve" \
451  --quirks unlock_csme_eve \
452  -i "${TO_IMAGE}" --wp=0
453
454test_update "Full update (failure by --quirks min_platform_version)" \
455  "${FROM_IMAGE}" "!Need platform version >= 3 (current is 2)" \
456  --quirks min_platform_version=3 \
457  -i "${TO_IMAGE}" --wp=0 --sys_props ,,2
458
459test_update "Full update (--quirks min_platform_version)" \
460  "${FROM_IMAGE}" "${EXPECTED}/full" \
461  --quirks min_platform_version=3 \
462  -i "${TO_IMAGE}" --wp=0 --sys_props ,,3
463
464test_update "Full update (incompatible platform)" \
465  "${FROM_IMAGE}".unpatched "!platform is not compatible" \
466  -i "${TO_IMAGE}" --wp=0
467
468test_update "Full update (--quirks no_check_platform)" \
469  "${FROM_IMAGE}".unpatched "${EXPECTED}/full" \
470  --quirks no_check_platform \
471  -i "${TO_IMAGE}" --wp=0
472
473test_update "Full update (--quirks preserve_me with non-host programmer)" \
474  "${FROM_IMAGE}" "${EXPECTED}/full" \
475  --quirks preserve_me \
476  -i "${TO_IMAGE}" --wp=0 \
477  -p raiden_debug_spi:target=AP
478
479test_update "Full update (--quirks preserve_me)" \
480  "${FROM_IMAGE}" "${EXPECTED}/full" \
481  --quirks preserve_me \
482  -i "${TO_IMAGE}" --wp=0
483
484test_update "Full update (--quirks preserve_me, autoupdate)" \
485  "${FROM_IMAGE}" "${EXPECTED}/me_preserved" \
486  --quirks preserve_me -m autoupdate \
487  -i "${TO_IMAGE}" --wp=0
488
489test_update "Full update (--quirks preserve_me, deferupdate_hold)" \
490  "${FROM_IMAGE}" "${EXPECTED}/me_preserved" \
491  --quirks preserve_me -m deferupdate_hold \
492  -i "${TO_IMAGE}" --wp=0
493
494test_update "Full update (--quirks preserve_me, factory)" \
495  "${FROM_IMAGE}" "${EXPECTED}/full" \
496  --quirks preserve_me -m factory \
497  -i "${TO_IMAGE}" --wp=0
498
499# Test manifest.
500TMP_JSON_OUT="${TMP}/json.out"
501echo "TEST: Manifest (--manifest, --image)"
502cp -f "${GERALT_BIOS}" "${TMP}/image.bin"
503(cd "${TMP}" &&
504 "${FUTILITY}" update -i image.bin --manifest) >"${TMP_JSON_OUT}"
505cmp \
506  <(jq -S <"${TMP_JSON_OUT}") \
507  <(jq -S <"${SCRIPT_DIR}/futility/bios_geralt_cbfs.manifest.json")
508
509TMP_PARSEABLE_OUT="${TMP}/manifest.parseable"
510echo "TEST: Manifest parseable (--parseable-manifest, --image)"
511(cd "${TMP}" &&
512 "${FUTILITY}" update -i image.bin --parseable-manifest) >"${TMP_PARSEABLE_OUT}"
513cmp \
514  <(sort "${TMP_PARSEABLE_OUT}") \
515  <(sort "${SCRIPT_DIR}/futility/bios_geralt_cbfs.manifest.parseable")
516
517# Test archive and manifest. CL_TAG is for custom_label_tag.
518A="${TMP}/archive"
519mkdir -p "${A}/bin"
520echo 'echo "${CL_TAG}"' >"${A}/bin/vpd"
521chmod +x "${A}/bin/vpd"
522
523cp -f "${LINK_BIOS}" "${A}/bios.bin"
524echo "TEST: Manifest (--manifest, -a, bios.bin)"
525"${FUTILITY}" update -a "${A}" --manifest >"${TMP_JSON_OUT}"
526cmp \
527  <(jq -S <"${TMP_JSON_OUT}") \
528  <(jq -S <"${SCRIPT_DIR}/futility/link_bios.manifest.json")
529
530echo "TEST: Manifest parseable (--parseable-manifest, -a, bios.bin)"
531"${FUTILITY}" update -a "${A}" --parseable-manifest >"${TMP_PARSEABLE_OUT}"
532diff -u \
533  <(sort "${TMP_PARSEABLE_OUT}") \
534  <(sort "${SCRIPT_DIR}/futility/link_bios.manifest.parseable")
535
536mv -f "${A}/bios.bin" "${A}/image.bin"
537echo "TEST: Manifest (--manifest, -a, image.bin)"
538"${FUTILITY}" update -a "${A}" --manifest >"${TMP_JSON_OUT}"
539cmp \
540  <(jq -S <"${TMP_JSON_OUT}") \
541  <(jq -S <"${SCRIPT_DIR}/futility/link_image.manifest.json")
542
543echo "TEST: Manifest parseable (--parseable-manifest, -a, image.bin)"
544"${FUTILITY}" update -a "${A}" --parseable-manifest >"${TMP_PARSEABLE_OUT}"
545diff -u \
546  <(sort "${TMP_PARSEABLE_OUT}") \
547  <(sort "${SCRIPT_DIR}/futility/link_image.manifest.parseable")
548
549cp -f "${TO_IMAGE}" "${A}/image.bin"
550test_update "Full update (--archive, single package)" \
551  "${FROM_IMAGE}" "${EXPECTED}/full" \
552  -a "${A}" --wp=0 --sys_props ,,3
553
554echo "TEST: Output (--archive, --mode=output)"
555TMP_OUTPUT="${TMP}/out_archive" && mkdir -p "${TMP_OUTPUT}"
556"${FUTILITY}" update -a "${A}" --mode=output \
557  --output_dir="${TMP_OUTPUT}"
558cmp "${TMP_OUTPUT}/image.bin" "${TO_IMAGE}"
559
560# Test Unified Build archives.
561mkdir -p "${A}/keyset" "${A}/images"
562cp -f "${SIGNER_CONFIG}" "${A}/"
563cp -f "${LINK_BIOS}" "${A}/image.bin"
564"${FUTILITY}" gbb -s --rootkey="${TMP_FROM}/rootkey" "${A}/image.bin"
565"${FUTILITY}" load_fmap "${A}/image.bin" VBLOCK_A:"${TMP_FROM}/VBLOCK_A"
566"${FUTILITY}" load_fmap "${A}/image.bin" VBLOCK_B:"${TMP_FROM}/VBLOCK_B"
567mv -f "${A}/image.bin" "${A}/images/bios_coral.bin"
568cp -f "${PEPPY_BIOS}" "${A}/images/bios_peppy.bin"
569cp -f "${LINK_BIOS}" "${A}/images/bios_link.bin"
570cp -f "${TMP_TO}/rootkey" "${A}/keyset/rootkey.customtip-cl"
571cp -f "${TMP_TO}/VBLOCK_A" "${A}/keyset/vblock_A.customtip-cl"
572cp -f "${TMP_TO}/VBLOCK_B" "${A}/keyset/vblock_B.customtip-cl"
573cp -f "${PEPPY_BIOS}" "${FROM_IMAGE}.ap"
574cp -f "${LINK_BIOS}" "${FROM_IMAGE}.al"
575cp -f "${VOXEL_BIOS}" "${FROM_IMAGE}.av"
576patch_file "${FROM_IMAGE}.ap" FW_MAIN_A 0 "corrupted"
577patch_file "${FROM_IMAGE}.al" FW_MAIN_A 0 "corrupted"
578patch_file "${FROM_IMAGE}.av" FW_MAIN_A 0 "corrupted"
579test_update "Full update (--archive, model=link)" \
580  "${FROM_IMAGE}.al" "${LINK_BIOS}" \
581  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --model=link
582test_update "Full update (--archive, model=peppy)" \
583  "${FROM_IMAGE}.ap" "${PEPPY_BIOS}" \
584  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --model=peppy
585test_update "Full update (--archive, model=unknown)" \
586  "${FROM_IMAGE}.ap" "!Unsupported model: 'unknown'" \
587  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --model=unknown
588
589test_update "Full update (--archive, detect-model)" \
590  "${FROM_IMAGE}.ap" "${PEPPY_BIOS}" \
591  -a "${A}" --wp=0 --sys_props 0,0x10001,3 \
592  --programmer raiden_debug_spi:target=AP
593test_update "Full update (--archive, detect-model, unsupported FRID)" \
594  "${FROM_IMAGE}.av" "!Unsupported FRID: 'Google_Voxel'" \
595  -a "${A}" --wp=0 --sys_props 0,0x10001,3 \
596  --programmer raiden_debug_spi:target=AP
597
598echo "*** Test Item: Detect model (--archive, --detect-model-only)"
599"${FUTILITY}" update -a "${A}" \
600  --emulate "${FROM_IMAGE}.ap" --detect-model-only >"${TMP}/model.out"
601cmp "${TMP}/model.out" <(echo peppy)
602
603test_update "Full update (--archive, custom label with tag specified)" \
604  "${FROM_IMAGE}.al" "${LINK_BIOS}" \
605  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --model=customtip-cl
606CL_TAG="bad" PATH="${A}/bin:${PATH}" \
607  test_update "Full update (--archive, custom label, wrong image)" \
608  "${FROM_IMAGE}.al" "!The firmware image for custom label" \
609  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --debug --model=customtip
610CL_TAG="cl" PATH="${A}/bin:${PATH}" \
611  test_update "Full update (--archive, custom label, fake VPD)" \
612  "${FROM_IMAGE}.al" "${LINK_BIOS}" \
613  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --model=customtip
614
615# The output mode (without specifying signature id) for custom label would still
616# need a source (emulate) image to decide the VPD, which is not a real use case.
617echo "TEST: Output (--archive, --mode=output, custom label with tag specified)"
618TMP_OUTPUT="${TMP}/out_custom_label" && mkdir -p "${TMP_OUTPUT}"
619"${FUTILITY}" update -a "${A}" --mode=output \
620  --output_dir="${TMP_OUTPUT}" --model=customtip-cl
621cmp "${TMP_OUTPUT}/image.bin" "${LINK_BIOS}"
622
623# Custom label + Unibuild with default keys as model name
624cp -f "${TMP_TO}/rootkey" "${A}/keyset/rootkey.customtip"
625cp -f "${TMP_TO}/VBLOCK_A" "${A}/keyset/vblock_A.customtip"
626cp -f "${TMP_TO}/VBLOCK_B" "${A}/keyset/vblock_B.customtip"
627test_update "Full update (--archive, custom label, no VPD, default keys)" \
628  "${FROM_IMAGE}.al" "${LINK_BIOS}" \
629  -a "${A}" --wp=0 --sys_props 0,0x10001,3 --model=customtip
630
631# Test special programmer
632test_flashrom() {
633  echo "TEST: Full update (dummy programmer)"
634  local emu="${TMP}/emu"
635  cp -f "${FROM_IMAGE}" "${emu}"
636  "${FUTILITY}" update --programmer \
637    dummy:emulate=VARIABLE_SIZE,image="${emu}",size=8388608 \
638    -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,3 >&2
639  cmp "${emu}" "${EXPECTED}/full"
640}
641type flashrom >/dev/null 2>&1 && test_flashrom
642
643test_cbfstool() {
644  echo "TEST: Update with cbsfstool"
645  local smm="${TMP}/smm"
646  local cbfs="${TMP}/cbfs"
647  local quirk="${TMP}/quirk"
648
649  echo "SMM STORE" >"${smm}"
650  truncate -s 262144 "${smm}"
651  cp -f "${FROM_IMAGE}" "${TMP_FROM}.smm"
652  cp -f "${EXPECTED}/full" "${EXPECTED}/full_smm"
653  cbfstool "${TMP_FROM}.smm" add -r RW_LEGACY -n "smm_store" \
654    -f "${smm}" -t raw
655  cbfstool "${EXPECTED}/full_smm" add -r RW_LEGACY -n "smm_store" \
656    -f "${smm}" -t raw -b 0x1bf000
657  test_update "Legacy update (--quirks eve_smm_store)" \
658    "${TMP_FROM}.smm" "${EXPECTED}/full_smm" \
659    -i "${TO_IMAGE}" --wp=0 \
660    --quirks eve_smm_store
661
662  echo "min_platform_version=3" >"${quirk}"
663  cp -f "${TO_IMAGE}" "${TO_IMAGE}.quirk"
664  "${FUTILITY}" dump_fmap -x "${TO_IMAGE}" "BOOT_STUB:${cbfs}"
665  # Create a fake CBFS using FW_MAIN_A size.
666  truncate -s $((0x000dffc0)) "${cbfs}"
667  "${FUTILITY}" load_fmap "${TO_IMAGE}.quirk" "FW_MAIN_A:${cbfs}"
668  cbfstool "${TO_IMAGE}.quirk" add -r FW_MAIN_A -n updater_quirks \
669    -f "${quirk}" -t raw
670  test_update "Full update (failure by CBFS quirks)" \
671    "${FROM_IMAGE}" "!Need platform version >= 3 (current is 2)" \
672    -i "${TO_IMAGE}.quirk" --wp=0 --sys_props 0,0x10001,2
673}
674type cbfstool >/dev/null 2>&1 && test_cbfstool
675
676test_ifdtool() {
677  test_update "Full update (--quirks unlock_csme, IFD chipset)" \
678    "${FROM_IMAGE}" "${EXPECTED}/me_unlocked.ifd_chipset" \
679    --quirks unlock_csme -i "${TO_IMAGE}.ifd_chipset" --wp=0
680
681  test_update "Full update (--quirks unlock_csme, IFD bin path)" \
682    "${FROM_IMAGE}" "${EXPECTED}/me_unlocked.ifd_path" \
683    --quirks unlock_csme -i "${TO_IMAGE}.ifd_path" --wp=0
684
685  test_update "Full update (--unlock_me)" \
686    "${FROM_IMAGE}" "${EXPECTED}/me_unlocked.ifd_chipset" \
687    --unlock_me -i "${TO_IMAGE}.ifd_chipset" --wp=0
688
689  echo "TEST: Output (--mode=output, --quirks unlock_csme)"
690  TMP_OUTPUT="${TMP}/out_csme" && mkdir -p "${TMP_OUTPUT}"
691  mkdir -p "${TMP_OUTPUT}"
692  "${FUTILITY}" update -i "${EXPECTED}/ifd_chipset" --mode=output \
693    --output_dir="${TMP_OUTPUT}" --quirks unlock_csme
694  cmp "${TMP_OUTPUT}/image.bin" "${EXPECTED}/me_unlocked.ifd_chipset"
695}
696type ifdtool >/dev/null 2>&1 && test_ifdtool
697
698rm -rf "${TMP}"
699exit 0
700