1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2021 Huawei Device Co., Ltd. 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""" 17Description : Defining constants, common interface 18""" 19import argparse 20import json 21import os 22import shutil 23import tempfile 24from collections import OrderedDict 25import xmltodict 26import zipfile 27 28from cryptography.hazmat.primitives import hashes 29from log_exception import UPDATE_LOGGER 30from build_pkcs7 import sign_ota_package 31from copy import copy 32from ctypes import cdll 33 34operation_path = os.path.dirname(os.path.realpath(__file__)) 35PRODUCT = 'hi3516' 36BUILD_TOOLS_FILE_NAME = 'build_tools.zip' 37UPDATE_BIN_FILE_NAME = "update.bin" 38UPDATE_EXE_FILE_NAME = "updater_binary" 39 40SCRIPT_KEY_LIST = ['prelude', 'verse', 'refrain', 'ending'] 41TOTAL_SCRIPT_FILE_NAME = "loadScript.us" 42REGISTER_SCRIPT_FILE_NAME = "registerCmd.us" 43SCRIPT_FILE_NAME = '-script.us' 44 45UPDATER_CONFIG = "updater_config" 46XML_FILE_PATH = "updater_specified_config.xml" 47SO_PATH = os.path.join(operation_path, 'lib/libpackage.so') 48SO_PATH_L1 = os.path.join(operation_path, 'lib/libpackageL1.so') 49DIFF_EXE_PATH = os.path.join(operation_path, 'lib/diff') 50E2FSDROID_PATH = os.path.join(operation_path, 'lib/e2fsdroid') 51MISC_INFO_PATH = "misc_info.txt" 52VERSION_MBN_PATH = "VERSION.mbn" 53BOARD_LIST_PATH = "BOARD.list" 54EXTEND_COMPONENT_LIST = ["version_list", "board_list"] 55EXTEND_OPTIONAL_COMPONENT_LIST = ["partitions_file"] 56PARTITION_FILE = "partitions_file" 57IGNORED_PARTITION_LIST = ['fastboot', 'boot', 'kernel', 'misc', 58 'updater', 'userdata'] 59 60HASH_ALGORITHM_DICT = {'sha256': hashes.SHA256, 'sha384': hashes.SHA384} 61LINUX_HASH_ALGORITHM_DICT = {'sha256': 'sha256sum', 'sha384': 'sha384sum'} 62HASH_CONTENT_LEN_DICT = {'sha256': 64, 'sha384': 96} 63 64COMPONENT_INFO_INNIT = ['', '000', '00', '0', '0o00'] 65 66ON_SERVER = "ON_SERVER" 67 68EXTEND_VALUE = 512 69 70FILE_MAP_ZERO_KEY = "__ZERO" 71FILE_MAP_NONZERO_KEY = "__NONZERO" 72FILE_MAP_COPY_KEY = "__COPY" 73 74MAX_BLOCKS_PER_GROUP = BLOCK_LIMIT = 1024 75PER_BLOCK_SIZE = 4096 76 77VERSE_SCRIPT_EVENT = 0 78INC_IMAGE_EVENT = 1 79SIGN_PACKAGE_EVENT = 2 80CHECK_BINARY_EVENT = 3 81CONFIG_EVENT = 4 82EXTEND_PATH_EVENT = 5 83ZIP_EVENT = 6 84GENERATE_SIGNED_DATA_EVENT = 7 # sign build tools files to get hash_signed_data 85PARTITION_CHANGE_EVENT = 8 86DECOUPLED_EVENT = 9 87 88# Image file can not support update. 89FORBIDEN_UPDATE_IMAGE_SET = {"ptable"} 90 91# 1000000: max number of function recursion depth 92MAXIMUM_RECURSION_DEPTH = 1000000 93 94 95def singleton(cls): 96 _instance = {} 97 98 def _singleton(*args, **kargs): 99 if cls not in _instance: 100 _instance[cls] = cls(*args, **kargs) 101 return _instance[cls] 102 103 return _singleton 104 105 106class ExtInit: 107 """ 108 Init event for ext 109 """ 110 111 def __init__(self): 112 self.funs = [] 113 114 def reg_event(self, evevt_id, funs): 115 self.funs.append([evevt_id, funs]) 116 UPDATE_LOGGER.print_log( 117 'register event %s: %s' % (evevt_id, funs.__name__)) 118 119 def invoke_event(self, evevt_id): 120 UPDATE_LOGGER.print_log(self.funs) 121 for event in self.funs: 122 funs = event[1] 123 if event[0] == evevt_id and funs is not None: 124 UPDATE_LOGGER.print_log( 125 'invoke event %s: %s' % (evevt_id, funs.__name__)) 126 return funs 127 return False 128 129 130class BaseOptionsManager: 131 def __init__(self): 132 # Entry parameters 133 self.source_package = None 134 self.target_package = None 135 self.update_package = None 136 self.unpack_package_path = None 137 self.no_zip = False 138 self.partition_file = None 139 self.signing_algorithm = None 140 self.hash_algorithm = None 141 self.private_key = None 142 self.not_l2 = False 143 self.signing_length = 256 144 self.xml_path = None 145 self.sd_card = False 146 147 self.make_dir_path = None 148 149 150@singleton 151class OptionsManager(BaseOptionsManager): 152 """ 153 Options management class 154 """ 155 156 def __init__(self): 157 super().__init__() 158 159 self.init = ExtInit() 160 self.parser = argparse.ArgumentParser() 161 162 # Own parameters 163 self.product = None 164 165 166 # Parsed package parameters 167 self.target_package_dir = None 168 self.target_package_config_dir = None 169 self.target_package_temp_obj = None 170 self.misc_info_dict = {} 171 self.version_mbn_file_path = None 172 self.version_mbn_content = None 173 self.board_list_file_path = None 174 self.board_list_content = None 175 176 self.source_package_dir = None 177 self.source_package_temp_obj = None 178 179 # XML parsing parameters 180 self.head_info_list = [] 181 self.component_info_dict = {} 182 self.full_img_list = [] 183 self.full_img_name_list = [] 184 self.incremental_img_list = [] 185 self.incremental_img_name_list = [] 186 self.target_package_version = None 187 self.source_package_version = None 188 self.full_image_path_list = [] 189 190 self.partition_file_obj = None 191 192 # Full processing parameters 193 self.full_image_content_len_list = [] 194 self.full_image_file_obj_list = [] 195 196 # Incremental processing parameters 197 self.incremental_content_len_list = [] 198 self.incremental_image_file_obj_dict = {} 199 self.incremental_block_file_obj_dict = {} 200 self.incremental_temp_file_obj_list = [] 201 self.max_stash_size = 0 202 self.src_image = None 203 self.tgt_image = None 204 205 # Script parameters 206 self.opera_script_file_name_dict = {} 207 for each in SCRIPT_KEY_LIST: 208 self.opera_script_file_name_dict[each] = [] 209 self.total_script_file_obj = None 210 211 self.register_script_file_obj = None 212 213 # Update package parameters 214 self.update_bin_obj = None 215 self.build_tools_zip_obj = None 216 self.update_package_file_path = None 217 self.signed_package = None 218 219 220OPTIONS_MANAGER = OptionsManager() 221 222 223def unzip_package(package_path, origin='target'): 224 """ 225 Decompress the zip package. 226 :param package_path: zip package path 227 :param origin: package origin, which indicates 228 whether the zip package is a source package or target package 229 :return: Temporary directory (tmp_dir) and zip_data package; 230 false if an exception occurs. 231 """ 232 try: 233 tmp_dir_obj = tempfile.TemporaryDirectory(prefix="%sfiles-" % origin) 234 tmp_dir = tmp_dir_obj.name 235 236 zf_obj = zipfile.ZipFile(package_path) 237 for name in zf_obj.namelist(): 238 if name.endswith('/'): 239 os.mkdir(os.path.join(tmp_dir, name)) 240 else: 241 ext_filename = os.path.join( 242 tmp_dir, name) 243 with open(ext_filename, 'wb') as f_w: 244 f_w.write(zf_obj.read(name)) 245 except OSError: 246 UPDATE_LOGGER.print_log( 247 "Unzip package failed! path: %s" % package_path, 248 log_type=UPDATE_LOGGER.ERROR_LOG) 249 return False, False 250 tmp_dir_list = os.listdir(tmp_dir) 251 if len(tmp_dir_list) == 1: 252 unzip_dir = os.path.join(tmp_dir, tmp_dir_list[0]) 253 if UPDATER_CONFIG not in \ 254 os.listdir(unzip_dir): 255 UPDATE_LOGGER.print_log( 256 'Unsupported zip package structure!', UPDATE_LOGGER.ERROR_LOG) 257 return False, False 258 elif UPDATER_CONFIG in tmp_dir_list: 259 unzip_dir = tmp_dir 260 else: 261 UPDATE_LOGGER.print_log( 262 'Unsupported zip package structure!', UPDATE_LOGGER.ERROR_LOG) 263 return False, False 264 UPDATE_LOGGER.print_log( 265 '%s package unzip complete! path: %s' % (origin.title(), unzip_dir)) 266 267 return tmp_dir_obj, unzip_dir 268 269 270def split_img_name(image_path): 271 """ 272 Split the image name by image path 273 :return image name 274 """ 275 tmp_path = image_path 276 str_list = tmp_path.split("/") 277 278 return str_list[-1] 279 280 281def get_update_config_softversion(mbn_dir, head_info_dict): 282 soft_version_file = head_info_dict.get('softVersionFile') 283 if soft_version_file is not None: 284 mbn_path = os.path.join(mbn_dir, soft_version_file) 285 if os.path.exists(mbn_path): 286 with open(mbn_path, 'r') as mbn_file: 287 head_info_dict['info']["@softVersion"] = mbn_file.read() 288 289 290def parse_update_config(xml_path): 291 """ 292 Parse the XML configuration file. 293 :param xml_path: XML configuration file path 294 :return head_info_dict: header information dict of the update package 295 component_info_dict: component information dict 296 full_img_list: full image list 297 incremental_img_list: incremental image list 298 """ 299 if os.path.exists(xml_path): 300 with open(xml_path, 'r') as xml_file: 301 xml_str = xml_file.read() 302 else: 303 UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % xml_path, UPDATE_LOGGER.ERROR_LOG) 304 ret_params = [False, False, False, False, False, False, False] 305 return ret_params 306 xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 307 package_dict = xml_content_dict.get('package', {}) 308 get_update_config_softversion(OPTIONS_MANAGER.target_package_dir, package_dict.get('head', {})) 309 head_dict = package_dict.get('head', {}).get('info') 310 package_version = head_dict.get("@softVersion") 311 # component 312 component_info = package_dict.get('group', {}).get('component') 313 head_list = list(head_dict.values()) 314 head_list.pop() 315 whole_list = [] 316 difference_list = [] 317 comp_dict = {} 318 full_image_path_list = [] 319 320 if not OPTIONS_MANAGER.not_l2: 321 expand_component(comp_dict) 322 if isinstance(component_info, OrderedDict) or isinstance(component_info, dict): 323 component_info = [component_info] 324 if component_info is None: 325 ret_params = [[], {}, [], [], '', [], False] 326 return ret_params 327 for component in component_info: 328 if component['@compAddr'] == 'userdata' and not OPTIONS_MANAGER.sd_card: 329 continue 330 component_list = list(component.values()) 331 component_list.pop() 332 comp_dict[component['@compAddr']] = component_list 333 334 if component['@compAddr'] in (whole_list + difference_list): 335 UPDATE_LOGGER.print_log("This component %s repeats!" % component['@compAddr'], UPDATE_LOGGER.ERROR_LOG) 336 ret_params = [False, False, False, False, False, False, False] 337 return ret_params 338 339 if component['@compType'] == '0': 340 whole_list.append(component['@compAddr']) 341 OPTIONS_MANAGER.full_img_name_list.append(split_img_name(component['#text'])) 342 tem_path = os.path.join(OPTIONS_MANAGER.target_package_dir, component.get("#text", None)) 343 full_image_path_list.append(tem_path) 344 comp_dict[component['@compAddr']] = component_list 345 elif component['@compType'] == '1': 346 difference_list.append(component['@compAddr']) 347 OPTIONS_MANAGER.incremental_img_name_list.append(split_img_name(component['#text'])) 348 349 ret_params = [head_list, comp_dict, whole_list, difference_list, package_version, full_image_path_list] 350 return ret_params 351 352 353def partitions_conversion(data): 354 """ 355 Convert the start or length data in the partition table through 356 multiply 1024 * 1024 and return the data. 357 :param data: start or length data 358 :return : 359 """ 360 if data == '0': 361 return 0 362 elif data.endswith('M'): 363 return int(data[0:-1]) * 1024 * 1024 // 512 364 else: 365 return False 366 367 368def parse_partition_file_xml(xml_path): 369 """ 370 Parse the XML configuration file. 371 :param xml_path: XML configuration file path 372 :return part_json: partition table information in JSON format 373 """ 374 if os.path.exists(xml_path): 375 with open(xml_path, 'r') as xml_file: 376 xml_str = xml_file.read() 377 else: 378 UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % 379 xml_path, UPDATE_LOGGER.ERROR_LOG) 380 return False, False, False 381 partitions_list = [] 382 partitions_file_path_list = [] 383 xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 384 part_list = xml_content_dict['Partition_Info']['Part'] 385 new_part_list = [] 386 for i, part in enumerate(part_list): 387 start_value = partitions_conversion(part.get('@Start')) 388 length_value = partitions_conversion(part.get('@Length')) 389 if start_value is False or length_value is False: 390 UPDATE_LOGGER.print_log( 391 "Partition file parsing failed! part_name: %s, xml_path: %s" % 392 (part.get('@PartitionName'), xml_path), 393 UPDATE_LOGGER.ERROR_LOG) 394 return False, False, False 395 396 if part.get('@PartitionName') not in IGNORED_PARTITION_LIST: 397 partitions_list.append(part.get('@PartitionName')) 398 partitions_file_path_list.append( 399 os.path.join(OPTIONS_MANAGER.target_package_dir, 400 "%s.img" % part.get('@PartitionName'))) 401 part_dict = {'start': start_value, 402 'length': length_value, 403 'partName': part.get('@PartitionName'), 404 'fsType': part.get('@FlashType')} 405 new_part_list.append(part_dict) 406 part_json = json.dumps(new_part_list) 407 part_json = '{"Partition": %s}' % part_json 408 file_obj = tempfile.NamedTemporaryFile( 409 dir=OPTIONS_MANAGER.target_package_dir, prefix="partition_file-", mode='wb') 410 file_obj.write(part_json.encode()) 411 file_obj.seek(0) 412 return file_obj, partitions_list, partitions_file_path_list 413 414 415def get_extend_path_list(): 416 get_config_list = OPTIONS_MANAGER.init.invoke_event(CONFIG_EVENT) 417 if get_config_list: 418 return get_config_list() 419 else: 420 return EXTEND_COMPONENT_LIST 421 422 423def expand_component(component_dict): 424 """ 425 Append components such as VERSION.mbn and board list. 426 :param component_dict: component information dict 427 :return: 428 """ 429 extend_path_list = get_extend_path_list() 430 if OPTIONS_MANAGER.partition_file is not None: 431 extend_component_list = \ 432 extend_path_list + EXTEND_OPTIONAL_COMPONENT_LIST 433 else: 434 extend_component_list = extend_path_list 435 for each in extend_component_list: 436 tmp_info_list = copy(COMPONENT_INFO_INNIT) 437 tmp_info_list[0] = each 438 component_dict[each] = tmp_info_list 439 440 441def clear_options(): 442 """ 443 Clear OPTIONS_MANAGER. 444 """ 445 OPTIONS_MANAGER.product = None 446 447 # Entry parameters 448 OPTIONS_MANAGER.source_package = None 449 OPTIONS_MANAGER.target_package = None 450 OPTIONS_MANAGER.update_package = None 451 OPTIONS_MANAGER.no_zip = False 452 OPTIONS_MANAGER.partition_file = None 453 OPTIONS_MANAGER.signing_algorithm = None 454 OPTIONS_MANAGER.hash_algorithm = None 455 OPTIONS_MANAGER.private_key = None 456 OPTIONS_MANAGER.not_l2 = False 457 OPTIONS_MANAGER.signing_length = 256 458 OPTIONS_MANAGER.xml_path = None 459 OPTIONS_MANAGER.sd_card = False 460 461 OPTIONS_MANAGER.full_image_path_list = [] 462 463 OPTIONS_MANAGER.make_dir_path = None 464 465 # Parsed package parameters 466 OPTIONS_MANAGER.target_package_dir = None 467 OPTIONS_MANAGER.target_package_config_dir = None 468 OPTIONS_MANAGER.target_package_temp_obj = None 469 OPTIONS_MANAGER.misc_info_dict = {} 470 OPTIONS_MANAGER.version_mbn_file_path = None 471 OPTIONS_MANAGER.version_mbn_content = None 472 OPTIONS_MANAGER.board_list_file_path = None 473 OPTIONS_MANAGER.board_list_content = None 474 475 OPTIONS_MANAGER.source_package_dir = None 476 OPTIONS_MANAGER.source_package_temp_obj = None 477 478 # XML parsing parameters 479 OPTIONS_MANAGER.head_info_list = [] 480 OPTIONS_MANAGER.component_info_dict = {} 481 OPTIONS_MANAGER.full_img_list = [] 482 OPTIONS_MANAGER.incremental_img_list = [] 483 OPTIONS_MANAGER.target_package_version = None 484 OPTIONS_MANAGER.source_package_version = None 485 OPTIONS_MANAGER.partition_file_obj = None 486 487 # Global processing parameters 488 OPTIONS_MANAGER.full_image_content_len_list = [] 489 OPTIONS_MANAGER.full_image_file_obj_list = [] 490 491 # Incremental processing parameters 492 OPTIONS_MANAGER.incremental_content_len_list = [] 493 OPTIONS_MANAGER.incremental_temp_file_obj_list = [] 494 495 # Script parameters 496 OPTIONS_MANAGER.opera_script_file_name_dict = {} 497 for each in SCRIPT_KEY_LIST: 498 OPTIONS_MANAGER.opera_script_file_name_dict[each] = [] 499 OPTIONS_MANAGER.total_script_file_obj = None 500 501 OPTIONS_MANAGER.register_script_file_obj = None 502 503 # Update package parameters 504 OPTIONS_MANAGER.update_bin_obj = None 505 OPTIONS_MANAGER.build_tools_zip_obj = None 506 OPTIONS_MANAGER.update_package_file_path = None 507 508 509def clear_resource(err_clear=False): 510 """ 511 Clear resources, close temporary files, and clear temporary paths. 512 :param err_clear: whether to clear errors 513 :return: 514 """ 515 target_package_temp_obj = OPTIONS_MANAGER.target_package_temp_obj 516 if target_package_temp_obj is not None: 517 target_package_temp_obj.cleanup() 518 source_package_temp_obj = OPTIONS_MANAGER.source_package_temp_obj 519 if source_package_temp_obj is not None: 520 source_package_temp_obj.cleanup() 521 522 partition_file_obj = OPTIONS_MANAGER.partition_file_obj 523 if partition_file_obj is not None: 524 partition_file_obj.close() 525 526 build_tools_zip_obj = OPTIONS_MANAGER.build_tools_zip_obj 527 if build_tools_zip_obj is not None: 528 build_tools_zip_obj.close() 529 update_bin_obj = OPTIONS_MANAGER.update_bin_obj 530 if update_bin_obj is not None: 531 update_bin_obj.close() 532 total_script_file_obj = OPTIONS_MANAGER.total_script_file_obj 533 if total_script_file_obj is not None: 534 total_script_file_obj.close() 535 536 register_script_file_obj = OPTIONS_MANAGER.register_script_file_obj 537 if register_script_file_obj is not None: 538 register_script_file_obj.close() 539 540 full_image_file_obj_list = OPTIONS_MANAGER.full_image_file_obj_list 541 if len(full_image_file_obj_list) != 0: 542 for each_full_obj in full_image_file_obj_list: 543 each_full_obj.close() 544 545 clear_file_obj(err_clear) 546 clear_options() 547 548 549def clear_file_obj(err_clear): 550 """ 551 Clear resources and temporary file objects. 552 :param err_clear: whether to clear errors 553 :return: 554 """ 555 incremental_temp_file_obj_list = \ 556 OPTIONS_MANAGER.incremental_temp_file_obj_list 557 if len(incremental_temp_file_obj_list) != 0: 558 for each_incremental_temp_obj in incremental_temp_file_obj_list: 559 if each_incremental_temp_obj is not None: 560 each_incremental_temp_obj.close() 561 opera_script_file_name_dict = OPTIONS_MANAGER.opera_script_file_name_dict 562 for each_value in opera_script_file_name_dict.values(): 563 for each in each_value: 564 each[1].close() 565 if err_clear: 566 make_dir_path = OPTIONS_MANAGER.make_dir_path 567 if make_dir_path is not None and os.path.exists(make_dir_path): 568 shutil.rmtree(make_dir_path) 569 update_package_file_path = OPTIONS_MANAGER.update_package_file_path 570 if update_package_file_path is not None and \ 571 os.path.exists(update_package_file_path): 572 os.remove(update_package_file_path) 573 UPDATE_LOGGER.print_log( 574 'Exception occurred, Resource cleaning completed!') 575 else: 576 UPDATE_LOGGER.print_log('Resource cleaning completed!') 577 578 579def get_file_content(file_path, file_name=None): 580 """ 581 Read the file content. 582 :param file_path: file path 583 :param file_name: file name 584 :return: file content 585 """ 586 if not os.path.exists(file_path): 587 UPDATE_LOGGER.print_log( 588 "%s is not exist! path: %s" % (file_name, file_path), 589 log_type=UPDATE_LOGGER.ERROR_LOG) 590 return False 591 with open(file_path, 'r') as r_f: 592 file_content = r_f.read() 593 UPDATE_LOGGER.print_log( 594 "%s file parsing complete! path: %s" % (file_name, file_path)) 595 return file_content 596 597 598def get_update_info(): 599 """ 600 Parse the configuration file to obtain the update information. 601 :return: update information if any; false otherwise. 602 """ 603 if not OPTIONS_MANAGER.not_l2: 604 decouple_res = OPTIONS_MANAGER.init.invoke_event(DECOUPLED_EVENT) 605 OPTIONS_MANAGER.version_mbn_file_path = os.path.join( 606 OPTIONS_MANAGER.target_package_config_dir, VERSION_MBN_PATH) 607 version_mbn_content = \ 608 get_file_content( 609 OPTIONS_MANAGER.version_mbn_file_path, os.path.basename( 610 os.path.join(OPTIONS_MANAGER.target_package_config_dir, 611 VERSION_MBN_PATH))) 612 if version_mbn_content is False and decouple_res is False: 613 UPDATE_LOGGER.print_log( 614 "Get version mbn content failed!", 615 log_type=UPDATE_LOGGER.ERROR_LOG) 616 return False 617 OPTIONS_MANAGER.version_mbn_content = version_mbn_content 618 OPTIONS_MANAGER.board_list_file_path = os.path.join( 619 OPTIONS_MANAGER.target_package_config_dir, BOARD_LIST_PATH) 620 board_list_content = \ 621 get_file_content( 622 OPTIONS_MANAGER.board_list_file_path, os.path.basename( 623 os.path.join(OPTIONS_MANAGER.target_package_config_dir, 624 BOARD_LIST_PATH))) 625 if board_list_content is False: 626 UPDATE_LOGGER.print_log("Get board list content failed!", log_type=UPDATE_LOGGER.ERROR_LOG) 627 return False 628 OPTIONS_MANAGER.board_list_content = board_list_content 629 630 if OPTIONS_MANAGER.xml_path is None: 631 xml_file_path = os.path.join( 632 OPTIONS_MANAGER.target_package_config_dir, XML_FILE_PATH) 633 else: 634 xml_file_path = OPTIONS_MANAGER.xml_path 635 636 # Parse the XML configuration file. 637 head_info_list, component_info_dict, \ 638 full_img_list, incremental_img_list, \ 639 OPTIONS_MANAGER.target_package_version, \ 640 OPTIONS_MANAGER.full_image_path_list = \ 641 parse_update_config(xml_file_path) 642 UPDATE_LOGGER.print_log("XML file parsing completed!") 643 if head_info_list is False or component_info_dict is False or \ 644 full_img_list is False or incremental_img_list is False: 645 UPDATE_LOGGER.print_log("Get parse update config xml failed!", log_type=UPDATE_LOGGER.ERROR_LOG) 646 return False 647 OPTIONS_MANAGER.head_info_list, OPTIONS_MANAGER.component_info_dict, \ 648 OPTIONS_MANAGER.full_img_list, OPTIONS_MANAGER.incremental_img_list = \ 649 head_info_list, component_info_dict, \ 650 full_img_list, incremental_img_list 651 return True 652 653 654def sign_package(): 655 return sign_ota_package( 656 OPTIONS_MANAGER.update_package_file_path, 657 OPTIONS_MANAGER.signed_package, 658 OPTIONS_MANAGER.private_key)