xref: /openbmc/skeleton/pyipmitest/ipmi_debug.py (revision 783fbb01)
1#!/usr/bin/env python
2
3import sys
4import subprocess
5import dbus
6import string
7import os
8import fcntl
9import glib
10import gobject
11import dbus.service
12import dbus.mainloop.glib
13
14DBUS_NAME = "org.openbmc.HostIpmi"
15OBJ_NAME = "/org/openbmc/HostIpmi/1"
16
17
18def header(seq, netfn, lun, cmd):
19    return ("seq:   0x%02x\nnetfn: 0x%02x\n\nlun: 0x%02d\ncmd:   0x%02x\n") % (
20        seq,
21        netfn,
22        lun,
23        cmd,
24    )
25
26
27def print_request(seq, netfn, lun, cmd, data):
28    str = header(seq, netfn, lun, cmd)
29    str += "data:  [%s]" % ", ".join(["0x%02x" % x for x in data])
30    print(str)
31
32
33def print_response(seq, netfn, lun, cmd, cc, data):
34    str = header(seq, netfn, lun, cmd)
35    str += "cc:    0x%02x\ndata:  [%s]" % (
36        cc,
37        ", ".join(["0x%02x" % x for x in data]),
38    )
39    print(str)
40
41
42class IpmiDebug(dbus.service.Object):
43    def __init__(self, bus, name):
44        dbus.service.Object.__init__(self, bus, name)
45
46    @dbus.service.signal(DBUS_NAME, "yyyyay")
47    def ReceivedMessage(self, seq, netfn, lun, cmd, data):
48        print("IPMI packet from host:")
49        print_request(seq, netfn, lun, cmd, data)
50
51    @dbus.service.method(DBUS_NAME, "yyyyyay", "x")
52    def sendMessage(self, seq, netfn, lun, cmd, ccode, data):
53        print("IPMI packet sent to host:")
54        print_response(seq, netfn, lun, cmd, ccode, data)
55        return 0
56
57    @dbus.service.method(DBUS_NAME)
58    def setAttention(self):
59        print("IPMI SMS_ATN set")
60
61
62class ConsoleReader(object):
63    def __init__(self, ipmi_obj):
64        self.buffer = ""
65        self.seq = 0
66        self.ipmi_obj = ipmi_obj
67        flags = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
68        flags |= os.O_NONBLOCK
69        fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, flags)
70        glib.io_add_watch(sys.stdin, glib.IO_IN, self.io_callback)
71
72    def io_callback(self, fd, condition):
73        chunk = fd.read()
74        for char in chunk:
75            self.buffer += char
76            if char == "\n":
77                self.line(self.buffer)
78                self.buffer = ""
79
80        return True
81
82    def line(self, data):
83        s = data.split(" ")
84        if len(s) < 2:
85            print("Not enough bytes to form a valid IPMI packet")
86            return
87        try:
88            data = [int(c, 16) for c in s]
89        except ValueError:
90            return
91        self.seq += 1
92        self.ipmi_obj.ReceivedMessage(self.seq, data[0], 0, data[1], data[2:])
93
94
95def main():
96    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
97    bus = dbus.SystemBus()
98    obj = IpmiDebug(bus, OBJ_NAME)
99    mainloop = gobject.MainLoop()
100    r = ConsoleReader(obj)
101
102    obj.unmask_signals()
103    name = dbus.service.BusName(DBUS_NAME, bus)
104
105    print(
106        "Enter IPMI packet as hex values. First three bytes will be used"
107        "as netfn and cmd.\nlun will be zero."
108    )
109    mainloop.run()
110
111
112if __name__ == "__main__":
113    sys.exit(main())
114
115# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
116