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