summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Zieba <robertzieba@google.com>2022-05-24 13:50:17 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-06-23 16:53:58 +0000
commit6bcf9f7b7913604368cde04f681ece204779c240 (patch)
tree55f77d20a9ab3f2e22d0878eb1e4d81de94a483f
parent61971455ccb99fc6da03c493dfcda102e71aee2f (diff)
downloadvboot-6bcf9f7b7913604368cde04f681ece204779c240.tar.gz
scripts/image_signing: Add ensure_amd_psp_flags script
Currently there is no script to ensure that AMD PSP flags are set correctly in a firmware image. This commit adds ensure_amd_psps_flags.sh to handle that functionality. The script can check that certain flags are set as well as checking that certain flags are not set. BRANCH=none BUG=b:202397678 TEST=Ran script with grunt, zork, MI and skyrim images, verified that it responds correctly to PSP flag values Signed-off-by: Robert Zieba <robertzieba@google.com> Change-Id: Ie0864544b9b97704ee901d893b4d833c1ab068b9 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3526100 Reviewed-by: Mike Frysinger <vapier@chromium.org>
-rwxr-xr-xscripts/image_signing/ensure_amd_psp_flags.sh115
1 files changed, 115 insertions, 0 deletions
diff --git a/scripts/image_signing/ensure_amd_psp_flags.sh b/scripts/image_signing/ensure_amd_psp_flags.sh
new file mode 100755
index 00000000..efccb69a
--- /dev/null
+++ b/scripts/image_signing/ensure_amd_psp_flags.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+# Copyright 2022 The ChromiumOS Authors.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+# Abort on error and uninitialized variables.
+set -eu
+
+declare -A -r REQUIRED_BIT_MASKS=(
+ # Bit 58 - PSP_S0I3_RESUME_VERSTAGE - Run PSP verstage during S0i3 resume.
+ # Checks that FW images have not been tampered with when exiting S0i3.
+ [guybrush]="$((1 << 58))"
+ [zork]="0x0"
+)
+
+declare -A -r FORBIDDEN_BIT_MASKS=(
+ [guybrush]="0x0"
+ [zork]="0x0"
+)
+
+# Grunt uses an old firmware format that amdfwread cannot read.
+# See b/233787191 for skyrim.
+BOARD_IGNORE_LIST=(grunt skyrim)
+
+usage() {
+ echo "$0: Validate AMD PSP soft-fuse flags contained in a ChromeOS image." \
+ "These flags can have security implications and control debug features."
+ echo "Usage $0 <board> <image>"
+}
+
+main() {
+ if [[ $# -ne 2 ]]; then
+ usage
+ exit 1
+ fi
+
+ local board="$1"
+ local image="$2"
+
+ # Check the ignore list.
+ if [[ " ${BOARD_IGNORE_LIST[*]} " == *" ${board} "* ]]; then
+ echo "Skipping ignore-listed board ${board}"
+ exit 0
+ fi
+
+ # Mount the image.
+ local loopdev rootfs
+ if [[ -d "${image}" ]]; then
+ rootfs="${image}"
+ else
+ rootfs="$(make_temp_dir)"
+ loopdev="$(loopback_partscan "${image}")"
+ mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}"
+ fi
+
+ local firmware_bundle shellball_dir
+ firmware_bundle="${rootfs}/usr/sbin/chromeos-firmwareupdate"
+ shellball_dir="$(make_temp_dir)"
+
+ # Get the board specific bit masks.
+ local required_bit_mask forbidden_bit_mask
+
+ if [[ ! -v "REQUIRED_BIT_MASKS[${board}]" ]]; then
+ die "Missing PSP required bit mask set for ${board}"
+ fi
+
+ if [[ ! -v "FORBIDDEN_BIT_MASKS[${board}]" ]]; then
+ die "Missing PSP forbidden bit mask set for ${board}"
+ fi
+
+ required_bit_mask="${REQUIRED_BIT_MASKS[${board}]}"
+ forbidden_bit_mask="${FORBIDDEN_BIT_MASKS[${board}]}"
+
+ # Extract our firmware.
+ if ! extract_firmware_bundle "${firmware_bundle}" "${shellball_dir}"; then
+ die "Failed to extract firmware bundle"
+ fi
+
+ # Find our images and check the soft-fuse bits in each.
+ declare -a images
+ readarray -t images < <(find "${shellball_dir}" -iname 'bios-*')
+
+ local image
+ for image in "${images[@]}"; do
+ local soft_fuse soft_fuse_output forbidden_set missing_set
+ if ! soft_fuse_output="$(amdfwread --soft-fuse "${image}")"; then
+ die "'amdfwread --soft-fuse ${image}' failed"
+ fi
+
+ # Output format from amdfwread is Soft-fuse:value, where value is in hex.
+ soft_fuse="$(echo "${soft_fuse_output}" | \
+ sed -E -n 's/Soft-fuse:(0[xX][0-9a-fA-F]+)/\1/p')"
+ if [[ -z "${soft_fuse}" ]]; then
+ die "Could not parse Soft-fuse value from output: '${soft_fuse_output}'"
+ fi
+
+ forbidden_set="$((soft_fuse & forbidden_bit_mask))"
+ if [[ "${forbidden_set}" != 0 ]]; then
+ local forbidden_hex
+ forbidden_hex="$(printf %#x "${forbidden_set}")"
+ die "${image}: Forbidden AMD PSP soft-fuse bits set: ${forbidden_hex}"
+ fi
+
+ missing_set="$((~soft_fuse & required_bit_mask))"
+ if [[ "${missing_set}" != 0 ]]; then
+ local missing_hex
+ missing_hex="$(printf %#x "${missing_set}")"
+ die "${image}: Required AMD PSP soft-fuse bits not set: ${missing_hex}"
+ fi
+ done
+}
+main "$@"