Fix USB match IDs that need zero-padding
[helenos.git] / tools / ew.py
blobed13a0f85b79521125d2128ca68c3f0e50c1f83e
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_net_options():
149 if is_override('nonet'):
150 return ''
152 nic_options = ''
153 if 'net' in overrides.keys():
154 if 'e1k' in overrides['net'].keys():
155 nic_options += qemu_nic_e1k_options()
156 if 'rtl8139' in overrides['net'].keys():
157 nic_options += qemu_nic_rtl8139_options()
158 if 'ne2k' in overrides['net'].keys():
159 nic_options += qemu_nic_ne2k_options()
160 else:
161 # Use the default NIC
162 nic_options += qemu_nic_e1k_options()
164 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'
166 def qemu_usb_options():
167 if is_override('nousb'):
168 return ''
169 return ' -usb'
171 def qemu_xhci_options():
172 if is_override('noxhci'):
173 return ''
174 return ' -device nec-usb-xhci,id=xhci'
176 def qemu_tablet_options():
177 if is_override('notablet') or (is_override('nousb') and is_override('noxhci')):
178 return ''
179 return ' -device usb-tablet'
181 def qemu_audio_options():
182 if is_override('nosnd'):
183 return ''
184 return ' -device intel-hda -device hda-duplex'
186 def qemu_run(platform, machine, processor):
187 cfg = cfg_get(platform, machine, processor)
188 suffix, options = platform_to_qemu_options(platform, machine, processor)
189 cmd = 'qemu-' + suffix
191 cmdline = cmd
192 if 'qemu_path' in overrides.keys():
193 cmdline = overrides['qemu_path'] + cmd
195 if options != '':
196 cmdline += ' ' + options
198 cmdline += qemu_bd_options()
200 if (not 'net' in cfg.keys()) or cfg['net']:
201 cmdline += qemu_net_options()
202 if (not 'usb' in cfg.keys()) or cfg['usb']:
203 cmdline += qemu_usb_options()
204 if (not 'xhci' in cfg.keys()) or cfg['xhci']:
205 cmdline += qemu_xhci_options()
206 if (not 'tablet' in cfg.keys()) or cfg['tablet']:
207 cmdline += qemu_tablet_options()
208 if (not 'audio' in cfg.keys()) or cfg['audio']:
209 cmdline += qemu_audio_options()
211 if cfg['image'] == 'image.iso':
212 cmdline += ' -boot d -cdrom image.iso'
213 elif cfg['image'] == 'image.boot':
214 cmdline += ' -kernel image.boot'
215 else:
216 cmdline += ' ' + cfg['image']
218 if ('console' in cfg.keys()) and not cfg['console']:
219 cmdline += ' -nographic'
221 title = 'HelenOS/' + platform
222 if machine != '':
223 title += ' on ' + machine
224 if 'expect' in cfg.keys():
225 cmdline = 'expect -c \'spawn %s; expect "%s" { send "%s" } timeout exp_continue; interact\'' % (cmdline, cfg['expect']['src'], cfg['expect']['dst'])
226 run_in_console(cmdline, title)
227 else:
228 print(cmdline)
229 if not is_override('dryrun'):
230 subprocess.call(cmdline, shell = True)
232 def ski_run(platform, machine, processor):
233 run_in_console('ski -i contrib/conf/ski.conf', 'HelenOS/ia64 on ski')
235 def msim_run(platform, machine, processor):
236 hdisk_mk()
237 run_in_console('msim -c contrib/conf/msim.conf', 'HelenOS/mips32 on msim')
239 def spike_run(platform, machine, processor):
240 run_in_console('spike -m1073741824:1073741824 image.boot', 'HelenOS/risvc64 on Spike')
242 emulators = {
243 'amd64' : {
244 'run' : qemu_run,
245 'image' : 'image.iso'
247 'arm32' : {
248 'integratorcp' : {
249 'run' : qemu_run,
250 'image' : 'image.boot',
251 'net' : False,
252 'audio' : False,
253 'xhci' : False,
254 'tablet' : False
257 'ia32' : {
258 'run' : qemu_run,
259 'image' : 'image.iso'
261 'ia64' : {
262 'ski' : {
263 'run' : ski_run
266 'mips32' : {
267 'msim' : {
268 'run' : msim_run
270 'lmalta' : {
271 'run' : qemu_run,
272 'image' : 'image.boot',
273 'console' : False
275 'bmalta' : {
276 'run' : qemu_run,
277 'image' : 'image.boot',
278 'console' : False
281 'ppc32' : {
282 'run' : qemu_run,
283 'image' : 'image.iso',
284 'audio' : False
286 'riscv64' : {
287 'run' : spike_run,
288 'image' : 'image.boot'
290 'sparc64' : {
291 'generic' : {
292 'us' : {
293 'run' : qemu_run,
294 'image' : 'image.iso',
295 'audio' : False,
296 'console' : False,
297 'net' : False,
298 'usb' : False,
299 'xhci' : False,
300 'tablet' : False
302 'sun4v' : {
303 'run' : qemu_run,
304 'image' : '-drive if=pflash,readonly=on,file=image.iso',
305 'audio' : False,
306 'console' : False,
307 'net' : False,
308 'usb' : False,
309 'xhci' : False,
310 'tablet' : False,
311 'expect' : {
312 'src' : 'ok ',
313 'dst' : 'boot\n'
320 def usage():
321 print("%s - emulator wrapper for running HelenOS\n" % os.path.basename(sys.argv[0]))
322 print("%s [-d] [-h] [-net e1k|rtl8139|ne2k] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb] [-noxhci] [-notablet]\n" %
323 os.path.basename(sys.argv[0]))
324 print("-d\tDry run: do not run the emulation, just print the command line.")
325 print("-h\tPrint the usage information and exit.")
326 print("-nohdd\tDisable hard disk, if applicable.")
327 print("-nokvm\tDisable KVM, if applicable.")
328 print("-nonet\tDisable networking support, if applicable.")
329 print("-nosnd\tDisable sound, if applicable.")
330 print("-nousb\tDisable USB support, if applicable.")
331 print("-noxhci\tDisable XHCI support, if applicable.")
332 print("-notablet\tDisable USB tablet (use only relative-position PS/2 mouse instead), if applicable.")
334 def fail(platform, machine):
335 print("Cannot start emulation for the chosen configuration. (%s/%s)" % (platform, machine))
338 def run():
339 expect_nic = False
340 expect_qemu = False
342 for i in range(1, len(sys.argv)):
344 if expect_nic:
345 expect_nic = False
346 if not 'net' in overrides.keys():
347 overrides['net'] = {}
348 if sys.argv[i] == 'e1k':
349 overrides['net']['e1k'] = True
350 elif sys.argv[i] == 'rtl8139':
351 overrides['net']['rtl8139'] = True
352 elif sys.argv[i] == 'ne2k':
353 overrides['net']['ne2k'] = True
354 else:
355 usage()
356 exit()
357 continue
359 if expect_qemu:
360 expect_qemu = False
361 overrides['qemu_path'] = sys.argv[i]
363 elif sys.argv[i] == '-h':
364 usage()
365 exit()
366 elif sys.argv[i] == '-d':
367 overrides['dryrun'] = True
368 elif sys.argv[i] == '-net' and i < len(sys.argv) - 1:
369 expect_nic = True
370 elif sys.argv[i] == '-nohdd':
371 overrides['nohdd'] = True
372 elif sys.argv[i] == '-nokvm':
373 overrides['nokvm'] = True
374 elif sys.argv[i] == '-nonet':
375 overrides['nonet'] = True
376 elif sys.argv[i] == '-nosnd':
377 overrides['nosnd'] = True
378 elif sys.argv[i] == '-nousb':
379 overrides['nousb'] = True
380 elif sys.argv[i] == '-noxhci':
381 overrides['noxhci'] = True
382 elif sys.argv[i] == '-notablet':
383 overrides['notablet'] = True
384 elif sys.argv[i] == '-qemu_path' and i < len(sys.argv) - 1:
385 expect_qemu = True
386 else:
387 usage()
388 exit()
390 config = {}
391 autotool.read_config(autotool.CONFIG, config)
393 if 'PLATFORM' in config.keys():
394 platform = config['PLATFORM']
395 else:
396 platform = ''
398 if 'MACHINE' in config.keys():
399 mach = config['MACHINE']
400 else:
401 mach = ''
403 if 'PROCESSOR' in config.keys():
404 processor = config['PROCESSOR']
405 else:
406 processor = ''
408 try:
409 emu_run = cfg_get(platform, mach, processor)['run']
410 emu_run(platform, mach, processor)
411 except:
412 fail(platform, mach)
413 return
415 run()