1#!/bin/bash -ex
2usage () {
3    echo "Create a Mixed Build archive with the given system and device archives."
4    echo
5    echo "Usage: $0 [-v <vendor_version>] [-m <modify_system_image_path>] [-p <override_vbmeta_image_path>]"
6    echo "    system_build_dir device_build_dir out_dir [check_tool]"
7    echo
8    echo "Options -v, -m, -p must precede positional arguments."
9    echo
10    echo "vendor_version is the version of the vendor image when the mixed"
11    echo "    build is inter branch. Optional."
12    echo "    eg. 8.1.0 for a mixed build of GSI and O-MR1 vendor image."
13    echo "modify_system_image_path is the path to the script that modifies the"
14    echo "    system image for an inter branch build target. Optional."
15    echo "override_vbmeta_image_path is the path to a vbmeta.img to use"
16    echo "    to override the existing vbmeta.img of device. Optional."
17    echo "system_build_dir is the path to the system build"
18    echo "    eg. aosp_arm64_ab-userdebug."
19    echo "device_build_dir is the path to the device build"
20    echo "    eg. sailfish-user."
21    echo "out_dir is the path to where the new build will be placed."
22    echo "check_tool is the path to the checkvintf executable that will be"
23    echo "    used to verify the compatibility of the given images. Optional."
24}
25
26# Print error message and exit.
27# Usage: exit_badparam message
28#
29# message is a string to be displayed before exit.
30exit_badparam () {
31    echo "ERROR: $1" >&2
32    usage
33    exit 1
34}
35
36cleanup_and_exit () {
37    readonly result="$?"
38    rm -rf "$TEMP_DIR"
39    exit "$result"
40}
41
42trap cleanup_and_exit EXIT
43
44while getopts :v:m:p: opt; do
45    case "$opt" in
46        v)
47            readonly VENDOR_VERSION="$OPTARG"
48            ;;
49        m)
50            readonly MODIFY_SYSTEM_SCRIPT="$OPTARG"
51            ;;
52        p)
53            readonly OVERRIDE_VBMETA_IMAGE_PATH="$OPTARG"
54            ;;
55        \?)
56            exit_badparam "Invalid options: -"$OPTARG""
57            ;;
58        :)
59            exit_badparam "Option -"$OPTARG" requires an argument."
60            ;;
61    esac
62done
63
64if [[ -z "${VENDOR_VERSION+x}" && ! -z "${MODIFY_SYSTEM_SCRIPT+x}" ]] || [[ ! -z "${VENDOR_VERSION+x}" && -z "${MODIFY_SYSTEM_SCRIPT+x}" ]]; then
65    exit_badparam "Options -v and -m must be set together."
66fi
67
68shift "$((OPTIND-1))"
69
70if [[ ! -z "${MODIFY_SYSTEM_SCRIPT+x}" && ! -f "$MODIFY_SYSTEM_SCRIPT" ]]; then
71    exit_badparam "Script not found: "$MODIFY_SYSTEM_SCRIPT""
72fi
73
74if [[ ! -z "${OVERRIDE_VBMETA_IMAGE_PATH+x}" && ! -f "$OVERRIDE_VBMETA_IMAGE_PATH" ]]; then
75    exit_badparam "Specified vbmeta.img not found: "$OVERRIDE_VBMETA_IMAGE_PATH""
76fi
77
78if [[ $# -lt 3 ]]; then
79    exit_badparam "Unexpected number of arguments"
80fi
81
82readonly SYSTEM_DIR="$1"
83readonly DEVICE_DIR="$2"
84readonly DIST_DIR="$3"
85readonly CHECK_TOOL="$4"
86readonly TEMP_DIR="$(mktemp -d /tmp/"$(basename $0)"_XXXXXXXX)"
87
88readonly SYSTEM_TARGET_FILES_ARCHIVE="$(find "$SYSTEM_DIR" -name "*-target_files-*.zip" -print)"
89if [[ ! -f "$SYSTEM_TARGET_FILES_ARCHIVE" ]]; then
90    exit_badparam "Could not find system target files archive in $SYSTEM_DIR."
91fi
92
93readonly DEVICE_ARCHIVE="$(find "$DEVICE_DIR" -name "*-img-*.zip" -print)"
94if [[ ! -f "$DEVICE_ARCHIVE" ]]; then
95    exit_badparam "Could not find device img archive in $DEVICE_DIR."
96fi
97
98readonly DEVICE_TARGET_FILES_ARCHIVE="$(find "$DEVICE_DIR" -name "*-target_files-*.zip" -print)"
99if [[ ! -f "$DEVICE_ARCHIVE" ]]; then
100    exit_badparam "Could not find device target_files archive in $DEVICE_DIR."
101fi
102
103readonly DEVICE_ARTIFACTS_DIR="$TEMP_DIR"/device_archive_artifacts
104readonly DEVICE_IMAGES_DIR="$DEVICE_ARTIFACTS_DIR"/IMAGES
105readonly SYSTEM_ARTIFACTS_DIR="$TEMP_DIR"/system_artifacts
106readonly SYSTEM_IMAGES_DIR="$SYSTEM_ARTIFACTS_DIR"/IMAGES
107
108readonly SPL_PROPERTY_NAME="ro.build.version.security_patch"
109readonly SYSTEM_BUILD_PROP="SYSTEM/build.prop"
110
111###
112# Uncompress the archives.
113mkdir -p "$SYSTEM_ARTIFACTS_DIR"
114# Get the system images and meta data.
115unzip "$SYSTEM_TARGET_FILES_ARCHIVE" \
116  IMAGES/system.img IMAGES/vbmeta.img META/system_matrix.xml META/system_manifest.xml "$SYSTEM_BUILD_PROP" \
117  -d "$SYSTEM_ARTIFACTS_DIR"
118
119mkdir -p "$DEVICE_IMAGES_DIR"
120# Get the device images.
121unzip "$DEVICE_ARCHIVE" -d "$DEVICE_IMAGES_DIR"
122# Get the device meta data.
123unzip "$DEVICE_TARGET_FILES_ARCHIVE" \
124  META/vendor_matrix.xml META/vendor_manifest.xml "$SYSTEM_BUILD_PROP" \
125  -d "$DEVICE_ARTIFACTS_DIR"
126
127###
128# Check compatibility between the system and device.
129if [[ -f "$CHECK_TOOL" ]]; then
130    chmod 755 "$CHECK_TOOL"
131    "$CHECK_TOOL" \
132        "$DEVICE_ARTIFACTS_DIR"/META/vendor_manifest.xml \
133        "$SYSTEM_ARTIFACTS_DIR"/META/system_matrix.xml
134    "$CHECK_TOOL" \
135        "$SYSTEM_ARTIFACTS_DIR"/META/system_manifest.xml \
136        "$DEVICE_ARTIFACTS_DIR"/META/vendor_matrix.xml
137fi
138
139###
140# Modify system.img if vendor version is provided.
141if [[ ! -z "${VENDOR_VERSION+x}" ]]; then
142    # Create copy of system target files package that can be modified
143    # since the original $SYSTEM_TARGET_FILES_ARCHIVE is a symlink to
144    # prebuilt files in cache
145    cp "$SYSTEM_TARGET_FILES_ARCHIVE" "$TEMP_DIR"
146    readonly COPY_SYSTEM_TARGET_FILES_ARCHIVE="$TEMP_DIR"/"$(basename "$SYSTEM_TARGET_FILES_ARCHIVE")"
147
148    # Check compatibility of security patch level
149    readonly SYSTEM_SPL=$(sed -n -r "s/^"$SPL_PROPERTY_NAME"=(.*)$/\1/p" "$SYSTEM_ARTIFACTS_DIR"/"$SYSTEM_BUILD_PROP")
150    readonly VENDOR_SPL=$(sed -n -r "s/^"$SPL_PROPERTY_NAME"=(.*)$/\1/p" "$DEVICE_ARTIFACTS_DIR"/"$SYSTEM_BUILD_PROP")
151    declare -a args
152    args=(-v "$VENDOR_VERSION" "$COPY_SYSTEM_TARGET_FILES_ARCHIVE")
153    if [[ "$SYSTEM_SPL" != "$VENDOR_SPL" ]]; then
154        echo "Security patch level mismatch detected..."
155        echo "  SPL of system: "$SYSTEM_SPL""
156        echo "  SPL of vendor: "$VENDOR_SPL""
157        args+=("$VENDOR_SPL")
158    fi
159    "$MODIFY_SYSTEM_SCRIPT" "${args[@]}"
160    # Replace system.img with newly modified system.img
161    unzip -o "$COPY_SYSTEM_TARGET_FILES_ARCHIVE" IMAGES/system.img -d "$SYSTEM_ARTIFACTS_DIR"
162fi
163
164###
165# Overwrite artifacts in the device archive to create the Mixed Build artifacts.
166cp "$SYSTEM_IMAGES_DIR"/system.img "$DEVICE_IMAGES_DIR"/
167
168# Only override vbmeta if it is already present since fastboot update will try
169# to flash whatever is in the archive.
170if [[ -f "$DEVICE_IMAGES_DIR"/vbmeta.img ]]; then
171    readonly VBMETA_IMAGE_PATH="${OVERRIDE_VBMETA_IMAGE_PATH:-"$SYSTEM_IMAGES_DIR"/vbmeta.img}"
172    cp "$VBMETA_IMAGE_PATH" "$DEVICE_IMAGES_DIR"/
173fi
174
175###
176# Create the Mixed Build archive.
177(
178    cd "$DEVICE_IMAGES_DIR"
179    zip -r mixed.zip ./*
180)
181
182###
183# Archive the artifacts.
184if [ -n "$DIST_DIR" ]; then
185    mkdir -p "$DIST_DIR" || true
186fi
187# Archive all the device artifacts.
188rsync --archive --verbose --copy-links --exclude='logs' \
189  "$DEVICE_DIR"/* "$DIST_DIR"
190# Overwrite the image archive with the Mixed Build archive.
191OUT_ARCHIVE="$DIST_DIR"/"$(basename $DEVICE_ARCHIVE)"
192cp "$DEVICE_IMAGES_DIR"/mixed.zip "$OUT_ARCHIVE"
193