github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/pkg/pci/pci_linux.go (about)

     1  // Copyright 2012-2017 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 pci
     6  
     7  //go:generate go run gen.go
     8  
     9  import (
    10  	"io/ioutil"
    11  	"path/filepath"
    12  	"reflect"
    13  )
    14  
    15  const (
    16  	pciPath = "/sys/bus/pci/devices"
    17  )
    18  
    19  type bus struct {
    20  	Devices []string
    21  }
    22  
    23  func onePCI(dir string) (*PCI, error) {
    24  	var pci PCI
    25  	v := reflect.TypeOf(pci)
    26  	for ix := 0; ix < v.NumField(); ix++ {
    27  		f := v.Field(ix)
    28  		n := f.Tag.Get("pci")
    29  		if n == "" {
    30  			continue
    31  		}
    32  		s, err := ioutil.ReadFile(filepath.Join(dir, n))
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  		// Linux never understood /proc.
    37  		reflect.ValueOf(&pci).Elem().Field(ix).SetString(string(s[2 : len(s)-1]))
    38  	}
    39  	pci.VendorName, pci.DeviceName = pci.Vendor, pci.Device
    40  	return &pci, nil
    41  }
    42  
    43  // Read implements the BusReader interface for type bus. Iterating over each
    44  // PCI bus device.
    45  func (bus *bus) Read() (Devices, error) {
    46  	devices := make(Devices, len(bus.Devices))
    47  	for i, d := range bus.Devices {
    48  		p, err := onePCI(d)
    49  		if err != nil {
    50  			return nil, err
    51  		}
    52  		p.Addr = filepath.Base(d)
    53  		p.FullPath = d
    54  		devices[i] = p
    55  	}
    56  	return devices, nil
    57  }
    58  
    59  // NewBusReader returns a BusReader, given a glob to match PCI devices against.
    60  // If it can't glob in pciPath/g then it returns an error.
    61  // We don't provide an option to do type I or PCIe MMIO config stuff.
    62  func NewBusReader(g string) (busReader, error) {
    63  	globs, err := filepath.Glob(filepath.Join(pciPath, g))
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	return &bus{Devices: globs}, nil
    69  }