1#!/usr/bin/env python 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 17""" 18The tool for making updater package. 19 20positional arguments: 21 target_package Target package file path. 22 update_package Update package file path. 23 24optional arguments: 25 -h, --help show this help message and exit 26 -s SOURCE_PACKAGE, --source_package SOURCE_PACKAGE 27 Source package file path. 28 -nz, --no_zip No zip mode, 29 which means to output the update package without zip. 30 -pf PARTITION_FILE, --partition_file PARTITION_FILE 31 Variable partition mode, Partition list file path. 32 -sa {ECC,RSA}, --signing_algorithm {ECC,RSA} 33 The signing algorithms 34 supported by the tool include ['ECC', 'RSA']. 35 -ha {sha256,sha384}, --hash_algorithm {sha256,sha384} 36 The hash algorithms 37 supported by the tool include ['sha256', 'sha384']. 38 -pk PRIVATE_KEY, --private_key PRIVATE_KEY 39 Private key file path. 40 -nl2, --not_l2 Not L2 mode, Distinguish between L1 and L2. 41 -sl {256,384}, --signing_length {256,384} 42 The signing content length 43 supported by the tool include ['256', '384']. 44 -xp, --xml_path XML file path. 45 -sc, --sd_card SD Card mode, Create update package for SD Card. 46""" 47import filecmp 48import os 49import argparse 50import subprocess 51 52import xmltodict 53 54import patch_package_process 55 56from gigraph_process import GigraphProcess 57from image_class import FullUpdateImage 58from image_class import is_sparse_image 59from image_class import IncUpdateImage 60from transfers_manager import TransfersManager 61from log_exception import UPDATE_LOGGER 62from script_generator import PreludeScript 63from script_generator import VerseScript 64from script_generator import RefrainScript 65from script_generator import EndingScript 66from update_package import build_update_package 67from utils import OPTIONS_MANAGER 68from utils import UPDATER_CONFIG 69from utils import parse_partition_file_xml 70from utils import unzip_package 71from utils import clear_resource 72from utils import PRODUCT 73from utils import XML_FILE_PATH 74from utils import get_update_info 75from utils import SCRIPT_KEY_LIST 76from utils import PER_BLOCK_SIZE 77from vendor_script import create_vendor_script_class 78 79 80def type_check(arg): 81 """ 82 Argument check, which is used to check whether the specified arg is a file. 83 :param arg: the arg to check 84 :return: Check result, which is False if the arg is invalid. 85 """ 86 if arg is not None and not os.path.exists(arg): 87 UPDATE_LOGGER.print_log( 88 "FileNotFoundError, path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 89 return False 90 return arg 91 92 93def private_key_check(arg): 94 """ 95 Argument check, which is used to check whether 96 the specified arg is a private_key. 97 :param arg: The arg to check. 98 :return: Check result, which is False if the arg is invalid. 99 """ 100 if arg != "ON_SERVER" and not os.path.isfile(arg): 101 UPDATE_LOGGER.print_log( 102 "FileNotFoundError, path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 103 return False 104 return arg 105 106 107def check_update_package(arg): 108 """ 109 Argument check, which is used to check whether 110 the update package path exists. 111 :param arg: The arg to check. 112 :return: Check result 113 """ 114 make_dir_path = None 115 if os.path.exists(arg): 116 if os.path.isfile(arg): 117 UPDATE_LOGGER.print_log( 118 "Update package must be a dir path, not a file path. " 119 "path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 120 return False 121 else: 122 try: 123 UPDATE_LOGGER.print_log( 124 "Update package path does not exist. The dir will be created!" 125 "path: %s" % arg, UPDATE_LOGGER.WARNING_LOG) 126 os.makedirs(arg) 127 make_dir_path = arg 128 except OSError: 129 UPDATE_LOGGER.print_log( 130 "Make update package path dir failed! " 131 "path: %s" % arg, UPDATE_LOGGER.ERROR_LOG) 132 return False 133 if make_dir_path is not None: 134 OPTIONS_MANAGER.make_dir_path = make_dir_path 135 return arg 136 137 138def create_entrance_args(): 139 """ 140 Arguments for the tool to create an update package 141 :return source_package : source version package 142 target_package : target version package 143 update_package : update package output path 144 no_zip : whether to enable the update package zip function. 145 partition_file : partition table XML file 146 signing_algorithm : signature algorithm (ECC and RSA (default)) 147 private_key : path of the private key file 148 """ 149 description = "Tool for creating update package." 150 parser = argparse.ArgumentParser(description=description) 151 parser.add_argument("-s", "--source_package", type=type_check, 152 default=None, help="Source package file path.") 153 parser.add_argument("target_package", type=type_check, 154 help="Target package file path.") 155 parser.add_argument("update_package", type=check_update_package, 156 help="Update package file path.") 157 parser.add_argument("-nz", "--no_zip", action='store_true', 158 help="No zip mode, Output update package without zip.") 159 parser.add_argument("-pf", "--partition_file", default=None, 160 help="Variable partition mode, " 161 "Partition list file path.") 162 parser.add_argument("-sa", "--signing_algorithm", default='RSA', 163 choices=['ECC', 'RSA'], 164 help="The signing algorithm " 165 "supported by the tool include ['ECC', 'RSA'].") 166 parser.add_argument("-ha", "--hash_algorithm", default='sha256', 167 choices=['sha256', 'sha384'], 168 help="The hash algorithm " 169 "supported by the tool include " 170 "['sha256', 'sha384'].") 171 parser.add_argument("-pk", "--private_key", type=private_key_check, 172 default=None, help="Private key file path.") 173 parser.add_argument("-nl2", "--not_l2", action='store_true', 174 help="Not L2 mode, Distinguish between L1 and L2.") 175 parser.add_argument("-sl", "--signing_length", default='256', 176 choices=['256', '384'], 177 help="The signing content length " 178 "supported by the tool include " 179 "['256', '384'].") 180 parser.add_argument("-xp", "--xml_path", type=private_key_check, 181 default=None, help="XML file path.") 182 parser.add_argument("-sc", "--sd_card", action='store_true', 183 help="SD Card mode, " 184 "Create update package for SD Card.") 185 186 args = parser.parse_args() 187 source_package = args.source_package 188 OPTIONS_MANAGER.source_package = source_package 189 target_package = args.target_package 190 OPTIONS_MANAGER.target_package = target_package 191 update_package = args.update_package 192 OPTIONS_MANAGER.update_package = update_package 193 no_zip = args.no_zip 194 OPTIONS_MANAGER.no_zip = no_zip 195 partition_file = args.partition_file 196 OPTIONS_MANAGER.partition_file = partition_file 197 signing_algorithm = args.signing_algorithm 198 OPTIONS_MANAGER.signing_algorithm = signing_algorithm 199 hash_algorithm = args.hash_algorithm 200 OPTIONS_MANAGER.hash_algorithm = hash_algorithm 201 private_key = args.private_key 202 OPTIONS_MANAGER.private_key = private_key 203 204 not_l2 = args.not_l2 205 OPTIONS_MANAGER.not_l2 = not_l2 206 signing_length = int(args.signing_length) 207 OPTIONS_MANAGER.signing_length = signing_length 208 xml_path = args.xml_path 209 OPTIONS_MANAGER.xml_path = xml_path 210 sd_card = args.sd_card 211 OPTIONS_MANAGER.sd_card = sd_card 212 213 ret_args = [source_package, target_package, update_package, 214 no_zip, not_l2, partition_file, signing_algorithm, 215 hash_algorithm, private_key] 216 return ret_args 217 218 219def get_script_obj(): 220 """ 221 Obtain Opera script object 222 :return: 223 """ 224 script_obj_list = create_vendor_script_class() 225 if script_obj_list == [None] * len(SCRIPT_KEY_LIST): 226 prelude_script = PreludeScript() 227 verse_script = VerseScript() 228 refrain_script = RefrainScript() 229 ending_script = EndingScript() 230 else: 231 UPDATE_LOGGER.print_log( 232 "Get vendor extension object completed!" 233 "The vendor extension script will be generated.") 234 prelude_script = script_obj_list[0] 235 verse_script = script_obj_list[1] 236 refrain_script = script_obj_list[2] 237 ending_script = script_obj_list[3] 238 return prelude_script, verse_script, refrain_script, ending_script 239 240 241def check_incremental_args(no_zip, partition_file, source_package, 242 incremental_img_list): 243 """ 244 When the incremental list is not empty, incremental processing is required. 245 In this case, check related arguments. 246 :param no_zip: no zip mode 247 :param partition_file: 248 :param source_package: 249 :param incremental_img_list: 250 :return: 251 """ 252 if "boot" in incremental_img_list: 253 UPDATE_LOGGER.print_log( 254 "boot cannot be incrementally processed!", 255 UPDATE_LOGGER.ERROR_LOG) 256 clear_resource(err_clear=True) 257 return False 258 if source_package is None: 259 UPDATE_LOGGER.print_log( 260 "The source package is missing, " 261 "cannot be incrementally processed!", 262 UPDATE_LOGGER.ERROR_LOG) 263 clear_resource(err_clear=True) 264 return False 265 if no_zip: 266 UPDATE_LOGGER.print_log( 267 "No ZIP mode, cannot be incrementally processed!", 268 UPDATE_LOGGER.ERROR_LOG) 269 clear_resource(err_clear=True) 270 return False 271 if partition_file is not None: 272 UPDATE_LOGGER.print_log( 273 "Partition file is not None, " 274 "cannot be incrementally processed!", 275 UPDATE_LOGGER.ERROR_LOG) 276 clear_resource(err_clear=True) 277 return False 278 279 OPTIONS_MANAGER.source_package_temp_obj, \ 280 OPTIONS_MANAGER.source_package_dir = \ 281 unzip_package(source_package, origin='source') 282 xml_path = '' 283 if OPTIONS_MANAGER.source_package_dir is not False: 284 xml_path = os.path.join(OPTIONS_MANAGER.source_package_dir, 285 UPDATER_CONFIG, XML_FILE_PATH) 286 if OPTIONS_MANAGER.source_package_dir is False: 287 OPTIONS_MANAGER.source_package_temp_obj = None 288 OPTIONS_MANAGER.source_package_dir = None 289 if os.path.exists(xml_path): 290 with open(xml_path, 'r') as xml_file: 291 xml_str = xml_file.read() 292 else: 293 UPDATE_LOGGER.print_log("XML file does not exist! xml path: %s" % 294 xml_path, UPDATE_LOGGER.ERROR_LOG) 295 return False 296 xml_content_dict = xmltodict.parse(xml_str, encoding='utf-8') 297 package_dict = xml_content_dict.get('package', {}) 298 head_dict = package_dict.get('head', {}).get('info') 299 OPTIONS_MANAGER.source_package_version = head_dict.get("@softVersion") 300 if check_package_version(OPTIONS_MANAGER.target_package_version, 301 OPTIONS_MANAGER.source_package_version) is False: 302 clear_resource(err_clear=True) 303 return False 304 return True 305 306 307def check_userdata_image(): 308 """ 309 Check the userdata image. Updating this image is prohibited. 310 :return: 311 """ 312 if 'userdata' in OPTIONS_MANAGER.full_img_list or \ 313 'userdata' in OPTIONS_MANAGER.incremental_img_list: 314 UPDATE_LOGGER.print_log( 315 "userdata image does not participate in update!" 316 "Please check xml config, path: %s!" % 317 os.path.join(OPTIONS_MANAGER.target_package_config_dir, 318 XML_FILE_PATH), 319 UPDATE_LOGGER.ERROR_LOG) 320 clear_resource(err_clear=True) 321 return False 322 return True 323 324 325def check_images_list(): 326 """ 327 Check full_img_list and incremental_img_list. 328 If their lengths are 0, an error will be logged. 329 :return: 330 """ 331 if len(OPTIONS_MANAGER.full_img_list) == 0 and \ 332 len(OPTIONS_MANAGER.incremental_img_list) == 0: 333 UPDATE_LOGGER.print_log( 334 "The image list is empty!" 335 "Please check xml config, path: %s!" % 336 os.path.join(OPTIONS_MANAGER.target_package_config_dir, 337 XML_FILE_PATH), 338 UPDATE_LOGGER.ERROR_LOG) 339 clear_resource(err_clear=True) 340 return False 341 return True 342 343 344def check_target_package_path(target_package): 345 """ 346 Check the target_package path. 347 :param target_package: target package path 348 :return: 349 """ 350 if os.path.isdir(target_package): 351 OPTIONS_MANAGER.target_package_dir = target_package 352 temp_dir_list = os.listdir(target_package) 353 if UPDATER_CONFIG in temp_dir_list: 354 OPTIONS_MANAGER.target_package_config_dir = \ 355 os.path.join(target_package, UPDATER_CONFIG) 356 else: 357 UPDATE_LOGGER.print_log( 358 "Exception's target package path! path: %s" % 359 target_package, UPDATE_LOGGER.ERROR_LOG) 360 return False 361 elif target_package.endswith('.zip'): 362 # Decompress the target package. 363 tmp_dir_obj, unzip_dir = unzip_package(target_package) 364 if tmp_dir_obj is False or unzip_dir is False: 365 clear_resource(err_clear=True) 366 return False 367 OPTIONS_MANAGER.target_package_dir = unzip_dir 368 OPTIONS_MANAGER.target_package_temp_obj = tmp_dir_obj 369 OPTIONS_MANAGER.target_package_config_dir = \ 370 os.path.join(unzip_dir, UPDATER_CONFIG) 371 else: 372 UPDATE_LOGGER.print_log( 373 "Input Update Package type exception! path: %s" % 374 target_package, UPDATE_LOGGER.ERROR_LOG) 375 clear_resource(err_clear=True) 376 return False 377 return True 378 379 380def check_miss_private_key(private_key): 381 """ 382 Check private key. 383 :param private_key: 384 :return: 385 """ 386 if private_key is None: 387 UPDATE_LOGGER.print_log( 388 "Private key is None, update package cannot be signed! " 389 "Please specify the signature private key by -pk.", 390 UPDATE_LOGGER.ERROR_LOG) 391 clear_resource(err_clear=True) 392 return False 393 return True 394 395 396def check_package_version(target_ver, source_ver): 397 """ 398 target_ver: target version 399 source_ver: source version 400 return: 401 """ 402 try: 403 target_num = ''.join(target_ver.split(' ')[-1].split('.')[1:3]) 404 source_num = ''.join(source_ver.split(' ')[-1].split('.')[1:3]) 405 if int(target_num) <= int(source_num): 406 UPDATE_LOGGER.print_log( 407 'Target package version %s <= Source package version!' 408 'Unable to make updater package!', 409 UPDATE_LOGGER.ERROR_LOG) 410 return False 411 except ValueError: 412 UPDATE_LOGGER.print_log('your package version number is not compliant.' 413 'Please check your package version number!', 414 UPDATE_LOGGER.ERROR_LOG) 415 return False 416 return True 417 418 419def increment_image_processing( 420 verse_script, incremental_img_list, source_package_dir, 421 target_package_dir): 422 """ 423 Incremental image processing 424 :param verse_script: verse script 425 :param incremental_img_list: incremental image list 426 :param source_package_dir: source package path 427 :param target_package_dir: target package path 428 :return: 429 """ 430 script_check_cmd_list = [] 431 script_write_cmd_list = [] 432 patch_process = None 433 for each_img in incremental_img_list: 434 each_src_image_path = \ 435 os.path.join(source_package_dir, 436 '%s.img' % each_img) 437 each_src_map_path = \ 438 os.path.join(source_package_dir, 439 '%s.map' % each_img) 440 each_tgt_image_path = \ 441 os.path.join(target_package_dir, 442 '%s.img' % each_img) 443 each_tgt_map_path = \ 444 os.path.join(target_package_dir, 445 '%s.map' % each_img) 446 if not os.path.exists(each_src_image_path): 447 UPDATE_LOGGER.print_log( 448 "The source %s.img file is missing from the source package, " 449 "the component: %s cannot be incrementally processed. " 450 "path: %s!" % 451 (each_img, each_img, 452 os.path.join(source_package_dir, UPDATER_CONFIG, 453 XML_FILE_PATH)), 454 UPDATE_LOGGER.ERROR_LOG) 455 clear_resource(err_clear=True) 456 return False 457 458 src_is_sparse = is_sparse_image(each_src_image_path) 459 tgt_is_sparse = is_sparse_image(each_tgt_image_path) 460 check_make_map_path(each_img) 461 cmd = ["e2fsdroid", "-B", each_src_map_path, 462 "-a", "/%s" % each_img, each_src_image_path] 463 if not src_is_sparse: 464 cmd.append("-e") 465 sub_p = subprocess.Popen( 466 cmd, shell=False, stdout=subprocess.PIPE, 467 stderr=subprocess.STDOUT) 468 sub_p.wait() 469 470 if not os.path.exists(each_tgt_image_path): 471 UPDATE_LOGGER.print_log( 472 "The target %s.img file is missing from the target package, " 473 "the component: %s cannot be incrementally processed. " 474 "Please check xml config, path: %s!" % 475 (each_img, each_img, 476 os.path.join(target_package_dir, UPDATER_CONFIG, 477 XML_FILE_PATH)), 478 UPDATE_LOGGER.ERROR_LOG) 479 clear_resource(err_clear=True) 480 return False 481 482 cmd = ["e2fsdroid", "-B", each_tgt_map_path, 483 "-a", "/%s" % each_img, each_tgt_image_path] 484 if not tgt_is_sparse: 485 cmd.append("-e") 486 sub_p = subprocess.Popen( 487 cmd, shell=False, stdout=subprocess.PIPE, 488 stderr=subprocess.STDOUT) 489 sub_p.wait() 490 491 if filecmp.cmp(each_src_image_path, each_tgt_image_path): 492 UPDATE_LOGGER.print_log( 493 "Source Image is the same as Target Image!" 494 "src image path: %s, tgt image path: %s" % 495 (each_src_image_path, each_tgt_image_path), 496 UPDATE_LOGGER.ERROR_LOG) 497 clear_resource(err_clear=True) 498 return False 499 if not src_is_sparse and not tgt_is_sparse: 500 src_image_class = \ 501 IncUpdateImage(each_src_image_path, each_src_map_path) 502 tgt_image_class = \ 503 IncUpdateImage(each_tgt_image_path, each_tgt_map_path) 504 else: 505 raise RuntimeError 506 507 transfers_manager = TransfersManager( 508 each_img, tgt_image_class, src_image_class) 509 transfers_manager.find_process_needs() 510 actions_list = transfers_manager.get_action_list() 511 512 graph_process = GigraphProcess(actions_list, src_image_class, 513 tgt_image_class) 514 actions_list = graph_process.actions_list 515 patch_process = \ 516 patch_package_process.PatchProcess( 517 each_img, tgt_image_class, src_image_class, actions_list) 518 patch_process.patch_process() 519 patch_process.package_patch_zip.package_patch_zip() 520 patch_process.write_script(each_img, script_check_cmd_list, 521 script_write_cmd_list, verse_script) 522 if not check_patch_file(patch_process): 523 UPDATE_LOGGER.print_log( 524 'Verify the incremental result failed!', 525 UPDATE_LOGGER.ERROR_LOG) 526 raise RuntimeError 527 UPDATE_LOGGER.print_log( 528 'Verify the incremental result successfully!', 529 UPDATE_LOGGER.INFO_LOG) 530 531 verse_script.add_command( 532 "\n# ---- start incremental check here ----\n") 533 for each_check_cmd in script_check_cmd_list: 534 verse_script.add_command(each_check_cmd) 535 verse_script.add_command( 536 "\n# ---- start incremental write here ----\n") 537 for each_write_cmd in script_write_cmd_list: 538 verse_script.add_command(each_write_cmd) 539 return True 540 541 542def check_patch_file(patch_process): 543 new_dat_file_obj, patch_dat_file_obj, transfer_list_file_obj = \ 544 patch_process.package_patch_zip.get_file_obj() 545 with open(transfer_list_file_obj.name) as f_t: 546 num = 0 547 diff_str = None 548 diff_num = 0 549 for line in f_t: 550 if line.startswith('new '): 551 each_line_list = \ 552 line.strip().replace("new ", "").split(",")[1:] 553 for idx in range(0, len(each_line_list), 2): 554 num += \ 555 int(each_line_list[idx + 1]) - int(each_line_list[idx]) 556 continue 557 if line.startswith('bsdiff ') or line.startswith('pkgdiff '): 558 diff_str = line 559 if diff_str: 560 diff_list = diff_str.split('\n')[0].split(' ') 561 diff_num = int(diff_list[1]) + int(diff_list[2]) 562 check_flag = \ 563 (os.path.getsize(new_dat_file_obj.name) == num * PER_BLOCK_SIZE) and \ 564 (os.path.getsize(patch_dat_file_obj.name) == diff_num) 565 return check_flag 566 567 568def check_make_map_path(each_img): 569 """ 570 If env does not exist, the command for map generation does not exist 571 in the environment variable, and False will be returned. 572 """ 573 try: 574 cmd = ["e2fsdroid", " -h"] 575 subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, 576 stderr=subprocess.STDOUT) 577 except FileNotFoundError: 578 UPDATE_LOGGER.print_log( 579 "Command not found, need check the env! " 580 "Make %s.map failed!" % each_img, 581 UPDATE_LOGGER.ERROR_LOG) 582 clear_resource(err_clear=True) 583 raise RuntimeError 584 return True 585 586 587def incremental_processing(no_zip, partition_file, source_package, 588 verse_script): 589 """ 590 Incremental processing. 591 :param no_zip: no zip mode 592 :param partition_file: partition xml file path 593 :param source_package: source package path 594 :param verse_script: verse script obj 595 :return : processing result 596 """ 597 if len(OPTIONS_MANAGER.incremental_img_list) != 0: 598 if check_incremental_args(no_zip, partition_file, source_package, 599 OPTIONS_MANAGER.incremental_img_list) \ 600 is False: 601 return False 602 if increment_image_processing( 603 verse_script, OPTIONS_MANAGER.incremental_img_list, 604 OPTIONS_MANAGER.source_package_dir, 605 OPTIONS_MANAGER.target_package_dir) is False: 606 return False 607 else: 608 if source_package is not None: 609 UPDATE_LOGGER.print_log( 610 "There is no incremental image, " 611 "the - S parameter is not required!", 612 UPDATE_LOGGER.ERROR_LOG) 613 raise RuntimeError 614 615 616def check_args(private_key, source_package, target_package, update_package): 617 """ 618 Input args check. 619 :param private_key: private key path 620 :param source_package: source package path 621 :param target_package: target package path 622 :param update_package: output package path 623 :return : Judgment result 624 """ 625 if source_package is False or private_key is False or \ 626 target_package is False or update_package is False: 627 return False 628 if check_miss_private_key(private_key) is False: 629 return False 630 if check_target_package_path(target_package) is False: 631 return False 632 if get_update_info() is False: 633 return False 634 if check_images_list() is False: 635 return False 636 return True 637 638 639def main(): 640 """ 641 Entry function. 642 """ 643 OPTIONS_MANAGER.product = PRODUCT 644 645 source_package, target_package, update_package, no_zip, not_l2, \ 646 partition_file, signing_algorithm, hash_algorithm, private_key = \ 647 create_entrance_args() 648 if not_l2: 649 no_zip = True 650 if OPTIONS_MANAGER.sd_card: 651 if source_package is not None or \ 652 OPTIONS_MANAGER.xml_path is not None or \ 653 partition_file is not None: 654 UPDATE_LOGGER.print_log( 655 "SD Card updater, " 656 "the -S/-xp/-pf parameter is not required!", 657 UPDATE_LOGGER.ERROR_LOG) 658 raise RuntimeError 659 if check_args(private_key, source_package, 660 target_package, update_package) is False: 661 clear_resource(err_clear=True) 662 return 663 664 if not OPTIONS_MANAGER.sd_card: 665 if check_userdata_image() is False: 666 clear_resource(err_clear=True) 667 return 668 669 # Create a Script object. 670 prelude_script, verse_script, refrain_script, ending_script = \ 671 get_script_obj() 672 673 # Create partition. 674 if partition_file is not None: 675 verse_script.add_command("\n# ---- do updater partitions ----\n") 676 updater_partitions_cmd = verse_script.updater_partitions() 677 verse_script.add_command(updater_partitions_cmd) 678 679 partition_file_obj, partitions_list, partitions_file_path_list = \ 680 parse_partition_file_xml(partition_file) 681 if partition_file_obj is False: 682 clear_resource(err_clear=True) 683 return False 684 OPTIONS_MANAGER.partition_file_obj = partition_file_obj 685 OPTIONS_MANAGER.full_img_list = partitions_list 686 OPTIONS_MANAGER.full_image_path_list = partitions_file_path_list 687 OPTIONS_MANAGER.two_step = False 688 689 # Upgrade the updater image. 690 if OPTIONS_MANAGER.two_step: 691 get_status_cmd = verse_script.get_status() 692 set_status_0_cmd = verse_script.set_status('0') 693 set_status_1_cmd = verse_script.set_status('1') 694 reboot_now_cmd = verse_script.reboot_now() 695 create_updater_script_command = \ 696 '\n# ---- do updater partitions ----\n\n' \ 697 'if ({get_status_cmd} == 0){{\nUPDATER_WRITE_FLAG\n' \ 698 ' {set_status_1_cmd} {reboot_now_cmd}}}\n' \ 699 'else{{ \nALL_WRITE_FLAG\n {set_status_0_cmd}}}'.format( 700 get_status_cmd=get_status_cmd, 701 set_status_1_cmd=set_status_1_cmd, 702 set_status_0_cmd=set_status_0_cmd, 703 reboot_now_cmd=reboot_now_cmd) 704 verse_script.add_command(create_updater_script_command) 705 706 if incremental_processing( 707 no_zip, partition_file, source_package, verse_script) is False: 708 clear_resource(err_clear=True) 709 return 710 711 # Full processing 712 if len(OPTIONS_MANAGER.full_img_list) != 0: 713 verse_script.add_command("\n# ---- full image ----\n") 714 full_image_content_len_list, full_image_file_obj_list = \ 715 FullUpdateImage(OPTIONS_MANAGER.target_package_dir, 716 OPTIONS_MANAGER.full_img_list, verse_script, 717 OPTIONS_MANAGER.full_image_path_list, 718 no_zip=OPTIONS_MANAGER.no_zip).\ 719 update_full_image() 720 if full_image_content_len_list is False or \ 721 full_image_file_obj_list is False: 722 clear_resource(err_clear=True) 723 return 724 OPTIONS_MANAGER.full_image_content_len_list, \ 725 OPTIONS_MANAGER.full_image_file_obj_list = \ 726 full_image_content_len_list, full_image_file_obj_list 727 728 # Generate the update package. 729 build_re = build_update_package(no_zip, update_package, 730 prelude_script, verse_script, 731 refrain_script, ending_script) 732 if build_re is False: 733 clear_resource(err_clear=True) 734 return 735 # Clear resources. 736 clear_resource() 737 738 739if __name__ == '__main__': 740 main() 741