Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/bin/sh | 1 #!/bin/sh |
| 2 # | 2 # |
| 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2011 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) and kernel config | 7 # This script can change key (usually developer keys) and kernel config |
| 8 # of a kernels on SSD. | 8 # of a kernels on an disk image (usually for SSD but also works for USB). |
|
Randall Spangler
2011/04/19 20:40:12
'a kernels' -> 'kernels'
Hung-Te
2011/04/20 01:30:20
Done.
| |
| 9 | 9 |
| 10 SCRIPT_BASE="$(dirname "$0")" | 10 SCRIPT_BASE="$(dirname "$0")" |
| 11 . "$SCRIPT_BASE/common_minimal.sh" | 11 . "$SCRIPT_BASE/common_minimal.sh" |
| 12 load_shflags || exit 1 | 12 load_shflags || exit 1 |
| 13 | 13 |
| 14 # Constants used by DEFINE_* | 14 # Constants used by DEFINE_* |
| 15 VBOOT_BASE='/usr/share/vboot' | 15 VBOOT_BASE='/usr/share/vboot' |
| 16 DEFAULT_KEYS_FOLDER="$VBOOT_BASE/devkeys" | 16 DEFAULT_KEYS_FOLDER="$VBOOT_BASE/devkeys" |
| 17 DEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups' | 17 DEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups' |
| 18 DEFAULT_PARTITIONS='2 4' | 18 DEFAULT_PARTITIONS='2 4' |
| 19 | 19 |
| 20 # TODO(hungte) or use "rootdev -s" in future | 20 # TODO(hungte) The default image selection is no longer a "make_dev_ssd"... More |
| 21 DEFAULT_IMAGE="/dev/sda" | 21 # like "make_dev_image". We may change the file name in future. |
| 22 ROOTDEV="$(rootdev -s 2>/dev/null)" | |
| 23 ROOTDEV_PARTITION="$(echo $ROOTDEV | sed -n 's/.*\([0-9][0-9]*\)$/\1/p')" | |
| 24 ROOTDEV_DISK="${ROOTDEV%$ROOTDEV_PARTITION}" | |
| 25 ROOTDEV_KERNEL="$((ROOTDEV_PARTITION - 1))" | |
| 22 | 26 |
| 23 # DEFINE_string name default_value description flag | 27 # DEFINE_string name default_value description flag |
| 24 DEFINE_string image "$DEFAULT_IMAGE" "Path to device or image file" "i" | 28 DEFINE_string image "$ROOTDEV_DISK" "Path to device or image file" "i" |
| 25 DEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k" | 29 DEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k" |
| 26 DEFINE_boolean remove_rootfs_verification \ | 30 DEFINE_boolean remove_rootfs_verification \ |
| 27 $FLAGS_FALSE "Modify kernel boot config to disable rootfs verification" "" | 31 $FLAGS_FALSE "Modify kernel boot config to disable rootfs verification" "" |
| 28 DEFINE_string backup_dir \ | 32 DEFINE_string backup_dir \ |
| 29 "$DEFAULT_BACKUP_FOLDER" "Path of directory to store kernel backups" "" | 33 "$DEFAULT_BACKUP_FOLDER" "Path of directory to store kernel backups" "" |
| 30 DEFINE_string save_config "" \ | 34 DEFINE_string save_config "" \ |
| 31 "Base filename to store kernel configs to, instead of resigning." "" | 35 "Base filename to store kernel configs to, instead of resigning." "" |
| 32 DEFINE_string set_config "" \ | 36 DEFINE_string set_config "" \ |
| 33 "Base filename to load kernel configs from" "" | 37 "Base filename to load kernel configs from" "" |
| 34 DEFINE_string partitions "$DEFAULT_PARTITIONS" \ | 38 DEFINE_string partitions "$DEFAULT_PARTITIONS" \ |
| 35 "List of partitions to examine" "" | 39 "List of partitions to examine" "" |
| 36 DEFINE_boolean recovery_key "$FLAGS_FALSE" \ | 40 DEFINE_boolean recovery_key "$FLAGS_FALSE" \ |
| 37 "Use recovery key to sign image (to boot from USB" "" | 41 "Use recovery key to sign image (to boot from USB" "" |
| 38 DEFINE_boolean force "$FLAGS_FALSE" "Skip sanity checks and make the change" "f" | 42 DEFINE_boolean force "$FLAGS_FALSE" "Skip sanity checks and make the change" "f" |
| 39 | 43 |
| 40 # Parse command line | 44 # Parse command line |
| 41 FLAGS "$@" || exit 1 | 45 FLAGS "$@" || exit 1 |
| 42 ORIGINAL_PARAMS="$@" | 46 ORIGINAL_PARAMS="$@" |
| 43 eval set -- "$FLAGS_ARGV" | 47 eval set -- "$FLAGS_ARGV" |
| 48 ORIGINAL_PARTITIONS="$FLAGS_partitions" | |
| 44 | 49 |
| 45 # Globals | 50 # Globals |
| 46 # ---------------------------------------------------------------------------- | 51 # ---------------------------------------------------------------------------- |
| 47 set -e | 52 set -e |
| 48 | 53 |
| 49 # a log file to keep the output results of executed command | 54 # a log file to keep the output results of executed command |
| 50 EXEC_LOG="$(make_temp_file)" | 55 EXEC_LOG="$(make_temp_file)" |
| 51 | 56 |
| 52 # Functions | 57 # Functions |
| 53 # ---------------------------------------------------------------------------- | 58 # ---------------------------------------------------------------------------- |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 echo "Kernel B" | 105 echo "Kernel B" |
| 101 ;; | 106 ;; |
| 102 6) | 107 6) |
| 103 echo "Kernel C" | 108 echo "Kernel C" |
| 104 ;; | 109 ;; |
| 105 *) | 110 *) |
| 106 echo "Partition $1" | 111 echo "Partition $1" |
| 107 esac | 112 esac |
| 108 } | 113 } |
| 109 | 114 |
| 115 find_valid_kernel_partitions() { | |
| 116 local part_id | |
| 117 local valid_partitions="" | |
| 118 for part_id in $*; do | |
| 119 local name="$(cros_kernel_name $part_id)" | |
| 120 if [ -z "$(dump_kernel_config $FLAGS_image$part_id 2>"$EXEC_LOG")" ]; then | |
| 121 echo "INFO: $name: no kernel boot information, ignored." >&2 | |
| 122 else | |
| 123 [ -z "$valid_partitions" ] && | |
| 124 valid_partitions="$part_id" || | |
| 125 valid_partitions="$valid_partitions $part_id" | |
| 126 continue | |
| 127 fi | |
| 128 done | |
| 129 debug_msg "find_valid_kernel_partitions: [$*] -> [$valid_partitions]" | |
| 130 echo "$valid_partitions" | |
| 131 } | |
| 132 | |
| 110 # Resigns a kernel on SSD or image. | 133 # Resigns a kernel on SSD or image. |
| 111 resign_ssd_kernel() { | 134 resign_ssd_kernel() { |
| 112 # bs=512 is the fixed block size for dd and cgpt | 135 # bs=512 is the fixed block size for dd and cgpt |
| 113 local bs=512 | 136 local bs=512 |
| 114 local ssd_device="$1" | 137 local ssd_device="$1" |
| 115 | 138 |
| 116 # reasonable size for current kernel partition | 139 # reasonable size for current kernel partition |
| 117 local min_kernel_size=32000 | 140 local min_kernel_size=32000 |
| 118 local max_kernel_size=65536 | 141 local max_kernel_size=65536 |
| 119 local resigned_kernels=0 | 142 local resigned_kernels=0 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 debug_msg "Writing $name to partition $kernel_index" | 251 debug_msg "Writing $name to partition $kernel_index" |
| 229 mydd \ | 252 mydd \ |
| 230 if="$new_kern" \ | 253 if="$new_kern" \ |
| 231 of="$ssd_device" \ | 254 of="$ssd_device" \ |
| 232 seek=$offset \ | 255 seek=$offset \ |
| 233 bs=$bs \ | 256 bs=$bs \ |
| 234 count=$size \ | 257 count=$size \ |
| 235 conv=notrunc | 258 conv=notrunc |
| 236 resigned_kernels=$(($resigned_kernels + 1)) | 259 resigned_kernels=$(($resigned_kernels + 1)) |
| 237 | 260 |
| 238 debug_msg "Make the root filesystem writable if needed." | 261 debug_msg "Make the root file system writable if needed." |
| 239 # TODO(hungte) for safety concern, a more robust way would be to: | 262 # TODO(hungte) for safety concern, a more robust way would be to: |
| 240 # (1) change kernel config to ro | 263 # (1) change kernel config to ro |
| 241 # (2) check if we can enable rw mount | 264 # (2) check if we can enable rw mount |
| 242 # (3) change kernel config to rw | 265 # (3) change kernel config to rw |
| 243 if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_TRUE ]; then | 266 if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_TRUE ]; then |
| 244 local root_offset_sector=$(partoffset "$ssd_device" $rootfs_index) | 267 local root_offset_sector=$(partoffset "$ssd_device" $rootfs_index) |
| 245 local root_offset_bytes=$((root_offset_sector * 512)) | 268 local root_offset_bytes=$((root_offset_sector * 512)) |
| 246 if ! is_ext2 "$ssd_device" "$root_offset_bytes"; then | 269 if ! is_ext2 "$ssd_device" "$root_offset_bytes"; then |
| 247 debug_msg "Non-ext2 partition: $ssd_device$rootfs_index, skip." | 270 debug_msg "Non-ext2 partition: $ssd_device$rootfs_index, skip." |
| 248 elif ! rw_mount_disabled "$ssd_device" "$root_offset_bytes"; then | 271 elif ! rw_mount_disabled "$ssd_device" "$root_offset_bytes"; then |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 266 | 289 |
| 267 # If we saved the kernel config, exit now so we don't print an error | 290 # If we saved the kernel config, exit now so we don't print an error |
| 268 if [ -n "${FLAGS_save_config}" ]; then | 291 if [ -n "${FLAGS_save_config}" ]; then |
| 269 echo "(Kernels have not been resigned.)" | 292 echo "(Kernels have not been resigned.)" |
| 270 exit 0 | 293 exit 0 |
| 271 fi | 294 fi |
| 272 | 295 |
| 273 return $resigned_kernels | 296 return $resigned_kernels |
| 274 } | 297 } |
| 275 | 298 |
| 299 sanity_check_live_partitions() { | |
| 300 debug_msg "Partition sanity check" | |
| 301 if [ "$FLAGS_partitions" = "$ROOTDEV_KERNEL" ]; then | |
| 302 debug_msg "only for current active partition - safe." | |
| 303 return | |
| 304 fi | |
| 305 if [ "$ORIGINAL_PARTITIONS" != "$DEFAULT_PARTITIONS" ]; then | |
|
Randall Spangler
2011/04/19 20:40:12
What does this check do?
(and what if I explicitl
Hung-Te
2011/04/20 01:30:20
Changed to compare with empty (new default value).
Randall Spangler
2011/04/20 19:31:57
Isn't the default above still '2 4'?
Hung-Te
2011/04/21 01:58:35
The default partitions is '2 4', but the "default"
| |
| 306 debug_msg "user has assigned some option - provide more info." | |
| 307 echo "INFO: Making change to $FLAGS_partitions on $FLAGS_image." | |
| 308 return | |
| 309 fi | |
| 310 echo " | |
| 311 ERROR: YOU ARE TRYING TO MODIFY THE LIVE SYSTEM IMAGE $FLAGS_image. | |
| 312 | |
| 313 The system may become unusable after that change, especially when you have | |
| 314 some auto updates in progress. To make it safer, we suggest you to only | |
| 315 change the partition you have booted with. To do that, re-execute this command | |
| 316 as: | |
| 317 | |
| 318 sudo ./make_dev_ssd.sh $ORIGINAL_PARAMS --partitions $ROOTDEV_KERNEL | |
| 319 | |
| 320 If you are sure to modify other partition, please invoke the command again and | |
| 321 explicitly assign only one target partition for each time (--partitions N ) | |
| 322 " | |
| 323 return $FLAGS_FALSE | |
| 324 } | |
| 325 | |
| 326 sanity_check_live_firmware() { | |
| 327 debug_msg "Firmware compatibility sanity check" | |
| 328 if [ "$(crossystem mainfw_type)" = "developer" ]; then | |
| 329 debug_msg "developer type firmware in active." | |
| 330 return | |
| 331 fi | |
| 332 debug_msg "Loading firmware to check root key..." | |
| 333 local bios_image="$(make_temp_file)" | |
| 334 local rootkey_file="$(make_temp_file)" | |
| 335 echo "INFO: checking system firmware..." | |
| 336 sudo flashrom -p internal:bus=spi -i GBB -r "$bios_image" >/dev/null 2>&1 | |
| 337 gbb_utility -g --rootkey="$rootkey_file" "$bios_image" >/dev/null 2>&1 | |
| 338 if [ ! -s "$rootkey_file" ]; then | |
| 339 debug_msg "failed to read root key from system firmware..." | |
| 340 else | |
| 341 # 130 is the magic number for DEV key | |
|
Randall Spangler
2011/04/19 20:40:12
Please add more explanation on how 130 was calcula
Hung-Te
2011/04/20 01:30:20
That's a great idea.
However the file sizes ar
| |
| 342 local rootkey_hash="$(od "$rootkey_file" | | |
| 343 head -130 | md5sum | | |
| 344 sed 's/ .*$//' )" | |
| 345 if [ "$rootkey_hash" = "a13642246ef93daaf75bd791446fec9b" ]; then | |
| 346 debug_msg "detected DEV root key in firmware." | |
| 347 return | |
| 348 else | |
| 349 debug_msg "non-devkey hash: $rootkey_hash" | |
| 350 fi | |
| 351 fi | |
| 352 | |
| 353 echo " | |
| 354 ERROR: YOU ARE NOT USING DEVELOPER FIRMWARE, AND RUNNING THIS COMMAND MAY | |
| 355 THROW YOUR CHROMEOS DEVICE INTO UN-BOOTABLE STATE. | |
| 356 | |
| 357 You need to either install developer firmware, or change system root key. | |
| 358 | |
| 359 - To install developer firmware: type command | |
| 360 sudo chromeos-firmwareupdate --mode=todev | |
| 361 | |
| 362 - To change system rootkey: disable firmware write protection (a hardware | |
| 363 switch) and then type command: | |
| 364 sudo ./make_dev_firmware.sh | |
| 365 | |
| 366 If you are sure that you want to make such image without developer | |
| 367 firmware or you've already changed system root keys, please run this | |
| 368 command again with --force paramemeter: | |
| 369 | |
| 370 sudo ./make_dev_ssd.sh --force $ORIGINAL_PARAMS | |
| 371 " | |
| 372 return $FLAGS_FALSE | |
| 373 } | |
| 374 | |
| 276 # Main | 375 # Main |
| 277 # ---------------------------------------------------------------------------- | 376 # ---------------------------------------------------------------------------- |
| 278 main() { | 377 main() { |
| 279 local num_signed=0 | 378 local num_signed=0 |
| 280 local num_given=$(echo "$FLAGS_partitions" | wc -w) | 379 local num_given=$(echo "$FLAGS_partitions" | wc -w) |
| 281 # Check parameters | 380 # Check parameters |
| 282 if [ "$FLAGS_recovery_key" = "$FLAGS_TRUE" ]; then | 381 if [ "$FLAGS_recovery_key" = "$FLAGS_TRUE" ]; then |
| 283 KERNEL_KEYBLOCK="$FLAGS_keys/recovery_kernel.keyblock" | 382 KERNEL_KEYBLOCK="$FLAGS_keys/recovery_kernel.keyblock" |
| 284 KERNEL_DATAKEY="$FLAGS_keys/recovery_kernel_data_key.vbprivk" | 383 KERNEL_DATAKEY="$FLAGS_keys/recovery_kernel_data_key.vbprivk" |
| 285 KERNEL_PUBKEY="$FLAGS_keys/recovery_key.vbpubk" | 384 KERNEL_PUBKEY="$FLAGS_keys/recovery_key.vbpubk" |
| 286 else | 385 else |
| 287 KERNEL_KEYBLOCK="$FLAGS_keys/kernel.keyblock" | 386 KERNEL_KEYBLOCK="$FLAGS_keys/kernel.keyblock" |
| 288 KERNEL_DATAKEY="$FLAGS_keys/kernel_data_key.vbprivk" | 387 KERNEL_DATAKEY="$FLAGS_keys/kernel_data_key.vbprivk" |
| 289 KERNEL_PUBKEY="$FLAGS_keys/kernel_subkey.vbpubk" | 388 KERNEL_PUBKEY="$FLAGS_keys/kernel_subkey.vbpubk" |
| 290 fi | 389 fi |
| 291 | 390 |
| 292 debug_msg "Prerequisite check" | 391 debug_msg "Prerequisite check" |
| 293 ensure_files_exist \ | 392 ensure_files_exist \ |
| 294 "$KERNEL_KEYBLOCK" \ | 393 "$KERNEL_KEYBLOCK" \ |
| 295 "$KERNEL_DATAKEY" \ | 394 "$KERNEL_DATAKEY" \ |
| 296 "$KERNEL_PUBKEY" \ | 395 "$KERNEL_PUBKEY" \ |
| 297 "$FLAGS_image" || | 396 "$FLAGS_image" || |
| 298 exit 1 | 397 exit 1 |
| 299 | 398 |
| 300 debug_msg "Firmware compatibility sanity check" | 399 # checks for running on a live system image. |
| 301 if [ "$FLAGS_force" = "$FLAGS_FALSE" ] && | 400 if [ "$FLAGS_image" = "$ROOTDEV_DISK" ]; then |
| 302 [ "$FLAGS_image" = "$DEFAULT_IMAGE" ] && | 401 debug_msg "check valid kernel partitions for live system" |
| 303 [ "$(crossystem mainfw_type)" != "developer" ]; then | 402 local valid_partitions="$(find_valid_kernel_partitions $FLAGS_partitions)" |
| 403 [ -n "$valid_partitions" ] || | |
| 404 err_die "No valid kernel partitions on $FLAGS_image ($FLAGS_partitions)." | |
| 405 FLAGS_partitions="$valid_partitions" | |
| 304 | 406 |
| 305 # TODO(hungte) we can check if the fimware rootkey is already dev keys." | 407 # Sanity checks |
| 408 if [ "$FLAGS_force" = "$FLAGS_TRUE" ]; then | |
| 306 echo " | 409 echo " |
| 307 ERROR: YOU ARE NOT USING DEVELOPER FIRMWARE, AND RUNNING THIS COMMAND MAY | 410 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| 308 THROW YOUR CHROMEOS DEVICE INTO UNBOOTABLE STATE. | 411 ! INFO: ALL SANITY CHECKS WERE BYPASSED. YOU ARE ON YOUR OWN. ! |
| 309 | 412 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| 310 You need to either install developer firmware, or change system rootkey. | 413 " >&2 |
| 311 | 414 local i |
| 312 - To install developer firmware: type command | 415 for i in $(seq 5 -1 1); do |
| 313 sudo chromeos-firmwareupdate --mode=todev | 416 echo -n "\rStart in $i second(s) (^C to abort)... " >&2 |
| 314 | 417 sleep 1 |
| 315 - To change system rootkey: disable firmware write protection (a hardware | 418 done |
| 316 switch) and then type command: | 419 echo "" |
| 317 sudo ./make_dev_firmware.sh | 420 elif ! sanity_check_live_firmware || |
| 318 | 421 ! sanity_check_live_partitions; then |
| 319 If you are sure that you want to make such image without developer | 422 err_die "IMAGE $FLAGS_image IS NOT MODIFIED." |
| 320 firmware or you've already changed system root keys, please run this | 423 fi |
| 321 command again with --force param: | |
| 322 | |
| 323 sudo ./make_dev_ssd.sh --force $ORIGINAL_PARAMS | |
| 324 | |
| 325 YOUR IMAGE $FLAGS_image IS NOT MODIFIED. | |
| 326 " | |
| 327 exit 1 | |
| 328 fi | 424 fi |
| 329 | 425 |
| 330 resign_ssd_kernel "$FLAGS_image" || num_signed=$? | 426 resign_ssd_kernel "$FLAGS_image" || num_signed=$? |
| 331 | 427 |
| 332 debug_msg "Complete." | 428 debug_msg "Complete." |
| 333 if [ $num_signed -gt 0 -a $num_signed -le $num_given ]; then | 429 if [ $num_signed -gt 0 -a $num_signed -le $num_given ]; then |
| 334 # signed something at least | 430 # signed something at least |
| 335 echo "Successfully re-signed $num_signed of $num_given kernel(s)" \ | 431 echo "Successfully re-signed $num_signed of $num_given kernel(s)" \ |
| 336 " on device $FLAGS_image". | 432 " on device $FLAGS_image". |
| 337 else | 433 else |
| 338 err_die "Failed re-signing kernels." | 434 err_die "Failed re-signing kernels." |
| 339 fi | 435 fi |
| 340 } | 436 } |
| 341 | 437 |
| 342 # People using this to process images may forget to add "-i", | 438 # People using this to process images may forget to add "-i", |
| 343 # so adding parameter check is safer. | 439 # so adding parameter check is safer. |
| 344 if [ "$#" -gt 0 ]; then | 440 if [ "$#" -gt 0 ]; then |
| 345 flags_help | 441 flags_help |
| 346 err_die "Unknown parameters: $@" | 442 err_die "Unknown parameters: $@" |
| 347 fi | 443 fi |
| 348 | 444 |
| 349 main | 445 main |
| OLD | NEW |