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 # Script which ensures that a given image has an up-to-date | |
8 # kernel partition, rootfs integrity hashes, and legacy bootloader configs. | |
9 | |
10 # Load common constants. This should be the first executable line. | |
11 # The path to common.sh should be relative to your script's location. | |
12 COMMON_PATH="/usr/lib/crosutils/common.sh" | |
13 if [ ! -r "${COMMON_PATH}" ]; then | |
14 echo "ERROR! Cannot find common.sh: ${COMMON_PATH}" 1>&2 | |
15 exit 1 | |
16 fi | |
17 . "/usr/lib/crosutils/common.sh" | |
18 | |
19 set -e | |
20 . "/usr/lib/installer/chromeos-common.sh" # for partoffset and partsize | |
21 if [ $# -lt 2 ]; then | |
22 echo "Usage: ${0} /PATH/TO/IMAGE IMAGE.BIN [shflags overrides]" | |
23 exit 1 | |
24 fi | |
25 | |
26 BOOT_DESC_FILE="${1}/boot.desc" | |
27 IMAGE="${1}/${2}" | |
28 shift | |
29 shift | |
30 FLAG_OVERRIDES="${@}" | |
31 | |
32 if [ ! -r "${BOOT_DESC_FILE}" ]; then | |
33 warn "${BOOT_DESC_FILE} cannot be read!" | |
34 warn "Falling back to command line parsing" | |
35 BOOT_DESC="${@}" | |
36 else | |
37 BOOT_DESC="$(cat ${BOOT_DESC_FILE} | tr -s '\n' ' ')" | |
38 info "Boot-time configuration for $(dirname ${IMAGE}): " | |
39 cat ${BOOT_DESC_FILE} | while read line; do | |
40 info " ${line}" | |
41 done | |
42 fi | |
43 | |
44 if [ ! -r "${IMAGE}" ]; then | |
45 die "${IMAGE} cannot be read!" | |
46 fi | |
47 | |
48 # Script must be run inside the chroot. | |
49 restart_in_chroot_if_needed $* | |
50 | |
51 locate_gpt | |
52 set +e | |
53 | |
54 # Now parse the build settings from ${OUTPUT_DIR}/boot.desc | |
55 | |
56 DEFINE_string output_dir "/tmp" \ | |
57 "Directory to place output in." | |
58 DEFINE_string image "chromiumos_base.img" \ | |
59 "Full path to the chromiumos image to make bootable." | |
60 DEFINE_string arch "x86" \ | |
61 "Architecture to make bootable for: arm or x86" | |
62 DEFINE_string usb_disk "/dev/sdb3" \ | |
63 "Path syslinux should use to do a usb boot." | |
64 DEFINE_boolean cleanup_dirs ${FLAGS_TRUE} \ | |
65 "Whether the mount dirs should be removed on completion." | |
66 | |
67 DEFINE_integer rootfs_size 720 \ | |
68 "rootfs filesystem size in MBs." | |
69 # ceil(0.1 * rootfs_size) is a good minimum. | |
70 DEFINE_integer rootfs_hash_pad 8 \ | |
71 "MBs reserved at the end of the rootfs image." | |
72 | |
73 DEFINE_string rootfs_hash "/tmp/rootfs.hash" \ | |
74 "Path where the rootfs hash should be stored." | |
75 DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \ | |
76 "Default all bootloaders to use kernel-based root fs integrity checking." | |
77 DEFINE_integer verity_error_behavior 2 \ | |
78 "Kernel verified boot error behavior (0: I/O errors, 1: reboot, 2: nothing)" | |
79 DEFINE_integer verity_depth 1 \ | |
80 "Kernel verified boot hash tree depth" | |
81 DEFINE_integer verity_max_ios 1024 \ | |
82 "Number of outstanding I/O operations dm-verity caps at." | |
83 DEFINE_string verity_algorithm "sha1" \ | |
84 "Cryptographic hash algorithm used for kernel vboot." | |
85 | |
86 DEFINE_string arm_extra_bootargs "" \ | |
87 "Additional command line options to pass to the ARM kernel." | |
88 | |
89 DEFINE_string keys_dir "/usr/share/vboot/devkeys" \ | |
90 "Directory containing the signing keys." | |
91 | |
92 DEFINE_string rootfs_mountpoint "/tmp/rootfs" \ | |
93 "Path where the rootfs can be safely mounted" | |
94 DEFINE_string statefulfs_mountpoint "/tmp/statefulfs" \ | |
95 "Path where the statefulfs can be safely mounted" | |
96 DEFINE_string espfs_mountpoint "/tmp/espfs" \ | |
97 "Path where the espfs can be safely mounted" | |
98 | |
99 DEFINE_boolean use_dev_keys ${FLAGS_FALSE} \ | |
100 "Use developer keys for signing. (Default: false)" | |
101 | |
102 # Parse the boot.desc and any overrides | |
103 eval set -- "${BOOT_DESC} ${FLAG_OVERRIDES}" | |
104 FLAGS "${@}" || exit 1 | |
105 | |
106 # Only now can we die on error. shflags functions leak non-zero error codes, | |
107 # so will die prematurely if 'set -e' is specified before now. | |
108 set -e -u | |
109 | |
110 # $1 - Directory where developer rootfs is mounted. | |
111 # $2 - Directory where developer stateful_partition is mounted. | |
112 # $3 - Directory where the ESP partition is mounted. | |
113 mount_gpt_cleanup() { | |
114 local rootfs="${1-$FLAGS_rootfs_mountpoint}" | |
115 local statefs="${2-$FLAGS_statefulfs_mountpoint}" | |
116 local espfs="${3-$FLAGS_espfs_mountpoint}" | |
117 "/usr/bin/cros_mount_gpt_image.sh" \ | |
118 -u -r "${rootfs}" -s "${statefs}" -e "${espfs}" | |
119 } | |
120 | |
121 make_image_bootable() { | |
122 local image="$1" | |
123 local use_dev_keys= | |
124 | |
125 cros_root=/dev/sd%D%P | |
126 if [[ "${FLAGS_arch}" = "arm" ]]; then | |
127 # TODO(wad) assumed like in build_gpt for now. | |
128 cros_root=/dev/mmcblk1p3 | |
129 fi | |
130 if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then | |
131 cros_root=/dev/dm-0 | |
132 fi | |
133 | |
134 trap "mount_gpt_cleanup" EXIT | |
135 /usr/bin/cros_mount_gpt_image.sh --from "$(dirname ${image})" \ | |
136 --image "$(basename ${image})" -r "${FLAGS_rootfs_mountpoint}" \ | |
137 -s "${FLAGS_statefulfs_mountpoint}" | |
138 | |
139 # The rootfs should never be mounted rw again after this point without | |
140 # re-calling make_image_bootable. | |
141 sudo mount -o remount,ro "${FLAGS_rootfs_mountpoint}" | |
142 root_dev=$(mount | grep -- "on ${FLAGS_rootfs_mountpoint} type" | | |
143 cut -f1 -d' ' | tail -1) | |
144 | |
145 if [ ${FLAGS_use_dev_keys} -eq ${FLAGS_TRUE} ]; then | |
146 use_dev_keys="--use_dev_keys" | |
147 fi | |
148 | |
149 # Builds the kernel partition image. The temporary files are kept around | |
150 # so that we can perform a load_kernel_test later on the final image. | |
151 /usr/bin/cros_build_kernel_image.sh \ | |
152 --arch="${FLAGS_arch}" \ | |
153 --to="${FLAGS_output_dir}/vmlinuz.image" \ | |
154 --hd_vblock="${FLAGS_output_dir}/vmlinuz_hd.vblock" \ | |
155 --vmlinuz="${FLAGS_rootfs_mountpoint}/boot/vmlinuz" \ | |
156 --working_dir="${FLAGS_output_dir}" \ | |
157 --keep_work \ | |
158 --rootfs_image=${root_dev} \ | |
159 --rootfs_hash=${FLAGS_rootfs_hash} \ | |
160 --verity_hash_alg=${FLAGS_verity_algorithm} \ | |
161 --verity_tree_depth=${FLAGS_verity_depth} \ | |
162 --verity_max_ios=${FLAGS_verity_max_ios} \ | |
163 --verity_error_behavior=${FLAGS_verity_error_behavior} \ | |
164 --root=${cros_root} \ | |
165 --keys_dir="${FLAGS_keys_dir}" \ | |
166 ${use_dev_keys} | |
167 | |
168 local rootfs_hash_size=$(stat -c '%s' ${FLAGS_rootfs_hash}) | |
169 info "Appending rootfs.hash (${rootfs_hash_size} bytes) to the root fs" | |
170 if [[ ${rootfs_hash_size} -gt $((FLAGS_rootfs_hash_pad * 1024 * 1024)) ]] | |
171 then | |
172 die "--rootfs_hash_pad reserves less than the needed ${rootfs_hash_size}" | |
173 fi | |
174 # Unfortunately, cros_mount_gpt_image uses mount and not losetup to create the | |
175 # loop devices. This means that they are not the correct size. We have to | |
176 # write directly to the image to append the hash tree data. | |
177 local hash_offset="$(partoffset ${image} 3)" | |
178 hash_offset=$((hash_offset + ((1024 * 1024 * ${FLAGS_rootfs_size}) / 512))) | |
179 sudo dd bs=512 \ | |
180 seek=${hash_offset} \ | |
181 if="${FLAGS_rootfs_hash}" \ | |
182 of="${image}" \ | |
183 conv=notrunc | |
184 # We don't need to keep the file around anymore. | |
185 sudo rm "${FLAGS_rootfs_hash}" | |
186 | |
187 # Move the verification block needed for the hard disk install to the | |
188 # stateful partition. Mount stateful fs, copy file, and umount fs. | |
189 # In original CL: http://codereview.chromium.org/2868044, this was done in | |
190 # create_base_image(). However, it could break the build if it is a clean | |
191 # build because vmlinuz_hd.vblock hasn't been created by | |
192 # cros_build_kernel_image.sh | |
193 if [[ "${FLAGS_arch}" = "x86" ]]; then | |
194 sudo cp "${FLAGS_output_dir}/vmlinuz_hd.vblock" \ | |
195 "${FLAGS_statefulfs_mountpoint}" | |
196 fi | |
197 | |
198 # START_KERN_A is set by the first call to install the gpt. | |
199 local koffset="$(partoffset ${image} 2)" | |
200 sudo dd if="${FLAGS_output_dir}/vmlinuz.image" of="${image}" \ | |
201 conv=notrunc bs=512 seek=${koffset} | |
202 | |
203 # Update the bootloaders. For legacy/efi x86, the EFI system partition | |
204 # will be updated and for arm, the mbr will be updated (for u-boot). | |
205 local kernel_part= | |
206 local usb_disk="${FLAGS_usb_disk}" | |
207 | |
208 # We should update the esp in place in the image. | |
209 local bootloader_to="${image}" | |
210 local esp_offset="$(partoffset ${image} 12)" | |
211 esp_offset=$((esp_offset * 512)) # sectors to bytes | |
212 local esp_size="$(partsize ${image} 12)" | |
213 esp_size=$((esp_size * 512)) # sectors to bytes | |
214 local bootloader_to_flags="--to_offset=${esp_offset} --to_size=${esp_size}" | |
215 | |
216 if [[ "${FLAGS_arch}" = "x86" ]]; then | |
217 # Use the kernel partition to acquire configuration flags. | |
218 kernel_part="--kernel_partition='${FLAGS_output_dir}/vmlinuz.image'" | |
219 # Install syslinux on the EFI System Partition. | |
220 kernel_part="${kernel_part} --install_syslinux" | |
221 elif [[ "${FLAGS_arch}" = "arm" ]]; then | |
222 # TODO(wad) mmcblk1p3 is hardcoded for arm for now! | |
223 usb_disk="/dev/mmcblk1p3" | |
224 # ARM doesn't support using the kernel image for kernel cmdline flags yet. | |
225 kernel_part="--kernel_cmdline=\"${FLAGS_arm_extra_bootargs}\" " | |
226 # TODO(wad) Integrate dmtable extraction into the arm build | |
227 # E.g. $(cat ${FLAGS_output_dir}/boot.config | tr -s '\n' ' ')" | |
228 local kpart_offset="--kernel_partition_offset=${koffset}" | |
229 local kpart_size="--kernel_partition_sectors=" | |
230 kpart_size="${kpart_size}$(partsize ${image} 2)" | |
231 kernel_part="${kernel_part} ${kpart_size} ${kpart_offset}" | |
232 info "Using addition bootloader arguments: ${kernel_part}" | |
233 fi | |
234 | |
235 # Update partition 12 | |
236 /usr/bin/cros_update_bootloaders.sh \ | |
237 --arch=${FLAGS_arch} \ | |
238 --to="${bootloader_to}" \ | |
239 --from="${FLAGS_rootfs_mountpoint}"/boot \ | |
240 --vmlinuz="${FLAGS_rootfs_mountpoint}"/boot/vmlinuz \ | |
241 --usb_disk="${usb_disk}" \ | |
242 ${bootloader_to_flags} \ | |
243 $kernel_part | |
244 | |
245 trap - EXIT | |
246 /usr/bin/cros_mount_gpt_image.sh -u -r "${FLAGS_rootfs_mountpoint}" \ | |
247 -s "${FLAGS_statefulfs_mountpoint}" | |
248 } | |
249 | |
250 # Create the directories if they don't exist. | |
251 mkdir -p ${FLAGS_rootfs_mountpoint} | |
252 mkdir -p ${FLAGS_statefulfs_mountpoint} | |
253 mkdir -p ${FLAGS_espfs_mountpoint} | |
254 | |
255 make_image_bootable ${IMAGE} | |
256 | |
257 if [ ${FLAGS_cleanup_dirs} -eq ${FLAGS_TRUE} ]; then | |
258 rmdir ${FLAGS_rootfs_mountpoint} | |
259 rmdir ${FLAGS_statefulfs_mountpoint} | |
260 rmdir ${FLAGS_espfs_mountpoint} | |
261 fi | |
OLD | NEW |