github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/core/pci/pci.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 //go:build !plan9 6 // +build !plan9 7 8 // pci: show pci bus vendor ids and other info 9 // 10 // Description: 11 // 12 // List the PCI bus, with names if possible. 13 // 14 // Options: 15 // 16 // -n: just show numbers 17 // -c: dump config space 18 // -s: specify glob for choosing devices. 19 package main 20 21 import ( 22 "encoding/json" 23 "fmt" 24 "io" 25 "log" 26 "os" 27 "strconv" 28 "strings" 29 30 flag "github.com/pborman/getopt/v2" 31 "github.com/mvdan/u-root-coreutils/pkg/pci" 32 ) 33 34 var ( 35 numbers = flag.Bool('n', "Show numeric IDs") 36 devs = flag.StringLong("select", 's', "*", "Devices to match") 37 dumpJSON = flag.BoolLong("json", 'j', "Dump the bus in JSON") 38 verbosity = flag.Counter('v', "verbosity") 39 hexdump = flag.Counter('x', "hexdump the config space") 40 readJSON = flag.StringLong("JSON", 'J', "", "Read JSON in instead of /sys") 41 ) 42 43 var format = map[int]string{ 44 32: "%08x:%08x", 45 16: "%08x:%04x", 46 8: "%08x:%02x", 47 } 48 49 // maybe we need a better syntax than the standard pcitools? 50 func registers(d pci.Devices, cmds ...string) { 51 var justCheck bool 52 for _, c := range cmds { 53 // TODO: replace this nonsense with a state machine. 54 // Split into register and value 55 rv := strings.Split(c, "=") 56 if len(rv) != 1 && len(rv) != 2 { 57 log.Printf("%v: only one = allowed. Due to this error no more commands will be issued", c) 58 justCheck = true 59 continue 60 } 61 62 // Split into register offset and size 63 rs := strings.Split(rv[0], ".") 64 if len(rs) != 1 && len(rs) != 2 { 65 log.Printf("%v: only one . allowed. Due to this error no more commands will be issued", rv[1]) 66 justCheck = true 67 continue 68 } 69 s := 32 70 if len(rs) == 2 { 71 switch rs[1] { 72 default: 73 log.Printf("Bad size: %v. Due to this error no more commands will be issued", rs[1]) 74 justCheck = true 75 continue 76 case "l": 77 case "w": 78 s = 16 79 case "b": 80 s = 8 81 } 82 } 83 if justCheck { 84 continue 85 } 86 reg, err := strconv.ParseUint(rs[0], 0, 16) 87 if err != nil { 88 log.Printf("%v:%v. Due to this error no more commands will be issued", rs[0], err) 89 justCheck = true 90 continue 91 } 92 if len(rv) == 1 { 93 v, err := d.ReadConfigRegister(int64(reg), int64(s)) 94 if err != nil { 95 log.Printf("%v:%v. Due to this error no more commands will be issued", rv[0], err) 96 justCheck = true 97 continue 98 } 99 // Should this go in the package somewhere? Not sure. 100 for i := range v { 101 d[i].ExtraInfo = append(d[i].ExtraInfo, fmt.Sprintf(format[s], reg, v[i])) 102 } 103 } 104 if len(rv) == 2 { 105 val, err := strconv.ParseUint(rv[1], 0, s) 106 if err != nil { 107 log.Printf("%v. Due to this error no more commands will be issued", err) 108 justCheck = true 109 continue 110 } 111 if err := d.WriteConfigRegister(int64(reg), int64(s), val); err != nil { 112 log.Printf("%v:%v. Due to this error no more commands will be issued", rv[1], err) 113 justCheck = true 114 continue 115 } 116 } 117 118 } 119 } 120 121 func pciExecution(w io.Writer, args ...string) error { 122 var dumpSize int 123 switch *hexdump { 124 case 4: 125 dumpSize = 4096 126 case 3: 127 dumpSize = 256 128 case 2: // lspci disallows this value 129 dumpSize = 256 130 case 1: 131 dumpSize = 64 132 } 133 r, err := pci.NewBusReader(strings.Split(*devs, ",")...) 134 if err != nil { 135 return err 136 } 137 138 var d pci.Devices 139 if len(*readJSON) != 0 { 140 b, err := os.ReadFile(*readJSON) 141 if err != nil { 142 return err 143 } 144 if err := json.Unmarshal(b, &d); err != nil { 145 return err 146 } 147 148 } else { 149 if d, err = r.Read(); err != nil { 150 return err 151 } 152 } 153 154 if !*numbers || *dumpJSON { 155 d.SetVendorDeviceName() 156 } 157 if len(args) > 0 { 158 registers(d, args...) 159 } 160 if *dumpJSON { 161 o, err := json.MarshalIndent(d, "", "\t") 162 if err != nil { 163 return err 164 } 165 fmt.Fprintf(w, "%s", string(o)) 166 return nil 167 } 168 if err := d.Print(w, *verbosity, dumpSize); err != nil { 169 return err 170 } 171 return nil 172 } 173 174 func main() { 175 flag.Parse() 176 if err := pciExecution(os.Stdout, flag.Args()...); err != nil { 177 log.Fatal(err) 178 } 179 }