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 = DBusHandler::getBus();
31         auto service = pldm::utils::DBusHandler().getService(keywrdObjPath,
32                                                              keywrdInterface);
33         auto method =
34             bus.new_method_call(service.c_str(), keywrdObjPath,
35                                 "org.freedesktop.DBus.Properties", "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     auto 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             pldm::PelSeverity::ERROR);
75         return PLDM_ERROR;
76     }
77 
78     if (offset > keywrdSize)
79     {
80         std::cerr << "Offset exceeds file size, OFFSET=" << offset
81                   << " FILE_SIZE=" << keywrdSize << std::endl;
82         return PLDM_DATA_OUT_OF_RANGE;
83     }
84 
85     // length of keyword data should be same as keyword data size in dbus object
86     length = static_cast<uint32_t>(keywrdSize) - offset;
87 
88     auto returnCode = lseek(fd, offset, SEEK_SET);
89     if (returnCode == -1)
90     {
91         std::cerr
92             << "Could not find keyword data at given offset. File Seek failed"
93             << std::endl;
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         std::cerr << "Error while writing to file: " << keywrdFilePath
102                   << std::endl;
103     }
104     keywrdFile.close();
105 
106     auto rc = readFile(keywrdFilePath, offset, keywrdSize, response);
107     fs::remove(keywrdFilePath);
108     if (rc)
109     {
110         std::cerr << "Read error for keyword file with size: " << keywrdSize
111                   << std::endl;
112         pldm::utils::reportError(
113             "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileReadError",
114             pldm::PelSeverity::ERROR);
115         return PLDM_ERROR;
116     }
117     return PLDM_SUCCESS;
118 }
119 } // namespace responder
120 } // namespace pldm
121