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