• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ver_file
41  local ecrw_comp_type
42  local ecrw_ver
43  local apro_ver
44  local aprw_ver
45  temp_dir=$(mktemp -d)
46  ecrw_file="${temp_dir}/ecrw"
47  futility dump_fmap -x "${ec_file}" "RW_FW:${ecrw_file}" >/dev/null
48  info "EC RW extracted to ${ecrw_file}"
49
50  ecrw_hash_file="${temp_dir}/ecrw.hash"
51  openssl dgst -sha256 -binary "${ecrw_file}" > "${ecrw_hash_file}"
52  info "EC RW hash saved to ${ecrw_hash_file}"
53
54  ecrw_ver_file="${temp_dir}/ecrw.version"
55  futility dump_fmap -x "${ec_file}" "RW_FWID:${ecrw_ver_file}" >/dev/null
56
57  for region in "${FMAP_REGIONS[@]}"
58  do
59    info="$(cbfstool "${ap_file}" print -r "${region}" -k -v \
60      | grep -m 1 "^${CBFS_ECRW_NAME}\s")"
61    ecrw_comp_type="$(cut -f7- <<< "${info}" | grep -o '\<comp\>:\w*' \
62      | cut -d: -f2)"
63    ecrw_comp_type=${ecrw_comp_type:-none}
64    cbfstool "${ap_file}" remove -r "${region}" -n "${CBFS_ECRW_NAME}"
65    cbfstool "${ap_file}" remove -r "${region}" -n "${CBFS_ECRW_HASH_NAME}"
66    cbfstool "${ap_file}" remove -r "${region}" -n "${CBFS_ECRW_VERSION_NAME}" \
67      || warn "${CBFS_ECRW_VERSION_NAME} not found, but will be added"
68    # TODO(b/307788351): Update ecrw.config. Right now the config info cannot
69    # be obtained from ec.bin.
70    cbfstool "${ap_file}" remove -r "${region}" \
71      -n "${CBFS_ECRW_CONFIG_NAME_NAME}" || true
72    cbfstool "${ap_file}" expand -r "${region}"
73    cbfstool "${ap_file}" add -r "${region}" -t raw \
74      -c "${ecrw_comp_type}" -f "${ecrw_file}" -n "${CBFS_ECRW_NAME}"
75    cbfstool "${ap_file}" add -r "${region}" -t raw \
76      -c none -f "${ecrw_hash_file}" -n "${CBFS_ECRW_HASH_NAME}"
77    cbfstool "${ap_file}" add -r "${region}" -t raw \
78      -c none -f "${ecrw_ver_file}" -n "${CBFS_ECRW_VERSION_NAME}"
79  done
80
81  local keyset
82  for keyset in /usr/share/vboot/devkeys "${SCRIPT_BASE}/../../tests/devkeys"; do
83    [[ -d "${keyset}" ]] && break
84  done
85
86  # 'futility sign' will call 'cbfstool truncate' if needed
87  futility sign "${ap_file}" --keyset "${keyset}"
88
89  ecrw_ver=$(futility update --manifest -e "${ec_file}" \
90    | jq -r '.default.ec.versions.rw')
91  apro_ver=$(futility update --manifest -i "${ap_file}" \
92    | jq -r '.default.host.versions.ro')
93  aprw_ver=$(futility update --manifest -i "${ap_file}" \
94    | jq -r '.default.host.versions.rw')
95  info "${CBFS_ECRW_NAME} (${ecrw_ver}) swapped in ${ap_file} (RO:${apro_ver}, RW:${aprw_ver})"
96  info "Done"
97}
98
99main() {
100  if [[ -z "${FLAGS_image}" ]]; then
101    flags_help
102    die "-i or --image required."
103  fi
104  if [[ -z "${FLAGS_ec}" ]]; then
105    flags_help
106    die "-e or --ec required."
107  fi
108
109  swap_ecrw "${FLAGS_image}" "${FLAGS_ec}"
110}
111
112main "$@"
113