Skip to content
Snippets Groups Projects
Verified Commit 00940f62 authored by Karel Koci's avatar Karel Koci :metal:
Browse files

Add boot container and initial support for loading system to RAM

parent 97c4aa3b
1 merge request!2Initial development
......@@ -4,3 +4,22 @@
# This is image used to boot medkit. It provides TFTP server with prepared image
# for u-boot.
##################################################################################
set -e
# Make prepare script executable so we can later run it
chmod +x "/bin/prepare_turris_image"
# Configure WAN interface for static local network
cat >> /etc/network/interfaces <<EOF
auto wan
iface wan inet static
address 192.168.1.1
netmask 255.255.255.0
EOF
# Install utilities we need to repack image
apk add uboot-tools
# Install and enable TFTP server
apk add tftp-hpa
rc-update add "in.tftpd" default
#!/bin/bash
set -e
TFTP_ROOT="/var/tftpboot"
# TODO use this
BOARD="$1"
MODE="$2"
TARGET="$3"
# TODO
# Get appropriate medkit
wait4network
wget "https://repo.turris.cz/hbk/medkit/omnia-medkit-latest.tar.gz" -O medkit.tar.gz
# Repack as CPIO
mkdir root
tar -xzf medkit.tar.gz -C root
( cd root && find . | cpio -H newc -o > ../root.cpio )
mkimage -A arm -O linux -T ramdisk -C none -d root.cpio root.uimage
# Prepare to TFTP
cp root/boot/zImage "$TFTP_ROOT/zImage"
cp -L root/boot/dtb "$TFTP_ROOT/dtb"
mv root.uimage "$TFTP_ROOT/root.uimage"
# Clean after ourself
rm -rf root root.cpio medkit.tar.gz
......@@ -7,6 +7,7 @@ import serial
import serial.tools.miniterm
from pexpect import fdpexpect
from . import cli
from .lxd import Container
MINITERM_DEFAULT_EXIT = '\x1d' # Ctrl+]
MINITERM_DEFAULT_MENU = '\x14' # Ctrl+T
......@@ -50,15 +51,28 @@ class Board():
self.pexpect.sendline("")
return cli.Uboot(self.pexpect)
def bootup(self):
def bootup(self, device_wan):
"""Boot board using TFTP boot. This ensures that board is booted up and ready to accept commands.
device_wan: Wan device to board. This is instance of nsfarm.lxd.NetInterface.
Returns instance of cli.Shell
"""
# First get U-Boot prompt
uboot = self.uboot()
# Now load FIT image from TFTP
# TODO
# Now load image from TFTP
with Container("boot", devices=[device_wan, ]) as cont:
ccli = cli.Shell(cont.pexpect())
ccli.run("prepare_turris_image")
assert uboot.batch([
'setenv ipaddr 192.168.1.142',
'setenv serverip 192.168.1.1',
'tftpboot 0x01000000 192.168.1.1:zImage',
'tftpboot 0x02000000 192.168.1.1:dtb',
'tftpboot 0x03000000 192.168.1.1:root.uimage',
'setenv bootargs "earlyprintk console=ttyS0,115200 rootfstype=ramfs initrd=0x03000000"',
], timeout=120)
self.pexpect.sendline('bootz 0x01000000 0x03000000 0x02000000')
# Wait for bootup
self.pexpect.expect_exact(["Router Turris successfully started.", ])
# Note Shell sends new line which opens terminal for it
......
......@@ -68,7 +68,7 @@ class Console:
command from output.
"""
self.sendline(cmd)
if not self.sexpect_exact(cmd + '\r\n'):
if not self.sexpect_exact(cmd) or not self.sexpect("(\r\n|\n\r)"):
# TODO better exception
raise Exception("cmd used but terminal probably does not echoes.")
......@@ -129,11 +129,11 @@ class Shell(Cli):
This is tested to handle busybox and bash.
"""
_SET_NSF_PROMPT = r"export PS1='nsfprompt:$(echo -n $?)\$ '"
_NSF_PROMPT = r"(\r\n|^)nsfprompt:([0-9]+)($|#) "
_NSF_PROMPT = r"(\r\n|\n\r|^)nsfprompt:([0-9]+)($|#) "
_INITIAL_PROMPTS = [
r"(\r\n|^).+? ($|#) ",
r"(\r\n|^)bash-.+?($|#) ",
r"(\r\n|^)root@[a-zA-Z0-9_-]*:",
r"(\r\n|\n\r|^).+? ($|#) ",
r"(\r\n|\n\r|^)bash-.+?($|#) ",
r"(\r\n|\n\r|^)root@[a-zA-Z0-9_-]*:",
_NSF_PROMPT,
]
# TODO compile prompt regexp to increase performance
......@@ -143,7 +143,6 @@ class Shell(Cli):
# Firt check if we are on some sort of shell prompt
self.cmd()
if not self.sexpect(self._INITIAL_PROMPTS):
print(self.before)
# TODO better exception
raise Exception("Initial shell prompt not found")
# Now sanitize prompt format
......@@ -164,7 +163,7 @@ class Shell(Cli):
class Uboot(Cli):
"""U-boot prompt support class.
"""
_PROMPT = "(\r\n|^)=> "
_PROMPT = "(\r\n|\n\r|^)=> "
_EXIT_CODE_ECHO = "echo $?"
def __init__(self, pexpect_handle, flush=True):
......@@ -190,3 +189,9 @@ class Uboot(Cli):
@property
def output(self):
return self._output
# Notest on some of the hacks in this file
#
# There are new line character matches in regular expressions. Correct one is \r\n but some serial controlles for some
# reason also use \n\r so we match both alternatives.
......@@ -203,6 +203,7 @@ class Container():
def pexpect(self, shell="/bin/sh"):
"""Returns pexpect handle for shell in container.
"""
# TODO some logging of this session
assert self._lxd_container is not None
return pexpect.spawn('lxc', ["exec", self._lxd_container.name, shell])
......@@ -247,16 +248,8 @@ class Container():
"""
return self._hash
@property
def image_alias(self):
"""Alias of image for this container.
"""
return self._image_alias
class BootContainer(Container):
"""Extension for Container handling specific tasks for container used to boot medkit on board.
"""
# TODO branch or build to pull?
def __init__(self, *args, **kwargs):
super().__init__("boot", *args, **kwargs)
import pytest
import nsfarm.board
import nsfarm.cli
import nsfarm.lxd
@pytest.fixture(scope="session", name="board", params=[pytest.param(None, marks=pytest.mark.serial)])
......@@ -23,11 +24,17 @@ def board_uboot(request, board):
return board.uboot()
@pytest.fixture(scope="session", name="wan", params=[pytest.param(None, marks=pytest.mark.wan)])
def fixture_wan(request):
"""Top level fixture used to share WAN interface handler.
"""
return nsfarm.lxd.NetInterface("wan", request.config.target_config['wan'])
@pytest.fixture(scope="session")
def board_shell(request, board):
def board_shell(request, board, wan):
"""Boot board to Shell.
Provides instance of nsfarm.cli.Shell()
"""
request.addfinalizer(lambda: board.reset(True))
# TODO prepare wan container with appropriate medkit
return board.bootup()
return board.bootup(wan)
import pytest
def no_test_help(board, board_uboot):
def test_terminal(board, board_shell):
board.serial_miniterm()
def test_cpu_env(board, board_uboot):
def no_test_cpu_env(board, board_uboot):
assert board_uboot.run("printenv cpu")
assert board_uboot.output == "cpu=armv7"
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment