| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 1 | #include "systemintfcmds.h" | 
|  | 2 | #include "host-ipmid/ipmid-api.h" | 
|  | 3 |  | 
|  | 4 | #include <stdio.h> | 
| Vishwanatha Subbanna | 83b5c1c | 2017-01-25 18:41:51 +0530 | [diff] [blame] | 5 | #include <mapper.h> | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 6 |  | 
|  | 7 | void register_netfn_app_functions() __attribute__((constructor)); | 
|  | 8 |  | 
|  | 9 | //------------------------------------------------------------------- | 
|  | 10 | // Called by Host post response from Get_Message_Flags | 
|  | 11 | //------------------------------------------------------------------- | 
|  | 12 | ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 13 | ipmi_request_t request, ipmi_response_t response, | 
|  | 14 | ipmi_data_len_t data_len, ipmi_context_t context) | 
|  | 15 | { | 
|  | 16 | ipmi_ret_t rc = IPMI_CC_OK; | 
| Vishwanatha Subbanna | 83b5c1c | 2017-01-25 18:41:51 +0530 | [diff] [blame] | 17 |  | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 18 | printf("IPMI APP READ EVENT command received\n"); | 
|  | 19 |  | 
|  | 20 | // TODO : For now, this is catering only to the Soft Power Off via OEM SEL | 
|  | 21 | //        mechanism. If we need to make this generically used for some | 
|  | 22 | //        other conditions, then we can take advantage of context pointer. | 
|  | 23 |  | 
| Vishwanatha Subbanna | 83b5c1c | 2017-01-25 18:41:51 +0530 | [diff] [blame] | 24 | constexpr auto objname        = "/xyz/openbmc_project/ipmi/internal/" | 
|  | 25 | "softpoweroff"; | 
|  | 26 | constexpr auto iface          = "org.freedesktop.DBus.Properties"; | 
|  | 27 | constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal." | 
|  | 28 | "SoftPowerOff"; | 
|  | 29 |  | 
|  | 30 | constexpr auto property       = "ResponseReceived"; | 
|  | 31 | constexpr auto value          = "xyz.openbmc_project.Ipmi.Internal." | 
|  | 32 | "SoftPowerOff.HostResponse.SoftOffReceived"; | 
|  | 33 | char *busname = nullptr; | 
|  | 34 |  | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 35 | struct oem_sel_timestamped soft_off = {0}; | 
|  | 36 | *data_len = sizeof(struct oem_sel_timestamped); | 
|  | 37 |  | 
| Vishwanatha Subbanna | 83b5c1c | 2017-01-25 18:41:51 +0530 | [diff] [blame] | 38 | // Get the system bus where most system services are provided. | 
|  | 39 | auto bus = ipmid_get_sd_bus_connection(); | 
|  | 40 |  | 
|  | 41 | // Nudge the SoftPowerOff application that it needs to stop the | 
|  | 42 | // initial watchdog timer. If we have some errors talking to Soft Off | 
|  | 43 | // object, get going and do our regular job | 
|  | 44 | mapper_get_service(bus, objname, &busname); | 
|  | 45 | if (busname) | 
|  | 46 | { | 
|  | 47 | // No error object or reply expected. | 
|  | 48 | auto r = sd_bus_call_method(bus, busname, objname, iface, | 
|  | 49 | "Set", nullptr, nullptr, "ssv", | 
|  | 50 | soft_off_iface, property, "s", value); | 
|  | 51 | if (r < 0) | 
|  | 52 | { | 
|  | 53 | fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n", | 
|  | 54 | strerror(-r)); | 
|  | 55 | } | 
|  | 56 | free (busname); | 
|  | 57 | } | 
|  | 58 | else | 
|  | 59 | { | 
|  | 60 | printf("Soft Power Off object is not available. Ignoring watchdog refresh"); | 
|  | 61 | } | 
|  | 62 |  | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 63 | // either id[0] -or- id[1] can be filled in. We will use id[0] | 
|  | 64 | soft_off.id[0]   = SEL_OEM_ID_0; | 
|  | 65 | soft_off.id[1]   = SEL_OEM_ID_0; | 
|  | 66 | soft_off.type    = SEL_RECORD_TYPE_OEM; | 
|  | 67 |  | 
|  | 68 | // Following 3 bytes are from IANA Manufactre_Id field. See below | 
|  | 69 | soft_off.manuf_id[0]= 0x41; | 
|  | 70 | soft_off.manuf_id[1]= 0xA7; | 
|  | 71 | soft_off.manuf_id[2]= 0x00; | 
|  | 72 |  | 
|  | 73 | // per IPMI spec NetFuntion for OEM | 
|  | 74 | soft_off.netfun  = 0x3A; | 
|  | 75 |  | 
|  | 76 | // Mechanism to kick start soft shutdown. | 
|  | 77 | soft_off.cmd     = CMD_POWER; | 
|  | 78 | soft_off.data[0] = SOFT_OFF; | 
|  | 79 |  | 
|  | 80 | // All '0xFF' since unused. | 
|  | 81 | memset(&soft_off.data[1], 0xFF, 3); | 
|  | 82 |  | 
|  | 83 | // Pack the actual response | 
|  | 84 | memcpy(response, &soft_off, *data_len); | 
|  | 85 | return rc; | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | //--------------------------------------------------------------------- | 
|  | 89 | // Called by Host on seeing a SMS_ATN bit set. Return a hardcoded | 
|  | 90 | // value of 0x2 indicating we need Host read some data. | 
|  | 91 | //------------------------------------------------------------------- | 
|  | 92 | ipmi_ret_t ipmi_app_get_msg_flags(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 93 | ipmi_request_t request, ipmi_response_t response, | 
|  | 94 | ipmi_data_len_t data_len, ipmi_context_t context) | 
|  | 95 | { | 
|  | 96 | // Generic return from IPMI commands. | 
|  | 97 | ipmi_ret_t rc = IPMI_CC_OK; | 
|  | 98 |  | 
|  | 99 | printf("IPMI APP GET MSG FLAGS returning with [bit:2] set\n"); | 
|  | 100 |  | 
|  | 101 | // From IPMI spec V2.0 for Get Message Flags Command : | 
|  | 102 | // bit:[1] from LSB : 1b = Event Message Buffer Full. | 
|  | 103 | // Return as 0 if Event Message Buffer is not supported, | 
|  | 104 | // or when the Event Message buffer is disabled. | 
|  | 105 | // TODO. For now. assume its not disabled and send "0x2" anyway: | 
|  | 106 |  | 
|  | 107 | uint8_t set_event_msg_buffer_full = 0x2; | 
|  | 108 | *data_len = sizeof(set_event_msg_buffer_full); | 
|  | 109 |  | 
|  | 110 | // Pack the actual response | 
|  | 111 | memcpy(response, &set_event_msg_buffer_full, *data_len); | 
|  | 112 |  | 
|  | 113 | return rc; | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | ipmi_ret_t ipmi_app_set_bmc_global_enables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 117 | ipmi_request_t request, ipmi_response_t response, | 
|  | 118 | ipmi_data_len_t data_len, ipmi_context_t context) | 
|  | 119 | { | 
|  | 120 | ipmi_ret_t rc = IPMI_CC_OK; | 
|  | 121 | *data_len = 0; | 
|  | 122 |  | 
|  | 123 | // Event and message logging enabled by default so return for now | 
|  | 124 | printf("IPMI APP SET BMC GLOBAL ENABLES Ignoring for now\n"); | 
|  | 125 |  | 
|  | 126 | return rc; | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | void register_netfn_app_functions() | 
|  | 130 | { | 
|  | 131 |  | 
|  | 132 | // <Read Event Message Buffer> | 
|  | 133 | printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_READ_EVENT); | 
| Tom | 0573237 | 2016-09-06 17:21:23 +0530 | [diff] [blame] | 134 | ipmi_register_callback(NETFUN_APP, IPMI_CMD_READ_EVENT, NULL, ipmi_app_read_event, | 
|  | 135 | SYSTEM_INTERFACE); | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 136 |  | 
|  | 137 | // <Set BMC Global Enables> | 
|  | 138 | printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, | 
|  | 139 | IPMI_CMD_SET_BMC_GLOBAL_ENABLES); | 
|  | 140 | ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_BMC_GLOBAL_ENABLES, NULL, | 
| Tom | 0573237 | 2016-09-06 17:21:23 +0530 | [diff] [blame] | 141 | ipmi_app_set_bmc_global_enables, SYSTEM_INTERFACE); | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 142 |  | 
|  | 143 | // <Get Message Flags> | 
|  | 144 | printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS); | 
| Tom | 0573237 | 2016-09-06 17:21:23 +0530 | [diff] [blame] | 145 | ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS, NULL, ipmi_app_get_msg_flags, | 
|  | 146 | SYSTEM_INTERFACE); | 
| Tom | 9e5232e | 2016-11-07 12:14:51 +0530 | [diff] [blame] | 147 |  | 
|  | 148 | return; | 
|  | 149 | } |