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 :{KEYWORD_INTF} ERROR={ERR_EXCEP}",
45             "KEYWORD_INTF", keywrdInterface, "ERR_EXCEP", e.what());
46     }
47 
48     uint32_t keywrdSize = std::get<std::vector<byte>>(keywrd).size();
49     if (length < keywrdSize)
50     {
51         error(
52             "length requested is less the keyword size, length:{LEN} keyword size:{KEYWORD_SIZE}",
53             "LEN", length, "KEYWORD_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("VPD keyword file open error: {KEYWORD_FILE_PATH} errno: {ERR}",
73               "KEYWORD_FILE_PATH", keywrdFilePath, "ERR", 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 exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}",
82               "OFFSET", offset, "FILE_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("Could not find keyword data at given offset. File Seek failed");
94         return PLDM_ERROR;
95     }
96 
97     keywrdFile.write((const char*)std::get<std::vector<byte>>(keywrd).data(),
98                      keywrdSize);
99     if (keywrdFile.bad())
100     {
101         error("Error while writing to file: {KEYWORD_FILE_PATH}",
102               "KEYWORD_FILE_PATH", keywrdFilePath);
103     }
104     keywrdFile.close();
105 
106     auto rc = readFile(keywrdFilePath, offset, keywrdSize, response);
107     fs::remove(keywrdFilePath);
108     if (rc)
109     {
110         error("Read error for keyword file with size: {KEYWORD_SIZE}",
111               "KEYWORD_SIZE", keywrdSize);
112         pldm::utils::reportError(
113             "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileReadError");
114         return PLDM_ERROR;
115     }
116     return PLDM_SUCCESS;
117 }
118 } // namespace responder
119 } // namespace pldm
120