mirror of
https://github.com/flatcar/scripts.git
synced 2025-09-23 14:41:31 +02:00
and install debs into the target rootfs. This will still run the maintainer scripts, but it is a step in the right direction to being able to create a cross-compiled image. This will allow us to experiment with disabling the maintainer scripts and attempt to get that working. It also makes it easier to modify the install_packages script since it now has access to shflags and the source tree properly. This CL also cleans up stuff doing in build_image.sh to bind mount the trunk into the target rootfs, set up packages for install there, etc. The next step is to experiment with disabling maintainer scripts. One possible way to do that would be to put a shim in place of dpkg so that when apt calls dpkg it install a package we call dpkg-deb with a simple unpack instead. This would allow us to continue to use the good nice features that apt provides. Review URL: http://codereview.chromium.org/517003
241 lines
7.9 KiB
Bash
Executable File
241 lines
7.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
# Script to build a bootable keyfob-based chromeos system image.
|
|
# It uses debootstrap (see https://wiki.ubuntu.com/DebootstrapChroot) to
|
|
# create a base file system. It then cusotmizes the file system and adds
|
|
# Ubuntu and chromeos specific packages. Finally, it creates a bootable USB
|
|
# image from the root fs.
|
|
#
|
|
# NOTE: This script must be run from the chromeos build chroot environment.
|
|
#
|
|
|
|
# Load common constants. This should be the first executable line.
|
|
# The path to common.sh should be relative to your script's location.
|
|
. "$(dirname "$0")/common.sh"
|
|
|
|
# Script must be run inside the chroot
|
|
assert_inside_chroot
|
|
|
|
DEFAULT_PKGLIST="${SRC_ROOT}/package_repo/package-list-prod.txt"
|
|
|
|
# Flags
|
|
DEFINE_integer build_attempt 1 \
|
|
"The build attempt for this image build."
|
|
DEFINE_string output_root "${DEFAULT_BUILD_ROOT}/images" \
|
|
"Directory in which to place image result directories (named by version)"
|
|
DEFINE_string build_root "$DEFAULT_BUILD_ROOT" \
|
|
"Root of build output"
|
|
DEFINE_boolean replace $FLAGS_FALSE "Overwrite existing output, if any."
|
|
DEFINE_boolean increment $FLAGS_FALSE \
|
|
"Picks the latest build and increments the minor version by one."
|
|
|
|
DEFINE_string mirror "$DEFAULT_IMG_MIRROR" "Repository mirror to use."
|
|
DEFINE_string suite "$DEFAULT_IMG_SUITE" "Repository suite to base image on."
|
|
DEFINE_string pkglist "$DEFAULT_PKGLIST" \
|
|
"Name of file listing packages to install from repository."
|
|
|
|
KERNEL_DEB_PATH=$(find "${FLAGS_build_root}/x86/local_packages" -name "linux-image-*.deb")
|
|
KERNEL_DEB=$(basename "${KERNEL_DEB_PATH}" .deb | sed -e 's/linux-image-//' -e 's/_.*//')
|
|
KERNEL_VERSION=${KERNEL_VERSION:-${KERNEL_DEB}}
|
|
|
|
# Parse command line
|
|
FLAGS "$@" || exit 1
|
|
eval set -- "${FLAGS_ARGV}"
|
|
|
|
# Die on any errors.
|
|
set -e
|
|
|
|
# Determine build version
|
|
. "${SCRIPTS_DIR}/chromeos_version.sh"
|
|
|
|
# Use canonical path since some tools (e.g. mount) do not like symlinks
|
|
# Append build attempt to output directory
|
|
IMAGE_SUBDIR="${CHROMEOS_VERSION_STRING}-a${FLAGS_build_attempt}"
|
|
OUTPUT_DIR="${FLAGS_output_root}/${IMAGE_SUBDIR}"
|
|
ROOT_FS_DIR="${OUTPUT_DIR}/rootfs"
|
|
ROOT_FS_IMG="${OUTPUT_DIR}/rootfs.image"
|
|
MBR_IMG="${OUTPUT_DIR}/mbr.image"
|
|
OUTPUT_IMG="${OUTPUT_DIR}/usb.img"
|
|
SETUP_DIR="${OUTPUT_DIR}/tmp"
|
|
|
|
LOOP_DEV=
|
|
|
|
# Handle existing directory
|
|
if [ -e "$OUTPUT_DIR" ]
|
|
then
|
|
if [ $FLAGS_replace -eq $FLAGS_TRUE ]
|
|
then
|
|
sudo rm -rf "$OUTPUT_DIR"
|
|
else
|
|
echo "Directory $OUTPUT_DIR already exists."
|
|
echo "Use --build_attempt option to specify an unused attempt."
|
|
echo "Or use --replace if you want to overwrite this directory."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# create the output directory
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# Make sure anything mounted in the rootfs is cleaned up ok on exit.
|
|
cleanup_rootfs_mounts() {
|
|
# Occasionally there are some daemons left hanging around that have our
|
|
# root image file system open. We do a best effort attempt to kill them.
|
|
PIDS=`sudo lsof -t "$ROOT_FS_DIR" | sort | uniq`
|
|
for pid in $PIDS
|
|
do
|
|
local cmdline=`cat /proc/$pid/cmdline`
|
|
echo "Killing process that has open file on our rootfs: $cmdline"
|
|
! sudo kill $pid # Preceded by ! to disable ERR trap.
|
|
done
|
|
|
|
# Sometimes the volatile directory is left mounted and sometimes it is not,
|
|
# so we precede by '!' to disable the ERR trap.
|
|
! sudo umount "$ROOT_FS_DIR"/lib/modules/2.6.*/volatile/
|
|
|
|
sudo umount "${ROOT_FS_DIR}/proc"
|
|
sudo umount "${ROOT_FS_DIR}/sys"
|
|
}
|
|
|
|
cleanup_rootfs_loop() {
|
|
sudo umount "$LOOP_DEV"
|
|
sleep 1 # in case $LOOP_DEV is in use
|
|
sudo losetup -d "$LOOP_DEV"
|
|
}
|
|
|
|
cleanup() {
|
|
# Disable die on error.
|
|
set +e
|
|
|
|
cleanup_rootfs_mounts
|
|
if [ -n "$LOOP_DEV" ]
|
|
then
|
|
cleanup_rootfs_loop
|
|
fi
|
|
|
|
# Turn die on error back on.
|
|
set -e
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "$ROOT_FS_DIR"
|
|
|
|
# Create root file system disk image to fit on a 1GB memory stick.
|
|
# 1 GB in hard-drive-manufacturer-speak is 10^9, not 2^30. 700MB < 10^9 bytes.
|
|
ROOT_SIZE_BYTES=$((1024 * 1024 * 700))
|
|
dd if=/dev/zero of="$ROOT_FS_IMG" bs=1 count=1 seek=$((ROOT_SIZE_BYTES - 1))
|
|
|
|
# Format, tune, and mount the rootfs.
|
|
# Make sure we have a mtab to keep mkfs happy.
|
|
if [ ! -e /etc/mtab ]; then
|
|
sudo touch /etc/mtab
|
|
fi
|
|
UUID=`uuidgen`
|
|
DISK_LABEL=C-ROOT
|
|
LOOP_DEV=`sudo losetup -f`
|
|
sudo losetup "$LOOP_DEV" "$ROOT_FS_IMG"
|
|
sudo mkfs.ext3 "$LOOP_DEV"
|
|
sudo tune2fs -L "$DISK_LABEL" -U "$UUID" -c 0 -i 0 "$LOOP_DEV"
|
|
sudo mount "$LOOP_DEV" "$ROOT_FS_DIR"
|
|
|
|
# Add debootstrap link for the suite, if it doesn't exist.
|
|
if [ ! -e "/usr/share/debootstrap/scripts/$FLAGS_suite" ]
|
|
then
|
|
sudo ln -s /usr/share/debootstrap/scripts/jaunty \
|
|
"/usr/share/debootstrap/scripts/$FLAGS_suite"
|
|
fi
|
|
|
|
# Bootstrap the base debian file system
|
|
# TODO: Switch to --variant=minbase
|
|
sudo debootstrap --arch=i386 $FLAGS_suite "$ROOT_FS_DIR" "${FLAGS_mirror}"
|
|
|
|
# -- Customize the root file system --
|
|
|
|
# Set up mounts for working within the chroot. We copy some basic
|
|
# network information from the host so that the chroot can access
|
|
# repositories on the network as needed.
|
|
sudo mount -t proc proc "${ROOT_FS_DIR}/proc"
|
|
sudo mount -t sysfs sysfs "${ROOT_FS_DIR}/sys" # TODO: Do we need sysfs?
|
|
sudo cp /etc/hosts "${ROOT_FS_DIR}/etc"
|
|
|
|
# Create setup directory and copy over scripts, config files, and locally
|
|
# built packages.
|
|
mkdir -p "$SETUP_DIR"
|
|
mkdir -p "${SETUP_DIR}/local_packages"
|
|
cp "${FLAGS_build_root}/x86/local_packages"/* "${SETUP_DIR}/local_packages"
|
|
|
|
# Set up repository for local packages to install in the rootfs via apt-get.
|
|
cd "$SETUP_DIR"
|
|
dpkg-scanpackages local_packages/ /dev/null | \
|
|
gzip > local_packages/Packages.gz
|
|
cd -
|
|
|
|
# Run the package install script
|
|
"${SCRIPTS_DIR}/install_packages.sh" \
|
|
--root="$ROOT_FS_DIR" \
|
|
--output_dir="${OUTPUT_DIR}" \
|
|
--setup_dir="${SETUP_DIR}" \
|
|
--package_list="$FLAGS_pkglist" \
|
|
--server="$FLAGS_mirror" \
|
|
--suite="$FLAGS_suite" \
|
|
--kernel_version="$KERNEL_VERSION"
|
|
|
|
# Run the script to customize the resulting root file system.
|
|
"${SCRIPTS_DIR}/customize_rootfs.sh" --root="${ROOT_FS_DIR}"
|
|
|
|
# Unmount mounts within the rootfs so it is ready to be imaged.
|
|
cleanup_rootfs_mounts
|
|
|
|
# -- Turn root file system into bootable image --
|
|
|
|
# Setup extlinux configuration.
|
|
# TODO: For some reason the /dev/disk/by-uuid is not being generated by udev
|
|
# in the initramfs. When we figure that out, switch to root=UUID=$UUID.
|
|
cat <<EOF | sudo dd of="$ROOT_FS_DIR"/boot/extlinux.conf
|
|
DEFAULT chromeos-usb
|
|
PROMPT 0
|
|
TIMEOUT 0
|
|
|
|
label chromeos-usb
|
|
menu label chromeos-usb
|
|
kernel vmlinuz
|
|
append quiet console=tty2 initrd=initrd.img init=/sbin/init boot=local rootwait root=LABEL=$DISK_LABEL ro noresume noswap i915.modeset=1 loglevel=1
|
|
|
|
label chromeos-hd
|
|
menu label chromeos-hd
|
|
kernel vmlinuz
|
|
append quiet console=tty2 init=/sbin/init boot=local rootwait root=HDROOT ro noresume noswap i915.modeset=1 loglevel=1
|
|
EOF
|
|
|
|
# Make partition bootable and label it.
|
|
sudo "$SCRIPTS_DIR/extlinux.sh" -z --install "${ROOT_FS_DIR}/boot"
|
|
|
|
cleanup_rootfs_loop
|
|
|
|
# Create a master boot record.
|
|
# Start with the syslinux master boot record. We need to zero-pad to
|
|
# fill out a 512-byte sector size.
|
|
SYSLINUX_MBR="/usr/lib/syslinux/mbr.bin"
|
|
dd if="$SYSLINUX_MBR" of="$MBR_IMG" bs=512 count=1 conv=sync
|
|
# Create a partition table in the MBR.
|
|
NUM_SECTORS=$((`stat --format="%s" "$ROOT_FS_IMG"` / 512))
|
|
sudo sfdisk -H64 -S32 -uS -f "$MBR_IMG" <<EOF
|
|
,$NUM_SECTORS,L,-,
|
|
,$NUM_SECTORS,S,-,
|
|
,$NUM_SECTORS,L,*,
|
|
;
|
|
EOF
|
|
|
|
OUTSIDE_OUTPUT_DIR="${EXTERNAL_TRUNK_PATH}/src/build/images/${IMAGE_SUBDIR}"
|
|
echo "Done. Image created in ${OUTPUT_DIR}"
|
|
echo "To copy to USB keyfob, outside the chroot, do something like:"
|
|
echo " ./image_to_usb.sh --from=${OUTSIDE_OUTPUT_DIR} --to=/dev/sdb"
|
|
echo "To convert to VMWare image, outside the chroot, do something like:"
|
|
echo " ./image_to_vmware.sh --from=${OUTSIDE_OUTPUT_DIR}"
|
|
|
|
trap - EXIT
|