blob: 748c1a395c94280af8602991d511ead00f19249e [file] [log] [blame]
Patrick Venturec9508db2018-10-16 17:18:43 -07001#include "writefrudata.hpp"
2
William A. Kennington III8ab57842019-02-12 12:49:51 -08003#include <ipmid/api.h>
vishwa13555bd2015-11-10 12:10:38 -06004#include <unistd.h>
vishwa13555bd2015-11-10 12:10:38 -06005
George Liu1c629542025-04-03 10:23:47 +08006#include <ipmid/api-types.hpp>
George Liu98de42a2025-07-30 09:54:21 +08007#include <phosphor-logging/lg2.hpp>
Patrick Venturea8093a22018-10-21 09:07:11 -07008#include <sdbusplus/bus.hpp>
Patrick Venture6cd51352018-10-17 13:26:06 -07009
Patrick Williamscfa96af2023-05-10 07:50:26 -050010#include <cstdio>
11#include <cstring>
12
George Liueed09532025-07-30 10:28:03 +080013void registerNetFnStorageWriteFru() __attribute__((constructor));
vishwa13555bd2015-11-10 12:10:38 -060014
15sd_bus* ipmid_get_sd_bus_connection(void);
16
17///-------------------------------------------------------
18// Called by IPMI netfn router for write fru data command
19//--------------------------------------------------------
Patrick Williamsdedaef52025-02-01 08:22:00 -050020ipmi_ret_t ipmiStorageWriteFruData(
21 ipmi_netfn_t /*netfn*/, ipmi_cmd_t /*cmd*/, ipmi_request_t request,
22 ipmi_response_t response, ipmi_data_len_t dataLen,
23 ipmi_context_t /*context*/)
vishwa13555bd2015-11-10 12:10:38 -060024{
Jayanth Othayoth883aa422024-12-18 10:33:06 -060025 FILE* fp = nullptr;
Patrick Ventureb25fb9f2018-10-21 12:35:03 -070026 char fruFilename[16] = {0};
Jean-Marie Verdun6d3b8052021-10-01 13:37:40 -070027 size_t offset = 0;
28 size_t len = 0;
George Liu1a843d02025-07-02 15:21:51 +080029 ipmi_ret_t rc = ipmi::ccInvalidCommand;
Jayanth Othayoth883aa422024-12-18 10:33:06 -060030 const char* mode = nullptr;
vishwa13555bd2015-11-10 12:10:38 -060031
32 // From the payload, extract the header that has fruid and the offsets
Patrick Ventureb65eef62018-10-17 13:18:55 -070033 auto reqptr = static_cast<write_fru_data_t*>(request);
vishwa13555bd2015-11-10 12:10:38 -060034
35 // Maintaining a temporary file to pump the data
Patrick Ventureb25fb9f2018-10-21 12:35:03 -070036 std::sprintf(fruFilename, "%s%02x", "/tmp/ipmifru", reqptr->frunum);
vishwa13555bd2015-11-10 12:10:38 -060037
Jean-Marie Verdun6d3b8052021-10-01 13:37:40 -070038 offset = ((size_t)reqptr->offsetms) << 8 | reqptr->offsetls;
vishwa13555bd2015-11-10 12:10:38 -060039
40 // Length is the number of request bytes minus the header itself.
41 // The header contains an extra byte to indicate the start of
42 // the data (so didn't need to worry about word/byte boundaries)
43 // hence the -1...
Jean-Marie Verdun6d3b8052021-10-01 13:37:40 -070044 len = ((size_t)*dataLen) - (sizeof(write_fru_data_t) - 1);
vishwa13555bd2015-11-10 12:10:38 -060045
46 // On error there is no response data for this command.
Patrick Ventureb25fb9f2018-10-21 12:35:03 -070047 *dataLen = 0;
vishwac93d6d42015-12-16 11:55:16 -060048
George Liu98de42a2025-07-30 09:54:21 +080049 lg2::debug(
50 "IPMI WRITE-FRU-DATA, file name: {FILE}, offset: {OFFSET}, length: {LENGTH}",
51 "FILE", fruFilename, "OFFSET", offset, "LENGTH", len);
vishwa13555bd2015-11-10 12:10:38 -060052
Patrick Ventureb25fb9f2018-10-21 12:35:03 -070053 if (access(fruFilename, F_OK) == -1)
Patrick Venturec9508db2018-10-16 17:18:43 -070054 {
vishwa13555bd2015-11-10 12:10:38 -060055 mode = "wb";
Patrick Venturec9508db2018-10-16 17:18:43 -070056 }
57 else
58 {
vishwa13555bd2015-11-10 12:10:38 -060059 mode = "rb+";
60 }
61
Jayanth Othayoth883aa422024-12-18 10:33:06 -060062 if ((fp = std::fopen(fruFilename, mode)) != nullptr)
vishwa13555bd2015-11-10 12:10:38 -060063 {
Patrick Venture6cd51352018-10-17 13:26:06 -070064 if (std::fseek(fp, offset, SEEK_SET))
vishwa13555bd2015-11-10 12:10:38 -060065 {
George Liu98de42a2025-07-30 09:54:21 +080066 lg2::error(
67 "Seek into fru file failed, file name: {FILE}, errno: {ERRNO}",
68 "FILE", fruFilename, "ERRNO", errno);
Patrick Venture6cd51352018-10-17 13:26:06 -070069 std::fclose(fp);
vishwa13555bd2015-11-10 12:10:38 -060070 return rc;
71 }
vishwac93d6d42015-12-16 11:55:16 -060072
Patrick Venture6cd51352018-10-17 13:26:06 -070073 if (std::fwrite(&reqptr->data, len, 1, fp) != 1)
vishwa13555bd2015-11-10 12:10:38 -060074 {
George Liu98de42a2025-07-30 09:54:21 +080075 lg2::error(
76 "Write into fru file failed, file name: {FILE}, errno: {ERRNO}",
77 "FILE", fruFilename, "ERRNO", errno);
Patrick Venture6cd51352018-10-17 13:26:06 -070078 std::fclose(fp);
vishwa13555bd2015-11-10 12:10:38 -060079 return rc;
80 }
vishwac93d6d42015-12-16 11:55:16 -060081
Patrick Venture6cd51352018-10-17 13:26:06 -070082 std::fclose(fp);
vishwac93d6d42015-12-16 11:55:16 -060083 }
84 else
vishwa13555bd2015-11-10 12:10:38 -060085 {
George Liu98de42a2025-07-30 09:54:21 +080086 lg2::error("Error trying to write to {FILE}", "FILE", fruFilename);
vishwa13555bd2015-11-10 12:10:38 -060087 return rc;
88 }
89
Manojkiran Edabc5725d2024-06-17 11:50:54 +053090 // If we got here then set the response byte
vishwa13555bd2015-11-10 12:10:38 -060091 // to the number of bytes written
Patrick Venture6cd51352018-10-17 13:26:06 -070092 std::memcpy(response, &len, 1);
Patrick Ventureb25fb9f2018-10-21 12:35:03 -070093 *dataLen = 1;
George Liu1a843d02025-07-02 15:21:51 +080094 rc = ipmi::ccSuccess;
vishwa13555bd2015-11-10 12:10:38 -060095
vishwac93d6d42015-12-16 11:55:16 -060096 // Get the reference to global sd_bus object
Patrick Venturec9508db2018-10-16 17:18:43 -070097 sd_bus* bus_type = ipmid_get_sd_bus_connection();
vishwaf3ca3522015-12-02 10:35:13 -060098
vishwa13555bd2015-11-10 12:10:38 -060099 // We received some bytes. It may be full or partial. Send a valid
100 // FRU file to the inventory controller on DBus for the correct number
Patrick Williams5e8829e2022-07-22 19:26:53 -0500101 sdbusplus::bus_t bus{bus_type};
Jayanth Othayoth70cb0672025-06-07 02:13:23 -0500102 validateFRUArea(reqptr->frunum, fruFilename, bus);
vishwa13555bd2015-11-10 12:10:38 -0600103
104 return rc;
105}
106
107//-------------------------------------------------------
108// Registering WRITE FRU DATA command handler with daemon
109//-------------------------------------------------------
George Liueed09532025-07-30 10:28:03 +0800110void registerNetFnStorageWriteFru()
vishwa13555bd2015-11-10 12:10:38 -0600111{
George Liu98de42a2025-07-30 09:54:21 +0800112 lg2::info(
113 "Registering WRITE FRU DATA command handler, netfn:{NETFN}, cmd:{CMD}",
114 "NETFN", lg2::hex, ipmi::netFnStorage, "CMD", lg2::hex,
115 ipmi::storage::cmdWriteFruData);
Patrick Venture6cd51352018-10-17 13:26:06 -0700116
George Liu1a843d02025-07-02 15:21:51 +0800117 ipmi_register_callback(ipmi::netFnStorage, ipmi::storage::cmdWriteFruData,
118 nullptr, ipmiStorageWriteFruData, SYSTEM_INTERFACE);
vishwa13555bd2015-11-10 12:10:38 -0600119}