OLD | NEW |
1 #!/bin/sh | 1 #!/bin/sh |
2 # | 2 # |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 # | 6 # |
7 # This script can change key (usually developer keys) in a firmware binary | 7 # This script can change key (usually developer keys) in a firmware binary |
8 # image or system live firmware, and assign proper HWID, BMPFV as well. | 8 # image or system live firmware (EEPROM), and assign proper HWID, BMPFV as well. |
9 | 9 |
10 SCRIPT_BASE="$(dirname "$0")" | 10 SCRIPT_BASE="$(dirname "$0")" |
11 . "$SCRIPT_BASE/common.sh" | 11 . "$SCRIPT_BASE/common.sh" |
| 12 load_shflags || exit 1 |
12 | 13 |
13 # Constants used by DEFINE_* | 14 # Constants used by DEFINE_* |
| 15 VBOOT_BASE='/usr/share/vboot' |
| 16 DEFAULT_KEYS_FOLDER="$VBOOT_BASE/devkeys" |
| 17 DEFAULT_BMPFV_FILE="$DEFAULT_KEYS_FOLDER/firmware_bmpfv.bin" |
14 DEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups' | 18 DEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups' |
15 | 19 |
16 # DEFINE_string name default_value description flag | 20 # DEFINE_string name default_value description flag |
17 DEFINE_string from "" "Path of input file (empty for system live firmware)" "f" | 21 DEFINE_string from "" "Path of input file (empty for system live firmware)" "f" |
18 DEFINE_string to "" "Path of output file (empty for system live firmware)" "t" | 22 DEFINE_string to "" "Path of output file (empty for system live firmware)" "t" |
19 DEFINE_string keys "$SCRIPT_BASE/keys" "Path of folder of dev keys" "k" | 23 DEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k" |
20 DEFINE_string bmpfv "$SCRIPT_BASE/rsrc/bmpfv.bin" "Path to the new bitmap FV" "" | 24 DEFINE_string bmpfv "$DEFAULT_BMPFV_FILE" "Path to the new bitmap FV" "" |
21 DEFINE_boolean force_backup \ | 25 DEFINE_boolean force_backup \ |
22 $FLAGS_TRUE "Create backup even if source is not live" "" | 26 $FLAGS_TRUE "Create backup even if source is not live" "" |
23 DEFINE_string backup_dir \ | 27 DEFINE_string backup_dir \ |
24 "$DEFAULT_BACKUP_FOLDER" "Path of directory to store firmware backups" "" | 28 "$DEFAULT_BACKUP_FOLDER" "Path of directory to store firmware backups" "" |
25 DEFINE_boolean debug $FLAGS_FALSE "Provide debug messages" "d" | 29 DEFINE_boolean debug $FLAGS_FALSE "Provide debug messages" "d" |
26 | 30 |
27 # Parse command line | 31 # Parse command line |
28 FLAGS "$@" || exit 1 | 32 FLAGS "$@" || exit 1 |
29 eval set -- "$FLAGS_ARGV" | 33 eval set -- "$FLAGS_ARGV" |
30 | 34 |
31 # Globals | 35 # Globals |
32 # ---------------------------------------------------------------------------- | 36 # ---------------------------------------------------------------------------- |
33 set -e | 37 set -e |
34 | 38 |
35 # the image we are (temporary) working with | 39 # the image we are (temporary) working with |
36 IMAGE=$(make_temp_file) | 40 IMAGE="$(make_temp_file)" |
37 | 41 |
38 # a log file to keep the output results of executed command | 42 # a log file to keep the output results of executed command |
39 EXEC_LOG=$(make_temp_file) | 43 EXEC_LOG="$(make_temp_file)" |
40 | 44 |
41 # Functions | 45 # Functions |
42 # ---------------------------------------------------------------------------- | 46 # ---------------------------------------------------------------------------- |
43 # Reports error message and exit(1) | 47 # Reports error message and exit(1) |
44 err_die() { | 48 err_die() { |
45 echo "ERROR: $*" 1>&2 | 49 echo "ERROR: $*" 1>&2 |
46 exit 1 | 50 exit 1 |
47 } | 51 } |
48 | 52 |
49 # Returns true if we're running in debug mode | 53 # Returns true if we're running in debug mode |
(...skipping 20 matching lines...) Expand all Loading... |
70 else | 74 else |
71 debug_msg "reading from file: $FLAGS_from" | 75 debug_msg "reading from file: $FLAGS_from" |
72 cp -f "$FLAGS_from" "$IMAGE" | 76 cp -f "$FLAGS_from" "$IMAGE" |
73 fi | 77 fi |
74 } | 78 } |
75 | 79 |
76 # Writes $IMAGE to $FLAGS_to | 80 # Writes $IMAGE to $FLAGS_to |
77 write_image() { | 81 write_image() { |
78 if [ -z "$FLAGS_to" ]; then | 82 if [ -z "$FLAGS_to" ]; then |
79 echo "Writing system live firmware..." | 83 echo "Writing system live firmware..." |
| 84 # TODO(hungte) we can enable partial write to make this faster |
80 if is_debug_mode; then | 85 if is_debug_mode; then |
81 flashrom -V -w "$IMAGE" | 86 flashrom -V -w "$IMAGE" |
82 else | 87 else |
83 flashrom -w "$IMAGE" >"$EXEC_LOG" 2>&1 | 88 flashrom -w "$IMAGE" >"$EXEC_LOG" 2>&1 |
84 fi | 89 fi |
85 else | 90 else |
86 debug_msg "writing to file: $FLAGS_to" | 91 debug_msg "writing to file: $FLAGS_to" |
87 cp -f "$IMAGE" "$FLAGS_to" | 92 cp -f "$IMAGE" "$FLAGS_to" |
88 chmod a+r "$FLAGS_to" | 93 chmod a+r "$FLAGS_to" |
89 fi | 94 fi |
90 } | 95 } |
91 | 96 |
92 # Converts HWID from $1 to proper format with "DEV" extension | 97 # Converts HWID from $1 to proper format with "DEV" extension |
93 echo_dev_hwid() { | 98 echo_dev_hwid() { |
94 local hwid="$1" | 99 local hwid="$1" |
95 local hwid_no_dev="${hwid% DEV}" | 100 local hwid_no_dev="${hwid% DEV}" |
96 | 101 |
97 # NOTE: Some DEV firmware image files may put GUID in HWID. | 102 # NOTE: Some DEV firmware image files may put GUID in HWID. |
98 # These are not officially supported and they will see "{GUID} DEV". | 103 # These are not officially supported and they will see "{GUID} DEV". |
| 104 # Also there's some length limitation in chromeos_acpi/HWID, so |
| 105 # a "{GUID} DEV" will become "{GUID} " in that case. |
99 | 106 |
100 if [ "$hwid" != "$hwid_no_dev" ]; then | 107 if [ "$hwid" != "$hwid_no_dev" ]; then |
101 hwid="$hwid_no_dev" | 108 hwid="$hwid_no_dev" |
102 fi | 109 fi |
103 local hwid_dev="$hwid DEV" | 110 local hwid_dev="$hwid DEV" |
104 debug_msg "echo_dev_hwid: [$1] -> [$hwid_dev]" | 111 debug_msg "echo_dev_hwid: [$1] -> [$hwid_dev]" |
105 echo "$hwid_dev" | 112 echo "$hwid_dev" |
106 } | 113 } |
107 | 114 |
108 # Checks if the files given by parameters all exist. | |
109 check_exist_or_die() { | |
110 local file is_success=$FLAGS_TRUE | |
111 for file in "$@"; do | |
112 if [ ! -s "$file" ]; then | |
113 echo "ERROR: Cannot find required file: $file" | |
114 is_success=$FLAGS_FALSE | |
115 fi | |
116 done | |
117 | |
118 if [ "$is_success" = $FLAGS_FALSE ]; then | |
119 exit 1 | |
120 fi | |
121 } | |
122 | |
123 # Main | 115 # Main |
124 # ---------------------------------------------------------------------------- | 116 # ---------------------------------------------------------------------------- |
125 main() { | 117 main() { |
126 # Check parameters | 118 # Check parameters |
127 local root_pubkey="$FLAGS_keys/root_key.vbpubk" | 119 local root_pubkey="$FLAGS_keys/root_key.vbpubk" |
128 local recovery_pubkey="$FLAGS_keys/recovery_key.vbpubk" | 120 local recovery_pubkey="$FLAGS_keys/recovery_key.vbpubk" |
129 local firmware_keyblock="$FLAGS_keys/firmware.keyblock" | 121 local firmware_keyblock="$FLAGS_keys/firmware.keyblock" |
130 local firmware_prvkey="$FLAGS_keys/firmware_data_key.vbprivk" | 122 local firmware_prvkey="$FLAGS_keys/firmware_data_key.vbprivk" |
131 local kernel_sub_pubkey="$FLAGS_keys/kernel_subkey.vbpubk" | 123 local kernel_sub_pubkey="$FLAGS_keys/kernel_subkey.vbpubk" |
132 local new_bmpfv="$FLAGS_bmpfv" | 124 local new_bmpfv="$FLAGS_bmpfv" |
133 local is_from_live=0 | 125 local is_from_live=0 |
134 local backup_image= | 126 local backup_image= |
135 | 127 |
136 debug_msg "Pre-requisition check" | 128 debug_msg "Prerequisite check" |
137 check_exist_or_die \ | 129 ensure_files_exist \ |
138 "$root_pubkey" \ | 130 "$root_pubkey" \ |
139 "$recovery_pubkey" \ | 131 "$recovery_pubkey" \ |
140 "$firmware_keyblock" \ | 132 "$firmware_keyblock" \ |
141 "$firmware_prvkey" \ | 133 "$firmware_prvkey" \ |
142 "$kernel_sub_pubkey" \ | 134 "$kernel_sub_pubkey" \ |
143 "$new_bmpfv" | 135 "$new_bmpfv" || |
| 136 exit 1 |
144 | 137 |
145 if [ -z "$FLAGS_from" ]; then | 138 if [ -z "$FLAGS_from" ]; then |
146 is_from_live=1 | 139 is_from_live=1 |
147 else | 140 else |
148 check_exist_or_die "$FLAGS_from" | 141 ensure_files_exist "$FLAGS_from" |
149 fi | 142 fi |
150 | 143 |
151 # TODO(hungte) check if GPIO.3 (WP) is enabled | 144 # TODO(hungte) check if GPIO.3 (WP) is enabled |
152 | 145 |
153 debug_msg "Pulling image to $IMAGE" | 146 debug_msg "Pulling image to $IMAGE" |
154 (read_image && [ -s "$IMAGE" ]) || | 147 (read_image && [ -s "$IMAGE" ]) || |
155 err_die "Failed to read image. Error message: $(cat "$EXEC_LOG")" | 148 err_die "Failed to read image. Error message: $(cat "$EXEC_LOG")" |
156 | 149 |
157 debug_msg "Prepare to backup the file" | 150 debug_msg "Prepare to backup the file" |
158 if [ -n "$is_from_live" -o $FLAGS_force_backup = $FLAGS_TRUE ]; then | 151 if [ -n "$is_from_live" -o $FLAGS_force_backup = $FLAGS_TRUE ]; then |
159 backup_image=$(make_temp_file) | 152 backup_image="$(make_temp_file)" |
160 debug_msg "Creating backup file to $backup_image..." | 153 debug_msg "Creating backup file to $backup_image..." |
161 cp -f "$IMAGE" "$backup_image" | 154 cp -f "$IMAGE" "$backup_image" |
162 fi | 155 fi |
163 | 156 |
164 # TODO(hungte) We can use vbutil_firmware to check if the current firmware is | 157 # TODO(hungte) We can use vbutil_firmware to check if the current firmware is |
165 # valid, so that we can know both they key, vbutil_firmware are working fine. | 158 # valid so that we know keys and vbutil_firmware are all working fine. |
166 | 159 |
167 echo "Preparing new firmware image..." | 160 echo "Preparing new firmware image..." |
168 | |
169 debug_msg "Extract current HWID and rootkey" | 161 debug_msg "Extract current HWID and rootkey" |
170 local old_hwid | 162 local old_hwid |
171 old_hwid=$(gbb_utility --get --hwid "$IMAGE" 2>"$EXEC_LOG" | | 163 old_hwid="$(gbb_utility --get --hwid "$IMAGE" 2>"$EXEC_LOG" | |
172 grep '^hardware_id:' | | 164 grep '^hardware_id:' | |
173 sed 's/^hardware_id: //') | 165 sed 's/^hardware_id: //')" |
174 | 166 |
175 debug_msg "Decide new HWID" | 167 debug_msg "Decide new HWID" |
176 if [ -z "$old_hwid" ]; then | 168 if [ -z "$old_hwid" ]; then |
177 err_die "Cannot find current HWID. (message: $(cat "$EXEC_LOG"))" | 169 err_die "Cannot find current HWID. (message: $(cat "$EXEC_LOG"))" |
178 fi | 170 fi |
179 local new_hwid=$(echo_dev_hwid "$old_hwid") | 171 local new_hwid="$(echo_dev_hwid "$old_hwid")" |
180 | 172 |
181 debug_msg "Replace GBB parts (gbb_utility allows changing on-the-fly)" | 173 debug_msg "Replace GBB parts (gbb_utility allows changing on-the-fly)" |
182 gbb_utility --set \ | 174 gbb_utility --set \ |
183 --hwid="$new_hwid" \ | 175 --hwid="$new_hwid" \ |
184 --bmpfv="$new_bmpfv" \ | 176 --bmpfv="$new_bmpfv" \ |
185 --rootkey="$root_pubkey" \ | 177 --rootkey="$root_pubkey" \ |
186 --recoverykey="$recovery_pubkey" \ | 178 --recoverykey="$recovery_pubkey" \ |
187 "$IMAGE" >"$EXEC_LOG" 2>&1 || | 179 "$IMAGE" >"$EXEC_LOG" 2>&1 || |
188 err_die "Failed to change GBB Data. (message: $(cat "$EXEC_LOG"))" | 180 err_die "Failed to change GBB Data. (message: $(cat "$EXEC_LOG"))" |
189 | 181 |
190 debug_msg "Resign the firmware code (A/B) with new keys" | 182 debug_msg "Resign the firmware code (A/B) with new keys" |
191 local unsigned_image=$(make_temp_file) | 183 local unsigned_image="$(make_temp_file)" |
192 cp -f "$IMAGE" "$unsigned_image" | 184 cp -f "$IMAGE" "$unsigned_image" |
193 "$SCRIPT_BASE/resign_firmwarefd.sh" \ | 185 "$SCRIPT_BASE/resign_firmwarefd.sh" \ |
194 "$unsigned_image" \ | 186 "$unsigned_image" \ |
195 "$IMAGE" \ | 187 "$IMAGE" \ |
196 "$firmware_prvkey" \ | 188 "$firmware_prvkey" \ |
197 "$firmware_keyblock" \ | 189 "$firmware_keyblock" \ |
198 "$kernel_sub_pubkey" >"$EXEC_LOG" 2>&1 || | 190 "$kernel_sub_pubkey" >"$EXEC_LOG" 2>&1 || |
199 err_die "Failed to re-sign firmware. (message: $(cat "$EXEC_LOG"))" | 191 err_die "Failed to re-sign firmware. (message: $(cat "$EXEC_LOG"))" |
200 | 192 |
201 # TODO(hungte) compare if the image really needs to be changed. | 193 # TODO(hungte) compare if the image really needs to be changed. |
202 | 194 |
203 debug_msg "Backup files when reading from system live image." | 195 debug_msg "Check if we need to make backup file(s)" |
204 if [ -n "$backup_image" ]; then | 196 if [ -n "$backup_image" ]; then |
205 local backup_hwid_name=$(echo "$old_hwid" | sed 's/ /_/g') | 197 local backup_hwid_name="$(echo "$old_hwid" | sed 's/ /_/g')" |
206 local backup_date_time=$(date +'%Y%m%d_%H%M%S') | 198 local backup_date_time="$(date +'%Y%m%d_%H%M%S')" |
207 local backup_file_name="firmware_${backup_hwid_name}_${backup_date_time}.fd" | 199 local backup_file_name="firmware_${backup_hwid_name}_${backup_date_time}.fd" |
208 local backup_file_path="$FLAGS_backup_dir/$backup_file_name" | 200 local backup_file_path="$FLAGS_backup_dir/$backup_file_name" |
209 if mkdir -p "$FLAGS_backup_dir" && | 201 if mkdir -p "$FLAGS_backup_dir" && |
210 cp -f "$backup_image" "$backup_file_path"; then | 202 cp -f "$backup_image" "$backup_file_path"; then |
211 echo "Backup of current firmware image is stored in: $backup_file_path" | 203 echo "Backup of current firmware image is stored in: $backup_file_path" |
212 else | 204 else |
213 echo "Cannot create file in $FLAGS_backup_dir... Ignore backups." | 205 echo "WARNING: Cannot create file in $FLAGS_backup_dir... Ignore backups." |
214 fi | 206 fi |
215 fi | 207 fi |
216 | 208 |
217 # TODO(hungte) use vbutil_firmware to check if the new firmware is valid. | 209 # TODO(hungte) use vbutil_firmware to check if the new firmware is valid. |
| 210 # Or, do verification in resign_firmwarefd.sh and trust it. |
218 | 211 |
219 debug_msg "Write the image" | 212 debug_msg "Write the image" |
220 write_image || | 213 write_image || |
221 err_die "Failed to write image. Error message: $(cat "$EXEC_LOG")" | 214 err_die "Failed to write image. Error message: $(cat "$EXEC_LOG")" |
222 | 215 |
223 debug_msg "Complete." | 216 debug_msg "Complete." |
224 if [ -z "$FLAGS_to" ]; then | 217 if [ -z "$FLAGS_to" ]; then |
225 echo "Successfully changed firmware to Developer Keys. New HWID: $new_hwid" | 218 echo "Successfully changed firmware to Developer Keys. New HWID: $new_hwid" |
226 else | 219 else |
227 echo "Firmware image '$FLAGS_to' now uses Developer Keys. HWID: $new_hwid" | 220 echo "Firmware '$FLAGS_to' now uses Developer Keys. New HWID: $new_hwid" |
228 fi | 221 fi |
229 } | 222 } |
230 | 223 |
231 main | 224 main |
OLD | NEW |