198a23840SMatthew Barth #include "sensorhandler.h"
2*37af7331SPatrick Williams #include "host-ipmid/ipmid-api.h"
398a23840SMatthew Barth #include <stdio.h>
498a23840SMatthew Barth #include <string.h>
598a23840SMatthew Barth #include <stdint.h>
698a23840SMatthew Barth #include <systemd/sd-bus.h>
798a23840SMatthew Barth 
898a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void *);
998a23840SMatthew Barth extern int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) ;
1098a23840SMatthew Barth extern int find_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) ;
1198a23840SMatthew Barth 
1298a23840SMatthew Barth void register_netfn_sen_functions()   __attribute__((constructor));
1398a23840SMatthew Barth 
1498a23840SMatthew Barth struct sensorTypemap_t {
1598a23840SMatthew Barth     uint8_t number;
1698a23840SMatthew Barth     uint8_t typecode;
1798a23840SMatthew Barth     char dbusname[32];
1898a23840SMatthew Barth } ;
1998a23840SMatthew Barth 
2098a23840SMatthew Barth 
2198a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = {
2298a23840SMatthew Barth 
2398a23840SMatthew Barth     {0x01, 0x6F, "Temp"},
2498a23840SMatthew Barth     {0x0C, 0x6F, "DIMM"},
2598a23840SMatthew Barth     {0x0C, 0x6F, "MEMORY_BUFFER"},
2698a23840SMatthew Barth     {0x07, 0x6F, "PROC"},
2798a23840SMatthew Barth     {0x07, 0x6F, "CORE"},
2898a23840SMatthew Barth     {0x07, 0x6F, "CPU"},
2998a23840SMatthew Barth     {0x0F, 0x6F, "BootProgress"},
3098a23840SMatthew Barth     {0xe9, 0x09, "OccStatus"},  // E9 is an internal mapping to handle sensor type code os 0x09
3198a23840SMatthew Barth     {0xC3, 0x6F, "BootCount"},
3298a23840SMatthew Barth     {0x1F, 0x6F, "OperatingSystemStatus"},
3398a23840SMatthew Barth     {0x12, 0x6F, "SYSTEM_EVENT"},
3498a23840SMatthew Barth     {0xC7, 0x03, "SYSTEM"},
3598a23840SMatthew Barth     {0xC7, 0x03, "MAIN_PLANAR"},
3698a23840SMatthew Barth     {0xC2, 0x6F, "PowerCap"},
3798a23840SMatthew Barth     {0xFF, 0x00, ""},
3898a23840SMatthew Barth };
3998a23840SMatthew Barth 
4098a23840SMatthew Barth 
4198a23840SMatthew Barth struct sensor_data_t {
4298a23840SMatthew Barth     uint8_t sennum;
4398a23840SMatthew Barth }  __attribute__ ((packed)) ;
4498a23840SMatthew Barth 
4598a23840SMatthew Barth struct sensorreadingresp_t {
4698a23840SMatthew Barth     uint8_t value;
4798a23840SMatthew Barth     uint8_t operation;
4898a23840SMatthew Barth     uint8_t indication[2];
4998a23840SMatthew Barth }  __attribute__ ((packed)) ;
5098a23840SMatthew Barth 
5198a23840SMatthew Barth uint8_t dbus_to_sensor_type(char *p) {
5298a23840SMatthew Barth 
5398a23840SMatthew Barth     sensorTypemap_t *s = g_SensorTypeMap;
5498a23840SMatthew Barth     char r=0;
5598a23840SMatthew Barth 
5698a23840SMatthew Barth     while (s->number != 0xFF) {
5798a23840SMatthew Barth         if (!strcmp(s->dbusname,p)) {
5898a23840SMatthew Barth             r = s->number;
5998a23840SMatthew Barth              break;
6098a23840SMatthew Barth         }
6198a23840SMatthew Barth         s++;
6298a23840SMatthew Barth     }
6398a23840SMatthew Barth 
6498a23840SMatthew Barth 
6598a23840SMatthew Barth     if (s->number == 0xFF)
6698a23840SMatthew Barth         printf("Failed to find Sensor Type %s\n", p);
6798a23840SMatthew Barth 
6898a23840SMatthew Barth     return r;
6998a23840SMatthew Barth }
7098a23840SMatthew Barth 
7198a23840SMatthew Barth 
7298a23840SMatthew Barth uint8_t dbus_to_sensor_type_from_dbus(dbus_interface_t *a) {
7398a23840SMatthew Barth     char fru_type_name[64];
7498a23840SMatthew Barth     int r= 0;
7598a23840SMatthew Barth 
7698a23840SMatthew Barth     r = find_interface_property_fru_type(a, "fru_type", fru_type_name);
7798a23840SMatthew Barth     if (r<0) {
7898a23840SMatthew Barth         fprintf(stderr, "Failed to get a fru type: %s", strerror(-r));
7998a23840SMatthew Barth         return -1;
8098a23840SMatthew Barth     } else {
8198a23840SMatthew Barth         return dbus_to_sensor_type(fru_type_name);
8298a23840SMatthew Barth     }
8398a23840SMatthew Barth }
8498a23840SMatthew Barth 
8598a23840SMatthew Barth 
8698a23840SMatthew Barth uint8_t find_sensor(uint8_t sensor_number) {
8798a23840SMatthew Barth 
8898a23840SMatthew Barth     dbus_interface_t a;
8998a23840SMatthew Barth     char *p;
9098a23840SMatthew Barth     char r;
9198a23840SMatthew Barth 
9298a23840SMatthew Barth     r = find_openbmc_path("SENSOR", sensor_number, &a);
9398a23840SMatthew Barth 
9498a23840SMatthew Barth     if (r < 0) { return 0; }
9598a23840SMatthew Barth 
9698a23840SMatthew Barth     // This is where sensors that do not exist in dbus but do
9798a23840SMatthew Barth     // exist in the host code stop.  This should indicate it
9898a23840SMatthew Barth     // is not a supported sensor
9998a23840SMatthew Barth     if (a.interface[0] == 0) { return 0;}
10098a23840SMatthew Barth 
10198a23840SMatthew Barth     if (strstr(a.interface, "InventoryItem")) {
10298a23840SMatthew Barth         // InventoryItems are real frus.  So need to get the
10398a23840SMatthew Barth         // fru_type property
10498a23840SMatthew Barth         r = dbus_to_sensor_type_from_dbus(&a);
10598a23840SMatthew Barth     } else {
10698a23840SMatthew Barth         // Non InventoryItems
10798a23840SMatthew Barth         p = strrchr (a.path, '/');
10898a23840SMatthew Barth         r = dbus_to_sensor_type(p+1);
10998a23840SMatthew Barth     }
11098a23840SMatthew Barth 
11198a23840SMatthew Barth     return r;
11298a23840SMatthew Barth  }
11398a23840SMatthew Barth 
11498a23840SMatthew Barth 
11598a23840SMatthew Barth 
11698a23840SMatthew Barth 
11798a23840SMatthew Barth 
11898a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
11998a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
12098a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
12198a23840SMatthew Barth {
12298a23840SMatthew Barth     sensor_data_t *reqptr = (sensor_data_t*)request;
12398a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
12498a23840SMatthew Barth 
12598a23840SMatthew Barth     printf("IPMI GET_SENSOR_TYPE [0x%02X]\n",reqptr->sennum);
12698a23840SMatthew Barth 
12798a23840SMatthew Barth     // TODO Not sure what the System-event-sensor is suppose to return
12898a23840SMatthew Barth     // need to ask Hostboot team
12998a23840SMatthew Barth     unsigned char buf[] = {0x00,0x6F};
13098a23840SMatthew Barth 
13198a23840SMatthew Barth     buf[0] = find_sensor(reqptr->sennum);
13298a23840SMatthew Barth 
13398a23840SMatthew Barth     // HACK UNTIL Dbus gets updated or we find a better way
13498a23840SMatthew Barth     if (buf[0] == 0) {
13598a23840SMatthew Barth         rc = IPMI_CC_SENSOR_INVALID;
13698a23840SMatthew Barth     }
13798a23840SMatthew Barth 
13898a23840SMatthew Barth 
13998a23840SMatthew Barth     *data_len = sizeof(buf);
14098a23840SMatthew Barth     memcpy(response, &buf, *data_len);
14198a23840SMatthew Barth 
14298a23840SMatthew Barth     return rc;
14398a23840SMatthew Barth }
14498a23840SMatthew Barth 
14598a23840SMatthew Barth 
14698a23840SMatthew Barth 
14798a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
14898a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
14998a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
15098a23840SMatthew Barth {
15198a23840SMatthew Barth     sensor_data_t *reqptr = (sensor_data_t*)request;
15298a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
15398a23840SMatthew Barth 
15498a23840SMatthew Barth     printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum);
15598a23840SMatthew Barth 
15698a23840SMatthew Barth     updateSensorRecordFromSSRAESC(reqptr);
15798a23840SMatthew Barth 
15898a23840SMatthew Barth     *data_len=0;
15998a23840SMatthew Barth 
16098a23840SMatthew Barth     return rc;
16198a23840SMatthew Barth }
16298a23840SMatthew Barth 
16398a23840SMatthew Barth 
16498a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
16598a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
16698a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
16798a23840SMatthew Barth {
16898a23840SMatthew Barth     sensor_data_t *reqptr = (sensor_data_t*)request;
16998a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_SENSOR_INVALID;
17098a23840SMatthew Barth     uint8_t type;
17198a23840SMatthew Barth     sensorreadingresp_t *resp = (sensorreadingresp_t*) response;
17298a23840SMatthew Barth     int r;
17398a23840SMatthew Barth     dbus_interface_t a;
17498a23840SMatthew Barth     sd_bus *bus = ipmid_get_sd_bus_connection();
17598a23840SMatthew Barth     sd_bus_message *reply = NULL;
17698a23840SMatthew Barth     int reading = 0;
17798a23840SMatthew Barth 
17898a23840SMatthew Barth 
17998a23840SMatthew Barth     printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum);
18098a23840SMatthew Barth 
18198a23840SMatthew Barth     r = find_openbmc_path("SENSOR", reqptr->sennum, &a);
18298a23840SMatthew Barth 
18398a23840SMatthew Barth     if (r < 0) {
18498a23840SMatthew Barth         fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum);
18598a23840SMatthew Barth         return IPMI_CC_SENSOR_INVALID;
18698a23840SMatthew Barth     }
18798a23840SMatthew Barth 
18898a23840SMatthew Barth     type = find_sensor(reqptr->sennum);
18998a23840SMatthew Barth 
19098a23840SMatthew Barth     fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface);
19198a23840SMatthew Barth 
19298a23840SMatthew Barth     *data_len=0;
19398a23840SMatthew Barth 
19498a23840SMatthew Barth     switch(type) {
19598a23840SMatthew Barth         case 0xC3:
19698a23840SMatthew Barth         case 0xC2:
19798a23840SMatthew Barth             r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i");
19898a23840SMatthew Barth             if (r < 0) {
19998a23840SMatthew Barth                 fprintf(stderr, "Failed to call sd_bus_get_property:%d,  %s\n", r, strerror(-r));
20098a23840SMatthew Barth                 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
20198a23840SMatthew Barth                         a.bus, a.path, a.interface);
20298a23840SMatthew Barth                 break;
20398a23840SMatthew Barth             }
20498a23840SMatthew Barth 
20598a23840SMatthew Barth             r = sd_bus_message_read(reply, "i", &reading);
20698a23840SMatthew Barth             if (r < 0) {
20798a23840SMatthew Barth                 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
20898a23840SMatthew Barth                 break;
20998a23840SMatthew Barth             }
21098a23840SMatthew Barth 
21198a23840SMatthew Barth             printf("Contents of a 0x%02x is 0x%02x\n", type, reading);
21298a23840SMatthew Barth 
21398a23840SMatthew Barth             rc = IPMI_CC_OK;
21498a23840SMatthew Barth             *data_len=sizeof(sensorreadingresp_t);
21598a23840SMatthew Barth 
21698a23840SMatthew Barth             resp->value         = (uint8_t)reading;
21798a23840SMatthew Barth             resp->operation     = 0;
21898a23840SMatthew Barth             resp->indication[0] = 0;
21998a23840SMatthew Barth             resp->indication[1] = 0;
22098a23840SMatthew Barth             break;
22198a23840SMatthew Barth 
22298a23840SMatthew Barth         default:
22398a23840SMatthew Barth             *data_len=0;
22498a23840SMatthew Barth             rc = IPMI_CC_SENSOR_INVALID;
22598a23840SMatthew Barth             break;
22698a23840SMatthew Barth     }
22798a23840SMatthew Barth 
22898a23840SMatthew Barth 
22998a23840SMatthew Barth     reply = sd_bus_message_unref(reply);
23098a23840SMatthew Barth 
23198a23840SMatthew Barth     return rc;
23298a23840SMatthew Barth }
23398a23840SMatthew Barth 
23498a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
23598a23840SMatthew Barth                              ipmi_request_t request, ipmi_response_t response,
23698a23840SMatthew Barth                              ipmi_data_len_t data_len, ipmi_context_t context)
23798a23840SMatthew Barth {
23898a23840SMatthew Barth     ipmi_ret_t rc = IPMI_CC_OK;
23998a23840SMatthew Barth 
24098a23840SMatthew Barth     printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd);
24198a23840SMatthew Barth     *data_len = 0;
24298a23840SMatthew Barth 
24398a23840SMatthew Barth     return rc;
24498a23840SMatthew Barth }
24598a23840SMatthew Barth 
24698a23840SMatthew Barth 
24798a23840SMatthew Barth void register_netfn_sen_functions()
24898a23840SMatthew Barth {
24998a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_WILDCARD);
25098a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, NULL, ipmi_sen_wildcard);
25198a23840SMatthew Barth 
25298a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE);
25398a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, NULL, ipmi_sen_get_sensor_type);
25498a23840SMatthew Barth 
25598a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_SET_SENSOR);
25698a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, NULL, ipmi_sen_set_sensor);
25798a23840SMatthew Barth 
25898a23840SMatthew Barth     printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING);
25998a23840SMatthew Barth     ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, NULL, ipmi_sen_get_sensor_reading);
26098a23840SMatthew Barth 
26198a23840SMatthew Barth     return;
26298a23840SMatthew Barth }
263