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 203 # Script parameters 204 self.opera_script_file_name_dict = {} 205 for each in SCRIPT_KEY_LIST: 206 self.opera_script_file_name_dict[each] = [] 207 self.total_script_file_obj = None 208 209 self.register_script_file_obj = None 210 211 # Update package parameters 212 self.update_bin_obj = None 213 self.build_tools_zip_obj = None 214 self.update_package_file_path = None 215 self.signed_package = None 216 217 218OPTIONS_MANAGER = OptionsManager() 219 220 221def unzip_package(package_path, origin='target'): 222 """ 223 Decompress the zip package. 224 :param package_path: zip package path 225 :param origin: package origin, which indicates 226 whether the zip package is a source package or target package 227 :return: Temporary directory (tmp_dir) and zip_data package; 228 false if an exception occurs. 229 """ 230 try: 231 tmp_dir_obj = tempfile.TemporaryDirectory(prefix="%sfiles-" % origin) 232 tmp_dir = tmp_dir_obj.name 233 234 zf_obj = zipfile.ZipFile(package_path) 235 for name in zf_obj.namelist(): 236 if name.endswith('/'): 237 os.mkdir(os.path.join(tmp_dir, name)) 238 else: 239 ext_filename = os.path.join( 240 tmp_dir, name) 241 fd = os.open(ext_filename, os.O_RDWR | os.O_CREAT, 0o755) 242 with os.fdopen(fd, "wb") as f_w: 243 f_w.write(zf_obj.read(name)) 244 except OSError: 245 UPDATE_LOGGER.print_log( 246 "Unzip package failed! path: %s" % package_path, 247 log_type=UPDATE_LOGGER.ERROR_LOG) 248 return False, False 249 tmp_dir_list = os.listdir(tmp_dir) 250 if len(tmp_dir_list) == 1: 251 unzip_dir = os.path.join(tmp_dir, tmp_dir_list[0]) 252 if UPDATER_CONFIG not in \ 253 os.listdir(unzip_dir): 254 UPDATE_LOGGER.print_log( 255 'Unsupported zip package structure!', UPDATE_LOGGER.ERROR_LOG) 256 return False, False 257 elif UPDATER_CONFIG in tmp_dir_list: 258 unzip_dir = tmp_dir 259 else: 260 UPDATE_LOGGER.print_log( 261 'Unsupported zip package structure!', UPDATE_LOGGER.ERROR_LOG) 262 return False, False 263 UPDATE_LOGGER.print_log( 264 '%s package unzip complete! path: %s' % (origin.title(), unzip_dir)) 265 266 return tmp_dir_obj, unzip_dir 267 268 269def split_img_name(image_path): 270 """ 271 Split the image name by image path 272 :return image name 273 """ 274 tmp_path = image_path 275 str_list = tmp_path.split("/") 276 277 return str_list[-1] 278 279 280def get_update_config_softversion(mbn_dir, head_info_dict): 281 soft_version_file = head_info_dict.get('softVersionFile') 282 if soft_version_file is not None: 283 mbn_path = os.path.join(mbn_dir, soft_version_file) 284 if os.path.exists(mbn_path): 285 with open(mbn_path, 'r') as mbn_file: 286 head_info_dict['info']["@softVersion"] = mbn_file.read() 287 288 289def parse_update_config(xml_path): 290 """ 291 Parse the XML configuration file. 292 :param xml_path: XML configuration file path 293 :return head_info_dict: header information dict of the update package 294 component_info_dict: component information dict 295 full_img_list: full image list 296 incremental_img_list: incremental image list 297 """ 298 if os.path.exists(xml_path): 299 with open(xml_path, 'r') as xml_file: 300 xml_str = xml_file.read() 301 else: 302 UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % xml_path, UPDATE_LOGGER.ERROR_LOG) 303 ret_params = [False, False, False, False, False, False, False] 304 return ret_params 305 xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 306 package_dict = xml_content_dict.get('package', {}) 307 get_update_config_softversion(OPTIONS_MANAGER.target_package_dir, package_dict.get('head', {})) 308 head_dict = package_dict.get('head', {}).get('info') 309 package_version = head_dict.get("@softVersion") 310 # component 311 component_info = package_dict.get('group', {}).get('component') 312 head_list = list(head_dict.values()) 313 head_list.pop() 314 whole_list = [] 315 difference_list = [] 316 comp_dict = {} 317 full_image_path_list = [] 318 319 if not OPTIONS_MANAGER.not_l2: 320 expand_component(comp_dict) 321 if isinstance(component_info, OrderedDict) or isinstance(component_info, dict): 322 component_info = [component_info] 323 if component_info is None: 324 ret_params = [[], {}, [], [], '', [], False] 325 return ret_params 326 for component in component_info: 327 if component['@compAddr'] == 'userdata' and not OPTIONS_MANAGER.sd_card: 328 continue 329 component_list = list(component.values()) 330 component_list.pop() 331 comp_dict[component['@compAddr']] = component_list 332 333 if component['@compAddr'] in (whole_list + difference_list): 334 UPDATE_LOGGER.print_log("This component %s repeats!" % component['@compAddr'], UPDATE_LOGGER.ERROR_LOG) 335 ret_params = [False, False, False, False, False, False, False] 336 return ret_params 337 338 if component['@compType'] == '0': 339 whole_list.append(component['@compAddr']) 340 OPTIONS_MANAGER.full_img_name_list.append(split_img_name(component['#text'])) 341 tem_path = os.path.join(OPTIONS_MANAGER.target_package_dir, component.get("#text", None)) 342 full_image_path_list.append(tem_path) 343 comp_dict[component['@compAddr']] = component_list 344 elif component['@compType'] == '1': 345 difference_list.append(component['@compAddr']) 346 OPTIONS_MANAGER.incremental_img_name_list.append(split_img_name(component['#text'])) 347 348 ret_params = [head_list, comp_dict, whole_list, difference_list, package_version, full_image_path_list] 349 return ret_params 350 351 352def partitions_conversion(data): 353 """ 354 Convert the start or length data in the partition table through 355 multiply 1024 * 1024 and return the data. 356 :param data: start or length data 357 :return : 358 """ 359 if data == '0': 360 return 0 361 elif data.endswith('M'): 362 return int(data[0:-1]) * 1024 * 1024 // 512 363 else: 364 return False 365 366 367def parse_partition_file_xml(xml_path): 368 """ 369 Parse the XML configuration file. 370 :param xml_path: XML configuration file path 371 :return part_json: partition table information in JSON format 372 """ 373 if os.path.exists(xml_path): 374 with open(xml_path, 'r') as xml_file: 375 xml_str = xml_file.read() 376 else: 377 UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % 378 xml_path, UPDATE_LOGGER.ERROR_LOG) 379 return False, False, False 380 partitions_list = [] 381 partitions_file_path_list = [] 382 xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 383 part_list = xml_content_dict['Partition_Info']['Part'] 384 new_part_list = [] 385 for i, part in enumerate(part_list): 386 start_value = partitions_conversion(part.get('@Start')) 387 length_value = partitions_conversion(part.get('@Length')) 388 if start_value is False or length_value is False: 389 UPDATE_LOGGER.print_log( 390 "Partition file parsing failed! part_name: %s, xml_path: %s" % 391 (part.get('@PartitionName'), xml_path), 392 UPDATE_LOGGER.ERROR_LOG) 393 return False, False, False 394 395 if part.get('@PartitionName') not in IGNORED_PARTITION_LIST: 396 partitions_list.append(part.get('@PartitionName')) 397 partitions_file_path_list.append( 398 os.path.join(OPTIONS_MANAGER.target_package_dir, 399 "%s.img" % part.get('@PartitionName'))) 400 part_dict = {'start': start_value, 401 'length': length_value, 402 'partName': part.get('@PartitionName'), 403 'fsType': part.get('@FlashType')} 404 new_part_list.append(part_dict) 405 part_json = json.dumps(new_part_list) 406 part_json = '{"Partition": %s}' % part_json 407 file_obj = tempfile.NamedTemporaryFile( 408 dir=OPTIONS_MANAGER.target_package_dir, prefix="partition_file-", mode='wb') 409 file_obj.write(part_json.encode()) 410 file_obj.seek(0) 411 return file_obj, partitions_list, partitions_file_path_list 412 413 414def get_extend_path_list(): 415 get_config_list = OPTIONS_MANAGER.init.invoke_event(CONFIG_EVENT) 416 if get_config_list: 417 return get_config_list() 418 else: 419 return EXTEND_COMPONENT_LIST 420 421 422def expand_component(component_dict): 423 """ 424 Append components such as VERSION.mbn and board list. 425 :param component_dict: component information dict 426 :return: 427 """ 428 extend_path_list = get_extend_path_list() 429 if OPTIONS_MANAGER.partition_file is not None: 430 extend_component_list = \ 431 extend_path_list + EXTEND_OPTIONAL_COMPONENT_LIST 432 else: 433 extend_component_list = extend_path_list 434 for each in extend_component_list: 435 tmp_info_list = copy(COMPONENT_INFO_INNIT) 436 tmp_info_list[0] = each 437 component_dict[each] = tmp_info_list 438 439 440def clear_options(): 441 """ 442 Clear OPTIONS_MANAGER. 443 """ 444 OPTIONS_MANAGER.product = None 445 446 # Entry parameters 447 OPTIONS_MANAGER.source_package = None 448 OPTIONS_MANAGER.target_package = None 449 OPTIONS_MANAGER.update_package = None 450 OPTIONS_MANAGER.no_zip = False 451 OPTIONS_MANAGER.partition_file = None 452 OPTIONS_MANAGER.signing_algorithm = None 453 OPTIONS_MANAGER.hash_algorithm = None 454 OPTIONS_MANAGER.private_key = None 455 OPTIONS_MANAGER.not_l2 = False 456 OPTIONS_MANAGER.signing_length = 256 457 OPTIONS_MANAGER.xml_path = None 458 OPTIONS_MANAGER.sd_card = False 459 460 OPTIONS_MANAGER.full_image_path_list = [] 461 462 OPTIONS_MANAGER.make_dir_path = None 463 464 # Parsed package parameters 465 OPTIONS_MANAGER.target_package_dir = None 466 OPTIONS_MANAGER.target_package_config_dir = None 467 OPTIONS_MANAGER.target_package_temp_obj = None 468 OPTIONS_MANAGER.misc_info_dict = {} 469 OPTIONS_MANAGER.version_mbn_file_path = None 470 OPTIONS_MANAGER.version_mbn_content = None 471 OPTIONS_MANAGER.board_list_file_path = None 472 OPTIONS_MANAGER.board_list_content = None 473 474 OPTIONS_MANAGER.source_package_dir = None 475 OPTIONS_MANAGER.source_package_temp_obj = None 476 477 # XML parsing parameters 478 OPTIONS_MANAGER.head_info_list = [] 479 OPTIONS_MANAGER.component_info_dict = {} 480 OPTIONS_MANAGER.full_img_list = [] 481 OPTIONS_MANAGER.incremental_img_list = [] 482 OPTIONS_MANAGER.target_package_version = None 483 OPTIONS_MANAGER.source_package_version = None 484 OPTIONS_MANAGER.partition_file_obj = None 485 486 # Global processing parameters 487 OPTIONS_MANAGER.full_image_content_len_list = [] 488 OPTIONS_MANAGER.full_image_file_obj_list = [] 489 490 # Incremental processing parameters 491 OPTIONS_MANAGER.incremental_content_len_list = [] 492 OPTIONS_MANAGER.incremental_temp_file_obj_list = [] 493 494 # Script parameters 495 OPTIONS_MANAGER.opera_script_file_name_dict = {} 496 for each in SCRIPT_KEY_LIST: 497 OPTIONS_MANAGER.opera_script_file_name_dict[each] = [] 498 OPTIONS_MANAGER.total_script_file_obj = None 499 500 OPTIONS_MANAGER.register_script_file_obj = None 501 502 # Update package parameters 503 OPTIONS_MANAGER.update_bin_obj = None 504 OPTIONS_MANAGER.build_tools_zip_obj = None 505 OPTIONS_MANAGER.update_package_file_path = None 506 507 508def clear_resource(err_clear=False): 509 """ 510 Clear resources, close temporary files, and clear temporary paths. 511 :param err_clear: whether to clear errors 512 :return: 513 """ 514 target_package_temp_obj = OPTIONS_MANAGER.target_package_temp_obj 515 if target_package_temp_obj is not None: 516 target_package_temp_obj.cleanup() 517 source_package_temp_obj = OPTIONS_MANAGER.source_package_temp_obj 518 if source_package_temp_obj is not None: 519 source_package_temp_obj.cleanup() 520 521 partition_file_obj = OPTIONS_MANAGER.partition_file_obj 522 if partition_file_obj is not None: 523 partition_file_obj.close() 524 525 build_tools_zip_obj = OPTIONS_MANAGER.build_tools_zip_obj 526 if build_tools_zip_obj is not None: 527 build_tools_zip_obj.close() 528 update_bin_obj = OPTIONS_MANAGER.update_bin_obj 529 if update_bin_obj is not None: 530 update_bin_obj.close() 531 total_script_file_obj = OPTIONS_MANAGER.total_script_file_obj 532 if total_script_file_obj is not None: 533 total_script_file_obj.close() 534 535 register_script_file_obj = OPTIONS_MANAGER.register_script_file_obj 536 if register_script_file_obj is not None: 537 register_script_file_obj.close() 538 539 full_image_file_obj_list = OPTIONS_MANAGER.full_image_file_obj_list 540 if len(full_image_file_obj_list) != 0: 541 for each_full_obj in full_image_file_obj_list: 542 each_full_obj.close() 543 544 clear_file_obj(err_clear) 545 clear_options() 546 547 548def clear_file_obj(err_clear): 549 """ 550 Clear resources and temporary file objects. 551 :param err_clear: whether to clear errors 552 :return: 553 """ 554 incremental_temp_file_obj_list = \ 555 OPTIONS_MANAGER.incremental_temp_file_obj_list 556 if len(incremental_temp_file_obj_list) != 0: 557 for each_incremental_temp_obj in incremental_temp_file_obj_list: 558 if each_incremental_temp_obj is not None: 559 each_incremental_temp_obj.close() 560 opera_script_file_name_dict = OPTIONS_MANAGER.opera_script_file_name_dict 561 for each_value in opera_script_file_name_dict.values(): 562 for each in each_value: 563 each[1].close() 564 if err_clear: 565 make_dir_path = OPTIONS_MANAGER.make_dir_path 566 if make_dir_path is not None and os.path.exists(make_dir_path): 567 shutil.rmtree(make_dir_path) 568 update_package_file_path = OPTIONS_MANAGER.update_package_file_path 569 if update_package_file_path is not None and \ 570 os.path.exists(update_package_file_path): 571 os.remove(update_package_file_path) 572 UPDATE_LOGGER.print_log( 573 'Exception occurred, Resource cleaning completed!') 574 else: 575 UPDATE_LOGGER.print_log('Resource cleaning completed!') 576 577 578def get_file_content(file_path, file_name=None): 579 """ 580 Read the file content. 581 :param file_path: file path 582 :param file_name: file name 583 :return: file content 584 """ 585 if not os.path.exists(file_path): 586 UPDATE_LOGGER.print_log( 587 "%s is not exist! path: %s" % (file_name, file_path), 588 log_type=UPDATE_LOGGER.ERROR_LOG) 589 return False 590 with open(file_path, 'r') as r_f: 591 file_content = r_f.read() 592 UPDATE_LOGGER.print_log( 593 "%s file parsing complete! path: %s" % (file_name, file_path)) 594 return file_content 595 596 597def get_update_info(): 598 """ 599 Parse the configuration file to obtain the update information. 600 :return: update information if any; false otherwise. 601 """ 602 if not OPTIONS_MANAGER.not_l2: 603 decouple_res = OPTIONS_MANAGER.init.invoke_event(DECOUPLED_EVENT) 604 OPTIONS_MANAGER.version_mbn_file_path = os.path.join( 605 OPTIONS_MANAGER.target_package_config_dir, VERSION_MBN_PATH) 606 version_mbn_content = \ 607 get_file_content( 608 OPTIONS_MANAGER.version_mbn_file_path, os.path.basename( 609 os.path.join(OPTIONS_MANAGER.target_package_config_dir, 610 VERSION_MBN_PATH))) 611 if version_mbn_content is False and decouple_res is False: 612 UPDATE_LOGGER.print_log( 613 "Get version mbn content failed!", 614 log_type=UPDATE_LOGGER.ERROR_LOG) 615 return False 616 OPTIONS_MANAGER.version_mbn_content = version_mbn_content 617 OPTIONS_MANAGER.board_list_file_path = os.path.join( 618 OPTIONS_MANAGER.target_package_config_dir, BOARD_LIST_PATH) 619 board_list_content = \ 620 get_file_content( 621 OPTIONS_MANAGER.board_list_file_path, os.path.basename( 622 os.path.join(OPTIONS_MANAGER.target_package_config_dir, 623 BOARD_LIST_PATH))) 624 if board_list_content is False: 625 UPDATE_LOGGER.print_log("Get board list content failed!", log_type=UPDATE_LOGGER.ERROR_LOG) 626 return False 627 OPTIONS_MANAGER.board_list_content = board_list_content 628 629 if OPTIONS_MANAGER.xml_path is None: 630 xml_file_path = os.path.join( 631 OPTIONS_MANAGER.target_package_config_dir, XML_FILE_PATH) 632 else: 633 xml_file_path = OPTIONS_MANAGER.xml_path 634 635 # Parse the XML configuration file. 636 head_info_list, component_info_dict, \ 637 full_img_list, incremental_img_list, \ 638 OPTIONS_MANAGER.target_package_version, \ 639 OPTIONS_MANAGER.full_image_path_list = \ 640 parse_update_config(xml_file_path) 641 UPDATE_LOGGER.print_log("XML file parsing completed!") 642 if head_info_list is False or component_info_dict is False or \ 643 full_img_list is False or incremental_img_list is False: 644 UPDATE_LOGGER.print_log("Get parse update config xml failed!", log_type=UPDATE_LOGGER.ERROR_LOG) 645 return False 646 OPTIONS_MANAGER.head_info_list, OPTIONS_MANAGER.component_info_dict, \ 647 OPTIONS_MANAGER.full_img_list, OPTIONS_MANAGER.incremental_img_list = \ 648 head_info_list, component_info_dict, \ 649 full_img_list, incremental_img_list 650 return True 651 652 653def sign_package(): 654 return sign_ota_package( 655 OPTIONS_MANAGER.update_package_file_path, 656 OPTIONS_MANAGER.signed_package, 657 OPTIONS_MANAGER.private_key)