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