github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/exp/ipmidump/ipmidump.go (about)

     1  // Copyright 2019-2020 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  // Synopsis:
     6  //     ipmidump [-option]
     7  //
     8  // Description:
     9  //
    10  // Options:
    11  //     -chassis : Print chassis power status.
    12  //     -sel     : Print SEL information.
    13  //     -lan     : Print IP information.
    14  //     -device  : Print device information.
    15  //     -raw     : Send raw command and print response.
    16  //     -help    : Print help message.
    17  package main
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"log"
    23  	"os"
    24  	"strconv"
    25  	"time"
    26  
    27  	"github.com/u-root/u-root/pkg/ipmi"
    28  )
    29  
    30  const cmd = "ipmidump [options] "
    31  
    32  var (
    33  	flagChassis = flag.Bool("chassis", false, "print chassis power status")
    34  	flagSEL     = flag.Bool("sel", false, "print SEL information")
    35  	flagLan     = flag.Bool("lan", false, "Print IP address")
    36  	flagRaw     = flag.Bool("raw", false, "Send IPMI raw command")
    37  	flagHelp    = flag.Bool("help", false, "print help message")
    38  	flagDev     = flag.Bool("device", false, "print device information")
    39  )
    40  
    41  func itob(i int) bool { return i != 0 }
    42  
    43  func init() {
    44  	defUsage := flag.Usage
    45  	flag.Usage = func() {
    46  		os.Args[0] = cmd
    47  		defUsage()
    48  	}
    49  }
    50  
    51  func main() {
    52  	flag.Parse()
    53  
    54  	if *flagHelp {
    55  		flag.Usage()
    56  		os.Exit(1)
    57  	}
    58  
    59  	if *flagChassis {
    60  		chassisInfo()
    61  	}
    62  
    63  	if *flagSEL {
    64  		selInfo()
    65  	}
    66  
    67  	if *flagLan {
    68  		lanConfig()
    69  	}
    70  
    71  	if *flagDev {
    72  		deviceID()
    73  	}
    74  
    75  	if *flagRaw {
    76  		sendRawCmd(flag.Args())
    77  	}
    78  }
    79  
    80  func chassisInfo() {
    81  	allow := map[bool]string{true: "allowed", false: "not allowed"}
    82  	act := map[bool]string{true: "active", false: "inactive"}
    83  	state := map[bool]string{true: "true", false: "false"}
    84  
    85  	policy := map[int]string{
    86  		0x0: "always-off",
    87  		0x1: "previous",
    88  		0x2: "always-on",
    89  		0x3: "unknown",
    90  	}
    91  
    92  	event := map[int]string{
    93  		0x10: "IPMI command",
    94  		0x08: "power fault",
    95  		0x04: "power interlock",
    96  		0x02: "power overload",
    97  		0x01: "AC failed",
    98  		0x00: "none",
    99  	}
   100  
   101  	ipmi, err := ipmi.Open(0)
   102  	if err != nil {
   103  		fmt.Printf("Failed to open ipmi device: %v\n", err)
   104  	}
   105  	defer ipmi.Close()
   106  
   107  	if status, err := ipmi.GetChassisStatus(); err != nil {
   108  		fmt.Printf("Failed to get chassis power status: %v\n", err)
   109  	} else {
   110  		// Current power status
   111  		data := int(status.CurrentPowerState)
   112  		fmt.Println("Chassis power status")
   113  		fmt.Println("Power Restore Policy:", policy[(data>>5)&0x03])
   114  		fmt.Println("Power Control Fault :", state[itob(data&0x10)])
   115  		fmt.Println("Power Fault         :", state[itob(data&0x08)])
   116  		fmt.Println("Power Interlock     :", act[itob(data&0x04)])
   117  		fmt.Println("Power Overload      :", state[itob(data&0x02)])
   118  		fmt.Printf("Power Status        : ")
   119  		if (data & 0x01) != 0 {
   120  			fmt.Println("on")
   121  		} else {
   122  			fmt.Println("off")
   123  		}
   124  
   125  		// Last power event
   126  		data = int(status.LastPowerEvent)
   127  		fmt.Println("Last Power Event    :", event[data&0x1F])
   128  
   129  		// Misc. chassis state
   130  		data = int(status.MiscChassisState)
   131  		fmt.Println("Misc. chassis state")
   132  		fmt.Println("Cooling/Fan Fault   :", state[itob(data&0x08)])
   133  		fmt.Println("Drive Fault         :", state[itob(data&0x04)])
   134  		fmt.Println("Front Panel Lockout :", act[itob(data&0x02)])
   135  		fmt.Println("Chass Intrusion     :", act[itob(data&0x01)])
   136  
   137  		// Front panel button (optional)
   138  		data = int(status.FrontPanelButton)
   139  		if status.FrontPanelButton != 0 {
   140  			fmt.Println("Front Panel Button")
   141  			fmt.Println("Standby Button Disable    :", allow[itob(data&0x80)])
   142  			fmt.Println("Diagnostic Buttton Disable:", allow[itob(data&0x40)])
   143  			fmt.Println("Reset Button Disable      :", allow[itob(data&0x20)])
   144  			fmt.Println("Power-off Button Disable  :", allow[itob(data&0x10)])
   145  
   146  			fmt.Println("Standby Button            :", state[itob(data&0x08)])
   147  			fmt.Println("Diagnostic Buttton        :", state[itob(data&0x04)])
   148  			fmt.Println("Reset Button              :", state[itob(data&0x02)])
   149  			fmt.Println("Power-off Button          :", state[itob(data&0x01)])
   150  		} else {
   151  			fmt.Println("Front Panel Button  : none")
   152  		}
   153  	}
   154  }
   155  
   156  func selInfo() {
   157  	support := map[bool]string{true: "supported", false: "unsupported"}
   158  
   159  	ipmi, err := ipmi.Open(0)
   160  	if err != nil {
   161  		fmt.Printf("Failed to open ipmi device: %v\n", err)
   162  	}
   163  	defer ipmi.Close()
   164  
   165  	if info, err := ipmi.GetSELInfo(); err != nil {
   166  		fmt.Printf("Failed to get SEL information: %v\n", err)
   167  	} else {
   168  		fmt.Println("SEL information")
   169  
   170  		switch info.Version {
   171  		case 0x51:
   172  			fallthrough
   173  		case 0x02:
   174  			fmt.Printf("Version        : %d.%d (1.5, 2.0 compliant)\n", info.Version&0x0F, info.Version>>4)
   175  		default:
   176  			fmt.Println("Version        : unknown")
   177  		}
   178  
   179  		fmt.Println("Entries        :", info.Entries)
   180  		fmt.Printf("Free Space     : %d bytes\n", info.FreeSpace)
   181  
   182  		// Most recent addition/erase timestamp
   183  		fmt.Printf("Last Add Time  : ")
   184  		if info.LastAddTime != 0xFFFFFFFF {
   185  			fmt.Println(time.Unix(int64(info.LastAddTime), 0))
   186  		} else {
   187  			fmt.Println("not available")
   188  		}
   189  
   190  		fmt.Printf("Last Del Time  : ")
   191  		if info.LastDelTime != 0xFFFFFFFF {
   192  			fmt.Println(time.Unix(int64(info.LastDelTime), 0))
   193  		} else {
   194  			fmt.Println("not available")
   195  		}
   196  
   197  		// Operation Support
   198  		fmt.Printf("Overflow       : ")
   199  		if (info.OpSupport & 0x80) != 0 {
   200  			fmt.Println("true")
   201  		} else {
   202  			fmt.Println("false")
   203  		}
   204  
   205  		data := int(info.OpSupport)
   206  		if (data & 0x0F) != 0 {
   207  			fmt.Println("Supported cmds")
   208  			fmt.Println("Delete         :", support[itob(data&0x08)])
   209  			fmt.Println("Partial Add    :", support[itob(data&0x04)])
   210  			fmt.Println("Reserve        :", support[itob(data&0x02)])
   211  			fmt.Println("Get Alloc Info :", support[itob(data&0x01)])
   212  		} else {
   213  			fmt.Println("Supported cmds : none")
   214  		}
   215  	}
   216  }
   217  
   218  func lanConfig() {
   219  	const (
   220  		setInProgress byte = iota
   221  		_
   222  		_
   223  		IPAddress
   224  		IPAddressSrc
   225  		MACAddress
   226  	)
   227  
   228  	setInProgressStr := []string{
   229  		"Set Complete", "Set In Progress", "Commit Write", "Reserved",
   230  	}
   231  
   232  	IPAddressSrcStr := []string{
   233  		"Unspecified", "Static Address", "DHCP Address", "BIOS Assigned Address",
   234  	}
   235  
   236  	ipmi, err := ipmi.Open(0)
   237  	if err != nil {
   238  		log.Fatal(err)
   239  	}
   240  	defer ipmi.Close()
   241  
   242  	// data 1	completion code
   243  	// data 2	parameter revision, 0x11
   244  	// data 3:N	data
   245  
   246  	// set in progress
   247  	if buf, err := ipmi.GetLanConfig(1, setInProgress); err != nil {
   248  		fmt.Printf("Failed to get LAN config: %v\n", err)
   249  	} else {
   250  		fmt.Printf("Set In Progress   : ")
   251  		if int(buf[2]) < len(setInProgressStr) {
   252  			fmt.Println(setInProgressStr[buf[2]])
   253  		} else {
   254  			fmt.Println("Unknown")
   255  			fmt.Printf("%v\n", buf)
   256  		}
   257  	}
   258  
   259  	// ip address source
   260  	if buf, err := ipmi.GetLanConfig(1, IPAddressSrc); err != nil {
   261  		fmt.Printf("Failed to get LAN config: %v\n", err)
   262  	} else {
   263  		fmt.Printf("IP Address Source : ")
   264  		if int(buf[2]) < len(IPAddressSrcStr) {
   265  			fmt.Println(IPAddressSrcStr[buf[2]])
   266  		} else {
   267  			fmt.Println("Other")
   268  			fmt.Printf("%v\n", buf)
   269  		}
   270  	}
   271  
   272  	// ip address
   273  	if buf, err := ipmi.GetLanConfig(1, IPAddress); err != nil {
   274  		fmt.Printf("Failed to get LAN config: %v\n", err)
   275  	} else {
   276  		fmt.Printf("IP Address        : ")
   277  		if len(buf) == 6 {
   278  			fmt.Printf("%d.%d.%d.%d\n", buf[2], buf[3], buf[4], buf[5])
   279  		} else {
   280  			fmt.Printf("Unknown\n")
   281  		}
   282  	}
   283  
   284  	// MAC address
   285  	if buf, err := ipmi.GetLanConfig(1, MACAddress); err != nil {
   286  		fmt.Printf("Failed to get LAN config: %v\n", err)
   287  	} else {
   288  		fmt.Printf("MAC Address       : ")
   289  		if len(buf) == 8 {
   290  			fmt.Printf("%02x:%02x:%02x:%02x:%02x:%02x\n", buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])
   291  		} else {
   292  			fmt.Printf("Unknown\n")
   293  		}
   294  	}
   295  }
   296  
   297  func deviceID() {
   298  	status := map[byte]string{
   299  		0x80: "yes",
   300  		0x00: "no",
   301  	}
   302  
   303  	adtlDevSupport := []string{
   304  		"Sensor Device",         /* bit 0 */
   305  		"SDR Repository Device", /* bit 1 */
   306  		"SEL Device",            /* bit 2 */
   307  		"FRU Inventory Device",  /* bit 3 */
   308  		"IPMB Event Receiver",   /* bit 4 */
   309  		"IPMB Event Generator",  /* bit 5 */
   310  		"Bridge",                /* bit	6 */
   311  		"Chassis Device",        /* bit 7 */
   312  	}
   313  
   314  	ipmi, err := ipmi.Open(0)
   315  	if err != nil {
   316  		fmt.Printf("Failed to open ipmi device: %v\n", err)
   317  	}
   318  	defer ipmi.Close()
   319  
   320  	if info, err := ipmi.GetDeviceID(); err != nil {
   321  		fmt.Printf("Failed to get device ID information: %v\n", err)
   322  	} else {
   323  		fmt.Println("Device ID information")
   324  		fmt.Printf("%-26s: %d\n", "Device ID", info.DeviceID)
   325  		fmt.Printf("%-26s: %d\n", "Device Revision", (info.DeviceRevision & 0x0F))
   326  		fmt.Printf("%-26s: %d.%02x\n", "Firmware Revision",
   327  			(info.FwRev1 & 0x3F), info.FwRev2)
   328  
   329  		spec := uint8(info.IpmiVersion)
   330  		fmt.Printf("%-26s: %x.%x\n", "IPMI Version", spec&0x0F, (spec&0xF0)>>4)
   331  
   332  		var mid uint32
   333  		mid = uint32(info.ManufacturerID[2]) << 16
   334  		mid |= uint32(info.ManufacturerID[1]) << 8
   335  		mid |= uint32(info.ManufacturerID[0])
   336  
   337  		fmt.Printf("%-26s: %d (0x%04X)\n", "Manufacturer ID", mid, mid)
   338  
   339  		var pid uint16
   340  		pid = uint16(info.ProductID[1]) << 8
   341  		pid |= uint16(info.ProductID[0])
   342  
   343  		fmt.Printf("%-26s: %d (0x%04X)\n", "Product ID", pid, pid)
   344  
   345  		// bit 7 == 0 indicates normal operation
   346  		fmt.Printf("%-26s: %s\n", "Device Available", status[(^info.FwRev1&0x80)])
   347  		fmt.Printf("%-26s: %s\n", "Provides Device SDRs",
   348  			status[(info.DeviceRevision&0x80)])
   349  
   350  		fmt.Printf("%-26s:\n", "Additional Device Support")
   351  		for i := 0; i < 8; i++ {
   352  			if (info.AdtlDeviceSupport & (1 << i)) != 0 {
   353  				fmt.Printf("    %s\n", adtlDevSupport[i])
   354  			}
   355  		}
   356  
   357  		// This field is optional, 4 bytes.
   358  		fmt.Printf("%-26s:\n", "Aux Firmware Rev Info")
   359  		for _, val := range info.AuxFwRev {
   360  			fmt.Printf("    0x%02x\n", val)
   361  		}
   362  	}
   363  }
   364  
   365  func sendRawCmd(cmds []string) {
   366  	ipmi, err := ipmi.Open(0)
   367  	if err != nil {
   368  		log.Fatal(err)
   369  	}
   370  	defer ipmi.Close()
   371  
   372  	data := make([]byte, 0)
   373  
   374  	for _, cmd := range cmds {
   375  		val, err := strconv.ParseInt(cmd, 0, 16)
   376  		if err != nil {
   377  			fmt.Printf("Invalid syntax: \"%s\"\n", cmd)
   378  			return
   379  		}
   380  		data = append(data, byte(val))
   381  	}
   382  
   383  	if buf, err := ipmi.RawCmd(data); err != nil {
   384  		fmt.Printf("Unable to send RAW command: %v\n", err)
   385  	} else {
   386  		for i, x := range buf {
   387  			fmt.Printf("| 0x%-2x ", x)
   388  			if i%8 == 7 || i == len(buf)-1 {
   389  				fmt.Printf("|\n")
   390  			}
   391  		}
   392  	}
   393  }