flatcar-scripts/build_image
Hung-Te Lin d32c59fe47 crosutils: build factory test image by emerge commands
The factory test image was created by using rsync from build artifacts
in chroot, which has some concerns:
 - Runtime dependencies of autotest-factory won't be picked into image.
 - If a developer skips build_package and builds image by using only pre-built
   binary packages, he will get nothing in factory test image.
 - It's hard for developers to figure out how and when his changes will be
   merged to next build_image (cros_workon does not really work).
 - Output image will be definitely different for every developers, also the
   official build bots.
 - If developers never wipes his chroot (setup_board), the factory test image
   will grow until out of space. (For example, my environment outputs a 825M
   image while the official buildbot generates only 563M for same ToT source).

This CL changes image build command to using portage emerge, so that output
image can be prepared faster and smaller, and easier for maintenance.

BUG=chromium-os:3335
TEST=./build_packages; ./build_image --factory  # Image starts factory UI successfully
     # Also tried tests in test_list.all, seems fine.

     time ./mod_image_for_test.sh --factory --force_copy --no_inplace
     # time: 3m2s => 1m55s, factory test image data: 825/563M => 378M

     ./build_image --factory_install # factory install shim is also fine

Change-Id: I82b4505c74cd31e718aaff4a319d50b69b2c852c
Reviewed-on: https://gerrit.chromium.org/gerrit/14473
Tested-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Richard Barnette <jrbarnette@chromium.org>
Commit-Ready: Hung-Te Lin <hungte@chromium.org>
2012-01-20 17:54:11 -08:00

282 lines
11 KiB
Bash
Executable File

#!/bin/bash
# Copyright (c) 2011 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 from within
# a chromiumos setup. This assumes that all needed packages have been built into
# the given target's root with binary packages turned on. This script will
# build the Chrome OS image using only pre-built binary packages.
SCRIPT_ROOT=$(dirname "$0")
. "${SCRIPT_ROOT}/build_library/build_common.sh" || exit 1
DEFINE_string board "${DEFAULT_BOARD}" \
"The board to build an image for."
DEFINE_string build_root "/build" \
"The root location for board sysroots."
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_boolean replace ${FLAGS_FALSE} \
"Overwrite existing output, if any."
DEFINE_boolean withdev ${FLAGS_TRUE} \
"Include useful developer friendly utilities in the image."
DEFINE_integer jobs -1 \
"How many packages to build in parallel at maximum."
DEFINE_boolean statefuldev ${FLAGS_TRUE} \
"Install development packages on stateful partition rather than the rootfs"
DEFINE_boolean test ${FLAGS_FALSE} \
"Modify the image for automated testing"
DEFINE_boolean factory ${FLAGS_FALSE} \
"Modify the image for manufacturing testing"
DEFINE_boolean factory_install ${FLAGS_FALSE} \
"Build a smaller image to overlay the factory install shim on; this argument \
is also required in image_to_usb."
DEFINE_integer rootfs_partition_size 1024 \
"rootfs partition size in MiBs."
DEFINE_integer rootfs_size 850 \
"rootfs filesystem size in MiBs."
# ceil(0.1 * rootfs_size) is a good minimum.
DEFINE_integer rootfs_hash_pad 8 \
"MiBs reserved at the end of the rootfs image."
DEFINE_integer statefulfs_size 1024 \
"stateful filesystem size in MiBs."
DEFINE_boolean fast ${DEFAULT_FAST} \
"Call many emerges in parallel"
DEFINE_string boot_args "noinitrd" \
"Additional boot arguments to pass to the commandline"
DEFINE_string usb_disk /dev/sdb3 \
"Path syslinux should use to do a usb boot. Default: /dev/sdb3"
DEFINE_boolean enable_rootfs_verification ${FLAGS_TRUE} \
"Default all bootloaders to use kernel-based root fs integrity checking."
DEFINE_integer verity_error_behavior 3 \
"Kernel verified boot error behavior (0: I/O errors, 1: panic, 2: nothing, \
3: cros) Default: 3"
DEFINE_integer verity_max_ios -1 \
"Number of outstanding I/O operations dm-verity caps at. Default: -1"
DEFINE_string verity_algorithm "sha1" \
"Cryptographic hash algorithm used for kernel vboot. Default : sha1"
DEFINE_string verity_salt "" \
"Root filesystem salt. Default: randomly generated."
DEFINE_boolean standard_backdoor ${FLAGS_TRUE} \
"Install standard backdoor credentials for testing"
DEFINE_string symlink "latest" \
"Symlink name to use for this image."
# TODO(clchiou): Remove this flag after buildbot is fixed
DEFINE_boolean crosbug12352_arm_kernel_signing ${FLAGS_TRUE} \
"A dummy this flag for preventing buildbot fail"
FLAGS_HELP="USAGE: build_image [flags] [list of images to build].
This script is used to build a Chromium OS image. Chromium OS comes in many
different forms. This scripts can be used to build the following:
base - Pristine Chromium OS image. As similar to Chrome OS as possible.
dev - Developer image. Like base but with additional developer packages.
test - Like dev, but with additional test specific packages and can be easily
used for automated testing using scripts like run_remote_tests, etc.
factory_test - Like test but with extra packages and modifications used to
test images in a factory setting. Cannot be built along with a test image.
factory_install - Install shim for bootstrapping the factory test process.
Cannot be built along with any other image.
Examples
build_image --board=<board> dev test - builds developer and test images.
build_image --board=<board> factory_install - builds a factory install shim.
...
"
# Parse command line.
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
# Only now can we die on error. shflags functions leak non-zero error codes,
# so will die prematurely if 'set -e' is specified before now.
set -e
# Determine build version.
OVERLAY_CHROMEOS_DIR="${SRC_ROOT}/third_party/chromiumos-overlay/chromeos"
. "${OVERLAY_CHROMEOS_DIR}/config/chromeos_version.sh" || exit 1
# N.B. Ordering matters for some of the libraries below, because
# some of the files contain initialization used by later files.
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/build_gpt.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/mount_gpt_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/build_image_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/base_image_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/dev_image_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/test_image_util.sh" || exit 1
. "${BUILD_LIBRARY_DIR}/test_image_content.sh" || exit 1
parse_build_image_args
# Tweak flags, configure extra USE flags, and add packages for the factory
# install shim.
EXTRA_PACKAGES=""
if [ ${FLAGS_factory_install} -eq ${FLAGS_TRUE} ]; then
# TODO: Build a separated ebuild for the install shim to reduce size.
INSTALL_MASK="${FACTORY_SHIM_INSTALL_MASK}"
# Reduce the size of factory install shim.
info "Fixing the rootfs size at 320 MiB for install shim"
FLAGS_rootfs_size=300
FLAGS_rootfs_partition_size=320
info "Fixing the statefulfs size at 140 MiB for install shim"
FLAGS_statefulfs_size=140
# Add the cros_factory_install boot arg.
FLAGS_boot_args="${FLAGS_boot_args} cros_factory_install"
# Factory install needs to have the factory installer added.
EXTRA_PACKAGES="${EXTRA_PACKAGES} chromeos-base/chromeos-factoryinstall"
# On x86, we boot the factory install shim from an SD card using
# initramfs for our root. On ARM, we boot the factory install shim
# over the network, so we don't require initramfs, but we do require
# fbconsole to fix a display driver bug.
if [ "${ARCH}" = "x86" ] ; then
export USE="${USE} initramfs"
fi
# CONFIG_BLK_DEV_RAM is disabled by default.
# But tftp install needs it to mount rootfs in ram
if [ "${ARCH}" = "arm" ] ; then
export USE="${USE} fbconsole blkdevram"
fi
fi
if [ $((FLAGS_rootfs_size + FLAGS_rootfs_hash_pad)) -gt \
${FLAGS_rootfs_partition_size} ] ; then
die "rootfs ($((FLAGS_rootfs_size + FLAGS_rootfs_hash_pad)) MiB) is" \
"bigger than partition (${FLAGS_rootfs_partition_size} MiB)."
fi
# If we are creating a developer image, also create a pristine image with a
# different name.
PRISTINE_IMAGE_NAME=
if [ ${FLAGS_withdev} -eq ${FLAGS_TRUE} ]; then
PRISTINE_IMAGE_NAME=${CHROMEOS_BASE_IMAGE_NAME}
# Rename pristine image for factory install shim.
elif [ ${FLAGS_factory_install} -eq ${FLAGS_TRUE} ]; then
PRISTINE_IMAGE_NAME=${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}
else
# No withdev and no factory_install set meaning we must be building just the
# base image.
PRISTINE_IMAGE_NAME=chromiumos_image.bin
# Verify our assertion is true.
if [ ${IMAGES_TO_BUILD} != ${CHROMEOS_BASE_IMAGE_NAME} ]; then
warn "${IMAGES_TO_BUILD} != ${CHROMEOS_BASE_IMAGE_NAME}"
die "Should only reach this condition if only building the base image."
fi
IMAGES_TO_BUILD="chromiumos_image.bin"
fi
ROOT_FS_DIR="${BUILD_DIR}/rootfs"
STATEFUL_FS_DIR="${BUILD_DIR}/stateful_partition"
ESP_FS_DIR=${BUILD_DIR}/esp
DEVKEYSDIR="/usr/share/vboot/devkeys"
# ${DEV_IMAGE_ROOT} specifies the location of where developer packages will
# be installed on the stateful dir. On a Chromium OS system, this will
# translate to /usr/local.
DEV_IMAGE_ROOT="${STATEFUL_FS_DIR}/dev_image"
eclean-$BOARD -d packages
check_blacklist
# Check that the build root is sane.
"${BUILD_LIBRARY_DIR}/test_build_root" --root="${BOARD_ROOT}"
# Hack to fix bug where x86_64 CHOST line gets incorrectly added.
# ToDo(msb): remove this hack.
PACKAGES_FILE="${BOARD_ROOT}/packages/Packages"
sudo sed -e "s/CHOST: x86_64-pc-linux-gnu//" -i "${PACKAGES_FILE}"
# Handle existing directory.
if [[ -e "${BUILD_DIR}" ]]; then
if [[ ${FLAGS_replace} -eq ${FLAGS_TRUE} ]]; then
sudo rm -rf "${BUILD_DIR}"
else
error "Directory ${BUILD_DIR} already exists."
error "Use --build_attempt option to specify an unused attempt."
die "Or use --replace if you want to overwrite this directory."
fi
fi
# Create the output directory and temporary mount points.
mkdir -p "${BUILD_DIR}"
mkdir -p "${ROOT_FS_DIR}" "${STATEFUL_FS_DIR}" "${ESP_FS_DIR}"
# Create the boot.desc file which stores the build-time configuration
# information needed for making the image bootable after creation with
# cros_make_image_bootable.
create_boot_desc
create_base_image ${PRISTINE_IMAGE_NAME}
BOOT_FLAG=
if [ ${FLAGS_factory_install} -eq ${FLAGS_TRUE} ]; then
BOOT_FLAG="-b 1" # BOOT_FLAG_DEVELOPER value defined in load_kernel_fw.h
info "--factory_install set, pass BOOT_FLAG_DEVELOPER flag to" \
"load_kernel_test"
fi
# Verify pristine image if we built it.
if should_build_image "${PRISTINE_IMAGE_NAME}"; then
load_kernel_test "${BUILD_DIR}/${PRISTINE_IMAGE_NAME}" \
"${DEVKEYSDIR}/recovery_key.vbpubk" ${BOOT_FLAG}
fi
# Create a developer image based on the chromium os base image.
if [ ${FLAGS_withdev} -eq ${FLAGS_TRUE} ]; then
copy_image ${CHROMEOS_BASE_IMAGE_NAME} ${CHROMEOS_DEVELOPER_IMAGE_NAME}
install_dev_packages ${CHROMEOS_DEVELOPER_IMAGE_NAME}
fi
# Create a test or factory test image if desired.
if [ ${FLAGS_factory} -eq ${FLAGS_TRUE} ]; then
copy_image ${CHROMEOS_DEVELOPER_IMAGE_NAME} \
${CHROMEOS_FACTORY_TEST_IMAGE_NAME}
mod_image_for_test ${CHROMEOS_FACTORY_TEST_IMAGE_NAME}
elif [ ${FLAGS_test} -eq ${FLAGS_TRUE} ]; then
copy_image ${CHROMEOS_DEVELOPER_IMAGE_NAME} ${CHROMEOS_TEST_IMAGE_NAME}
mod_image_for_test ${CHROMEOS_TEST_IMAGE_NAME}
fi
rmdir "${ROOT_FS_DIR}" "${STATEFUL_FS_DIR}" "${ESP_FS_DIR}"
# Generating AU generator zip file to run outside chroot
generate_au_zip || echo "Failed generating AU zip file - ignoring Error..."
# Create a named symlink.
LINK_NAME="${FLAGS_output_root}/${BOARD}/${FLAGS_symlink}"
ln -sfT $(basename ${BUILD_DIR}) ${LINK_NAME}
echo "Done. Image created in ${BUILD_DIR}"
echo "Chromium OS image created as ${PRISTINE_IMAGE_NAME}"
if [ ${FLAGS_withdev} -eq ${FLAGS_TRUE} ]; then
echo "Developer image created as ${CHROMEOS_DEVELOPER_IMAGE_NAME}"
fi
if [ ${FLAGS_factory} -eq ${FLAGS_TRUE} ]; then
echo "Factory test image created as ${CHROMEOS_FACTORY_TEST_IMAGE_NAME}"
elif [ ${FLAGS_test} -eq ${FLAGS_TRUE} ]; then
echo "Test image created as ${CHROMEOS_TEST_IMAGE_NAME}"
fi
print_time_elapsed
echo "To copy to USB keyfob, do something like:"
echo " ./image_to_usb.sh --from=${OUTSIDE_OUTPUT_DIR} --to=/dev/sdX"
echo "To convert to VMWare image, INSIDE the chroot, do something like:"
echo " ./image_to_vm.sh --from=${OUTSIDE_OUTPUT_DIR} --board=${BOARD}"
echo "from the scripts directory where you entered the chroot."