18b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert#!/usr/bin/env python 28b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 38b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# Copyright (C) 2008 The Android Open Source Project 48b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 58b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# Licensed under the Apache License, Version 2.0 (the "License"); 68b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# you may not use this file except in compliance with the License. 78b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# You may obtain a copy of the License at 88b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 98b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# http://www.apache.org/licenses/LICENSE-2.0 108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# 118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# Unless required by applicable law or agreed to in writing, software 128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# distributed under the License is distributed on an "AS IS" BASIS, 138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# See the License for the specific language governing permissions and 158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert# limitations under the License. 168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" 188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertGiven a target-files zipfile, produces an OTA package that installs 198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertthat build. An incremental OTA is produced if -i is given, otherwise 208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Alberta full OTA is produced. 218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertUsage: ota_from_target_files [flags] input_target_files output_ota_package 238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert --board_config <file> 258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Deprecated. 268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -k (--package_key) <key> Key to use to sign the package (default is 288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert the value of default_system_dev_certificate from the input 298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target-files's META/misc_info.txt, or 308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "build/target/product/security/testkey" if that value is not 318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert specified). 328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert For incremental OTAs, the default value is based on the source 348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target-file, not the target build. 358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -i (--incremental_from) <file> 378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Generate an incremental OTA using the given target-files zip as 388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert the starting build. 398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4043078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao --full_radio 4143078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao When generating an incremental OTA, always include a full copy of 4243078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao radio image. This option is only meaningful when -i is specified, 4343078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao because a full radio is always included in a full OTA if applicable. 4443078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao 45aa6c1a144545b655837d024445020ecba202f0e0leozwang --full_bootloader 46aa6c1a144545b655837d024445020ecba202f0e0leozwang Similar to --full_radio. When generating an incremental OTA, always 47aa6c1a144545b655837d024445020ecba202f0e0leozwang include a full copy of bootloader image. 48aa6c1a144545b655837d024445020ecba202f0e0leozwang 498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -v (--verify) 508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Remount and verify the checksums of the files written to the 518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert system and vendor (if used) partitions. Incremental builds only. 528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 537f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh -o (--oem_settings) <main_file[,additional_files...]> 547f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh Comma seperated list of files used to specify the expected OEM-specific 557f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh properties on the OEM partition of the intended device. 567f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh Multiple expected values can be used by providing multiple files. 577f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh 588608cde944d64dece63e8c770deb78c1d092c719Tao Bao --oem_no_mount 598608cde944d64dece63e8c770deb78c1d092c719Tao Bao For devices with OEM-specific properties but without an OEM partition, 608608cde944d64dece63e8c770deb78c1d092c719Tao Bao do not mount the OEM partition in the updater-script. This should be 618608cde944d64dece63e8c770deb78c1d092c719Tao Bao very rarely used, since it's expected to have a dedicated OEM partition 628608cde944d64dece63e8c770deb78c1d092c719Tao Bao for OEM-specific properties. Only meaningful when -o is specified. 638608cde944d64dece63e8c770deb78c1d092c719Tao Bao 648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -w (--wipe_user_data) 658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Generate an OTA package that will wipe the user data partition 668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert when installed. 678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 685d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao --downgrade 695d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao Intentionally generate an incremental OTA that updates from a newer 705d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao build to an older one (based on timestamp comparison). "post-timestamp" 715d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao will be replaced by "ota-downgrade=yes" in the metadata file. A data 725d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao wipe will always be enforced, so "ota-wipe=yes" will also be included in 734996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao the metadata file. The update-binary in the source build will be used in 743e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao the OTA package, unless --binary flag is specified. Please also check the 753e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao doc for --override_timestamp below. 763e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao 773e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao --override_timestamp 783e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao Intentionally generate an incremental OTA that updates from a newer 793e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao build to an older one (based on timestamp comparison), by overriding the 803e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao timestamp in package metadata. This differs from --downgrade flag: we 813e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao know for sure this is NOT an actual downgrade case, but two builds are 823e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao cut in a reverse order. A legit use case is that we cut a new build C 833e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao (after having A and B), but want to enfore an update path of A -> C -> B. 843e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao Specifying --downgrade may not help since that would enforce a data wipe 853e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao for C -> B update. The value of "post-timestamp" will be set to the newer 863e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao timestamp plus one, so that the package can be pushed and applied. 875d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao 888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -e (--extra_script) <file> 898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Insert the contents of file at the end of the update script. 908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -2 (--two_step) 928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Generate a 'two-step' OTA package, where recovery is updated 938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert first, so that any changes made to the system partition are done 948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert using the new recovery (new kernel, etc.). 958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert --block 97457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao Generate a block-based OTA for non-A/B device. We have deprecated the 98457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao support for file-based OTA since O. Block-based OTA will be used by 99457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao default for all non-A/B devices. Keeping this flag here to not break 100457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao existing callers. 1018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -b (--binary) <file> 1038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Use the given binary as the update-binary in the output package, 1048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert instead of the binary in the build's target_files. Use for 1058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert development only. 1068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert -t (--worker_threads) <int> 1088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert Specifies the number of worker-threads that will be used when 1098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert generating patches for incremental updates (defaults to 3). 1108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1118dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao --stash_threshold <float> 1128dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao Specifies the threshold that will be used to compute the maximum 1138dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao allowed stash size (defaults to 0.8). 1149bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 1159bc6bb23b5bf64635275041fecace64635f41fbaTao Bao --gen_verify 1169bc6bb23b5bf64635275041fecace64635f41fbaTao Bao Generate an OTA package that verifies the partitions. 117d62c603573c53713164fda0430d477daa11d5e31Tao Bao 118d62c603573c53713164fda0430d477daa11d5e31Tao Bao --log_diff <file> 119d62c603573c53713164fda0430d477daa11d5e31Tao Bao Generate a log file that shows the differences in the source and target 120d62c603573c53713164fda0430d477daa11d5e31Tao Bao builds for an incremental package. This option is only meaningful when 121d62c603573c53713164fda0430d477daa11d5e31Tao Bao -i is specified. 122dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao 123dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao --payload_signer <signer> 124dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao Specify the signer when signing the payload and metadata for A/B OTAs. 125dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao By default (i.e. without this flag), it calls 'openssl pkeyutl' to sign 126dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao with the package private key. If the private key cannot be accessed 127dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao directly, a payload signer that knows how to do that should be specified. 128dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao The signer will be supplied with "-inkey <path_to_key>", 129dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-in <input_file>" and "-out <output_file>" parameters. 1302abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin 1312abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin --payload_signer_args <args> 1322abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin Specify the arguments needed for payload signer. 1338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" 1348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 13589fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Baofrom __future__ import print_function 13689fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao 1378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport sys 1388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertif sys.hexversion < 0x02070000: 14089fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("Python 2.7 or newer is required.", file=sys.stderr) 1418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert sys.exit(1) 1428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1432dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Baoimport copy 1448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport multiprocessing 1452dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Baoimport os.path 146c098e9efd989a46d5d1aa625bc899536de15eaaaTao Baoimport subprocess 1472abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddinimport shlex 1488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport tempfile 1498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport zipfile 1508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport common 1528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport edify_generator 1538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertimport sparse_img 1548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS = common.OPTIONS 1568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.package_key = None 1578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.incremental_source = None 1588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.verify = False 1598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.patch_threshold = 0.95 1608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.wipe_user_data = False 1615d1825664a0fec256fa28d62aadcac96f59a41b2Tao BaoOPTIONS.downgrade = False 1623e6161a3b33da5a46c80c79e2d815168923e83c3Tao BaoOPTIONS.timestamp = False 1638b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.extra_script = None 1648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.worker_threads = multiprocessing.cpu_count() // 2 1658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertif OPTIONS.worker_threads == 0: 1668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.worker_threads = 1 1678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.two_step = False 1688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.no_signing = False 169457cbf6a8a3c858aff5160f02f4ee220716900efTao BaoOPTIONS.block_based = True 1708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.updater_binary = None 1718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.oem_source = None 1728608cde944d64dece63e8c770deb78c1d092c719Tao BaoOPTIONS.oem_no_mount = False 1738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan AlbertOPTIONS.fallback_to_full = True 17443078aa37aa771149bfd85d10c47cce4e818b3d4Tao BaoOPTIONS.full_radio = False 175aa6c1a144545b655837d024445020ecba202f0e0leozwangOPTIONS.full_bootloader = False 176d47d8e14880132c42a75f41c8041851797c75e35Tao Bao# Stash size cannot exceed cache_size * threshold. 177d47d8e14880132c42a75f41c8041851797c75e35Tao BaoOPTIONS.cache_size = None 178d47d8e14880132c42a75f41c8041851797c75e35Tao BaoOPTIONS.stash_threshold = 0.8 1799bc6bb23b5bf64635275041fecace64635f41fbaTao BaoOPTIONS.gen_verify = False 180d62c603573c53713164fda0430d477daa11d5e31Tao BaoOPTIONS.log_diff = None 181dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao BaoOPTIONS.payload_signer = None 1822abbbd03339947327ada0becba5bd4ef41f1bdabBaligh UddinOPTIONS.payload_signer_args = [] 1835f8ff9319b086c2f2b95bded2d40700037b5003fTao BaoOPTIONS.extracted_input = None 1848dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao 1852dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao BaoMETADATA_NAME = 'META-INF/com/android/metadata' 1866b0b2f9db0c7d89a678e5b0cb9dbffbec3d96f0bTao BaoUNZIP_PATTERN = ['IMAGES/*', 'META/*'] 1876b0b2f9db0c7d89a678e5b0cb9dbffbec3d96f0bTao Bao 1882dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 1898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef SignOutput(temp_zip_name, output_zip_name): 1908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert key_passwords = common.GetKeyPasswords([OPTIONS.package_key]) 1918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert pw = key_passwords[OPTIONS.package_key] 1928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw, 1948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert whole_file=True) 1958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1977f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanhdef AppendAssertions(script, info_dict, oem_dicts=None): 1988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert oem_props = info_dict.get("oem_fingerprint_properties") 1993e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao if not oem_props: 2008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device = GetBuildProp("ro.product.device", info_dict) 2018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AssertDevice(device) 2028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 2037f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh if not oem_dicts: 2048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert raise common.ExternalError( 2058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "No OEM file provided to answer expected assertions") 2068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert for prop in oem_props.split(): 2077f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh values = [] 2087f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh for oem_dict in oem_dicts: 2097f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh if oem_dict.get(prop): 2107f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh values.append(oem_dict[prop]) 2117f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh if not values: 2128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert raise common.ExternalError( 2138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "The OEM file is missing the property %s" % prop) 2147f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh script.AssertOemProperty(prop, values) 2157f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh 2167f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh 217ebce697429c9db5ffd6ac52fc8f4bbf9cd56f9c6Tao Baodef _LoadOemDicts(script, recovery_mount_options=None): 2187f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh """Returns the list of loaded OEM properties dict.""" 2197f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = None 2207f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh if OPTIONS.oem_source is None: 2217f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh raise common.ExternalError("OEM source required for this build") 222ebce697429c9db5ffd6ac52fc8f4bbf9cd56f9c6Tao Bao if not OPTIONS.oem_no_mount and script: 2237f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh script.Mount("/oem", recovery_mount_options) 2247f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = [] 2257f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh for oem_file in OPTIONS.oem_source: 2267f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts.append(common.LoadDictionaryFromLines( 2277f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh open(oem_file).readlines())) 2287f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh return oem_dicts 2298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 231d42e97ebb45fdc5a30799a3f37e482948d318010Tao Baodef _WriteRecoveryImageToBoot(script, output_zip): 232d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao """Find and write recovery image to /boot in two-step OTA. 233d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 234d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao In two-step OTAs, we write recovery image to /boot as the first step so that 235d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao we can reboot to there and install a new recovery image to /recovery. 236d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao A special "recovery-two-step.img" will be preferred, which encodes the correct 237d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao path of "/boot". Otherwise the device may show "device is corrupt" message 238d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao when booting into /boot. 239d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 240d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao Fall back to using the regular recovery.img if the two-step recovery image 241d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao doesn't exist. Note that rebuilding the special image at this point may be 242d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao infeasible, because we don't have the desired boot signer and keys when 243d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao calling ota_from_target_files.py. 244d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao """ 245d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 246d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao recovery_two_step_img_name = "recovery-two-step.img" 247d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao recovery_two_step_img_path = os.path.join( 248d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao OPTIONS.input_tmp, "IMAGES", recovery_two_step_img_name) 249d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao if os.path.exists(recovery_two_step_img_path): 250d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao recovery_two_step_img = common.GetBootableImage( 251d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao recovery_two_step_img_name, recovery_two_step_img_name, 252d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao OPTIONS.input_tmp, "RECOVERY") 253d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao common.ZipWriteStr( 254d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao output_zip, recovery_two_step_img_name, recovery_two_step_img.data) 25589fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("two-step package: using %s in stage 1/3" % ( 25689fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao recovery_two_step_img_name,)) 257d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.WriteRawImage("/boot", recovery_two_step_img_name) 258d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao else: 25989fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("two-step package: using recovery.img in stage 1/3") 260d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # The "recovery.img" entry has been written into package earlier. 261d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.WriteRawImage("/boot", "recovery.img") 262d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 263d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 2648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef HasRecoveryPatch(target_files_zip): 265f2cffbddb9dccc6dd46ea2be0bbde387315f09c3Tao Bao namelist = [name for name in target_files_zip.namelist()] 266f2cffbddb9dccc6dd46ea2be0bbde387315f09c3Tao Bao return ("SYSTEM/recovery-from-boot.p" in namelist or 267f2cffbddb9dccc6dd46ea2be0bbde387315f09c3Tao Bao "SYSTEM/etc/recovery.img" in namelist) 2688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 269457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao 2708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef HasVendorPartition(target_files_zip): 2718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 2728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_files_zip.getinfo("VENDOR/") 2738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return True 2748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert except KeyError: 2758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return False 2768b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 277457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao 2788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef GetOemProperty(name, oem_props, oem_dict, info_dict): 2798b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if oem_props is not None and name in oem_props: 2808b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return oem_dict[name] 2818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return GetBuildProp(name, info_dict) 2828b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef CalculateFingerprint(oem_props, oem_dict, info_dict): 2858b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if oem_props is None: 2868b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return GetBuildProp("ro.build.fingerprint", info_dict) 2878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return "%s/%s/%s:%s" % ( 2888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict), 2898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict), 2908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict), 2918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert GetBuildProp("ro.build.thumbprint", info_dict)) 2928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 2947e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Baodef GetImage(which, tmpdir): 2957e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao """Returns an image object suitable for passing to BlockImageDiff. 2967e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao 2977e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao 'which' partition must be "system" or "vendor". A prebuilt image and file 2987e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao map must already exist in tmpdir. 2997e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao """ 3008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert assert which in ("system", "vendor") 3028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert path = os.path.join(tmpdir, "IMAGES", which + ".img") 3048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert mappath = os.path.join(tmpdir, "IMAGES", which + ".map") 3058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3067e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao # The image and map files must have been created prior to calling 3077e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao # ota_from_target_files.py (since LMP). 3087e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao assert os.path.exists(path) and os.path.exists(mappath) 3098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 310ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao # Bug: http://b/20939131 311ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao # In ext4 filesystems, block 0 might be changed even being mounted 312ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao # R/O. We add it to clobbered_blocks so that it will be written to the 313ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao # target unconditionally. Note that they are still part of care_map. 314ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao clobbered_blocks = "0" 315ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao 316ff7778166bd13a90c89fa333591ee2037f587a11Tao Bao return sparse_img.SparseImage(path, mappath, clobbered_blocks) 3178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 319b63c952cc72eda821532b3bcb00a66278503287eTao Baodef AddCompatibilityArchive(target_zip, output_zip, system_included=True, 320b63c952cc72eda821532b3bcb00a66278503287eTao Bao vendor_included=True): 321b63c952cc72eda821532b3bcb00a66278503287eTao Bao """Adds compatibility info from target files into the output zip. 322b63c952cc72eda821532b3bcb00a66278503287eTao Bao 323b63c952cc72eda821532b3bcb00a66278503287eTao Bao Metadata used for on-device compatibility verification is retrieved from 324b63c952cc72eda821532b3bcb00a66278503287eTao Bao target_zip then added to compatibility.zip which is added to the output_zip 325b63c952cc72eda821532b3bcb00a66278503287eTao Bao archive. 326b63c952cc72eda821532b3bcb00a66278503287eTao Bao 327b63c952cc72eda821532b3bcb00a66278503287eTao Bao Compatibility archive should only be included for devices with a vendor 328b63c952cc72eda821532b3bcb00a66278503287eTao Bao partition as checking provides value when system and vendor are independently 329b63c952cc72eda821532b3bcb00a66278503287eTao Bao versioned. 330b63c952cc72eda821532b3bcb00a66278503287eTao Bao 331b63c952cc72eda821532b3bcb00a66278503287eTao Bao Args: 332b63c952cc72eda821532b3bcb00a66278503287eTao Bao target_zip: Zip file containing the source files to be included for OTA. 333b63c952cc72eda821532b3bcb00a66278503287eTao Bao output_zip: Zip file that will be sent for OTA. 334b63c952cc72eda821532b3bcb00a66278503287eTao Bao system_included: If True, the system image will be updated and therefore 335b63c952cc72eda821532b3bcb00a66278503287eTao Bao its metadata should be included. 336b63c952cc72eda821532b3bcb00a66278503287eTao Bao vendor_included: If True, the vendor image will be updated and therefore 337b63c952cc72eda821532b3bcb00a66278503287eTao Bao its metadata should be included. 338b63c952cc72eda821532b3bcb00a66278503287eTao Bao """ 339b63c952cc72eda821532b3bcb00a66278503287eTao Bao 340b63c952cc72eda821532b3bcb00a66278503287eTao Bao # Determine what metadata we need. Files are names relative to META/. 341b63c952cc72eda821532b3bcb00a66278503287eTao Bao compatibility_files = [] 342b63c952cc72eda821532b3bcb00a66278503287eTao Bao vendor_metadata = ("vendor_manifest.xml", "vendor_matrix.xml") 343b63c952cc72eda821532b3bcb00a66278503287eTao Bao system_metadata = ("system_manifest.xml", "system_matrix.xml") 344b63c952cc72eda821532b3bcb00a66278503287eTao Bao if vendor_included: 345b63c952cc72eda821532b3bcb00a66278503287eTao Bao compatibility_files += vendor_metadata 346b63c952cc72eda821532b3bcb00a66278503287eTao Bao if system_included: 347b63c952cc72eda821532b3bcb00a66278503287eTao Bao compatibility_files += system_metadata 348b63c952cc72eda821532b3bcb00a66278503287eTao Bao 349b63c952cc72eda821532b3bcb00a66278503287eTao Bao # Create new archive. 350b63c952cc72eda821532b3bcb00a66278503287eTao Bao compatibility_archive = tempfile.NamedTemporaryFile() 351b63c952cc72eda821532b3bcb00a66278503287eTao Bao compatibility_archive_zip = zipfile.ZipFile(compatibility_archive, "w", 352b63c952cc72eda821532b3bcb00a66278503287eTao Bao compression=zipfile.ZIP_DEFLATED) 353b63c952cc72eda821532b3bcb00a66278503287eTao Bao 354b63c952cc72eda821532b3bcb00a66278503287eTao Bao # Add metadata. 355b63c952cc72eda821532b3bcb00a66278503287eTao Bao for file_name in compatibility_files: 356b63c952cc72eda821532b3bcb00a66278503287eTao Bao target_file_name = "META/" + file_name 357b63c952cc72eda821532b3bcb00a66278503287eTao Bao 358b63c952cc72eda821532b3bcb00a66278503287eTao Bao if target_file_name in target_zip.namelist(): 359b63c952cc72eda821532b3bcb00a66278503287eTao Bao data = target_zip.read(target_file_name) 360b63c952cc72eda821532b3bcb00a66278503287eTao Bao common.ZipWriteStr(compatibility_archive_zip, file_name, data) 361b63c952cc72eda821532b3bcb00a66278503287eTao Bao 362b63c952cc72eda821532b3bcb00a66278503287eTao Bao # Ensure files are written before we copy into output_zip. 363b63c952cc72eda821532b3bcb00a66278503287eTao Bao compatibility_archive_zip.close() 364b63c952cc72eda821532b3bcb00a66278503287eTao Bao 365b63c952cc72eda821532b3bcb00a66278503287eTao Bao # Only add the archive if we have any compatibility info. 366b63c952cc72eda821532b3bcb00a66278503287eTao Bao if compatibility_archive_zip.namelist(): 367b63c952cc72eda821532b3bcb00a66278503287eTao Bao common.ZipWrite(output_zip, compatibility_archive.name, 368b63c952cc72eda821532b3bcb00a66278503287eTao Bao arcname="compatibility.zip", 369b63c952cc72eda821532b3bcb00a66278503287eTao Bao compress_type=zipfile.ZIP_STORED) 370b63c952cc72eda821532b3bcb00a66278503287eTao Bao 371b63c952cc72eda821532b3bcb00a66278503287eTao Bao 3728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef WriteFullOTAPackage(input_zip, output_zip): 3738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # TODO: how to determine this? We don't know what version it will 37434b47bf42b4b9fad8e775a37e40922598bb7bd96Tao Bao # be installed on top of. For now, we expect the API just won't 37534b47bf42b4b9fad8e775a37e40922598bb7bd96Tao Bao # change very often. Similarly for fstab, it might have changed 37634b47bf42b4b9fad8e775a37e40922598bb7bd96Tao Bao # in the target build. 3778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict) 3788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 379838c68fa1ae35a4b0fd017e92728cb5720f74782Tao Bao recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options") 3803e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") 3817f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = None 3823e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao if oem_props: 3837f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = _LoadOemDicts(script, recovery_mount_options) 3847f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh 3857f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh target_fp = CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0], 3867f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh OPTIONS.info_dict) 3878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert metadata = { 38839f3eaf22135d52b87a83039355df90a56e7d85bTao Bao "post-build": target_fp, 3897f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh "pre-device": GetOemProperty("ro.product.device", oem_props, 3907f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts and oem_dicts[0], 3918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.info_dict), 3928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict), 3938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert } 3948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 3958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific = common.DeviceSpecificParams( 3968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert input_zip=input_zip, 3978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert input_version=OPTIONS.info_dict["recovery_api_version"], 3988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert output_zip=output_zip, 3998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script=script, 4008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert input_tmp=OPTIONS.input_tmp, 4018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert metadata=metadata, 4028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert info_dict=OPTIONS.info_dict) 4038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 404457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao assert HasRecoveryPatch(input_zip) 4058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 406457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao metadata["ota-type"] = "BLOCK" 407d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao 408d8a52f97859356c65b21f8aed775f685b314ca22Elliott Hughes ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict) 409d8a52f97859356c65b21f8aed775f685b314ca22Elliott Hughes ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict) 410d8a52f97859356c65b21f8aed775f685b314ca22Elliott Hughes script.AssertOlderBuild(ts, ts_text) 4118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4127f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh AppendAssertions(script, OPTIONS.info_dict, oem_dicts) 4138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.FullOTA_Assertions() 4148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Two-step package strategy (in chronological order, which is *not* 4168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # the order in which the generated script has things): 4178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # 4188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # if stage is not "2/3" or "3/3": 4198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # write recovery image to boot partition 4208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set stage to "2/3" 4218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # reboot to boot partition and restart recovery 4228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # else if stage is "2/3": 4238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # write recovery image to recovery partition 4248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set stage to "3/3" 4258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # reboot to recovery partition and restart recovery 4268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # else: 4278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # (stage must be "3/3") 4288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set stage to "" 4298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # do normal full package installation: 4308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # wipe and install system, boot image, etc. 4318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set up system to update recovery partition on first boot 4328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # complete script normally 4338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # (allow recovery to mark itself finished and reboot) 4348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert recovery_img = common.GetBootableImage("recovery.img", "recovery.img", 4368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.input_tmp, "RECOVERY") 4378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.two_step: 4388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not OPTIONS.info_dict.get("multistage_support", None): 4398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert assert False, "two-step packages not supported by this build" 4408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert fs = OPTIONS.info_dict["fstab"]["/misc"] 4418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert assert fs.fs_type.upper() == "EMMC", \ 4428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "two-step packages only supported on devices with EMMC /misc partitions" 4438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert bcb_dev = {"bcb_dev": fs.device} 4448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data) 4458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 4468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertif get_stage("%(bcb_dev)s") == "2/3" then 4478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 448d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 449d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 2/3: Write recovery image to /recovery (currently running /boot). 450d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.Comment("Stage 2/3") 4518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.WriteRawImage("/recovery", "recovery.img") 4528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 4538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertset_stage("%(bcb_dev)s", "3/3"); 4548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertreboot_now("%(bcb_dev)s", "recovery"); 4558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertelse if get_stage("%(bcb_dev)s") == "3/3" then 4568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 4578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 458d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 3/3: Make changes. 459d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.Comment("Stage 3/3") 460d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 4616c55a8adc81a3a2febd4e4a61f70cb464906e3b8Tao Bao # Dump fingerprints 4623e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao script.Print("Target: %s" % target_fp) 4636c55a8adc81a3a2febd4e4a61f70cb464906e3b8Tao Bao 4648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.FullOTA_InstallBegin() 4658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert system_progress = 0.75 4678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.wipe_user_data: 4698b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert system_progress -= 0.1 4708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if HasVendorPartition(input_zip): 4718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert system_progress -= 0.1 4728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 473d3a803e6680e86f7b4960d51ab0b620728b793caStephen Smalley # Place a copy of file_contexts.bin into the OTA package which will be used 474d3a803e6680e86f7b4960d51ab0b620728b793caStephen Smalley # by the recovery program. 4758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if "selinux_fc" in OPTIONS.info_dict: 4768b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip) 4778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options") 4798b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4808b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ShowProgress(system_progress, 0) 4818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 482457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao # Full OTA is done as an "incremental" against an empty source image. This 483457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao # has the effect of writing new data from the package to the entire 484457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao # partition, but lets us reuse the updater code that writes incrementals to 485457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao # do it. 486457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao system_tgt = GetImage("system", OPTIONS.input_tmp) 487457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao system_tgt.ResetFileMap() 488457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao system_diff = common.BlockDifference("system", system_tgt, src=None) 489457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao system_diff.WriteScript(script, output_zip) 4908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4917a5bf8a645fea21ab4f8d67f900c16692643d166Tao Bao boot_img = common.GetBootableImage( 4927a5bf8a645fea21ab4f8d67f900c16692643d166Tao Bao "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") 4938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 4948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if HasVendorPartition(input_zip): 4958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ShowProgress(0.1, 0) 4968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 497457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao vendor_tgt = GetImage("vendor", OPTIONS.input_tmp) 498457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao vendor_tgt.ResetFileMap() 499457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao vendor_diff = common.BlockDifference("vendor", vendor_tgt) 500457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao vendor_diff.WriteScript(script, output_zip) 5018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict) 5038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWriteStr(output_zip, "boot.img", boot_img.data) 5048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ShowProgress(0.05, 5) 5068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.WriteRawImage("/boot", "boot.img") 5078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ShowProgress(0.2, 10) 5098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.FullOTA_InstallEnd() 5108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.extra_script is not None: 5128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(OPTIONS.extra_script) 5138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.UnmountAll() 5158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.wipe_user_data: 5178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ShowProgress(0.1, 10) 5188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.FormatPartition("/data") 5198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.two_step: 5218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 5228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertset_stage("%(bcb_dev)s", ""); 5238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 5248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra("else\n") 525d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 526d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 1/3: Nothing to verify for full OTA. Write recovery image to /boot. 527d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.Comment("Stage 1/3") 528d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao _WriteRecoveryImageToBoot(script, output_zip) 529d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 5308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 5318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertset_stage("%(bcb_dev)s", "2/3"); 5328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertreboot_now("%(bcb_dev)s", ""); 5338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertendif; 5348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertendif; 5358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 536d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao 5375d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao script.SetProgress(1) 5385d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) 539d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao metadata["ota-required-cache"] = str(script.required_cache) 5408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert WriteMetadata(metadata, output_zip) 5418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef WritePolicyConfig(file_name, output_zip): 5448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWrite(output_zip, file_name, os.path.basename(file_name)) 5458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef WriteMetadata(metadata, output_zip): 5482dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao value = "".join(["%s=%s\n" % kv for kv in sorted(metadata.iteritems())]) 5492dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao common.ZipWriteStr(output_zip, METADATA_NAME, value, 5502dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao compress_type=zipfile.ZIP_STORED) 5518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef GetBuildProp(prop, info_dict): 5548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert """Return the fingerprint of the build of a given target-files info_dict.""" 5558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 5568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return info_dict.get("build.prop", {})[prop] 5578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert except KeyError: 5588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert raise common.ExternalError("couldn't find %s in build.prop" % (prop,)) 5598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 561b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Baodef HandleDowngradeMetadata(metadata): 562b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao # Only incremental OTAs are allowed to reach here. 563b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao assert OPTIONS.incremental_source is not None 564b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao 565b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao post_timestamp = GetBuildProp("ro.build.date.utc", OPTIONS.target_info_dict) 566b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao pre_timestamp = GetBuildProp("ro.build.date.utc", OPTIONS.source_info_dict) 567b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao is_downgrade = long(post_timestamp) < long(pre_timestamp) 568b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao 569b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao if OPTIONS.downgrade: 570b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao if not is_downgrade: 571b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao raise RuntimeError("--downgrade specified but no downgrade detected: " 572b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao "pre: %s, post: %s" % (pre_timestamp, post_timestamp)) 5733e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao metadata["ota-downgrade"] = "yes" 5743e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao elif OPTIONS.timestamp: 5753e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao if not is_downgrade: 5763e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao raise RuntimeError("--timestamp specified but no timestamp hack needed: " 5773e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao "pre: %s, post: %s" % (pre_timestamp, post_timestamp)) 5783e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao metadata["post-timestamp"] = str(long(pre_timestamp) + 1) 579b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao else: 580b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao if is_downgrade: 5813e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao raise RuntimeError("Downgrade detected based on timestamp check: " 5823e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao "pre: %s, post: %s. Need to specify --timestamp OR " 5833e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao "--downgrade to allow building the incremental." % ( 5843e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao pre_timestamp, post_timestamp)) 585b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao metadata["post-timestamp"] = post_timestamp 586b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao 587b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao 5888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): 5898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_version = OPTIONS.source_info_dict["recovery_api_version"] 5908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_version = OPTIONS.target_info_dict["recovery_api_version"] 5918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if source_version == 0: 5933e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao print("WARNING: generating edify script for a source that " 5943e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao "can't install it.") 59534b47bf42b4b9fad8e775a37e40922598bb7bd96Tao Bao script = edify_generator.EdifyGenerator( 59634b47bf42b4b9fad8e775a37e40922598bb7bd96Tao Bao source_version, OPTIONS.target_info_dict, 59734b47bf42b4b9fad8e775a37e40922598bb7bd96Tao Bao fstab=OPTIONS.source_info_dict["fstab"]) 5988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 5993806c231a9a229cbb6c2bb2cfb514ba25304c913Tao Bao recovery_mount_options = OPTIONS.source_info_dict.get( 6003806c231a9a229cbb6c2bb2cfb514ba25304c913Tao Bao "recovery_mount_options") 6013e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao source_oem_props = OPTIONS.source_info_dict.get("oem_fingerprint_properties") 6023e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao target_oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties") 6037f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = None 6047f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh if source_oem_props and target_oem_props: 6057f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = _LoadOemDicts(script, recovery_mount_options) 6063806c231a9a229cbb6c2bb2cfb514ba25304c913Tao Bao 6078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert metadata = { 6083e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao "pre-device": GetOemProperty("ro.product.device", source_oem_props, 6097f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts and oem_dicts[0], 6107f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh OPTIONS.source_info_dict), 611d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao "ota-type": "BLOCK", 6128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert } 6138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 614b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao HandleDowngradeMetadata(metadata) 6155d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao 6168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific = common.DeviceSpecificParams( 6178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_zip=source_zip, 6188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_version=source_version, 6198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_zip=target_zip, 6208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_version=target_version, 6218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert output_zip=output_zip, 6228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script=script, 6238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert metadata=metadata, 6246f0b219ac551710c724e3f344023943178cdc217Tao Bao info_dict=OPTIONS.source_info_dict) 6258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6267f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh source_fp = CalculateFingerprint(source_oem_props, oem_dicts and oem_dicts[0], 6273806c231a9a229cbb6c2bb2cfb514ba25304c913Tao Bao OPTIONS.source_info_dict) 6287f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh target_fp = CalculateFingerprint(target_oem_props, oem_dicts and oem_dicts[0], 6293806c231a9a229cbb6c2bb2cfb514ba25304c913Tao Bao OPTIONS.target_info_dict) 6308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert metadata["pre-build"] = source_fp 6318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert metadata["post-build"] = target_fp 632d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu metadata["pre-build-incremental"] = GetBuildProp( 633d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu "ro.build.version.incremental", OPTIONS.source_info_dict) 634d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu metadata["post-build-incremental"] = GetBuildProp( 635d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu "ro.build.version.incremental", OPTIONS.target_info_dict) 6368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_boot = common.GetBootableImage( 6388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", 6398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.source_info_dict) 6408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_boot = common.GetBootableImage( 6418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT") 6428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert updating_boot = (not OPTIONS.two_step and 6438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert (source_boot.data != target_boot.data)) 6448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_recovery = common.GetBootableImage( 6468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") 6478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6487e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao system_src = GetImage("system", OPTIONS.source_tmp) 6497e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao system_tgt = GetImage("system", OPTIONS.target_tmp) 6508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert blockimgdiff_version = 1 6528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.info_dict: 6538b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert blockimgdiff_version = max( 6548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert int(i) for i in 6558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(",")) 6568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 657f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao # Check the first block of the source system partition for remount R/W only 658f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao # if the filesystem is ext4. 659f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao system_src_partition = OPTIONS.source_info_dict["fstab"]["/system"] 660f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao check_first_block = system_src_partition.fs_type == "ext4" 661293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao # Disable using imgdiff for squashfs. 'imgdiff -z' expects input files to be 662293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao # in zip formats. However with squashfs, a) all files are compressed in LZ4; 663293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao # b) the blocks listed in block map may not contain all the bytes for a given 664293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao # file (because they're rounded to be 4K-aligned). 665f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao system_tgt_partition = OPTIONS.target_info_dict["fstab"]["/system"] 666f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao disable_imgdiff = (system_src_partition.fs_type == "squashfs" or 667f8acad1480a3b4479c7ddfa89df8be946d83d3edTao Bao system_tgt_partition.fs_type == "squashfs") 6688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert system_diff = common.BlockDifference("system", system_tgt, system_src, 669fc3422ad3697b5d83adfb69133f66e1623416b18Tianjie Xu check_first_block, 670293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao version=blockimgdiff_version, 671293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao disable_imgdiff=disable_imgdiff) 6728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if HasVendorPartition(target_zip): 6748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not HasVendorPartition(source_zip): 6758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert raise RuntimeError("can't generate incremental that adds /vendor") 6767e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao vendor_src = GetImage("vendor", OPTIONS.source_tmp) 6777e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao vendor_tgt = GetImage("vendor", OPTIONS.target_tmp) 678fc3422ad3697b5d83adfb69133f66e1623416b18Tianjie Xu 679fc3422ad3697b5d83adfb69133f66e1623416b18Tianjie Xu # Check first block of vendor partition for remount R/W only if 680fc3422ad3697b5d83adfb69133f66e1623416b18Tianjie Xu # disk type is ext4 681fc3422ad3697b5d83adfb69133f66e1623416b18Tianjie Xu vendor_partition = OPTIONS.source_info_dict["fstab"]["/vendor"] 682d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao check_first_block = vendor_partition.fs_type == "ext4" 683293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao disable_imgdiff = vendor_partition.fs_type == "squashfs" 6848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src, 685fc3422ad3697b5d83adfb69133f66e1623416b18Tianjie Xu check_first_block, 686293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao version=blockimgdiff_version, 687293fd135c7bc0c21b41f1782d21c26de64e8854aTao Bao disable_imgdiff=disable_imgdiff) 6888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 6898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert vendor_diff = None 6908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6917f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh AppendAssertions(script, OPTIONS.target_info_dict, oem_dicts) 6928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.IncrementalOTA_Assertions() 6938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 6948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Two-step incremental package strategy (in chronological order, 6958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # which is *not* the order in which the generated script has 6968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # things): 6978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # 6988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # if stage is not "2/3" or "3/3": 6998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # do verification on current system 7008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # write recovery image to boot partition 7018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set stage to "2/3" 7028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # reboot to boot partition and restart recovery 7038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # else if stage is "2/3": 7048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # write recovery image to recovery partition 7058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set stage to "3/3" 7068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # reboot to recovery partition and restart recovery 7078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # else: 7088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # (stage must be "3/3") 7098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # perform update: 7108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # patch system files, etc. 7118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # force full install of new boot image 7128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # set up system to update recovery partition on first boot 7138b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # complete script normally 7148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # (allow recovery to mark itself finished and reboot) 7158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 7168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.two_step: 717dd24da9ec91b74b7e3c8d1af9f1f9f792d41ac4dTao Bao if not OPTIONS.source_info_dict.get("multistage_support", None): 7188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert assert False, "two-step packages not supported by this build" 719dd24da9ec91b74b7e3c8d1af9f1f9f792d41ac4dTao Bao fs = OPTIONS.source_info_dict["fstab"]["/misc"] 7208b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert assert fs.fs_type.upper() == "EMMC", \ 7218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "two-step packages only supported on devices with EMMC /misc partitions" 7228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert bcb_dev = {"bcb_dev": fs.device} 7238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) 7248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 7258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertif get_stage("%(bcb_dev)s") == "2/3" then 7268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 727d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 728d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 2/3: Write recovery image to /recovery (currently running /boot). 729d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.Comment("Stage 2/3") 7308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra("sleep(20);\n") 7318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.WriteRawImage("/recovery", "recovery.img") 7328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 7338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertset_stage("%(bcb_dev)s", "3/3"); 7348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertreboot_now("%(bcb_dev)s", "recovery"); 7358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertelse if get_stage("%(bcb_dev)s") != "3/3" then 7368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 7378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 738d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 1/3: (a) Verify the current system. 739d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.Comment("Stage 1/3") 740d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 7416c55a8adc81a3a2febd4e4a61f70cb464906e3b8Tao Bao # Dump fingerprints 742f9023856ad04cbe866939bbdd9efcd3cecc286a3Tao Bao script.Print("Source: %s" % (source_fp,)) 743f9023856ad04cbe866939bbdd9efcd3cecc286a3Tao Bao script.Print("Target: %s" % (target_fp,)) 7446c55a8adc81a3a2febd4e4a61f70cb464906e3b8Tao Bao 7458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.Print("Verifying current system...") 7468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 7478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.IncrementalOTA_VerifyBegin() 7488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 7493e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao # When blockimgdiff version is less than 3 (non-resumable block-based OTA), 7503e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao # patching on a device that's already on the target build will damage the 7513e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao # system. Because operations like move don't check the block state, they 7523e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao # always apply the changes unconditionally. 7533e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao if blockimgdiff_version <= 2: 7543e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao if source_oem_props is None: 7558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AssertSomeFingerprint(source_fp) 7568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 7578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AssertSomeThumbprint( 7588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) 7593e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao 7603e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao else: # blockimgdiff_version > 2 7613e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao if source_oem_props is None and target_oem_props is None: 7623e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao script.AssertSomeFingerprint(source_fp, target_fp) 7633e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao elif source_oem_props is not None and target_oem_props is not None: 764838c68fa1ae35a4b0fd017e92728cb5720f74782Tao Bao script.AssertSomeThumbprint( 765838c68fa1ae35a4b0fd017e92728cb5720f74782Tao Bao GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), 766c086370440bb32501da427718a7313f12ec2c841Tao Bao GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) 7673e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao elif source_oem_props is None and target_oem_props is not None: 7683e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao script.AssertFingerprintOrThumbprint( 7693e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao source_fp, 7703e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict)) 7713e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao else: 7723e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao script.AssertFingerprintOrThumbprint( 7733e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao target_fp, 7743e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) 7758b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 776d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao # Check the required cache size (i.e. stashed blocks). 777d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao size = [] 778d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao if system_diff: 779d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao size.append(system_diff.required_cache) 780d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao if vendor_diff: 781d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao size.append(vendor_diff.required_cache) 782d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao 7838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if updating_boot: 784dd24da9ec91b74b7e3c8d1af9f1f9f792d41ac4dTao Bao boot_type, boot_device = common.GetTypeAndDevice( 785dd24da9ec91b74b7e3c8d1af9f1f9f792d41ac4dTao Bao "/boot", OPTIONS.source_info_dict) 7868b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert d = common.Difference(target_boot, source_boot) 7878b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert _, _, d = d.ComputePatch() 7888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if d is None: 7898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert include_full_boot = True 7908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWriteStr(output_zip, "boot.img", target_boot.data) 7918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 7928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert include_full_boot = False 7938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 79489fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("boot target: %d source: %d diff: %d" % ( 79589fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao target_boot.size, source_boot.size, len(d))) 7968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 7978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWriteStr(output_zip, "patch/boot.img.p", d) 7988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 7998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.PatchCheck("%s:%s:%d:%s:%d:%s" % 8008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert (boot_type, boot_device, 8018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_boot.size, source_boot.sha1, 8028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_boot.size, target_boot.sha1)) 803d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao size.append(target_boot.size) 804d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao 805d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao if size: 806d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao script.CacheFreeSpaceCheck(max(size)) 8078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8088b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.IncrementalOTA_VerifyEnd() 8098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.two_step: 811d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 1/3: (b) Write recovery image to /boot. 812d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao _WriteRecoveryImageToBoot(script, output_zip) 813d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 8148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 8158b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertset_stage("%(bcb_dev)s", "2/3"); 8168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertreboot_now("%(bcb_dev)s", ""); 8178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertelse 8188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 8198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 820d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao # Stage 3/3: Make changes. 821d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao script.Comment("Stage 3/3") 822d42e97ebb45fdc5a30799a3f37e482948d318010Tao Bao 8238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Verify the existing partitions. 824d522bdc9edbf64d15a59c6924853b2e2c8c39e90Tao Bao system_diff.WriteVerifyScript(script, touched_blocks_only=True) 8258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if vendor_diff: 826d522bdc9edbf64d15a59c6924853b2e2c8c39e90Tao Bao vendor_diff.WriteVerifyScript(script, touched_blocks_only=True) 8278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.Comment("---- start making changes here ----") 8298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.IncrementalOTA_InstallBegin() 8318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert system_diff.WriteScript(script, output_zip, 8338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert progress=0.8 if vendor_diff else 0.9) 83468658c0f4fe5420226df5849b642f98fb7f5d984Tao Bao 8358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if vendor_diff: 8368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert vendor_diff.WriteScript(script, output_zip, progress=0.1) 8378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.two_step: 8398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.ZipWriteStr(output_zip, "boot.img", target_boot.data) 8408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.WriteRawImage("/boot", "boot.img") 84189fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("writing full boot image (forced by two-step mode)") 8428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not OPTIONS.two_step: 8448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if updating_boot: 8458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if include_full_boot: 84689fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("boot image changed; including full.") 8478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.Print("Installing boot image...") 8488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.WriteRawImage("/boot", "boot.img") 8498b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 8508b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Produce the boot image by applying a patch to the current 8518b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # contents of the boot partition, and write it back to the 8528b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # partition. 85389fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("boot image changed; including patch.") 8548b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.Print("Patching boot image...") 8558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ShowProgress(0.1, 10) 8568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.ApplyPatch("%s:%s:%d:%s:%d:%s" 8578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert % (boot_type, boot_device, 8588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_boot.size, source_boot.sha1, 8598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_boot.size, target_boot.sha1), 8608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "-", 8618b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert target_boot.size, target_boot.sha1, 8628b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert source_boot.sha1, "patch/boot.img.p") 8638b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 86489fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("boot image unchanged; skipping.") 8658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Do device-specific installation (eg, write radio image). 8678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert device_specific.IncrementalOTA_InstallEnd() 8688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8698b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.extra_script is not None: 8708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(OPTIONS.extra_script) 8718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.wipe_user_data: 8738b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.Print("Erasing user data...") 8748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.FormatPartition("/data") 8755d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao metadata["ota-wipe"] = "yes" 8768b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.two_step: 8788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.AppendExtra(""" 8798b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertset_stage("%(bcb_dev)s", ""); 8808b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertendif; 8818b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertendif; 8828b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert""" % bcb_dev) 8838b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert script.SetProgress(1) 8854996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao # For downgrade OTAs, we prefer to use the update-binary in the source 8864996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao # build that is actually newer than the one in the target build. 8874996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao if OPTIONS.downgrade: 8884996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao script.AddToZip(source_zip, output_zip, input_path=OPTIONS.updater_binary) 8894996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao else: 8904996cf03d2321eef56a8163c7fc73ba9976e1021Tao Bao script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) 891d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao metadata["ota-required-cache"] = str(script.required_cache) 8928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert WriteMetadata(metadata, output_zip) 8938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 8959bc6bb23b5bf64635275041fecace64635f41fbaTao Baodef WriteVerifyPackage(input_zip, output_zip): 8969bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict) 8979bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 8989bc6bb23b5bf64635275041fecace64635f41fbaTao Bao oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") 8999bc6bb23b5bf64635275041fecace64635f41fbaTao Bao recovery_mount_options = OPTIONS.info_dict.get( 9009bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "recovery_mount_options") 9017f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = None 9023e30d97dde42416a1762c161ed7217d4e7ebf2c6Tao Bao if oem_props: 903ebce697429c9db5ffd6ac52fc8f4bbf9cd56f9c6Tao Bao oem_dicts = _LoadOemDicts(script, recovery_mount_options) 9047f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh 9057f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh target_fp = CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0], 9067f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh OPTIONS.info_dict) 9079bc6bb23b5bf64635275041fecace64635f41fbaTao Bao metadata = { 9089bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "post-build": target_fp, 9097f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh "pre-device": GetOemProperty("ro.product.device", oem_props, 9107f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts and oem_dicts[0], 9119bc6bb23b5bf64635275041fecace64635f41fbaTao Bao OPTIONS.info_dict), 9129bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict), 9139bc6bb23b5bf64635275041fecace64635f41fbaTao Bao } 9149bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9159bc6bb23b5bf64635275041fecace64635f41fbaTao Bao device_specific = common.DeviceSpecificParams( 9169bc6bb23b5bf64635275041fecace64635f41fbaTao Bao input_zip=input_zip, 9179bc6bb23b5bf64635275041fecace64635f41fbaTao Bao input_version=OPTIONS.info_dict["recovery_api_version"], 9189bc6bb23b5bf64635275041fecace64635f41fbaTao Bao output_zip=output_zip, 9199bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script=script, 9209bc6bb23b5bf64635275041fecace64635f41fbaTao Bao input_tmp=OPTIONS.input_tmp, 9219bc6bb23b5bf64635275041fecace64635f41fbaTao Bao metadata=metadata, 9229bc6bb23b5bf64635275041fecace64635f41fbaTao Bao info_dict=OPTIONS.info_dict) 9239bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9247f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh AppendAssertions(script, OPTIONS.info_dict, oem_dicts) 9259bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9269bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.Print("Verifying device images against %s..." % target_fp) 9279bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.AppendExtra("") 9289bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9299bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.Print("Verifying boot...") 9309bc6bb23b5bf64635275041fecace64635f41fbaTao Bao boot_img = common.GetBootableImage( 9319bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") 9329bc6bb23b5bf64635275041fecace64635f41fbaTao Bao boot_type, boot_device = common.GetTypeAndDevice( 9339bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "/boot", OPTIONS.info_dict) 9349bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.Verify("%s:%s:%d:%s" % ( 9359bc6bb23b5bf64635275041fecace64635f41fbaTao Bao boot_type, boot_device, boot_img.size, boot_img.sha1)) 9369bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.AppendExtra("") 9379bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9389bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.Print("Verifying recovery...") 9399bc6bb23b5bf64635275041fecace64635f41fbaTao Bao recovery_img = common.GetBootableImage( 9409bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY") 9419bc6bb23b5bf64635275041fecace64635f41fbaTao Bao recovery_type, recovery_device = common.GetTypeAndDevice( 9429bc6bb23b5bf64635275041fecace64635f41fbaTao Bao "/recovery", OPTIONS.info_dict) 9439bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.Verify("%s:%s:%d:%s" % ( 9449bc6bb23b5bf64635275041fecace64635f41fbaTao Bao recovery_type, recovery_device, recovery_img.size, recovery_img.sha1)) 9459bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.AppendExtra("") 9469bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9477e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao system_tgt = GetImage("system", OPTIONS.input_tmp) 9489bc6bb23b5bf64635275041fecace64635f41fbaTao Bao system_tgt.ResetFileMap() 9499bc6bb23b5bf64635275041fecace64635f41fbaTao Bao system_diff = common.BlockDifference("system", system_tgt, src=None) 9509bc6bb23b5bf64635275041fecace64635f41fbaTao Bao system_diff.WriteStrictVerifyScript(script) 9519bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9529bc6bb23b5bf64635275041fecace64635f41fbaTao Bao if HasVendorPartition(input_zip): 9537e0f160f30247ce234dfc563fc4f1e3a008fed20Tao Bao vendor_tgt = GetImage("vendor", OPTIONS.input_tmp) 9549bc6bb23b5bf64635275041fecace64635f41fbaTao Bao vendor_tgt.ResetFileMap() 9559bc6bb23b5bf64635275041fecace64635f41fbaTao Bao vendor_diff = common.BlockDifference("vendor", vendor_tgt, src=None) 9569bc6bb23b5bf64635275041fecace64635f41fbaTao Bao vendor_diff.WriteStrictVerifyScript(script) 9579bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9589bc6bb23b5bf64635275041fecace64635f41fbaTao Bao # Device specific partitions, such as radio, bootloader and etc. 9599bc6bb23b5bf64635275041fecace64635f41fbaTao Bao device_specific.VerifyOTA_Assertions() 9609bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9619bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.SetProgress(1.0) 9629bc6bb23b5bf64635275041fecace64635f41fbaTao Bao script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) 963d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao metadata["ota-required-cache"] = str(script.required_cache) 9649bc6bb23b5bf64635275041fecace64635f41fbaTao Bao WriteMetadata(metadata, output_zip) 9659bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 9669bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 967c098e9efd989a46d5d1aa625bc899536de15eaaaTao Baodef WriteABOTAPackageWithBrilloScript(target_file, output_file, 968c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao source_file=None): 969c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao """Generate an Android OTA package that has A/B update payload.""" 970c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 9712dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao def ComputeStreamingMetadata(zip_file, reserve_space=False, 9722dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao expected_length=None): 9732dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao """Compute the streaming metadata for a given zip. 9742dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 9752dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao When 'reserve_space' is True, we reserve extra space for the offset and 9762dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao length of the metadata entry itself, although we don't know the final 9772dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao values until the package gets signed. This function will be called again 9782dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao after signing. We then write the actual values and pad the string to the 9792dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao length we set earlier. Note that we can't use the actual length of the 9802dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao metadata entry in the second run. Otherwise the offsets for other entries 9812dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao will be changing again. 9822dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao """ 983c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 984c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao def ComputeEntryOffsetSize(name): 985c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao """Compute the zip entry offset and size.""" 986c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao info = zip_file.getinfo(name) 987c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao offset = info.header_offset + len(info.FileHeader()) 988c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao size = info.file_size 9892dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao return '%s:%d:%d' % (os.path.basename(name), offset, size) 990c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 991c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao # payload.bin and payload_properties.txt must exist. 992c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao offsets = [ComputeEntryOffsetSize('payload.bin'), 993c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao ComputeEntryOffsetSize('payload_properties.txt')] 994c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 995c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao # care_map.txt is available only if dm-verity is enabled. 996c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao if 'care_map.txt' in zip_file.namelist(): 997c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao offsets.append(ComputeEntryOffsetSize('care_map.txt')) 9982dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 999b63c952cc72eda821532b3bcb00a66278503287eTao Bao if 'compatibility.zip' in zip_file.namelist(): 1000b63c952cc72eda821532b3bcb00a66278503287eTao Bao offsets.append(ComputeEntryOffsetSize('compatibility.zip')) 1001b63c952cc72eda821532b3bcb00a66278503287eTao Bao 10022dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # 'META-INF/com/android/metadata' is required. We don't know its actual 10032dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # offset and length (as well as the values for other entries). So we 10042dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # reserve 10-byte as a placeholder, which is to cover the space for metadata 10052dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # entry ('xx:xxx', since it's ZIP_STORED which should appear at the 10062dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # beginning of the zip), as well as the possible value changes in other 10072dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # entries. 10082dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao if reserve_space: 10092dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao offsets.append('metadata:' + ' ' * 10) 10102dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao else: 10112dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao offsets.append(ComputeEntryOffsetSize(METADATA_NAME)) 10122dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 10132dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao value = ','.join(offsets) 10142dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao if expected_length is not None: 10152dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao assert len(value) <= expected_length, \ 10162dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 'Insufficient reserved space: reserved=%d, actual=%d' % ( 10172dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao expected_length, len(value)) 10182dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao value += ' ' * (expected_length - len(value)) 10192dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao return value 1020c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 1021d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo # The place where the output from the subprocess should go. 1022d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE 1023d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo 1024c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # Setup signing keys. 1025c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if OPTIONS.package_key is None: 1026c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao OPTIONS.package_key = OPTIONS.info_dict.get( 1027c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "default_system_dev_certificate", 1028c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "build/target/product/security/testkey") 1029c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1030dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao # A/B updater expects a signing key in RSA format. Gets the key ready for 1031dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao # later use in step 3, unless a payload_signer has been specified. 1032dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao if OPTIONS.payload_signer is None: 1033dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao cmd = ["openssl", "pkcs8", 1034dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-in", OPTIONS.package_key + OPTIONS.private_key_suffix, 1035dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-inform", "DER", "-nocrypt"] 1036dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao rsa_key = common.MakeTempFile(prefix="key-", suffix=".key") 1037dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao cmd.extend(["-out", rsa_key]) 10386047c24faea772eabe2eaad96087290f47720c75Tao Bao p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 10396047c24faea772eabe2eaad96087290f47720c75Tao Bao p1.communicate() 1040dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao assert p1.returncode == 0, "openssl pkcs8 failed" 1041dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao 1042dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao # Stage the output zip package for package signing. 1043c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao temp_zip_file = tempfile.NamedTemporaryFile() 1044c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao output_zip = zipfile.ZipFile(temp_zip_file, "w", 1045c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao compression=zipfile.ZIP_DEFLATED) 1046c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1047c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # Metadata to comply with Android OTA package format. 1048c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties", None) 10497f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts = None 1050c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if oem_props: 1051ebce697429c9db5ffd6ac52fc8f4bbf9cd56f9c6Tao Bao oem_dicts = _LoadOemDicts(None) 1052c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1053c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao metadata = { 10547f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh "post-build": CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0], 1055c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao OPTIONS.info_dict), 1056d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu "post-build-incremental" : GetBuildProp("ro.build.version.incremental", 1057d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu OPTIONS.info_dict), 10587f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh "pre-device": GetOemProperty("ro.product.device", oem_props, 10597f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts and oem_dicts[0], 1060c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao OPTIONS.info_dict), 1061d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao "ota-required-cache": "0", 1062d8d14bec0d9fb604060634729b4a09c7898d0c9aTao Bao "ota-type": "AB", 1063c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao } 1064c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1065c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if source_file is not None: 10667f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh metadata["pre-build"] = CalculateFingerprint(oem_props, 10677f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh oem_dicts and oem_dicts[0], 1068c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao OPTIONS.source_info_dict) 1069d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu metadata["pre-build-incremental"] = GetBuildProp( 1070d06f07eef48005a3fa99fdd0ca5380d60c5ae459Tianjie Xu "ro.build.version.incremental", OPTIONS.source_info_dict) 1071c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1072b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao HandleDowngradeMetadata(metadata) 1073b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao else: 1074b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao metadata["post-timestamp"] = GetBuildProp( 1075b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao "ro.build.date.utc", OPTIONS.info_dict) 1076b31892e5de3259e5bcce3b43399f9fa7f723f81dTao Bao 1077c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # 1. Generate payload. 1078c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao payload_file = common.MakeTempFile(prefix="payload-", suffix=".bin") 1079c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao cmd = ["brillo_update_payload", "generate", 1080c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--payload", payload_file, 1081c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--target_image", target_file] 1082c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if source_file is not None: 1083c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao cmd.extend(["--source_image", source_file]) 1084d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 1085d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1.communicate() 1086c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao assert p1.returncode == 0, "brillo_update_payload generate failed" 1087c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1088c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # 2. Generate hashes of the payload and metadata files. 1089c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin") 1090c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin") 1091c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao cmd = ["brillo_update_payload", "hash", 1092c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--unsigned_payload", payload_file, 1093c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--signature_size", "256", 1094c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--metadata_hash_file", metadata_sig_file, 1095c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--payload_hash_file", payload_sig_file] 1096d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 1097d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1.communicate() 1098c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao assert p1.returncode == 0, "brillo_update_payload hash failed" 1099c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1100c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # 3. Sign the hashes and insert them back into the payload file. 1101c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao signed_payload_sig_file = common.MakeTempFile(prefix="signed-sig-", 1102c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao suffix=".bin") 1103c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao signed_metadata_sig_file = common.MakeTempFile(prefix="signed-sig-", 1104c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao suffix=".bin") 1105c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # 3a. Sign the payload hash. 1106dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao if OPTIONS.payload_signer is not None: 11072abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin cmd = [OPTIONS.payload_signer] 11082abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin cmd.extend(OPTIONS.payload_signer_args) 1109dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao else: 1110dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao cmd = ["openssl", "pkeyutl", "-sign", 1111dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-inkey", rsa_key, 1112dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-pkeyopt", "digest:sha256"] 1113dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao cmd.extend(["-in", payload_sig_file, 1114dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-out", signed_payload_sig_file]) 1115d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 1116d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1.communicate() 1117c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao assert p1.returncode == 0, "openssl sign payload failed" 1118c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1119c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # 3b. Sign the metadata hash. 1120dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao if OPTIONS.payload_signer is not None: 11212abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin cmd = [OPTIONS.payload_signer] 11222abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin cmd.extend(OPTIONS.payload_signer_args) 1123dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao else: 1124dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao cmd = ["openssl", "pkeyutl", "-sign", 1125dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-inkey", rsa_key, 1126dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-pkeyopt", "digest:sha256"] 1127dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao cmd.extend(["-in", metadata_sig_file, 1128dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "-out", signed_metadata_sig_file]) 1129d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 1130d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1.communicate() 1131c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao assert p1.returncode == 0, "openssl sign metadata failed" 1132c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1133c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # 3c. Insert the signatures back into the payload file. 1134c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao signed_payload_file = common.MakeTempFile(prefix="signed-payload-", 1135c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao suffix=".bin") 1136c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao cmd = ["brillo_update_payload", "sign", 1137c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--unsigned_payload", payload_file, 1138c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--payload", signed_payload_file, 1139c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--signature_size", "256", 1140c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--metadata_signature_file", signed_metadata_sig_file, 1141c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao "--payload_signature_file", signed_payload_sig_file] 1142d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 1143d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1.communicate() 1144c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao assert p1.returncode == 0, "brillo_update_payload sign failed" 1145c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 114619241c11bd1cf039bcd74859426ad22282849912Alex Deymo # 4. Dump the signed payload properties. 114719241c11bd1cf039bcd74859426ad22282849912Alex Deymo properties_file = common.MakeTempFile(prefix="payload-properties-", 114819241c11bd1cf039bcd74859426ad22282849912Alex Deymo suffix=".txt") 114919241c11bd1cf039bcd74859426ad22282849912Alex Deymo cmd = ["brillo_update_payload", "properties", 115019241c11bd1cf039bcd74859426ad22282849912Alex Deymo "--payload", signed_payload_file, 115119241c11bd1cf039bcd74859426ad22282849912Alex Deymo "--properties_file", properties_file] 1152d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT) 1153d8d96ecdaebbccc003a5de6a7b90661d4de016abAlex Deymo p1.communicate() 115419241c11bd1cf039bcd74859426ad22282849912Alex Deymo assert p1.returncode == 0, "brillo_update_payload properties failed" 115519241c11bd1cf039bcd74859426ad22282849912Alex Deymo 11567c5dc578b3b683c3fc02c32b76562f7f2fcb6dbdTao Bao if OPTIONS.wipe_user_data: 11577c5dc578b3b683c3fc02c32b76562f7f2fcb6dbdTao Bao with open(properties_file, "a") as f: 11587c5dc578b3b683c3fc02c32b76562f7f2fcb6dbdTao Bao f.write("POWERWASH=1\n") 11597c5dc578b3b683c3fc02c32b76562f7f2fcb6dbdTao Bao metadata["ota-wipe"] = "yes" 11607c5dc578b3b683c3fc02c32b76562f7f2fcb6dbdTao Bao 1161c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao # Add the signed payload file and properties into the zip. In order to 1162c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao # support streaming, we pack payload.bin, payload_properties.txt and 1163c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao # care_map.txt as ZIP_STORED. So these entries can be read directly with 1164c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao # the offset and length pairs. 1165c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao common.ZipWrite(output_zip, signed_payload_file, arcname="payload.bin", 1166c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao compress_type=zipfile.ZIP_STORED) 1167c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao common.ZipWrite(output_zip, properties_file, 1168c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao arcname="payload_properties.txt", 1169c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao compress_type=zipfile.ZIP_STORED) 1170c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1171cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu # If dm-verity is supported for the device, copy contents of care_map 1172cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu # into A/B OTA package. 1173b63c952cc72eda821532b3bcb00a66278503287eTao Bao target_zip = zipfile.ZipFile(target_file, "r") 1174cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu if OPTIONS.info_dict.get("verity") == "true": 1175cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu care_map_path = "META/care_map.txt" 1176cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu namelist = target_zip.namelist() 1177cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu if care_map_path in namelist: 1178cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu care_map_data = target_zip.read(care_map_path) 1179c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao common.ZipWriteStr(output_zip, "care_map.txt", care_map_data, 1180c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao compress_type=zipfile.ZIP_STORED) 1181cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu else: 118289fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("Warning: cannot find care map file in target_file package") 1183b63c952cc72eda821532b3bcb00a66278503287eTao Bao 1184b63c952cc72eda821532b3bcb00a66278503287eTao Bao if HasVendorPartition(target_zip): 1185b63c952cc72eda821532b3bcb00a66278503287eTao Bao update_vendor = True 1186b63c952cc72eda821532b3bcb00a66278503287eTao Bao update_system = True 1187b63c952cc72eda821532b3bcb00a66278503287eTao Bao 1188b63c952cc72eda821532b3bcb00a66278503287eTao Bao # If incremental then figure out what is being updated so metadata only for 1189b63c952cc72eda821532b3bcb00a66278503287eTao Bao # the updated image is included. 1190b63c952cc72eda821532b3bcb00a66278503287eTao Bao if source_file is not None: 1191b63c952cc72eda821532b3bcb00a66278503287eTao Bao input_tmp, input_zip = common.UnzipTemp( 1192b63c952cc72eda821532b3bcb00a66278503287eTao Bao target_file, UNZIP_PATTERN) 1193b63c952cc72eda821532b3bcb00a66278503287eTao Bao source_tmp, source_zip = common.UnzipTemp( 1194b63c952cc72eda821532b3bcb00a66278503287eTao Bao source_file, UNZIP_PATTERN) 1195b63c952cc72eda821532b3bcb00a66278503287eTao Bao 1196b63c952cc72eda821532b3bcb00a66278503287eTao Bao vendor_src = GetImage("vendor", source_tmp) 1197b63c952cc72eda821532b3bcb00a66278503287eTao Bao vendor_tgt = GetImage("vendor", input_tmp) 1198b63c952cc72eda821532b3bcb00a66278503287eTao Bao system_src = GetImage("system", source_tmp) 1199b63c952cc72eda821532b3bcb00a66278503287eTao Bao system_tgt = GetImage("system", input_tmp) 1200b63c952cc72eda821532b3bcb00a66278503287eTao Bao 1201b63c952cc72eda821532b3bcb00a66278503287eTao Bao update_system = system_src.TotalSha1() != system_tgt.TotalSha1() 1202b63c952cc72eda821532b3bcb00a66278503287eTao Bao update_vendor = vendor_src.TotalSha1() != vendor_tgt.TotalSha1() 1203b63c952cc72eda821532b3bcb00a66278503287eTao Bao 1204b63c952cc72eda821532b3bcb00a66278503287eTao Bao input_zip.close() 1205b63c952cc72eda821532b3bcb00a66278503287eTao Bao source_zip.close() 1206b63c952cc72eda821532b3bcb00a66278503287eTao Bao 1207b63c952cc72eda821532b3bcb00a66278503287eTao Bao target_zip = zipfile.ZipFile(target_file, "r") 1208b63c952cc72eda821532b3bcb00a66278503287eTao Bao AddCompatibilityArchive(target_zip, output_zip, update_system, 1209b63c952cc72eda821532b3bcb00a66278503287eTao Bao update_vendor) 1210b63c952cc72eda821532b3bcb00a66278503287eTao Bao common.ZipClose(target_zip) 1211cfa86223d62a6afa0eb8f5a1a215e985bb0a8c89Tianjie Xu 12122dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # Write the current metadata entry with placeholders. 12132dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao metadata['ota-streaming-property-files'] = ComputeStreamingMetadata( 12142dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao output_zip, reserve_space=True) 12152dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao WriteMetadata(metadata, output_zip) 1216c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao common.ZipClose(output_zip) 1217c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 12182dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # SignOutput(), which in turn calls signapk.jar, will possibly reorder the 12192dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # zip entries, as well as padding the entry headers. We do a preliminary 12202dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # signing (with an incomplete metadata entry) to allow that to happen. Then 12212dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # compute the zip entry offsets, write back the final metadata and do the 12222dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # final signing. 12232dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao prelim_signing = tempfile.NamedTemporaryFile() 12242dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao SignOutput(temp_zip_file.name, prelim_signing.name) 12252dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao common.ZipClose(temp_zip_file) 12262dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 12272dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # Open the signed zip. Compute the final metadata that's needed for streaming. 12282dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao prelim_zip = zipfile.ZipFile(prelim_signing, "r", 1229c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao compression=zipfile.ZIP_DEFLATED) 12302dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao expected_length = len(metadata['ota-streaming-property-files']) 1231bfdcb1257cbb1acd91fe546b7c91a3277154211aTao Bao metadata['ota-streaming-property-files'] = ComputeStreamingMetadata( 12322dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao prelim_zip, reserve_space=False, expected_length=expected_length) 12332dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 12342dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # Copy the zip entries, as we cannot update / delete entries with zipfile. 12352dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao final_signing = tempfile.NamedTemporaryFile() 12362dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao output_zip = zipfile.ZipFile(final_signing, "w", 12372dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao compression=zipfile.ZIP_DEFLATED) 12382dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao for item in prelim_zip.infolist(): 12392dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao if item.filename == METADATA_NAME: 12402dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao continue 12412dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao 12422dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao data = prelim_zip.read(item.filename) 12432dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao out_info = copy.copy(item) 12442dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao common.ZipWriteStr(output_zip, out_info, data) 1245c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 12462dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # Now write the final metadata entry. 1247c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao WriteMetadata(metadata, output_zip) 12482dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao common.ZipClose(prelim_zip) 1249c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao common.ZipClose(output_zip) 1250c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 12512dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # Re-sign the package after updating the metadata entry. 12522dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao SignOutput(final_signing.name, output_file) 12532dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao final_signing.close() 1254c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 12552dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao # Reopen the final signed zip to double check the streaming metadata. 1256c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao output_zip = zipfile.ZipFile(output_file, "r") 12572dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao actual = metadata['ota-streaming-property-files'].strip() 12582dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao expected = ComputeStreamingMetadata(output_zip) 12592dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao assert actual == expected, \ 12602dd1c4837712a1ec3f5c9dc7d861247894a1eb4fTao Bao "Mismatching streaming metadata: %s vs %s." % (actual, expected) 1261c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao common.ZipClose(output_zip) 1262c96316c89b6b4fdcccdb46c8a39c79eb62468fffTao Bao 1263c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 12648b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertdef main(argv): 12658b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 12668b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert def option_handler(o, a): 12678b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if o == "--board_config": 12688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert pass # deprecated 12698b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-k", "--package_key"): 12708b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.package_key = a 12718b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-i", "--incremental_from"): 12728b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.incremental_source = a 127343078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao elif o == "--full_radio": 127443078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao OPTIONS.full_radio = True 1275aa6c1a144545b655837d024445020ecba202f0e0leozwang elif o == "--full_bootloader": 1276aa6c1a144545b655837d024445020ecba202f0e0leozwang OPTIONS.full_bootloader = True 12778b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-w", "--wipe_user_data"): 12788b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.wipe_user_data = True 12795d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao elif o == "--downgrade": 12805d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao OPTIONS.downgrade = True 12815d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao OPTIONS.wipe_user_data = True 12823e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao elif o == "--override_timestamp": 12833e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao OPTIONS.timestamp = True 12848b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-o", "--oem_settings"): 12857f804ba71fd5fa32e6d9735ec2544075a63b9684Alain Vongsouvanh OPTIONS.oem_source = a.split(',') 12868608cde944d64dece63e8c770deb78c1d092c719Tao Bao elif o == "--oem_no_mount": 12878608cde944d64dece63e8c770deb78c1d092c719Tao Bao OPTIONS.oem_no_mount = True 12888b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-e", "--extra_script"): 12898b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.extra_script = a 12908b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-t", "--worker_threads"): 12918b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if a.isdigit(): 12928b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.worker_threads = int(a) 12938b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 12948b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert raise ValueError("Cannot parse value %r for option %r - only " 12958b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "integers are allowed." % (a, o)) 12968b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-2", "--two_step"): 12978b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.two_step = True 12988b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o == "--no_signing": 12998b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.no_signing = True 13008b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o == "--verify": 13018b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.verify = True 13028b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o == "--block": 13038b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.block_based = True 13048b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("-b", "--binary"): 13058b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.updater_binary = a 13068b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert elif o in ("--no_fallback_to_full",): 13078b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.fallback_to_full = False 13088dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao elif o == "--stash_threshold": 13098dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao try: 13108dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao OPTIONS.stash_threshold = float(a) 13118dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao except ValueError: 13128dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao raise ValueError("Cannot parse value %r for option %r - expecting " 13138dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao "a float" % (a, o)) 13149bc6bb23b5bf64635275041fecace64635f41fbaTao Bao elif o == "--gen_verify": 13159bc6bb23b5bf64635275041fecace64635f41fbaTao Bao OPTIONS.gen_verify = True 1316d62c603573c53713164fda0430d477daa11d5e31Tao Bao elif o == "--log_diff": 1317d62c603573c53713164fda0430d477daa11d5e31Tao Bao OPTIONS.log_diff = a 1318dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao elif o == "--payload_signer": 1319dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao OPTIONS.payload_signer = a 13202abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin elif o == "--payload_signer_args": 13212abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin OPTIONS.payload_signer_args = shlex.split(a) 1322cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen elif o == "--extracted_input_target_files": 1323cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.extracted_input = a 13248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 13258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return False 13268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert return True 13278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 13288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert args = common.ParseOptions(argv, __doc__, 13292a0d1da4d9c064e8cefd581aea9031aa9e79a3beTao Bao extra_opts="b:k:i:d:we:t:2o:", 13308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert extra_long_opts=[ 13318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "board_config=", 13328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "package_key=", 13338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "incremental_from=", 133443078aa37aa771149bfd85d10c47cce4e818b3d4Tao Bao "full_radio", 1335aa6c1a144545b655837d024445020ecba202f0e0leozwang "full_bootloader", 13368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "wipe_user_data", 13375d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao "downgrade", 13383e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao "override_timestamp", 13398b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "extra_script=", 13408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "worker_threads=", 13418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "two_step", 13428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "no_signing", 13438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "block", 13448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "binary=", 13458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "oem_settings=", 13468608cde944d64dece63e8c770deb78c1d092c719Tao Bao "oem_no_mount", 13478b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "verify", 13488b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert "no_fallback_to_full", 13498dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao "stash_threshold=", 1350d62c603573c53713164fda0430d477daa11d5e31Tao Bao "gen_verify", 1351d62c603573c53713164fda0430d477daa11d5e31Tao Bao "log_diff=", 1352dea0f8bfed01fa620d23d7dd8ff533246f26e8a0Tao Bao "payload_signer=", 13532abbbd03339947327ada0becba5bd4ef41f1bdabBaligh Uddin "payload_signer_args=", 1354cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen "extracted_input_target_files=", 13558b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert ], extra_option_handler=option_handler) 13568b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 13578b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if len(args) != 2: 13588b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.Usage(__doc__) 13598b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert sys.exit(1) 13608b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 13615d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao if OPTIONS.downgrade: 13625d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao # Sanity check to enforce a data wipe. 13635d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao if not OPTIONS.wipe_user_data: 13645d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao raise ValueError("Cannot downgrade without a data wipe") 13655d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao 13665d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao # We should only allow downgrading incrementals (as opposed to full). 13675d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao # Otherwise the device may go back from arbitrary build with this full 13685d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao # OTA package. 13695d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao if OPTIONS.incremental_source is None: 1370d8a52f97859356c65b21f8aed775f685b314ca22Elliott Hughes raise ValueError("Cannot generate downgradable full OTAs") 13715d1825664a0fec256fa28d62aadcac96f59a41b2Tao Bao 13723e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao assert not (OPTIONS.downgrade and OPTIONS.timestamp), \ 13733e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao "Cannot have --downgrade AND --override_timestamp both" 13743e6161a3b33da5a46c80c79e2d815168923e83c3Tao Bao 1375c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # Load the dict file from the zip directly to have a peek at the OTA type. 1376c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao # For packages using A/B update, unzipping is not needed. 1377cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen if OPTIONS.extracted_input is not None: 1378cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.extracted_input, OPTIONS.extracted_input) 1379cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen else: 1380cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen input_zip = zipfile.ZipFile(args[0], "r") 1381cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.info_dict = common.LoadInfoDict(input_zip) 1382cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen common.ZipClose(input_zip) 1383c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1384c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao ab_update = OPTIONS.info_dict.get("ab_update") == "true" 1385c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1386c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if ab_update: 1387c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if OPTIONS.incremental_source is not None: 1388c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao OPTIONS.target_info_dict = OPTIONS.info_dict 1389c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao source_zip = zipfile.ZipFile(OPTIONS.incremental_source, "r") 1390c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao OPTIONS.source_info_dict = common.LoadInfoDict(source_zip) 1391c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao common.ZipClose(source_zip) 1392c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1393c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if OPTIONS.verbose: 139489fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("--- target info ---") 1395c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao common.DumpInfoDict(OPTIONS.info_dict) 1396c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1397c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if OPTIONS.incremental_source is not None: 139889fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("--- source info ---") 1399c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao common.DumpInfoDict(OPTIONS.source_info_dict) 1400c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 1401c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao WriteABOTAPackageWithBrilloScript( 1402c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao target_file=args[0], 1403c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao output_file=args[1], 1404c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao source_file=OPTIONS.incremental_source) 1405c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 140689fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("done.") 1407c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao return 1408c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao 14098b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.extra_script is not None: 14108b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.extra_script = open(OPTIONS.extra_script).read() 14118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1412cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen if OPTIONS.extracted_input is not None: 1413cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.input_tmp = OPTIONS.extracted_input 1414cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.target_tmp = OPTIONS.input_tmp 1415cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, OPTIONS.input_tmp) 1416cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen input_zip = zipfile.ZipFile(args[0], "r") 1417cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen else: 1418cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen print("unzipping target target-files...") 1419cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.input_tmp, input_zip = common.UnzipTemp( 1420cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen args[0], UNZIP_PATTERN) 14218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1422cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.target_tmp = OPTIONS.input_tmp 1423cea5cd210e5c0251025e5125215fa1fab1d18dfbDan Willemsen OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.target_tmp) 14248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 14258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.verbose: 142689fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("--- target info ---") 14278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.DumpInfoDict(OPTIONS.info_dict) 14288b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 14298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # If the caller explicitly specified the device-specific extensions 14308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # path via -s/--device_specific, use that. Otherwise, use 14318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # META/releasetools.py if it is present in the target target_files. 14328b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # Otherwise, take the path of the file from 'tool_extensions' in the 14338b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # info dict and look for that in the local filesystem, relative to 14348b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert # the current directory. 14358b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 14368b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.device_specific is None: 14378b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") 14388b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if os.path.exists(from_input): 143989fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("(using device-specific extensions from target_files)") 14408b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.device_specific = from_input 14418b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert else: 14428b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None) 14438b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 14448b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if OPTIONS.device_specific is not None: 14458b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) 14468b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1447c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if OPTIONS.info_dict.get("no_recovery") == "true": 1448db45efa64764c1de5c007384ab172ad817e1d295Tao Bao raise common.ExternalError( 1449db45efa64764c1de5c007384ab172ad817e1d295Tao Bao "--- target build has specified no recovery ---") 1450db45efa64764c1de5c007384ab172ad817e1d295Tao Bao 1451767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao # Use the default key to sign the package if not specified with package_key. 1452767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao if not OPTIONS.no_signing: 1453767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao if OPTIONS.package_key is None: 1454767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.package_key = OPTIONS.info_dict.get( 1455767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao "default_system_dev_certificate", 1456767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao "build/target/product/security/testkey") 1457767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao 1458767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao # Set up the output zip. Create a temporary zip file if signing is needed. 1459767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao if OPTIONS.no_signing: 1460767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao if os.path.exists(args[1]): 1461767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao os.unlink(args[1]) 1462767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao output_zip = zipfile.ZipFile(args[1], "w", 1463767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao compression=zipfile.ZIP_DEFLATED) 1464767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao else: 1465767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao temp_zip_file = tempfile.NamedTemporaryFile() 1466767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao output_zip = zipfile.ZipFile(temp_zip_file, "w", 1467767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao compression=zipfile.ZIP_DEFLATED) 14688b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 146940ef35b9e916163bc408d6d9945f92f012885d33Daniel Rosenberg # Non A/B OTAs rely on /cache partition to store temporary files. 1470767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao cache_size = OPTIONS.info_dict.get("cache_size", None) 1471c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao if cache_size is None: 147289fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("--- can't determine the cache partition size ---") 1473767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.cache_size = cache_size 14748b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 14759bc6bb23b5bf64635275041fecace64635f41fbaTao Bao # Generate a verify package. 14769bc6bb23b5bf64635275041fecace64635f41fbaTao Bao if OPTIONS.gen_verify: 14779bc6bb23b5bf64635275041fecace64635f41fbaTao Bao WriteVerifyPackage(input_zip, output_zip) 14789bc6bb23b5bf64635275041fecace64635f41fbaTao Bao 1479767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao # Generate a full OTA. 14809bc6bb23b5bf64635275041fecace64635f41fbaTao Bao elif OPTIONS.incremental_source is None: 1481c098e9efd989a46d5d1aa625bc899536de15eaaaTao Bao WriteFullOTAPackage(input_zip, output_zip) 14828dcf738234d2701ad907fc14cfe0ce8fb760b8b0Tao Bao 1483767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao # Generate an incremental OTA. It will fall back to generate a full OTA on 1484767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao # failure unless no_fallback_to_full is specified. 1485767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao else: 148689fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("unzipping source target-files...") 1487767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.source_tmp, source_zip = common.UnzipTemp( 14886b0b2f9db0c7d89a678e5b0cb9dbffbec3d96f0bTao Bao OPTIONS.incremental_source, 1489457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao UNZIP_PATTERN) 1490767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.target_info_dict = OPTIONS.info_dict 1491767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.source_info_dict = common.LoadInfoDict(source_zip, 1492767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.source_tmp) 1493767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao if OPTIONS.verbose: 149489fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("--- source info ---") 1495767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao common.DumpInfoDict(OPTIONS.source_info_dict) 1496767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao try: 1497457cbf6a8a3c858aff5160f02f4ee220716900efTao Bao WriteBlockIncrementalOTAPackage(input_zip, source_zip, output_zip) 1498d62c603573c53713164fda0430d477daa11d5e31Tao Bao if OPTIONS.log_diff: 1499d62c603573c53713164fda0430d477daa11d5e31Tao Bao out_file = open(OPTIONS.log_diff, 'w') 1500d62c603573c53713164fda0430d477daa11d5e31Tao Bao import target_files_diff 1501d62c603573c53713164fda0430d477daa11d5e31Tao Bao target_files_diff.recursiveDiff('', 1502d62c603573c53713164fda0430d477daa11d5e31Tao Bao OPTIONS.source_tmp, 1503d62c603573c53713164fda0430d477daa11d5e31Tao Bao OPTIONS.input_tmp, 1504d62c603573c53713164fda0430d477daa11d5e31Tao Bao out_file) 1505d62c603573c53713164fda0430d477daa11d5e31Tao Bao out_file.close() 1506767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao except ValueError: 1507767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao if not OPTIONS.fallback_to_full: 1508767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao raise 150989fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("--- failed to build incremental; falling back to full ---") 1510767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao OPTIONS.incremental_source = None 15118b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert WriteFullOTAPackage(input_zip, output_zip) 15128b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1513767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao common.ZipClose(output_zip) 15148b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 1515767e3ac246c03a72834f80413ebcd7dceea4fc0bTao Bao # Sign the generated zip package unless no_signing is specified. 15168b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert if not OPTIONS.no_signing: 15178b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert SignOutput(temp_zip_file.name, args[1]) 15188b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert temp_zip_file.close() 15198b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 152089fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("done.") 15218b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 15228b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert 15238b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albertif __name__ == '__main__': 15248b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert try: 15258b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.CloseInheritedPipes() 15268b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert main(sys.argv[1:]) 15278b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert except common.ExternalError as e: 152889fbb0f6d586b4111b9207438d5d047ba0ad6d5fTao Bao print("\n ERROR: %s\n" % (e,)) 15298b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert sys.exit(1) 15308b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert finally: 15318b72aefb5a8ed4da28c6f83854e8babf53b9cb53Dan Albert common.Cleanup() 1532