1 #include "file_io_type_pcie.hpp" 2 3 #include "libpldm/base.h" 4 #include "libpldm/file_io.h" 5 6 #include <stdint.h> 7 8 #include <phosphor-logging/lg2.hpp> 9 10 PHOSPHOR_LOG2_USING; 11 12 namespace pldm 13 { 14 namespace responder 15 { 16 17 static constexpr auto pciePath = "/var/lib/pldm/pcie-topology/"; 18 constexpr auto topologyFile = "topology"; 19 constexpr auto cableInfoFile = "cableinfo"; 20 21 namespace fs = std::filesystem; 22 std::unordered_map<uint16_t, bool> PCIeInfoHandler::receivedFiles; 23 24 PCIeInfoHandler::PCIeInfoHandler(uint32_t fileHandle, uint16_t fileType) : 25 FileHandler(fileHandle), infoType(fileType) 26 { 27 receivedFiles.emplace(infoType, false); 28 } 29 30 int PCIeInfoHandler::writeFromMemory( 31 uint32_t offset, uint32_t length, uint64_t address, 32 oem_platform::Handler* /*oemPlatformHandler*/) 33 { 34 if (!fs::exists(pciePath)) 35 { 36 fs::create_directories(pciePath); 37 fs::permissions(pciePath, 38 fs::perms::others_read | fs::perms::owner_write); 39 } 40 41 fs::path infoFile(fs::path(pciePath) / topologyFile); 42 if (infoType == PLDM_FILE_TYPE_CABLE_INFO) 43 { 44 infoFile = (fs::path(pciePath) / cableInfoFile); 45 } 46 47 try 48 { 49 std::ofstream pcieData(infoFile, std::ios::out | std::ios::binary); 50 auto rc = transferFileData(infoFile, false, offset, length, address); 51 if (rc != PLDM_SUCCESS) 52 { 53 error("TransferFileData failed in PCIeTopology with error {ERROR}", 54 "ERROR", rc); 55 return rc; 56 } 57 return PLDM_SUCCESS; 58 } 59 catch (const std::exception& e) 60 { 61 error("Create/Write data to the File type {TYPE}, failed {ERROR}", 62 "TYPE", infoType, "ERROR", e); 63 return PLDM_ERROR; 64 } 65 } 66 67 int PCIeInfoHandler::write(const char* buffer, uint32_t, uint32_t& length, 68 oem_platform::Handler* /*oemPlatformHandler*/) 69 { 70 fs::path infoFile(fs::path(pciePath) / topologyFile); 71 if (infoType == PLDM_FILE_TYPE_CABLE_INFO) 72 { 73 infoFile = (fs::path(pciePath) / cableInfoFile); 74 } 75 76 try 77 { 78 std::ofstream pcieData(infoFile, std::ios::out | std::ios::binary | 79 std::ios::app); 80 81 if (!buffer) 82 { 83 pcieData.write(buffer, length); 84 } 85 pcieData.close(); 86 } 87 catch (const std::exception& e) 88 { 89 error("Create/Write data to the File type {TYPE}, failed {ERROR}", 90 "TYPE", infoType, "ERROR", e); 91 return PLDM_ERROR; 92 } 93 94 return PLDM_SUCCESS; 95 } 96 97 int PCIeInfoHandler::fileAck(uint8_t /*fileStatus*/) 98 { 99 receivedFiles[infoType] = true; 100 try 101 { 102 if (receivedFiles.at(PLDM_FILE_TYPE_CABLE_INFO) && 103 receivedFiles.at(PLDM_FILE_TYPE_PCIE_TOPOLOGY)) 104 { 105 receivedFiles.clear(); 106 } 107 } 108 catch (const std::out_of_range& e) 109 { 110 info("Received only one of the topology file"); 111 } 112 return PLDM_SUCCESS; 113 } 114 115 } // namespace responder 116 } // namespace pldm 117