| OLD | NEW |
| (Empty) | |
| 1 #!/bin/bash |
| 2 |
| 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 # |
| 17 # Both the fmap_decode tool and vbutil_firmware should be in the system path. |
| 18 # |
| 19 # This script parses the output of fmap_decode tool from the Flashmap project |
| 20 # http://code.google.com/p/flashmap |
| 21 # |
| 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 # |
| 28 # Here is an example output of fmap_decode: |
| 29 # |
| 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 |
| 50 # Abort on error |
| 51 set -e |
| 52 |
| 53 # Check arguments |
| 54 if [ $# -ne 5 ] ; then |
| 55 echo \ |
| 56 "Usage: $0 src_fd dst_fd firmware_datakey firmware_keyblock kernel_subkey" |
| 57 exit 1 |
| 58 fi |
| 59 |
| 60 # Make sure the tools we need are available. |
| 61 for prog in fmap_decode vbutil_firmware; do |
| 62 type -P "${prog}" &>/dev/null || \ |
| 63 { echo "${prog} tool not found."; exit 1; } |
| 64 done |
| 65 |
| 66 src_fd=$1 |
| 67 dst_fd=$2 |
| 68 firmware_datakey=$3 |
| 69 firmware_keyblock=$4 |
| 70 kernel_subkey=$5 |
| 71 |
| 72 # TODO(gauravsh): Figure out where the version comes from. |
| 73 # Do we rev it manually? |
| 74 VERSION=1 |
| 75 |
| 76 # Parse offsets and size of firmware data and vblocks |
| 77 for i in "A" "B" |
| 78 do |
| 79 match_str="$i Key" |
| 80 line=$(fmap_decode $1 | grep "$match_str") |
| 81 offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')" |
| 82 eval let \ |
| 83 fw${i}_vblock_offset="$offset" |
| 84 size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')" |
| 85 eval let \ |
| 86 fw${i}_vblock_size="$size" |
| 87 |
| 88 match_str="$i Data" |
| 89 line=$(fmap_decode $1 | grep "$match_str") |
| 90 offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')" |
| 91 eval let \ |
| 92 fw${i}_offset="$offset" |
| 93 size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')" |
| 94 eval let \ |
| 95 fw${i}_size="$size" |
| 96 done |
| 97 |
| 98 temp_fwimage=$(mktemp) |
| 99 temp_out_vb=$(mktemp) |
| 100 trap "rm -f ${temp_fwimage} ${temp_out_vb}" EXIT |
| 101 |
| 102 # Extract out Firmware A data and generate signature using the right keys |
| 103 dd if="${src_fd}" of="${temp_fwimage}" skip="${fwA_offset}" bs=1 \ |
| 104 count="${fwA_size}" |
| 105 |
| 106 echo "Re-calculating Firmware A vblock" |
| 107 vbutil_firmware \ |
| 108 --vblock "${temp_out_vb}" \ |
| 109 --keyblock "${firmware_keyblock}" \ |
| 110 --signprivate "${firmware_datakey}" \ |
| 111 --version "${VERSION}" \ |
| 112 --fv "${temp_fwimage}" \ |
| 113 --kernelkey "${kernel_subkey}" |
| 114 |
| 115 # Create a copy of the input image and put in the new vblock for firmware A |
| 116 cp "${src_fd}" "${dst_fd}" |
| 117 dd if="${temp_out_vb}" of="${dst_fd}" seek="${fwA_vblock_offset}" bs=1 \ |
| 118 count="${fwA_vblock_size}" conv=notrunc |
| 119 |
| 120 # Repeat for firmware B |
| 121 dd if="${src_fd}" of="${temp_fwimage}" skip="${fwB_offset}" bs=1 \ |
| 122 count="${fwB_size}" |
| 123 echo "Re-calculating Firmware B vblock" |
| 124 vbutil_firmware \ |
| 125 --vblock "${temp_out_vb}" \ |
| 126 --keyblock "${firmware_keyblock}" \ |
| 127 --signprivate "${firmware_datakey}" \ |
| 128 --version "${VERSION}" \ |
| 129 --fv "${temp_fwimage}" \ |
| 130 --kernelkey "${kernel_subkey}" |
| 131 |
| 132 # Destination image has already been created. |
| 133 dd if="${temp_out_vb}" of="${dst_fd}" seek="${fwB_vblock_offset}" bs=1 \ |
| 134 count="${fwB_vblock_size}" conv=notrunc |
| 135 |
| 136 echo "New signed image was output to ${dst_fd}" |
| OLD | NEW |