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