blob: 9096ba31bfe1cb1acc7606951967e0598bd73104 [file] [log] [blame]
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright 2021 Google LLC
# Replace fallback/payload with U-Boot in the image
# This uses cbfstool which prints a long usage message on any error. Look at the
# top for the error message.
# TODO: Consider using binman to do this. At present it does not support
# inferring an fdtmap from a Chromium OS image.
# Use this one if you don't want output from coreboot
old=~/image-coral.bin
# Use this one if you do
#old=~/image-coral.dev.bin
# Location of developer keys, for signing
devkeys_dir=cros/data/devkeys
# Output filename
new=cb.bin
# Input directory
ub=/tmp/b/chromeos_coreboot
# Name of file to replace
name=fallback/payload
# Run cbfstool and die if something goes wrong
do_cbfstool() {
local output
output=$(cbfstool "$@" 2>&1)
if [ $? != 0 ]; then
echo here
die "Failed cbfstool invocation: cbfstool $@\n${output}"
fi
printf "${output}"
}
# Delete various locales to create plenty of space for U-Boot, etc.
# This is not strictly necessary, but we cannot know where $name appears in
# the image, so even a size increase of 20 bytes will not be supported, since
# cbfstool does not support moving existing files.
# Args:
# $1: Filename of image to update
delete_locales() {
local rom="$1"
for f in locale_tr.bin \
locale_bg.bin \
locale_hr.bin \
locale_nl.bin \
locale_ro.bin \
locale_es.bin \
locale_ja.bin \
locale_el.bin \
locale_pt-BR.bin \
locale_de.bin \
locale_lt.bin \
locale_hi.bin \
locale_vi.bin \
locale_ca.bin \
locale_hu.bin \
locale_sr.bin \
locale_pt-PT.bin \
locale_fi.bin \
locale_cs.bin \
locale_he.bin \
locale_fr.bin \
locale_id.bin \
locale_ta.bin \
locale_bn.bin \
locale_th.bin \
locale_ar.bin \
locale_it.bin \
locale_pl.bin \
locale_lv.bin \
locale_mr.bin \
locale_es-419.bin \
locale_et.bin \
locale_ms.bin \
locale_nb.bin \
locale_zh-CN.bin \
locale_ko.bin \
locale_fil.bin \
locale_da.bin \
locale_ru.bin \
locale_uk.bin \
locale_sl.bin \
locale_te.bin \
locale_sk.bin \
locale_gu.bin \
locale_sv.bin \
locale_kn.bin \
locale_ml.bin \
locale_fa.bin \
locale_zh-TW.bin \
vbt-astronaut.bin vbt-epaulette.bin vbt-babytiger.bin \
vbt-babymega.bin vbt-nasher.bin vbt-rabbid_rugged.bin; do
do_cbfstool $rom remove -n $f
done
}
# Process one region of the image
# Removes unwanted files and adds in the u-boot.bin binary
# Args:
# $1: Filename of image to update
# $2: region params ('' for recovery, '-r FW_MAIN_A' for firmare a)
do_part() {
local fw_image="$1"
local region="$2"
do_cbfstool $fw_image remove $region -n $name
# Drop the unused bootblock in recovery to add space
if [ -z "$region" ]; then
do_cbfstool $fw_image remove $region -n bootblock
delete_locales $fw_image
fi
do_cbfstool $fw_image expand $region
if ! do_cbfstool $fw_image add-flat-binary $region -n $name \
-f $ub/u-boot.bin -c lzma -l 0x1110000 -e 0x1110000; then
do_cbfstool $fw_image print $region
fi
}
# Size the image and update signature region (VBLOCK_A/B)
# Args:
# $1: Filename of image to update
# $2: Directory containing (dev) keys
# $3: Slot to update (either "A" or "B")
sign_region() {
local fw_image="$1"
local keydir="$2"
local slot="$3"
local tmpfile=`mktemp`
local cbfs=FW_MAIN_${slot}
local vblock=VBLOCK_${slot}
do_cbfstool ${fw_image} read -r ${cbfs} -f ${tmpfile}
# Read the contents of $cbfs and get the last line, e.g.:
# (empty) 0x121c80 null 0x28 0x34e314 0x34e33c
# Then use sed to get its offset in the file (e.g. 0x121c80)
local size=$(do_cbfstool ${fw_image} print -k -r ${cbfs} | \
tail -1 | \
sed "/(empty).*null/ s,^(empty)[[:space:]]\(0x[0-9a-f]*\)\tnull\t.*$,\1,")
size=$(printf "%d" ${size})
# If the last entry is called "(empty)" and of type "null", remove it
# from the section so it isn't part of the signed data, to improve boot
# speed, if (as often happens) there's a large unused suffix.
if [ -n "${size}" ] && [ ${size} -gt 0 ]; then
head -c ${size} ${tmpfile} > ${tmpfile}.2
mv ${tmpfile}.2 ${tmpfile}
# Use 255 (aka 0xff) as the filler, this greatly reduces
# memory areas which need to be programmed for spi flash
# chips, because the erase value is 0xff.
do_cbfstool ${fw_image} write --force -u -i 255 \
-r ${cbfs} -f ${tmpfile}
fi
futility vbutil_firmware \
--vblock ${tmpfile}.out \
--keyblock ${keydir}/firmware.keyblock \
--signprivate ${keydir}/firmware_data_key.vbprivk \
--version 1 \
--fv ${tmpfile} \
--kernelkey ${keydir}/kernel_subkey.vbpubk \
--flags 0
# Write the signature to the vblock region
do_cbfstool ${fw_image} write -u -i 255 -r ${vblock} -f ${tmpfile}.out
rm -f ${tmpfile} ${tmpfile}.out
}
# Add signatures for the updated image, to both A and B
# Args:
# $1: Filename of image to update
# $2: Directory containing (dev) keys
sign_image() {
local fw_image=$1
local keydir=$2
sign_region "${fw_image}" "${keydir}" A
sign_region "${fw_image}" "${keydir}" B
}
# Add the Memory-Reference-Code (MRC) cache data to speed up the first boot
# This saves about 21 seconds on coral`
# Args:
# $1: Filename of image to update
add_mrc() {
local fw_image=$1
# These files can be created from the image with:
# dump_fmap rom.bin -x RECOVERY_MRC_CACHE RW_MRC_CACHE RW_VAR_MRC_CACHE
do_cbfstool $fw_image write -r RW_MRC_CACHE -f RW_MRC_CACHE
do_cbfstool $fw_image write -r RW_VAR_MRC_CACHE -f RW_VAR_MRC_CACHE
do_cbfstool $fw_image write -r RECOVERY_MRC_CACHE -f RECOVERY_MRC_CACHE
}
# Start with the original image
cp $old $new
# Do read/write and recovery
do_part $new "-r FW_MAIN_A"
do_part $new "-r FW_MAIN_B"
do_part $new
# Sign the image with dev keys for A and B, so it will boot
sign_image $new "${devkeys_dir}"
# Optionally, put valid MRC-cache data in there for a faster boot
# add_mrc
if [ -f RW_MRC_CACHE ]; then
add_mrc $new
fi