Home | History | Annotate | Download | only in gsi
      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