#!/bin/bash -eux # Copyright 2018 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. me=${0##*/} TMP="$me.tmp" # Test --sys_props (primitive test needed for future updating tests). test_sys_props() { ! "${FUTILITY}" --debug update --sys_props "$*" | sed -n 's/.*property\[\(.*\)].value = \(.*\)/\1,\2,/p' | tr '\n' ' ' } test "$(test_sys_props "1,2,3")" = "0,1, 1,2, 2,3, " test "$(test_sys_props "1 2 3")" = "0,1, 1,2, 2,3, " test "$(test_sys_props "1, 2,3 ")" = "0,1, 1,2, 2,3, " test "$(test_sys_props " 1,, 2")" = "0,1, 2,2, " test "$(test_sys_props " , 4,")" = "1,4, " test_quirks() { ! "${FUTILITY}" --debug update --quirks "$*" | sed -n 's/.*Set quirk \(.*\) to \(.*\)./\1,\2/p' | tr '\n' ' ' } test "$(test_quirks "enlarge_image")" = "enlarge_image,1 " test "$(test_quirks "enlarge_image=2")" = "enlarge_image,2 " test "$(test_quirks " enlarge_image, enlarge_image=2")" = \ "enlarge_image,1 enlarge_image,2 " # Test data files LINK_BIOS="${SCRIPTDIR}/data/bios_link_mp.bin" PEPPY_BIOS="${SCRIPTDIR}/data/bios_peppy_mp.bin" # Work in scratch directory cd "$OUTDIR" set -o pipefail # In all the test scenario, we want to test "updating from PEPPY to LINK". TO_IMAGE=${TMP}.src.link FROM_IMAGE=${TMP}.src.peppy TO_HWID="X86 LINK TEST 6638" FROM_HWID="X86 PEPPY TEST 4211" cp -f ${LINK_BIOS} ${TO_IMAGE} cp -f ${PEPPY_BIOS} ${FROM_IMAGE} patch_file() { local file="$1" local section="$2" local section_offset="$3" local data="$4" # NAME OFFSET SIZE local fmap_info="$(${FUTILITY} dump_fmap -p ${file} ${section})" local base="$(echo "${fmap_info}" | sed 's/^[^ ]* //; s/ [^ ]*$//')" local offset=$((base + section_offset)) echo "offset: ${offset}" printf "${data}" | dd of="${file}" bs=1 seek="${offset}" conv=notrunc } # PEPPY and LINK have different platform element ("Google_Link" and # "Google_Peppy") in firmware ID so we want to hack them by changing # "Google_" to "Google.". patch_file ${TO_IMAGE} RW_FWID_A 0 Google. patch_file ${TO_IMAGE} RW_FWID_B 0 Google. patch_file ${TO_IMAGE} RO_FRID 0 Google. patch_file ${FROM_IMAGE} RW_FWID_A 0 Google. patch_file ${FROM_IMAGE} RW_FWID_B 0 Google. patch_file ${FROM_IMAGE} RO_FRID 0 Google. unpack_image() { local folder="${TMP}.$1" local image="$2" mkdir -p "${folder}" (cd "${folder}" && ${FUTILITY} dump_fmap -x "../${image}") ${FUTILITY} gbb -g --rootkey="${folder}/rootkey" "${image}" } # Unpack images so we can prepare expected results by individual sections. unpack_image "to" "${TO_IMAGE}" unpack_image "from" "${FROM_IMAGE}" # Hack FROM_IMAGE so it has same root key as TO_IMAGE (for RW update). FROM_DIFFERENT_ROOTKEY_IMAGE="${FROM_IMAGE}2" cp -f "${FROM_IMAGE}" "${FROM_DIFFERENT_ROOTKEY_IMAGE}" "${FUTILITY}" gbb -s --rootkey="${TMP}.to/rootkey" "${FROM_IMAGE}" # Hack for quirks cp -f "${FROM_IMAGE}" "${FROM_IMAGE}.large" truncate -s $((8388608 * 2)) "${FROM_IMAGE}.large" # Generate expected results. cp -f "${TO_IMAGE}" "${TMP}.expected.full" cp -f "${FROM_IMAGE}" "${TMP}.expected.rw" cp -f "${FROM_IMAGE}" "${TMP}.expected.a" cp -f "${FROM_IMAGE}" "${TMP}.expected.b" cp -f "${FROM_IMAGE}" "${TMP}.expected.legacy" "${FUTILITY}" gbb -s --hwid="${FROM_HWID}" "${TMP}.expected.full" "${FUTILITY}" load_fmap "${TMP}.expected.full" \ RW_VPD:${TMP}.from/RW_VPD \ RO_VPD:${TMP}.from/RO_VPD "${FUTILITY}" load_fmap "${TMP}.expected.rw" \ RW_SECTION_A:${TMP}.to/RW_SECTION_A \ RW_SECTION_B:${TMP}.to/RW_SECTION_B \ RW_SHARED:${TMP}.to/RW_SHARED \ RW_LEGACY:${TMP}.to/RW_LEGACY "${FUTILITY}" load_fmap "${TMP}.expected.a" \ RW_SECTION_A:${TMP}.to/RW_SECTION_A "${FUTILITY}" load_fmap "${TMP}.expected.b" \ RW_SECTION_B:${TMP}.to/RW_SECTION_B "${FUTILITY}" load_fmap "${TMP}.expected.legacy" \ RW_LEGACY:${TMP}.to/RW_LEGACY cp -f "${TMP}.expected.full" "${TMP}.expected.large" dd if=/dev/zero bs=8388608 count=1 | tr '\000' '\377' >>"${TMP}.expected.large" cp -f "${TMP}.expected.full" "${TMP}.expected.me_unlocked" patch_file "${TMP}.expected.me_unlocked" SI_DESC 128 \ "\x00\xff\xff\xff\x00\xff\xff\xff\x00\xff\xff\xff" test_update() { local test_name="$1" local emu_src="$2" local expected="$3" local error_msg="${expected#!}" local msg shift 3 cp -f "${emu_src}" "${TMP}.emu" echo "*** Test Item: ${test_name}" if [ "${error_msg}" != "${expected}" ] && [ -n "${error_msg}" ]; then msg="$(! "${FUTILITY}" update --emulate "${TMP}.emu" "$@" 2>&1)" echo "${msg}" | grep -qF -- "${error_msg}" else "${FUTILITY}" update --emulate "${TMP}.emu" "$@" cmp "${TMP}.emu" "${expected}" fi } # --sys_props: mainfw_act, tpm_fwver, is_vboot2, platform_ver, [wp_hw, wp_sw] # tpm_fwver = . # TO_IMAGE is signed with data key version = 1, firmware version = 4 => 0x10004. # Test Full update. test_update "Full update" \ "${FROM_IMAGE}" "${TMP}.expected.full" \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 test_update "Full update (incompatible platform)" \ "${FROM_IMAGE}" "!platform is not compatible" \ -i "${LINK_BIOS}" --wp=0 --sys_props 0,0x10001,1 test_update "Full update (TPM Anti-rollback: data key)" \ "${FROM_IMAGE}" "!Data key version rollback detected (2->1)" \ -i "${TO_IMAGE}" --wp=0 --sys_props 1,0x20001,1 test_update "Full update (TPM Anti-rollback: kernel key)" \ "${FROM_IMAGE}" "!Firmware version rollback detected (5->4)" \ -i "${TO_IMAGE}" --wp=0 --sys_props 1,0x10005,1 # Test RW-only update. test_update "RW update" \ "${FROM_IMAGE}" "${TMP}.expected.rw" \ -i "${TO_IMAGE}" --wp=1 --sys_props 0,0x10001,1 test_update "RW update (incompatible platform)" \ "${FROM_IMAGE}" "!platform is not compatible" \ -i "${LINK_BIOS}" --wp=1 --sys_props 0,0x10001,1 test_update "RW update (incompatible rootkey)" \ "${FROM_DIFFERENT_ROOTKEY_IMAGE}" "!RW not signed by same RO root key" \ -i "${TO_IMAGE}" --wp=1 --sys_props 0,0x10001,1 test_update "RW update (TPM Anti-rollback: data key)" \ "${FROM_IMAGE}" "!Data key version rollback detected (2->1)" \ -i "${TO_IMAGE}" --wp=1 --sys_props 1,0x20001,1 test_update "RW update (TPM Anti-rollback: kernel key)" \ "${FROM_IMAGE}" "!Firmware version rollback detected (5->4)" \ -i "${TO_IMAGE}" --wp=1 --sys_props 1,0x10005,1 # Test Try-RW update (vboot2). test_update "RW update (A->B)" \ "${FROM_IMAGE}" "${TMP}.expected.b" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 0,0x10001,1 test_update "RW update (B->A)" \ "${FROM_IMAGE}" "${TMP}.expected.a" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 1,0x10001,1 test_update "RW update -> fallback to RO+RW Full update" \ "${FROM_IMAGE}" "${TMP}.expected.full" \ -i "${TO_IMAGE}" -t --wp=0 --sys_props 1,0x10002,1 test_update "RW update (incompatible platform)" \ "${FROM_IMAGE}" "!platform is not compatible" \ -i "${LINK_BIOS}" -t --wp=1 --sys_props 0x10001,1 test_update "RW update (incompatible rootkey)" \ "${FROM_DIFFERENT_ROOTKEY_IMAGE}" "!RW not signed by same RO root key" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 0,0x10001,1 test_update "RW update (TPM Anti-rollback: data key)" \ "${FROM_IMAGE}" "!Data key version rollback detected (2->1)" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 1,0x20001,1 test_update "RW update (TPM Anti-rollback: kernel key)" \ "${FROM_IMAGE}" "!Firmware version rollback detected (5->4)" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 1,0x10005,1 test_update "RW update -> fallback to RO+RW Full update (TPM Anti-rollback)" \ "${TO_IMAGE}" "!Firmware version rollback detected (4->2)" \ -i "${FROM_IMAGE}" -t --wp=0 --sys_props 1,0x10004,1 # Test Try-RW update (vboot1). test_update "RW update (vboot1, A->B)" \ "${FROM_IMAGE}" "${TMP}.expected.b" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 0,0 --sys_props 0,0x10001,0 test_update "RW update (vboot1, B->B)" \ "${FROM_IMAGE}" "${TMP}.expected.b" \ -i "${TO_IMAGE}" -t --wp=1 --sys_props 1,0 --sys_props 0,0x10001,0 # Test legacy update test_update "Legacy update" \ "${FROM_IMAGE}" "${TMP}.expected.legacy" \ -i "${TO_IMAGE}" --mode=legacy # Test quirks test_update "Full update (wrong size)" \ "${FROM_IMAGE}.large" "!Image size is different" \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 test_update "Full update (--quirks enlarge_image)" \ "${FROM_IMAGE}.large" "${TMP}.expected.large" --quirks enlarge_image \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 test_update "Full update (--quirks unlock_me_for_update)" \ "${FROM_IMAGE}" "${TMP}.expected.me_unlocked" \ --quirks unlock_me_for_update \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 test_update "Full update (failure by --quirks min_platform_version)" \ "${FROM_IMAGE}" "!Need platform version >= 3 (current is 2)" \ --quirks min_platform_version=3 \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1,2 test_update "Full update (--quirks min_platform_version)" \ "${FROM_IMAGE}" "${TMP}.expected.full" \ --quirks min_platform_version=3 \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1,3