mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-09 05:56:58 +02:00
When we want to separate kernel and rootfs, there must be a more flexible syntax to assign input source. The partition info parsing code is also improved to detect errors. BUG=chromium-os:15050 TEST=./make_factory_package --release RECOVERY --factory FACTORY Change-Id: Ie74b3e23117480a7f503488b39dedceadbfb41e3 Reviewed-on: http://gerrit.chromium.org/gerrit/5962 Reviewed-by: Nick Sanders <nsanders@chromium.org> Tested-by: Hung-Te Lin <hungte@chromium.org>
170 lines
4.9 KiB
Bash
Executable File
170 lines
4.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.
|
|
|
|
# This script takes a path to a rootfs.ext2 which was generated by
|
|
# build_image.sh and generates an image that can be used for auto
|
|
# update.
|
|
|
|
set -e
|
|
|
|
# --- 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=(/usr/lib/crosutils $(dirname "$(readlink -f "$0")"))
|
|
local path
|
|
|
|
SCRIPT_ROOT=
|
|
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" || { echo "Unable to load common.sh"; exit 1; }
|
|
# --- END COMMON.SH BOILERPLATE ---
|
|
|
|
# Load functions designed for image processing
|
|
if ! . "${SCRIPT_ROOT}/lib/cros_image_common.sh"; then
|
|
echo "ERROR: Cannot load required library: lib/cros_image_common.sh; Abort."
|
|
exit 1
|
|
fi
|
|
|
|
# We need 2-3 non-zero parameters.
|
|
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ] || [ -z "$1" ] || [ -z "$2" ]; then
|
|
echo "
|
|
Usage: $0 kernel_partition_img[:index] rootfs_partition_img[:index] [output_dir]
|
|
|
|
Input parameters may be either a simple partition image file, or a
|
|
disk image file name followed by ':' and target partition index number
|
|
|
|
If output_dir is omitted, the folder of kernel_partition_img will be
|
|
use.
|
|
|
|
Examples:
|
|
$0 part_2 part_3
|
|
$0 chromiumos_image.bin:2 part3
|
|
$0 chromiumos_image.bin:2 otherimage.bin:3 /tmp/myoutput
|
|
"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$CROS_GENERATE_UPDATE_PAYLOAD_CALLED" != "1" ]; then
|
|
echo "WARNING:"
|
|
echo " This script should only be called from cros_generate_update_payload"
|
|
echo " Please run that script with --help to see how to use it."
|
|
fi
|
|
|
|
if ! image_has_command pigz; then
|
|
(echo "WARNING:"
|
|
echo " Your system does not have pigz (parallel gzip) installed."
|
|
echo " COMPRESSING WILL BE VERY SLOW. It is recommended to install pigz"
|
|
if image_has_command apt-get; then
|
|
echo " by 'sudo apt-get install pigz'."
|
|
elif image_has_command emerge; then
|
|
echo " by 'sudo emerge pigz'."
|
|
fi) >&2
|
|
fi
|
|
|
|
if [ $(whoami) = "root" ]; then
|
|
echo "running $0 as root which is unneccessary"
|
|
fi
|
|
|
|
# Usage: load_partition_file VARIABLE_NAME_PREFIX partition_file
|
|
# Writes VARIABLE_NAME_PREFIX[, _OFFSE, _SIZE, _SECTORS] by parsing
|
|
# partition_file, which can be a simple file or image:partno.
|
|
load_partition_file() {
|
|
local var_prefix="$1"
|
|
local var="$2"
|
|
local var_offset=""
|
|
local var_size=""
|
|
local var_sectors=""
|
|
local part_no="${var##*:}"
|
|
|
|
# test if var is in image:partno format.
|
|
if [ "$part_no" != "$var" ]; then
|
|
var="${var%:*}"
|
|
else
|
|
part_no=""
|
|
fi
|
|
|
|
if [ -z "$part_no" ]; then
|
|
var_offset=0
|
|
var_size="$(stat -c"%s" "$var")" ||
|
|
image_die "Invalid file: $var"
|
|
var_sectors="$((var_size / 512))"
|
|
else
|
|
var_offset="$(image_part_offset "$var" "$part_no")" ||
|
|
image_die "Cannot retieve offset for partition $var:$part_no"
|
|
var_sectors="$(image_part_size "$var" "$part_no")" ||
|
|
image_die "Cannot retieve size for partition $var:$part_no"
|
|
var_size=$((var_sectors * 512))
|
|
fi
|
|
|
|
# publish the values
|
|
eval "${var_prefix}"="$var"
|
|
eval "${var_prefix}_OFFSET"="$var_offset"
|
|
eval "${var_prefix}_SIZE"="$var_size"
|
|
eval "${var_prefix}_SECTORS"="$var_sectors"
|
|
}
|
|
|
|
load_partition_file KPART "$1"
|
|
load_partition_file ROOTFS "$2"
|
|
|
|
# Sanity check size.
|
|
if [ "$KPART_SIZE" -gt $((16 * 1024 * 1024)) ]; then
|
|
echo "Kernel partition size ($KPART_SIZE bytes) greater than 16 MiB."
|
|
echo "That's too big."
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$#" = "3" ]; then
|
|
FINAL_OUT_DIR="$(readlink -f $3)"
|
|
else
|
|
FINAL_OUT_DIR="$(dirname "$(readlink -f $1)")"
|
|
fi
|
|
FINAL_OUT_FILE="$FINAL_OUT_DIR/update.gz"
|
|
echo "Output: $FINAL_OUT_FILE"
|
|
|
|
# Update payload format:
|
|
# [kernel_size: big-endian uint64][kernel_blob][rootfs_blob]
|
|
|
|
# Prepare kernel_size by using printf as a number like 00000000003d0900, then
|
|
# sed to convert as: \x00\x00\x00\x00\x00\x3d\x09\x00, finally echo -e to
|
|
# convert into binary.
|
|
KPART_SIZE_SIGNATURE="$(printf "%016x" "$KPART_SIZE" |
|
|
sed 's/\([0-9a-f][0-9a-f]\)/\\x\1/g')"
|
|
|
|
# Build the blob!
|
|
CS_AND_RET_CODES="$(
|
|
(echo -en "$KPART_SIZE_SIGNATURE"
|
|
echo "Compressing kernel..." >&2
|
|
image_dump_partial_file "$KPART" "$KPART_OFFSET" "$KPART_SECTORS"
|
|
echo "Compressing rootfs..." >&2
|
|
image_dump_partial_file "$ROOTFS" "$ROOTFS_OFFSET" "$ROOTFS_SECTORS") |
|
|
image_gzip_compress -c -9 |
|
|
tee "$FINAL_OUT_FILE" |
|
|
openssl sha1 -binary |
|
|
openssl base64 |
|
|
tr '\n' ' '
|
|
echo ${PIPESTATUS[*]})"
|
|
|
|
EXPECTED_RET_CODES="0 0 0 0 0 0"
|
|
set -- $CS_AND_RET_CODES
|
|
CALC_CS="$1"
|
|
shift
|
|
RET_CODES="$@"
|
|
if [ "$RET_CODES" != "$EXPECTED_RET_CODES" ]; then
|
|
echo compression/hash failed. $RET_CODES
|
|
exit 1
|
|
fi
|
|
|
|
echo Success. hash is "$CALC_CS"
|