Fold assembler flags into cflags, for consistent behavior
[helenos.git] / tools / ew.py
blobee3fa3dede928c2a67504ebff851333c5c4f4c6b
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 emus = ['gnome-terminal', 'xfce4-terminal', 'xterm']
60 for termemu in emus:
61 try:
62 subprocess.check_output('which ' + termemu, shell = True)
63 return termemu
64 except:
65 pass
67 print('Could not find any of the terminal emulators %s.'%(emus))
68 sys.exit(1)
70 def run_in_console(cmd, title):
71 temu = termemu_detect()
72 if temu == 'gnome-terminal':
73 cmdline = temu + ' -- ' + cmd
74 else:
75 ecmd = cmd.replace('"', '\\"')
76 cmdline = temu + ' -T ' + '"' + title + '"' + ' -e "' + ecmd + '"'
78 print(cmdline)
79 if not is_override('dryrun'):
80 subprocess.call(cmdline, shell = True)
82 def get_host_native_width():
83 return int(platform.architecture()[0].strip('bit'))
85 def pc_options(guest_width):
86 opts = ''
88 # Do not enable KVM if running 64 bits HelenOS
89 # on 32 bits host
90 host_width = get_host_native_width()
91 if guest_width <= host_width and not is_override('nokvm'):
92 opts = opts + ' -enable-kvm'
94 # Remove the leading space
95 return opts[1:]
97 def malta_options():
98 return '-cpu 4Kc -append "console=devices/\\hw\\pci0\\00:0a.0\\com1\\a"'
100 def find_firmware(name, environ_var, default_paths, extra_info=None):
101 """Find firmware image(s)."""
103 if environ_var in os.environ:
104 return os.environ[environ_var]
106 for path in default_paths:
107 if os.path.exists(path):
108 return path
110 sys.stderr.write("Cannot find %s binary image(s)!\n" % name)
111 sys.stderr.write(
112 "Either set %s environment variable accordingly or place the image(s) in one of the default locations: %s.\n" %
113 (environ_var, ", ".join(default_paths)))
114 if extra_info is not None:
115 sys.stderr.write(extra_info)
116 return None
118 def platform_to_qemu_options(platform, machine, processor):
119 if platform == 'amd64':
120 return 'system-x86_64', pc_options(64)
121 elif platform == 'arm32':
122 return 'system-arm', '-M integratorcp'
123 elif platform == 'arm64':
124 # Search for the EDK2 firmware image
125 default_paths = (
126 '/usr/local/qemu-efi-aarch64/QEMU_EFI.fd', # Custom
127 '/usr/share/edk2/aarch64/QEMU_EFI.fd', # Fedora
128 '/usr/share/qemu-efi-aarch64/QEMU_EFI.fd', # Ubuntu
130 extra_info = ("Pre-compiled binary can be obtained from "
131 "http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-AARCH64/RELEASE_GCC49/QEMU_EFI.fd.\n")
132 efi_path = find_firmware(
133 "EDK2", 'EW_QEMU_EFI_AARCH64', default_paths, extra_info)
134 if efi_path is None:
135 raise Exception
137 return 'system-aarch64', \
138 '-M virt -cpu cortex-a57 -m 1024 -bios %s' % efi_path
139 elif platform == 'ia32':
140 return 'system-i386', pc_options(32)
141 elif platform == 'mips32':
142 if machine == 'lmalta':
143 return 'system-mipsel', malta_options()
144 elif machine == 'bmalta':
145 return 'system-mips', malta_options()
146 elif platform == 'ppc32':
147 return 'system-ppc', '-m 256'
148 elif platform == 'sparc64':
149 if machine != 'generic':
150 raise Exception
151 if processor == 'us':
152 return 'system-sparc64', '-M sun4u --prom-env boot-args="console=devices/\\hw\\pci0\\01:01.0\\com1\\a"'
154 # processor = 'sun4v'
155 opensparc_bins = find_firmware(
156 "OpenSPARC", 'OPENSPARC_BINARIES',
157 ('/usr/local/opensparc/image/', ))
158 if opensparc_bins is None:
159 raise Exception
161 return 'system-sparc64', '-M niagara -m 256 -L %s' % (opensparc_bins)
164 def hdisk_mk():
165 if not os.path.exists('hdisk.img'):
166 subprocess.call('tools/mkfat.py 1048576 uspace/dist/data hdisk.img', shell = True)
168 def qemu_bd_options():
169 if is_override('nohdd'):
170 return ''
172 hdisk_mk()
174 hdd_options = ''
175 if 'hdd' in overrides.keys():
176 if 'ata' in overrides['hdd'].keys():
177 hdd_options += ''
178 elif 'virtio-blk' in overrides['hdd'].keys():
179 hdd_options += ',if=virtio'
181 return ' -drive file=hdisk.img,index=0,media=disk,format=raw' + hdd_options
183 def qemu_nic_ne2k_options():
184 return ' -device ne2k_isa,irq=5,netdev=n1'
186 def qemu_nic_e1k_options():
187 return ' -device e1000,netdev=n1'
189 def qemu_nic_rtl8139_options():
190 return ' -device rtl8139,netdev=n1'
192 def qemu_nic_virtio_options():
193 return ' -device virtio-net,netdev=n1'
195 def qemu_net_options():
196 if is_override('nonet'):
197 return ''
199 nic_options = ''
200 if 'net' in overrides.keys():
201 if 'e1k' in overrides['net'].keys():
202 nic_options += qemu_nic_e1k_options()
203 if 'rtl8139' in overrides['net'].keys():
204 nic_options += qemu_nic_rtl8139_options()
205 if 'ne2k' in overrides['net'].keys():
206 nic_options += qemu_nic_ne2k_options()
207 if 'virtio-net' in overrides['net'].keys():
208 nic_options += qemu_nic_virtio_options()
209 else:
210 # Use the default NIC
211 nic_options += qemu_nic_e1k_options()
213 return nic_options + ' -netdev user,id=n1,hostfwd=udp::8080-:8080,hostfwd=udp::8081-:8081,hostfwd=tcp::8080-:8080,hostfwd=tcp::8081-:8081,hostfwd=tcp::2223-:2223'
215 def qemu_usb_options():
216 if is_override('nousb'):
217 return ''
218 return ' -usb'
220 def qemu_xhci_options():
221 if is_override('noxhci'):
222 return ''
223 return ' -device nec-usb-xhci,id=xhci'
225 def qemu_tablet_options():
226 if is_override('notablet') or (is_override('nousb') and is_override('noxhci')):
227 return ''
228 return ' -device usb-tablet'
230 def qemu_audio_options():
231 if is_override('nosnd'):
232 return ''
233 return ' -device intel-hda -device hda-duplex'
235 def qemu_run(platform, machine, processor):
236 cfg = cfg_get(platform, machine, processor)
237 suffix, options = platform_to_qemu_options(platform, machine, processor)
238 cmd = 'qemu-' + suffix
240 cmdline = cmd
241 if 'qemu_path' in overrides.keys():
242 cmdline = overrides['qemu_path'] + cmd
244 if options != '':
245 cmdline += ' ' + options
247 if (not 'hdd' in cfg.keys() or cfg['hdd']):
248 cmdline += qemu_bd_options()
249 if (not 'net' in cfg.keys()) or cfg['net']:
250 cmdline += qemu_net_options()
251 if (not 'usb' in cfg.keys()) or cfg['usb']:
252 cmdline += qemu_usb_options()
253 if (not 'xhci' in cfg.keys()) or cfg['xhci']:
254 cmdline += qemu_xhci_options()
255 if (not 'tablet' in cfg.keys()) or cfg['tablet']:
256 cmdline += qemu_tablet_options()
257 if (not 'audio' in cfg.keys()) or cfg['audio']:
258 cmdline += qemu_audio_options()
260 console = ('console' in cfg.keys() and cfg['console'])
262 if (is_override('nographic')):
263 cmdline += ' -nographic'
265 if (not console and (not is_override('nographic')) and not is_override('noserial')):
266 cmdline += ' -serial stdio'
268 if (is_override('bigmem')):
269 cmdline += ' -m 4G'
271 if cfg['image'] == 'image.iso':
272 cmdline += ' -boot d -cdrom image.iso'
273 elif cfg['image'] == 'image.iso@arm64':
274 # Define image.iso cdrom backend.
275 cmdline += ' -drive if=none,file=image.iso,id=cdrom,media=cdrom'
276 # Define scsi bus.
277 cmdline += ' -device virtio-scsi-device'
278 # Define cdrom frontend connected to this scsi bus.
279 cmdline += ' -device scsi-cd,drive=cdrom'
280 elif cfg['image'] == 'image.boot':
281 cmdline += ' -kernel image.boot'
282 else:
283 cmdline += ' ' + cfg['image']
285 if console:
286 cmdline += ' -nographic'
288 title = 'HelenOS/' + platform
289 if machine != '':
290 title += ' on ' + machine
291 if 'expect' in cfg.keys():
292 cmdline = 'expect -c \'spawn %s; expect "%s" { send "%s" } timeout exp_continue; interact\'' % (cmdline, cfg['expect']['src'], cfg['expect']['dst'])
293 run_in_console(cmdline, title)
294 else:
295 print(cmdline)
296 if not is_override('dryrun'):
297 subprocess.call(cmdline, shell = True)
299 def ski_run(platform, machine, processor):
300 run_in_console('ski -i tools/conf/ski.conf', 'HelenOS/ia64 on ski')
302 def msim_run(platform, machine, processor):
303 hdisk_mk()
304 run_in_console('msim -c tools/conf/msim.conf', 'HelenOS/mips32 on msim')
306 def spike_run(platform, machine, processor):
307 run_in_console('spike -m1073741824:1073741824 image.boot', 'HelenOS/risvc64 on Spike')
309 emulators = {
310 'amd64' : {
311 'run' : qemu_run,
312 'image' : 'image.iso'
314 'arm32' : {
315 'integratorcp' : {
316 'run' : qemu_run,
317 'image' : 'image.boot',
318 'net' : False,
319 'audio' : False,
320 'xhci' : False,
321 'tablet' : False
324 'arm64' : {
325 'virt' : {
326 'run' : qemu_run,
327 'image' : 'image.iso@arm64',
328 'audio' : False,
329 'console' : True,
330 'hdd' : False,
331 'net' : False,
332 'tablet' : False,
333 'usb' : False,
334 'xhci' : False
337 'ia32' : {
338 'run' : qemu_run,
339 'image' : 'image.iso'
341 'ia64' : {
342 'ski' : {
343 'run' : ski_run
346 'mips32' : {
347 'msim' : {
348 'run' : msim_run
350 'lmalta' : {
351 'run' : qemu_run,
352 'image' : 'image.boot',
353 'console' : True
355 'bmalta' : {
356 'run' : qemu_run,
357 'image' : 'image.boot',
358 'console' : True
361 'ppc32' : {
362 'run' : qemu_run,
363 'image' : 'image.iso',
364 'audio' : False
366 'riscv64' : {
367 'run' : spike_run,
368 'image' : 'image.boot'
370 'sparc64' : {
371 'generic' : {
372 'us' : {
373 'run' : qemu_run,
374 'image' : 'image.iso',
375 'audio' : False,
376 'console' : True,
377 'net' : False,
378 'usb' : False,
379 'xhci' : False,
380 'tablet' : False
382 'sun4v' : {
383 'run' : qemu_run,
384 'image' : '-drive if=pflash,readonly=on,file=image.iso',
385 'audio' : False,
386 'console' : True,
387 'net' : False,
388 'usb' : False,
389 'xhci' : False,
390 'tablet' : False,
391 'expect' : {
392 'src' : 'ok ',
393 'dst' : 'boot\n'
400 def usage():
401 print("%s - emulator wrapper for running HelenOS\n" % os.path.basename(sys.argv[0]))
402 print("%s [-d] [-h] [-net e1k|rtl8139|ne2k|virtio-net] [-hdd ata|virtio-blk] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb] [-noxhci] [-notablet]\n" %
403 os.path.basename(sys.argv[0]))
404 print("-d\tDry run: do not run the emulation, just print the command line.")
405 print("-h\tPrint the usage information and exit.")
406 print("-nohdd\tDisable hard disk, if applicable.")
407 print("-nokvm\tDisable KVM, if applicable.")
408 print("-nonet\tDisable networking support, if applicable.")
409 print("-nosnd\tDisable sound, if applicable.")
410 print("-nousb\tDisable USB support, if applicable.")
411 print("-noxhci\tDisable XHCI support, if applicable.")
412 print("-notablet\tDisable USB tablet (use only relative-position PS/2 mouse instead), if applicable.")
413 print("-nographic\tDisable graphical output. Serial port output must be enabled for this to be useful.")
414 print("-noserial\tDisable serial port output in the terminal.")
415 print("-bigmem\tSets maximum RAM size to 4GB.")
417 def fail(platform, machine):
418 print("Cannot start emulation for the chosen configuration. (%s/%s)" % (platform, machine))
421 def run():
422 expect_nic = False
423 expect_hdd = False
424 expect_qemu = False
426 for i in range(1, len(sys.argv)):
428 if expect_nic:
429 expect_nic = False
430 if not 'net' in overrides.keys():
431 overrides['net'] = {}
432 if sys.argv[i] == 'e1k':
433 overrides['net']['e1k'] = True
434 elif sys.argv[i] == 'rtl8139':
435 overrides['net']['rtl8139'] = True
436 elif sys.argv[i] == 'ne2k':
437 overrides['net']['ne2k'] = True
438 elif sys.argv[i] == 'virtio-net':
439 overrides['net']['virtio-net'] = True
440 else:
441 usage()
442 exit()
443 continue
445 if expect_hdd:
446 expect_hdd = False
447 if not 'hdd' in overrides.keys():
448 overrides['hdd'] = {}
449 if sys.argv[i] == 'ata':
450 overrides['hdd']['ata'] = True
451 elif sys.argv[i] == 'virtio-blk':
452 overrides['hdd']['virtio-blk'] = True
453 else:
454 usage()
455 exit()
456 continue
458 if expect_qemu:
459 expect_qemu = False
460 overrides['qemu_path'] = sys.argv[i]
462 elif sys.argv[i] == '-h':
463 usage()
464 exit()
465 elif sys.argv[i] == '-d':
466 overrides['dryrun'] = True
467 elif sys.argv[i] == '-net' and i < len(sys.argv) - 1:
468 expect_nic = True
469 elif sys.argv[i] == '-hdd' and i < len(sys.argv) - 1:
470 expect_hdd = True
471 elif sys.argv[i] == '-nohdd':
472 overrides['nohdd'] = True
473 elif sys.argv[i] == '-nokvm':
474 overrides['nokvm'] = True
475 elif sys.argv[i] == '-nonet':
476 overrides['nonet'] = True
477 elif sys.argv[i] == '-nosnd':
478 overrides['nosnd'] = True
479 elif sys.argv[i] == '-nousb':
480 overrides['nousb'] = True
481 elif sys.argv[i] == '-noxhci':
482 overrides['noxhci'] = True
483 elif sys.argv[i] == '-notablet':
484 overrides['notablet'] = True
485 elif sys.argv[i] == '-nographic':
486 overrides['nographic'] = True
487 elif sys.argv[i] == '-bigmem':
488 overrides['bigmem'] = True
489 elif sys.argv[i] == '-noserial':
490 overrides['noserial'] = True
491 elif sys.argv[i] == '-qemu_path' and i < len(sys.argv) - 1:
492 expect_qemu = True
493 else:
494 usage()
495 exit()
497 config = {}
498 autotool.read_config(autotool.CONFIG, config)
500 if 'PLATFORM' in config.keys():
501 platform = config['PLATFORM']
502 else:
503 platform = ''
505 if 'MACHINE' in config.keys():
506 mach = config['MACHINE']
507 else:
508 mach = ''
510 if 'PROCESSOR' in config.keys():
511 processor = config['PROCESSOR']
512 else:
513 processor = ''
515 try:
516 emu_run = cfg_get(platform, mach, processor)['run']
517 emu_run(platform, mach, processor)
518 except:
519 fail(platform, mach)
520 return
522 run()