1 #!/bin/bash 2 3 # Copyright (C) 2018 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 # This script modifies the original GSI to match the vendor version and 18 # the security patch level. 19 # 20 # Usage: change_security_patch_ver.sh <system.img> [<output_system.img> \ 21 # [<new_security_patch_level> [<input_file_contexts.bin>]]] \ 22 # [-v <vendor_version>] 23 # 24 # Examples: 25 # change_security_patch_ver.sh system.img 26 # - Shows current version information. 27 # change_security_patch_ver.sh system.img new_system.img 2018-04-05 28 # - Make new_system.img that has replaced SPL with 2018-04-05. 29 # change_security_patch_ver.sh system.img new_system.img -v 8.1.0 30 # - Make new_system.img that includes the patches for vendor version 8.1.0. 31 # change_security_patch_ver.sh system.img new_system.img 2018-04-05 -v 8.1.0 32 # - Make new_system.img that has both new SPL and vendor version. 33 34 function unmount() { 35 echo "Unmounting..." 36 sudo umount "${MOUNT_POINT}/" 37 } 38 39 SCRIPT_NAME=$(basename $0) 40 SUPPORTED_VENDOR_VERSIONS="8.1.0" 41 42 param_count=0 43 while [[ $# -gt 0 ]] 44 do 45 case $1 in 46 -v|--vendor) # set vendor version 47 VENDOR_VERSION=$2 48 shift 49 shift 50 ;; 51 *) # set the ordered parameters 52 ((param_count++)) 53 case $param_count in 54 1) # The input file name for original GSI 55 SYSTEM_IMG=$1 56 shift 57 ;; 58 2) # The output file name for modified GSI 59 OUTPUT_SYSTEM_IMG=$1 60 shift 61 ;; 62 3) # New Security Patch Level to be written. It must be YYYY-MM-DD format. 63 NEW_SPL=$1 64 shift 65 ;; 66 4) # Selinux file context 67 FILE_CONTEXTS_BIN=$1 68 shift 69 ;; 70 *) 71 ERROR=true 72 break 73 ;; 74 esac 75 ;; 76 esac 77 done 78 79 if ((param_count == 0)) || [ "$ERROR" == "true" ]; then 80 echo "Usage: $SCRIPT_NAME <system.img> [<output_system.img> [<new_security_patch_level> [<input_file_contexts.bin>]]] [-v <vendor_version>]" 81 exit 1 82 fi 83 84 # SPL must have YYYY-MM-DD format 85 if ((param_count >= 3)) && [[ ! ${NEW_SPL} =~ ^[0-9]{4}-(0[0-9]|1[012])-([012][0-9]|3[01])$ ]]; then 86 echo "<new_security_patch_level> must have YYYY-MM-DD format" 87 exit 1 88 fi 89 90 if [ "$VENDOR_VERSION" != "" ] && [[ ! ${VENDOR_VERSION} =~ ^(${SUPPORTED_VENDOR_VERSIONS// /\|})$ ]]; then 91 echo "Available vendor_version: $SUPPORTED_VENDOR_VERSIONS" 92 exit 1 93 fi 94 95 if [ "$VENDOR_VERSION" != "" ] && [ "$OUTPUT_SYSTEM_IMG" == "" ]; then 96 echo "<output_system.img> must be provided to set vendor version" 97 exit 1 98 fi 99 100 # First, check whether environment is set by lunch. 101 if [ -d "${ANDROID_HOST_OUT}" ]; then 102 BIN_PATH="${ANDROID_HOST_OUT}/bin" 103 fi 104 105 # If BIN_PATH is not a directory, or cannot find simg2img binary then 106 # try to get bin path from the current location. 107 if [ ! -d "${BIN_PATH}" ] || [ ! -f "${BIN_PATH}/simg2img" ]; then 108 BASE="${PWD##*/}" 109 if [ "${BASE}" == "testcases" ]; then 110 # If shell is executed through 'run', its base path is "testcases" 111 BIN_PATH="${PWD}/host/bin" 112 elif [ "${BASE}" == "gsi" ]; then 113 # If current path is "gsi" then we assume current path is 114 # testcases/host_controller/gsi 115 BIN_PATH="${PWD}/../../host/bin" 116 fi 117 fi 118 119 if [ ! -d "${BIN_PATH}" ] || [ ! -f "${BIN_PATH}/simg2img" ]; then 120 echo "Cannot find the required binaries. Need lunch; or run in a correct path" 121 exit 1 122 fi 123 124 MOUNT_POINT="${PWD}/temp_mnt" 125 SPL_PROPERTY_NAME="ro.build.version.security_patch" 126 RELEASE_VERSION_PROPERTY_NAME="ro.build.version.release" 127 VNDK_VERSION_PROPERTY="ro.vndk.version" 128 VNDK_VERSION_PROPERTY_OMR1="${VNDK_VERSION_PROPERTY}=27" 129 130 UNSPARSED_SYSTEM_IMG="${SYSTEM_IMG}.raw" 131 SYSTEM_IMG_MAGIC="$(xxd -g 4 -l 4 "$SYSTEM_IMG" | head -n1 | awk '{print $2}')" 132 if [ "$SYSTEM_IMG_MAGIC" = "3aff26ed" ]; then 133 echo "Unsparsing ${SYSTEM_IMG}..." 134 $BIN_PATH/simg2img "$SYSTEM_IMG" "$UNSPARSED_SYSTEM_IMG" 135 else 136 echo "Copying unsparse input system image ${SYSTEM_IMG}..." 137 cp "$SYSTEM_IMG" "$UNSPARSED_SYSTEM_IMG" 138 fi 139 140 IMG_SIZE=$(stat -c%s "$UNSPARSED_SYSTEM_IMG") 141 142 echo "Mounting..." 143 mkdir -p "$MOUNT_POINT" 144 sudo mount -t ext4 -o loop "$UNSPARSED_SYSTEM_IMG" "${MOUNT_POINT}/" 145 146 # check the property file path 147 BUILD_PROP_PATH_LIST=( 148 "/system/build.prop" # layout of A/B support 149 "/build.prop" # layout of non-A/B support 150 ) 151 BUILD_PROP_MOUNT_PATH="" 152 BUILD_PROP_PATH="" 153 PROP_DEFAULT_PATH="/system/etc/prop.default" 154 155 echo "Finding build.prop..." 156 for path in ${BUILD_PROP_PATH_LIST[@]}; do 157 if [ -f "${MOUNT_POINT}${path}" ]; then 158 BUILD_PROP_MOUNT_PATH="${MOUNT_POINT}${path}" 159 BUILD_PROP_PATH=${path} 160 echo " ${path}" 161 break 162 fi 163 done 164 165 if [ "$BUILD_PROP_MOUNT_PATH" != "" ]; then 166 if [ "$OUTPUT_SYSTEM_IMG" != "" ]; then 167 echo "Replacing..." 168 fi 169 CURRENT_SPL=`sudo sed -n -r "s/^${SPL_PROPERTY_NAME}=(.*)$/\1/p" ${BUILD_PROP_MOUNT_PATH}` 170 CURRENT_VERSION=`sudo sed -n -r "s/^${RELEASE_VERSION_PROPERTY_NAME}=(.*)$/\1/p" ${BUILD_PROP_MOUNT_PATH}` 171 echo " Current security patch level: ${CURRENT_SPL}" 172 echo " Current release version: ${CURRENT_VERSION}" 173 174 # Update SPL to <new_security_patch_level> 175 if [[ "$OUTPUT_SYSTEM_IMG" != "" && "$NEW_SPL" != "" ]]; then 176 if [[ "$CURRENT_SPL" == "" ]]; then 177 echo "ERROR: Cannot find ${SPL_PROPERTY_NAME} in ${BUILD_PROP_PATH}" 178 else 179 echo " New security patch level: ${NEW_SPL}" 180 seek=$(sudo grep --byte-offset "${SPL_PROPERTY_NAME}=" "${BUILD_PROP_MOUNT_PATH}" | cut -d':' -f 1) 181 seek=$(($seek + ${#SPL_PROPERTY_NAME} + 1)) # 1 is for '=' 182 echo "${NEW_SPL}" | sudo dd of="${BUILD_PROP_MOUNT_PATH}" seek="$seek" bs=1 count=10 conv=notrunc 183 fi 184 fi 185 186 # Update release version to <vendor_version> 187 if [[ "$OUTPUT_SYSTEM_IMG" != "" && "$VENDOR_VERSION" != "" ]]; then 188 if [[ "$CURRENT_VERSION" == "" ]]; then 189 echo "ERROR: Cannot find ${RELEASE_VERSION_PROPERTY_NAME} in ${BUILD_PROP_PATH}" 190 else 191 echo " New release version for vendor.img: ${VENDOR_VERSION}" 192 sudo sed -i -e "s/^${RELEASE_VERSION_PROPERTY_NAME}=.*$/${RELEASE_VERSION_PROPERTY_NAME}=${VENDOR_VERSION}/" ${BUILD_PROP_MOUNT_PATH} 193 fi 194 195 if [[ "$VENDOR_VERSION" == "8.1.0" ]]; then 196 # add ro.vndk.version for O-MR1 197 if [ -f "${MOUNT_POINT}${PROP_DEFAULT_PATH}" ]; then 198 CURRENT_VNDK_VERSION=`sudo sed -n -r "s/^${VNDK_VERSION_PROPERTY}=(.*)$/\1/p" ${MOUNT_POINT}${PROP_DEFAULT_PATH}` 199 if [[ "$CURRENT_VNDK_VERSION" != "" ]]; then 200 echo "WARNING: ${VNDK_VERSION_PROPERTY} is already set to ${CURRENT_VNDK_VERSION} in ${PROP_DEFAULT_PATH}" 201 else 202 echo " Add \"${VNDK_VERSION_PROPERTY_OMR1}\" to ${PROP_DEFAULT_PATH} for O-MR1 vendor image." 203 sudo sed -i -e "\$a\#\n\# FOR O-MR1 DEVICES\n\#\n${VNDK_VERSION_PROPERTY_OMR1}" ${MOUNT_POINT}${PROP_DEFAULT_PATH} 204 fi 205 else 206 echo "ERROR: Cannot find $(basename ${PROP_DEFAULT_PATH})" 207 fi 208 fi 209 fi 210 else 211 echo "ERROR: Cannot find build.prop." 212 fi 213 214 if [ "$OUTPUT_SYSTEM_IMG" != "" ]; then 215 if [ "$FILE_CONTEXTS_BIN" != "" ]; then 216 echo "Writing ${OUTPUT_SYSTEM_IMG}..." 217 218 (cd $ANDROID_BUILD_TOP 219 if [[ "$(whereis mkuserimg_mke2fs.sh | wc -w)" < 2 ]]; then 220 make mkuserimg_mke2fs.sh -j 221 fi 222 NON_AB=$(expr "$BUILD_PROP_PATH" == "/build.prop") 223 if [ $NON_AB -eq 1 ]; then 224 sudo /bin/bash -c "PATH=out/host/linux-x86/bin/:\$PATH mkuserimg_mke2fs.sh -s ${MOUNT_POINT} $OUTPUT_SYSTEM_IMG ext4 system $IMG_SIZE -D ${MOUNT_POINT} -L system $FILE_CONTEXTS_BIN" 225 else 226 sudo /bin/bash -c "PATH=out/host/linux-x86/bin/:\$PATH mkuserimg_mke2fs.sh -s ${MOUNT_POINT} $OUTPUT_SYSTEM_IMG ext4 / $IMG_SIZE -D ${MOUNT_POINT}/system -L / $FILE_CONTEXTS_BIN" 227 fi) 228 229 unmount 230 else 231 unmount 232 233 echo "Writing ${OUTPUT_SYSTEM_IMG}..." 234 $BIN_PATH/img2simg "$UNSPARSED_SYSTEM_IMG" "$OUTPUT_SYSTEM_IMG" 235 fi 236 else 237 unmount 238 fi 239 240 echo "Done." 241