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