1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15import ast 16import os 17import shutil 18import zipfile 19 20from test.fake_data import RSA_PRIVATE_KEY_DATA 21 22UPDATER_BINARY_DATA = b"updater binary data" 23BOARD_LIST_DATA = b"""HI3516 24HI3518 25HI3559""" 26VERSION_MBN_DATA = b"""Hi3516DV300-eng 10 QP1A.190711.020 27Hi3516DV300-eng 10 QP1A.190711.021""" 28 29UPDATER_SPECIFIED_CONFIG_XML_DATA = """<?xml version="1.0"?> 30<package> 31 <head name="Component header information"> 32 <info fileVersion="01" prdID="123456" 33 softVersion="Hi3516DV300-eng 10 QP1A.190711.0VERSION_MARK" 34 date="2021-01-23" time="12:30">head info</info> 35 </head> 36 <group name = "Component information"> 37 SYSTEM_MARK 38 COMPONENT_MARK 39 </group> 40</package>""" 41UPDATER_PARTITIONS_XML_DATA = b"""<?xml version="1.0" encoding="GB2312" ?> 42<Partition_Info> 43<Part PartitionName="boot" FlashType="emmc" FileSystem="none" 44 Start="0" Length="1M"/> 45<Part PartitionName="kernel" FlashType="emmc" FileSystem="none" 46 Start="1M" Length="15M"/> 47<Part PartitionName="updater" FlashType="emmc" FileSystem="ext3/4" 48 Start="16M" Length="20M"/> 49<Part PartitionName="misc" FlashType="emmc" FileSystem="none" 50 Start="36M" Length="1M"/> 51<Part PartitionName="system" FlashType="emmc" FileSystem="ext3/4" 52 Start="37M" Length="3300M"/> 53<Part PartitionName="vendor" FlashType="emmc" FileSystem="ext3/4" 54 Start="3337M" Length="263M"/> 55<Part PartitionName="userdata" FlashType="emmc" FileSystem="ext3/4" 56 Start="3600M" Length="1464M"/> 57</Partition_Info>""" 58 59SYSTEM_COMPONENT_STR = """<component compAddr="system" compId="12" 60 resType="05" compType="0" compVer="0o00">./system.img</component>""" 61COMPONENT_STR_INC = """<component compAddr="vendor" compId="13" 62 resType="05" compType="1" compVer="0o00">./vendor.img</component>""" 63COMPONENT_STR_FULL = """<component compAddr="vendor" compId="13" 64 resType="05" compType="0" compVer="0o00">./vendor.img</component>""" 65COMPONENT_STR_USERDATA = """<component compAddr="userdata" compId="14" 66 resType="05" compType="0" compVer="0o00">./userdata.img</component>""" 67SOURCE_VERSION_STR = "20" 68TARGET_VERSION_STR = "21" 69 70 71def create_input_package( 72 package_name, package_type="target", is_su=False, 73 is_updater_partitions=False, has_userdata=False, 74 is_inc_full_none=False, is_miss_image=False, 75 is_miss_version_list=False, is_miss_updater_binary=False): 76 """ 77 Create input package. 78 :param package_name: package name 79 :param package_type: package type, source or target 80 :param is_su: Is it an updater upgrade package 81 :param is_updater_partitions: Is it an updater partitions upgrade package 82 :param has_userdata: Configuring UserData in XML 83 :param is_inc_full_none: Both full and incremental list lengths are zero 84 :param is_miss_image: Is image missing 85 :param is_miss_version_list: Is VERSION.list missing 86 :param is_miss_updater_binary: Is updater_binary missing 87 :return: 88 """ 89 # Create a folder for the input package. 90 package_name_path = "./%s" % package_name 91 if not os.path.exists(package_name_path): 92 os.mkdir(package_name_path) 93 94 if not is_miss_image: 95 create_file(os.path.join(package_name_path, "system.img"), 96 get_target_vendor_data()) 97 98 # Judge the type of input package and generate the corresponding vendor.img 99 if package_type == "target": 100 vendor_content = get_target_vendor_data() 101 elif package_type == "source": 102 vendor_content = get_source_vendor_data() 103 else: 104 print("Unknown package type!") 105 raise RuntimeError 106 if not is_miss_image: 107 create_file(os.path.join(package_name_path, "vendor.img"), 108 vendor_content) 109 if not is_miss_updater_binary: 110 create_file(os.path.join(package_name_path, "updater_binary"), 111 UPDATER_BINARY_DATA) 112 # updater upgrade package 113 if is_su: 114 create_file(os.path.join(package_name_path, "uImage"), 115 get_target_vendor_data()) 116 create_file(os.path.join(package_name_path, "updater.img"), 117 get_target_vendor_data()) 118 create_file(os.path.join(package_name_path, "updater_b.img"), 119 get_target_vendor_data()) 120 create_file(os.path.join(package_name_path, "updater_uImage"), 121 get_target_vendor_data()) 122 # Create updater_config dir. 123 updater_config_path = "./%s/updater_config" % package_name 124 if not os.path.exists(updater_config_path): 125 os.mkdir(updater_config_path) 126 create_file(os.path.join(updater_config_path, "BOARD.list"), 127 BOARD_LIST_DATA) 128 if not is_miss_version_list: 129 create_file(os.path.join(updater_config_path, "VERSION.mbn"), 130 VERSION_MBN_DATA) 131 # Judge the type of input package and 132 xml_content = \ 133 create_updater_specified_config_file( 134 has_userdata, is_updater_partitions, package_type) 135 136 if is_inc_full_none: 137 xml_content = xml_content.replace("SYSTEM_MARK", "") 138 xml_content = xml_content.replace( 139 "COMPONENT_MARK", "").encode() 140 else: 141 xml_content = xml_content.replace( 142 "SYSTEM_MARK", SYSTEM_COMPONENT_STR) 143 xml_content = xml_content.replace( 144 "COMPONENT_MARK", COMPONENT_STR_FULL).encode() 145 146 create_file( 147 os.path.join(updater_config_path, "updater_specified_config.xml"), 148 xml_content) 149 # Create partition_file.xml. 150 if is_updater_partitions: 151 create_file("./partition_file.xml", UPDATER_PARTITIONS_XML_DATA) 152 # Create rsa_private_key2048.pem. 153 create_file("./rsa_private_key2048.pem", RSA_PRIVATE_KEY_DATA) 154 # Create zip package. 155 with zipfile.ZipFile('./%s.zip' % package_name, 156 'w', zipfile.ZIP_DEFLATED) as package_zip: 157 package_zip.write(package_name_path) 158 for home, dirs, files in os.walk(package_name_path): 159 for each_file_name in files: 160 package_zip.write(os.path.join(home, each_file_name)) 161 for each_dir_name in dirs: 162 package_zip.write(os.path.join(home, each_dir_name)) 163 164 165def create_updater_specified_config_file( 166 has_userdata, is_updater_partitions, package_type): 167 """ 168 generate the corresponding updater_specified_config.xml 169 :param has_userdata: has userdata 170 :param is_updater_partitions: is updater partitions 171 :param package_type: package type 172 :return: 173 """ 174 if package_type == "target": 175 xml_content = UPDATER_SPECIFIED_CONFIG_XML_DATA.replace( 176 "VERSION_MARK", TARGET_VERSION_STR) 177 xml_content = xml_content.replace( 178 "COMPONENT_MARK", COMPONENT_STR_INC) 179 elif package_type == "source": 180 xml_content = UPDATER_SPECIFIED_CONFIG_XML_DATA.replace( 181 "VERSION_MARK", SOURCE_VERSION_STR) 182 if is_updater_partitions: 183 xml_content = xml_content.replace( 184 "COMPONENT_MARK", COMPONENT_STR_FULL) 185 elif has_userdata: 186 xml_content = xml_content.replace( 187 "COMPONENT_MARK", COMPONENT_STR_USERDATA) 188 else: 189 print("Unknown package type!") 190 raise RuntimeError 191 return xml_content 192 193 194def create_file(file_path, file_data): 195 """ 196 Create file 197 :param file_path: file path 198 :param file_data: file data 199 :return: 200 """ 201 with open(file_path, "wb") as w_f: 202 w_f.write(file_data) 203 204 205def clear_package(package_name): 206 """ 207 Clean up the constructed input package and files 208 :param package_name: constructed input package name 209 :return: 210 """ 211 if os.path.exists("./%s" % package_name): 212 shutil.rmtree("./%s" % package_name) 213 if os.path.exists("./%s.zip" % package_name): 214 os.remove("./%s.zip" % package_name) 215 if os.path.exists("./partition_file.xml"): 216 os.remove("./partition_file.xml") 217 if os.path.exists("./rsa_private_key2048.pem"): 218 os.remove("./rsa_private_key2048.pem") 219 220 221def get_source_vendor_data(): 222 """ 223 Get source vendor image file data 224 :return: 225 """ 226 with open(r"./source_vendor_data", "r") as r_f: 227 content = r_f.read() 228 return ast.literal_eval(content) 229 230 231def get_target_vendor_data(): 232 """ 233 Get target vendor image file data 234 :return: 235 """ 236 with open(r"./target_vendor_data", "r") as r_f: 237 content = r_f.read() 238 return ast.literal_eval(content) 239