blob: f556322f4035855eef408db6a5bcc29ebffe0bed [file] [log] [blame]
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: cros-ec-merge-ro.eclass
# Chromium OS Firmware Team
# Please report bugs via (with label Build)
# @BLURB: helper eclass for merging RO firmware into EC firmware
# Merges a specific RO version of firmware into the firmware that was built
# during the build.
# NOTE: When making changes to this class, make sure to modify all the -9999
# ebuilds that inherit it to work around
if [[ -z "${_ECLASS_CROS_EC_MERGE_RO}" ]]; then
# Check for EAPI 6+
case "${EAPI:-0}" in
0|1|2|3|4|5|6) die "unsupported EAPI (${EAPI}) in eclass (${ECLASS})" ;;
*) ;;
inherit cros-ec-utils
# Make sure that private files ebuild has run since it creates the symlink
# used in the src_install step below.
# We also use cros_config_host below.
# @FUNCTION: cros-ec-merge-ro_do_merge
# @USAGE: <RO firmware path> <RW firmware path>
# Copy RO firmware from firmware specified in <RO firmware path> and RW firmware
# from <RW firmware path> into a new file. Returns the filename
# of the new file.
cros-ec-merge-ro_do_merge() {
local ec_ro="$1"
local ec_rw="$2"
einfo "Merging RO firmware"
# Print RO and RW versions.
local ro_version_string
local rw_version_string
ro_version_string="$(cros-ec-utils-get_firmware_ro_version "${ec_ro}" || die)"
rw_version_string="$(cros-ec-utils-get_firmware_rw_version "${ec_rw}" || die)"
einfo "Using firmware RO version: ${ro_version_string}"
einfo "Using firmware RW version: ${rw_version_string}"
# Use RW firmware version as file name.
local new_file="${rw_version_string}.bin"
# fmap_rw_section[0]="EC_RW"
# fmap_rw_section[1]=offset
# fmap_rw_section[2]=size (decimal)
local fmap_rw_section
IFS=" " read -r -a fmap_rw_section <<< "$(dump_fmap -p "${ec_ro}" EC_RW \
|| die)"
# Inject RW into the existing RO file.
einfo "Merging files..."
cp "${ec_ro}" "${new_file}" || die
dd if="${ec_rw}" of="${new_file}" \
bs=1 skip="${fmap_rw_section[1]}" seek="${fmap_rw_section[1]}" \
count="${fmap_rw_section[2]}" conv=notrunc status=none || die
echo "${new_file}"
# @FUNCTION: cros-ec-merge-ro_src_install
# Copy pre-built RO firmware into RW firmware that was built.
cros-ec-merge-ro_src_install() {
debug-print-function "${FUNCNAME[0]}" "$@"
# Use our specified board.
local target="${FIRMWARE_EC_BOARD}"
local firmware_bin_dir="$(readlink -f \
if [[ ! -d "${firmware_bin_dir}" ]]; then
einfo "No RO firmware found. This is expected in a public build."
return 0
# If cros_config provides RO firmware version, then use it. The RO firmware
# version does not have to be specified, in which case cros_config_host will
# exit with success and not print any firmware version.
# In that case, we want to use the "default" RO firmware, so validate
# that there is exactly one RO binary.
local fw_target="${target%%_fp}"
local ro_version
ro_version="$(cros_config_host \
get-fpmcu-firmware-ro-version "${fw_target}" || die)"
local ro_fw
if [[ -n ${ro_version} ]]; then
einfo "RO version specified: ${ro_version}."
ro_fw="$(ls "${firmware_bin_dir}/${fw_target}/RO/${ro_version}.bin" || die)"
einfo "No RO version specified; using default."
local ro_fw_count=0
if [[ ${ro_fw_count} -ne 1 ]]; then
eerror "Incorrect number of RO firmware files found: ${ro_fw_count}"
local rw_fw="${WORKDIR}/build_${target}/${target}/ec.bin"
local merged_fw="$(cros-ec-merge-ro_do_merge "${ro_fw}" "${rw_fw}")"
cp "${merged_fw}" "${rw_fw}" || die