1 #include "file_io_type_vpd.hpp" 2 3 #include "common/utils.hpp" 4 5 #include <libpldm/base.h> 6 #include <libpldm/oem/ibm/file_io.h> 7 #include <stdint.h> 8 9 #include <phosphor-logging/lg2.hpp> 10 11 PHOSPHOR_LOG2_USING; 12 13 typedef uint8_t byte; 14 15 namespace pldm 16 { 17 namespace responder 18 { 19 int keywordHandler::read(uint32_t offset, uint32_t& length, Response& response, 20 oem_platform::Handler* /*oemPlatformHandler*/) 21 { 22 const char* keywrdObjPath = 23 "/xyz/openbmc_project/inventory/system/chassis/motherboard"; 24 const char* keywrdPropName = "PD_D"; 25 const char* keywrdInterface = "com.ibm.ipzvpd.PSPD"; 26 27 std::variant<std::vector<byte>> keywrd; 28 29 try 30 { 31 auto& bus = pldm::utils::DBusHandler::getBus(); 32 auto service = pldm::utils::DBusHandler().getService(keywrdObjPath, 33 keywrdInterface); 34 auto method = bus.new_method_call(service.c_str(), keywrdObjPath, 35 "org.freedesktop.DBus.Properties", 36 "Get"); 37 method.append(keywrdInterface, keywrdPropName); 38 auto reply = bus.call(method, dbusTimeout); 39 reply.read(keywrd); 40 } 41 catch (const std::exception& e) 42 { 43 error( 44 "Get keyword error from dbus interface {INTERFACE}, error - {ERROR}", 45 "INTERFACE", keywrdInterface, "ERROR", e); 46 } 47 48 uint32_t keywrdSize = std::get<std::vector<byte>>(keywrd).size(); 49 if (length < keywrdSize) 50 { 51 error("Length '{LENGTH}' requested is less than keyword size '{SIZE}'", 52 "LENGTH", length, "SIZE", keywrdSize); 53 return PLDM_ERROR_INVALID_DATA; 54 } 55 56 namespace fs = std::filesystem; 57 constexpr auto keywrdDirPath = "/tmp/pldm/"; 58 constexpr auto keywrdFilePath = "/tmp/pldm/vpdKeywrd.bin"; 59 60 if (!fs::exists(keywrdDirPath)) 61 { 62 fs::create_directories(keywrdDirPath); 63 fs::permissions(keywrdDirPath, 64 fs::perms::others_read | fs::perms::owner_write); 65 } 66 67 std::ofstream keywrdFile(keywrdFilePath); 68 auto fd = open(keywrdFilePath, std::ios::out | std::ofstream::binary); 69 if (!keywrdFile) 70 { 71 error( 72 "Failed to open VPD keyword file '{PATH}', error number - {ERROR_NUM}", 73 "PATH", keywrdFilePath, "ERROR_NUM", errno); 74 pldm::utils::reportError( 75 "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileOpenError"); 76 return PLDM_ERROR; 77 } 78 79 if (offset > keywrdSize) 80 { 81 error("Offset '{OFFSET}' exceeds file size '{SIZE}'", "OFFSET", offset, 82 "SIZE", keywrdSize); 83 return PLDM_DATA_OUT_OF_RANGE; 84 } 85 86 // length of keyword data should be same as keyword data size in dbus 87 // object 88 length = static_cast<uint32_t>(keywrdSize) - offset; 89 90 auto returnCode = lseek(fd, offset, SEEK_SET); 91 if (returnCode == -1) 92 { 93 error( 94 "Could not find keyword data of length '{LENGTH}' at given offset '{OFFSET}'. File Seek failed with response code '{RC}'", 95 "LENGTH", length, "OFFSET", offset, "RC", returnCode); 96 return PLDM_ERROR; 97 } 98 99 keywrdFile.write((const char*)std::get<std::vector<byte>>(keywrd).data(), 100 keywrdSize); 101 if (keywrdFile.bad()) 102 { 103 error("Error while writing to file '{PATH}'", "PATH", keywrdFilePath); 104 } 105 keywrdFile.close(); 106 107 auto rc = readFile(keywrdFilePath, offset, keywrdSize, response); 108 fs::remove(keywrdFilePath); 109 if (rc) 110 { 111 error("Read error for keyword file with size '{SIZE}'", "SIZE", 112 keywrdSize); 113 pldm::utils::reportError( 114 "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileReadError"); 115 return PLDM_ERROR; 116 } 117 return PLDM_SUCCESS; 118 } 119 } // namespace responder 120 } // namespace pldm 121