diff options
Diffstat (limited to 'tests/src/lib/replicant_releases.py')
-rw-r--r-- | tests/src/lib/replicant_releases.py | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/tests/src/lib/replicant_releases.py b/tests/src/lib/replicant_releases.py new file mode 100644 index 0000000..3da6e47 --- /dev/null +++ b/tests/src/lib/replicant_releases.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python3 +# Copyright (C) 2020 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +import os +import re +import sh + +import lib.devices +import lib.hosts + +from lib.common import get_output +from lib.common import trace + +class ReplicantRelease(object): + def __init__(self, config, major_version, minor_version, host, device, + quiet=False): + self.config = config + self.quiet = quiet + + self.major_version = major_version + self.minor_version = minor_version + self.host = host + self.device = device + + @trace + def get_recovery_path(self): + path = "" + path += os.sep.join([ + self.config['releases_directory'], + 'replicant' + '-' + self.major_version, + self.minor_version]) + path += os.sep + 'images' + os.sep + str(self.device) + path += os.sep + 'recovery-{}.img'.format(self.device) + return path + + @trace + def get_zip_path(self): + filename = 'replicant-{}-{}.zip'.format(self.major_version, + self.device) + if self.major_version == '6.0': + if self.minor_version > '0003': + filename = 'replicant-{}-{}-{}.zip'.format(self.major_version, + self.minor_version, + self.device) + path = "" + path += os.sep.join([ + self.config['releases_directory'], + 'replicant' + '-' + self.major_version, + self.minor_version]) + path += os.sep + 'images' + os.sep + str(self.device) + path += os.sep + filename + return path + + @trace + def get_supported_targets(self): + if self.major_version != '6.0': + assert(False) + + return ['espresso3g', 'espressowifi', 'i9100', 'i9300', 'i9305', + 'maguro', 'n5100', 'n5110', 'n7000', 'n7100'] + +class RecoveryRuntime(object): + def __init__(self, config, host, device, release, quiet=False): + self.config = config + self.quiet = quiet + self.host = host + self.device = device + self.release = release + + @trace + def get_partition(self, partition): + if not self.release.major_version == '6.0': + assert(False) + + if str(self.device) in ['i9100', 'i9300', 'n7100', 'n5100']: + return '/dev/block/platform/dw_mmc/by-name/' + str(partition) + elif str(self.device) in ['maguro']: + return '/dev/block/platform/omap/omap_hsmmc.0/by-name/' \ + + str(partition) + elif str(self.device) in ['p3100']: + return '/dev/block/platform/omap/omap_hsmmc.1/by-name/' \ + + str(partition) + else: + # TODO: + # - i9305 + # - n5110 + # - n7000 + # - p3110 + # - p311 + # - p5100 + # - p5510 + assert(False) + + @trace + def get_boot_partition(self): + if self.release.major_version != '6.0': + # TODO + assert(False) + + if str(self.device) in ['i9300', 'i9305', 'n7100']: + return self.get_partition('BOOT') + else: + # TODO: + # - i9100 + # - maguro + # - n5110 + # - n7000 + # - p3100 + # - p3110 + # - p3113 + # - p5100 + # - p5100 + # - p5510 + assert(False) + + @trace + def get_cache_partition(self): + if self.release.major_version != '6.0': + # TODO + assert(False) + + if str(self.device) in ['maguro']: + return self.get_partition('cache') + elif str(self.device) in ['espresso3g', 'espressowifi', 'i9100', + 'i9300', 'i9305', 'n5100', 'n5110', 'n7000', + 'n7100']: + return self.get_partition('CACHE') + else: + # TODO: + # - p3110 + # - p3113 + # - p5100 + # - p5510 + assert(False) + + @trace + def wait_for_ready(self): + self.host.run(['adb', 'wait-for-recovery']) + + @trace + def is_remote(self): + if self.config['machine'] == None: + return False + if re.match('^ssh://', self.config['machine']): + return True + else: + return False + + @trace + def run(self, commands): + result = None + + if not self.quiet: + print('\tRunning \'{}\''.format(' '.join(commands))) + + if type(commands) == type(list()): + commands = ' '.join(commands) + + shell_command = 'cd {} && {}'.format('~', + 'adb shell ' + + '"' + + commands.replace('"', '\\"') + + '"') + + self.wait_for_ready() + + if self.is_remote(): + machine = re.sub('^ssh://', '', self.config['machine']) + result = sh.ssh(machine, shell_command) + else: + result = sh.bash('-c', shell_command) + + return result + + @trace + def mount_cache(self): + return self.run(['mount', self.get_cache_partition(), '/cache']) + + # Documentation: bootable/recovery/recovery.cpp + @trace + def append_recovery_command(self, command): + self.wait_for_ready() + self.run(['echo', command, '>>', '/cache/recovery/command']) + + @trace + def wipe_cache_and_data(self): + if not self.quiet: + print('Starting to wipe the data data and cache partition:') + + self.mount_cache() + + self.append_recovery_command('--wipe_data') + + self.host.run(['adb', 'reboot', 'recovery']) + + @trace + def install_zip(self, recovery_path): + filename = recovery_path.split(os.sep)[-1] + + if not self.quiet: + print('RecoveryRuntime.install_zip: ' + + 'Starting to install {} on {}'.format(filename, self.device)) + + self.append_recovery_command('--sideload') + self.host.run(['adb', 'reboot', 'recovery']) + + @trace + def install_boot_img(self, path, retries=100): + if not self.quiet: + print('Starting to install the {} boot image on {}'.format( + path, self.device)) + + filename = os.path.basename(path) + partition = self.get_boot_partition() + + self.host.run(['adb', 'wait-for-recovery']) + self.host.run(['adb', 'push', path, '/' + filename]) + self.host.run(['adb', 'shell', 'dd', 'if=/dev/zero', 'of=' + partition]) + self.host.run(['adb', 'shell', 'dd', 'if=' + filename, 'of=' + partition]) + self.host.run(['adb', 'shell', 'sync']) + self.host.run(['adb', 'shell', 'rm', '-f', '/' + filename]) + +def install_replicant_release(local_config, + major_version, minor_version, + device, wipe_cache_and_data=True, + add_root=True, + disable_modem=False, quiet=False): + if not quiet: + print('RecoveryRuntime.install_replicant_release: ' + + 'Installing Replicant {} release for the {}'.format( + minor_version, device)) + host = lib.hosts.Host(local_config, quiet=quiet) + device = lib.devices.Device(host, device, quiet=quiet) + + release = lib.replicant_releases.ReplicantRelease(local_config, + major_version, + minor_version, + host, device, quiet) + + runtime = lib.devices.DeviceRuntime(local_config, host, device, release, + quiet=quiet) + + runtime.install_recovery(release.get_recovery_path(), add_root) + if wipe_cache_and_data: + runtime.wipe_cache_and_data() + runtime.install_zip(release.get_zip_path(), add_root, disable_modem) + runtime.boot('replicant') + runtime.wait_for_boot_complete() |