Source code for wlauto.utils.uboot

#    Copyright 2014-2015 ARM Limited
# 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
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
import re
import time
import logging
from distutils.version import LooseVersion
from wlauto.utils.serial_port import TIMEOUT

logger = logging.getLogger('U-Boot')

[docs]class UbootMenu(object): """ Allows navigating Das U-boot menu over serial (it relies on a pexpect connection). """ option_regex = re.compile(r'^\[(\d+)\]\s+([^\r]+)\r\n', re.M) prompt_regex = re.compile(r'^([^\r\n]+):\s*', re.M) invalid_regex = re.compile(r'Invalid input \(max (\d+)\)', re.M) uboot_regex = re.compile(r"U-Boot\s(\d\S*)\s") load_delay = 1 # seconds default_timeout = 60 # seconds fixed_uboot_version = '2016.03' # The version on U-Boot that fixed newlines def __init__(self, conn, start_prompt='Hit any key to stop autoboot'): """ :param conn: A serial connection as returned by ``pexect.spawn()``. :param prompt: U-Boot menu prompt :param start_prompt: The starting prompt to wait for during ``open()``. """ self.conn = conn self.conn.crlf = None self.start_prompt = start_prompt self.options = {} self.prompt = None
[docs] def open(self, timeout=default_timeout): """ "Open" the UEFI menu by sending an interrupt on STDIN after seeing the starting prompt (configurable upon creation of the ``UefiMenu`` object. """ self.conn.expect(self.start_prompt, timeout) self._set_line_separator() self.conn.sendline('') time.sleep(self.load_delay) self.conn.readline() # garbage self.conn.sendline('') self.prompt = self.conn.readline().strip()
[docs] def getenv(self): output = self.enter('printenv') result = {} for line in output.split('\n'): if '=' in line: variable, value = line.split('=', 1) result[variable.strip()] = value.strip() return result
[docs] def setenv(self, variable, value, force=False): force_str = ' -f' if force else '' if value is not None: command = 'setenv{} {} {}'.format(force_str, variable, value) else: command = 'setenv{} {}'.format(force_str, variable) return self.enter(command)
[docs] def boot(self): self.write_characters('boot')
[docs] def nudge(self): """Send a little nudge to ensure there is something to read. This is useful when you're not sure if all out put from the serial has been read already.""" self.enter('')
[docs] def enter(self, value, delay=load_delay): """Like ``select()`` except no resolution is performed -- the value is sent directly to the serial connection.""" # Empty the buffer first, so that only response to the input about to # be sent will be processed by subsequent commands. value = str(value) self.empty_buffer() self.write_characters(value) self.conn.expect(self.prompt, timeout=delay) return self.conn.before
[docs] def write_characters(self, line): line = line.rstrip('\r\n') for c in line: self.conn.send(c) time.sleep(0.05) self.conn.sendline('')
[docs] def empty_buffer(self): try: while True: time.sleep(0.1) self.conn.read_nonblocking(size=1024, timeout=0.1) except TIMEOUT: pass self.conn.buffer = ''
def _set_line_separator(self): uboot_text = self.conn.before uboot_ver = self.uboot_regex.findall(uboot_text) if uboot_ver and LooseVersion(uboot_ver[0]) < LooseVersion(self.fixed_uboot_version): self.conn.crlf = "\n\r" else: self.conn.crlf = "\r\n"