#include "systemintfcmds.h" #include "host-ipmid/ipmid-api.h" #include "config.h" #include #include void register_netfn_app_functions() __attribute__((constructor)); //------------------------------------------------------------------- // Called by Host post response from Get_Message_Flags //------------------------------------------------------------------- ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; printf("IPMI APP READ EVENT command received\n"); // TODO : For now, this is catering only to the Soft Power Off via OEM SEL // mechanism. If we need to make this generically used for some // other conditions, then we can take advantage of context pointer. constexpr auto iface = "org.freedesktop.DBus.Properties"; constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal." "SoftPowerOff"; constexpr auto property = "ResponseReceived"; constexpr auto value = "xyz.openbmc_project.Ipmi.Internal." "SoftPowerOff.HostResponse.SoftOffReceived"; char *busname = nullptr; struct oem_sel_timestamped soft_off = {0}; *data_len = sizeof(struct oem_sel_timestamped); // Get the system bus where most system services are provided. auto bus = ipmid_get_sd_bus_connection(); // Nudge the SoftPowerOff application that it needs to stop the // initial watchdog timer. If we have some errors talking to Soft Off // object, get going and do our regular job mapper_get_service(bus, SOFTOFF_OBJPATH, &busname); if (busname) { // No error object or reply expected. auto r = sd_bus_call_method(bus, busname, SOFTOFF_OBJPATH, iface, "Set", nullptr, nullptr, "ssv", soft_off_iface, property, "s", value); if (r < 0) { fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n", strerror(-r)); } free (busname); } else { printf("Soft Power Off object is not available. Ignoring watchdog refresh"); } // either id[0] -or- id[1] can be filled in. We will use id[0] soft_off.id[0] = SEL_OEM_ID_0; soft_off.id[1] = SEL_OEM_ID_0; soft_off.type = SEL_RECORD_TYPE_OEM; // Following 3 bytes are from IANA Manufactre_Id field. See below soft_off.manuf_id[0]= 0x41; soft_off.manuf_id[1]= 0xA7; soft_off.manuf_id[2]= 0x00; // per IPMI spec NetFuntion for OEM soft_off.netfun = 0x3A; // Mechanism to kick start soft shutdown. soft_off.cmd = CMD_POWER; soft_off.data[0] = SOFT_OFF; // All '0xFF' since unused. memset(&soft_off.data[1], 0xFF, 3); // Pack the actual response memcpy(response, &soft_off, *data_len); return rc; } //--------------------------------------------------------------------- // Called by Host on seeing a SMS_ATN bit set. Return a hardcoded // value of 0x2 indicating we need Host read some data. //------------------------------------------------------------------- ipmi_ret_t ipmi_app_get_msg_flags(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) { // Generic return from IPMI commands. ipmi_ret_t rc = IPMI_CC_OK; printf("IPMI APP GET MSG FLAGS returning with [bit:2] set\n"); // From IPMI spec V2.0 for Get Message Flags Command : // bit:[1] from LSB : 1b = Event Message Buffer Full. // Return as 0 if Event Message Buffer is not supported, // or when the Event Message buffer is disabled. // TODO. For now. assume its not disabled and send "0x2" anyway: uint8_t set_event_msg_buffer_full = 0x2; *data_len = sizeof(set_event_msg_buffer_full); // Pack the actual response memcpy(response, &set_event_msg_buffer_full, *data_len); return rc; } ipmi_ret_t ipmi_app_set_bmc_global_enables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; *data_len = 0; // Event and message logging enabled by default so return for now printf("IPMI APP SET BMC GLOBAL ENABLES Ignoring for now\n"); return rc; } void register_netfn_app_functions() { // printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_READ_EVENT); ipmi_register_callback(NETFUN_APP, IPMI_CMD_READ_EVENT, NULL, ipmi_app_read_event, SYSTEM_INTERFACE); // printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_BMC_GLOBAL_ENABLES); ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_BMC_GLOBAL_ENABLES, NULL, ipmi_app_set_bmc_global_enables, SYSTEM_INTERFACE); // printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS); ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS, NULL, ipmi_app_get_msg_flags, SYSTEM_INTERFACE); return; }