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>]" 6 echo " [-t <prebuilt_otatools_path>] [-p <override_vbmeta_image_path>]" 7 echo " [-b <override_boot_image_path>]" 8 echo " [-s] [-d] system_build_dir device_build_dir out_dir" 9 echo 10 echo "Options -v, -m, -t, -p, -b, -s, -d must precede positional arguments." 11 echo 12 echo "vendor_version is the version of the vendor image when Keymaster v3" 13 echo " related modifications to the system image is necessary. Optional." 14 echo " eg. 8.1.0 for a mixed build of GSI and O-MR1 vendor image." 15 echo "modify_system_image_path is the path to the script that modifies the" 16 echo " system image, needed for Keymaster v3. Optional." 17 echo "prebuilt_otatools_path is the path to otatools.zip file that has all" 18 echo " required host binaries to modify system image. It also must include" 19 echo " VINTF check tool to verify the compatibility of the given images." 20 echo " Optional." 21 echo "override_vbmeta_image_path is the path to a vbmeta.img to use" 22 echo " to override the existing vbmeta.img of device. Optional." 23 echo "override_boot_image_path is the path to a boot imgage to use to" 24 echo " override the existing boot.img of device. Optional." 25 echo "-s is used to fetch and flash both product.img and system.img from" 26 echo " the system_build_dir for devices with a product partition." 27 echo " product.img will be removed if system_build_dir does not have" 28 echo " product.img when -s option is declared." 29 echo " By default, only system.img is flashed to the target device for" 30 echo " independent system update. No parameter required. Optional" 31 echo "-d is used to skip vbmeta.img replacement in its entirety and the" 32 echo " one from the device build (if exists) is left untouched" 33 echo "system_build_dir is the path to the system build" 34 echo " eg. aosp_arm64_ab-userdebug." 35 echo "device_build_dir is the path to the device build" 36 echo " eg. sailfish-user." 37 echo "out_dir is the path to where the new build will be placed." 38} 39 40# Print error message and exit. 41# Usage: exit_badparam message 42# 43# message is a string to be displayed before exit. 44exit_badparam () { 45 echo "ERROR: $1" >&2 46 usage 47 exit 1 48} 49 50cleanup_and_exit () { 51 readonly result="$?" 52 rm -rf "$TEMP_DIR" 53 exit "$result" 54} 55 56trap cleanup_and_exit EXIT 57 58while getopts :v:m:p:b:t:sd opt; do 59 case "$opt" in 60 v) 61 readonly VENDOR_VERSION="$OPTARG" 62 ;; 63 m) 64 readonly MODIFY_SYSTEM_SCRIPT="$OPTARG" 65 ;; 66 p) 67 readonly OVERRIDE_VBMETA_IMAGE_PATH="$OPTARG" 68 ;; 69 b) 70 readonly OVERRIDE_BOOT_IMAGE_PATH="$OPTARG" 71 ;; 72 t) 73 readonly OTATOOLS_ZIP="$OPTARG" 74 ;; 75 s) 76 readonly INCLUDE_PRODUCT=true 77 ;; 78 d) 79 readonly SKIP_VBMETA_REPLACE=true 80 ;; 81 \?) 82 exit_badparam "Invalid options: -"$OPTARG"" 83 ;; 84 :) 85 exit_badparam "Option -"$OPTARG" requires an argument." 86 ;; 87 esac 88done 89 90if [[ -z "${VENDOR_VERSION+x}" && ! -z "${MODIFY_SYSTEM_SCRIPT+x}" ]] || \ 91 [[ ! -z "${VENDOR_VERSION+x}" && -z "${MODIFY_SYSTEM_SCRIPT+x}" ]]; then 92 exit_badparam "Options -v and -m must be set together." 93fi 94 95shift "$((OPTIND-1))" 96 97if [[ $# -lt 3 ]]; then 98 exit_badparam "Unexpected number of arguments" 99fi 100 101readonly SYSTEM_DIR="$1" 102readonly DEVICE_DIR="$2" 103readonly DIST_DIR="$3" 104readonly TEMP_DIR="$(mktemp -d /tmp/"$(basename $0)"_XXXXXXXX)" 105 106readonly SYSTEM_TARGET_FILES_ARCHIVE="$(find "$SYSTEM_DIR" -name "*-target_files-*.zip" -print)" 107if [[ ! -f "$SYSTEM_TARGET_FILES_ARCHIVE" ]]; then 108 exit_badparam "Could not find system target files archive in $SYSTEM_DIR." 109fi 110 111readonly DEVICE_ARCHIVE="$(find "$DEVICE_DIR" -name "*-img-*.zip" -print)" 112if [[ ! -f "$DEVICE_ARCHIVE" ]]; then 113 exit_badparam "Could not find device img archive in $DEVICE_DIR." 114fi 115 116readonly DEVICE_TARGET_FILES_ARCHIVE="$(find "$DEVICE_DIR" -name "*-target_files-*.zip" -print)" 117if [[ ! -f "$DEVICE_TARGET_FILES_ARCHIVE" ]]; then 118 exit_badparam "Could not find device target_files archive in $DEVICE_DIR." 119fi 120 121if [[ ! -z "${MODIFY_SYSTEM_SCRIPT+x}" && ! -f "$MODIFY_SYSTEM_SCRIPT" ]]; then 122 exit_badparam "Script not found: "$MODIFY_SYSTEM_SCRIPT"" 123fi 124 125if [[ ! -z "${OVERRIDE_VBMETA_IMAGE_PATH+x}" && ! -f "$OVERRIDE_VBMETA_IMAGE_PATH" ]]; then 126 exit_badparam "Specified vbmeta.img not found: "$OVERRIDE_VBMETA_IMAGE_PATH"" 127fi 128 129if [[ ! -z "${OVERRIDE_BOOT_IMAGE_PATH+x}" && ! -f "$OVERRIDE_BOOT_IMAGE_PATH" ]]; then 130 exit_badparam "Specified boot image not found: "$OVERRIDE_BOOT_IMAGE_PATH"" 131fi 132 133readonly DEVICE_ARTIFACTS_DIR="$TEMP_DIR"/device_archive_artifacts 134readonly DEVICE_IMAGES_DIR="$DEVICE_ARTIFACTS_DIR"/IMAGES 135readonly SYSTEM_ARTIFACTS_DIR="$TEMP_DIR"/system_artifacts 136readonly SYSTEM_IMAGES_DIR="$SYSTEM_ARTIFACTS_DIR"/IMAGES 137readonly OTATOOLS_DIR="$TEMP_DIR"/otatools 138 139readonly SPL_PROPERTY_NAME="ro.build.version.security_patch" 140readonly SYSTEM_BUILD_PROP="SYSTEM/build.prop" 141 142declare -a EXTRACT_SYSTEM_FILE_LIST 143EXTRACT_SYSTEM_FILE_LIST=( 144 IMAGES/system.img \ 145 IMAGES/vbmeta.img \ 146 "$SYSTEM_BUILD_PROP" \ 147) 148 149declare -a EXTRACT_VINTF_SYSTEM_FILE_LIST 150EXTRACT_VINTF_SYSTEM_FILE_LIST=( 151 "$SYSTEM_BUILD_PROP" \ 152) 153 154declare -a EXTRACT_DEVICE_FILE_LIST 155EXTRACT_DEVICE_FILE_LIST=( 156 */build.prop \ 157 META/* \ 158) 159 160declare -A SYSTEM_SEARCH_PATH 161SYSTEM_SEARCH_PATH=( \ 162 [/system]="SYSTEM" \ 163 [/product]="PRODUCT SYSTEM/product" \ 164 [/system_ext]="SYSTEM_EXT SYSTEM/system_ext" \ 165) 166 167declare -A DEVICE_SEARCH_PATH 168# Mixed build will not have /vendor to SYSTEM/vendor case 169DEVICE_SEARCH_PATH=( \ 170 [/vendor]="VENDOR" \ 171 [/odm]="ODM VENDOR/odm" \ 172) 173 174### 175# Uncompress otatools.zip and get vintf file list. 176if [[ ! -f "$OTATOOLS_ZIP" ]]; then 177 echo "WARNING: otatools.zip is missing. Add \"-t otatools.zip\" to enable checkvintf" 178else 179 readonly OTATOOLS_AVAILABLE=true 180 # Uncompress otatools 181 mkdir -p "$OTATOOLS_DIR" 182 unzip "$OTATOOLS_ZIP" bin/* lib64/* -d "$OTATOOLS_DIR" 183 # Set paths for using prebuilt host binaries. 184 export PATH="$OTATOOLS_DIR"/bin:"$PATH" 185 export LD_LIBRARY_PATH="$OTATOOLS_DIR"/lib64:"$LD_LIBRARY_PATH" 186 187 # Add vintf file to extract file list 188 declare -a VINTF_DUMP_FILE_LIST 189 VINTF_DUMP_FILE_LIST=( "$(checkvintf --dump-file-list)" ) 190 191 for vintf_file_list in ${VINTF_DUMP_FILE_LIST[*]}; do 192 if [[ "$vintf_file_list" == */ ]]; then 193 vintf_file_list="$vintf_file_list"\* 194 # Create system vintf file list for system target files archive 195 for system_dir in "${!SYSTEM_SEARCH_PATH[@]}"; do 196 if [[ "$vintf_file_list" == "$system_dir"/* ]]; then 197 for search_dir in ${SYSTEM_SEARCH_PATH["$system_dir"]}; do 198 search_file=${vintf_file_list/$system_dir/$search_dir} 199 unzip -l "$SYSTEM_TARGET_FILES_ARCHIVE" "$search_file" > /dev/null && \ 200 EXTRACT_VINTF_SYSTEM_FILE_LIST+=( "$search_file" ) 201 done 202 break 203 fi 204 done 205 # Create device vintf file list for device target files archive 206 for device_dir in "${!DEVICE_SEARCH_PATH[@]}"; do 207 if [[ "$vintf_file_list" == "$device_dir"/* ]]; then 208 for search_dir in ${DEVICE_SEARCH_PATH["$device_dir"]}; do 209 search_file=${vintf_file_list/$device_dir/$search_dir} 210 unzip -l "$DEVICE_TARGET_FILES_ARCHIVE" "$search_file" > /dev/null && \ 211 EXTRACT_DEVICE_FILE_LIST+=( "$search_file" ) 212 done 213 break 214 fi 215 done 216 fi 217 done 218fi 219 220### 221# Uncompress the system archives. 222if [[ "$INCLUDE_PRODUCT" == true ]]; then 223 unzip -l "$SYSTEM_TARGET_FILES_ARCHIVE" | grep -q IMAGES/product.img && 224 EXTRACT_SYSTEM_FILE_LIST+=(IMAGES/product.img) 225fi 226 227mkdir -p "$SYSTEM_ARTIFACTS_DIR" 228# Get system images. 229unzip "$SYSTEM_TARGET_FILES_ARCHIVE" "${EXTRACT_SYSTEM_FILE_LIST[@]}" \ 230 -d "$SYSTEM_ARTIFACTS_DIR" 231 232### 233# Uncompress the device archives. 234mkdir -p "$DEVICE_IMAGES_DIR" 235# Get device images. 236unzip "$DEVICE_ARCHIVE" -d "$DEVICE_IMAGES_DIR" 237# Get the device meta data. 238unzip "$DEVICE_TARGET_FILES_ARCHIVE" "${EXTRACT_DEVICE_FILE_LIST[@]}" \ 239 -d "$DEVICE_ARTIFACTS_DIR" 240 241### 242# Modify system.img if vendor version is provided. 243if [[ ! -z "${VENDOR_VERSION+x}" ]]; then 244 # Create copy of system target files package that can be modified 245 # since the original $SYSTEM_TARGET_FILES_ARCHIVE is a symlink to 246 # prebuilt files in cache 247 cp "$SYSTEM_TARGET_FILES_ARCHIVE" "$TEMP_DIR" 248 readonly COPY_SYSTEM_TARGET_FILES_ARCHIVE="$TEMP_DIR"/"$(basename "$SYSTEM_TARGET_FILES_ARCHIVE")" 249 250 # Check compatibility of security patch level 251 readonly SYSTEM_SPL=$(sed -n -r "s/^"$SPL_PROPERTY_NAME"=(.*)$/\1/p" "$SYSTEM_ARTIFACTS_DIR"/"$SYSTEM_BUILD_PROP") 252 readonly VENDOR_SPL=$(sed -n -r "s/^"$SPL_PROPERTY_NAME"=(.*)$/\1/p" "$DEVICE_ARTIFACTS_DIR"/"$SYSTEM_BUILD_PROP") 253 declare -a args 254 args=(-v "$VENDOR_VERSION" "$COPY_SYSTEM_TARGET_FILES_ARCHIVE") 255 if [[ "$SYSTEM_SPL" != "$VENDOR_SPL" ]]; then 256 echo "Security patch level mismatch detected..." 257 echo " SPL of system: "$SYSTEM_SPL"" 258 echo " SPL of vendor: "$VENDOR_SPL"" 259 args+=("$VENDOR_SPL") 260 fi 261 "$MODIFY_SYSTEM_SCRIPT" "${args[@]}" 262 # Replace system.img with newly modified system.img 263 unzip -o "$COPY_SYSTEM_TARGET_FILES_ARCHIVE" IMAGES/system.img -d "$SYSTEM_ARTIFACTS_DIR" 264fi 265 266# Check vintf 267if [[ "$OTATOOLS_AVAILABLE" == true ]]; then 268 # Overwrite VINTF system matrix to device artifacts dir 269 unzip -o "$SYSTEM_TARGET_FILES_ARCHIVE" "${EXTRACT_VINTF_SYSTEM_FILE_LIST[@]}" \ 270 -d "$DEVICE_ARTIFACTS_DIR" 271 check_target_files_vintf "$DEVICE_ARTIFACTS_DIR" 272fi 273 274### 275# Overwrite artifacts in the device archive to create the Mixed Build artifacts. 276cp "$SYSTEM_IMAGES_DIR"/system.img "$DEVICE_IMAGES_DIR"/ 277if [[ "$INCLUDE_PRODUCT" == true ]]; then 278 if [[ -f "$SYSTEM_IMAGES_DIR"/product.img ]]; then 279 cp "$SYSTEM_IMAGES_DIR"/product.img "$DEVICE_IMAGES_DIR"/ 280 else 281 rm -f "$DEVICE_IMAGES_DIR"/product.img 282 # Removed product partition from required partition list 283 sed -i "/partition-exists=product$/d" "$DEVICE_IMAGES_DIR"/android-info.txt 284 fi 285fi 286 287if [[ "$SKIP_VBMETA_REPLACE" == true ]]; then 288 # Totally skip the vbmeta.img replacement 289 echo "Skip vbmeta.img replacement." 290else 291 # Only override vbmeta if it is already present since fastboot update will try 292 # to flash whatever is in the archive. 293 if [[ -f "$DEVICE_IMAGES_DIR"/vbmeta.img ]]; then 294 readonly VBMETA_IMAGE_PATH="${OVERRIDE_VBMETA_IMAGE_PATH:-"$SYSTEM_IMAGES_DIR"/vbmeta.img}" 295 cp "$VBMETA_IMAGE_PATH" "$DEVICE_IMAGES_DIR"/ 296 fi 297fi 298 299# Override boot.img with the provided boot image file since fastboot update cmd 300# will try to flash boot.img in the archive. 301if [[ ! -z "${OVERRIDE_BOOT_IMAGE_PATH+x}" && -f "$DEVICE_IMAGES_DIR"/boot.img ]]; then 302 cp "$OVERRIDE_BOOT_IMAGE_PATH" "$DEVICE_IMAGES_DIR"/boot.img 303fi 304 305### 306# Create the Mixed Build archive. 307( 308 cd "$DEVICE_IMAGES_DIR" 309 zip -r mixed.zip ./* 310) 311 312### 313# Archive the artifacts. 314if [ -n "$DIST_DIR" ]; then 315 mkdir -p "$DIST_DIR" || true 316fi 317# Archive all the device artifacts. 318rsync --archive --verbose --copy-links --exclude='logs' \ 319 "$DEVICE_DIR"/* "$DIST_DIR" 320# Overwrite the image archive with the Mixed Build archive. 321OUT_ARCHIVE="$DIST_DIR"/"$(basename $DEVICE_ARCHIVE)" 322cp "$DEVICE_IMAGES_DIR"/mixed.zip "$OUT_ARCHIVE" 323# Overwrite android-info.txt with the updated one. 324cp "$DEVICE_IMAGES_DIR"/android-info.txt "$DIST_DIR"/ 325