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 {
read(uint32_t offset,uint32_t & length,Response & response,oem_platform::Handler *)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