1de6ed120SBrad Bishop#!/usr/bin/env python
240a360c2SBrad Bishop
340a360c2SBrad Bishopimport gobject
440a360c2SBrad Bishopimport dbus
540a360c2SBrad Bishopimport dbus.service
640a360c2SBrad Bishopimport dbus.mainloop.glib
740a360c2SBrad Bishopimport os
840a360c2SBrad Bishopimport obmc.dbuslib.propertycacher as PropertyCacher
940a360c2SBrad Bishopfrom obmc.dbuslib.bindings import DbusProperties, DbusObjectManager, get_dbus
1040a360c2SBrad Bishopimport obmc.enums
110b380f7bSBrad Bishopimport obmc_system_config as System
126173a896SBrad Bishopimport obmc.mapper.utils
137e5ec46dSBrad Bishopimport obmc.inventory
14a7ac805bSBrad Bishopimport obmc.system
1540a360c2SBrad Bishop
1640a360c2SBrad BishopDBUS_NAME = 'org.openbmc.managers.System'
1740a360c2SBrad BishopOBJ_NAME = '/org/openbmc/managers/System'
1840a360c2SBrad BishopINTF_SENSOR = 'org.openbmc.SensorValue'
1940a360c2SBrad BishopINTF_ITEM = 'org.openbmc.InventoryItem'
2040a360c2SBrad Bishop
21520f8b05SRatan GuptaSYS_STATE_FILE = '/var/lib/obmc/last-system-state'
22520f8b05SRatan GuptaPOWER_OFF = "0"
23520f8b05SRatan Gupta
2440a360c2SBrad Bishop
2540a360c2SBrad Bishopclass SystemManager(DbusProperties, DbusObjectManager):
2640a360c2SBrad Bishop    def __init__(self, bus, obj_name):
27f47f5faaSBrad Bishop        super(SystemManager, self).__init__(
28f47f5faaSBrad Bishop            conn=bus,
29f47f5faaSBrad Bishop            object_path=obj_name)
30fa736499SBrad Bishop        self.bus = bus
3140a360c2SBrad Bishop
32fa736499SBrad Bishop        bus.add_signal_receiver(
33416539dfSBrad Bishop            self.NewObjectHandler,
3440a360c2SBrad Bishop            signal_name="InterfacesAdded", sender_keyword='bus_name')
35416539dfSBrad Bishop        bus.add_signal_receiver(
36416539dfSBrad Bishop            self.SystemStateHandler, signal_name="GotoSystemState")
3740a360c2SBrad Bishop
38520f8b05SRatan Gupta        bus.add_signal_receiver(
39520f8b05SRatan Gupta            self.chassisPowerStateHandler,
40520f8b05SRatan Gupta            dbus_interface="org.freedesktop.DBus.Properties",
41520f8b05SRatan Gupta            signal_name="PropertiesChanged",
42520f8b05SRatan Gupta            path="/org/openbmc/control/power0")
4340a360c2SBrad Bishop
44520f8b05SRatan Gupta        self.Set(DBUS_NAME, "current_state", "")
45520f8b05SRatan Gupta        self.Set(DBUS_NAME, "system_last_state", POWER_OFF)
46520f8b05SRatan Gupta        self.import_system_state_from_disk()
47520f8b05SRatan Gupta        # replace symbolic path in ID_LOOKUP
4840a360c2SBrad Bishop        for category in System.ID_LOOKUP:
4940a360c2SBrad Bishop            for key in System.ID_LOOKUP[category]:
5040a360c2SBrad Bishop                val = System.ID_LOOKUP[category][key]
51416539dfSBrad Bishop                new_val = val.replace(
527e5ec46dSBrad Bishop                    "<inventory_root>", obmc.inventory.INVENTORY_ROOT)
5340a360c2SBrad Bishop                System.ID_LOOKUP[category][key] = new_val
5440a360c2SBrad Bishop
5540a360c2SBrad Bishop        self.SystemStateHandler(System.SYSTEM_STATES[0])
5640a360c2SBrad Bishop
5740a360c2SBrad Bishop        print "SystemManager Init Done"
5840a360c2SBrad Bishop
59520f8b05SRatan Gupta    def chassisPowerStateHandler(self, interface_name, changed_properties,
60520f8b05SRatan Gupta                                 invalidated_properties):
61520f8b05SRatan Gupta        value = changed_properties.get('state')
62520f8b05SRatan Gupta        if value is not None:
63520f8b05SRatan Gupta            self.write_to_disk_and_update(str(value))
64520f8b05SRatan Gupta
6540a360c2SBrad Bishop    def SystemStateHandler(self, state_name):
6640a360c2SBrad Bishop        print "Running System State: "+state_name
6740a360c2SBrad Bishop
6840a360c2SBrad Bishop        self.Set(DBUS_NAME, "current_state", state_name)
6940a360c2SBrad Bishop
706173a896SBrad Bishop        waitlist = System.EXIT_STATE_DEPEND.get(state_name, {}).keys()
716173a896SBrad Bishop        if waitlist:
726173a896SBrad Bishop            self.waiter = obmc.mapper.utils.Wait(
736173a896SBrad Bishop                self.bus, waitlist,
746173a896SBrad Bishop                callback=self.gotoNextState)
756173a896SBrad Bishop
7640a360c2SBrad Bishop    def gotoNextState(self):
7740a360c2SBrad Bishop        s = 0
7840a360c2SBrad Bishop        current_state = self.Get(DBUS_NAME, "current_state")
7940a360c2SBrad Bishop        for i in range(len(System.SYSTEM_STATES)):
8040a360c2SBrad Bishop            if (System.SYSTEM_STATES[i] == current_state):
8140a360c2SBrad Bishop                s = i+1
8240a360c2SBrad Bishop
8340a360c2SBrad Bishop        if (s == len(System.SYSTEM_STATES)):
8440a360c2SBrad Bishop            print "ERROR SystemManager: No more system states"
8540a360c2SBrad Bishop        else:
8640a360c2SBrad Bishop            new_state_name = System.SYSTEM_STATES[s]
8740a360c2SBrad Bishop            print "SystemManager Goto System State: "+new_state_name
8840a360c2SBrad Bishop            self.SystemStateHandler(new_state_name)
8940a360c2SBrad Bishop
90520f8b05SRatan Gupta    def import_system_state_from_disk(self):
91520f8b05SRatan Gupta        state = str(POWER_OFF)
92520f8b05SRatan Gupta        try:
93520f8b05SRatan Gupta            with open(SYS_STATE_FILE, 'r+') as f:
94520f8b05SRatan Gupta                state = f.readline().rstrip('\n')
95520f8b05SRatan Gupta        except IOError:
96520f8b05SRatan Gupta            pass
97520f8b05SRatan Gupta        self.Set(DBUS_NAME, "system_last_state", state)
98520f8b05SRatan Gupta        return state
99520f8b05SRatan Gupta
100520f8b05SRatan Gupta    def write_to_disk_and_update(self, state):
101520f8b05SRatan Gupta        try:
102520f8b05SRatan Gupta            with open(SYS_STATE_FILE, 'w+') as f:
103520f8b05SRatan Gupta                f.write(str(state))
104520f8b05SRatan Gupta                self.Set(DBUS_NAME, "system_last_state", state)
105520f8b05SRatan Gupta        except IOError:
106520f8b05SRatan Gupta            pass
107520f8b05SRatan Gupta
108416539dfSBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='', out_signature='s')
10940a360c2SBrad Bishop    def getSystemState(self):
11040a360c2SBrad Bishop        return self.Get(DBUS_NAME, "current_state")
11140a360c2SBrad Bishop
11240a360c2SBrad Bishop    def doObjectLookup(self, category, key):
11340a360c2SBrad Bishop        obj_path = ""
11440a360c2SBrad Bishop        intf_name = INTF_ITEM
11540a360c2SBrad Bishop        try:
11640a360c2SBrad Bishop            obj_path = System.ID_LOOKUP[category][key]
11740a360c2SBrad Bishop            parts = obj_path.split('/')
11840a360c2SBrad Bishop            if (parts[3] == 'sensors'):
11940a360c2SBrad Bishop                intf_name = INTF_SENSOR
12040a360c2SBrad Bishop        except Exception as e:
12140a360c2SBrad Bishop            print "ERROR SystemManager: "+str(e)+" not found in lookup"
12240a360c2SBrad Bishop
123fc38a575SBrad Bishop        return [obj_path, intf_name]
12440a360c2SBrad Bishop
125fc38a575SBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='ss', out_signature='(ss)')
12640a360c2SBrad Bishop    def getObjectFromId(self, category, key):
12740a360c2SBrad Bishop        return self.doObjectLookup(category, key)
12840a360c2SBrad Bishop
129fc38a575SBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='sy', out_signature='(ss)')
13040a360c2SBrad Bishop    def getObjectFromByteId(self, category, key):
13140a360c2SBrad Bishop        byte = int(key)
13240a360c2SBrad Bishop        return self.doObjectLookup(category, byte)
13340a360c2SBrad Bishop
13440a360c2SBrad Bishop    # Get the FRU area names defined in ID_LOOKUP table given a fru_id.
13540a360c2SBrad Bishop    # If serval areas are defined for a fru_id, the areas are returned
13640a360c2SBrad Bishop    # together as a string with each area name seperated with ','.
13740a360c2SBrad Bishop    # If no fru area defined in ID_LOOKUP, an empty string will be returned.
138416539dfSBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='y', out_signature='s')
13940a360c2SBrad Bishop    def getFRUArea(self, fru_id):
14040a360c2SBrad Bishop        ret_str = ''
14140a360c2SBrad Bishop        fru_id = '_' + str(fru_id)
142416539dfSBrad Bishop        area_list = [
143416539dfSBrad Bishop            area for area in System.ID_LOOKUP['FRU_STR'].keys()
14440a360c2SBrad Bishop            if area.endswith(fru_id)]
14540a360c2SBrad Bishop        for area in area_list:
14640a360c2SBrad Bishop            ret_str = area + ',' + ret_str
14740a360c2SBrad Bishop        # remove the last ','
14840a360c2SBrad Bishop        return ret_str[:-1]
14940a360c2SBrad Bishop
15040a360c2SBrad Bishop    def NewObjectHandler(self, obj_path, iprops, bus_name=None):
15140a360c2SBrad Bishop        current_state = self.Get(DBUS_NAME, "current_state")
1524de42643SBrad Bishop        if current_state not in System.EXIT_STATE_DEPEND:
1534de42643SBrad Bishop            return
15440a360c2SBrad Bishop
1554de42643SBrad Bishop        if obj_path in System.EXIT_STATE_DEPEND[current_state]:
1564de42643SBrad Bishop            print "New object: "+obj_path+" ("+bus_name+")"
15740a360c2SBrad Bishop
158416539dfSBrad Bishop    @dbus.service.method(DBUS_NAME, in_signature='s', out_signature='sis')
15940a360c2SBrad Bishop    def gpioInit(self, name):
16040a360c2SBrad Bishop        gpio_path = ''
16140a360c2SBrad Bishop        gpio_num = -1
16240a360c2SBrad Bishop        r = ['', gpio_num, '']
163416539dfSBrad Bishop        if name not in System.GPIO_CONFIG:
164605620d2SXo Wang            # TODO: Better error handling
165605620d2SXo Wang            msg = "ERROR: "+name+" not found in GPIO config table"
166605620d2SXo Wang            print msg
167605620d2SXo Wang            raise Exception(msg)
16840a360c2SBrad Bishop        else:
16940a360c2SBrad Bishop
17040a360c2SBrad Bishop            gpio_num = -1
17140a360c2SBrad Bishop            gpio = System.GPIO_CONFIG[name]
172416539dfSBrad Bishop            if 'gpio_num' in System.GPIO_CONFIG[name]:
17340a360c2SBrad Bishop                gpio_num = gpio['gpio_num']
17440a360c2SBrad Bishop            else:
175416539dfSBrad Bishop                if 'gpio_pin' in System.GPIO_CONFIG[name]:
176a7ac805bSBrad Bishop                    gpio_num = obmc.system.convertGpio(gpio['gpio_pin'])
17740a360c2SBrad Bishop                else:
178605620d2SXo Wang                    msg = "ERROR: SystemManager - GPIO lookup failed for "+name
179605620d2SXo Wang                    print msg
180605620d2SXo Wang                    raise Exception(msg)
18140a360c2SBrad Bishop
18240a360c2SBrad Bishop            if (gpio_num != -1):
18340a360c2SBrad Bishop                r = [obmc.enums.GPIO_DEV, gpio_num, gpio['direction']]
18440a360c2SBrad Bishop        return r
18540a360c2SBrad Bishop
1863f87de8bSXo Wang    @dbus.service.method(DBUS_NAME, in_signature='',
187*75a18a23SLei YU            out_signature='ssa(sb)a(sb)a(sbb)ssssa(sb)')
188*75a18a23SLei YU    def getGpioConfiguration(self):
189*75a18a23SLei YU        power_config = System.GPIO_CONFIGS.get('power_config', {})
190*75a18a23SLei YU        power_good_in = power_config.get('power_good_in', '')
191*75a18a23SLei YU        latch_out = power_config.get('latch_out', '')
192*75a18a23SLei YU        power_up_outs = power_config.get('power_up_outs', [])
193*75a18a23SLei YU        reset_outs = power_config.get('reset_outs', [])
194*75a18a23SLei YU        pci_reset_outs = System.GPIO_CONFIGS.get('pci_reset_outs', [])
195*75a18a23SLei YU        hostctl_config = System.GPIO_CONFIGS.get('hostctl_config', {})
196*75a18a23SLei YU        fsi_data = hostctl_config.get('fsi_data', '')
197*75a18a23SLei YU        fsi_clk = hostctl_config.get('fsi_clk', '')
198*75a18a23SLei YU        fsi_enable = hostctl_config.get('fsi_enable', '')
199*75a18a23SLei YU        cronus_sel = hostctl_config.get('cronus_sel', '')
200*75a18a23SLei YU        optionals = hostctl_config.get('optionals', [])
201*75a18a23SLei YU        r = [power_good_in, latch_out, power_up_outs, reset_outs, pci_reset_outs,\
202*75a18a23SLei YU             fsi_data, fsi_clk, fsi_enable, cronus_sel, optionals]
2033f87de8bSXo Wang        print "Power GPIO config: " + str(r)
2043f87de8bSXo Wang        return r
2053f87de8bSXo Wang
20640a360c2SBrad Bishop
20740a360c2SBrad Bishopif __name__ == '__main__':
20840a360c2SBrad Bishop    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
20940a360c2SBrad Bishop    bus = get_dbus()
21040a360c2SBrad Bishop    obj = SystemManager(bus, OBJ_NAME)
21140a360c2SBrad Bishop    mainloop = gobject.MainLoop()
212f0f3efe1SBrad Bishop    obj.unmask_signals()
21370852a38SBrad Bishop    name = dbus.service.BusName(DBUS_NAME, bus)
21440a360c2SBrad Bishop
21540a360c2SBrad Bishop    print "Running SystemManager"
21640a360c2SBrad Bishop    mainloop.run()
21753066750SBrad Bishop
21853066750SBrad Bishop# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
219