| # Copyright (c) 2012 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. |
| |
| . "${SRC_ROOT}/platform/dev/toolchain_utils.sh" || exit 1 |
| |
| cleanup_mounts() { |
| local prev_ret=$? |
| |
| # Disable die on error. |
| set +e |
| |
| # See if we ran out of space. Only show if we errored out via a trap. |
| if [[ ${prev_ret} -ne 0 ]]; then |
| local df=$(df -B 1M "${root_fs_dir}") |
| if [[ ${df} == *100%* ]]; then |
| error "Here are the biggest files (by disk usage):" |
| # Send final output to stderr to match `error` behavior. |
| sudo find "${root_fs_dir}" -xdev -type f -printf '%b %P\n' | \ |
| awk '$1 > 16 { $1 = $1 * 512; print }' | sort -n | tail -100 1>&2 |
| error "Target image has run out of space:" |
| error "${df}" |
| fi |
| fi |
| |
| echo "Cleaning up mounts" |
| safe_umount_tree "${root_fs_dir}" |
| safe_umount_tree "${stateful_fs_dir}" |
| safe_umount_tree "${esp_fs_dir}" |
| |
| # Turn die on error back on. |
| set -e |
| } |
| |
| zero_free_space() { |
| local fs_mount_point=$1 |
| info "Zeroing freespace in ${fs_mount_point}" |
| # dd is a silly thing and will produce a "No space left on device" message |
| # that cannot be turned off and is confusing to unsuspecting victims. |
| info "${fs_mount_point}/filler" |
| ( sudo dd if=/dev/zero of="${fs_mount_point}/filler" bs=4096 conv=fdatasync \ |
| status=noxfer || true ) 2>&1 | grep -v "No space left on device" |
| sudo rm "${fs_mount_point}/filler" |
| } |
| |
| create_base_image() { |
| local image_name=$1 |
| local rootfs_verification_enabled=$2 |
| local bootcache_enabled=$3 |
| local image_type="usb" |
| |
| if [[ "${FLAGS_disk_layout}" != "default" ]]; then |
| image_type="${FLAGS_disk_layout}" |
| else |
| if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then |
| image_type="factory_install" |
| fi |
| fi |
| |
| check_valid_layout "base" |
| check_valid_layout ${image_type} |
| |
| info "Using image type ${image_type}" |
| get_disk_layout_path |
| info "Using disk layout ${DISK_LAYOUT_PATH}" |
| root_fs_dir="${BUILD_DIR}/rootfs" |
| stateful_fs_dir="${BUILD_DIR}/stateful" |
| esp_fs_dir="${BUILD_DIR}/esp" |
| |
| trap "cleanup_mounts && delete_prompt" EXIT |
| cleanup_mounts &> /dev/null |
| |
| mkdir "${root_fs_dir}" "${stateful_fs_dir}" "${esp_fs_dir}" |
| build_gpt_image "${BUILD_DIR}/${image_name}" "${image_type}" |
| mount_image "${BUILD_DIR}/${image_name}" \ |
| "${root_fs_dir}" "${stateful_fs_dir}" "${esp_fs_dir}" |
| |
| df -h "${root_fs_dir}" |
| |
| # Create symlinks so that /usr/local/usr based directories are symlinked to |
| # /usr/local/ directories e.g. /usr/local/usr/bin -> /usr/local/bin, etc. |
| setup_symlinks_on_root "${stateful_fs_dir}/dev_image" \ |
| "${stateful_fs_dir}/var_overlay" "${stateful_fs_dir}" |
| |
| # We need to install libc manually from the cross toolchain. |
| # TODO: Improve this? It would be ideal to use emerge to do this. |
| PKGDIR="/var/lib/portage/pkgs" |
| LIBC_TAR="glibc-${LIBC_VERSION}.tbz2" |
| LIBC_PATH="${PKGDIR}/cross-${CHOST}/${LIBC_TAR}" |
| |
| if ! [[ -e ${LIBC_PATH} ]]; then |
| die_notrace \ |
| "${LIBC_PATH} does not exist. Try running ./setup_board" \ |
| "--board=${BOARD} to update the version of libc installed on that board." |
| fi |
| |
| # Strip out files we don't need in the final image at runtime. |
| local libc_excludes=( |
| # Compile-time headers. |
| 'usr/include' 'sys-include' |
| # Link-time objects. |
| '*.[ao]' |
| ) |
| pbzip2 -dc --ignore-trailing-garbage=1 "${LIBC_PATH}" | \ |
| sudo tar xpf - -C "${root_fs_dir}" ./usr/${CHOST} \ |
| --strip-components=3 "${libc_excludes[@]/#/--exclude=}" |
| |
| if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then |
| # Install our custom factory install kernel with the appropriate use flags |
| # to the image. |
| emerge_custom_kernel "${root_fs_dir}" |
| fi |
| |
| # We "emerge --root=${root_fs_dir} --root-deps=rdeps --usepkgonly" all of the |
| # runtime packages for chrome os. This builds up a chrome os image from |
| # binary packages with runtime dependencies only. We use INSTALL_MASK to |
| # trim the image size as much as possible. |
| emerge_to_image --root="${root_fs_dir}" ${BASE_PACKAGE} |
| |
| # Run ldconfig to create /etc/ld.so.cache. |
| sudo ldconfig -r "${root_fs_dir}" |
| |
| # Set /etc/lsb-release on the image. |
| "${OVERLAY_CHROMEOS_DIR}/scripts/cros_set_lsb_release" \ |
| --root="${root_fs_dir}" \ |
| --board="${BOARD}" |
| |
| # 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 "${image_type}" |
| |
| # Write out the GPT creation script. |
| # This MUST be done before writing bootloader templates else we'll break |
| # the hash on the root FS. |
| write_partition_script "${image_type}" \ |
| "${root_fs_dir}/${PARTITION_SCRIPT_PATH}" |
| |
| # Populates the root filesystem with legacy bootloader templates |
| # appropriate for the platform. The autoupdater and installer will |
| # use those templates to update the legacy boot partition (12/ESP) |
| # on update. |
| # (This script does not populate vmlinuz.A and .B needed by syslinux.) |
| # Factory install shims may be booted from USB by legacy EFI BIOS, which does |
| # not support verified boot yet (see create_legacy_bootloader_templates.sh) |
| # so rootfs verification is disabled if we are building with --factory_install |
| local enable_rootfs_verification= |
| if [[ ${rootfs_verification_enabled} -eq ${FLAGS_TRUE} ]]; then |
| enable_rootfs_verification="--enable_rootfs_verification" |
| fi |
| local enable_bootcache= |
| if [[ ${bootcache_enabled} -eq ${FLAGS_TRUE} ]]; then |
| enable_bootcache="--enable_bootcache" |
| fi |
| |
| ${BUILD_LIBRARY_DIR}/create_legacy_bootloader_templates.sh \ |
| --arch=${ARCH} \ |
| --to="${root_fs_dir}"/boot \ |
| --boot_args="${FLAGS_boot_args}" \ |
| ${enable_rootfs_verification} \ |
| ${enable_bootcache} |
| |
| # Don't test the factory install shim |
| if ! should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then |
| if [[ ${skip_test_image_content} -ne 1 ]]; then |
| # Check that the image has been correctly created. |
| test_image_content "$root_fs_dir" |
| fi |
| fi |
| |
| # Clean up symlinks so they work on a running target rooted at "/". |
| # Here development packages are rooted at /usr/local. However, do not |
| # create /usr/local or /var on host (already exist on target). |
| setup_symlinks_on_root "/usr/local" "/var" "${stateful_fs_dir}" |
| |
| # Our masking of files will implicitly leave behind a bunch of empty |
| # dirs. We can't differentiate between empty dirs we want and empty |
| # dirs we don't care about, so just prune ones we know are OK. |
| sudo find "${root_fs_dir}/usr/include" -depth -type d -exec rmdir {} + \ |
| 2>/dev/null || : |
| |
| # Zero rootfs free space to make it more compressible so auto-update |
| # payloads become smaller |
| zero_free_space "${root_fs_dir}" |
| |
| cleanup_mounts |
| |
| USE_DEV_KEYS= |
| if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then |
| USE_DEV_KEYS="--use_dev_keys" |
| fi |
| |
| if [[ ${skip_kernelblock_install} -ne 1 ]]; then |
| # Place flags before positional args. |
| ${SCRIPTS_DIR}/bin/cros_make_image_bootable "${BUILD_DIR}" \ |
| ${image_name} ${USE_DEV_KEYS} --adjust_part="${FLAGS_adjust_part}" |
| fi |
| } |