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