blob: ad72a70e640553cb5a7a23763cba8a5fb93e648c [file] [log] [blame]
Gaurav Shah605500b2011-01-18 12:00:50 -08001#!/bin/sh
Gaurav Shahaa22a5d2010-07-27 10:52:07 -07002
3# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# Script to resign a firmware image using a different set of keys
8# for use on signing servers.
9#
10# arguments: src_fd, dst_fd, firmware_datakey, and firmware_keyblock
11#
12# src_fd: Input firmware image (in .fd format)
13# dst_fd: output firmware image name
14# firmware_datakey: Key used to sign firmware data (in .vbprivk format)
15# firmware_keyblock: Key block for firmware data key (in .keyblock format)
16#
Hung-Te Lin89feaed2010-09-15 09:36:49 +080017# Both the mosys tool and vbutil_firmware should be in the system path.
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070018#
Hung-Te Lin89feaed2010-09-15 09:36:49 +080019# This script parses the output of mosys tool from
20# http://code.google.com/p/mosys
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070021#
22# to determine the regions in the image containing "Firmware [A|B] Data" and
23# "Firmware [A|B] Key", which contain firmware data and firmware vblocks
24# respectively. It will then generate new vblocks using the set of keys
25# passed as arguments and output a new firmware image, with this new firmware
26# vblocks the old ones.
27#
Hung-Te Lin89feaed2010-09-15 09:36:49 +080028# Here is an example output of mosys:
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070029#
30# area_offset="0x001c0000" area_size="0x00040000" area_name="Boot Stub" \
31# area_flags_raw="0x01" area_flags="static"
32# area_offset="0x001a0000" area_size="0x00020000" area_name="GBB Area" \
33# area_flags_raw="0x01" area_flags="static"
34# area_offset="0x00008000" area_size="0x00002000" area_name="Firmware A Key" \
35# area_flags_raw="0x01" area_flags="static"
36# area_offset="0x0000a000" area_size="0x0009e000" area_name="Firmware A Data" \
37# area_flags_raw="0x03" area_flags="static,compressed"
38# area_offset="0x000a8000" area_size="0x00002000" area_name="Firmware B Key" \
39# area_flags_raw="0x01" area_flags="static"
40# area_offset="0x000aa000" area_size="0x0002e000" area_name="Firmware B Data" \
41# area_flags_raw="0x03" area_flags="static,compressed"
42# area_offset="0x00005200" area_size="0x00001000" area_name="RW VPD" \
43# area_flags_raw="0x00" area_flags=""
44#
45# This shows that Firmware A Data is at offset 0x0000a0000 in the .fd image
46# and is of size 0x0009e000 bytes. This can be extracted to generate new vblocks
47# which can then replace old vblock for Firmware A ("Firmware A Key" region at
48# offset 0x00008000 and size 0x00002000).
49
Gaurav Shah0c4c9ba2010-08-16 13:29:00 -070050# Load common constants and variables.
Gaurav Shah605500b2011-01-18 12:00:50 -080051. "$(dirname "$0")/common_minimal.sh"
Gaurav Shah0c4c9ba2010-08-16 13:29:00 -070052
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070053# Abort on error
54set -e
55
56# Check arguments
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +080057if [ $# -lt 7 ] || [ $# -gt 9 ]; then
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -080058 echo "Usage: $PROG src_fd dst_fd firmware_datakey firmware_keyblock"\
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +080059 "dev_firmware_datakey dev_firmware_keyblock kernel_subkey [version [flag]]"
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070060 exit 1
61fi
62
63# Make sure the tools we need are available.
Hung-Te Lin89feaed2010-09-15 09:36:49 +080064for prog in mosys vbutil_firmware; do
Gaurav Shah605500b2011-01-18 12:00:50 -080065 type "${prog}" &>/dev/null || \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070066 { echo "${prog} tool not found."; exit 1; }
67done
68
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -080069SRC_FD=$1
70DST_FD=$2
71FIRMWARE_DATAKEY=$3
72FIRMWARE_KEYBLOCK=$4
Gaurav Shah57468452011-03-02 14:50:46 -080073DEV_FIRMWARE_DATAKEY=$5
74DEV_FIRMWARE_KEYBLOCK=$6
75KERNEL_SUBKEY=$7
76VERSION=$8
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +080077# This is the --flag in vbutil_firmware. It currently has only two values:
78# 0 for RW-NORMAL firmware, and 1 for RO-NORMAL firmware (search "two_stop
79# firmware" for more information).
80PREAMBLE_FLAG=$9
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070081
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +080082if [ -z "$VERSION" ]; then
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -080083 VERSION=1
84fi
85echo "Using firmware version: $VERSION"
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070086
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +080087if [ -n "$PREAMBLE_FLAG" ]; then
88 echo "Using firmware preamble flag: $PREAMBLE_FLAG"
89 PREAMBLE_FLAG="--flag $PREAMBLE_FLAG"
90fi
91
Gaurav Shahaa22a5d2010-07-27 10:52:07 -070092# Parse offsets and size of firmware data and vblocks
93for i in "A" "B"
94do
Gaurav Shahe1649e12011-02-13 16:57:38 -080095 line=$(mosys -f -k eeprom map $1 | grep "$i Key") ||
96 line=$(mosys -f -k eeprom map $1 | grep "VBLOCK_$i") ||
97 { echo "Couldn't parse vblock section $i from mosys output";
98 exit 1; }
99
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700100 offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')"
Gaurav Shah605500b2011-01-18 12:00:50 -0800101 eval fw${i}_vblock_offset=$((offset))
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700102 size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')"
Gaurav Shah605500b2011-01-18 12:00:50 -0800103 eval fw${i}_vblock_size=$((size))
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700104
Gaurav Shahe1649e12011-02-13 16:57:38 -0800105 line=$(mosys -f -k eeprom map $1 | grep "$i Data") ||
106 line=$(mosys -f -k eeprom map $1 | grep "FW_MAIN_$i") ||
107 { echo "Couldn't parse Firmware $i section from mosys output";
108 exit 1; }
109
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700110 offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')"
Gaurav Shah605500b2011-01-18 12:00:50 -0800111 eval fw${i}_offset=$((offset))
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700112 size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')"
Gaurav Shah605500b2011-01-18 12:00:50 -0800113 eval fw${i}_size=$((size))
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700114done
115
Gaurav Shah0c4c9ba2010-08-16 13:29:00 -0700116temp_fwimage=$(make_temp_file)
117temp_out_vb=$(make_temp_file)
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700118
Gaurav Shah57468452011-03-02 14:50:46 -0800119# Extract out Firmware A data and generate signature using the right keys.
120# Firmware A is the dev firmware.
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800121dd if="${SRC_FD}" of="${temp_fwimage}" skip="${fwA_offset}" bs=1 \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700122 count="${fwA_size}"
123
124echo "Re-calculating Firmware A vblock"
125vbutil_firmware \
126 --vblock "${temp_out_vb}" \
Gaurav Shah57468452011-03-02 14:50:46 -0800127 --keyblock "${DEV_FIRMWARE_KEYBLOCK}" \
128 --signprivate "${DEV_FIRMWARE_DATAKEY}" \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700129 --version "${VERSION}" \
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +0800130 $PREAMBLE_FLAG \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700131 --fv "${temp_fwimage}" \
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800132 --kernelkey "${KERNEL_SUBKEY}"
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700133
134# Create a copy of the input image and put in the new vblock for firmware A
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800135cp "${SRC_FD}" "${DST_FD}"
136dd if="${temp_out_vb}" of="${DST_FD}" seek="${fwA_vblock_offset}" bs=1 \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700137 count="${fwA_vblock_size}" conv=notrunc
138
Gaurav Shah57468452011-03-02 14:50:46 -0800139# Firmware B is the normal firmware.
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800140dd if="${SRC_FD}" of="${temp_fwimage}" skip="${fwB_offset}" bs=1 \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700141 count="${fwB_size}"
142echo "Re-calculating Firmware B vblock"
143vbutil_firmware \
144 --vblock "${temp_out_vb}" \
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800145 --keyblock "${FIRMWARE_KEYBLOCK}" \
146 --signprivate "${FIRMWARE_DATAKEY}" \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700147 --version "${VERSION}" \
Hung-Te Lin8e17e5f2011-07-22 16:07:58 +0800148 $PREAMBLE_FLAG \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700149 --fv "${temp_fwimage}" \
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800150 --kernelkey "${KERNEL_SUBKEY}"
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700151
152# Destination image has already been created.
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800153dd if="${temp_out_vb}" of="${DST_FD}" seek="${fwB_vblock_offset}" bs=1 \
Gaurav Shahaa22a5d2010-07-27 10:52:07 -0700154 count="${fwB_vblock_size}" conv=notrunc
155
Gaurav Shah8ae7b0e2011-02-06 15:44:39 -0800156echo "New signed image was output to ${DST_FD}"