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  }