summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xutility/chromeos-tpm-recovery89
1 files changed, 71 insertions, 18 deletions
diff --git a/utility/chromeos-tpm-recovery b/utility/chromeos-tpm-recovery
index e2b0a8de..28a8fa3d 100755
--- a/utility/chromeos-tpm-recovery
+++ b/utility/chromeos-tpm-recovery
@@ -16,6 +16,8 @@ awk=/usr/bin/awk
initctl=/sbin/initctl
daemon_was_running=
err=0
+secdata_firmware=0x1007
+secdata_kernel=0x1008
tpm2_target() {
# This is not an ideal way to tell if we are running on a tpm2 target, but
@@ -27,6 +29,32 @@ tpm2_target() {
fi
}
+use_v0_secdata_kernel() {
+ local fwid=$(crossystem ro_fwid)
+ local major=$(printf "$fwid" | cut -d. -f2)
+ local minor=$(printf "$fwid" | cut -d. -f3)
+
+ # TPM1 firmware never supports the v1 kernel space format.
+ if ! tpm2_target; then
+ return 0
+ fi
+
+ # First some sanity checks: X -eq X checks that X is a number. cut may return
+ # the whole string if no delimiter found, so major != minor checks that the
+ # version was at least somewhat correctly formatted.
+ if [ $major -eq $major ] && [ $minor -eq $minor ] && [ $major -ne $minor ]; then
+ # Now what we really care about: is this firmware older than CL:2041695?
+ if [ $major -lt 12953 ]; then
+ return 0
+ else
+ return 1
+ fi
+ else
+ log "Cannot parse FWID. Assuming local build that supports v1 kernel space."
+ return 1
+ fi
+}
+
log() {
echo "$*"
}
@@ -63,27 +91,49 @@ tpm_clear_and_reenable () {
$tpmc activate
}
-reset_space () {
+write_space () {
+ # do not quote "$2", as we mean to expand it here
+ if ! $tpmc write $1 $2; then
+ log_error "writing to $1 failed"
+ else
+ log "$1 written successfully"
+ fi
+}
+
+reset_ro_space () {
local index=$1
- local permissions=$2
- local size=$3
- local bytes="$4"
+ local bytes="$2"
+ local size=$(printf "$bytes" | wc -w)
+ local permissions=0x8001
- if ! tpm2_target; then
- # definespace is not yet supported for tpm2 (crosbug.com/p/59361), let's
- # just rely on the firmware having created the required spaces for now.
+ if tpm2_target; then
+ log "Cannot redefine RO space for TPM2 (b/140958855). Let's just hope it looks good..."
+ else
if ! $tpmc definespace $index $size $permissions; then
- log "could not redefine space $index"
- return 1
+ log_error "could not redefine RO space $index"
+ # try writing it anyway, just in case it works...
fi
fi
- # do not quote "$bytes", as we mean to expand it here
- if ! $tpmc write $index $bytes; then
- log "writing to $index failed"
- return 1
+ write_space $index "$bytes"
+}
+
+reset_rw_space () {
+ local index=$1
+ local bytes="$2"
+ local size=$(printf "$bytes" | wc -w)
+ local permissions=0x1
+
+ if tpm2_target; then
+ permissions=0x40050001
+ fi
+
+ if ! $tpmc definespace $index $size $permissions; then
+ log_error "could not redefine RW space $index"
+ # try writing it anyway, just in case it works...
fi
- log "space $index was recreated successfully"
+
+ write_space $index "$bytes"
}
restart_daemon_if_needed() {
@@ -161,10 +211,13 @@ fi
tpm_clear_and_reenable
# Reset firmware and kernel spaces to default (rollback version 1/1)
-reset_space 0x1007 0x8001 0xa "02 00 01 00 01 00 00 00 00 4f" || \
- log_error "could not fix firmware space"
-reset_space 0x1008 0x1 0xd "02 4c 57 52 47 01 00 01 00 00 00 00 55" || \
- log_error "could not fix kernel space"
+reset_ro_space $secdata_firmware "02 0 1 0 1 0 0 0 0 4f"
+
+if use_v0_secdata_kernel; then
+ reset_rw_space $secdata_kernel "02 4c 57 52 47 1 0 1 0 0 0 0 55"
+else
+ reset_rw_space $secdata_kernel "10 28 0c 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
+fi
restart_daemon_if_needed