github.com/shaardie/u-root@v4.0.1-0.20190127173353-f24a1c26aa2e+incompatible/pkg/qemu/devices.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package qemu 6 7 import ( 8 "fmt" 9 "net" 10 "sync/atomic" 11 ) 12 13 // Device is a QEMU device to expose to a VM. 14 type Device interface { 15 // Cmdline returns arguments to append to the QEMU command line for this device. 16 Cmdline() []string 17 } 18 19 // Network is a Device that can connect multiple QEMU VMs to each other. 20 // 21 // Network uses the QEMU socket mechanism to connect multiple VMs with a simple 22 // TCP socket. 23 type Network struct { 24 port uint16 25 26 // numVMs must be atomically accessed so VMs can be started in parallel 27 // in goroutines. 28 numVMs uint32 29 } 30 31 func NewNetwork() *Network { 32 return &Network{ 33 port: 1234, 34 } 35 } 36 37 // Cmdline implements Device. 38 func (n *Network) Cmdline() []string { 39 if n == nil { 40 return nil 41 } 42 43 newNum := atomic.AddUint32(&n.numVMs, 1) 44 num := newNum - 1 45 46 // MAC for the virtualized NIC. 47 // 48 // This is from the range of locally administered address ranges. 49 mac := net.HardwareAddr{0x0e, 0x00, 0x00, 0x00, 0x00, byte(num)} 50 51 args := []string{"-net", fmt.Sprintf("nic,macaddr=%s", mac)} 52 if num != 0 { 53 args = append(args, "-net", fmt.Sprintf("socket,connect=:%d", n.port)) 54 } else { 55 args = append(args, "-net", fmt.Sprintf("socket,listen=:%d", n.port)) 56 } 57 return args 58 } 59 60 // ReadOnlyDirectory is a Device that exposes a directory as a /dev/sda1 61 // readonly vfat partition in the VM. 62 type ReadOnlyDirectory struct { 63 // Dir is the directory to expose as a read-only vfat partition. 64 Dir string 65 } 66 67 // Cmdline implements Device. 68 func (rod ReadOnlyDirectory) Cmdline() []string { 69 if len(rod.Dir) == 0 { 70 return nil 71 } 72 73 // Expose the temp directory to QEMU as /dev/sda1 74 return []string{ 75 "-drive", fmt.Sprintf("file=fat:ro:%s,if=none,id=tmpdir", rod.Dir), 76 "-device", "ich9-ahci,id=ahci", 77 "-device", "ide-drive,drive=tmpdir,bus=ahci.0", 78 } 79 } 80 81 // VirtioRandom exposes a PCI random number generator Device to the QEMU VM. 82 type VirtioRandom struct{} 83 84 // Cmdline implements Device. 85 func (VirtioRandom) Cmdline() []string { 86 return []string{"-device", "virtio-rng-pci"} 87 } 88 89 // ArbitraryArgs allows users to add arbitrary arguments to the QEMU command 90 // line. 91 type ArbitraryArgs []string 92 93 // Cmdline implements Device. 94 func (aa ArbitraryArgs) Cmdline() []string { 95 return aa 96 }