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)