1########################################################################## 2# Copyright (c) 2014-2016 ETH Zurich. 3# All rights reserved. 4# 5# This file is distributed under the terms in the attached LICENSE file. 6# If you do not find this file, copies can be found by writing to: 7# ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group. 8########################################################################## 9 10import debug, eth_machinedata 11import subprocess, os, socket, sys, shutil, tempfile, pty 12from machines import ARMMachineBase, MachineFactory, MachineOperations 13from machines.eth import ETHBaseMachineOperations 14 15# XXX: the rack-mount pandaboard machines are ETH-specific 16PANDA_ROOT='/mnt/emmentaler1_nfs/pandaboot' 17PANDA_BOOT_HOST='masterpanda.in.barrelfish.org' 18PANDA_PORT=10000 19TOOLS_PATH='/home/netos/tools/bin' 20RACKBOOT=os.path.join(TOOLS_PATH, 'rackboot.sh') 21RACKPOWER=os.path.join(TOOLS_PATH, 'rackpower') 22 23 24class PandaboardMachine(ARMMachineBase): 25 '''Machine to run tests on locally attached pandaboard. Assumes your 26 pandaboard's serial port is attached to /dev/ttyUSB0''' 27 name = 'panda_local' 28 imagename = "armv7_omap44xx_image" 29 30 def __init__(self, options, **kwargs): 31 super(PandaboardMachine, self).__init__(options, PandaboardOperations(self), **kwargs) 32 self.menulst_template = "menu.lst.armv7_omap44xx" 33 34 def setup(self, builddir=None): 35 pass 36 37 def get_buildall_target(self): 38 return "PandaboardES" 39 40class PandaboardOperations(MachineOperations): 41 42 def __init__(self, machine): 43 super(PandaboardOperations, self).__init__(machine) 44 self.picocom = None 45 self.tftp_dir = None 46 self.masterfd = None 47 48 def get_tftp_dir(self): 49 if self.tftp_dir is None: 50 self.tftp_dir = tempfile.mkdtemp(prefix="panda_") 51 return self.tftp_dir 52 53 def set_bootmodules(self, modules): 54 menulst_fullpath = os.path.join(self._machine.options.builds[0].build_dir, 55 "platforms", "arm", self._machine.menulst_template) 56 self._machine._write_menu_lst(modules.get_menu_data("/"), menulst_fullpath) 57 debug.verbose("building proper pandaboard image") 58 debug.checkcmd(["make", self._machine.imagename], 59 cwd=self._machine.options.builds[0].build_dir) 60 61 def __usbboot(self): 62 debug.verbose("Usbbooting pandaboard; press reset") 63 debug.verbose("build dir: %s" % self._machine.options.builds[0].build_dir) 64 debug.checkcmd(["make", "usbboot_panda"], 65 cwd=self._machine.options.builds[0].build_dir) 66 67 def lock(self): 68 pass 69 70 def unlock(self): 71 pass 72 73 def reboot(self): 74 self.__usbboot() 75 76 def shutdown(self): 77 '''shutdown: close picocom''' 78 # FIXME: sending C-A C-X to close picocom does not seem to work 79 #if self.masterfd is not None: 80 # debug.verbose("Sending C-A C-X to picocom") 81 # os.write(self.masterfd, "\x01\x24") 82 if self.picocom is not None: 83 debug.verbose("Killing picocom") 84 self.picocom.kill() 85 try: 86 os.unlink("/var/lock/LCK..ttyUSB0") 87 except OSError: 88 pass 89 self.picocom = None 90 self.masterfd = None 91 92 def get_output(self): 93 '''Use picocom to get output. This replicates part of 94 ETHMachine.lock()''' 95 (self.masterfd, slavefd) = pty.openpty() 96 self.picocom = subprocess.Popen( 97 ["picocom", "-b", "115200", "/dev/ttyUSB0"], 98 close_fds=True, stdout=slavefd, stdin=slavefd) 99 os.close(slavefd) 100 self.console_out = os.fdopen(self.masterfd, 'rb', 0) 101 return self.console_out 102 103 104class ETHRackPandaboardMachine(ARMMachineBase): 105 _machines = eth_machinedata.pandaboards 106 imagename = "armv7_omap44xx_image" 107 108 def __init__(self, options, **kwargs): 109 super(ETHRackPandaboardMachine, self).__init__(options, ETHRackPandaboardMachineOperations(self), **kwargs) 110 self.menulst_template = "menu.lst.armv7_omap44xx" 111 112 def setup(self, builddir=None): 113 pass 114 115 # pandaboard specifics 116 def get_platform(self): 117 return 'omap44xx' 118 119 def get_buildall_target(self): 120 return "PandaboardES" 121 122class ETHRackPandaboardMachineOperations(ETHBaseMachineOperations): 123 124 def __init__(self, machine): 125 super(ETHRackPandaboardMachineOperations, self).__init__(machine) 126 self._tftp_dir = None 127 self.targe_name = None 128 129 def __chmod_ar(self, file): 130 '''make file/directory readable by all''' 131 import stat 132 extra = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH 133 if os.path.isdir(file): 134 extra |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH 135 os.chmod(file, os.stat(file).st_mode | extra) 136 137 def get_tftp_dir(self): 138 if self._tftp_dir is None: 139 self._tftp_dir = tempfile.mkdtemp(dir=PANDA_ROOT, prefix="%s_" % self._machine.getName()) 140 self.__chmod_ar(self._tftp_dir) 141 return self._tftp_dir 142 143 def set_bootmodules(self, modules): 144 menulst_fullpath = os.path.join(self._machine.options.builds[0].build_dir, 145 "platforms", "arm", self._machine.menulst_template) 146 self._machine._write_menu_lst(modules.get_menu_data("/"), menulst_fullpath) 147 source_name = os.path.join(self._machine.options.builds[0].build_dir, self._machine.imagename) 148 self.target_name = os.path.join(self.get_tftp_dir(), self._machine.imagename) 149 debug.verbose("building proper pandaboard image") 150 debug.checkcmd(["make", self._machine.imagename], 151 cwd=self._machine.options.builds[0].build_dir) 152 debug.verbose("copying %s to %s" % (source_name, self.target_name)) 153 shutil.copyfile(source_name, self.target_name) 154 self.__chmod_ar(self.target_name) 155 156 def __usbboot(self): 157 pandanum = self._machine.get_machine_name()[5:] 158 imagename = os.path.relpath(self.target_name, PANDA_ROOT) 159 # send "boot PANDANUM pandaboot/$tempdir/IMAGE_NAME" to 160 # masterpanda:10000 161 debug.verbose("sending boot command for pandaboard %s; pandaboard_image %s" % (pandanum, imagename)) 162 masterpanda_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 163 masterpanda_sock.connect((PANDA_BOOT_HOST, PANDA_PORT)) 164 masterpanda_sock.send('boot %s pandaboot/%s\n' % 165 (pandanum, imagename)) 166 masterpanda_sock.shutdown(socket.SHUT_WR) 167 while True: 168 data = masterpanda_sock.recv(1024) 169 os.write(sys.stdout.fileno(), data) 170 if data == "": 171 break 172 173 def _get_console_status(self): 174 # for Pandaboards we cannot do console -i <machine> so we grab full -i 175 # output and find relevant line here 176 proc = subprocess.Popen(["console", "-i"], stdout=subprocess.PIPE) 177 output = proc.communicate()[0] 178 assert(proc.returncode == 0) 179 output = map(str.strip, output.split("\n")) 180 return filter(lambda l: l.startswith(self._machine.get_machine_name()), output)[0] 181 182 def __rackpower(self, arg): 183 try: 184 debug.checkcmd([RACKPOWER, arg, self._machine.get_machine_name()]) 185 except subprocess.CalledProcessError: 186 debug.warning("rackpower %s %s failed" % 187 (arg, self._machine.get_machine_name())) 188 189 def reboot(self): 190 self.__usbboot() 191 192 def shutdown(self): 193 self.__rackpower('-d') 194 195for pb in ETHRackPandaboardMachine._machines: 196 class TmpMachine(ETHRackPandaboardMachine): 197 name = pb 198 MachineFactory.addMachine(pb, TmpMachine, **ETHRackPandaboardMachine._machines[pb]) 199 200MachineFactory.addMachine("panda_local", PandaboardMachine, 201 bootarch='armv7', 202 platform='omap44xx', 203 ncores=2) 204