| 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 |