1##########################################################################
2# Copyright (c) 2012-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 os, tempfile, subprocess, time
11import debug
12from machines import ARMSimulatorBase, MachineFactory, ARMSimulatorOperations
13import efiimage
14
15FVP_PATH = '/home/netos/tools/DS-5/bin'
16
17# Get the prebuilt binary snapshots (fvp-uefi.zip) from:
18# https://community.arm.com/docs/DOC-10952
19FVP_UEFI_BL1="/home/netos/tools/fvp-uefi/bl1.bin"
20FVP_UEFI_FIP="/home/netos/tools/fvp-uefi/fip.bin"
21FVP_LICENSE = '8224@sgv-license-01.ethz.ch'
22FVP_START_TIMEOUT = 2 # in seconds
23
24class FVPMachineBase(ARMSimulatorBase):
25    imagename = "armv7_a9ve_1_image"
26
27    def __init__(self, options, operations, **kwargs):
28        if operations is None:
29            operations = FVPMachineBaseOperations(self)
30        super(FVPMachineBase, self).__init__(options, operations, **kwargs)
31        self.simulator_start_timeout = FVP_START_TIMEOUT
32
33    def get_buildall_target(self):
34        return "VExpressEMM-A9"
35
36class FVPMachineBaseOperations(ARMSimulatorOperations):
37
38    def get_tftp_dir(self):
39        if self.tftp_dir is None:
40            debug.verbose('Creating temporary directory for FVP files')
41            self.tftp_dir = tempfile.mkdtemp(prefix='harness_fvp_')
42            debug.verbose('FVP install directory is %s' % self.tftp_dir)
43        return self.tftp_dir
44
45    def reboot(self):
46        self._kill_child()
47        cmd = self._get_cmdline()
48        debug.verbose('starting "%s" in FVP:reboot' % ' '.join(cmd))
49        env = dict(os.environ)
50        env['ARMLMD_LICENSE_FILE'] = FVP_LICENSE
51        self.child = \
52            subprocess.Popen(cmd, stdout=subprocess.PIPE,
53                             stderr=subprocess.STDOUT, env=env)
54        #time.sleep(FVP_START_TIMEOUT)
55
56
57class FVPMachineARMv7(FVPMachineBase):
58
59    def __init__(self, options, operations, **kwargs):
60        super(FVPMachineARMv7, self).__init__(options, operations, **kwargs)
61
62    def set_bootmodules(self, modules):
63        # write menu.lst in build directory
64        debug.verbose("writing menu.lst in build directory")
65        menulst_fullpath = os.path.join(self.options.builds[0].build_dir,
66                "platforms", "arm", "menu.lst.armv7_a9ve_1")
67        debug.verbose("writing menu.lst in build directory: %s" %
68                menulst_fullpath)
69        self._write_menu_lst(modules.get_menu_data("/"), menulst_fullpath)
70        debug.verbose("building proper FVP image")
71        debug.checkcmd(["make", self.imagename],
72                cwd=self.options.builds[0].build_dir)
73
74class FVPMachineARMv7NCores(FVPMachineARMv7):
75
76    def __init__(self, options, **kwargs):
77        super(FVPMachineARMv7NCores, self).__init__(options, FVPMachineARMv7NCoresOperations(self), **kwargs)
78
79class FVPMachineARMv7NCoresOperations(FVPMachineBaseOperations):
80
81    def _get_cmdline(self):
82        self.get_free_port()
83
84        return [os.path.join(FVP_PATH, "FVP_VE_Cortex-A9x" + str(self._machine.get_ncores())),
85                # Don't try to pop an LCD window up
86                "-C", "motherboard.vis.disable_visualisation=1",
87                # Don't start a telnet xterm
88                "-C", "motherboard.terminal_0.start_telnet=0",
89                "-C", "motherboard.terminal_0.start_port=%d" % self.telnet_port,
90                self._machine.kernel_img]
91
92# Single core machine
93MachineFactory.addMachine("armv7_fvp", FVPMachineARMv7NCores,
94                          bootarch="armv7",
95                          platform="a9ve")
96
97# Quad-core machine
98MachineFactory.addMachine('armv7_fvp_4', FVPMachineARMv7NCores,
99                          bootarch="armv7",
100                          platform="a9ve",
101                          ncores=4)
102
103
104class FVPMachineEFI(FVPMachineBase):
105    imagename = "armv8_efi"
106
107    def __init__(self, options, simulator=None, **kwargs):
108        super(FVPMachineEFI, self).__init__(options, FVPMachineEFIOperations(self), **kwargs)
109        assert(simulator)
110        self.simulator = simulator
111
112    def set_bootmodules(self, modules):
113        # write menu.lst in build directory
114        debug.verbose("writing menu.lst in build directory")
115        menulst_fullpath = os.path.join(self.options.builds[0].build_dir,
116                "platforms", "arm", "menu.lst.armv8_base")
117        debug.verbose("writing menu.lst in build directory: %s" %
118                menulst_fullpath)
119        self._write_menu_lst(modules.get_menu_data("/"), menulst_fullpath)
120
121#        debug.checkcmd(["make"] + modules.get_build_targets(), cwd=self.options.builds[0].build_dir)
122
123        debug.verbose("building proper FVP image")
124        efi = efiimage.EFIImage(self.kernel_img, 200)
125        efi.create()
126        for module in modules.get_build_targets():
127            efi.addFile(os.path.join(self.options.builds[0].build_dir, module), module)
128        efi.writeFile("startup.nsh", "Hagfish.efi hagfish.cfg")
129        efi.addFile("/home/netos/tftpboot/Hagfish.efi", "Hagfish.efi")
130        efi.addFile(menulst_fullpath, "hagfish.cfg")
131
132    def get_buildall_target(self):
133        # XXX: this is a misnomer in hake for the a57v platform
134        return "FVP"
135
136class FVPMachineEFIOperations(FVPMachineBaseOperations):
137
138
139    def get_output(self):
140        return self.child.stdout
141
142    def _get_cmdline(self):
143        self.get_free_port()
144
145        return [os.path.join(FVP_PATH, self._machine.simulator),
146                # Don't try to pop an LCD window up
147                "-C", "bp.vis.disable_visualisation=1",
148                # Don't start a telnet xterm
149                "-C", "bp.terminal_0.start_telnet=0",
150                "-C", "bp.terminal_1.start_telnet=0",
151                "-C", "bp.secureflashloader.fname=%s" % FVP_UEFI_BL1,
152                "-C", "bp.flashloader0.fname=%s" % FVP_UEFI_FIP,
153                "-C", "bp.mmc.p_mmc_file=%s" % self._machine.kernel_img,
154                "-C", "bp.pl011_uart0.unbuffered_output=1",
155                # This has to be the last parameter because otherwise the command
156                # passed to the OS has incorrect parameters. Don't know why
157                # MH 11/2016
158                "-C", "bp.pl011_uart0.out_file=-",
159                ]
160
161MachineFactory.addMachine('armv8_fvp_base', FVPMachineEFI,
162                          bootarch='armv8',
163                          platform='a57_fvp',
164                          boot_timeout=60,
165                          simulator="FVP_Base_AEMv8A")
166
167MachineFactory.addMachine('armv8_fvp_a57x1', FVPMachineEFI,
168                          bootarch='armv8',
169                          boot_driver = 'boot_armv8_generic',
170                          platform='a57_fvp',
171                          boot_timeout=60,
172                          simulator="FVP_Base_Cortex-A57x1")
173
174MachineFactory.addMachine('armv8_fvp_a57x2_a53x4', FVPMachineEFI,
175                          bootarch='armv8',
176                          boot_driver = 'boot_armv8_generic',
177                          platform='a57_fvp',
178                          boot_timeout=60,
179                          simulator="FVP_Base_Cortex-A57x2-A53x4")
180