1*98a23840SMatthew Barth #include "sensorhandler.h"
2*98a23840SMatthew Barth #include "ipmid-api.h"
3*98a23840SMatthew Barth #include <stdio.h>
4*98a23840SMatthew Barth #include <string.h>
5*98a23840SMatthew Barth #include <stdint.h>
6*98a23840SMatthew Barth #include <systemd/sd-bus.h>
7*98a23840SMatthew Barth 
8*98a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void *);
9*98a23840SMatthew Barth extern int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) ;
10*98a23840SMatthew Barth extern int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) ;
11*98a23840SMatthew Barth 
12*98a23840SMatthew Barth void register_netfn_sen_functions()   __attribute__((constructor));
13*98a23840SMatthew Barth 
14*98a23840SMatthew Barth struct sensorTypemap_t {
15*98a23840SMatthew Barth     uint8_t number;
16*98a23840SMatthew Barth     uint8_t typecode;
17*98a23840SMatthew Barth     char dbusname[32];
18*98a23840SMatthew Barth } ;
19*98a23840SMatthew Barth 
20*98a23840SMatthew Barth 
21*98a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = {
22*98a23840SMatthew Barth 
23*98a23840SMatthew Barth     {0x01, 0x6F, "Temp"},
24*98a23840SMatthew Barth     {0x0C, 0x6F, "DIMM"},
25*98a23840SMatthew Barth     {0x0C, 0x6F, "MEMORY_BUFFER"},
26*98a23840SMatthew Barth     {0x07, 0x6F, "PROC"},
27*98a23840SMatthew Barth     {0x07, 0x6F, "CORE"},
28*98a23840SMatthew Barth     {0x07, 0x6F, "CPU"},
29*98a23840SMatthew Barth     {0x0F, 0x6F, "BootProgress"},
30*98a23840SMatthew Barth     {0xe9, 0x09, "OccStatus"},  // E9 is an internal mapping to handle sensor type code os 0x09
31*98a23840SMatthew Barth     {0xC3, 0x6F, "BootCount"},
32*98a23840SMatthew Barth     {0x1F, 0x6F, "OperatingSystemStatus"},
33*98a23840SMatthew Barth     {0x12, 0x6F, "SYSTEM_EVENT"},
34*98a23840SMatthew Barth     {0xC7, 0x03, "SYSTEM"},
35*98a23840SMatthew Barth     {0xC7, 0x03, "MAIN_PLANAR"},
36*98a23840SMatthew Barth     {0xC2, 0x6F, "PowerCap"},
37*98a23840SMatthew Barth     {0xFF, 0x00, ""},
38*98a23840SMatthew Barth };
39*98a23840SMatthew Barth 
40*98a23840SMatthew Barth 
41*98a23840SMatthew Barth struct sensor_data_t {
42*98a23840SMatthew Barth     uint8_t sennum;
43*98a23840SMatthew Barth }  __attribute__ ((packed)) ;
44*98a23840SMatthew Barth 
45*98a23840SMatthew Barth struct sensorreadingresp_t {
46*98a23840SMatthew Barth     uint8_t value;
47*98a23840SMatthew Barth     uint8_t operation;
48*98a23840SMatthew Barth     uint8_t indication[2];
49*98a23840SMatthew Barth }  __attribute__ ((packed)) ;
50*98a23840SMatthew Barth 
51*98a23840SMatthew Barth uint8_t dbus_to_sensor_type(char *p) {
52*98a23840SMatthew Barth 
53*98a23840SMatthew Barth     sensorTypemap_t *s = g_SensorTypeMap;
54*98a23840SMatthew Barth     char r=0;
55*98a23840SMatthew Barth 
56*98a23840SMatthew Barth     while (s->number != 0xFF) {
57*98a23840SMatthew Barth         if (!strcmp(s->dbusname,p)) {
58*98a23840SMatthew Barth             r = s->number;
59*98a23840SMatthew Barth              break;
60*98a23840SMatthew Barth         }
61*98a23840SMatthew Barth         s++;
62*98a23840SMatthew Barth     }
63*98a23840SMatthew Barth 
64*98a23840SMatthew Barth 
65*98a23840SMatthew Barth     if (s->number == 0xFF)
66*98a23840SMatthew Barth         printf("Failed to find Sensor Type %s\n", p);
67*98a23840SMatthew Barth 
68*98a23840SMatthew Barth     return r;
69*98a23840SMatthew Barth }
70*98a23840SMatthew Barth 
71*98a23840SMatthew Barth 
72*98a23840SMatthew Barth uint8_t dbus_to_sensor_type_from_dbus(dbus_interface_t *a) {
73*98a23840SMatthew Barth     char fru_type_name[64];
74*98a23840SMatthew Barth     int r= 0;
75*98a23840SMatthew Barth 
76*98a23840SMatthew Barth     r = find_interface_property_fru_type(a, "fru_type", fru_type_name);
77*98a23840SMatthew Barth     if (r<0) {
78*98a23840SMatthew Barth         fprintf(stderr, "Failed to get a fru type: %s", strerror(-r));
79*98a23840SMatthew Barth         return -1;
80*98a23840SMatthew Barth     } else {
81*98a23840SMatthew Barth         return dbus_to_sensor_type(fru_type_name);
82*98a23840SMatthew Barth     }
83*98a23840SMatthew Barth }
84*98a23840SMatthew Barth 
85*98a23840SMatthew Barth 
86*98a23840SMatthew Barth uint8_t find_sensor(uint8_t sensor_number) {
87*98a23840SMatthew Barth 
88*98a23840SMatthew Barth     dbus_interface_t a;
89*98a23840SMatthew Barth     char *p;
90*98a23840SMatthew Barth     char r;
91*98a23840SMatthew Barth 
92*98a23840SMatthew Barth     r = find_openbmc_path("SENSOR", sensor_number, &a);
93*98a23840SMatthew Barth 
94*98a23840SMatthew Barth     if (r < 0) { return 0; }
95*98a23840SMatthew Barth 
96*98a23840SMatthew Barth     // This is where sensors that do not exist in dbus but do
97*98a23840SMatthew Barth     // exist in the host code stop.  This should indicate it
98*98a23840SMatthew Barth     // is not a supported sensor
99*98a23840SMatthew Barth     if (a.interface[0] == 0) { return 0;}
100*98a23840SMatthew Barth 
101*98a23840SMatthew Barth     if (strstr(a.interface, "InventoryItem")) {
102*98a23840SMatthew Barth         // InventoryItems are real frus.  So need to get the
103*98a23840SMatthew Barth         // fru_type property
104*98a23840SMatthew Barth         r = dbus_to_sensor_type_from_dbus(&a);
105*98a23840SMatthew Barth     } else {
106*98a23840SMatthew Barth         // Non InventoryItems
107*98a23840SMatthew Barth         p = strrchr (a.path, '/');
108*98a23840SMatthew Barth         r = dbus_to_sensor_type(p+1);
109*98a23840SMatthew Barth     }
110*98a23840SMatthew Barth 
111*98a23840SMatthew Barth     return r;
112*98a23840SMatthew Barth  }
113*98a23840SMatthew Barth 
114*98a23840SMatthew Barth 
115*98a23840SMatthew Barth 
116*98a23840SMatthew Barth 
117*98a23840SMatthew Barth 
118*98a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
119*98a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
120*98a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
121*98a23840SMatthew Barth {
122*98a23840SMatthew Barth     sensor_data_t *reqptr = (sensor_data_t*)request;
123*98a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
124*98a23840SMatthew Barth 
125*98a23840SMatthew Barth     printf("IPMI GET_SENSOR_TYPE [0x%02X]\n",reqptr->sennum);
126*98a23840SMatthew Barth 
127*98a23840SMatthew Barth     // TODO Not sure what the System-event-sensor is suppose to return
128*98a23840SMatthew Barth     // need to ask Hostboot team
129*98a23840SMatthew Barth     unsigned char buf[] = {0x00,0x6F};
130*98a23840SMatthew Barth 
131*98a23840SMatthew Barth     buf[0] = find_sensor(reqptr->sennum);
132*98a23840SMatthew Barth 
133*98a23840SMatthew Barth     // HACK UNTIL Dbus gets updated or we find a better way
134*98a23840SMatthew Barth     if (buf[0] == 0) {
135*98a23840SMatthew Barth         rc = IPMI_CC_SENSOR_INVALID;
136*98a23840SMatthew Barth     }
137*98a23840SMatthew Barth 
138*98a23840SMatthew Barth 
139*98a23840SMatthew Barth     *data_len = sizeof(buf);
140*98a23840SMatthew Barth     memcpy(response, &buf, *data_len);
141*98a23840SMatthew Barth 
142*98a23840SMatthew Barth     return rc;
143*98a23840SMatthew Barth }
144*98a23840SMatthew Barth 
145*98a23840SMatthew Barth 
146*98a23840SMatthew Barth 
147*98a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
148*98a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
149*98a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
150*98a23840SMatthew Barth {
151*98a23840SMatthew Barth     sensor_data_t *reqptr = (sensor_data_t*)request;
152*98a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
153*98a23840SMatthew Barth 
154*98a23840SMatthew Barth     printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum);
155*98a23840SMatthew Barth 
156*98a23840SMatthew Barth     updateSensorRecordFromSSRAESC(reqptr);
157*98a23840SMatthew Barth 
158*98a23840SMatthew Barth     *data_len=0;
159*98a23840SMatthew Barth 
160*98a23840SMatthew Barth     return rc;
161*98a23840SMatthew Barth }
162*98a23840SMatthew Barth 
163*98a23840SMatthew Barth 
164*98a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
165*98a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
166*98a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
167*98a23840SMatthew Barth {
168*98a23840SMatthew Barth     sensor_data_t *reqptr = (sensor_data_t*)request;
169*98a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_SENSOR_INVALID;
170*98a23840SMatthew Barth     uint8_t type;
171*98a23840SMatthew Barth     sensorreadingresp_t *resp = (sensorreadingresp_t*) response;
172*98a23840SMatthew Barth     int r;
173*98a23840SMatthew Barth     dbus_interface_t a;
174*98a23840SMatthew Barth     sd_bus *bus = ipmid_get_sd_bus_connection();
175*98a23840SMatthew Barth     sd_bus_message *reply = NULL;
176*98a23840SMatthew Barth     int reading = 0;
177*98a23840SMatthew Barth 
178*98a23840SMatthew Barth 
179*98a23840SMatthew Barth     printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum);
180*98a23840SMatthew Barth 
181*98a23840SMatthew Barth     r = find_openbmc_path("SENSOR", reqptr->sennum, &a);
182*98a23840SMatthew Barth 
183*98a23840SMatthew Barth     if (r < 0) {
184*98a23840SMatthew Barth         fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum);
185*98a23840SMatthew Barth         return IPMI_CC_SENSOR_INVALID;
186*98a23840SMatthew Barth     }
187*98a23840SMatthew Barth 
188*98a23840SMatthew Barth     type = find_sensor(reqptr->sennum);
189*98a23840SMatthew Barth 
190*98a23840SMatthew Barth     fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface);
191*98a23840SMatthew Barth 
192*98a23840SMatthew Barth     *data_len=0;
193*98a23840SMatthew Barth 
194*98a23840SMatthew Barth     switch(type) {
195*98a23840SMatthew Barth         case 0xC3:
196*98a23840SMatthew Barth         case 0xC2:
197*98a23840SMatthew Barth             r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i");
198*98a23840SMatthew Barth             if (r < 0) {
199*98a23840SMatthew Barth                 fprintf(stderr, "Failed to call sd_bus_get_property:%d,  %s\n", r, strerror(-r));
200*98a23840SMatthew Barth                 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
201*98a23840SMatthew Barth                         a.bus, a.path, a.interface);
202*98a23840SMatthew Barth                 break;
203*98a23840SMatthew Barth             }
204*98a23840SMatthew Barth 
205*98a23840SMatthew Barth             r = sd_bus_message_read(reply, "i", &reading);
206*98a23840SMatthew Barth             if (r < 0) {
207*98a23840SMatthew Barth                 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
208*98a23840SMatthew Barth                 break;
209*98a23840SMatthew Barth             }
210*98a23840SMatthew Barth 
211*98a23840SMatthew Barth             printf("Contents of a 0x%02x is 0x%02x\n", type, reading);
212*98a23840SMatthew Barth 
213*98a23840SMatthew Barth             rc = IPMI_CC_OK;
214*98a23840SMatthew Barth             *data_len=sizeof(sensorreadingresp_t);
215*98a23840SMatthew Barth 
216*98a23840SMatthew Barth             resp->value         = (uint8_t)reading;
217*98a23840SMatthew Barth             resp->operation     = 0;
218*98a23840SMatthew Barth             resp->indication[0] = 0;
219*98a23840SMatthew Barth             resp->indication[1] = 0;
220*98a23840SMatthew Barth             break;
221*98a23840SMatthew Barth 
222*98a23840SMatthew Barth         default:
223*98a23840SMatthew Barth             *data_len=0;
224*98a23840SMatthew Barth             rc = IPMI_CC_SENSOR_INVALID;
225*98a23840SMatthew Barth             break;
226*98a23840SMatthew Barth     }
227*98a23840SMatthew Barth 
228*98a23840SMatthew Barth 
229*98a23840SMatthew Barth     reply = sd_bus_message_unref(reply);
230*98a23840SMatthew Barth 
231*98a23840SMatthew Barth     return rc;
232*98a23840SMatthew Barth }
233*98a23840SMatthew Barth 
234*98a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
235*98a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
236*98a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
237*98a23840SMatthew Barth {
238*98a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
239*98a23840SMatthew Barth 
240*98a23840SMatthew Barth     printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd);
241*98a23840SMatthew Barth     *data_len = 0;
242*98a23840SMatthew Barth 
243*98a23840SMatthew Barth     return rc;
244*98a23840SMatthew Barth }
245*98a23840SMatthew Barth 
246*98a23840SMatthew Barth 
247*98a23840SMatthew Barth void register_netfn_sen_functions()
248*98a23840SMatthew Barth {
249*98a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_WILDCARD);
250*98a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, NULL, ipmi_sen_wildcard);
251*98a23840SMatthew Barth 
252*98a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE);
253*98a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, NULL, ipmi_sen_get_sensor_type);
254*98a23840SMatthew Barth 
255*98a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_SET_SENSOR);
256*98a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, NULL, ipmi_sen_set_sensor);
257*98a23840SMatthew Barth 
258*98a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING);
259*98a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, NULL, ipmi_sen_get_sensor_reading);
260*98a23840SMatthew Barth 
261*98a23840SMatthew Barth     return;
262*98a23840SMatthew Barth }
263