github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/pci/devices.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 import ( 8 "bytes" 9 "encoding/hex" 10 "fmt" 11 "io" 12 "os" 13 ) 14 15 // Devices contains a slice of one or more PCI devices 16 type Devices []*PCI 17 18 // Print prints information to an io.Writer 19 func (d Devices) Print(o io.Writer, verbose, confSize int) error { 20 for _, pci := range d { 21 if _, err := fmt.Fprintf(o, "%s\n", pci.String()); err != nil { 22 return err 23 } 24 var extraNL bool 25 // Make sure we have read enough config space to satisfy the verbose and confSize requests. 26 // If len(pci.Config) is > 64, that's the only test we need. 27 if (verbose > 1 || confSize > 64) && len(pci.Config) < 256 { 28 return os.ErrPermission 29 } 30 if verbose >= 1 { 31 c := pci.Config 32 if _, err := fmt.Fprintf(o, "\tControl: %s\n\tStatus: %s\n\tLatency: %d", pci.Control.String(), pci.Status.String(), pci.Latency); err != nil { 33 return err 34 } 35 if pci.Bridge { 36 // Bus: primary=00, secondary=05, subordinate=0c, sec-latency=0 37 // I/O behind bridge: 00002000-00002fff [size=4K] 38 // Memory behind bridge: f0000000-f1ffffff [size=32M] 39 // Prefetchable memory behind bridge: 00000000f2900000-00000000f29fffff [size=1M] 40 if _, err := fmt.Fprintf(o, ", Cache Line Size: %d bytes", c[CacheLineSize]); err != nil { 41 return err 42 } 43 if _, err := fmt.Fprintf(o, "\n\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%s", 44 pci.Primary, pci.Secondary, pci.Subordinate, pci.SecLatency); err != nil { 45 return err 46 } 47 // I hate this code. 48 // I miss Rust tuples at times. 49 for _, e := range []struct { 50 h, f string 51 b, l uint64 52 }{ 53 {h: "\n\tI/O behind bridge: ", f: "%#08x-%#08x [size=%#x]", b: pci.IO.Base, l: pci.IO.Lim}, 54 {h: "\n\tMemory behind bridge: ", f: "%#08x-%#08x [size=%#x]", b: pci.Mem.Base, l: pci.Mem.Lim}, 55 {h: "\n\tPrefetchable memory behind bridge: ", f: "%#08x-%#08x [size=%#x]", b: pci.PrefMem.Base, l: pci.PrefMem.Lim}, 56 } { 57 s := e.h + " [disabled]" 58 if e.b != 0 { 59 sz := e.l - e.b + 1 60 s = fmt.Sprintf(e.h+e.f, e.b, e.l, sz) 61 } 62 if _, err := fmt.Fprintf(o, s); err != nil { 63 return err 64 } 65 } 66 } 67 fmt.Fprintf(o, "\n") 68 if pci.IRQPin != 0 { 69 if _, err := fmt.Fprintf(o, "\tInterrupt: pin %X routed to IRQ %X\n", 9+pci.IRQPin, pci.IRQLine); err != nil { 70 return err 71 } 72 } 73 if !pci.Bridge { 74 for _, b := range pci.BARS { 75 if _, err := fmt.Fprintf(o, "\t%v\n", b.String()); err != nil { 76 return err 77 } 78 } 79 } 80 extraNL = true 81 } 82 83 if confSize > 0 { 84 r := io.LimitReader(bytes.NewBuffer(pci.Config), int64(confSize)) 85 e := hex.Dumper(o) 86 if _, err := io.Copy(e, r); err != nil { 87 return err 88 } 89 extraNL = true 90 } 91 // lspci likes that extra line of separation 92 if extraNL { 93 fmt.Fprintf(o, "\n") 94 } 95 } 96 return nil 97 } 98 99 // SetVendorDeviceName sets all numeric IDs of all the devices 100 // using the pci device SetVendorDeviceName. 101 func (d Devices) SetVendorDeviceName() { 102 for _, p := range d { 103 p.SetVendorDeviceName() 104 } 105 } 106 107 // ReadConfig reads the config info for all the devices. 108 func (d Devices) ReadConfig() error { 109 for _, p := range d { 110 if err := p.ReadConfig(); err != nil { 111 return err 112 } 113 } 114 return nil 115 } 116 117 // ReadConfigRegister reads the config info for all the devices. 118 func (d Devices) ReadConfigRegister(offset, size int64) ([]uint64, error) { 119 var vals []uint64 120 for _, p := range d { 121 val, err := p.ReadConfigRegister(offset, size) 122 if err != nil { 123 return nil, err 124 } 125 vals = append(vals, val) 126 } 127 return vals, nil 128 } 129 130 // WriteConfigRegister writes the config info for all the devices. 131 func (d Devices) WriteConfigRegister(offset, size int64, val uint64) error { 132 for _, p := range d { 133 if err := p.WriteConfigRegister(offset, size, val); err != nil { 134 return err 135 } 136 } 137 return nil 138 }