diff --git a/bin/cros_make_image_bootable b/bin/cros_make_image_bootable index e9acf310f8..38783cbc70 100755 --- a/bin/cros_make_image_bootable +++ b/bin/cros_make_image_bootable @@ -99,8 +99,12 @@ DEFINE_integer rootfs_hash_pad 8 \ DEFINE_string rootfs_hash "/tmp/rootfs.hash" \ "Path where the rootfs hash should be stored." +# TODO(taysom): when we turn on boot cache, both verification and +# bootcache should have their default be FLAGS_TRUE. DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \ - "Default all bootloaders to use kernel-based root fs integrity checking." + "Default all bootloaders to NOT use kernel-based root fs integrity checking." +DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \ + "Default all bootloaders to NOT use bootcache." DEFINE_integer verity_error_behavior 3 \ "Kernel verified boot error behavior (0: I/O errors, 1: reboot, 2: nothing)" DEFINE_integer verity_max_ios -1 \ @@ -173,6 +177,10 @@ make_image_bootable() { if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then enable_rootfs_verification_flag=--enable_rootfs_verification fi + local enable_bootcache_flag=--noenable_bootcache + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + enable_bootcache_flag=--enable_bootcache + fi trap "mount_gpt_cleanup" EXIT "${SCRIPTS_DIR}/mount_gpt_image.sh" --from "$(dirname "${image}")" \ @@ -233,6 +241,7 @@ make_image_bootable() { --verity_salt=${FLAGS_verity_salt} \ --keys_dir="${FLAGS_keys_dir}" \ ${enable_rootfs_verification_flag} \ + ${enable_bootcache_flag} \ ${use_dev_keys} # Check the size of kernel image and issue warning when image size is diff --git a/build_image b/build_image index 28940b0a5a..b03b6f4726 100755 --- a/build_image +++ b/build_image @@ -19,6 +19,8 @@ DEFINE_string board "${DEFAULT_BOARD}" \ "The board to build an image for." DEFINE_string boot_args "noinitrd" \ "Additional boot arguments to pass to the commandline" +DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \ + "Default all bootloaders to NOT use boot cache." DEFINE_boolean enable_rootfs_verification ${FLAGS_TRUE} \ "Default all bootloaders to use kernel-based root fs integrity checking." DEFINE_string output_root "${DEFAULT_BUILD_ROOT}/images" \ @@ -30,6 +32,14 @@ DEFINE_boolean standard_backdoor ${FLAGS_TRUE} \ DEFINE_string usb_disk /dev/sdb3 \ "Path syslinux should use to do a usb boot. Default: /dev/sdb3" +FLAGS_bootcache_use_board_default=${FLAGS_TRUE} +case " $* " in + *" --enable_bootcache "*|\ + *" --noenable_bootcache "*) + FLAGS_bootcache_use_board_default=${FLAGS_FALSE} + ;; +esac + FLAGS_HELP="USAGE: build_image [flags] [list of images to build]. This script is used to build a Chromium OS image. Chromium OS comes in many different forms. This scripts can be used to build the following: @@ -175,7 +185,8 @@ fi mkdir -p "${BUILD_DIR}" # Create the base image. -create_base_image ${PRISTINE_IMAGE_NAME} +create_base_image ${PRISTINE_IMAGE_NAME} ${FLAGS_enable_rootfs_verification} \ + ${FLAGS_enable_bootcache} # Running board-specific setup if any exists. if type board_setup &>/dev/null; then diff --git a/build_kernel_image.sh b/build_kernel_image.sh index 63917c9e3e..167e1991df 100755 --- a/build_kernel_image.sh +++ b/build_kernel_image.sh @@ -47,6 +47,8 @@ DEFINE_string verity_salt "" \ "Salt to use for rootfs hash (Default: \"\")" DEFINE_boolean enable_rootfs_verification ${FLAGS_TRUE} \ "Enable kernel-based root fs integrity checking. (Default: true)" +DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \ + "Enable boot cache to accelerate booting. (Default: false)" # Parse flags FLAGS "$@" || exit 1 @@ -55,7 +57,28 @@ eval set -- "${FLAGS_ARGV}" # Die on error switch_to_strict_mode -verity_args= +rootdigest() { + local digest=${table#*root_hexdigest=} + echo ${digest% salt*} +} + +salt() { + local salt=${table#*salt=} + echo ${salt%} +} + +hashstart() { + local hash=${table#*hashstart=} + echo ${hash% alg*} +} + +# Estimate of sectors used by verity +# (num blocks) * 32 (bytes per hash) * 2 (overhead) / 512 (bytes per sector) +veritysize() { + echo $((root_fs_blocks * 32 * 2 / 512)) +} + +device_mapper_args= # Even with a rootfs_image, root= is not changed unless specified. if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then # Gets the number of blocks. 4096 byte blocks _are_ expected. @@ -94,12 +117,29 @@ if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then # Don't claim the root device unless verity is enabled. # Doing so will claim /dev/sdDP out from under the system. if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then - base_root='%U+1' # kern_guid + 1 + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + base_root='254:0' # major:minor numbers for /dev/dm-0 + else + base_root='%U+1' # kern_guid + 1 + fi table=${table//HASH_DEV/${base_root}} table=${table//ROOT_DEV/${base_root}} fi - verity_args="dm=\"vroot none ro,${table}\"" - info "dm-verity configuration: ${verity_args}" + verity_dev="vroot none ro 1,${table}" + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + signature=$(rootdigest) + cachestart=$(($(hashstart) + $(veritysize))) + size_limit=512 + max_trace=20000 + max_pages=100000 + bootcache_args="%U+1 ${cachestart} ${signature} ${size_limit}" + bootcache_args="${bootcache_args} ${max_trace} ${max_pages}" + bootcache_dev="vboot none ro 1,0 ${cachestart} bootcache ${bootcache_args}" + device_mapper_args="dm=\"2 ${bootcache_dev}, ${verity_dev}\"" + else + device_mapper_args="dm=\"1 ${verity_dev}\"" + fi + info "device mapper configuration: ${device_mapper_args}" fi mkdir -p "${FLAGS_working_dir}" @@ -111,8 +151,16 @@ mkdir -p "${FLAGS_working_dir}" dev_wait=0 root_dev="PARTUUID=%U/PARTNROFF=1" if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then - root_dev=/dev/dm-0 dev_wait=1 + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + root_dev=/dev/dm-1 + else + root_dev=/dev/dm-0 + fi +else + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + die "Having bootcache without verity is not supported" + fi fi cat < "${FLAGS_working_dir}/boot.config" @@ -122,7 +170,7 @@ ro dm_verity.error_behavior=${FLAGS_verity_error_behavior} dm_verity.max_bios=${FLAGS_verity_max_ios} dm_verity.dev_wait=${dev_wait} -${verity_args} +${device_mapper_args} ${FLAGS_boot_args} vt.global_cursor_default=0 kern_guid=%U diff --git a/build_library/base_image_util.sh b/build_library/base_image_util.sh index 898d433f95..84b31118c7 100755 --- a/build_library/base_image_util.sh +++ b/build_library/base_image_util.sh @@ -47,6 +47,7 @@ zero_free_space() { create_base_image() { local image_name=$1 local rootfs_verification_enabled=$2 + local bootcache_enabled=$3 local image_type="usb" if [[ "${FLAGS_disk_layout}" != "default" ]]; then @@ -223,15 +224,20 @@ create_base_image() { # not support verified boot yet (see create_legacy_bootloader_templates.sh) # so rootfs verification is disabled if we are building with --factory_install local enable_rootfs_verification= - if [[ ${rootfs_verification_enabled} -eq 1 ]]; then - enable_rootfs_verification="--enable_rootfs_verification" + if [[ ${rootfs_verification_enabled} -eq ${FLAGS_TRUE} ]]; then + enable_rootfs_verification="--enable_rootfs_verification" + fi + local enable_bootcache= + if [[ ${bootcache_enabled} -eq ${FLAGS_TRUE} ]]; then + enable_bootcache="--enable_bootcache" fi ${BUILD_LIBRARY_DIR}/create_legacy_bootloader_templates.sh \ --arch=${ARCH} \ --to="${root_fs_dir}"/boot \ --boot_args="${FLAGS_boot_args}" \ - ${enable_rootfs_verification} + ${enable_rootfs_verification} \ + ${enable_bootcache} # Don't test the factory install shim if ! should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index e35f2b25bf..523b3e3d9c 100755 --- a/build_library/build_image_util.sh +++ b/build_library/build_image_util.sh @@ -121,6 +121,10 @@ create_boot_desc() { if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then enable_rootfs_verification_flag="--enable_rootfs_verification" fi + local enable_bootcache_flag="" + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + enable_bootcache_flag=--enable_bootcache + fi [ -z "${FLAGS_verity_salt}" ] && FLAGS_verity_salt=$(make_salt) cat < ${BUILD_DIR}/boot.desc @@ -133,6 +137,7 @@ create_boot_desc() { --nocleanup_dirs --verity_algorithm=sha1 ${enable_rootfs_verification_flag} + ${enable_bootcache_flag} EOF } diff --git a/build_library/create_legacy_bootloader_templates.sh b/build_library/create_legacy_bootloader_templates.sh index 4b74379cee..73bcb4cca3 100755 --- a/build_library/create_legacy_bootloader_templates.sh +++ b/build_library/create_legacy_bootloader_templates.sh @@ -22,6 +22,8 @@ DEFINE_string usb_disk /dev/sdb3 \ "Path syslinux should use to do a usb boot. Default: /dev/sdb3" DEFINE_string boot_args "" \ "Additional boot arguments to pass to the commandline (Default: '')" +DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \ + "Default all bootloaders to NOT use boot cache." DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \ "Controls if verity is used for root filesystem checking (Default: false)" DEFINE_integer verity_error_behavior 3 \ @@ -36,9 +38,14 @@ eval set -- "${FLAGS_ARGV}" switch_to_strict_mode # Only let dm-verity block if rootfs verification is configured. +# Also, set which device mapper correspondes to verity dev_wait=0 +ROOTDEV=/dev/dm-0 if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then dev_wait=1 + if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then + ROOTDEV=/dev/dm-1 + fi fi # Common kernel command-line args @@ -104,7 +111,8 @@ label chromeos-usb.A label chromeos-vusb.A menu label chromeos-vusb.A kernel vmlinuz.A - append ${common_args} ${verity_common} root=/dev/dm-0 i915.modeset=1 cros_legacy dm="DMTABLEA" + append ${common_args} ${verity_common} root=${ROOTDEV} \ + i915.modeset=1 cros_legacy dm="DMTABLEA" EOF info "Emitted ${SYSLINUX_DIR}/usb.A.cfg" @@ -120,7 +128,8 @@ label chromeos-hd.A label chromeos-vhd.A menu label chromeos-vhd.A kernel vmlinuz.A - append ${common_args} ${verity_common} root=/dev/dm-0 i915.modeset=1 cros_legacy dm="DMTABLEA" + append ${common_args} ${verity_common} root=${ROOTDEV} \ + i915.modeset=1 cros_legacy dm="DMTABLEA" EOF info "Emitted ${SYSLINUX_DIR}/root.A.cfg" @@ -133,7 +142,8 @@ label chromeos-hd.B label chromeos-vhd.B menu label chromeos-vhd.B kernel vmlinuz.B - append ${common_args} ${verity_common} root=/dev/dm-0 i915.modeset=1 cros_legacy dm="DMTABLEB" + append ${common_args} ${verity_common} root=${ROOTDEV} \ + i915.modeset=1 cros_legacy dm="DMTABLEB" EOF info "Emitted ${SYSLINUX_DIR}/root.B.cfg" @@ -175,11 +185,13 @@ menuentry "local image B" { } menuentry "verified image A" { - linux \$grubpartA/boot/vmlinuz ${common_args} ${verity_common} i915.modeset=1 cros_efi root=/dev/dm-0 dm=\\"DMTABLEA\\" + linux \$grubpartA/boot/vmlinuz ${common_args} ${verity_common} \ + i915.modeset=1 cros_efi root=${ROOTDEV} dm=\\"DMTABLEA\\" } menuentry "verified image B" { - linux \$grubpartB/boot/vmlinuz ${common_args} ${verity_common} i915.modeset=1 cros_efi root=/dev/dm-0 dm=\\"DMTABLEB\\" + linux \$grubpartB/boot/vmlinuz ${common_args} ${verity_common} \ + i915.modeset=1 cros_efi root=${ROOTDEV} dm=\\"DMTABLEB\\" } # FIXME: usb doesn't support verified boot for now