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