github.com/andrewsun2898/u-root@v6.0.1-0.20200616011413-4b2895c1b815+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 "sort" 14 ) 15 16 const ( 17 pciPath = "/sys/bus/pci/devices" 18 ) 19 20 type bus struct { 21 Devices []string 22 } 23 24 func onePCI(dir string) (*PCI, error) { 25 var pci PCI 26 v := reflect.TypeOf(pci) 27 for ix := 0; ix < v.NumField(); ix++ { 28 f := v.Field(ix) 29 n := f.Tag.Get("pci") 30 if n == "" { 31 continue 32 } 33 s, err := ioutil.ReadFile(filepath.Join(dir, n)) 34 if err != nil { 35 return nil, err 36 } 37 // Linux never understood /proc. 38 reflect.ValueOf(&pci).Elem().Field(ix).SetString(string(s[2 : len(s)-1])) 39 } 40 pci.VendorName, pci.DeviceName = pci.Vendor, pci.Device 41 return &pci, nil 42 } 43 44 // Read implements the BusReader interface for type bus. Iterating over each 45 // PCI bus device. 46 func (bus *bus) Read() (Devices, error) { 47 devices := make(Devices, len(bus.Devices)) 48 for i, d := range bus.Devices { 49 p, err := onePCI(d) 50 if err != nil { 51 return nil, err 52 } 53 p.Addr = filepath.Base(d) 54 p.FullPath = d 55 devices[i] = p 56 } 57 return devices, nil 58 } 59 60 // NewBusReader returns a BusReader, given a ...glob to match PCI devices against. 61 // If it can't glob in pciPath/g then it returns an error. 62 // For convenience, we use * as the glob if none are supplied. 63 // We don't provide an option to do type I or PCIe MMIO config stuff. 64 func NewBusReader(globs ...string) (busReader, error) { 65 if len(globs) == 0 { 66 globs = []string{"*"} 67 } 68 var exp []string 69 for _, g := range globs { 70 gg, err := filepath.Glob(filepath.Join(pciPath, g)) 71 if err != nil { 72 return nil, err 73 } 74 exp = append(exp, gg...) 75 } 76 // uniq 77 var u = map[string]struct{}{} 78 for _, e := range exp { 79 u[e] = struct{}{} 80 } 81 exp = []string{} 82 for v := range u { 83 exp = append(exp, v) 84 } 85 // sort. This might even sort like a shell would do it. 86 sort.Strings(exp) 87 return &bus{Devices: exp}, nil 88 }