xref: /aosp_15_r20/external/vboot_reference/scripts/image_signing/swap_ec_rw (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1#!/bin/bash
2#
3# Copyright 2024 The ChromiumOS Authors
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7SCRIPT_BASE="$(dirname "$0")"
8. "$SCRIPT_BASE/common_minimal.sh"
9load_shflags || exit 1
10
11FLAGS_HELP="
12Swap the EC RW (ecrw) within an AP firmware (BIOS) image.
13"
14
15# Flags.
16DEFINE_string image "" "The AP firmware file (e.g 'image-steelix.bin') to swap out ecrw" i
17DEFINE_string ec "" "The EC firmware file (e.g 'ec.bin')" e
18
19# Parse command line.
20FLAGS "$@" || exit 1
21eval set -- "${FLAGS_ARGV}"
22
23# Only after this point should you enable `set -e` as shflags does not work
24# when that is turned on first.
25set -e
26
27FMAP_REGIONS=( "FW_MAIN_A" "FW_MAIN_B" )
28CBFS_ECRW_NAME="ecrw"
29CBFS_ECRW_HASH_NAME="ecrw.hash"
30CBFS_ECRW_VERSION_NAME="ecrw.version"
31CBFS_ECRW_CONFIG_NAME="ecrw.config"
32
33swap_ecrw() {
34  local ap_file=$1
35  local ec_file=$2
36  local temp_dir
37  local info
38  local ecrw_file
39  local ecrw_hash_file
40  local ecrw_version_file
41  local ecrw_comp_type
42  local ecrw_version
43  temp_dir=$(mktemp -d)
44  ecrw_file="${temp_dir}/ecrw"
45  futility dump_fmap -x "${ec_file}" "RW_FW:${ecrw_file}" >/dev/null
46  info "EC RW extracted to ${ecrw_file}"
47
48  ecrw_hash_file="${temp_dir}/ecrw.hash"
49  openssl dgst -sha256 -binary "${ecrw_file}" > "${ecrw_hash_file}"
50  info "EC RW hash saved to ${ecrw_hash_file}"
51
52  ecrw_version_file="${temp_dir}/ecrw.version"
53  futility dump_fmap -x "${ec_file}" "RW_FWID:${ecrw_version_file}" >/dev/null
54
55  for region in "${FMAP_REGIONS[@]}"
56  do
57    info="$(cbfstool "${ap_file}" print -r "${region}" -k -v \
58      | grep -m 1 "^${CBFS_ECRW_NAME}\s")"
59    ecrw_comp_type="$(cut -f7- <<< "${info}" | grep -o '\<comp\>:\w*' \
60      | cut -d: -f2)"
61    ecrw_comp_type=${ecrw_comp_type:-none}
62    cbfstool "${ap_file}" remove -r "${region}" -n "${CBFS_ECRW_NAME}"
63    cbfstool "${ap_file}" remove -r "${region}" -n "${CBFS_ECRW_HASH_NAME}"
64    cbfstool "${ap_file}" remove -r "${region}" -n "${CBFS_ECRW_VERSION_NAME}" \
65      || warn "${CBFS_ECRW_VERSION_NAME} not found, but will be added"
66    # TODO(b/307788351): Update ecrw.config. Right now the config info cannot
67    # be obtained from ec.bin.
68    cbfstool "${ap_file}" remove -r "${region}" \
69      -n "${CBFS_ECRW_CONFIG_NAME_NAME}" || true
70    cbfstool "${ap_file}" expand -r "${region}"
71    cbfstool "${ap_file}" add -r "${region}" -t raw \
72      -c "${ecrw_comp_type}" -f "${ecrw_file}" -n "${CBFS_ECRW_NAME}"
73    cbfstool "${ap_file}" add -r "${region}" -t raw \
74      -c none -f "${ecrw_hash_file}" -n "${CBFS_ECRW_HASH_NAME}"
75    cbfstool "${ap_file}" add -r "${region}" -t raw \
76      -c none -f "${ecrw_version_file}" -n "${CBFS_ECRW_VERSION_NAME}"
77  done
78
79  local keyset
80  for keyset in /usr/share/vboot/devkeys "${SCRIPT_BASE}/../../tests/devkeys"; do
81    [[ -d "${keyset}" ]] && break
82  done
83
84  # 'futility sign' will call 'cbfstool truncate' if needed
85  futility sign "${ap_file}" --keyset "${keyset}"
86
87  ecrw_version=$(futility update --manifest -e "${ec_file}" \
88    | jq -r '.default.ec.versions.rw')
89  info "${CBFS_ECRW_NAME} (${ecrw_version}) swapped in ${ap_file}"
90  info "Done"
91}
92
93main() {
94  if [[ -z "${FLAGS_image}" ]]; then
95    flags_help
96    die "-i or --image required."
97  fi
98  if [[ -z "${FLAGS_ec}" ]]; then
99    flags_help
100    die "-e or --ec required."
101  fi
102
103  swap_ecrw "${FLAGS_image}" "${FLAGS_ec}"
104}
105
106main "$@"
107