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 #include <iostream>
12 
13 PHOSPHOR_LOG2_USING;
14 
15 typedef uint8_t byte;
16 
17 namespace pldm
18 {
19 namespace responder
20 {
21 int keywordHandler::read(uint32_t offset, uint32_t& length, Response& response,
22                          oem_platform::Handler* /*oemPlatformHandler*/)
23 {
24     const char* keywrdObjPath =
25         "/xyz/openbmc_project/inventory/system/chassis/motherboard";
26     const char* keywrdPropName = "PD_D";
27     const char* keywrdInterface = "com.ibm.ipzvpd.PSPD";
28 
29     std::variant<std::vector<byte>> keywrd;
30 
31     try
32     {
33         auto& bus = pldm::utils::DBusHandler::getBus();
34         auto service = pldm::utils::DBusHandler().getService(keywrdObjPath,
35                                                              keywrdInterface);
36         auto method = bus.new_method_call(service.c_str(), keywrdObjPath,
37                                           "org.freedesktop.DBus.Properties",
38                                           "Get");
39         method.append(keywrdInterface, keywrdPropName);
40         auto reply = bus.call(method, dbusTimeout);
41         reply.read(keywrd);
42     }
43     catch (const std::exception& e)
44     {
45         error(
46             "Get keyword error from dbus interface :{KEYWORD_INTF} ERROR={ERR_EXCEP}",
47             "KEYWORD_INTF", keywrdInterface, "ERR_EXCEP", e.what());
48     }
49 
50     uint32_t keywrdSize = std::get<std::vector<byte>>(keywrd).size();
51     if (length < keywrdSize)
52     {
53         error(
54             "length requested is less the keyword size, length:{LEN} keyword size:{KEYWORD_SIZE}",
55             "LEN", length, "KEYWORD_SIZE", keywrdSize);
56         return PLDM_ERROR_INVALID_DATA;
57     }
58 
59     namespace fs = std::filesystem;
60     constexpr auto keywrdDirPath = "/tmp/pldm/";
61     constexpr auto keywrdFilePath = "/tmp/pldm/vpdKeywrd.bin";
62 
63     if (!fs::exists(keywrdDirPath))
64     {
65         fs::create_directories(keywrdDirPath);
66         fs::permissions(keywrdDirPath,
67                         fs::perms::others_read | fs::perms::owner_write);
68     }
69 
70     std::ofstream keywrdFile(keywrdFilePath);
71     auto fd = open(keywrdFilePath, std::ios::out | std::ofstream::binary);
72     if (!keywrdFile)
73     {
74         error("VPD keyword file open error: {KEYWORD_FILE_PATH} errno: {ERR}",
75               "KEYWORD_FILE_PATH", keywrdFilePath, "ERR", errno);
76         pldm::utils::reportError(
77             "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileOpenError");
78         return PLDM_ERROR;
79     }
80 
81     if (offset > keywrdSize)
82     {
83         error("Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}",
84               "OFFSET", offset, "FILE_SIZE", keywrdSize);
85         return PLDM_DATA_OUT_OF_RANGE;
86     }
87 
88     // length of keyword data should be same as keyword data size in dbus
89     // object
90     length = static_cast<uint32_t>(keywrdSize) - offset;
91 
92     auto returnCode = lseek(fd, offset, SEEK_SET);
93     if (returnCode == -1)
94     {
95         error("Could not find keyword data at given offset. File Seek failed");
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: {KEYWORD_FILE_PATH}",
104               "KEYWORD_FILE_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: {KEYWORD_SIZE}",
113               "KEYWORD_SIZE", 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