rebuild recovery patch in sign_target_files_apks

The target_files zip should now contain the recovery-from-boot patch
and the script to install it.  This means that sign_target_files_apks,
which generates a signed target_files from an unsigned target_files,
now needs to recompute the patch and script (taking into account the
key replacement, property changes, etc., that it does) so its output
contains the correct patch.

Change-Id: I18afd73864ba5c480b7ec11de19d1f5e7763a8c0
This commit is contained in:
Doug Zongker 2014-02-13 10:58:24 -08:00
parent ca389b9048
commit 412c02fffb
2 changed files with 73 additions and 11 deletions

View File

@ -990,7 +990,8 @@ def ParseCertificate(data):
return cert return cert
def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img): def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
info_dict=None):
"""Generate a binary patch that creates the recovery image starting """Generate a binary patch that creates the recovery image starting
with the boot image. (Most of the space in these images is just the with the boot image. (Most of the space in these images is just the
kernel, which is identical for the two, so the resulting patch kernel, which is identical for the two, so the resulting patch
@ -1003,6 +1004,9 @@ def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img):
common.LoadInfoDict() on the input target_files. common.LoadInfoDict() on the input target_files.
""" """
if info_dict is None:
info_dict = OPTIONS.info_dict
diff_program = ["imgdiff"] diff_program = ["imgdiff"]
path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat") path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat")
if os.path.exists(path): if os.path.exists(path):
@ -1016,8 +1020,8 @@ def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img):
_, _, patch = d.ComputePatch() _, _, patch = d.ComputePatch()
output_sink("recovery-from-boot.p", patch) output_sink("recovery-from-boot.p", patch)
boot_type, boot_device = GetTypeAndDevice("/boot", OPTIONS.info_dict) boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
recovery_type, recovery_device = GetTypeAndDevice("/recovery", OPTIONS.info_dict) recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
sh = """#!/system/bin/sh sh = """#!/system/bin/sh
if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then

View File

@ -77,6 +77,7 @@ import copy
import errno import errno
import os import os
import re import re
import shutil
import subprocess import subprocess
import tempfile import tempfile
import zipfile import zipfile
@ -139,14 +140,40 @@ def SignApk(data, keyname, pw):
return data return data
def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
apk_key_map, key_passwords):
maxsize = max([len(os.path.basename(i.filename)) maxsize = max([len(os.path.basename(i.filename))
for i in input_tf_zip.infolist() for i in input_tf_zip.infolist()
if i.filename.endswith('.apk')]) if i.filename.endswith('.apk')])
rebuild_recovery = False
tmpdir = tempfile.mkdtemp()
def write_to_temp(fn, attr, data):
fn = os.path.join(tmpdir, fn)
if fn.endswith("/"):
fn = os.path.join(tmpdir, fn)
os.mkdir(fn)
else:
d = os.path.dirname(fn)
if d and not os.path.exists(d):
os.makedirs(d)
if attr >> 16 == 0xa1ff:
os.symlink(data, fn)
else:
with open(fn, "wb") as f:
f.write(data)
for info in input_tf_zip.infolist(): for info in input_tf_zip.infolist():
data = input_tf_zip.read(info.filename) data = input_tf_zip.read(info.filename)
out_info = copy.copy(info) out_info = copy.copy(info)
if (info.filename.startswith("BOOT/") or
info.filename.startswith("RECOVERY/") or
info.filename.startswith("META/") or
info.filename == "SYSTEM/etc/recovery-resource.dat"):
write_to_temp(info.filename, info.external_attr, data)
if info.filename.endswith(".apk"): if info.filename.endswith(".apk"):
name = os.path.basename(info.filename) name = os.path.basename(info.filename)
key = apk_key_map[name] key = apk_key_map[name]
@ -163,14 +190,43 @@ def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords):
print "rewriting %s:" % (info.filename,) print "rewriting %s:" % (info.filename,)
new_data = RewriteProps(data) new_data = RewriteProps(data)
output_tf_zip.writestr(out_info, new_data) output_tf_zip.writestr(out_info, new_data)
if info.filename == "RECOVERY/RAMDISK/default.prop":
write_to_temp(info.filename, info.external_attr, new_data)
elif info.filename.endswith("mac_permissions.xml"): elif info.filename.endswith("mac_permissions.xml"):
print "rewriting %s with new keys." % (info.filename,) print "rewriting %s with new keys." % (info.filename,)
new_data = ReplaceCerts(data) new_data = ReplaceCerts(data)
output_tf_zip.writestr(out_info, new_data) output_tf_zip.writestr(out_info, new_data)
elif info.filename in ("SYSTEM/recovery-from-boot.p",
"SYSTEM/bin/install-recovery.sh"):
rebuild_recovery = True
elif (OPTIONS.replace_ota_keys and
info.filename in ("RECOVERY/RAMDISK/res/keys",
"SYSTEM/etc/security/otacerts.zip")):
# don't copy these files if we're regenerating them below
pass
else: else:
# a non-APK file; copy it verbatim # a non-APK file; copy it verbatim
output_tf_zip.writestr(out_info, data) output_tf_zip.writestr(out_info, data)
if OPTIONS.replace_ota_keys:
new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info)
if new_recovery_keys:
write_to_temp("RECOVERY/RAMDISK/res/keys", 0755 << 16, new_recovery_keys)
if rebuild_recovery:
recovery_img = common.GetBootableImage(
"recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info)
boot_img = common.GetBootableImage(
"boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info)
def output_sink(fn, data):
output_tf_zip.writestr("SYSTEM/"+fn, data)
common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img,
info_dict=misc_info)
shutil.rmtree(tmpdir)
def ReplaceCerts(data): def ReplaceCerts(data):
"""Given a string of data, replace all occurences of a set """Given a string of data, replace all occurences of a set
@ -265,7 +321,8 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info):
for k in keylist: for k in keylist:
m = re.match(r"^(.*)\.x509\.pem$", k) m = re.match(r"^(.*)\.x509\.pem$", k)
if not m: if not m:
raise common.ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,)) raise common.ExternalError(
"can't parse \"%s\" from META/otakeys.txt" % (k,))
k = m.group(1) k = m.group(1)
mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem") mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem")
@ -287,10 +344,11 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info):
os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")] os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")]
+ mapped_keys + extra_recovery_keys, + mapped_keys + extra_recovery_keys,
stdout=subprocess.PIPE) stdout=subprocess.PIPE)
data, _ = p.communicate() new_recovery_keys, _ = p.communicate()
if p.returncode != 0: if p.returncode != 0:
raise common.ExternalError("failed to run dumpkeys") raise common.ExternalError("failed to run dumpkeys")
common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data) common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys",
new_recovery_keys)
# SystemUpdateActivity uses the x509.pem version of the keys, but # SystemUpdateActivity uses the x509.pem version of the keys, but
# put into a zipfile system/etc/security/otacerts.zip. # put into a zipfile system/etc/security/otacerts.zip.
@ -304,6 +362,8 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info):
common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip",
tempfile.getvalue()) tempfile.getvalue())
return new_recovery_keys
def BuildKeyMap(misc_info, key_mapping_options): def BuildKeyMap(misc_info, key_mapping_options):
for s, d in key_mapping_options: for s, d in key_mapping_options:
@ -375,10 +435,8 @@ def main(argv):
CheckAllApksSigned(input_zip, apk_key_map) CheckAllApksSigned(input_zip, apk_key_map)
key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
SignApks(input_zip, output_zip, apk_key_map, key_passwords) ProcessTargetFiles(input_zip, output_zip, misc_info,
apk_key_map, key_passwords)
if OPTIONS.replace_ota_keys:
ReplaceOtaKeys(input_zip, output_zip, misc_info)
input_zip.close() input_zip.close()
output_zip.close() output_zip.close()