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 }