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