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