summaryrefslogtreecommitdiff
path: root/tools/releasetools/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/releasetools/common.py')
-rw-r--r--tools/releasetools/common.py70
1 files changed, 48 insertions, 22 deletions
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 8ee983f81a..8ce6083f44 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -39,18 +39,23 @@ import tempfile
import threading
import time
import zipfile
+
+from typing import Iterable, Callable
from dataclasses import dataclass
-from genericpath import isdir
from hashlib import sha1, sha256
import images
-import rangelib
import sparse_img
from blockimgdiff import BlockImageDiff
logger = logging.getLogger(__name__)
+@dataclass
+class OptionHandler:
+ extra_long_opts: Iterable[str]
+ handler: Callable
+
class Options(object):
def __init__(self):
@@ -210,7 +215,7 @@ def InitLogging():
'': {
'handlers': ['default'],
'propagate': True,
- 'level': 'WARNING',
+ 'level': 'NOTSET',
}
}
}
@@ -1235,26 +1240,16 @@ def _FindAndLoadRecoveryFstab(info_dict, input_file, read_helper):
system_root_image = info_dict.get('system_root_image') == 'true'
if info_dict.get('no_recovery') != 'true':
recovery_fstab_path = 'RECOVERY/RAMDISK/system/etc/recovery.fstab'
- if isinstance(input_file, zipfile.ZipFile):
- if recovery_fstab_path not in input_file.namelist():
- recovery_fstab_path = 'RECOVERY/RAMDISK/etc/recovery.fstab'
- else:
- path = os.path.join(input_file, *recovery_fstab_path.split('/'))
- if not os.path.exists(path):
- recovery_fstab_path = 'RECOVERY/RAMDISK/etc/recovery.fstab'
+ if not DoesInputFileContain(input_file, recovery_fstab_path):
+ recovery_fstab_path = 'RECOVERY/RAMDISK/etc/recovery.fstab'
return LoadRecoveryFSTab(
read_helper, info_dict['fstab_version'], recovery_fstab_path,
system_root_image)
if info_dict.get('recovery_as_boot') == 'true':
recovery_fstab_path = 'BOOT/RAMDISK/system/etc/recovery.fstab'
- if isinstance(input_file, zipfile.ZipFile):
- if recovery_fstab_path not in input_file.namelist():
- recovery_fstab_path = 'BOOT/RAMDISK/etc/recovery.fstab'
- else:
- path = os.path.join(input_file, *recovery_fstab_path.split('/'))
- if not os.path.exists(path):
- recovery_fstab_path = 'BOOT/RAMDISK/etc/recovery.fstab'
+ if not DoesInputFileContain(input_file, recovery_fstab_path):
+ recovery_fstab_path = 'BOOT/RAMDISK/etc/recovery.fstab'
return LoadRecoveryFSTab(
read_helper, info_dict['fstab_version'], recovery_fstab_path,
system_root_image)
@@ -1947,7 +1942,18 @@ def _SignBootableImage(image_path, prebuilt_name, partition_name,
cmd = [avbtool, "add_hash_footer", "--image", image_path,
"--partition_size", str(part_size), "--partition_name",
partition_name]
- AppendAVBSigningArgs(cmd, partition_name)
+ # Use sha256 of the kernel as salt for reproducible builds
+ with tempfile.TemporaryDirectory() as tmpdir:
+ RunAndCheckOutput(["unpack_bootimg", "--boot_img", image_path, "--out", tmpdir])
+ for filename in ["kernel", "ramdisk", "vendor_ramdisk00"]:
+ path = os.path.join(tmpdir, filename)
+ if os.path.exists(path) and os.path.getsize(path):
+ print("Using {} as salt for avb footer of {}".format(
+ filename, partition_name))
+ with open(path, "rb") as fp:
+ salt = sha256(fp.read()).hexdigest()
+ break
+ AppendAVBSigningArgs(cmd, partition_name, salt)
args = info_dict.get("avb_" + partition_name + "_add_hash_footer_args")
if args and args.strip():
split_args = ResolveAVBSigningPathArgs(shlex.split(args))
@@ -2653,7 +2659,9 @@ def CheckSize(data, target, info_dict):
device = p.device
if "/" in device:
device = device[device.rfind("/")+1:]
- limit = info_dict.get(device + "_size")
+ limit = info_dict.get(device + "_size", 0)
+ if isinstance(limit, str):
+ limit = int(limit, 0)
if not fs_type or not limit:
return
@@ -2790,12 +2798,19 @@ def Usage(docstring):
def ParseOptions(argv,
docstring,
extra_opts="", extra_long_opts=(),
- extra_option_handler=None):
+ extra_option_handler: Iterable[OptionHandler] = None):
"""Parse the options in argv and return any arguments that aren't
flags. docstring is the calling module's docstring, to be displayed
for errors and -h. extra_opts and extra_long_opts are for flags
defined by the caller, which are processed by passing them to
extra_option_handler."""
+ extra_long_opts = list(extra_long_opts)
+ if not isinstance(extra_option_handler, Iterable):
+ extra_option_handler = [extra_option_handler]
+
+ for handler in extra_option_handler:
+ if isinstance(handler, OptionHandler):
+ extra_long_opts.extend(handler.extra_long_opts)
try:
opts, args = getopt.getopt(
@@ -2857,8 +2872,19 @@ def ParseOptions(argv,
elif o in ("--logfile",):
OPTIONS.logfile = a
else:
- if extra_option_handler is None or not extra_option_handler(o, a):
- assert False, "unknown option \"%s\"" % (o,)
+ if extra_option_handler is None:
+ raise ValueError("unknown option \"%s\"" % (o,))
+ success = False
+ for handler in extra_option_handler:
+ if isinstance(handler, OptionHandler):
+ if handler.handler(o, a):
+ success = True
+ break
+ elif handler(o, a):
+ success = True
+ if not success:
+ raise ValueError("unknown option \"%s\"" % (o,))
+
if OPTIONS.search_path:
os.environ["PATH"] = (os.path.join(OPTIONS.search_path, "bin") +