github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/smn/main.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 // smn: read or write registers in the System Management Network on AMD cpus 6 // 7 // Synopsis: 8 // 9 // snm [0 or more addresses] 10 // 11 // N.B. having no addresses is an easy way to see if you can 12 // access PCI at all. 13 // 14 // Description: 15 // 16 // read and write System Management Network registers 17 // 18 // Options: 19 // 20 // -s: device glob in the form tttt:bb:dd.fn with * as needed 21 // -n: number of 32-bit words to dump. 22 // -v: 32-bit value to write 23 // -w: write the value to the register(s) 24 package main 25 26 import ( 27 "flag" 28 "fmt" 29 "log" 30 "strconv" 31 "strings" 32 33 "github.com/mvdan/u-root-coreutils/pkg/pci" 34 ) 35 36 // Index/Data register pairs, as, e.g., cf8/cfc for PCI, 37 // are known to be a terrible idea, from almost any point of view. 38 // It took years to kill them on regular PCI. 39 // AMD brought them back for the SMN. Bummer. 40 const ( 41 regIndex = 0xa0 42 regData = 0xa4 43 ) 44 45 var ( 46 devs = flag.String("s", "0000:00:00.0", "Glob for northbridge") 47 n = flag.Uint("n", 1, "Number 32-bit words to dump/set") 48 val = flag.Uint64("v", 0, "Val to set on write") 49 write = flag.Bool("w", false, "Write a value") 50 ) 51 52 func usage() { 53 log.Fatal("Usage: smn [-w] [-d glob] address [# 32-words to read | 32-bit value to write]") 54 } 55 56 func main() { 57 flag.Parse() 58 r, err := pci.NewBusReader(strings.Split(*devs, ",")...) 59 if err != nil { 60 log.Fatalf("%v", err) 61 } 62 63 d, err := r.Read() 64 if err != nil { 65 log.Fatalf("Read: %v", err) 66 } 67 68 a := flag.Args() 69 if uint32(*val>>32) != 0 { 70 log.Fatalf("Value:%#x is not a 32-bit number", *val) 71 } 72 for i := range a { 73 addr, err := strconv.ParseUint(a[i], 16, 32) 74 if err != nil { 75 log.Fatal(err) 76 } 77 switch *write { 78 case true: 79 if err := d.WriteConfigRegister(regIndex, 32, addr); err != nil { 80 log.Fatal(err) 81 } 82 if err := d.WriteConfigRegister(regData, 32, *val); err != nil { 83 log.Fatal(err) 84 } 85 case false: 86 for i := addr; i < addr+uint64(*n); i += 4 { 87 if err := d.WriteConfigRegister(regIndex, 32, i); err != nil { 88 log.Fatal(err) 89 } 90 // SMN data is 32 bits! 91 dat, err := d.ReadConfigRegister(regData, 32) 92 if err != nil { 93 log.Fatal(err) 94 } 95 fmt.Printf("%#x:", i) 96 for i := range dat { 97 fmt.Printf("%s:%#x,", d[i].Addr, dat[i]) 98 } 99 fmt.Println() 100 } 101 } 102 } 103 }