mirror of
https://github.com/flatcar/scripts.git
synced 2025-12-08 10:52:03 +01:00
Move from optparse to argparse. Move layout file and layout type to global options with reasonable default values so every command doesn't need to them. Adjust calling scripts to match. For now layout type is being passed via an environment variable DISK_LAYOUT_TYPE but this is a temporary situation.
299 lines
10 KiB
Bash
Executable File
299 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2010 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 which ensures that a given image has an up-to-date
|
|
# kernel partition, rootfs integrity hashes, and legacy bootloader configs.
|
|
|
|
# --- BEGIN COMMON.SH BOILERPLATE ---
|
|
# Load common CrOS utilities. Inside the chroot this file is installed in
|
|
# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
|
|
# location.
|
|
find_common_sh() {
|
|
local common_paths=("$(dirname "$(readlink -f "$0")")/.." /usr/lib/crosutils)
|
|
local path
|
|
|
|
SCRIPT_ROOT="${common_paths[0]}"
|
|
for path in "${common_paths[@]}"; do
|
|
if [ -r "${path}/common.sh" ]; then
|
|
SCRIPT_ROOT="${path}"
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
find_common_sh
|
|
. "${SCRIPT_ROOT}/common.sh" || exit 1
|
|
# --- END COMMON.SH BOILERPLATE ---
|
|
|
|
# Need to be inside the chroot to load chromeos-common.sh
|
|
assert_inside_chroot
|
|
|
|
# Load functions and constants for chromeos-install
|
|
. /usr/lib/installer/chromeos-common.sh || exit 1
|
|
. "${BUILD_LIBRARY_DIR}/toolchain_util.sh" || exit 1
|
|
. "${BUILD_LIBRARY_DIR}/build_image_util.sh" || exit 1
|
|
|
|
switch_to_strict_mode
|
|
|
|
if [ $# -lt 2 ]; then
|
|
echo "Usage: ${0} /PATH/TO/IMAGE IMAGE.BIN [shflags overrides]"
|
|
exit 1
|
|
fi
|
|
|
|
IMAGE_DIR="$(readlink -f "${1}")"
|
|
BOOT_DESC_FILE="${IMAGE_DIR}/boot.desc"
|
|
IMAGE="${IMAGE_DIR}/${2}"
|
|
shift
|
|
shift
|
|
FLAG_OVERRIDES="${@}"
|
|
|
|
if [ ! -r "${BOOT_DESC_FILE}" ]; then
|
|
warn "${BOOT_DESC_FILE} cannot be read!"
|
|
warn "Falling back to command line parsing"
|
|
BOOT_DESC="${@}"
|
|
else
|
|
BOOT_DESC="$(cat ${BOOT_DESC_FILE} | tr -s '\n' ' ')"
|
|
info "Boot-time configuration for $(dirname "${IMAGE}"): "
|
|
cat ${BOOT_DESC_FILE} | while read line; do
|
|
info " ${line}"
|
|
done
|
|
fi
|
|
|
|
if [ ! -r "${IMAGE}" ]; then
|
|
die "${IMAGE} cannot be read!"
|
|
fi
|
|
|
|
|
|
locate_gpt
|
|
set +e
|
|
|
|
# Now parse the build settings from ${OUTPUT_DIR}/boot.desc
|
|
DEFINE_string adjust_part "" \
|
|
"Adjustments to apply to the partition table"
|
|
DEFINE_string board "${DEFAULT_BOARD}" \
|
|
"Board we're building for."
|
|
DEFINE_string output_dir "/tmp" \
|
|
"Directory to place output in."
|
|
DEFINE_string image "coreos_base.img" \
|
|
"Full path to the coreos image to make bootable."
|
|
DEFINE_string arch "x86" \
|
|
"Architecture to make bootable for: arm, x86, or amd64"
|
|
DEFINE_boolean cleanup_dirs ${FLAGS_TRUE} \
|
|
"Whether the mount dirs should be removed on completion."
|
|
|
|
DEFINE_string boot_args "noinitrd" \
|
|
"Additional boot arguments to pass to the commandline"
|
|
|
|
DEFINE_boolean enable_rootfs_verification ${FLAGS_FALSE} \
|
|
"Default all bootloaders to NOT use kernel-based root fs integrity checking."
|
|
|
|
DEFINE_string keys_dir "/usr/share/vboot/devkeys" \
|
|
"Directory containing the signing keys."
|
|
|
|
DEFINE_string au_key "" \
|
|
"Filename of the au_key to install"
|
|
|
|
DEFINE_string production_track "" \
|
|
"Use production values and a given track for update service."
|
|
|
|
DEFINE_string rootfs_mountpoint "/tmp/rootfs" \
|
|
"Path where the rootfs can be safely mounted"
|
|
DEFINE_string statefulfs_mountpoint "/tmp/statefulfs" \
|
|
"Path where the statefulfs can be safely mounted"
|
|
DEFINE_string espfs_mountpoint "/tmp/espfs" \
|
|
"Path where the espfs can be safely mounted"
|
|
|
|
DEFINE_boolean use_dev_keys ${FLAGS_FALSE} \
|
|
"Use developer keys for signing. (Default: false)"
|
|
|
|
DEFINE_boolean fsck_rootfs ${FLAGS_FALSE} \
|
|
"Check integrity of the rootfs on the modified image."
|
|
|
|
# TODO(pkumar): Remove once known that no images are using this flag
|
|
DEFINE_boolean crosbug12352_arm_kernel_signing ${FLAGS_FALSE} \
|
|
"This flag is deprecated but the bots still need parse old images."
|
|
|
|
# TODO(sosa): Remove once known images no longer use this in their config.
|
|
DEFINE_string arm_extra_bootargs "" "DEPRECATED FLAG. Do not use."
|
|
|
|
DEFINE_boolean force_developer_mode ${FLAGS_FALSE} \
|
|
"Add cros_debug to boot args."
|
|
|
|
DEFINE_boolean enable_squashfs ${FLAGS_FALSE} \
|
|
"Make the rootfs of the image squashfs."
|
|
DEFINE_string squash_sort_file "" \
|
|
"Specify the priority of files when squashing the rootfs."
|
|
|
|
|
|
# Parse the boot.desc and any overrides
|
|
eval set -- "${BOOT_DESC} ${FLAG_OVERRIDES}"
|
|
FLAGS "${@}" || exit 1
|
|
|
|
. "${BUILD_LIBRARY_DIR}/board_options.sh" || exit 1
|
|
|
|
# Only now can we die on error. shflags functions leak non-zero error codes,
|
|
# so will die prematurely if 'switch_to_strict_mode' is specified before now.
|
|
switch_to_strict_mode -u
|
|
|
|
# $1 - Directory where developer rootfs is mounted.
|
|
# $2 - Directory where developer stateful_partition is mounted.
|
|
# $3 - Directory where the ESP partition is mounted.
|
|
mount_gpt_cleanup() {
|
|
local rootfs="${1-$FLAGS_rootfs_mountpoint}"
|
|
local statefs="${2-$FLAGS_statefulfs_mountpoint}"
|
|
local espfs="${3-$FLAGS_espfs_mountpoint}"
|
|
"${SCRIPTS_DIR}/mount_gpt_image.sh" \
|
|
-u -r "${rootfs}" -s "${statefs}" -e "${espfs}"
|
|
}
|
|
|
|
make_image_bootable() {
|
|
local image="$1"
|
|
local use_dev_keys=
|
|
|
|
# Default to non-verified
|
|
local enable_rootfs_verification_flag=--noenable_rootfs_verification
|
|
if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
|
|
enable_rootfs_verification_flag=--enable_rootfs_verification
|
|
fi
|
|
|
|
trap "mount_gpt_cleanup" EXIT
|
|
"${SCRIPTS_DIR}/mount_gpt_image.sh" --from "$(dirname "${image}")" \
|
|
--image "$(basename ${image})" -r "${FLAGS_rootfs_mountpoint}" \
|
|
-s "${FLAGS_statefulfs_mountpoint}"
|
|
|
|
legacy_offset_size_export ${image}
|
|
|
|
if [ -n "${FLAGS_production_track}" ]; then
|
|
# Replace /etc/lsb-release on the image.
|
|
"${BUILD_LIBRARY_DIR}/set_lsb_release" \
|
|
--production_track="${FLAGS_production_track}" \
|
|
--root="${FLAGS_rootfs_mountpoint}" \
|
|
--board="${BOARD}"
|
|
fi
|
|
|
|
# Install an auto update key on the root before sealing it off
|
|
if [ ! -z "${FLAGS_au_key}" ]; then
|
|
local key_location=${FLAGS_rootfs_mountpoint}"/usr/share/update_engine/"
|
|
sudo mkdir -p "${key_location}"
|
|
sudo cp "${FLAGS_au_key}" "$key_location/update-payload-key.pub.pem"
|
|
sudo chown root:root "$key_location/update-payload-key.pub.pem"
|
|
sudo chmod 644 "$key_location/update-payload-key.pub.pem"
|
|
echo "AU verification key was installed. Do not forget to resign the image!"
|
|
fi
|
|
|
|
# The rootfs should never be mounted rw again after this point without
|
|
# re-calling make_image_bootable.
|
|
sudo mount -o remount,ro "${FLAGS_rootfs_mountpoint}"
|
|
# Newer `mount` will decode the filename backing the loop device,
|
|
# so we need to dig deeper and find the answer ourselves.
|
|
root_dev=$(awk -v mnt="${FLAGS_rootfs_mountpoint}" \
|
|
'$2 == mnt { print $1 }' /proc/mounts)
|
|
|
|
# Make the filesystem un-mountable as read-write.
|
|
# mount_gpt_image.sh will undo this as needed.
|
|
# TODO(wad) make sure there is parity in the signing scripts.
|
|
if [ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]; then
|
|
# TODO(wad) this would be a good place to reset any other ext2 metadata.
|
|
warn "Disabling r/w mount of the root filesystem"
|
|
disable_rw_mount "$root_dev"
|
|
fi
|
|
|
|
if [ ${FLAGS_use_dev_keys} -eq ${FLAGS_TRUE} ]; then
|
|
use_dev_keys="--use_dev_keys"
|
|
fi
|
|
|
|
if [ ${FLAGS_force_developer_mode} -eq ${FLAGS_TRUE} ]; then
|
|
FLAGS_boot_args="${FLAGS_boot_args} cros_debug"
|
|
fi
|
|
|
|
local squash_sort_flag=
|
|
if [ -n "${FLAGS_squash_sort_file}" ]; then
|
|
squash_sort_flag="-sort ${FLAGS_squash_sort_file}"
|
|
fi
|
|
|
|
if [ $FLAGS_enable_squashfs -eq $FLAGS_TRUE ]; then
|
|
local squashfs_img="${FLAGS_output_dir}/squashfs.image"
|
|
sudo mksquashfs "${FLAGS_rootfs_mountpoint}" ${squashfs_img} -comp lzo \
|
|
-noI -noF -ef ${SCRIPTS_DIR}/exclude-list -wildcards ${squash_sort_flag}
|
|
root_dev=$squashfs_img
|
|
fi
|
|
|
|
# We should update the esp in place in the image.
|
|
local bootloader_to="${image}"
|
|
local esp_offset="$(partoffset ${image} ${NUM_ESP})"
|
|
esp_offset=$((esp_offset * 512)) # sectors to bytes
|
|
local esp_size="$(partsize ${image} ${NUM_ESP})"
|
|
esp_size=$((esp_size * 512)) # sectors to bytes
|
|
local bootloader_to_flags="--to_offset=${esp_offset} --to_size=${esp_size}"
|
|
|
|
# Update ESP partition
|
|
# NOTE: Boot kernel is identical to regular kernel for now
|
|
${SCRIPTS_DIR}/update_bootloaders.sh \
|
|
--arch=${FLAGS_arch} \
|
|
--to="${bootloader_to}" \
|
|
--from="${FLAGS_rootfs_mountpoint}"/boot \
|
|
--vmlinuz_boot_kernel="${FLAGS_rootfs_mountpoint}"/boot/vmlinuz \
|
|
--vmlinuz="${FLAGS_rootfs_mountpoint}"/boot/vmlinuz \
|
|
${bootloader_to_flags}
|
|
|
|
trap - EXIT
|
|
${SCRIPTS_DIR}/mount_gpt_image.sh -u -r "${FLAGS_rootfs_mountpoint}" \
|
|
-s "${FLAGS_statefulfs_mountpoint}"
|
|
|
|
# I can only copy the squashfs image to the image only when it is umounted.
|
|
if [ $FLAGS_enable_squashfs -eq $FLAGS_TRUE ]; then
|
|
# copy the squashfs image to the partition
|
|
info "copy the squashfs to the partition"
|
|
local part_offset="$(partoffset ${image} ${NUM_ROOTFS_A})"
|
|
sudo dd bs=512 if="${squashfs_img}" of="${image}" \
|
|
seek=${part_offset} conv=notrunc status=none
|
|
sudo rm "${squashfs_img}"
|
|
fi
|
|
}
|
|
|
|
verify_image_rootfs() {
|
|
local image=$1
|
|
local rootfs_offset="$(partoffset ${image} 3)"
|
|
|
|
local rootfs_tmp_file=$(mktemp)
|
|
trap "rm ${rootfs_tmp_file}" EXIT
|
|
sudo dd if="${image}" of="${rootfs_tmp_file}" bs=512 skip="${rootfs_offset}" \
|
|
status=none
|
|
|
|
# This flips the read-only compatibility flag, so that
|
|
# e2fsck does not complain about unknown file system capabilities.
|
|
enable_rw_mount "${rootfs_tmp_file}"
|
|
info "Running e2fsck to check root file system for errors"
|
|
sudo e2fsck -fn "${rootfs_tmp_file}" ||
|
|
die "Root file system has errors, please ensure boot.desc and/or \
|
|
command line parameters are correct"
|
|
}
|
|
|
|
# Store output and temporary files next to image.
|
|
FLAGS_output_dir="${IMAGE_DIR}"
|
|
FLAGS_rootfs_mountpoint="${IMAGE_DIR}/rootfs_dir"
|
|
FLAGS_statefulfs_mountpoint="${IMAGE_DIR}/stateful_dir"
|
|
FLAGS_espfs_mountpoint="${IMAGE_DIR}/esp"
|
|
|
|
# Create the directories if they don't exist.
|
|
mkdir -p ${FLAGS_rootfs_mountpoint}
|
|
mkdir -p ${FLAGS_statefulfs_mountpoint}
|
|
mkdir -p ${FLAGS_espfs_mountpoint}
|
|
|
|
make_image_bootable "${IMAGE}"
|
|
# We can't verify the image if squashfs is enabled because the kernel
|
|
# on the host does not support squashfs with LZO
|
|
if [ ${FLAGS_fsck_rootfs} -eq ${FLAGS_TRUE} \
|
|
-a ${FLAGS_enable_squashfs} -eq ${FLAGS_FALSE} ]; then
|
|
verify_image_rootfs "${IMAGE}"
|
|
fi
|
|
|
|
if [ ${FLAGS_cleanup_dirs} -eq ${FLAGS_TRUE} ]; then
|
|
rmdir ${FLAGS_rootfs_mountpoint}
|
|
rmdir ${FLAGS_statefulfs_mountpoint}
|
|
rmdir ${FLAGS_espfs_mountpoint}
|
|
fi
|