1# 2# Copyright (C) 2018 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the 'License'); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an 'AS IS' BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import datetime 18import logging 19import os 20import shutil 21import tempfile 22import zipfile 23 24from host_controller import common 25from host_controller.command_processor import base_command_processor 26from host_controller.utils.gsi import img_utils 27 28from vts.utils.python.common import cmd_utils 29 30 31class CommandGsispl(base_command_processor.BaseCommandProcessor): 32 """Command processor for gsispl command. 33 34 Attributes: 35 arg_parser: ConsoleArgumentParser object, argument parser. 36 console: cmd.Cmd console object. 37 command: string, command name which this processor will handle. 38 command_detail: string, detailed explanation for the command. 39 """ 40 41 command = "gsispl" 42 command_detail = "Changes security patch level on a selected GSI file." 43 44 # @Override 45 def SetUp(self): 46 """Initializes the parser for device command.""" 47 self.arg_parser.add_argument( 48 "--gsi", 49 help="Path to GSI image to change security patch level. " 50 "If path is not given, the most recently fetched system.img " 51 "kept in device_image_info dictionary is used and then " 52 "device_image_info will be updated with the new GSI file.") 53 self.arg_parser.add_argument( 54 "--version", help="New version ID. It should be YYYY-mm-dd format") 55 self.arg_parser.add_argument( 56 "--version_from_path", 57 help="Path to vendor provided image file to retrieve SPL version. " 58 "If just a file name is given, the most recently fetched .img " 59 "file will be used.") 60 self.arg_parser.add_argument( 61 "--vendor_version", 62 help="The version of vendor.img that will be used (e.g., 8.1.0).") 63 64 # @Override 65 def Run(self, arg_line): 66 """Changes security patch level on a selected GSI file.""" 67 args = self.arg_parser.ParseLine(arg_line) 68 if args.gsi: 69 if os.path.isfile(args.gsi): 70 gsi_path = args.gsi 71 else: 72 logging.error("Cannot find system image in given path") 73 return 74 elif "system.img" in self.console.device_image_info: 75 gsi_path = self.console.device_image_info["system.img"] 76 else: 77 logging.error("Cannot find system image.") 78 return False 79 80 if args.version: 81 try: 82 version_date = datetime.datetime.strptime( 83 args.version, "%Y-%m-%d") 84 version = "{:04d}-{:02d}-{:02d}".format( 85 version_date.year, version_date.month, version_date.day) 86 except ValueError as e: 87 logging.error("version ID should be YYYY-mm-dd format.") 88 return 89 elif args.version_from_path: 90 dest_path = None 91 if os.path.isabs(args.version_from_path) and os.path.exists( 92 args.version_from_path): 93 img_path = args.version_from_path 94 elif args.version_from_path in self.console.device_image_info: 95 img_path = self.console.device_image_info[ 96 args.version_from_path] 97 elif (args.version_from_path == "boot.img" 98 and "full-zipfile" in self.console.device_image_info): 99 tempdir_base = os.path.join(os.getcwd(), "tmp") 100 if not os.path.exists(tempdir_base): 101 os.mkdir(tempdir_base) 102 dest_path = tempfile.mkdtemp(dir=tempdir_base) 103 104 with zipfile.ZipFile( 105 self.console.device_image_info["full-zipfile"], 106 'r') as zip_ref: 107 zip_ref.extractall(dest_path) 108 img_path = os.path.join(dest_path, "boot.img") 109 if not os.path.exists(img_path): 110 logging.error("No %s file in device img .zip.", 111 args.version_from_path) 112 shutil.rmtree(dest_path) 113 return 114 else: 115 logging.error("Cannot find %s file.", args.version_from_path) 116 return False 117 118 version_dict = img_utils.GetSPLVersionFromBootImg(img_path) 119 if dest_path: 120 shutil.rmtree(dest_path) 121 if "year" in version_dict and "month" in version_dict: 122 version = "{:04d}-{:02d}-{:02d}".format( 123 version_dict["year"], version_dict["month"], 124 common._SPL_DEFAULT_DAY) 125 else: 126 logging.error("Failed to fetch SPL version from %s file.", 127 img_path) 128 return False 129 else: 130 logging.error("version ID or path of .img file must be given.") 131 return False 132 133 output_path = os.path.join( 134 os.path.dirname(os.path.abspath(gsi_path)), 135 "system-{}.img".format(version)) 136 command = "{} {} {} {}".format( 137 os.path.join(os.getcwd(), "..", "bin", 138 "change_security_patch_ver.sh"), gsi_path, 139 output_path, version) 140 if args.vendor_version: 141 command = command + " -v " + args.vendor_version 142 if self.console.password.value: 143 command = "echo {} | sudo -S {}".format( 144 self.console.password.value, command) 145 stdout, stderr, err_code = cmd_utils.ExecuteOneShellCommand(command) 146 if err_code is 0: 147 if not args.gsi: 148 logging.info( 149 "system.img path is updated to : {}".format(output_path)) 150 self.console.device_image_info["system.img"] = output_path 151 else: 152 logging.error("gsispl error: {} {}".format(stdout, stderr)) 153 return False 154