summaryrefslogtreecommitdiffstats
path: root/tools/releasetools
diff options
context:
space:
mode:
Diffstat (limited to 'tools/releasetools')
-rwxr-xr-xtools/releasetools/check_target_files_signatures5
-rw-r--r--tools/releasetools/common.py126
-rw-r--r--tools/releasetools/edify_generator.py32
-rwxr-xr-xtools/releasetools/img_from_target_files35
-rwxr-xr-xtools/releasetools/ota_from_target_files105
-rwxr-xr-xtools/releasetools/sign_target_files_apks19
6 files changed, 205 insertions, 117 deletions
diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures
index 99bc801..1325ef4 100755
--- a/tools/releasetools/check_target_files_signatures
+++ b/tools/releasetools/check_target_files_signatures
@@ -116,7 +116,7 @@ class CertDB(object):
self.certs[cert] = self.certs[cert] + "," + name
else:
if name is None:
- name = "unknown cert %s (%s)" % (sha1(cert).hexdigest()[:12],
+ name = "unknown cert %s (%s)" % (common.sha1(cert).hexdigest()[:12],
GetCertSubject(cert))
self.certs[cert] = name
@@ -249,7 +249,7 @@ class TargetFiles(object):
self.max_fn_len = 20
def LoadZipFile(self, filename):
- d = common.UnzipTemp(filename, '*.apk')
+ d, z = common.UnzipTemp(filename, '*.apk')
try:
self.apks = {}
self.apks_by_basename = {}
@@ -267,7 +267,6 @@ class TargetFiles(object):
finally:
shutil.rmtree(d)
- z = zipfile.ZipFile(open(filename, "rb"))
self.certmap = common.ReadApkCerts(z)
z.close()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index fd098ea..2cb5680 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -165,11 +165,27 @@ def LoadRecoveryFSTab(zip):
p.mount_point = pieces[0]
p.fs_type = pieces[1]
p.device = pieces[2]
- if len(pieces) == 4:
- p.device2 = pieces[3]
+ p.length = 0
+ options = None
+ if len(pieces) >= 4:
+ if pieces[3].startswith("/"):
+ p.device2 = pieces[3]
+ if len(pieces) >= 5:
+ options = pieces[4]
+ else:
+ p.device2 = None
+ options = pieces[3]
else:
p.device2 = None
+ if options:
+ options = options.split(",")
+ for i in options:
+ if i.startswith("length="):
+ p.length = int(i[7:])
+ else:
+ print "%s: unknown option \"%s\"" % (p.mount_point, i)
+
d[p.mount_point] = p
return d
@@ -178,23 +194,6 @@ def DumpInfoDict(d):
for k, v in sorted(d.items()):
print "%-25s = (%s) %s" % (k, type(v).__name__, v)
-def BuildAndAddBootableImage(sourcedir, targetname, output_zip, info_dict):
- """Take a kernel, cmdline, and ramdisk directory from the input (in
- 'sourcedir'), and turn them into a boot image. Put the boot image
- into the output zip file under the name 'targetname'. Returns
- targetname on success or None on failure (if sourcedir does not
- appear to contain files for the requested image)."""
-
- print "creating %s..." % (targetname,)
-
- img = BuildBootableImage(sourcedir)
- if img is None:
- return None
-
- CheckSize(img, targetname, info_dict)
- ZipWriteStr(output_zip, targetname, img)
- return targetname
-
def BuildBootableImage(sourcedir):
"""Take a kernel, cmdline, and ramdisk directory from the input (in
'sourcedir'), and turn them into a boot image. Return the image
@@ -252,28 +251,53 @@ def BuildBootableImage(sourcedir):
return data
-def AddRecovery(output_zip, info_dict):
- BuildAndAddBootableImage(os.path.join(OPTIONS.input_tmp, "RECOVERY"),
- "recovery.img", output_zip, info_dict)
+def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir):
+ """Return a File object (with name 'name') with the desired bootable
+ image. Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name
+ 'prebuilt_name', otherwise construct it from the source files in
+ 'unpack_dir'/'tree_subdir'."""
+
+ prebuilt_path = os.path.join(unpack_dir, "BOOTABLE_IMAGES", prebuilt_name)
+ if os.path.exists(prebuilt_path):
+ print "using prebuilt %s..." % (prebuilt_name,)
+ return File.FromLocalFile(name, prebuilt_path)
+ else:
+ print "building image from target_files %s..." % (tree_subdir,)
+ return File(name, BuildBootableImage(os.path.join(unpack_dir, tree_subdir)))
-def AddBoot(output_zip, info_dict):
- BuildAndAddBootableImage(os.path.join(OPTIONS.input_tmp, "BOOT"),
- "boot.img", output_zip, info_dict)
def UnzipTemp(filename, pattern=None):
- """Unzip the given archive into a temporary directory and return the name."""
+ """Unzip the given archive into a temporary directory and return the name.
+
+ If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a
+ temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
+
+ Returns (tempdir, zipobj) where zipobj is a zipfile.ZipFile (of the
+ main file), open for reading.
+ """
tmp = tempfile.mkdtemp(prefix="targetfiles-")
OPTIONS.tempfiles.append(tmp)
- cmd = ["unzip", "-o", "-q", filename, "-d", tmp]
- if pattern is not None:
- cmd.append(pattern)
- p = Run(cmd, stdout=subprocess.PIPE)
- p.communicate()
- if p.returncode != 0:
- raise ExternalError("failed to unzip input target-files \"%s\"" %
- (filename,))
- return tmp
+
+ def unzip_to_dir(filename, dirname):
+ cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
+ if pattern is not None:
+ cmd.append(pattern)
+ p = Run(cmd, stdout=subprocess.PIPE)
+ p.communicate()
+ if p.returncode != 0:
+ raise ExternalError("failed to unzip input target-files \"%s\"" %
+ (filename,))
+
+ m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)
+ if m:
+ unzip_to_dir(m.group(1), tmp)
+ unzip_to_dir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"))
+ filename = m.group(1)
+ else:
+ unzip_to_dir(filename, tmp)
+
+ return tmp, zipfile.ZipFile(filename, "r")
def GetKeyPasswords(keylist):
@@ -330,7 +354,7 @@ def SignFile(input_name, output_name, key, password, align=None,
else:
sign_name = output_name
- cmd = ["java", "-Xmx512m", "-jar",
+ cmd = ["java", "-Xmx2048m", "-jar",
os.path.join(OPTIONS.search_path, "framework", "signapk.jar")]
if whole_file:
cmd.append("-w")
@@ -371,18 +395,17 @@ def CheckSize(data, target, info_dict):
# image size should be increased by 1/64th to account for the
# spare area (64 bytes per 2k page)
limit = limit / 2048 * (2048+64)
-
- size = len(data)
- pct = float(size) * 100.0 / limit
- msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
- if pct >= 99.0:
- raise ExternalError(msg)
- elif pct >= 95.0:
- print
- print " WARNING: ", msg
- print
- elif OPTIONS.verbose:
- print " ", msg
+ size = len(data)
+ pct = float(size) * 100.0 / limit
+ msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
+ if pct >= 99.0:
+ raise ExternalError(msg)
+ elif pct >= 95.0:
+ print
+ print " WARNING: ", msg
+ print
+ elif OPTIONS.verbose:
+ print " ", msg
def ReadApkCerts(tf_zip):
@@ -665,6 +688,13 @@ class File(object):
self.size = len(data)
self.sha1 = sha1(data).hexdigest()
+ @classmethod
+ def FromLocalFile(cls, name, diskname):
+ f = open(diskname, "rb")
+ data = f.read()
+ f.close()
+ return File(name, data)
+
def WriteToTemp(self):
t = tempfile.NamedTemporaryFile()
t.write(self.data)
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index a7c8e32..6c53f9e 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -161,11 +161,13 @@ class EdifyGenerator(object):
"""Format the given partition, specified by its mount point (eg,
"/system")."""
+ reserve_size = 0
fstab = self.info.get("fstab", None)
if fstab:
p = fstab[partition]
- self.script.append('format("%s", "%s", "%s");' %
- (p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device))
+ self.script.append('format("%s", "%s", "%s", "%s");' %
+ (p.fs_type, common.PARTITION_TYPES[p.fs_type],
+ p.device, p.length))
def DeleteFiles(self, file_list):
"""Delete all files in file_list."""
@@ -187,18 +189,6 @@ class EdifyGenerator(object):
cmd = "".join(cmd)
self.script.append(self._WordWrap(cmd))
- def WriteFirmwareImage(self, kind, fn):
- """Arrange to update the given firmware image (kind must be
- "hboot" or "radio") when recovery finishes."""
- if self.version == 1:
- self.script.append(
- ('assert(package_extract_file("%(fn)s", "/tmp/%(kind)s.img"),\n'
- ' write_firmware_image("/tmp/%(kind)s.img", "%(kind)s"));')
- % {'kind': kind, 'fn': fn})
- else:
- self.script.append(
- 'write_firmware_image("PACKAGE:%s", "%s");' % (fn, kind))
-
def WriteRawImage(self, mount_point, fn):
"""Write the given package file into the partition for the given
mount point."""
@@ -239,6 +229,20 @@ class EdifyGenerator(object):
",\0".join(['"' + i + '"' for i in sorted(links)]) + ");")
self.script.append(self._WordWrap(cmd))
+ def RetouchBinaries(self, file_list):
+ """Execute the retouch instructions in files listed."""
+ cmd = ('retouch_binaries(' +
+ ', '.join(['"' + i[0] + '", "' + i[1] + '"' for i in file_list]) +
+ ');')
+ self.script.append(self._WordWrap(cmd))
+
+ def UndoRetouchBinaries(self, file_list):
+ """Undo the retouching (retouch to zero offset)."""
+ cmd = ('undo_retouch_binaries(' +
+ ', '.join(['"' + i[0] + '", "' + i[1] + '"' for i in file_list]) +
+ ');')
+ self.script.append(self._WordWrap(cmd))
+
def AppendExtra(self, extra):
"""Append text verbatim to the output script."""
self.script.append(extra)
diff --git a/tools/releasetools/img_from_target_files b/tools/releasetools/img_from_target_files
index 4a23ab4..c5b9886 100755
--- a/tools/releasetools/img_from_target_files
+++ b/tools/releasetools/img_from_target_files
@@ -23,6 +23,10 @@ Usage: img_from_target_files [flags] input_target_files output_image_zip
-b (--board_config) <file>
Deprecated.
+ -z (--bootable_zip)
+ Include only the bootable images (eg 'boot' and 'recovery') in
+ the output.
+
"""
import sys
@@ -78,7 +82,7 @@ def AddUserdata(output_zip):
build_command.append(user_dir)
build_command.append(img.name)
- p = common.Run(build_command)
+ p = common.Run(build_command);
p.communicate()
assert p.returncode == 0, "build userdata.img image failed"
@@ -149,35 +153,44 @@ def CopyInfo(output_zip):
def main(argv):
+ bootable_only = [False]
def option_handler(o, a):
if o in ("-b", "--board_config"):
pass # deprecated
+ if o in ("-z", "--bootable_zip"):
+ bootable_only[0] = True
else:
return False
return True
args = common.ParseOptions(argv, __doc__,
- extra_opts="b:",
- extra_long_opts=["board_config="],
+ extra_opts="b:z",
+ extra_long_opts=["board_config=",
+ "bootable_zip"],
extra_option_handler=option_handler)
+ bootable_only = bootable_only[0]
+
if len(args) != 2:
common.Usage(__doc__)
sys.exit(1)
- OPTIONS.input_tmp = common.UnzipTemp(args[0])
-
- input_zip = zipfile.ZipFile(args[0], "r")
+ OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
OPTIONS.info_dict = common.LoadInfoDict(input_zip)
output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
- common.AddBoot(output_zip, OPTIONS.info_dict)
- common.AddRecovery(output_zip, OPTIONS.info_dict)
- AddSystem(output_zip)
- AddUserdata(output_zip)
- CopyInfo(output_zip)
+ common.GetBootableImage(
+ "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT").AddToZip(output_zip)
+ common.GetBootableImage(
+ "recovery.img", "recovery.img", OPTIONS.input_tmp,
+ "RECOVERY").AddToZip(output_zip)
+
+ if not bootable_only:
+ AddSystem(output_zip)
+ AddUserdata(output_zip)
+ CopyInfo(output_zip)
print "cleaning up..."
output_zip.close()
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index 78f37db..aead38f 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -44,6 +44,8 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package
-e (--extra_script) <file>
Insert the contents of file at the end of the update script.
+ -a (--aslr_mode) <on|off>
+ Specify whether to turn on ASLR for the package (on by default).
"""
import sys
@@ -78,6 +80,7 @@ OPTIONS.patch_threshold = 0.95
OPTIONS.wipe_user_data = False
OPTIONS.omit_prereq = False
OPTIONS.extra_script = None
+OPTIONS.aslr_mode = True
OPTIONS.worker_threads = 3
def MostPopularKey(d, default):
@@ -94,6 +97,10 @@ def IsSymlink(info):
symlink."""
return (info.external_attr >> 16) == 0120777
+def IsRegular(info):
+ """Return true if the zipfile.ZipInfo object passed in represents a
+ symlink."""
+ return (info.external_attr >> 28) == 010
class Item:
"""Items represent the metadata (user, group, mode) of files and
@@ -248,13 +255,15 @@ def CopySystemFiles(input_zip, output_zip=None,
substitute=None):
"""Copies files underneath system/ in the input zip to the output
zip. Populates the Item class with their metadata, and returns a
- list of symlinks. output_zip may be None, in which case the copy is
- skipped (but the other side effects still happen). substitute is an
- optional dict of {output filename: contents} to be output instead of
- certain input files.
+ list of symlinks as well as a list of files that will be retouched.
+ output_zip may be None, in which case the copy is skipped (but the
+ other side effects still happen). substitute is an optional dict
+ of {output filename: contents} to be output instead of certain input
+ files.
"""
symlinks = []
+ retouch_files = []
for info in input_zip.infolist():
if info.filename.startswith("SYSTEM/"):
@@ -272,6 +281,9 @@ def CopySystemFiles(input_zip, output_zip=None,
data = substitute[fn]
else:
data = input_zip.read(info.filename)
+ if info.filename.startswith("SYSTEM/lib/") and IsRegular(info):
+ retouch_files.append(("/system/" + basefilename,
+ common.sha1(data).hexdigest()))
output_zip.writestr(info2, data)
if fn.endswith("/"):
Item.Get(fn[:-1], dir=True)
@@ -279,7 +291,7 @@ def CopySystemFiles(input_zip, output_zip=None,
Item.Get(fn, dir=False)
symlinks.sort()
- return symlinks
+ return (symlinks, retouch_files)
def SignOutput(temp_zip_name, output_zip_name):
@@ -304,7 +316,8 @@ def MakeRecoveryPatch(output_zip, recovery_img, boot_img):
patching and install the new recovery image.
recovery_img and boot_img should be File objects for the
- corresponding images.
+ corresponding images. info should be the dictionary returned by
+ common.LoadInfoDict() on the input target_files.
Returns an Item for the shell script, which must be made
executable.
@@ -322,7 +335,7 @@ def MakeRecoveryPatch(output_zip, recovery_img, boot_img):
# we check to see if this recovery has already been installed by
# testing just the first 2k.
HEADER_SIZE = 2048
- header_sha1 = sha1(recovery_img.data[:HEADER_SIZE]).hexdigest()
+ header_sha1 = common.sha1(recovery_img.data[:HEADER_SIZE]).hexdigest()
sh = """#!/system/bin/sh
if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(header_size)d:%(header_sha1)s; then
log -t recovery "Installing new recovery image"
@@ -382,13 +395,17 @@ def WriteFullOTAPackage(input_zip, output_zip):
script.UnpackPackageDir("recovery", "/system")
script.UnpackPackageDir("system", "/system")
- symlinks = CopySystemFiles(input_zip, output_zip)
+ (symlinks, retouch_files) = CopySystemFiles(input_zip, output_zip)
script.MakeSymlinks(symlinks)
+ if OPTIONS.aslr_mode:
+ script.RetouchBinaries(retouch_files)
+ else:
+ script.UndoRetouchBinaries(retouch_files)
- boot_img = common.File("boot.img", common.BuildBootableImage(
- os.path.join(OPTIONS.input_tmp, "BOOT")))
- recovery_img = common.File("recovery.img", common.BuildBootableImage(
- os.path.join(OPTIONS.input_tmp, "RECOVERY")))
+ boot_img = common.GetBootableImage("boot.img", "boot.img",
+ OPTIONS.input_tmp, "BOOT")
+ recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
+ OPTIONS.input_tmp, "RECOVERY")
MakeRecoveryPatch(output_zip, recovery_img, boot_img)
Item.GetMetadata(input_zip)
@@ -424,12 +441,17 @@ def LoadSystemFiles(z):
"""Load all the files from SYSTEM/... in a given target-files
ZipFile, and return a dict of {filename: File object}."""
out = {}
+ retouch_files = []
for info in z.infolist():
if info.filename.startswith("SYSTEM/") and not IsSymlink(info):
- fn = "system/" + info.filename[7:]
+ basefilename = info.filename[7:]
+ fn = "system/" + basefilename
data = z.read(info.filename)
out[fn] = common.File(fn, data)
- return out
+ if info.filename.startswith("SYSTEM/lib/") and IsRegular(info):
+ retouch_files.append(("/system/" + basefilename,
+ out[fn].sha1))
+ return (out, retouch_files)
def GetBuildProp(property, z):
@@ -451,7 +473,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
if source_version == 0:
print ("WARNING: generating edify script for a source that "
"can't install it.")
- script = edify_generator.EdifyGenerator(source_version, OPTIONS.info_dict)
+ script = edify_generator.EdifyGenerator(source_version, OPTIONS.target_info_dict)
metadata = {"pre-device": GetBuildProp("ro.product.device", source_zip),
"post-timestamp": GetBuildProp("ro.build.date.utc", target_zip),
@@ -468,9 +490,9 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
info_dict=OPTIONS.info_dict)
print "Loading target..."
- target_data = LoadSystemFiles(target_zip)
+ (target_data, target_retouch_files) = LoadSystemFiles(target_zip)
print "Loading source..."
- source_data = LoadSystemFiles(source_zip)
+ (source_data, source_retouch_files) = LoadSystemFiles(source_zip)
verbatim_targets = []
patch_list = []
@@ -505,7 +527,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
verbatim_targets.append((tf.name, tf.size))
else:
common.ZipWriteStr(output_zip, "patch/" + tf.name + ".p", d)
- patch_list.append((tf.name, tf, sf, tf.size, sha1(d).hexdigest()))
+ patch_list.append((tf.name, tf, sf, tf.size, common.sha1(d).hexdigest()))
largest_source_size = max(largest_source_size, sf.size)
source_fp = GetBuildProp("ro.build.fingerprint", source_zip)
@@ -516,20 +538,16 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
script.Mount("/system")
script.AssertSomeFingerprint(source_fp, target_fp)
- source_boot = common.File("/tmp/boot.img",
- common.BuildBootableImage(
- os.path.join(OPTIONS.source_tmp, "BOOT")))
- target_boot = common.File("/tmp/boot.img",
- common.BuildBootableImage(
- os.path.join(OPTIONS.target_tmp, "BOOT")))
+ source_boot = common.GetBootableImage(
+ "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT")
+ target_boot = common.GetBootableImage(
+ "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT")
updating_boot = (source_boot.data != target_boot.data)
- source_recovery = common.File("system/recovery.img",
- common.BuildBootableImage(
- os.path.join(OPTIONS.source_tmp, "RECOVERY")))
- target_recovery = common.File("system/recovery.img",
- common.BuildBootableImage(
- os.path.join(OPTIONS.target_tmp, "RECOVERY")))
+ source_recovery = common.GetBootableImage(
+ "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY")
+ target_recovery = common.GetBootableImage(
+ "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY")
updating_recovery = (source_recovery.data != target_recovery.data)
# Here's how we divide up the progress bar:
@@ -639,7 +657,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
script.ShowProgress(0.1, 10)
- target_symlinks = CopySystemFiles(target_zip, None)
+ (target_symlinks, target_retouch_dummies) = CopySystemFiles(target_zip, None)
target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks])
temp_script = script.MakeTemporary()
@@ -648,7 +666,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
# Note that this call will mess up the tree of Items, so make sure
# we're done with it.
- source_symlinks = CopySystemFiles(source_zip, None)
+ (source_symlinks, source_retouch_dummies) = CopySystemFiles(source_zip, None)
source_symlinks_d = dict([(i[1], i[0]) for i in source_symlinks])
# Delete all the symlinks in source that aren't in target. This
@@ -682,6 +700,10 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
to_create.append((dest, link))
script.DeleteFiles([i[1] for i in to_create])
script.MakeSymlinks(to_create)
+ if OPTIONS.aslr_mode:
+ script.RetouchBinaries(target_retouch_files)
+ else:
+ script.UndoRetouchBinaries(target_retouch_files)
# Now that the symlinks are created, we can set all the
# permissions.
@@ -691,7 +713,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
device_specific.IncrementalOTA_InstallEnd()
if OPTIONS.extra_script is not None:
- scirpt.AppendExtra(OPTIONS.extra_script)
+ script.AppendExtra(OPTIONS.extra_script)
script.AddToZip(target_zip, output_zip)
WriteMetadata(metadata, output_zip)
@@ -712,6 +734,11 @@ def main(argv):
OPTIONS.omit_prereq = True
elif o in ("-e", "--extra_script"):
OPTIONS.extra_script = a
+ elif o in ("-a", "--aslr_mode"):
+ if a in ("on", "On", "true", "True", "yes", "Yes"):
+ OPTIONS.aslr_mode = True
+ else:
+ OPTIONS.aslr_mode = False
elif o in ("--worker_threads"):
OPTIONS.worker_threads = int(a)
else:
@@ -719,14 +746,16 @@ def main(argv):
return True
args = common.ParseOptions(argv, __doc__,
- extra_opts="b:k:i:d:wne:",
+ extra_opts="b:k:i:d:wne:a:",
extra_long_opts=["board_config=",
"package_key=",
"incremental_from=",
"wipe_user_data",
"no_prereq",
"extra_script=",
- "worker_threads="],
+ "worker_threads=",
+ "aslr_mode=",
+ ],
extra_option_handler=option_handler)
if len(args) != 2:
@@ -737,10 +766,9 @@ def main(argv):
OPTIONS.extra_script = open(OPTIONS.extra_script).read()
print "unzipping target target-files..."
- OPTIONS.input_tmp = common.UnzipTemp(args[0])
+ OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
OPTIONS.target_tmp = OPTIONS.input_tmp
- input_zip = zipfile.ZipFile(args[0], "r")
OPTIONS.info_dict = common.LoadInfoDict(input_zip)
if OPTIONS.verbose:
print "--- target info ---"
@@ -764,8 +792,7 @@ def main(argv):
WriteFullOTAPackage(input_zip, output_zip)
else:
print "unzipping source target-files..."
- OPTIONS.source_tmp = common.UnzipTemp(OPTIONS.incremental_source)
- source_zip = zipfile.ZipFile(OPTIONS.incremental_source, "r")
+ OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)
OPTIONS.target_info_dict = OPTIONS.info_dict
OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
if OPTIONS.verbose:
diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks
index 5fca691..5353063 100755
--- a/tools/releasetools/sign_target_files_apks
+++ b/tools/releasetools/sign_target_files_apks
@@ -204,6 +204,17 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
except KeyError:
raise ExternalError("can't read META/otakeys.txt from input")
+ misc_info = common.LoadInfoDict(input_tf_zip)
+
+ extra_recovery_keys = misc_info.get("extra_recovery_keys", None)
+ if extra_recovery_keys:
+ extra_recovery_keys = [OPTIONS.key_map.get(k, k) + ".x509.pem"
+ for k in extra_recovery_keys.split()]
+ if extra_recovery_keys:
+ print "extra recovery-only key(s): " + ", ".join(extra_recovery_keys)
+ else:
+ extra_recovery_keys = []
+
mapped_keys = []
for k in keylist:
m = re.match(r"^(.*)\.x509\.pem$", k)
@@ -217,15 +228,18 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
print "for OTA package verification"
else:
mapped_keys.append(
- OPTIONS.key_map["build/target/product/security/testkey"] + ".x509.pem")
+ OPTIONS.key_map.get("build/target/product/security/testkey",
+ "build/target/product/security/testkey")
+ + ".x509.pem")
print "META/otakeys.txt has no keys; using", mapped_keys[0]
# recovery uses a version of the key that has been slightly
# predigested (by DumpPublicKey.java) and put in res/keys.
+ # extra_recovery_keys are used only in recovery.
p = common.Run(["java", "-jar",
os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")]
- + mapped_keys,
+ + mapped_keys + extra_recovery_keys,
stdout=subprocess.PIPE)
data, _ = p.communicate()
if p.returncode != 0:
@@ -234,6 +248,7 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
# SystemUpdateActivity uses the x509.pem version of the keys, but
# put into a zipfile system/etc/security/otacerts.zip.
+ # We DO NOT include the extra_recovery_keys (if any) here.
tempfile = cStringIO.StringIO()
certs_zip = zipfile.ZipFile(tempfile, "w")