mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-08 21:46:58 +02:00
make_factory_pack: auto detect release image type (--detect_release_image)
The release image parameter must be an image signed for SSD booting. This CL adds detection code and allows on-the-fly conversion from recovery to SSD image. BUG=chromium-os:15050 TEST=./make_factory_package --release RECOVERY --factory FACTORY # success # Seeing: INFO : Image type is [recovery]:... ./make_factory_package --release USB --factory FACTORY # success # Seeing: Image type is [usb]:... ./make_factory_package --release SSD --factory FACTORY # success # Seeing: Image type is [ssd]:... ./make_factory_package --release GARBAGE --factory FACTORY # failure # Seeing: Image type is [invalid]:... ./make_factory_package --release GARBAGE --factory FACTORY --nodetect_release_image # success # No image type messages Change-Id: I8530b3f58574a4298b4d6d904a12bb92636c7365 Reviewed-on: http://gerrit.chromium.org/gerrit/5965 Tested-by: Hung-Te Lin <hungte@chromium.org> Reviewed-by: Nick Sanders <nsanders@chromium.org>
This commit is contained in:
parent
596520acd9
commit
5c67986738
@ -202,3 +202,79 @@ image_partition_copy() {
|
|||||||
image_dump_partition "${src}" "${srcpart}" |
|
image_dump_partition "${src}" "${srcpart}" |
|
||||||
dd of="${dst}" bs="${bs}" seek="${dstoffset}" conv=notrunc oflag=dsync
|
dd of="${dst}" bs="${bs}" seek="${dstoffset}" conv=notrunc oflag=dsync
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Temporary object management
|
||||||
|
_IMAGE_TEMP_OBJECTS=""
|
||||||
|
|
||||||
|
# Add a temporary object (by mktemp) into list for image_clean_temp to clean
|
||||||
|
image_add_temp() {
|
||||||
|
_IMAGE_TEMP_OBJECTS="$_IMAGE_TEMP_OBJECTS $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleans objects tracked by image_add_temp.
|
||||||
|
image_clean_temp() {
|
||||||
|
local temp_list="$_IMAGE_TEMP_OBJECTS"
|
||||||
|
local object
|
||||||
|
_IMAGE_TEMP_OBJECTS=""
|
||||||
|
|
||||||
|
for object in $temp_list; do
|
||||||
|
if [ -d "$object" ]; then
|
||||||
|
sudo umount -d "$object" >/dev/null 2>&1 || true
|
||||||
|
sudo rmdir "$object" >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
rm -f "$object" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determines the boot type of a ChromeOS kernel partition.
|
||||||
|
# Prints "recovery", "ssd", "usb", "factory_install", "invalid", or "unknown".
|
||||||
|
image_cros_kernel_boot_type() {
|
||||||
|
local keyblock="$1"
|
||||||
|
local magic flag skip kernel_config
|
||||||
|
|
||||||
|
# TODO(hungte) use vbutil_keyblock if available
|
||||||
|
|
||||||
|
# Reference: firmware/include/vboot_struct.h
|
||||||
|
local KEY_BLOCK_FLAG_DEVELOPER_0=1 # Developer switch off
|
||||||
|
local KEY_BLOCK_FLAG_DEVELOPER_1=2 # Developer switch on
|
||||||
|
local KEY_BLOCK_FLAG_RECOVERY_0=4 # Not recovery mode
|
||||||
|
local KEY_BLOCK_FLAG_RECOVERY_1=8 # Recovery mode
|
||||||
|
local KEY_BLOCK_MAGIC="CHROMEOS"
|
||||||
|
local KEY_BLOCK_MAGIC_SIZE=8
|
||||||
|
local KEY_BLOCK_FLAG_OFFSET=72 # magic:8 major:4 minor:4 size:8 2*(sig:8*3)
|
||||||
|
|
||||||
|
magic="$(dd if="$keyblock" bs=$KEY_BLOCK_MAGIC_SIZE count=1 2>/dev/null)"
|
||||||
|
if [ "$magic" != "$KEY_BLOCK_MAGIC" ]; then
|
||||||
|
echo "invalid"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
skip="$KEY_BLOCK_FLAG_OFFSET"
|
||||||
|
flag="$(dd if="$keyblock" bs=1 count=1 skip="$skip" 2>/dev/null |
|
||||||
|
od -t u1 -A n)"
|
||||||
|
if [ "$((flag & KEY_BLOCK_FLAG_RECOVERY_0))" != 0 ]; then
|
||||||
|
echo "ssd"
|
||||||
|
elif [ "$((flag & KEY_BLOCK_FLAG_RECOVERY_1))" != 0 ]; then
|
||||||
|
if [ "$((flag & KEY_BLOCK_FLAG_DEVELOPER_0))" = 0 ]; then
|
||||||
|
echo "factory_install"
|
||||||
|
else
|
||||||
|
# Recovery or USB. Check "cros_recovery" in kernel config.
|
||||||
|
if image_has_command dump_kernel_config; then
|
||||||
|
kernel_config="$(dump_kernel_config "$keyblock")"
|
||||||
|
else
|
||||||
|
# strings is less secure than dump_kernel_config, so let's try more
|
||||||
|
# keywords
|
||||||
|
kernel_config="$(strings "$keyblock" |
|
||||||
|
grep -w "root=" | grep -w "cros_recovery")"
|
||||||
|
fi
|
||||||
|
if (echo "$kernel_config" | grep -qw "cros_recovery") &&
|
||||||
|
(echo "$kernel_config" | grep -qw "kern_b_hash"); then
|
||||||
|
echo "recovery"
|
||||||
|
else
|
||||||
|
echo "usb"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "unknown"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
@ -68,24 +68,15 @@ DEFINE_string diskimg "" \
|
|||||||
DEFINE_boolean preserve ${FLAGS_FALSE} \
|
DEFINE_boolean preserve ${FLAGS_FALSE} \
|
||||||
"If set, reuse the diskimage file, if available"
|
"If set, reuse the diskimage file, if available"
|
||||||
DEFINE_integer sectors 31277232 "Size of image in sectors"
|
DEFINE_integer sectors 31277232 "Size of image in sectors"
|
||||||
|
DEFINE_boolean detect_release_image ${FLAGS_TRUE} \
|
||||||
|
"If set, try to auto-detect the type of release image and convert if required"
|
||||||
|
|
||||||
# Parse command line
|
# Parse command line
|
||||||
FLAGS "$@" || exit 1
|
FLAGS "$@" || exit 1
|
||||||
eval set -- "${FLAGS_ARGV}"
|
eval set -- "${FLAGS_ARGV}"
|
||||||
|
|
||||||
IMAGE_MOUNT_STACK=""
|
on_exit() {
|
||||||
|
image_clean_temp
|
||||||
image_push_mounts() {
|
|
||||||
IMAGE_MOUNT_STACK="$* $IMAGE_MOUNT_STACK"
|
|
||||||
}
|
|
||||||
|
|
||||||
image_pop_mounts() {
|
|
||||||
local dir=""
|
|
||||||
for dir in $IMAGE_MOUNT_STACK; do
|
|
||||||
sudo umount "$dir" || true
|
|
||||||
sudo rmdir "$dir" || true
|
|
||||||
done
|
|
||||||
IMAGE_MOUNT_STACK=""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_optional_file() {
|
check_optional_file() {
|
||||||
@ -159,12 +150,66 @@ setup_environment() {
|
|||||||
RELEASE_IMAGE="$(basename "${FLAGS_release}")"
|
RELEASE_IMAGE="$(basename "${FLAGS_release}")"
|
||||||
FACTORY_IMAGE="$(basename "${FLAGS_factory}")"
|
FACTORY_IMAGE="$(basename "${FLAGS_factory}")"
|
||||||
|
|
||||||
|
# Override this with path to modified kernel (for non-SSD images)
|
||||||
|
RELEASE_KERNEL=""
|
||||||
|
|
||||||
# Check required tools.
|
# Check required tools.
|
||||||
if ! image_has_part_tools; then
|
if ! image_has_part_tools; then
|
||||||
die "Missing partition tools. Please install cgpt/parted, or run in chroot."
|
die "Missing partition tools. Please install cgpt/parted, or run in chroot."
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Prepares release image source by checking image type, and creates modified
|
||||||
|
# partition blob in RELEASE_KERNEL if required.
|
||||||
|
prepare_release_image() {
|
||||||
|
local image="$(readlink -f "$1")"
|
||||||
|
local kernel="$(mktemp --tmpdir)"
|
||||||
|
image_add_temp "$kernel"
|
||||||
|
|
||||||
|
# Image Types:
|
||||||
|
# - recovery: kernel in #4 and vmlinuz_hd.vblock in #1
|
||||||
|
# - usb: kernel in #2 and vmlinuz_hd.vblock in #1
|
||||||
|
# - ssd: kernel in #2, no need to change
|
||||||
|
image_dump_partition "$image" "2" >"$kernel" 2>/dev/null ||
|
||||||
|
die "Cannot extract kernel partition from image: $image"
|
||||||
|
|
||||||
|
local image_type="$(image_cros_kernel_boot_type "$kernel")"
|
||||||
|
local need_vmlinuz_hd=""
|
||||||
|
info "Image type is [$image_type]: $image"
|
||||||
|
|
||||||
|
case "$image_type" in
|
||||||
|
"ssd" )
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
"usb" )
|
||||||
|
RELEASE_KERNEL="$kernel"
|
||||||
|
need_vmlinuz_hd="TRUE"
|
||||||
|
;;
|
||||||
|
"recovery" )
|
||||||
|
RELEASE_KERNEL="$kernel"
|
||||||
|
image_dump_partition "$image" "4" >"$kernel" 2>/dev/null ||
|
||||||
|
die "Cannot extract real kernel for recovery image: $image"
|
||||||
|
need_vmlinuz_hd="TRUE"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
die "Unexpected release image type: $image_type."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "$need_vmlinuz_hd" ]; then
|
||||||
|
local temp_mount="$(mktemp -d --tmpdir)"
|
||||||
|
local vmlinuz_hd_file="vmlinuz_hd.vblock"
|
||||||
|
image_add_temp "$temp_mount"
|
||||||
|
image_mount_partition "$image" "1" "$temp_mount" "ro" ||
|
||||||
|
die "No stateful partition in $image."
|
||||||
|
[ -s "$temp_mount/$vmlinuz_hd_file" ] ||
|
||||||
|
die "Missing $vmlinuz_hd_file in stateful partition: $image"
|
||||||
|
sudo dd if="$temp_mount/$vmlinuz_hd_file" of="$kernel" \
|
||||||
|
bs=512 conv=notrunc >/dev/null 2>&1 ||
|
||||||
|
die "Cannot update kernel with $vmlinuz_hd_file"
|
||||||
|
image_umount_partition "$temp_mount"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
prepare_img() {
|
prepare_img() {
|
||||||
local outdev="$(readlink -f "$FLAGS_diskimg")"
|
local outdev="$(readlink -f "$FLAGS_diskimg")"
|
||||||
@ -173,7 +218,8 @@ prepare_img() {
|
|||||||
|
|
||||||
# We'll need some code to put in the PMBR, for booting on legacy BIOS.
|
# We'll need some code to put in the PMBR, for booting on legacy BIOS.
|
||||||
echo "Fetch PMBR"
|
echo "Fetch PMBR"
|
||||||
local pmbrcode="$(mktemp -d)/gptmbr.bin"
|
local pmbrcode="$(mktemp --tmpdir)"
|
||||||
|
image_add_temp "$pmbrcode"
|
||||||
sudo dd bs=512 count=1 if="${FLAGS_release}" of="${pmbrcode}" status=noxfer
|
sudo dd bs=512 count=1 if="${FLAGS_release}" of="${pmbrcode}" status=noxfer
|
||||||
|
|
||||||
echo "Prepare base disk image"
|
echo "Prepare base disk image"
|
||||||
@ -213,10 +259,15 @@ prepare_dir() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Compresses kernel and rootfs of an imge file, and output its hash.
|
||||||
|
# Usage:compress_and_hash_memento_image kernel rootfs
|
||||||
|
# Please see "mk_memento_images --help" for detail of parameter syntax
|
||||||
compress_and_hash_memento_image() {
|
compress_and_hash_memento_image() {
|
||||||
local input_file="$1"
|
local kern="$1"
|
||||||
|
local rootfs="$2"
|
||||||
|
[ "$#" = "2" ] || die "Internal error: compress_and_hash_memento_image $*"
|
||||||
|
|
||||||
"${SCRIPTS_DIR}/mk_memento_images.sh" "$input_file:2" "$input_file:3" |
|
"${SCRIPTS_DIR}/mk_memento_images.sh" "$kern" "$rootfs" "." |
|
||||||
grep hash |
|
grep hash |
|
||||||
awk '{print $4}'
|
awk '{print $4}'
|
||||||
}
|
}
|
||||||
@ -268,8 +319,13 @@ generate_usbimg() {
|
|||||||
fi
|
fi
|
||||||
local builder="$(dirname "$SCRIPT")/make_universal_factory_shim.sh"
|
local builder="$(dirname "$SCRIPT")/make_universal_factory_shim.sh"
|
||||||
|
|
||||||
|
# TODO(hungte) Support non-SSD images
|
||||||
|
[ -z "$RELEASE_KERNEL" ] ||
|
||||||
|
die "Non-SSD image is not supported for --usbimg mode yet."
|
||||||
|
|
||||||
"$builder" -m "${FLAGS_factory}" -f "${FLAGS_usbimg}" \
|
"$builder" -m "${FLAGS_factory}" -f "${FLAGS_usbimg}" \
|
||||||
"${FLAGS_install_shim}" "${FLAGS_factory}" "${FLAGS_release}"
|
"${FLAGS_install_shim}" "${FLAGS_factory}" "${FLAGS_release}"
|
||||||
|
apply_hwid_updater "${FLAGS_hwid_updater}" "${FLAGS_usbimg}"
|
||||||
|
|
||||||
# Extract and modify lsb-factory from original install shim
|
# Extract and modify lsb-factory from original install shim
|
||||||
local lsb_path="/dev_image/etc/lsb-factory"
|
local lsb_path="/dev_image/etc/lsb-factory"
|
||||||
@ -277,9 +333,7 @@ generate_usbimg() {
|
|||||||
local src_lsb="${src_dir}${lsb_path}"
|
local src_lsb="${src_dir}${lsb_path}"
|
||||||
local new_dir="$(mktemp -d --tmpdir)"
|
local new_dir="$(mktemp -d --tmpdir)"
|
||||||
local new_lsb="${new_dir}${lsb_path}"
|
local new_lsb="${new_dir}${lsb_path}"
|
||||||
apply_hwid_updater "${FLAGS_hwid_updater}" "${FLAGS_usbimg}"
|
image_add_temp "$src_dir" "$new_dir"
|
||||||
image_push_mounts "$src_dir"
|
|
||||||
image_push_mounts "$new_dir"
|
|
||||||
image_mount_partition "${FLAGS_install_shim}" 1 "${src_dir}" ""
|
image_mount_partition "${FLAGS_install_shim}" 1 "${src_dir}" ""
|
||||||
image_mount_partition "${FLAGS_usbimg}" 1 "${new_dir}" "rw"
|
image_mount_partition "${FLAGS_usbimg}" 1 "${new_dir}" "rw"
|
||||||
# Copy firmware updater, if available
|
# Copy firmware updater, if available
|
||||||
@ -299,7 +353,8 @@ generate_usbimg() {
|
|||||||
echo "FACTORY_INSTALL_USB_OFFSET=2" &&
|
echo "FACTORY_INSTALL_USB_OFFSET=2" &&
|
||||||
echo "$updater_settings") |
|
echo "$updater_settings") |
|
||||||
sudo dd of="${new_lsb}"
|
sudo dd of="${new_lsb}"
|
||||||
image_pop_mounts
|
image_umount_partition "$new_dir"
|
||||||
|
image_umount_partition "$src_dir"
|
||||||
|
|
||||||
# Deactivate all kernel partitions except installer slot
|
# Deactivate all kernel partitions except installer slot
|
||||||
local i=""
|
local i=""
|
||||||
@ -325,7 +380,16 @@ generate_img() {
|
|||||||
# Get the release image.
|
# Get the release image.
|
||||||
local release_image="${RELEASE_DIR}/${RELEASE_IMAGE}"
|
local release_image="${RELEASE_DIR}/${RELEASE_IMAGE}"
|
||||||
echo "Release Kernel"
|
echo "Release Kernel"
|
||||||
|
if [ -n "$RELEASE_KERNEL" ]; then
|
||||||
|
local newkernel="$(image_map_partition "${outdev}" "4")"
|
||||||
|
local failed=""
|
||||||
|
sudo dd if="$RELEASE_KERNEL" of="$newkernel" bs=512 ||
|
||||||
|
failed="TRUE"
|
||||||
|
image_unmap_partition "$newkernel"
|
||||||
|
[ -z "$failed" ] || die "Failed to build release kernel."
|
||||||
|
else
|
||||||
image_partition_copy "${release_image}" 2 "${outdev}" 4
|
image_partition_copy "${release_image}" 2 "${outdev}" 4
|
||||||
|
fi
|
||||||
echo "Release Rootfs"
|
echo "Release Rootfs"
|
||||||
image_partition_copy "${release_image}" 3 "${outdev}" 5
|
image_partition_copy "${release_image}" 3 "${outdev}" 5
|
||||||
echo "OEM parition"
|
echo "OEM parition"
|
||||||
@ -347,8 +411,8 @@ generate_img() {
|
|||||||
# when cleaning up kernel commandlines. There is code that touches
|
# when cleaning up kernel commandlines. There is code that touches
|
||||||
# this in postint/chromeos-setimage and build_image. However none
|
# this in postint/chromeos-setimage and build_image. However none
|
||||||
# of the preexisting code actually does what we want here.
|
# of the preexisting code actually does what we want here.
|
||||||
local tmpesp="$(mktemp -d)"
|
local tmpesp="$(mktemp -d --tmpdir)"
|
||||||
image_push_mounts "$tmpesp"
|
image_add_temp "$tmpesp"
|
||||||
image_mount_partition "${outdev}" 12 "$tmpesp" "rw"
|
image_mount_partition "${outdev}" 12 "$tmpesp" "rw"
|
||||||
|
|
||||||
# Edit boot device default for legacy.
|
# Edit boot device default for legacy.
|
||||||
@ -362,12 +426,13 @@ generate_img() {
|
|||||||
# Somewhat safe as ARM does not support syslinux, I believe.
|
# Somewhat safe as ARM does not support syslinux, I believe.
|
||||||
sudo sed -i "s'HDROOTA'/dev/sda3'g" "${tmpesp}"/syslinux/root.A.cfg
|
sudo sed -i "s'HDROOTA'/dev/sda3'g" "${tmpesp}"/syslinux/root.A.cfg
|
||||||
|
|
||||||
image_pop_mounts
|
image_umount_partition "$tmpesp"
|
||||||
echo "Generated Image at $outdev."
|
echo "Generated Image at $outdev."
|
||||||
echo "Done"
|
echo "Done"
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_omaha() {
|
generate_omaha() {
|
||||||
|
local kernel rootfs
|
||||||
# Clean up stale config and data files.
|
# Clean up stale config and data files.
|
||||||
prepare_dir "${OMAHA_DATA_DIR}"
|
prepare_dir "${OMAHA_DATA_DIR}"
|
||||||
|
|
||||||
@ -381,7 +446,9 @@ generate_omaha() {
|
|||||||
pushd "${RELEASE_DIR}" >/dev/null
|
pushd "${RELEASE_DIR}" >/dev/null
|
||||||
prepare_dir "."
|
prepare_dir "."
|
||||||
|
|
||||||
release_hash="$(compress_and_hash_memento_image "${RELEASE_IMAGE}")"
|
kernel="${RELEASE_KERNEL:-${RELEASE_IMAGE}:2}"
|
||||||
|
rootfs="${RELEASE_IMAGE}:3"
|
||||||
|
release_hash="$(compress_and_hash_memento_image "$kernel" "$rootfs")"
|
||||||
mv ./update.gz "${OMAHA_DATA_DIR}/rootfs-release.gz"
|
mv ./update.gz "${OMAHA_DATA_DIR}/rootfs-release.gz"
|
||||||
echo "release: ${release_hash}"
|
echo "release: ${release_hash}"
|
||||||
|
|
||||||
@ -395,7 +462,9 @@ generate_omaha() {
|
|||||||
pushd "${FACTORY_DIR}" >/dev/null
|
pushd "${FACTORY_DIR}" >/dev/null
|
||||||
prepare_dir "."
|
prepare_dir "."
|
||||||
|
|
||||||
test_hash="$(compress_and_hash_memento_image "${FACTORY_IMAGE}")"
|
kernel="${FACTORY_IMAGE}:2"
|
||||||
|
rootfs="${FACTORY_IMAGE}:3"
|
||||||
|
test_hash="$(compress_and_hash_memento_image "$kernel" "$rootfs")"
|
||||||
mv ./update.gz "${OMAHA_DATA_DIR}/rootfs-test.gz"
|
mv ./update.gz "${OMAHA_DATA_DIR}/rootfs-test.gz"
|
||||||
echo "test: ${test_hash}"
|
echo "test: ${test_hash}"
|
||||||
|
|
||||||
@ -509,10 +578,13 @@ To run the server:
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
set -e
|
set -e
|
||||||
trap image_pop_mounts EXIT
|
trap on_exit EXIT
|
||||||
|
|
||||||
check_parameters
|
check_parameters
|
||||||
setup_environment
|
setup_environment
|
||||||
|
if [ "$FLAGS_detect_release_image" = "$FLAGS_TRUE" ]; then
|
||||||
|
prepare_release_image "$FLAGS_release"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$FLAGS_usbimg" ]; then
|
if [ -n "$FLAGS_usbimg" ]; then
|
||||||
generate_usbimg
|
generate_usbimg
|
||||||
|
Loading…
Reference in New Issue
Block a user