• 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 """
17 Description : Defining constants, common interface
18 """
19 import argparse
20 import json
21 import os
22 import shutil
23 import tempfile
24 import zipfile
25 from collections import OrderedDict
26 from copy import copy
27 from ctypes import cdll
28 from cryptography.hazmat.primitives import hashes
29 from log_exception import UPDATE_LOGGER
30 import xmltodict
31 from build_pkcs7 import sign_ota_package
32 
33 operation_path = os.path.dirname(os.path.realpath(__file__))
34 PRODUCT = 'hi3516'
35 BUILD_TOOLS_FILE_NAME = 'build_tools.zip'
36 UPDATE_EXE_FILE_NAME = "updater_binary"
37 
38 SCRIPT_KEY_LIST = ['prelude', 'verse', 'refrain', 'ending']
39 TOTAL_SCRIPT_FILE_NAME = "loadScript.us"
40 REGISTER_SCRIPT_FILE_NAME = "registerCmd.us"
41 SCRIPT_FILE_NAME = '-script.us'
42 
43 UPDATER_CONFIG = "updater_config"
44 XML_FILE_PATH = "updater_specified_config.xml"
45 SO_PATH = os.path.join(operation_path, 'lib/libpackage.so')
46 SO_PATH_L1 = os.path.join(operation_path, 'lib/libpackageL1.so')
47 DIFF_EXE_PATH = os.path.join(operation_path, 'lib/diff')
48 E2FSDROID_PATH = os.path.join(operation_path, 'lib/e2fsdroid')
49 MISC_INFO_PATH = "misc_info.txt"
50 VERSION_MBN_PATH = "VERSION.mbn"
51 BOARD_LIST_PATH = "BOARD.list"
52 EXTEND_COMPONENT_LIST = ["version_list", "board_list"]
53 EXTEND_OPTIONAL_COMPONENT_LIST = ["partitions_file"]
54 PARTITION_FILE = "partitions_file"
55 IGNORED_PARTITION_LIST = ['fastboot', 'boot', 'kernel', 'misc',
56                           'updater', 'userdata']
57 
58 HASH_ALGORITHM_DICT = {'sha256': hashes.SHA256, 'sha384': hashes.SHA384}
59 LINUX_HASH_ALGORITHM_DICT = {'sha256': 'sha256sum', 'sha384': 'sha384sum'}
60 HASH_CONTENT_LEN_DICT = {'sha256': 64, 'sha384': 96}
61 
62 COMPONENT_INFO_INNIT = ['', '000', '00', '0', '0o00']
63 
64 ON_SERVER = "ON_SERVER"
65 
66 EXTEND_VALUE = 512
67 
68 FILE_MAP_ZERO_KEY = "__ZERO"
69 FILE_MAP_NONZERO_KEY = "__NONZERO"
70 FILE_MAP_COPY_KEY = "__COPY"
71 
72 MAX_BLOCKS_PER_GROUP = BLOCK_LIMIT = 1024
73 PER_BLOCK_SIZE = 4096
74 TWO_STEP = "updater"
75 
76 VERSE_SCRIPT_EVENT = 0
77 INC_IMAGE_EVENT = 1
78 SIGN_PACKAGE_EVENT = 2
79 
80 # Image file can not support update.
81 FORBIDEN_UPDATE_IMAGE_LIST = ["updater_boot", "updater_b", "ptable"]
82 
83 # 1000000: max number of function recursion depth
84 MAXIMUM_RECURSION_DEPTH = 1000000
85 
86 
87 def 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 
98 class 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
123 class 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 
205 OPTIONS_MANAGER = OptionsManager()
206 
207 
208 def 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 
255 def 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 
266 def 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 
275 def 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 
348 def 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 
363 def 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 
410 def 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 
427 def 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 
496 def 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 
536 def 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 
572 def 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 
591 def 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 
650 def sign_package():
651     return sign_ota_package(
652         OPTIONS_MANAGER.update_package_file_path,
653         OPTIONS_MANAGER.signed_package,
654         OPTIONS_MANAGER.private_key)