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