Source code for labgrid.driver.smallubootdriver

import attr

from ..factory import target_factory
from ..util import gen_marker
from ..step import step
from .common import Driver

from .ubootdriver import UBootDriver
from ..util import re_vt100

[docs] @target_factory.reg_driver @attr.s(eq=False) class SmallUBootDriver(UBootDriver): """ SmallUBootDriver is meant as a driver for UBoot with only little functionality compared to standard a standard UBoot. Especially is copes with the following limitations: - The UBoot does not have a real password-prompt but can be activated by entering a "secret" after a message was displayed. - The command line is does not have a build-in echo command. Thus this driver uses 'Unknown Command' messages as marker before and after the output of a command. - Since there is no echo we can not return the exit code of the command. Commands will always return 0 unless the command was not found. This driver needs the following features activated in UBoot to work: - The UBoot must not have real password prompt. Instead it must be keyword activated. For example it should be activated by a dialog like the following: UBoot: "Autobooting in 1s..." Labgrid: "secret" UBoot: <switching to console> - The UBoot must be able to parse multiple commands in a single line separated by ";". - The UBoot must support the "bootm" command to boot from a memory location. This driver was created especially for the following devices: - TP-Link WR841 v11 Args: boot_secret (str): optional, secret used to unlock prompt boot_secret_nolf (bool): optional, send boot_secret without new line login_timeout (int): optional, timeout for login prompt detection, """ boot_expression = attr.ib(default=r"U-Boot 20\d+", validator=attr.validators.instance_of(str)) boot_secret = attr.ib(default="a", validator=attr.validators.instance_of(str)) boot_secret_nolf = attr.ib(default=False, validator=attr.validators.instance_of(bool)) login_timeout = attr.ib(default=60, validator=attr.validators.instance_of(int)) @step() def _await_prompt(self): """ Await autoboot_expression. If this line was read enter the 'secret' (or a single character) to interrupt normal boot. """ # wait for boot expression. Afterwards enter secret self.console.expect(self.boot_expression, timeout=self.login_timeout) if self.boot_secret_nolf: self.console.write(self.boot_secret.encode('ASCII')) else: self.console.sendline(self.boot_secret) self._status = 1 # wait until UBoot has reached it's prompt self.console.expect(self.prompt) for command in self.init_commands: self._run(command) def _run(self, cmd: str, *, timeout: int = 30, codec: str = "utf-8", decodeerrors: str = "strict"): # pylint: disable=line-too-long """ If Uboot is in Command-Line mode: Run command cmd and return it's output. Arguments: cmd - Command to run """ # TODO: use codec, decodeerrors # Check if Uboot is in command line mode if self._status != 1: return None marker = gen_marker() # Create multi-part command like we would do for a normal uboot. # but since this simple uboot does not have an echo-command we will # handle it's error message as an echo-output. # additionally we are not able to get the command's return code and # will always return 0. cmp_command = f"echo{marker}; {cmd}; echo{marker}" self.console.sendline(cmp_command) _, before, _, _ = self.console.expect(self.prompt, timeout=timeout) data = re_vt100.sub( '', before.decode('utf-8'), count=1000000 ).replace("\r", "").split("\n") data = data[1:] data = data[data.index(f"Unknown command 'echo{marker}' - try 'help'") +1 :] data = data[:data.index(f"Unknown command 'echo{marker}' - try 'help'")] if len(data) >= 1: if data[0].startswith("Unknown command '"): return (data, [], 1) return (data, [], 0)
[docs] @Driver.check_active @step(args=['name'], result=True) def boot(self, name): """ Boot the device from the given memory location using 'bootm'. Args: name (str): address to boot """ self.console.sendline(f"bootm {name}")