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