#include #include #include #include #include "writefrudata.hpp" void register_netfn_storage_write_fru() __attribute__((constructor)); sd_bus* ipmid_get_sd_bus_connection(void); ///------------------------------------------------------- // Called by IPMI netfn router for write fru data command //-------------------------------------------------------- ipmi_ret_t ipmi_storage_write_fru_data(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) { FILE *fp = NULL; char fru_file_name[16] = {0}; uint8_t offset = 0; uint16_t len = 0; ipmi_ret_t rc = IPMI_CC_INVALID; const char *mode = NULL; // From the payload, extract the header that has fruid and the offsets write_fru_data_t *reqptr = (write_fru_data_t*)request; // Maintaining a temporary file to pump the data sprintf(fru_file_name, "%s%02x", "/tmp/ipmifru", reqptr->frunum); offset = ((uint16_t)reqptr->offsetms) << 8 | reqptr->offsetls; // Length is the number of request bytes minus the header itself. // The header contains an extra byte to indicate the start of // the data (so didn't need to worry about word/byte boundaries) // hence the -1... len = ((uint16_t)*data_len) - (sizeof(write_fru_data_t)-1); // On error there is no response data for this command. *data_len = 0; #ifdef __IPMI__DEBUG__ printf("IPMI WRITE-FRU-DATA for [%s] Offset = [%d] Length = [%d]\n", fru_file_name, offset, len); #endif if( access( fru_file_name, F_OK ) == -1 ) { mode = "wb"; } else { mode = "rb+"; } if ((fp = fopen(fru_file_name, mode)) != NULL) { if(fseek(fp, offset, SEEK_SET)) { perror("Error:"); fclose(fp); return rc; } if(fwrite(&reqptr->data, len, 1, fp) != 1) { perror("Error:"); fclose(fp); return rc; } fclose(fp); } else { fprintf(stderr, "Error trying to write to fru file %s\n",fru_file_name); return rc; } // If we got here then set the resonse byte // to the number of bytes written memcpy(response, &len, 1); *data_len = 1; rc = IPMI_CC_OK; // Get the reference to global sd_bus object sd_bus *bus_type = ipmid_get_sd_bus_connection(); // We received some bytes. It may be full or partial. Send a valid // FRU file to the inventory controller on DBus for the correct number bool bmc_fru = false; ipmi_validate_fru_area(reqptr->frunum, fru_file_name, bus_type, bmc_fru); return rc; } //------------------------------------------------------- // Registering WRITE FRU DATA command handler with daemon //------------------------------------------------------- void register_netfn_storage_write_fru() { printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_STORAGE, IPMI_CMD_WRITE_FRU_DATA); ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_WRITE_FRU_DATA, NULL, ipmi_storage_write_fru_data, SYSTEM_INTERFACE); }