140681896Sopenharmony_ci#!/usr/bin/env python3 240681896Sopenharmony_ci# -*- coding: utf-8 -*- 340681896Sopenharmony_ci 440681896Sopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd. 540681896Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 640681896Sopenharmony_ci# you may not use this file except in compliance with the License. 740681896Sopenharmony_ci# You may obtain a copy of the License at 840681896Sopenharmony_ci# 940681896Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 1040681896Sopenharmony_ci# 1140681896Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 1240681896Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 1340681896Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1440681896Sopenharmony_ci# See the License for the specific language governing permissions and 1540681896Sopenharmony_ci# limitations under the License. 1640681896Sopenharmony_ci""" 1740681896Sopenharmony_ciDescription : Defining constants, common interface 1840681896Sopenharmony_ci""" 1940681896Sopenharmony_ciimport argparse 2040681896Sopenharmony_ciimport json 2140681896Sopenharmony_ciimport os 2240681896Sopenharmony_ciimport shutil 2340681896Sopenharmony_ciimport tempfile 2440681896Sopenharmony_cifrom collections import OrderedDict 2540681896Sopenharmony_ciimport xmltodict 2640681896Sopenharmony_ciimport zipfile 2740681896Sopenharmony_ci 2840681896Sopenharmony_cifrom cryptography.hazmat.primitives import hashes 2940681896Sopenharmony_cifrom log_exception import UPDATE_LOGGER 3040681896Sopenharmony_cifrom build_pkcs7 import sign_ota_package 3140681896Sopenharmony_cifrom copy import copy 3240681896Sopenharmony_cifrom ctypes import cdll 3340681896Sopenharmony_ci 3440681896Sopenharmony_cioperation_path = os.path.dirname(os.path.realpath(__file__)) 3540681896Sopenharmony_ciPRODUCT = 'hi3516' 3640681896Sopenharmony_ciBUILD_TOOLS_FILE_NAME = 'build_tools.zip' 3740681896Sopenharmony_ciUPDATE_BIN_FILE_NAME = "update.bin" 3840681896Sopenharmony_ciUPDATE_EXE_FILE_NAME = "updater_binary" 3940681896Sopenharmony_ci 4040681896Sopenharmony_ciSCRIPT_KEY_LIST = ['prelude', 'verse', 'refrain', 'ending'] 4140681896Sopenharmony_ciTOTAL_SCRIPT_FILE_NAME = "loadScript.us" 4240681896Sopenharmony_ciREGISTER_SCRIPT_FILE_NAME = "registerCmd.us" 4340681896Sopenharmony_ciSCRIPT_FILE_NAME = '-script.us' 4440681896Sopenharmony_ci 4540681896Sopenharmony_ciUPDATER_CONFIG = "updater_config" 4640681896Sopenharmony_ciXML_FILE_PATH = "updater_specified_config.xml" 4740681896Sopenharmony_ciSO_PATH = os.path.join(operation_path, 'lib/libpackage.so') 4840681896Sopenharmony_ciSO_PATH_L1 = os.path.join(operation_path, 'lib/libpackageL1.so') 4940681896Sopenharmony_ciDIFF_EXE_PATH = os.path.join(operation_path, 'lib/diff') 5040681896Sopenharmony_ciE2FSDROID_PATH = os.path.join(operation_path, 'lib/e2fsdroid') 5140681896Sopenharmony_ciMISC_INFO_PATH = "misc_info.txt" 5240681896Sopenharmony_ciVERSION_MBN_PATH = "VERSION.mbn" 5340681896Sopenharmony_ciBOARD_LIST_PATH = "BOARD.list" 5440681896Sopenharmony_ciEXTEND_COMPONENT_LIST = ["version_list", "board_list"] 5540681896Sopenharmony_ciEXTEND_OPTIONAL_COMPONENT_LIST = ["partitions_file"] 5640681896Sopenharmony_ciPARTITION_FILE = "partitions_file" 5740681896Sopenharmony_ciIGNORED_PARTITION_LIST = ['fastboot', 'boot', 'kernel', 'misc', 5840681896Sopenharmony_ci 'updater', 'userdata'] 5940681896Sopenharmony_ci 6040681896Sopenharmony_ciHASH_ALGORITHM_DICT = {'sha256': hashes.SHA256, 'sha384': hashes.SHA384} 6140681896Sopenharmony_ciLINUX_HASH_ALGORITHM_DICT = {'sha256': 'sha256sum', 'sha384': 'sha384sum'} 6240681896Sopenharmony_ciHASH_CONTENT_LEN_DICT = {'sha256': 64, 'sha384': 96} 6340681896Sopenharmony_ci 6440681896Sopenharmony_ciCOMPONENT_INFO_INNIT = ['', '000', '00', '0', '0o00'] 6540681896Sopenharmony_ci 6640681896Sopenharmony_ciON_SERVER = "ON_SERVER" 6740681896Sopenharmony_ci 6840681896Sopenharmony_ciEXTEND_VALUE = 512 6940681896Sopenharmony_ci 7040681896Sopenharmony_ciFILE_MAP_ZERO_KEY = "__ZERO" 7140681896Sopenharmony_ciFILE_MAP_NONZERO_KEY = "__NONZERO" 7240681896Sopenharmony_ciFILE_MAP_COPY_KEY = "__COPY" 7340681896Sopenharmony_ci 7440681896Sopenharmony_ciMAX_BLOCKS_PER_GROUP = BLOCK_LIMIT = 1024 7540681896Sopenharmony_ciPER_BLOCK_SIZE = 4096 7640681896Sopenharmony_ci 7740681896Sopenharmony_ciVERSE_SCRIPT_EVENT = 0 7840681896Sopenharmony_ciINC_IMAGE_EVENT = 1 7940681896Sopenharmony_ciSIGN_PACKAGE_EVENT = 2 8040681896Sopenharmony_ciCHECK_BINARY_EVENT = 3 8140681896Sopenharmony_ciCONFIG_EVENT = 4 8240681896Sopenharmony_ciEXTEND_PATH_EVENT = 5 8340681896Sopenharmony_ciZIP_EVENT = 6 8440681896Sopenharmony_ciGENERATE_SIGNED_DATA_EVENT = 7 # sign build tools files to get hash_signed_data 8540681896Sopenharmony_ciPARTITION_CHANGE_EVENT = 8 8640681896Sopenharmony_ciDECOUPLED_EVENT = 9 8740681896Sopenharmony_ci 8840681896Sopenharmony_ci# Image file can not support update. 8940681896Sopenharmony_ciFORBIDEN_UPDATE_IMAGE_SET = {"ptable"} 9040681896Sopenharmony_ci 9140681896Sopenharmony_ci# 1000000: max number of function recursion depth 9240681896Sopenharmony_ciMAXIMUM_RECURSION_DEPTH = 1000000 9340681896Sopenharmony_ci 9440681896Sopenharmony_ci 9540681896Sopenharmony_cidef singleton(cls): 9640681896Sopenharmony_ci _instance = {} 9740681896Sopenharmony_ci 9840681896Sopenharmony_ci def _singleton(*args, **kargs): 9940681896Sopenharmony_ci if cls not in _instance: 10040681896Sopenharmony_ci _instance[cls] = cls(*args, **kargs) 10140681896Sopenharmony_ci return _instance[cls] 10240681896Sopenharmony_ci 10340681896Sopenharmony_ci return _singleton 10440681896Sopenharmony_ci 10540681896Sopenharmony_ci 10640681896Sopenharmony_ciclass ExtInit: 10740681896Sopenharmony_ci """ 10840681896Sopenharmony_ci Init event for ext 10940681896Sopenharmony_ci """ 11040681896Sopenharmony_ci 11140681896Sopenharmony_ci def __init__(self): 11240681896Sopenharmony_ci self.funs = [] 11340681896Sopenharmony_ci 11440681896Sopenharmony_ci def reg_event(self, evevt_id, funs): 11540681896Sopenharmony_ci self.funs.append([evevt_id, funs]) 11640681896Sopenharmony_ci UPDATE_LOGGER.print_log( 11740681896Sopenharmony_ci 'register event %s: %s' % (evevt_id, funs.__name__)) 11840681896Sopenharmony_ci 11940681896Sopenharmony_ci def invoke_event(self, evevt_id): 12040681896Sopenharmony_ci UPDATE_LOGGER.print_log(self.funs) 12140681896Sopenharmony_ci for event in self.funs: 12240681896Sopenharmony_ci funs = event[1] 12340681896Sopenharmony_ci if event[0] == evevt_id and funs is not None: 12440681896Sopenharmony_ci UPDATE_LOGGER.print_log( 12540681896Sopenharmony_ci 'invoke event %s: %s' % (evevt_id, funs.__name__)) 12640681896Sopenharmony_ci return funs 12740681896Sopenharmony_ci return False 12840681896Sopenharmony_ci 12940681896Sopenharmony_ci 13040681896Sopenharmony_ciclass BaseOptionsManager: 13140681896Sopenharmony_ci def __init__(self): 13240681896Sopenharmony_ci # Entry parameters 13340681896Sopenharmony_ci self.source_package = None 13440681896Sopenharmony_ci self.target_package = None 13540681896Sopenharmony_ci self.update_package = None 13640681896Sopenharmony_ci self.unpack_package_path = None 13740681896Sopenharmony_ci self.no_zip = False 13840681896Sopenharmony_ci self.partition_file = None 13940681896Sopenharmony_ci self.signing_algorithm = None 14040681896Sopenharmony_ci self.hash_algorithm = None 14140681896Sopenharmony_ci self.private_key = None 14240681896Sopenharmony_ci self.not_l2 = False 14340681896Sopenharmony_ci self.signing_length = 256 14440681896Sopenharmony_ci self.xml_path = None 14540681896Sopenharmony_ci self.sd_card = False 14640681896Sopenharmony_ci 14740681896Sopenharmony_ci self.make_dir_path = None 14840681896Sopenharmony_ci 14940681896Sopenharmony_ci 15040681896Sopenharmony_ci@singleton 15140681896Sopenharmony_ciclass OptionsManager(BaseOptionsManager): 15240681896Sopenharmony_ci """ 15340681896Sopenharmony_ci Options management class 15440681896Sopenharmony_ci """ 15540681896Sopenharmony_ci 15640681896Sopenharmony_ci def __init__(self): 15740681896Sopenharmony_ci super().__init__() 15840681896Sopenharmony_ci 15940681896Sopenharmony_ci self.init = ExtInit() 16040681896Sopenharmony_ci self.parser = argparse.ArgumentParser() 16140681896Sopenharmony_ci 16240681896Sopenharmony_ci # Own parameters 16340681896Sopenharmony_ci self.product = None 16440681896Sopenharmony_ci 16540681896Sopenharmony_ci 16640681896Sopenharmony_ci # Parsed package parameters 16740681896Sopenharmony_ci self.target_package_dir = None 16840681896Sopenharmony_ci self.target_package_config_dir = None 16940681896Sopenharmony_ci self.target_package_temp_obj = None 17040681896Sopenharmony_ci self.misc_info_dict = {} 17140681896Sopenharmony_ci self.version_mbn_file_path = None 17240681896Sopenharmony_ci self.version_mbn_content = None 17340681896Sopenharmony_ci self.board_list_file_path = None 17440681896Sopenharmony_ci self.board_list_content = None 17540681896Sopenharmony_ci 17640681896Sopenharmony_ci self.source_package_dir = None 17740681896Sopenharmony_ci self.source_package_temp_obj = None 17840681896Sopenharmony_ci 17940681896Sopenharmony_ci # XML parsing parameters 18040681896Sopenharmony_ci self.head_info_list = [] 18140681896Sopenharmony_ci self.component_info_dict = {} 18240681896Sopenharmony_ci self.full_img_list = [] 18340681896Sopenharmony_ci self.full_img_name_list = [] 18440681896Sopenharmony_ci self.incremental_img_list = [] 18540681896Sopenharmony_ci self.incremental_img_name_list = [] 18640681896Sopenharmony_ci self.target_package_version = None 18740681896Sopenharmony_ci self.source_package_version = None 18840681896Sopenharmony_ci self.full_image_path_list = [] 18940681896Sopenharmony_ci 19040681896Sopenharmony_ci self.partition_file_obj = None 19140681896Sopenharmony_ci 19240681896Sopenharmony_ci # Full processing parameters 19340681896Sopenharmony_ci self.full_image_content_len_list = [] 19440681896Sopenharmony_ci self.full_image_file_obj_list = [] 19540681896Sopenharmony_ci 19640681896Sopenharmony_ci # Incremental processing parameters 19740681896Sopenharmony_ci self.incremental_content_len_list = [] 19840681896Sopenharmony_ci self.incremental_image_file_obj_dict = {} 19940681896Sopenharmony_ci self.incremental_block_file_obj_dict = {} 20040681896Sopenharmony_ci self.incremental_temp_file_obj_list = [] 20140681896Sopenharmony_ci self.max_stash_size = 0 20240681896Sopenharmony_ci 20340681896Sopenharmony_ci # Script parameters 20440681896Sopenharmony_ci self.opera_script_file_name_dict = {} 20540681896Sopenharmony_ci for each in SCRIPT_KEY_LIST: 20640681896Sopenharmony_ci self.opera_script_file_name_dict[each] = [] 20740681896Sopenharmony_ci self.total_script_file_obj = None 20840681896Sopenharmony_ci 20940681896Sopenharmony_ci self.register_script_file_obj = None 21040681896Sopenharmony_ci 21140681896Sopenharmony_ci # Update package parameters 21240681896Sopenharmony_ci self.update_bin_obj = None 21340681896Sopenharmony_ci self.build_tools_zip_obj = None 21440681896Sopenharmony_ci self.update_package_file_path = None 21540681896Sopenharmony_ci self.signed_package = None 21640681896Sopenharmony_ci 21740681896Sopenharmony_ci 21840681896Sopenharmony_ciOPTIONS_MANAGER = OptionsManager() 21940681896Sopenharmony_ci 22040681896Sopenharmony_ci 22140681896Sopenharmony_cidef unzip_package(package_path, origin='target'): 22240681896Sopenharmony_ci """ 22340681896Sopenharmony_ci Decompress the zip package. 22440681896Sopenharmony_ci :param package_path: zip package path 22540681896Sopenharmony_ci :param origin: package origin, which indicates 22640681896Sopenharmony_ci whether the zip package is a source package or target package 22740681896Sopenharmony_ci :return: Temporary directory (tmp_dir) and zip_data package; 22840681896Sopenharmony_ci false if an exception occurs. 22940681896Sopenharmony_ci """ 23040681896Sopenharmony_ci try: 23140681896Sopenharmony_ci tmp_dir_obj = tempfile.TemporaryDirectory(prefix="%sfiles-" % origin) 23240681896Sopenharmony_ci tmp_dir = tmp_dir_obj.name 23340681896Sopenharmony_ci 23440681896Sopenharmony_ci zf_obj = zipfile.ZipFile(package_path) 23540681896Sopenharmony_ci for name in zf_obj.namelist(): 23640681896Sopenharmony_ci if name.endswith('/'): 23740681896Sopenharmony_ci os.mkdir(os.path.join(tmp_dir, name)) 23840681896Sopenharmony_ci else: 23940681896Sopenharmony_ci ext_filename = os.path.join( 24040681896Sopenharmony_ci tmp_dir, name) 24140681896Sopenharmony_ci fd = os.open(ext_filename, os.O_RDWR | os.O_CREAT, 0o755) 24240681896Sopenharmony_ci with os.fdopen(fd, "wb") as f_w: 24340681896Sopenharmony_ci f_w.write(zf_obj.read(name)) 24440681896Sopenharmony_ci except OSError: 24540681896Sopenharmony_ci UPDATE_LOGGER.print_log( 24640681896Sopenharmony_ci "Unzip package failed! path: %s" % package_path, 24740681896Sopenharmony_ci log_type=UPDATE_LOGGER.ERROR_LOG) 24840681896Sopenharmony_ci return False, False 24940681896Sopenharmony_ci tmp_dir_list = os.listdir(tmp_dir) 25040681896Sopenharmony_ci if len(tmp_dir_list) == 1: 25140681896Sopenharmony_ci unzip_dir = os.path.join(tmp_dir, tmp_dir_list[0]) 25240681896Sopenharmony_ci if UPDATER_CONFIG not in \ 25340681896Sopenharmony_ci os.listdir(unzip_dir): 25440681896Sopenharmony_ci UPDATE_LOGGER.print_log( 25540681896Sopenharmony_ci 'Unsupported zip package structure!', UPDATE_LOGGER.ERROR_LOG) 25640681896Sopenharmony_ci return False, False 25740681896Sopenharmony_ci elif UPDATER_CONFIG in tmp_dir_list: 25840681896Sopenharmony_ci unzip_dir = tmp_dir 25940681896Sopenharmony_ci else: 26040681896Sopenharmony_ci UPDATE_LOGGER.print_log( 26140681896Sopenharmony_ci 'Unsupported zip package structure!', UPDATE_LOGGER.ERROR_LOG) 26240681896Sopenharmony_ci return False, False 26340681896Sopenharmony_ci UPDATE_LOGGER.print_log( 26440681896Sopenharmony_ci '%s package unzip complete! path: %s' % (origin.title(), unzip_dir)) 26540681896Sopenharmony_ci 26640681896Sopenharmony_ci return tmp_dir_obj, unzip_dir 26740681896Sopenharmony_ci 26840681896Sopenharmony_ci 26940681896Sopenharmony_cidef split_img_name(image_path): 27040681896Sopenharmony_ci """ 27140681896Sopenharmony_ci Split the image name by image path 27240681896Sopenharmony_ci :return image name 27340681896Sopenharmony_ci """ 27440681896Sopenharmony_ci tmp_path = image_path 27540681896Sopenharmony_ci str_list = tmp_path.split("/") 27640681896Sopenharmony_ci 27740681896Sopenharmony_ci return str_list[-1] 27840681896Sopenharmony_ci 27940681896Sopenharmony_ci 28040681896Sopenharmony_cidef get_update_config_softversion(mbn_dir, head_info_dict): 28140681896Sopenharmony_ci soft_version_file = head_info_dict.get('softVersionFile') 28240681896Sopenharmony_ci if soft_version_file is not None: 28340681896Sopenharmony_ci mbn_path = os.path.join(mbn_dir, soft_version_file) 28440681896Sopenharmony_ci if os.path.exists(mbn_path): 28540681896Sopenharmony_ci with open(mbn_path, 'r') as mbn_file: 28640681896Sopenharmony_ci head_info_dict['info']["@softVersion"] = mbn_file.read() 28740681896Sopenharmony_ci 28840681896Sopenharmony_ci 28940681896Sopenharmony_cidef parse_update_config(xml_path): 29040681896Sopenharmony_ci """ 29140681896Sopenharmony_ci Parse the XML configuration file. 29240681896Sopenharmony_ci :param xml_path: XML configuration file path 29340681896Sopenharmony_ci :return head_info_dict: header information dict of the update package 29440681896Sopenharmony_ci component_info_dict: component information dict 29540681896Sopenharmony_ci full_img_list: full image list 29640681896Sopenharmony_ci incremental_img_list: incremental image list 29740681896Sopenharmony_ci """ 29840681896Sopenharmony_ci if os.path.exists(xml_path): 29940681896Sopenharmony_ci with open(xml_path, 'r') as xml_file: 30040681896Sopenharmony_ci xml_str = xml_file.read() 30140681896Sopenharmony_ci else: 30240681896Sopenharmony_ci UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % xml_path, UPDATE_LOGGER.ERROR_LOG) 30340681896Sopenharmony_ci ret_params = [False, False, False, False, False, False, False] 30440681896Sopenharmony_ci return ret_params 30540681896Sopenharmony_ci xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 30640681896Sopenharmony_ci package_dict = xml_content_dict.get('package', {}) 30740681896Sopenharmony_ci get_update_config_softversion(OPTIONS_MANAGER.target_package_dir, package_dict.get('head', {})) 30840681896Sopenharmony_ci head_dict = package_dict.get('head', {}).get('info') 30940681896Sopenharmony_ci package_version = head_dict.get("@softVersion") 31040681896Sopenharmony_ci # component 31140681896Sopenharmony_ci component_info = package_dict.get('group', {}).get('component') 31240681896Sopenharmony_ci head_list = list(head_dict.values()) 31340681896Sopenharmony_ci head_list.pop() 31440681896Sopenharmony_ci whole_list = [] 31540681896Sopenharmony_ci difference_list = [] 31640681896Sopenharmony_ci comp_dict = {} 31740681896Sopenharmony_ci full_image_path_list = [] 31840681896Sopenharmony_ci 31940681896Sopenharmony_ci if not OPTIONS_MANAGER.not_l2: 32040681896Sopenharmony_ci expand_component(comp_dict) 32140681896Sopenharmony_ci if isinstance(component_info, OrderedDict) or isinstance(component_info, dict): 32240681896Sopenharmony_ci component_info = [component_info] 32340681896Sopenharmony_ci if component_info is None: 32440681896Sopenharmony_ci ret_params = [[], {}, [], [], '', [], False] 32540681896Sopenharmony_ci return ret_params 32640681896Sopenharmony_ci for component in component_info: 32740681896Sopenharmony_ci if component['@compAddr'] == 'userdata' and not OPTIONS_MANAGER.sd_card: 32840681896Sopenharmony_ci continue 32940681896Sopenharmony_ci component_list = list(component.values()) 33040681896Sopenharmony_ci component_list.pop() 33140681896Sopenharmony_ci comp_dict[component['@compAddr']] = component_list 33240681896Sopenharmony_ci 33340681896Sopenharmony_ci if component['@compAddr'] in (whole_list + difference_list): 33440681896Sopenharmony_ci UPDATE_LOGGER.print_log("This component %s repeats!" % component['@compAddr'], UPDATE_LOGGER.ERROR_LOG) 33540681896Sopenharmony_ci ret_params = [False, False, False, False, False, False, False] 33640681896Sopenharmony_ci return ret_params 33740681896Sopenharmony_ci 33840681896Sopenharmony_ci if component['@compType'] == '0': 33940681896Sopenharmony_ci whole_list.append(component['@compAddr']) 34040681896Sopenharmony_ci OPTIONS_MANAGER.full_img_name_list.append(split_img_name(component['#text'])) 34140681896Sopenharmony_ci tem_path = os.path.join(OPTIONS_MANAGER.target_package_dir, component.get("#text", None)) 34240681896Sopenharmony_ci full_image_path_list.append(tem_path) 34340681896Sopenharmony_ci comp_dict[component['@compAddr']] = component_list 34440681896Sopenharmony_ci elif component['@compType'] == '1': 34540681896Sopenharmony_ci difference_list.append(component['@compAddr']) 34640681896Sopenharmony_ci OPTIONS_MANAGER.incremental_img_name_list.append(split_img_name(component['#text'])) 34740681896Sopenharmony_ci 34840681896Sopenharmony_ci ret_params = [head_list, comp_dict, whole_list, difference_list, package_version, full_image_path_list] 34940681896Sopenharmony_ci return ret_params 35040681896Sopenharmony_ci 35140681896Sopenharmony_ci 35240681896Sopenharmony_cidef partitions_conversion(data): 35340681896Sopenharmony_ci """ 35440681896Sopenharmony_ci Convert the start or length data in the partition table through 35540681896Sopenharmony_ci multiply 1024 * 1024 and return the data. 35640681896Sopenharmony_ci :param data: start or length data 35740681896Sopenharmony_ci :return : 35840681896Sopenharmony_ci """ 35940681896Sopenharmony_ci if data == '0': 36040681896Sopenharmony_ci return 0 36140681896Sopenharmony_ci elif data.endswith('M'): 36240681896Sopenharmony_ci return int(data[0:-1]) * 1024 * 1024 // 512 36340681896Sopenharmony_ci else: 36440681896Sopenharmony_ci return False 36540681896Sopenharmony_ci 36640681896Sopenharmony_ci 36740681896Sopenharmony_cidef parse_partition_file_xml(xml_path): 36840681896Sopenharmony_ci """ 36940681896Sopenharmony_ci Parse the XML configuration file. 37040681896Sopenharmony_ci :param xml_path: XML configuration file path 37140681896Sopenharmony_ci :return part_json: partition table information in JSON format 37240681896Sopenharmony_ci """ 37340681896Sopenharmony_ci if os.path.exists(xml_path): 37440681896Sopenharmony_ci with open(xml_path, 'r') as xml_file: 37540681896Sopenharmony_ci xml_str = xml_file.read() 37640681896Sopenharmony_ci else: 37740681896Sopenharmony_ci UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % 37840681896Sopenharmony_ci xml_path, UPDATE_LOGGER.ERROR_LOG) 37940681896Sopenharmony_ci return False, False, False 38040681896Sopenharmony_ci partitions_list = [] 38140681896Sopenharmony_ci partitions_file_path_list = [] 38240681896Sopenharmony_ci xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 38340681896Sopenharmony_ci part_list = xml_content_dict['Partition_Info']['Part'] 38440681896Sopenharmony_ci new_part_list = [] 38540681896Sopenharmony_ci for i, part in enumerate(part_list): 38640681896Sopenharmony_ci start_value = partitions_conversion(part.get('@Start')) 38740681896Sopenharmony_ci length_value = partitions_conversion(part.get('@Length')) 38840681896Sopenharmony_ci if start_value is False or length_value is False: 38940681896Sopenharmony_ci UPDATE_LOGGER.print_log( 39040681896Sopenharmony_ci "Partition file parsing failed! part_name: %s, xml_path: %s" % 39140681896Sopenharmony_ci (part.get('@PartitionName'), xml_path), 39240681896Sopenharmony_ci UPDATE_LOGGER.ERROR_LOG) 39340681896Sopenharmony_ci return False, False, False 39440681896Sopenharmony_ci 39540681896Sopenharmony_ci if part.get('@PartitionName') not in IGNORED_PARTITION_LIST: 39640681896Sopenharmony_ci partitions_list.append(part.get('@PartitionName')) 39740681896Sopenharmony_ci partitions_file_path_list.append( 39840681896Sopenharmony_ci os.path.join(OPTIONS_MANAGER.target_package_dir, 39940681896Sopenharmony_ci "%s.img" % part.get('@PartitionName'))) 40040681896Sopenharmony_ci part_dict = {'start': start_value, 40140681896Sopenharmony_ci 'length': length_value, 40240681896Sopenharmony_ci 'partName': part.get('@PartitionName'), 40340681896Sopenharmony_ci 'fsType': part.get('@FlashType')} 40440681896Sopenharmony_ci new_part_list.append(part_dict) 40540681896Sopenharmony_ci part_json = json.dumps(new_part_list) 40640681896Sopenharmony_ci part_json = '{"Partition": %s}' % part_json 40740681896Sopenharmony_ci file_obj = tempfile.NamedTemporaryFile( 40840681896Sopenharmony_ci dir=OPTIONS_MANAGER.target_package_dir, prefix="partition_file-", mode='wb') 40940681896Sopenharmony_ci file_obj.write(part_json.encode()) 41040681896Sopenharmony_ci file_obj.seek(0) 41140681896Sopenharmony_ci return file_obj, partitions_list, partitions_file_path_list 41240681896Sopenharmony_ci 41340681896Sopenharmony_ci 41440681896Sopenharmony_cidef get_extend_path_list(): 41540681896Sopenharmony_ci get_config_list = OPTIONS_MANAGER.init.invoke_event(CONFIG_EVENT) 41640681896Sopenharmony_ci if get_config_list: 41740681896Sopenharmony_ci return get_config_list() 41840681896Sopenharmony_ci else: 41940681896Sopenharmony_ci return EXTEND_COMPONENT_LIST 42040681896Sopenharmony_ci 42140681896Sopenharmony_ci 42240681896Sopenharmony_cidef expand_component(component_dict): 42340681896Sopenharmony_ci """ 42440681896Sopenharmony_ci Append components such as VERSION.mbn and board list. 42540681896Sopenharmony_ci :param component_dict: component information dict 42640681896Sopenharmony_ci :return: 42740681896Sopenharmony_ci """ 42840681896Sopenharmony_ci extend_path_list = get_extend_path_list() 42940681896Sopenharmony_ci if OPTIONS_MANAGER.partition_file is not None: 43040681896Sopenharmony_ci extend_component_list = \ 43140681896Sopenharmony_ci extend_path_list + EXTEND_OPTIONAL_COMPONENT_LIST 43240681896Sopenharmony_ci else: 43340681896Sopenharmony_ci extend_component_list = extend_path_list 43440681896Sopenharmony_ci for each in extend_component_list: 43540681896Sopenharmony_ci tmp_info_list = copy(COMPONENT_INFO_INNIT) 43640681896Sopenharmony_ci tmp_info_list[0] = each 43740681896Sopenharmony_ci component_dict[each] = tmp_info_list 43840681896Sopenharmony_ci 43940681896Sopenharmony_ci 44040681896Sopenharmony_cidef clear_options(): 44140681896Sopenharmony_ci """ 44240681896Sopenharmony_ci Clear OPTIONS_MANAGER. 44340681896Sopenharmony_ci """ 44440681896Sopenharmony_ci OPTIONS_MANAGER.product = None 44540681896Sopenharmony_ci 44640681896Sopenharmony_ci # Entry parameters 44740681896Sopenharmony_ci OPTIONS_MANAGER.source_package = None 44840681896Sopenharmony_ci OPTIONS_MANAGER.target_package = None 44940681896Sopenharmony_ci OPTIONS_MANAGER.update_package = None 45040681896Sopenharmony_ci OPTIONS_MANAGER.no_zip = False 45140681896Sopenharmony_ci OPTIONS_MANAGER.partition_file = None 45240681896Sopenharmony_ci OPTIONS_MANAGER.signing_algorithm = None 45340681896Sopenharmony_ci OPTIONS_MANAGER.hash_algorithm = None 45440681896Sopenharmony_ci OPTIONS_MANAGER.private_key = None 45540681896Sopenharmony_ci OPTIONS_MANAGER.not_l2 = False 45640681896Sopenharmony_ci OPTIONS_MANAGER.signing_length = 256 45740681896Sopenharmony_ci OPTIONS_MANAGER.xml_path = None 45840681896Sopenharmony_ci OPTIONS_MANAGER.sd_card = False 45940681896Sopenharmony_ci 46040681896Sopenharmony_ci OPTIONS_MANAGER.full_image_path_list = [] 46140681896Sopenharmony_ci 46240681896Sopenharmony_ci OPTIONS_MANAGER.make_dir_path = None 46340681896Sopenharmony_ci 46440681896Sopenharmony_ci # Parsed package parameters 46540681896Sopenharmony_ci OPTIONS_MANAGER.target_package_dir = None 46640681896Sopenharmony_ci OPTIONS_MANAGER.target_package_config_dir = None 46740681896Sopenharmony_ci OPTIONS_MANAGER.target_package_temp_obj = None 46840681896Sopenharmony_ci OPTIONS_MANAGER.misc_info_dict = {} 46940681896Sopenharmony_ci OPTIONS_MANAGER.version_mbn_file_path = None 47040681896Sopenharmony_ci OPTIONS_MANAGER.version_mbn_content = None 47140681896Sopenharmony_ci OPTIONS_MANAGER.board_list_file_path = None 47240681896Sopenharmony_ci OPTIONS_MANAGER.board_list_content = None 47340681896Sopenharmony_ci 47440681896Sopenharmony_ci OPTIONS_MANAGER.source_package_dir = None 47540681896Sopenharmony_ci OPTIONS_MANAGER.source_package_temp_obj = None 47640681896Sopenharmony_ci 47740681896Sopenharmony_ci # XML parsing parameters 47840681896Sopenharmony_ci OPTIONS_MANAGER.head_info_list = [] 47940681896Sopenharmony_ci OPTIONS_MANAGER.component_info_dict = {} 48040681896Sopenharmony_ci OPTIONS_MANAGER.full_img_list = [] 48140681896Sopenharmony_ci OPTIONS_MANAGER.incremental_img_list = [] 48240681896Sopenharmony_ci OPTIONS_MANAGER.target_package_version = None 48340681896Sopenharmony_ci OPTIONS_MANAGER.source_package_version = None 48440681896Sopenharmony_ci OPTIONS_MANAGER.partition_file_obj = None 48540681896Sopenharmony_ci 48640681896Sopenharmony_ci # Global processing parameters 48740681896Sopenharmony_ci OPTIONS_MANAGER.full_image_content_len_list = [] 48840681896Sopenharmony_ci OPTIONS_MANAGER.full_image_file_obj_list = [] 48940681896Sopenharmony_ci 49040681896Sopenharmony_ci # Incremental processing parameters 49140681896Sopenharmony_ci OPTIONS_MANAGER.incremental_content_len_list = [] 49240681896Sopenharmony_ci OPTIONS_MANAGER.incremental_temp_file_obj_list = [] 49340681896Sopenharmony_ci 49440681896Sopenharmony_ci # Script parameters 49540681896Sopenharmony_ci OPTIONS_MANAGER.opera_script_file_name_dict = {} 49640681896Sopenharmony_ci for each in SCRIPT_KEY_LIST: 49740681896Sopenharmony_ci OPTIONS_MANAGER.opera_script_file_name_dict[each] = [] 49840681896Sopenharmony_ci OPTIONS_MANAGER.total_script_file_obj = None 49940681896Sopenharmony_ci 50040681896Sopenharmony_ci OPTIONS_MANAGER.register_script_file_obj = None 50140681896Sopenharmony_ci 50240681896Sopenharmony_ci # Update package parameters 50340681896Sopenharmony_ci OPTIONS_MANAGER.update_bin_obj = None 50440681896Sopenharmony_ci OPTIONS_MANAGER.build_tools_zip_obj = None 50540681896Sopenharmony_ci OPTIONS_MANAGER.update_package_file_path = None 50640681896Sopenharmony_ci 50740681896Sopenharmony_ci 50840681896Sopenharmony_cidef clear_resource(err_clear=False): 50940681896Sopenharmony_ci """ 51040681896Sopenharmony_ci Clear resources, close temporary files, and clear temporary paths. 51140681896Sopenharmony_ci :param err_clear: whether to clear errors 51240681896Sopenharmony_ci :return: 51340681896Sopenharmony_ci """ 51440681896Sopenharmony_ci target_package_temp_obj = OPTIONS_MANAGER.target_package_temp_obj 51540681896Sopenharmony_ci if target_package_temp_obj is not None: 51640681896Sopenharmony_ci target_package_temp_obj.cleanup() 51740681896Sopenharmony_ci source_package_temp_obj = OPTIONS_MANAGER.source_package_temp_obj 51840681896Sopenharmony_ci if source_package_temp_obj is not None: 51940681896Sopenharmony_ci source_package_temp_obj.cleanup() 52040681896Sopenharmony_ci 52140681896Sopenharmony_ci partition_file_obj = OPTIONS_MANAGER.partition_file_obj 52240681896Sopenharmony_ci if partition_file_obj is not None: 52340681896Sopenharmony_ci partition_file_obj.close() 52440681896Sopenharmony_ci 52540681896Sopenharmony_ci build_tools_zip_obj = OPTIONS_MANAGER.build_tools_zip_obj 52640681896Sopenharmony_ci if build_tools_zip_obj is not None: 52740681896Sopenharmony_ci build_tools_zip_obj.close() 52840681896Sopenharmony_ci update_bin_obj = OPTIONS_MANAGER.update_bin_obj 52940681896Sopenharmony_ci if update_bin_obj is not None: 53040681896Sopenharmony_ci update_bin_obj.close() 53140681896Sopenharmony_ci total_script_file_obj = OPTIONS_MANAGER.total_script_file_obj 53240681896Sopenharmony_ci if total_script_file_obj is not None: 53340681896Sopenharmony_ci total_script_file_obj.close() 53440681896Sopenharmony_ci 53540681896Sopenharmony_ci register_script_file_obj = OPTIONS_MANAGER.register_script_file_obj 53640681896Sopenharmony_ci if register_script_file_obj is not None: 53740681896Sopenharmony_ci register_script_file_obj.close() 53840681896Sopenharmony_ci 53940681896Sopenharmony_ci full_image_file_obj_list = OPTIONS_MANAGER.full_image_file_obj_list 54040681896Sopenharmony_ci if len(full_image_file_obj_list) != 0: 54140681896Sopenharmony_ci for each_full_obj in full_image_file_obj_list: 54240681896Sopenharmony_ci each_full_obj.close() 54340681896Sopenharmony_ci 54440681896Sopenharmony_ci clear_file_obj(err_clear) 54540681896Sopenharmony_ci clear_options() 54640681896Sopenharmony_ci 54740681896Sopenharmony_ci 54840681896Sopenharmony_cidef clear_file_obj(err_clear): 54940681896Sopenharmony_ci """ 55040681896Sopenharmony_ci Clear resources and temporary file objects. 55140681896Sopenharmony_ci :param err_clear: whether to clear errors 55240681896Sopenharmony_ci :return: 55340681896Sopenharmony_ci """ 55440681896Sopenharmony_ci incremental_temp_file_obj_list = \ 55540681896Sopenharmony_ci OPTIONS_MANAGER.incremental_temp_file_obj_list 55640681896Sopenharmony_ci if len(incremental_temp_file_obj_list) != 0: 55740681896Sopenharmony_ci for each_incremental_temp_obj in incremental_temp_file_obj_list: 55840681896Sopenharmony_ci if each_incremental_temp_obj is not None: 55940681896Sopenharmony_ci each_incremental_temp_obj.close() 56040681896Sopenharmony_ci opera_script_file_name_dict = OPTIONS_MANAGER.opera_script_file_name_dict 56140681896Sopenharmony_ci for each_value in opera_script_file_name_dict.values(): 56240681896Sopenharmony_ci for each in each_value: 56340681896Sopenharmony_ci each[1].close() 56440681896Sopenharmony_ci if err_clear: 56540681896Sopenharmony_ci make_dir_path = OPTIONS_MANAGER.make_dir_path 56640681896Sopenharmony_ci if make_dir_path is not None and os.path.exists(make_dir_path): 56740681896Sopenharmony_ci shutil.rmtree(make_dir_path) 56840681896Sopenharmony_ci update_package_file_path = OPTIONS_MANAGER.update_package_file_path 56940681896Sopenharmony_ci if update_package_file_path is not None and \ 57040681896Sopenharmony_ci os.path.exists(update_package_file_path): 57140681896Sopenharmony_ci os.remove(update_package_file_path) 57240681896Sopenharmony_ci UPDATE_LOGGER.print_log( 57340681896Sopenharmony_ci 'Exception occurred, Resource cleaning completed!') 57440681896Sopenharmony_ci else: 57540681896Sopenharmony_ci UPDATE_LOGGER.print_log('Resource cleaning completed!') 57640681896Sopenharmony_ci 57740681896Sopenharmony_ci 57840681896Sopenharmony_cidef get_file_content(file_path, file_name=None): 57940681896Sopenharmony_ci """ 58040681896Sopenharmony_ci Read the file content. 58140681896Sopenharmony_ci :param file_path: file path 58240681896Sopenharmony_ci :param file_name: file name 58340681896Sopenharmony_ci :return: file content 58440681896Sopenharmony_ci """ 58540681896Sopenharmony_ci if not os.path.exists(file_path): 58640681896Sopenharmony_ci UPDATE_LOGGER.print_log( 58740681896Sopenharmony_ci "%s is not exist! path: %s" % (file_name, file_path), 58840681896Sopenharmony_ci log_type=UPDATE_LOGGER.ERROR_LOG) 58940681896Sopenharmony_ci return False 59040681896Sopenharmony_ci with open(file_path, 'r') as r_f: 59140681896Sopenharmony_ci file_content = r_f.read() 59240681896Sopenharmony_ci UPDATE_LOGGER.print_log( 59340681896Sopenharmony_ci "%s file parsing complete! path: %s" % (file_name, file_path)) 59440681896Sopenharmony_ci return file_content 59540681896Sopenharmony_ci 59640681896Sopenharmony_ci 59740681896Sopenharmony_cidef get_update_info(): 59840681896Sopenharmony_ci """ 59940681896Sopenharmony_ci Parse the configuration file to obtain the update information. 60040681896Sopenharmony_ci :return: update information if any; false otherwise. 60140681896Sopenharmony_ci """ 60240681896Sopenharmony_ci if not OPTIONS_MANAGER.not_l2: 60340681896Sopenharmony_ci decouple_res = OPTIONS_MANAGER.init.invoke_event(DECOUPLED_EVENT) 60440681896Sopenharmony_ci OPTIONS_MANAGER.version_mbn_file_path = os.path.join( 60540681896Sopenharmony_ci OPTIONS_MANAGER.target_package_config_dir, VERSION_MBN_PATH) 60640681896Sopenharmony_ci version_mbn_content = \ 60740681896Sopenharmony_ci get_file_content( 60840681896Sopenharmony_ci OPTIONS_MANAGER.version_mbn_file_path, os.path.basename( 60940681896Sopenharmony_ci os.path.join(OPTIONS_MANAGER.target_package_config_dir, 61040681896Sopenharmony_ci VERSION_MBN_PATH))) 61140681896Sopenharmony_ci if version_mbn_content is False and decouple_res is False: 61240681896Sopenharmony_ci UPDATE_LOGGER.print_log( 61340681896Sopenharmony_ci "Get version mbn content failed!", 61440681896Sopenharmony_ci log_type=UPDATE_LOGGER.ERROR_LOG) 61540681896Sopenharmony_ci return False 61640681896Sopenharmony_ci OPTIONS_MANAGER.version_mbn_content = version_mbn_content 61740681896Sopenharmony_ci OPTIONS_MANAGER.board_list_file_path = os.path.join( 61840681896Sopenharmony_ci OPTIONS_MANAGER.target_package_config_dir, BOARD_LIST_PATH) 61940681896Sopenharmony_ci board_list_content = \ 62040681896Sopenharmony_ci get_file_content( 62140681896Sopenharmony_ci OPTIONS_MANAGER.board_list_file_path, os.path.basename( 62240681896Sopenharmony_ci os.path.join(OPTIONS_MANAGER.target_package_config_dir, 62340681896Sopenharmony_ci BOARD_LIST_PATH))) 62440681896Sopenharmony_ci if board_list_content is False: 62540681896Sopenharmony_ci UPDATE_LOGGER.print_log("Get board list content failed!", log_type=UPDATE_LOGGER.ERROR_LOG) 62640681896Sopenharmony_ci return False 62740681896Sopenharmony_ci OPTIONS_MANAGER.board_list_content = board_list_content 62840681896Sopenharmony_ci 62940681896Sopenharmony_ci if OPTIONS_MANAGER.xml_path is None: 63040681896Sopenharmony_ci xml_file_path = os.path.join( 63140681896Sopenharmony_ci OPTIONS_MANAGER.target_package_config_dir, XML_FILE_PATH) 63240681896Sopenharmony_ci else: 63340681896Sopenharmony_ci xml_file_path = OPTIONS_MANAGER.xml_path 63440681896Sopenharmony_ci 63540681896Sopenharmony_ci # Parse the XML configuration file. 63640681896Sopenharmony_ci head_info_list, component_info_dict, \ 63740681896Sopenharmony_ci full_img_list, incremental_img_list, \ 63840681896Sopenharmony_ci OPTIONS_MANAGER.target_package_version, \ 63940681896Sopenharmony_ci OPTIONS_MANAGER.full_image_path_list = \ 64040681896Sopenharmony_ci parse_update_config(xml_file_path) 64140681896Sopenharmony_ci UPDATE_LOGGER.print_log("XML file parsing completed!") 64240681896Sopenharmony_ci if head_info_list is False or component_info_dict is False or \ 64340681896Sopenharmony_ci full_img_list is False or incremental_img_list is False: 64440681896Sopenharmony_ci UPDATE_LOGGER.print_log("Get parse update config xml failed!", log_type=UPDATE_LOGGER.ERROR_LOG) 64540681896Sopenharmony_ci return False 64640681896Sopenharmony_ci OPTIONS_MANAGER.head_info_list, OPTIONS_MANAGER.component_info_dict, \ 64740681896Sopenharmony_ci OPTIONS_MANAGER.full_img_list, OPTIONS_MANAGER.incremental_img_list = \ 64840681896Sopenharmony_ci head_info_list, component_info_dict, \ 64940681896Sopenharmony_ci full_img_list, incremental_img_list 65040681896Sopenharmony_ci return True 65140681896Sopenharmony_ci 65240681896Sopenharmony_ci 65340681896Sopenharmony_cidef sign_package(): 65440681896Sopenharmony_ci return sign_ota_package( 65540681896Sopenharmony_ci OPTIONS_MANAGER.update_package_file_path, 65640681896Sopenharmony_ci OPTIONS_MANAGER.signed_package, 65740681896Sopenharmony_ci OPTIONS_MANAGER.private_key)