+#!/usr/bin/python3
+
+'''
+
+Copyright © 2022 Samsung Electronics Co., Ltd.. All rights reserved.
+
+Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute
+this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear
+in all copies of this software.
+
+IN NO EVENT SHALL SAMSUNG ELECTRONICS CO., LTD. BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF SAMSUNG ELECTRONICS CO., LTD. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+SAMSUNG ELECTRONICS CO., LTD. SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND SAMSUNG ELECTRONICS CO., LTD. HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+'''
+
+'''
+This script is used to generate an info file, which is to be attached to a delta of any type.
+The file contains specific details about an image that a particular delta will upgrade.
+Sample file (with currently supported image details)
+<<<
+ model_name=rpi4
+ manufacturer=Tizen
+ device_type=IoT_Headless
+ tz_build_release_name=Tizen7/Unified
+ tz_build_arch=aarch64
+ tz_build_date=20220922_060719
+>>>
+'''
+
+
+import xml.etree.ElementTree as ET
+import sys
+import os
+import argparse
+
+
+TIZEN_PREFIX = "tizen.org"
+SYSTEM_PREFIX = os.path.join(TIZEN_PREFIX, "system")
+BUILD_PREFIX = "TZ_BUILD_"
+
+
+# following three could be simpler, but this way its easier in case we add more variables to check
+def generate_hal_model_config_set():
+ hal_list = [
+ 'model_name'
+ ]
+ return set(os.path.join(SYSTEM_PREFIX, elem) for elem in hal_list)
+
+
+def generate_rootfs_model_config_set():
+ rootfs_list = [
+ 'manufacturer',
+ 'device_type'
+ ]
+ return set(os.path.join(SYSTEM_PREFIX, elem) for elem in rootfs_list)
+
+
+def generate_tizen_build_set():
+ tizen_list = [
+ 'RELEASE_NAME',
+ 'ARCH',
+ 'DATE'
+ ]
+ return set(BUILD_PREFIX + elem for elem in tizen_list)
+
+
+def get_dict_from_text_file(path, set_info):
+ tmp_dict = {}
+ with open(path, 'r') as reader:
+ lines = (line.rstrip() for line in reader.readlines())
+ lines = (line for line in lines if line)
+ for line in lines:
+ var_name, var_value = line.split('=')
+ var_name.rstrip()
+ var_value.lstrip()
+ if var_name in set_info:
+ set_info.remove(var_name)
+ # for consistent formatting
+ tmp_dict[var_name.lower()] = var_value
+ if len(set_info) == 0:
+ return tmp_dict
+
+ return None
+
+
+def get_dict_from_xml_file(path, set_info):
+ tmp_dict = {}
+
+ xml_tree = ET.parse(path)
+ xml_root = xml_tree.getroot()
+
+ for elem in xml_root.findall('./platform/key'):
+ name = elem.get('name')
+ if name in set_info:
+ set_info.remove(name)
+ tmp_dict[name] = elem.text
+ if len(set_info) == 0:
+ return tmp_dict
+
+ return None
+
+
+def generate_main_dict(args):
+ main_dict = {}
+
+ hal_set = generate_hal_model_config_set()
+ rootfs_set = generate_rootfs_model_config_set()
+ tizen_set = generate_tizen_build_set()
+
+ hal_dict = get_dict_from_xml_file(args.hal_model_config_path, hal_set)
+ if not hal_dict:
+ print(f'{args.hal_model_config_path}: error parsing file', file=sys.stderr)
+ return None
+
+ rootfs_dict = get_dict_from_xml_file(args.rootfs_model_config_path, rootfs_set)
+ if not rootfs_dict:
+ print(f'{args.rootfs_model_config_path}: error parsing file', file=sys.stderr)
+ return None
+
+ tizen_dict = get_dict_from_text_file(args.tizen_build_config_path, tizen_set)
+ if not tizen_dict:
+ print(f'{args.tizen_build_config_path}: error parsing file', file=sys.stderr)
+ return None
+
+ main_dict.update(hal_dict)
+ main_dict.update(rootfs_dict)
+ main_dict.update(tizen_dict)
+
+ return main_dict
+
+
+def create_parser():
+ parser = argparse.ArgumentParser(description='Generate a formated update-info.ini file used to verify whether \
+ delta archive used during update is compatible with our device. This file will be created using three files.')
+
+ parser.add_argument('hal_model_config_path', type=str, help='path to a file originally at path_to_hal/etc/config/model-config.xml')
+ parser.add_argument('rootfs_model_config_path', type=str, help='path to a file originally at path_to_rootfs/etc/config/model-config.xml')
+ parser.add_argument('tizen_build_config_path', type=str, help='path to a file originally at path_to_rootfs/etc/tizen-build.conf')
+ parser.add_argument('output_file', type=str, help='path to an output file')
+
+ return parser
+
+
+def main():
+ parser = create_parser()
+ args = parser.parse_args()
+
+ for index, (arg_name, arg_value) in enumerate(vars(args).items(), start=1):
+ # we do not want output file to exist
+ if index == len(vars(args)):
+ if os.path.exists(arg_value):
+ parser.error(f'{arg_name} = {arg_value} is a file that already exists!')
+ break
+ if not (os.path.exists(arg_value) and os.path.isfile(arg_value)):
+ parser.error(f'{arg_name} = {arg_value} is not a valid path!')
+
+ print('--- Generate update info file ---')
+ update_data = generate_main_dict(args)
+ if not update_data:
+ # TODO make this exception more verbose
+ raise Exception
+
+ with open(args.output_file, 'w') as writer:
+ for key, value in update_data.items():
+ _, key = os.path.split(key)
+ key = key.split()[-1]
+ value = value.replace('\"', '')
+ writer.write(f'{key}={value}\n')
+
+ print('--- Generating update info file successful ---')
+ return
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file