OLD | NEW |
1 #!/bin/bash | 1 #!/bin/bash |
2 | 2 |
3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2009 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 # Script to build a bootable keyfob-based chromeos system image. | 7 # Script to build a bootable keyfob-based chromeos system image. |
8 # It uses debootstrap (see https://wiki.ubuntu.com/DebootstrapChroot) to | 8 # It uses debootstrap (see https://wiki.ubuntu.com/DebootstrapChroot) to |
9 # create a base file system. It then cusotmizes the file system and adds | 9 # create a base file system. It then cusotmizes the file system and adds |
10 # Ubuntu and chromeos specific packages. Finally, it creates a bootable USB | 10 # Ubuntu and chromeos specific packages. Finally, it creates a bootable USB |
(...skipping 20 matching lines...) Expand all Loading... |
31 "Root of build output" | 31 "Root of build output" |
32 DEFINE_boolean replace $FLAGS_FALSE "Overwrite existing output, if any." | 32 DEFINE_boolean replace $FLAGS_FALSE "Overwrite existing output, if any." |
33 DEFINE_boolean increment $FLAGS_FALSE \ | 33 DEFINE_boolean increment $FLAGS_FALSE \ |
34 "Picks the latest build and increments the minor version by one." | 34 "Picks the latest build and increments the minor version by one." |
35 | 35 |
36 DEFINE_string mirror "$DEFAULT_IMG_MIRROR" "Repository mirror to use." | 36 DEFINE_string mirror "$DEFAULT_IMG_MIRROR" "Repository mirror to use." |
37 DEFINE_string suite "$DEFAULT_IMG_SUITE" "Repository suite to base image on." | 37 DEFINE_string suite "$DEFAULT_IMG_SUITE" "Repository suite to base image on." |
38 DEFINE_string pkglist "$DEFAULT_PKGLIST" \ | 38 DEFINE_string pkglist "$DEFAULT_PKGLIST" \ |
39 "Name of file listing packages to install from repository." | 39 "Name of file listing packages to install from repository." |
40 | 40 |
41 DEFINE_string mirror2 "$DEFAULT_EXT_MIRROR" "Additional mirror to use." | |
42 DEFINE_string suite2 "$DEFAULT_EXT_SUITE" "Suite to use in additional mirror." | |
43 DEFINE_string pkglist2 "" \ | |
44 "Name of file listing packages to install from additional mirror." | |
45 | |
46 KERNEL_DEB_PATH=$(find "${FLAGS_build_root}/x86/local_packages" -name "linux-ima
ge-*.deb") | 41 KERNEL_DEB_PATH=$(find "${FLAGS_build_root}/x86/local_packages" -name "linux-ima
ge-*.deb") |
47 KERNEL_DEB=$(basename "${KERNEL_DEB_PATH}" .deb | sed -e 's/linux-image-//' -e '
s/_.*//') | 42 KERNEL_DEB=$(basename "${KERNEL_DEB_PATH}" .deb | sed -e 's/linux-image-//' -e '
s/_.*//') |
48 KERNEL_VERSION=${KERNEL_VERSION:-${KERNEL_DEB}} | 43 KERNEL_VERSION=${KERNEL_VERSION:-${KERNEL_DEB}} |
49 | 44 |
50 # Parse command line | 45 # Parse command line |
51 FLAGS "$@" || exit 1 | 46 FLAGS "$@" || exit 1 |
52 eval set -- "${FLAGS_ARGV}" | 47 eval set -- "${FLAGS_ARGV}" |
53 | 48 |
54 # Die on any errors. | 49 # Die on any errors. |
55 set -e | 50 set -e |
56 | 51 |
57 # Determine build version | 52 # Determine build version |
58 . "${SCRIPTS_DIR}/chromeos_version.sh" | 53 . "${SCRIPTS_DIR}/chromeos_version.sh" |
59 | 54 |
60 # Use canonical path since some tools (e.g. mount) do not like symlinks | 55 # Use canonical path since some tools (e.g. mount) do not like symlinks |
61 # Append build attempt to output directory | 56 # Append build attempt to output directory |
62 IMAGE_SUBDIR="${CHROMEOS_VERSION_STRING}-a${FLAGS_build_attempt}" | 57 IMAGE_SUBDIR="${CHROMEOS_VERSION_STRING}-a${FLAGS_build_attempt}" |
63 OUTPUT_DIR="${FLAGS_output_root}/${IMAGE_SUBDIR}" | 58 OUTPUT_DIR="${FLAGS_output_root}/${IMAGE_SUBDIR}" |
64 ROOT_FS_DIR="${OUTPUT_DIR}/rootfs" | 59 ROOT_FS_DIR="${OUTPUT_DIR}/rootfs" |
65 ROOT_FS_IMG="${OUTPUT_DIR}/rootfs.image" | 60 ROOT_FS_IMG="${OUTPUT_DIR}/rootfs.image" |
66 MBR_IMG="${OUTPUT_DIR}/mbr.image" | 61 MBR_IMG="${OUTPUT_DIR}/mbr.image" |
67 OUTPUT_IMG="${OUTPUT_DIR}/usb.img" | 62 OUTPUT_IMG="${OUTPUT_DIR}/usb.img" |
68 | 63 SETUP_DIR="${OUTPUT_DIR}/tmp" |
69 # These paths are relative to SCRIPTS_DIR. | |
70 ROOTFS_PACKAGE_INSTALL_SCRIPT="install_packages.sh" | |
71 ROOTFS_CUSTOMIZE_SCRIPT="customize_rootfs.sh" | |
72 | |
73 ROOTFS_STATIC_DATA="${SRC_ROOT}/rootfs_static_data" | |
74 ROOTFS_SETUP_DIR="/tmp/chromeos_setup" | |
75 SETUP_DIR="${ROOT_FS_DIR}/${ROOTFS_SETUP_DIR}" | |
76 | 64 |
77 LOOP_DEV= | 65 LOOP_DEV= |
78 | 66 |
79 # Handle existing directory | 67 # Handle existing directory |
80 if [ -e "$OUTPUT_DIR" ] | 68 if [ -e "$OUTPUT_DIR" ] |
81 then | 69 then |
82 if [ $FLAGS_replace -eq $FLAGS_TRUE ] | 70 if [ $FLAGS_replace -eq $FLAGS_TRUE ] |
83 then | 71 then |
84 sudo rm -rf "$OUTPUT_DIR" | 72 sudo rm -rf "$OUTPUT_DIR" |
85 else | 73 else |
(...skipping 18 matching lines...) Expand all Loading... |
104 echo "Killing process that has open file on our rootfs: $cmdline" | 92 echo "Killing process that has open file on our rootfs: $cmdline" |
105 ! sudo kill $pid # Preceded by ! to disable ERR trap. | 93 ! sudo kill $pid # Preceded by ! to disable ERR trap. |
106 done | 94 done |
107 | 95 |
108 # Sometimes the volatile directory is left mounted and sometimes it is not, | 96 # Sometimes the volatile directory is left mounted and sometimes it is not, |
109 # so we precede by '!' to disable the ERR trap. | 97 # so we precede by '!' to disable the ERR trap. |
110 ! sudo umount "$ROOT_FS_DIR"/lib/modules/2.6.*/volatile/ | 98 ! sudo umount "$ROOT_FS_DIR"/lib/modules/2.6.*/volatile/ |
111 | 99 |
112 sudo umount "${ROOT_FS_DIR}/proc" | 100 sudo umount "${ROOT_FS_DIR}/proc" |
113 sudo umount "${ROOT_FS_DIR}/sys" | 101 sudo umount "${ROOT_FS_DIR}/sys" |
114 sudo umount "${ROOT_FS_DIR}/trunk" | |
115 } | 102 } |
116 | 103 |
117 cleanup_rootfs_loop() { | 104 cleanup_rootfs_loop() { |
118 sudo umount "$LOOP_DEV" | 105 sudo umount "$LOOP_DEV" |
119 sleep 1 # in case $LOOP_DEV is in use | 106 sleep 1 # in case $LOOP_DEV is in use |
120 sudo losetup -d "$LOOP_DEV" | 107 sudo losetup -d "$LOOP_DEV" |
121 } | 108 } |
122 | 109 |
123 cleanup() { | 110 cleanup() { |
124 # Disable die on error. | 111 # Disable die on error. |
125 set +e | 112 set +e |
126 | 113 |
127 cleanup_rootfs_mounts | 114 cleanup_rootfs_mounts |
128 if [ -n "$LOOP_DEV" ] | 115 if [ -n "$LOOP_DEV" ] |
129 then | 116 then |
130 cleanup_rootfs_loop | 117 cleanup_rootfs_loop |
131 fi | 118 fi |
132 | 119 |
133 # Turn die on error back on. | 120 # Turn die on error back on. |
134 set -e | 121 set -e |
135 } | 122 } |
136 trap cleanup EXIT | 123 trap cleanup EXIT |
137 | 124 |
138 mkdir -p "$ROOT_FS_DIR" | 125 mkdir -p "$ROOT_FS_DIR" |
139 | 126 |
140 # Create root file system disk image to fit on a 1GB memory stick. | 127 # Create root file system disk image to fit on a 1GB memory stick. |
141 # 1 GB in hard-drive-manufacturer-speak is 10^9, not 2^30. 950MB < 10^9 bytes. | 128 # 1 GB in hard-drive-manufacturer-speak is 10^9, not 2^30. 700MB < 10^9 bytes. |
142 ROOT_SIZE_BYTES=$((1024 * 1024 * 950)) | 129 ROOT_SIZE_BYTES=$((1024 * 1024 * 700)) |
143 dd if=/dev/zero of="$ROOT_FS_IMG" bs=1 count=1 seek=$((ROOT_SIZE_BYTES - 1)) | 130 dd if=/dev/zero of="$ROOT_FS_IMG" bs=1 count=1 seek=$((ROOT_SIZE_BYTES - 1)) |
144 | 131 |
145 # Format, tune, and mount the rootfs. | 132 # Format, tune, and mount the rootfs. |
146 # Make sure we have a mtab to keep mkfs happy. | 133 # Make sure we have a mtab to keep mkfs happy. |
147 if [ ! -e /etc/mtab ]; then | 134 if [ ! -e /etc/mtab ]; then |
148 sudo touch /etc/mtab | 135 sudo touch /etc/mtab |
149 fi | 136 fi |
150 UUID=`uuidgen` | 137 UUID=`uuidgen` |
151 DISK_LABEL=C-ROOT | 138 DISK_LABEL=C-ROOT |
152 LOOP_DEV=`sudo losetup -f` | 139 LOOP_DEV=`sudo losetup -f` |
153 sudo losetup "$LOOP_DEV" "$ROOT_FS_IMG" | 140 sudo losetup "$LOOP_DEV" "$ROOT_FS_IMG" |
154 sudo mkfs.ext3 "$LOOP_DEV" | 141 sudo mkfs.ext3 "$LOOP_DEV" |
155 sudo tune2fs -L "$DISK_LABEL" -U "$UUID" -c 0 -i 0 "$LOOP_DEV" | 142 sudo tune2fs -L "$DISK_LABEL" -U "$UUID" -c 0 -i 0 "$LOOP_DEV" |
156 sudo mount "$LOOP_DEV" "$ROOT_FS_DIR" | 143 sudo mount "$LOOP_DEV" "$ROOT_FS_DIR" |
157 | 144 |
158 # Add debootstrap link for the suite, if it doesn't exist. | 145 # Add debootstrap link for the suite, if it doesn't exist. |
159 if [ ! -e "/usr/share/debootstrap/scripts/$FLAGS_suite" ] | 146 if [ ! -e "/usr/share/debootstrap/scripts/$FLAGS_suite" ] |
160 then | 147 then |
161 sudo ln -s /usr/share/debootstrap/scripts/jaunty \ | 148 sudo ln -s /usr/share/debootstrap/scripts/jaunty \ |
162 "/usr/share/debootstrap/scripts/$FLAGS_suite" | 149 "/usr/share/debootstrap/scripts/$FLAGS_suite" |
163 fi | 150 fi |
164 | 151 |
165 # Bootstrap the base debian file system | 152 # Bootstrap the base debian file system |
| 153 # TODO: Switch to --variant=minbase |
166 sudo debootstrap --arch=i386 $FLAGS_suite "$ROOT_FS_DIR" "${FLAGS_mirror}" | 154 sudo debootstrap --arch=i386 $FLAGS_suite "$ROOT_FS_DIR" "${FLAGS_mirror}" |
167 | 155 |
168 # -- Customize the root file system -- | 156 # -- Customize the root file system -- |
169 | 157 |
170 # Set up mounts for working within the chroot. We copy some basic | 158 # Set up mounts for working within the chroot. We copy some basic |
171 # network information from the host so that the chroot can access | 159 # network information from the host so that the chroot can access |
172 # repositories on the network as needed. | 160 # repositories on the network as needed. |
173 sudo mount -t proc proc "${ROOT_FS_DIR}/proc" | 161 sudo mount -t proc proc "${ROOT_FS_DIR}/proc" |
174 sudo mount -t sysfs sysfs "${ROOT_FS_DIR}/sys" # TODO: Do we need sysfs? | 162 sudo mount -t sysfs sysfs "${ROOT_FS_DIR}/sys" # TODO: Do we need sysfs? |
175 sudo cp /etc/hosts "${ROOT_FS_DIR}/etc" | 163 sudo cp /etc/hosts "${ROOT_FS_DIR}/etc" |
176 | 164 |
177 # Set up bind mount for trunk, so we can get to package repository | |
178 # TODO: also use this instead of SETUP_DIR for other things below? | |
179 sudo mkdir -p "$ROOT_FS_DIR/trunk" | |
180 sudo mount --bind "$GCLIENT_ROOT" "$ROOT_FS_DIR/trunk" | |
181 | |
182 # Create setup directory and copy over scripts, config files, and locally | 165 # Create setup directory and copy over scripts, config files, and locally |
183 # built packages. | 166 # built packages. |
184 mkdir -p "$SETUP_DIR" | 167 mkdir -p "$SETUP_DIR" |
185 mkdir -p "${SETUP_DIR}/local_packages" | 168 mkdir -p "${SETUP_DIR}/local_packages" |
186 cp "${SCRIPTS_DIR}/${ROOTFS_PACKAGE_INSTALL_SCRIPT}" "$SETUP_DIR" | |
187 cp -r "$ROOTFS_STATIC_DATA" "$SETUP_DIR" | |
188 cp "$FLAGS_pkglist" "${SETUP_DIR}/package-list-prod.txt" | |
189 cp "${FLAGS_build_root}/x86/local_packages"/* "${SETUP_DIR}/local_packages" | 169 cp "${FLAGS_build_root}/x86/local_packages"/* "${SETUP_DIR}/local_packages" |
190 | 170 |
191 if [ -n "$FLAGS_pkglist2" ] | |
192 then | |
193 cp "$FLAGS_pkglist2" "${SETUP_DIR}/package-list-2.txt" | |
194 fi | |
195 | |
196 # Set up repository for local packages to install in the rootfs via apt-get. | 171 # Set up repository for local packages to install in the rootfs via apt-get. |
197 cd "$SETUP_DIR" | 172 cd "$SETUP_DIR" |
198 dpkg-scanpackages local_packages/ /dev/null | \ | 173 dpkg-scanpackages local_packages/ /dev/null | \ |
199 gzip > local_packages/Packages.gz | 174 gzip > local_packages/Packages.gz |
200 cd - | 175 cd - |
201 | 176 |
202 # File-type mirrors have a different path when bind-mounted inside the chroot | |
203 # ${FOO/bar/baz} replaces bar with baz when evaluating $FOO. | |
204 MIRROR_INSIDE="${FLAGS_mirror/$GCLIENT_ROOT//trunk}" | |
205 MIRROR2_INSIDE="${FLAGS_mirror2/$GCLIENT_ROOT//trunk}" | |
206 | |
207 # Write options for customize script into the chroot | |
208 CUST_OPTS="${SETUP_DIR}/customize_opts.sh" | |
209 cat <<EOF > $CUST_OPTS | |
210 REAL_USER=$USER | |
211 SETUP_DIR="$ROOTFS_SETUP_DIR" | |
212 KERNEL_VERSION="$KERNEL_VERSION" | |
213 SERVER="$MIRROR_INSIDE" | |
214 SUITE="$FLAGS_suite" | |
215 SERVER2="$MIRROR2_INSIDE" | |
216 SUITE2="$FLAGS_suite2" | |
217 EOF | |
218 # ...and all CHROMEOS_ vars | |
219 set | egrep "^CHROMEOS_|^BUILDBOT_" >> $CUST_OPTS | |
220 | |
221 # Run the package install script | 177 # Run the package install script |
222 sudo chroot "$ROOT_FS_DIR" \ | 178 "${SCRIPTS_DIR}/install_packages.sh" \ |
223 "${ROOTFS_SETUP_DIR}/${ROOTFS_PACKAGE_INSTALL_SCRIPT}" | 179 --root="$ROOT_FS_DIR" \ |
| 180 --output_dir="${OUTPUT_DIR}" \ |
| 181 --setup_dir="${SETUP_DIR}" \ |
| 182 --package_list="$FLAGS_pkglist" \ |
| 183 --server="$FLAGS_mirror" \ |
| 184 --suite="$FLAGS_suite" \ |
| 185 --kernel_version="$KERNEL_VERSION" |
224 | 186 |
225 # Run the script to customize the resulting root file system. | 187 # Run the script to customize the resulting root file system. |
226 "${SCRIPTS_DIR}/${ROOTFS_CUSTOMIZE_SCRIPT}" --root="${ROOT_FS_DIR}" | 188 "${SCRIPTS_DIR}/customize_rootfs.sh" --root="${ROOT_FS_DIR}" |
227 | |
228 # No longer need the setup directory in the rootfs. | |
229 rm -rf "$SETUP_DIR" | |
230 | |
231 # Move package lists from the image into the output dir | |
232 sudo mv "$ROOT_FS_DIR"/etc/package_list_*.txt "$OUTPUT_DIR" | |
233 | 189 |
234 # Unmount mounts within the rootfs so it is ready to be imaged. | 190 # Unmount mounts within the rootfs so it is ready to be imaged. |
235 cleanup_rootfs_mounts | 191 cleanup_rootfs_mounts |
236 | 192 |
237 # -- Turn root file system into bootable image -- | 193 # -- Turn root file system into bootable image -- |
238 | 194 |
239 # Setup extlinux configuration. | 195 # Setup extlinux configuration. |
240 # TODO: For some reason the /dev/disk/by-uuid is not being generated by udev | 196 # TODO: For some reason the /dev/disk/by-uuid is not being generated by udev |
241 # in the initramfs. When we figure that out, switch to root=UUID=$UUID. | 197 # in the initramfs. When we figure that out, switch to root=UUID=$UUID. |
242 cat <<EOF | sudo dd of="$ROOT_FS_DIR"/boot/extlinux.conf | 198 cat <<EOF | sudo dd of="$ROOT_FS_DIR"/boot/extlinux.conf |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 EOF | 231 EOF |
276 | 232 |
277 OUTSIDE_OUTPUT_DIR="${EXTERNAL_TRUNK_PATH}/src/build/images/${IMAGE_SUBDIR}" | 233 OUTSIDE_OUTPUT_DIR="${EXTERNAL_TRUNK_PATH}/src/build/images/${IMAGE_SUBDIR}" |
278 echo "Done. Image created in ${OUTPUT_DIR}" | 234 echo "Done. Image created in ${OUTPUT_DIR}" |
279 echo "To copy to USB keyfob, outside the chroot, do something like:" | 235 echo "To copy to USB keyfob, outside the chroot, do something like:" |
280 echo " ./image_to_usb.sh --from=${OUTSIDE_OUTPUT_DIR} --to=/dev/sdb" | 236 echo " ./image_to_usb.sh --from=${OUTSIDE_OUTPUT_DIR} --to=/dev/sdb" |
281 echo "To convert to VMWare image, outside the chroot, do something like:" | 237 echo "To convert to VMWare image, outside the chroot, do something like:" |
282 echo " ./image_to_vmware.sh --from=${OUTSIDE_OUTPUT_DIR}" | 238 echo " ./image_to_vmware.sh --from=${OUTSIDE_OUTPUT_DIR}" |
283 | 239 |
284 trap - EXIT | 240 trap - EXIT |
OLD | NEW |