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 # Helper script that generates the signed kernel image | |
8 | |
9 . "/usr/lib/crosutils/common.sh" | |
10 | |
11 get_default_board | |
12 | |
13 # Flags. | |
14 DEFINE_string arch "x86" \ | |
15 "The boot architecture: arm or x86. (Default: x86)" | |
16 DEFINE_string to "/tmp/vmlinuz.image" \ | |
17 "The path to the kernel image to be created. (Default: /tmp/vmlinuz.image)" | |
18 DEFINE_string hd_vblock "/tmp/vmlinuz_hd.vblock" \ | |
19 "The path to the installed kernel's vblock (Default: /tmp/vmlinuz_hd.vblock)" | |
20 DEFINE_string vmlinuz "vmlinuz" \ | |
21 "The path to the kernel (Default: vmlinuz)" | |
22 DEFINE_string working_dir "/tmp/vmlinuz.working" \ | |
23 "Working directory for in-progress files. (Default: /tmp/vmlinuz.working)" | |
24 DEFINE_boolean keep_work ${FLAGS_FALSE} \ | |
25 "Keep temporary files (*.keyblock, *.vbpubk). (Default: false)" | |
26 DEFINE_string keys_dir "${SRC_ROOT}/platform/vboot_reference/tests/testkeys" \ | |
27 "Directory with the RSA signing keys. (Defaults to test keys)" | |
28 DEFINE_boolean use_dev_keys ${FLAGS_FALSE} \ | |
29 "Use developer keys for signing. (Default: false)" | |
30 # Note, to enable verified boot, the caller would manually pass: | |
31 # --boot_args='dm="... /dev/sd%D%P /dev/sd%D%P ..." \ | |
32 # --root=/dev/dm-0 | |
33 DEFINE_string boot_args "noinitrd" \ | |
34 "Additional boot arguments to pass to the commandline (Default: noinitrd)" | |
35 DEFINE_string root "/dev/sd%D%P" \ | |
36 "Expected device root (Default: root=/dev/sd%D%P)" | |
37 | |
38 # If provided, will automatically add verified boot arguments. | |
39 DEFINE_string rootfs_image "" \ | |
40 "Optional path to the rootfs device or image.(Default: \"\")" | |
41 DEFINE_string rootfs_hash "" \ | |
42 "Optional path to output the rootfs hash to. (Default: \"\")" | |
43 DEFINE_integer verity_error_behavior 2 \ | |
44 "Verified boot error behavior [0: I/O errors, 1: reboot, 2: nothing] \ | |
45 (Default: 2)" | |
46 DEFINE_integer verity_tree_depth 1 \ | |
47 "Optional Verified boot hash tree depth. (Default: 1)" | |
48 DEFINE_integer verity_max_ios 1024 \ | |
49 "Optional number of outstanding I/O operations. (Default: 1024)" | |
50 DEFINE_string verity_hash_alg "sha1" \ | |
51 "Cryptographic hash algorithm used for dm-verity. (Default: sha1)" | |
52 | |
53 # Parse flags | |
54 FLAGS "$@" || exit 1 | |
55 eval set -- "${FLAGS_ARGV}" | |
56 | |
57 # Die on error | |
58 set -e | |
59 | |
60 verity_args= | |
61 # Even with a rootfs_image, root= is not changed unless specified. | |
62 if [[ -n "${FLAGS_rootfs_image}" && -n "${FLAGS_rootfs_hash}" ]]; then | |
63 # Gets the number of blocks. 4096 byte blocks _are_ expected. | |
64 root_fs_blocks=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null | | |
65 grep "Block count" | | |
66 tr -d ' ' | | |
67 cut -f2 -d:) | |
68 root_fs_block_sz=$(sudo dumpe2fs "${FLAGS_rootfs_image}" 2> /dev/null | | |
69 grep "Block size" | | |
70 tr -d ' ' | | |
71 cut -f2 -d:) | |
72 info "rootfs is ${root_fs_blocks} blocks of ${root_fs_block_sz} bytes" | |
73 if [[ ${root_fs_block_sz} -ne 4096 ]]; then | |
74 error "Root file system blocks are not 4k!" | |
75 fi | |
76 | |
77 info "Generating root fs hash tree." | |
78 # Runs as sudo in case the image is a block device. | |
79 table=$(sudo verity create ${FLAGS_verity_tree_depth} \ | |
80 ${FLAGS_verity_hash_alg} \ | |
81 ${FLAGS_rootfs_image} \ | |
82 ${root_fs_blocks} \ | |
83 ${FLAGS_rootfs_hash}) | |
84 if [[ -f "${FLAGS_rootfs_hash}" ]]; then | |
85 sudo chmod a+r "${FLAGS_rootfs_hash}" | |
86 fi | |
87 # Don't claim the root device unless the root= flag is pointed to | |
88 # the verified boot device. Doing so will claim /dev/sdDP out from | |
89 # under the system. | |
90 if [[ ${FLAGS_root} = "/dev/dm-0" ]]; then | |
91 table=${table//HASH_DEV//dev/sd%D%P} | |
92 table=${table//ROOT_DEV//dev/sd%D%P} | |
93 fi | |
94 verity_args="dm=\"vroot none ro,${table}\"" | |
95 info "dm-verity configuration: ${verity_args}" | |
96 fi | |
97 | |
98 mkdir -p "${FLAGS_working_dir}" | |
99 cat <<EOF > "${FLAGS_working_dir}/boot.config" | |
100 root=${FLAGS_root} | |
101 dm_verity.error_behavior=${FLAGS_verity_error_behavior} | |
102 dm_verity.max_bios=${FLAGS_verity_max_ios} | |
103 ${verity_args} | |
104 ${FLAGS_boot_args} | |
105 EOF | |
106 | |
107 WORK="${WORK} ${FLAGS_working_dir}/boot.config" | |
108 info "Emitted cross-platform boot params to ${FLAGS_working_dir}/boot.config" | |
109 | |
110 # FIXME: At the moment, we're working on signed images for x86 only. ARM will | |
111 # support this before shipping, but at the moment they don't. | |
112 if [[ "${FLAGS_arch}" = "x86" ]]; then | |
113 | |
114 # Legacy BIOS will use the kernel in the rootfs (via syslinux), as will | |
115 # standard EFI BIOS (via grub, from the EFI System Partition). Chrome OS | |
116 # BIOS will use a separate signed kernel partition, which we'll create now. | |
117 # FIXME: remove serial output, debugging messages. | |
118 mkdir -p ${FLAGS_working_dir} | |
119 cat <<EOF | cat - "${FLAGS_working_dir}/boot.config" \ | |
120 > "${FLAGS_working_dir}/config.txt" | |
121 earlyprintk=serial,ttyS0,115200 | |
122 console=ttyS0,115200 | |
123 init=/sbin/init | |
124 add_efi_memmap | |
125 boot=local | |
126 rootwait | |
127 ro | |
128 noresume | |
129 noswap | |
130 i915.modeset=1 | |
131 loglevel=7 | |
132 cros_secure | |
133 kern_guid=%U | |
134 EOF | |
135 WORK="${WORK} ${FLAGS_working_dir}/config.txt" | |
136 | |
137 # We sign the image with the recovery_key, because this is what goes onto the | |
138 # USB key. We can only boot from the USB drive in recovery mode. | |
139 # For dev install shim, we need to use the installer keyblock instead of | |
140 # the recovery keyblock because of the difference in flags. | |
141 if [ ${FLAGS_use_dev_keys} -eq ${FLAGS_TRUE} ]; then | |
142 USB_KEYBLOCK=installer_kernel.keyblock | |
143 info "DEBUG: use dev install signing key" | |
144 else | |
145 USB_KEYBLOCK=recovery_kernel.keyblock | |
146 info "DEBUG: use recovery signing key" | |
147 fi | |
148 | |
149 # Create and sign the kernel blob | |
150 vbutil_kernel \ | |
151 --pack "${FLAGS_to}" \ | |
152 --keyblock "${FLAGS_keys_dir}/${USB_KEYBLOCK}" \ | |
153 --signprivate "${FLAGS_keys_dir}/recovery_kernel_data_key.vbprivk" \ | |
154 --version 1 \ | |
155 --config "${FLAGS_working_dir}/config.txt" \ | |
156 --bootloader /lib64/bootstub/bootstub.efi \ | |
157 --vmlinuz "${FLAGS_vmlinuz}" | |
158 | |
159 # And verify it. | |
160 vbutil_kernel \ | |
161 --verify "${FLAGS_to}" \ | |
162 --signpubkey "${FLAGS_keys_dir}/recovery_key.vbpubk" | |
163 | |
164 | |
165 # Now we re-sign the same image using the normal keys. This is the kernel | |
166 # image that is put on the hard disk by the installer. Note: To save space on | |
167 # the USB image, we're only emitting the new verfication block, and the | |
168 # installer just replaces that part of the hard disk's kernel partition. | |
169 vbutil_kernel \ | |
170 --repack "${FLAGS_hd_vblock}" \ | |
171 --vblockonly \ | |
172 --keyblock "${FLAGS_keys_dir}/kernel.keyblock" \ | |
173 --signprivate "${FLAGS_keys_dir}/kernel_data_key.vbprivk" \ | |
174 --oldblob "${FLAGS_to}" | |
175 | |
176 | |
177 # To verify it, we have to replace the vblock from the original image. | |
178 tempfile=$(mktemp) | |
179 trap "rm -f $tempfile" EXIT | |
180 cat "${FLAGS_hd_vblock}" > $tempfile | |
181 dd if="${FLAGS_to}" bs=65536 skip=1 >> $tempfile | |
182 | |
183 vbutil_kernel \ | |
184 --verify $tempfile \ | |
185 --signpubkey "${FLAGS_keys_dir}/kernel_subkey.vbpubk" | |
186 | |
187 rm -f $tempfile | |
188 trap - EXIT | |
189 | |
190 elif [[ "${FLAGS_arch}" = "arm" ]]; then | |
191 # FIXME: For now, ARM just uses the unsigned kernel by itself. | |
192 cp -f "${FLAGS_vmlinuz}" "${FLAGS_to}" | |
193 else | |
194 error "Unknown arch: ${FLAGS_arch}" | |
195 fi | |
196 | |
197 set +e # cleanup failure is a-ok | |
198 | |
199 if [[ ${FLAGS_keep_work} -eq ${FLAGS_FALSE} ]]; then | |
200 info "Cleaning up temporary files: ${WORK}" | |
201 rm ${WORK} | |
202 rmdir ${FLAGS_working_dir} | |
203 fi | |
204 | |
205 info "Kernel partition image emitted: ${FLAGS_to}" | |
206 | |
207 if [[ -f ${FLAGS_rootfs_hash} ]]; then | |
208 info "Root filesystem hash emitted: ${FLAGS_rootfs_hash}" | |
209 fi | |
OLD | NEW |