Do not combine -nographic and -serial stdio at the
[helenos.git] / tools / ew.py
blob56befd80bae4cb11df2d7fe39bd7ca8573a30099
1 #!/usr/bin/env python
3 # Copyright (c) 2013 Jakub Jermar
4 # All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
10 # - Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # - Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
15 # - The name of the author may not be used to endorse or promote products
16 # derived from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 """
32 Emulator wrapper for running HelenOS
33 """
35 import os
36 import sys
37 import subprocess
38 import autotool
39 import platform
40 import thread
41 import time
43 overrides = {}
45 def is_override(str):
46 if str in overrides.keys():
47 return overrides[str]
48 return False
50 def cfg_get(platform, machine, processor):
51 if machine == "" or emulators[platform].has_key("run"):
52 return emulators[platform]
53 elif processor == "" or emulators[platform][machine].has_key("run"):
54 return emulators[platform][machine]
55 else:
56 return emulators[platform][machine][processor]
58 def termemu_detect():
59 for termemu in ['xfce4-terminal', 'xterm']:
60 try:
61 subprocess.check_output('which ' + termemu, shell = True)
62 return termemu
63 except:
64 pass
66 def run_in_console(cmd, title):
67 ecmd = cmd.replace('"', '\\"')
68 cmdline = termemu_detect() + ' -T ' + '"' + title + '"' + ' -e "' + ecmd + '"'
69 print(cmdline)
70 if not is_override('dryrun'):
71 subprocess.call(cmdline, shell = True)
73 def get_host_native_width():
74 return int(platform.architecture()[0].strip('bit'))
76 def pc_options(guest_width):
77 opts = ''
79 # Do not enable KVM if running 64 bits HelenOS
80 # on 32 bits host
81 host_width = get_host_native_width()
82 if guest_width <= host_width and not is_override('nokvm'):
83 opts = opts + ' -enable-kvm'
85 # Remove the leading space
86 return opts[1:]
88 def malta_options():
89 return '-cpu 4Kc'
91 def platform_to_qemu_options(platform, machine, processor):
92 if platform == 'amd64':
93 return 'system-x86_64', pc_options(64)
94 elif platform == 'arm32':
95 return 'system-arm', '-M integratorcp'
96 elif platform == 'ia32':
97 return 'system-i386', pc_options(32)
98 elif platform == 'mips32':
99 if machine == 'lmalta':
100 return 'system-mipsel', malta_options()
101 elif machine == 'bmalta':
102 return 'system-mips', malta_options()
103 elif platform == 'ppc32':
104 return 'system-ppc', '-m 256'
105 elif platform == 'sparc64':
106 if machine != 'generic':
107 raise Exception
108 if processor == 'us':
109 return 'system-sparc64', '-M sun4u --prom-env boot-args="console=devices/\\hw\\pci0\\01:01.0\\com1\\a"'
110 elif processor == 'sun4v':
111 default_path = '/usr/local/opensparc/image/'
112 try:
113 if os.path.exists(default_path):
114 opensparc_bins = default_path
115 elif os.path.exists(os.environ['OPENSPARC_BINARIES']):
116 opensparc_bins = os.environ['OPENSPARC_BINARIES']
117 else:
118 raise Exception
119 except:
120 print("Cannot find OpenSPARC binary images!")
121 print("Either set OPENSPARC_BINARIES environment variable accordingly or place the images in %s." % (default_path))
122 raise Exception
124 return 'system-sparc64', '-M niagara -m 256 -L %s' % (opensparc_bins)
127 def hdisk_mk():
128 if not os.path.exists('hdisk.img'):
129 subprocess.call('tools/mkfat.py 1048576 uspace/dist/data hdisk.img', shell = True)
131 def qemu_bd_options():
132 if is_override('nohdd'):
133 return ''
135 hdisk_mk()
137 return ' -drive file=hdisk.img,index=0,media=disk,format=raw'
139 def qemu_nic_ne2k_options():
140 return ' -device ne2k_isa,irq=5,vlan=0'
142 def qemu_nic_e1k_options():
143 return ' -device e1000,vlan=0'
145 def qemu_nic_rtl8139_options():
146 return ' -device rtl8139,vlan=0'
148 def qemu_nic_virtio_options():
149 return ' -device virtio-net,vlan=0'
151 def qemu_net_options():
152 if is_override('nonet'):
153 return ''
155 nic_options = ''
156 if 'net' in overrides.keys():
157 if 'e1k' in overrides['net'].keys():
158 nic_options += qemu_nic_e1k_options()
159 if 'rtl8139' in overrides['net'].keys():
160 nic_options += qemu_nic_rtl8139_options()
161 if 'ne2k' in overrides['net'].keys():
162 nic_options += qemu_nic_ne2k_options()
163 if 'virtio-net' in overrides['net'].keys():
164 nic_options += qemu_nic_virtio_options()
165 else:
166 # Use the default NIC
167 nic_options += qemu_nic_e1k_options()
169 return nic_options + ' -net user,hostfwd=udp::8080-:8080,hostfwd=udp::8081-:8081,hostfwd=tcp::8080-:8080,hostfwd=tcp::8081-:8081,hostfwd=tcp::2223-:2223'
171 def qemu_usb_options():
172 if is_override('nousb'):
173 return ''
174 return ' -usb'
176 def qemu_xhci_options():
177 if is_override('noxhci'):
178 return ''
179 return ' -device nec-usb-xhci,id=xhci'
181 def qemu_tablet_options():
182 if is_override('notablet') or (is_override('nousb') and is_override('noxhci')):
183 return ''
184 return ' -device usb-tablet'
186 def qemu_audio_options():
187 if is_override('nosnd'):
188 return ''
189 return ' -device intel-hda -device hda-duplex'
191 def qemu_run(platform, machine, processor):
192 cfg = cfg_get(platform, machine, processor)
193 suffix, options = platform_to_qemu_options(platform, machine, processor)
194 cmd = 'qemu-' + suffix
196 cmdline = cmd
197 if 'qemu_path' in overrides.keys():
198 cmdline = overrides['qemu_path'] + cmd
200 if options != '':
201 cmdline += ' ' + options
203 cmdline += qemu_bd_options()
205 if (not 'net' in cfg.keys()) or cfg['net']:
206 cmdline += qemu_net_options()
207 if (not 'usb' in cfg.keys()) or cfg['usb']:
208 cmdline += qemu_usb_options()
209 if (not 'xhci' in cfg.keys()) or cfg['xhci']:
210 cmdline += qemu_xhci_options()
211 if (not 'tablet' in cfg.keys()) or cfg['tablet']:
212 cmdline += qemu_tablet_options()
213 if (not 'audio' in cfg.keys()) or cfg['audio']:
214 cmdline += qemu_audio_options()
216 console = ('console' in cfg.keys() and cfg['console'])
218 if (is_override('nographic')):
219 cmdline += ' -nographic'
221 if (not console and (not is_override('nographic')) and not is_override('noserial')):
222 cmdline += ' -serial stdio'
224 if (is_override('bigmem')):
225 cmdline += ' -m 4G'
227 if cfg['image'] == 'image.iso':
228 cmdline += ' -boot d -cdrom image.iso'
229 elif cfg['image'] == 'image.boot':
230 cmdline += ' -kernel image.boot'
231 else:
232 cmdline += ' ' + cfg['image']
234 if console:
235 cmdline += ' -nographic'
237 title = 'HelenOS/' + platform
238 if machine != '':
239 title += ' on ' + machine
240 if 'expect' in cfg.keys():
241 cmdline = 'expect -c \'spawn %s; expect "%s" { send "%s" } timeout exp_continue; interact\'' % (cmdline, cfg['expect']['src'], cfg['expect']['dst'])
242 run_in_console(cmdline, title)
243 else:
244 print(cmdline)
245 if not is_override('dryrun'):
246 subprocess.call(cmdline, shell = True)
248 def ski_run(platform, machine, processor):
249 run_in_console('ski -i tools/conf/ski.conf', 'HelenOS/ia64 on ski')
251 def msim_run(platform, machine, processor):
252 hdisk_mk()
253 run_in_console('msim -c tools/conf/msim.conf', 'HelenOS/mips32 on msim')
255 def spike_run(platform, machine, processor):
256 run_in_console('spike -m1073741824:1073741824 image.boot', 'HelenOS/risvc64 on Spike')
258 emulators = {
259 'amd64' : {
260 'run' : qemu_run,
261 'image' : 'image.iso'
263 'arm32' : {
264 'integratorcp' : {
265 'run' : qemu_run,
266 'image' : 'image.boot',
267 'net' : False,
268 'audio' : False,
269 'xhci' : False,
270 'tablet' : False
273 'ia32' : {
274 'run' : qemu_run,
275 'image' : 'image.iso'
277 'ia64' : {
278 'ski' : {
279 'run' : ski_run
282 'mips32' : {
283 'msim' : {
284 'run' : msim_run
286 'lmalta' : {
287 'run' : qemu_run,
288 'image' : 'image.boot',
289 'console' : True
291 'bmalta' : {
292 'run' : qemu_run,
293 'image' : 'image.boot',
294 'console' : True
297 'ppc32' : {
298 'run' : qemu_run,
299 'image' : 'image.iso',
300 'audio' : False
302 'riscv64' : {
303 'run' : spike_run,
304 'image' : 'image.boot'
306 'sparc64' : {
307 'generic' : {
308 'us' : {
309 'run' : qemu_run,
310 'image' : 'image.iso',
311 'audio' : False,
312 'console' : True,
313 'net' : False,
314 'usb' : False,
315 'xhci' : False,
316 'tablet' : False
318 'sun4v' : {
319 'run' : qemu_run,
320 'image' : '-drive if=pflash,readonly=on,file=image.iso',
321 'audio' : False,
322 'console' : True,
323 'net' : False,
324 'usb' : False,
325 'xhci' : False,
326 'tablet' : False,
327 'expect' : {
328 'src' : 'ok ',
329 'dst' : 'boot\n'
336 def usage():
337 print("%s - emulator wrapper for running HelenOS\n" % os.path.basename(sys.argv[0]))
338 print("%s [-d] [-h] [-net e1k|rtl8139|ne2k|virtio-net] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb] [-noxhci] [-notablet]\n" %
339 os.path.basename(sys.argv[0]))
340 print("-d\tDry run: do not run the emulation, just print the command line.")
341 print("-h\tPrint the usage information and exit.")
342 print("-nohdd\tDisable hard disk, if applicable.")
343 print("-nokvm\tDisable KVM, if applicable.")
344 print("-nonet\tDisable networking support, if applicable.")
345 print("-nosnd\tDisable sound, if applicable.")
346 print("-nousb\tDisable USB support, if applicable.")
347 print("-noxhci\tDisable XHCI support, if applicable.")
348 print("-notablet\tDisable USB tablet (use only relative-position PS/2 mouse instead), if applicable.")
349 print("-nographic\tDisable graphical output. Serial port output must be enabled for this to be useful.")
350 print("-noserial\tDisable serial port output in the terminal.")
351 print("-bigmem\tSets maximum RAM size to 4GB.")
353 def fail(platform, machine):
354 print("Cannot start emulation for the chosen configuration. (%s/%s)" % (platform, machine))
357 def run():
358 expect_nic = False
359 expect_qemu = False
361 for i in range(1, len(sys.argv)):
363 if expect_nic:
364 expect_nic = False
365 if not 'net' in overrides.keys():
366 overrides['net'] = {}
367 if sys.argv[i] == 'e1k':
368 overrides['net']['e1k'] = True
369 elif sys.argv[i] == 'rtl8139':
370 overrides['net']['rtl8139'] = True
371 elif sys.argv[i] == 'ne2k':
372 overrides['net']['ne2k'] = True
373 elif sys.argv[i] == 'virtio-net':
374 overrides['net']['virtio-net'] = True
375 else:
376 usage()
377 exit()
378 continue
380 if expect_qemu:
381 expect_qemu = False
382 overrides['qemu_path'] = sys.argv[i]
384 elif sys.argv[i] == '-h':
385 usage()
386 exit()
387 elif sys.argv[i] == '-d':
388 overrides['dryrun'] = True
389 elif sys.argv[i] == '-net' and i < len(sys.argv) - 1:
390 expect_nic = True
391 elif sys.argv[i] == '-nohdd':
392 overrides['nohdd'] = True
393 elif sys.argv[i] == '-nokvm':
394 overrides['nokvm'] = True
395 elif sys.argv[i] == '-nonet':
396 overrides['nonet'] = True
397 elif sys.argv[i] == '-nosnd':
398 overrides['nosnd'] = True
399 elif sys.argv[i] == '-nousb':
400 overrides['nousb'] = True
401 elif sys.argv[i] == '-noxhci':
402 overrides['noxhci'] = True
403 elif sys.argv[i] == '-notablet':
404 overrides['notablet'] = True
405 elif sys.argv[i] == '-nographic':
406 overrides['nographic'] = True
407 elif sys.argv[i] == '-bigmem':
408 overrides['bigmem'] = True
409 elif sys.argv[i] == '-noserial':
410 overrides['noserial'] = True
411 elif sys.argv[i] == '-qemu_path' and i < len(sys.argv) - 1:
412 expect_qemu = True
413 else:
414 usage()
415 exit()
417 config = {}
418 autotool.read_config(autotool.CONFIG, config)
420 if 'PLATFORM' in config.keys():
421 platform = config['PLATFORM']
422 else:
423 platform = ''
425 if 'MACHINE' in config.keys():
426 mach = config['MACHINE']
427 else:
428 mach = ''
430 if 'PROCESSOR' in config.keys():
431 processor = config['PROCESSOR']
432 else:
433 processor = ''
435 try:
436 emu_run = cfg_get(platform, mach, processor)['run']
437 emu_run(platform, mach, processor)
438 except:
439 fail(platform, mach)
440 return
442 run()