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