update_engine: Add "verify" support to brillo_update_payload
This change adds a new command "verify" to brillo_update_payload to verify the
process of update by applying a delta or full payload to temporary target
partitions and comparing them with the original target partitions. This is
specially usefull when manually debuggin/testing delta performer operations.
BUG=none
TEST=brillo_update_payload verify --payload=payload.delta --source_image=link_8872.49.bin --target_image=link_9000.82.bin
Change-Id: I4b30bc8a1088f4f72b681c6095cca6863a715078
Reviewed-on: https://chromium-review.googlesource.com/585565
Commit-Ready: Amin Hassani <ahassani@chromium.org>
Tested-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Sen Jiang <senj@chromium.org>
diff --git a/scripts/brillo_update_payload b/scripts/brillo_update_payload
index b139491..911d622 100755
--- a/scripts/brillo_update_payload
+++ b/scripts/brillo_update_payload
@@ -1,8 +1,20 @@
#!/bin/bash
-# Copyright 2015 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.
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
# Script to generate a Brillo update for use by the update engine.
#
@@ -12,14 +24,15 @@
# hash generate a payload or metadata hash
# sign generate a signed payload
# properties generate a properties file from a payload
+# verify verify a payload by recreating a target image.
#
# Generate command arguments:
# --payload generated unsigned payload output file
# --source_image if defined, generate a delta payload from the specified
# image to the target_image
# --target_image the target image that should be sent to clients
-# --metadata_size_file if defined, generate a file containing the size of the payload
-# metadata in bytes to the specified file
+# --metadata_size_file if defined, generate a file containing the size of the
+# payload metadata in bytes to the specified file
#
# Hash command arguments:
# --unsigned_payload the input unsigned payload to generate the hash from
@@ -50,6 +63,10 @@
# --payload the input signed or unsigned payload
# --properties_file the output path where to write the properties, or
# '-' for stdout.
+# Verify command arguments:
+# --payload payload input file
+# --source_image verify payload to the specified source image.
+# --target_image the target image to verify upon.
# Exit codes:
@@ -85,6 +102,7 @@
for signing."
HELP_SIGN="sign: Insert the signatures into the unsigned payload."
HELP_PROPERTIES="properties: Extract payload properties to a file."
+HELP_VERIFY="verify: Verify a (signed) update payload."
usage() {
echo "Supported commands:"
@@ -93,6 +111,7 @@
echo "${HELP_HASH}"
echo "${HELP_SIGN}"
echo "${HELP_PROPERTIES}"
+ echo "${HELP_VERIFY}"
echo
echo "Use: \"$0 <command> --help\" for more options."
}
@@ -123,6 +142,11 @@
properties)
FLAGS_HELP="${HELP_PROPERTIES}"
;;
+
+ verify)
+ FLAGS_HELP="${HELP_VERIFY}"
+ ;;
+
*)
echo "Unrecognized command: \"${COMMAND}\"" >&2
usage >&2
@@ -174,6 +198,15 @@
"Path to output the extracted property files. If '-' is passed stdout will \
be used."
fi
+if [[ "${COMMAND}" == "verify" ]]; then
+ DEFINE_string payload "" \
+ "Path to the input payload file."
+ DEFINE_string target_image "" \
+ "Path to the target image to verify upon."
+ DEFINE_string source_image "" \
+ "Optional: Path to a source image. If specified, the delta update is \
+applied to this."
+fi
DEFINE_string work_dir "${TMPDIR:-/tmp}" "Where to dump temporary files."
@@ -621,6 +654,87 @@
-properties_file="${FLAGS_properties_file}"
}
+validate_verify() {
+ [[ -n "${FLAGS_payload}" ]] ||
+ die "Error: you must specify an input filename with --payload FILENAME"
+
+ [[ -n "${FLAGS_target_image}" ]] ||
+ die "Error: you must specify a target image with --target_image FILENAME"
+}
+
+cmd_verify() {
+ local payload_type="delta"
+ if [[ -z "${FLAGS_source_image}" ]]; then
+ payload_type="full"
+ fi
+
+ echo "Extracting images for ${payload_type} update."
+
+ if [[ "${payload_type}" == "delta" ]]; then
+ extract_image "${FLAGS_source_image}" SRC_PARTITIONS
+ fi
+ extract_image "${FLAGS_target_image}" DST_PARTITIONS PARTITIONS_ORDER
+
+ declare -A TMP_PARTITIONS
+ for part in "${PARTITIONS_ORDER[@]}"; do
+ local tmp_part=$(create_tempfile "tmp_part.bin.XXXXXX")
+ echo "Creating temporary target partition ${tmp_part} for ${part}"
+ CLEANUP_FILES+=("${tmp_part}")
+ TMP_PARTITIONS[${part}]=${tmp_part}
+ local FILESIZE=$(stat -c%s "${DST_PARTITIONS[${part}]}")
+ echo "Truncating ${TMP_PARTITIONS[${part}]} to ${FILESIZE}"
+ truncate_file "${TMP_PARTITIONS[${part}]}" "${FILESIZE}"
+ done
+
+ echo "Verifying ${payload_type} update."
+ # Common payload args:
+ GENERATOR_ARGS=( -in_file="${FLAGS_payload}" )
+
+ local part old_partitions="" new_partitions="" partition_names=""
+ for part in "${PARTITIONS_ORDER[@]}"; do
+ if [[ -n "${partition_names}" ]]; then
+ partition_names+=":"
+ new_partitions+=":"
+ old_partitions+=":"
+ fi
+ partition_names+="${part}"
+ new_partitions+="${TMP_PARTITIONS[${part}]}"
+ old_partitions+="${SRC_PARTITIONS[${part}]:-}"
+ done
+
+ # Target image args:
+ GENERATOR_ARGS+=(
+ -partition_names="${partition_names}"
+ -new_partitions="${new_partitions}"
+ )
+
+ if [[ "${payload_type}" == "delta" ]]; then
+ # Source image args:
+ GENERATOR_ARGS+=(
+ -old_partitions="${old_partitions}"
+ )
+ fi
+
+ echo "Running delta_generator to verify ${payload_type} payload with args: \
+${GENERATOR_ARGS[@]}"
+ "${GENERATOR}" "${GENERATOR_ARGS[@]}"
+
+ if [[ $? -eq 0 ]]; then
+ echo "Done applying ${payload_type} update."
+ echo "Checking the newly generated partitions against the target partitions"
+ for part in "${PARTITIONS_ORDER[@]}"; do
+ cmp "${TMP_PARTITIONS[${part}]}" "${DST_PARTITIONS[${part}]}"
+ local not_str=""
+ if [[ $? -ne 0 ]]; then
+ not_str="in"
+ fi
+ echo "The new partition (${part}) is ${not_str}valid."
+ done
+ else
+ echo "Failed to apply ${payload_type} update."
+ fi
+}
+
# Sanity check that the real generator exists:
GENERATOR="$(which delta_generator || true)"
[[ -x "${GENERATOR}" ]] || die "can't find delta_generator"
@@ -638,4 +752,7 @@
properties) validate_properties
cmd_properties
;;
+ verify) validate_verify
+ cmd_verify
+ ;;
esac