diff --git a/gsi/gsi_util/Android.bp b/gsi/gsi_util/Android.bp index 8ec481a35..2eb80fdf8 100644 --- a/gsi/gsi_util/Android.bp +++ b/gsi/gsi_util/Android.bp @@ -20,6 +20,9 @@ python_binary_host { "gsi_util/commands/*.py", "gsi_util/utils/*.py", ], + required: [ + "avbtool", + ], version: { py2: { enabled: true, diff --git a/gsi/gsi_util/gsi_util.py b/gsi/gsi_util/gsi_util.py index d3cab52ff..2b535a85f 100755 --- a/gsi/gsi_util/gsi_util.py +++ b/gsi/gsi_util/gsi_util.py @@ -28,7 +28,7 @@ class GsiUtil(object): # Adds gsi_util COMMAND here. # TODO(bowgotsai): auto collect from gsi_util/commands/*.py - _COMMANDS = ['hello'] + _COMMANDS = ['flash_gsi', 'hello'] _LOGGING_FORMAT = '%(message)s' _LOGGING_LEVEL = logging.WARNING diff --git a/gsi/gsi_util/gsi_util/commands/flash_gsi.py b/gsi/gsi_util/gsi_util/commands/flash_gsi.py new file mode 100644 index 000000000..6f8fd9dfe --- /dev/null +++ b/gsi/gsi_util/gsi_util/commands/flash_gsi.py @@ -0,0 +1,63 @@ +# Copyright 2017 - The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Implementation of gsi_util flash_gsi command.""" + +from gsi_util.utils import cmd_utils +from gsi_util.utils import fastboot_utils +from gsi_util.utils import file_utils + + +def do_flash_gsi(args): + """Flashes a GSI image (system.img). + + Also erases userdata/metadata partition and disables + Android Verified Boot (AVB). + + Args: + args: flash_gsi command arguments. + """ + + fastboot_utils.erase() # erases userdata/cache partition + # Not every device has metadata partition, so allow_error is True. + fastboot_utils.erase('metadata', allow_error=True) + + # Flashes GSI. + fastboot_utils.flash('system', args.image) + + # Disables AVB. + with file_utils.UnopenedTemporaryFile() as vbmeta_image: + # vbmeta flag 2 means disable entire AVB verification. + cmd_utils.run_command(['avbtool', 'make_vbmeta_image', + '--flag', '2', + '--padding_size', '4096', + '--output', vbmeta_image]) + # Not every device uses AVB, so allow_error is True. + fastboot_utils.flash('vbmeta', vbmeta_image, allow_error=True) + + # Reboots the device. + fastboot_utils.reboot() + + +def setup_command_args(subparsers): + """Sets up command args for 'flash_gsi'.""" + parser = subparsers.add_parser( + 'flash_gsi', help='flash a GSI image', + description=('Flash a GSI image - ' + 'including erasing userdata, ' + 'disabling AVB (if the device supports AVB) ' + 'and erasing metadata partition (if the device has).')) + parser.add_argument('-i', '--image', + help='the GSI image to flash', type=str) + parser.set_defaults(func=do_flash_gsi) diff --git a/gsi/gsi_util/gsi_util/utils/fastboot_utils.py b/gsi/gsi_util/gsi_util/utils/fastboot_utils.py new file mode 100644 index 000000000..a6f11eecd --- /dev/null +++ b/gsi/gsi_util/gsi_util/utils/fastboot_utils.py @@ -0,0 +1,45 @@ +# Copyright 2017 - The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Fastboot-related commands.""" + +from gsi_util.utils.cmd_utils import run_command + + +def flash(partition_name, image_name=None, allow_error=False): + """fastboot flash a partition with a given image.""" + + cmd = ['fastboot', 'flash', partition_name] + + # image_name can be None, for `fastboot` to flash + # ${ANDROID_PRODUCT_OUT}/{partition_name}.img. + if image_name is not None: + cmd.append(image_name) + + run_command(cmd, raise_on_error=not allow_error) + + +def erase(partition_name=None, allow_error=False): + """fastboot erase a partition.""" + + if partition_name is None: + run_command(['fastboot', '-w'], raise_on_error=not allow_error) + else: + run_command(['fastboot', 'erase', partition_name], + raise_on_error=not allow_error) + + +def reboot(): + """fastboot reboot a device.""" + run_command(['fastboot', 'reboot'], raise_on_error=False)