blob: e20f16e784ea922604cdc324116fee57c7281ec8 [file] [log] [blame]
Will Drewry69563b72010-06-24 16:12:58 -05001#!/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# Helper script that generates the signed kernel image
8
9. "$(dirname "$0")/common.sh"
10
11get_default_board
12
13# Flags.
14DEFINE_string arch "x86" \
15 "The boot architecture: arm or x86. (Default: x86)"
16DEFINE_string to "/tmp/vmlinuz.image" \
17 "The path to the kernel image to be created. (Default: /tmp/vmlinuz.image)"
18DEFINE_string vmlinuz "vmlinuz" \
19 "The path to the kernel (Default: vmlinuz)"
20DEFINE_string working_dir "/tmp/vmlinuz.working" \
21 "Working directory for in-progress files. (Default: /tmp/vmlinuz.working)"
22DEFINE_boolean keep_work ${FLAGS_FALSE} \
23 "Keep temporary files (*.keyblock, *.vbpubk). (Default: false)"
24DEFINE_string keys_dir "${SRC_ROOT}/platform/vboot_reference/tests/testkeys" \
Bill Richardson2ace49e2010-07-01 10:23:27 -070025 "Directory with the RSA signing keys. (Defaults to test keys)"
Will Drewrybcbf1c42010-07-03 10:23:30 -050026# Note, to enable verified boot, the caller would manually pass:
Will Drewry69563b72010-06-24 16:12:58 -050027# --boot_args='dm="... /dev/sd%D%P /dev/sd%D%P ..." \
28# --root=/dev/dm-0
29DEFINE_string boot_args "noinitrd" \
30 "Additional boot arguments to pass to the commandline (Default: noinitrd)"
31DEFINE_string root "/dev/sd%D%P" \
32 "Expected device root (Default: root=/dev/sd%D%P)"
33
Will Drewrybcbf1c42010-07-03 10:23:30 -050034# If provided, will automatically add verified boot arguments.
35DEFINE_string rootfs_image "" \
36 "Optional path to the rootfs device or image.(Default: \"\")"
37DEFINE_string rootfs_hash "" \
38 "Optional path to output the rootfs hash to. (Default: \"\")"
39DEFINE_integer vboot_error_behavior 2 \
40 "Verified boot error behavior [0: I/O errors, 1: reboot, 2: nothing] \
41(Default: 2)"
42DEFINE_integer vboot_tree_depth 1 \
43 "Optional Verified boot hash tree depth. (Default: 1)"
44DEFINE_integer vboot_max_ios 1024 \
45 "Optional number of outstanding I/O operations. (Default: 1024)"
46DEFINE_string vboot_hash_alg "sha1" \
47 "Cryptographic hash algorithm used for vboot. (Default: sha1)"
48
Will Drewry69563b72010-06-24 16:12:58 -050049# Parse flags
50FLAGS "$@" || exit 1
51eval set -- "${FLAGS_ARGV}"
52
53# Die on error
54set -e
55
Will Drewrybcbf1c42010-07-03 10:23:30 -050056vboot_args=
57# Even with a rootfs_image, root= is not changed unless specified.
58if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then
59 info "Determining root fs block count."
60 # Gets the number of blocks. 4096 byte blocks _are_ expected.
61 root_fs_blocks=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null |
62 grep "Block count" |
63 tr -d ' ' |
64 cut -f2 -d:)
65 info "Checking root fs block size."
66 root_fs_block_sz=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null |
67 grep "Block size" |
68 tr -d ' ' |
69 cut -f2 -d:)
70 if [[ ${root_fs_block_sz} -ne 4096 ]]; then
71 error "Root file system blocks are not 4k!"
72 fi
73
74 info "Generating root fs hash tree."
75 # Runs as sudo in case the image is a block device.
76 table=$(sudo verity create ${FLAGS_vboot_tree_depth} \
77 ${FLAGS_vboot_hash_alg} \
78 ${FLAGS_rootfs_image} \
79 ${root_fs_blocks} \
80 ${FLAGS_rootfs_hash})
Will Drewry821d07c2010-07-03 17:14:58 -070081 if [[ -f "${FLAGS_rootfs_hash}" ]]; then
82 sudo chmod a+r "${FLAGS_rootfs_hash}"
83 fi
Will Drewrybcbf1c42010-07-03 10:23:30 -050084 # Don't claim the root device unless the root= flag is pointed to
85 # the verified boot device. Doing so will claim /dev/sdDP out from
86 # under the system.
87 if [[ ${FLAGS_root} = "/dev/dm-0" ]]; then
88 table=${table//HASH_DEV/\/dev\/sd%D%P}
89 table=${table//ROOT_DEV/\/dev\/sd%D%P}
90 fi
91 vboot_args="dm=\"${table}\""
92 info "dm-verity configuration: ${vboot_args}"
93fi
94
95mkdir -p "${FLAGS_working_dir}"
96cat <<EOF > "${FLAGS_working_dir}/boot.config"
97root=${FLAGS_root}
98dm_verity.error_behavior=${FLAGS_vboot_error_behavior}
99dm_verity.max_bios=${FLAGS_vboot_max_ios}
100${vboot_args}
101${FLAGS_boot_args}
102EOF
103
104WORK="${WORK} ${FLAGS_working_dir}/boot.config"
105info "Emitted cross-platform boot params to ${FLAGS_working_dir}/boot.config"
106
Will Drewry69563b72010-06-24 16:12:58 -0500107# FIXME: At the moment, we're working on signed images for x86 only. ARM will
108# support this before shipping, but at the moment they don't.
109if [[ "${FLAGS_arch}" = "x86" ]]; then
110
Will Drewrybcbf1c42010-07-03 10:23:30 -0500111 # Legacy BIOS will use the kernel in the rootfs (via syslinux), as will
112 # standard EFI BIOS (via grub, from the EFI System Partition). Chrome OS
113 # BIOS will use a separate signed kernel partition, which we'll create now.
114 # FIXME: remove serial output, debugging messages.
115 mkdir -p ${FLAGS_working_dir}
116 cat <<EOF | cat - "${FLAGS_working_dir}/boot.config" \
117 > "${FLAGS_working_dir}/config.txt"
Will Drewry69563b72010-06-24 16:12:58 -0500118earlyprintk=serial,ttyS0,115200
119console=ttyS0,115200
120init=/sbin/init
121add_efi_memmap
122boot=local
123rootwait
Will Drewry69563b72010-06-24 16:12:58 -0500124ro
125noresume
126noswap
127i915.modeset=1
128loglevel=7
129cros_secure
Will Drewry69563b72010-06-24 16:12:58 -0500130EOF
Will Drewrybcbf1c42010-07-03 10:23:30 -0500131 WORK="${WORK} ${FLAGS_working_dir}/config.txt"
Will Drewry69563b72010-06-24 16:12:58 -0500132
Bill Richardson2ace49e2010-07-01 10:23:27 -0700133
Will Drewrybcbf1c42010-07-03 10:23:30 -0500134 # FIX: The .vbprivk files are not encrypted, so we shouldn't just leave them
135 # lying around as a general thing.
Bill Richardson2ace49e2010-07-01 10:23:27 -0700136
Will Drewrybcbf1c42010-07-03 10:23:30 -0500137 # Wrap the kernel data keypair, used for the kernel body
138 vbutil_key \
139 --pack "${FLAGS_working_dir}/kernel_data_key.vbpubk" \
140 --key "${FLAGS_keys_dir}/key_rsa2048.keyb" \
141 --version 1 \
142 --algorithm 4
143 WORK="${WORK} ${FLAGS_working_dir}/kernel_data_key.vbpubk"
Will Drewry69563b72010-06-24 16:12:58 -0500144
Will Drewrybcbf1c42010-07-03 10:23:30 -0500145 vbutil_key \
146 --pack "${FLAGS_working_dir}/kernel_data_key.vbprivk" \
147 --key "${FLAGS_keys_dir}/key_rsa2048.pem" \
148 --algorithm 4
149 WORK="${WORK} ${FLAGS_working_dir}/kernel_data_key.vbprivk"
Will Drewry69563b72010-06-24 16:12:58 -0500150
Bill Richardson2ace49e2010-07-01 10:23:27 -0700151
Will Drewrybcbf1c42010-07-03 10:23:30 -0500152 # Wrap the kernel subkey pair, used for the kernel's keyblock
153 vbutil_key \
154 --pack "${FLAGS_working_dir}/kernel_subkey.vbpubk" \
155 --key "${FLAGS_keys_dir}/key_rsa4096.keyb" \
156 --version 1 \
157 --algorithm 8
158 WORK="${WORK} ${FLAGS_working_dir}/kernel_subkey.vbpubk"
Bill Richardson2ace49e2010-07-01 10:23:27 -0700159
Will Drewrybcbf1c42010-07-03 10:23:30 -0500160 vbutil_key \
161 --pack "${FLAGS_working_dir}/kernel_subkey.vbprivk" \
162 --key "${FLAGS_keys_dir}/key_rsa4096.pem" \
163 --algorithm 8
164 WORK="${WORK} ${FLAGS_working_dir}/kernel_subkey.vbprivk"
Bill Richardson2ace49e2010-07-01 10:23:27 -0700165
166
Will Drewrybcbf1c42010-07-03 10:23:30 -0500167 # Create the kernel keyblock, containing the kernel data key
168 vbutil_keyblock \
169 --pack "${FLAGS_working_dir}/kernel.keyblock" \
170 --datapubkey "${FLAGS_working_dir}/kernel_data_key.vbpubk" \
171 --signprivate "${FLAGS_working_dir}/kernel_subkey.vbprivk" \
172 --flags 15
173 WORK="${WORK} ${FLAGS_working_dir}/kernel.keyblock"
Will Drewry69563b72010-06-24 16:12:58 -0500174
Will Drewrybcbf1c42010-07-03 10:23:30 -0500175 # Verify the keyblock.
176 vbutil_keyblock \
177 --unpack "${FLAGS_working_dir}/kernel.keyblock" \
178 --signpubkey "${FLAGS_working_dir}/kernel_subkey.vbpubk"
Will Drewry69563b72010-06-24 16:12:58 -0500179
Will Drewrybcbf1c42010-07-03 10:23:30 -0500180 # TODO: We should sign the kernel blob using the recovery root key and
181 # recovery kernel data key instead (to create the recovery image), and then
182 # re-sign it this way for the install image. But we'll want to keep the
183 # install vblock separate, so we can just copy that part over separately when
184 # we install it instead of the whole kernel blob.
Bill Richardson2ace49e2010-07-01 10:23:27 -0700185
Will Drewrybcbf1c42010-07-03 10:23:30 -0500186 # Create and sign the kernel blob
187 vbutil_kernel \
188 --pack "${FLAGS_to}" \
189 --keyblock "${FLAGS_working_dir}/kernel.keyblock" \
190 --signprivate "${FLAGS_working_dir}/kernel_data_key.vbprivk" \
191 --version 1 \
192 --config "${FLAGS_working_dir}/config.txt" \
193 --bootloader /lib64/bootstub/bootstub.efi \
194 --vmlinuz "${FLAGS_vmlinuz}"
Will Drewry69563b72010-06-24 16:12:58 -0500195
Will Drewrybcbf1c42010-07-03 10:23:30 -0500196 # And verify it.
197 vbutil_kernel \
198 --verify "${FLAGS_to}" \
199 --signpubkey "${FLAGS_working_dir}/kernel_subkey.vbpubk"
Will Drewry69563b72010-06-24 16:12:58 -0500200
Will Drewrybcbf1c42010-07-03 10:23:30 -0500201elif [[ "${FLAGS_arch}" = "arm" ]]; then
Will Drewry69563b72010-06-24 16:12:58 -0500202 # FIXME: For now, ARM just uses the unsigned kernel by itself.
203 cp -f "${FLAGS_vmlinuz}" "${FLAGS_to}"
Will Drewrybcbf1c42010-07-03 10:23:30 -0500204else
205 error "Unknown arch: ${FLAGS_arch}"
Will Drewry69563b72010-06-24 16:12:58 -0500206fi
207
208set +e # cleanup failure is a-ok
209
210if [[ ${FLAGS_keep_work} -eq ${FLAGS_FALSE} ]]; then
Will Drewrybcbf1c42010-07-03 10:23:30 -0500211 info "Cleaning up temporary files: ${WORK}"
Will Drewry69563b72010-06-24 16:12:58 -0500212 rm ${WORK}
213 rmdir ${FLAGS_working_dir}
214fi
215
Will Drewrybcbf1c42010-07-03 10:23:30 -0500216info "Kernel partition image emitted: ${FLAGS_to}"
217
218if [[ -f ${FLAGS_rootfs_hash} ]]; then
219 info "Root filesystem hash emitted: ${FLAGS_rootfs_hash}"
220fi