xref: /openbmc/pldm/oem/ibm/libpldmresponder/file_io_type_vpd.cpp (revision b3b84b497a20c33f5c49e67e89c20638929166a3)
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 
8 #include <phosphor-logging/lg2.hpp>
9 
10 #include <cstdint>
11 
12 PHOSPHOR_LOG2_USING;
13 
14 typedef uint8_t byte;
15 
16 namespace pldm
17 {
18 namespace responder
19 {
read(uint32_t offset,uint32_t & length,Response & response,oem_platform::Handler *)20 int keywordHandler::read(uint32_t offset, uint32_t& length, Response& response,
21                          oem_platform::Handler* /*oemPlatformHandler*/)
22 {
23     const char* keywrdObjPath =
24         "/xyz/openbmc_project/inventory/system/chassis/motherboard";
25     const char* keywrdPropName = "PD_D";
26     const char* keywrdInterface = "com.ibm.ipzvpd.PSPD";
27 
28     std::variant<std::vector<byte>> keywrd;
29 
30     try
31     {
32         auto& bus = pldm::utils::DBusHandler::getBus();
33         auto service = pldm::utils::DBusHandler().getService(keywrdObjPath,
34                                                              keywrdInterface);
35         auto method =
36             bus.new_method_call(service.c_str(), keywrdObjPath,
37                                 "org.freedesktop.DBus.Properties", "Get");
38         method.append(keywrdInterface, keywrdPropName);
39         auto reply = bus.call(method, dbusTimeout);
40         reply.read(keywrd);
41     }
42     catch (const std::exception& e)
43     {
44         error(
45             "Get keyword error from dbus interface {INTERFACE}, error - {ERROR}",
46             "INTERFACE", keywrdInterface, "ERROR", e);
47     }
48 
49     uint32_t keywrdSize = std::get<std::vector<byte>>(keywrd).size();
50     if (length < keywrdSize)
51     {
52         error("Length '{LENGTH}' requested is less than keyword size '{SIZE}'",
53               "LENGTH", length, "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(
73             "Failed to open VPD keyword file '{PATH}', error number - {ERROR_NUM}",
74             "PATH", keywrdFilePath, "ERROR_NUM", errno);
75         pldm::utils::reportError(
76             "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileOpenError");
77         return PLDM_ERROR;
78     }
79 
80     if (offset > keywrdSize)
81     {
82         error("Offset '{OFFSET}' exceeds file size '{SIZE}'", "OFFSET", offset,
83               "SIZE", keywrdSize);
84         return PLDM_DATA_OUT_OF_RANGE;
85     }
86 
87     // length of keyword data should be same as keyword data size in dbus
88     // object
89     length = static_cast<uint32_t>(keywrdSize) - offset;
90 
91     auto returnCode = lseek(fd, offset, SEEK_SET);
92     if (returnCode == -1)
93     {
94         error(
95             "Could not find keyword data of length '{LENGTH}' at given offset '{OFFSET}'. File Seek failed with response code '{RC}'",
96             "LENGTH", length, "OFFSET", offset, "RC", returnCode);
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 '{PATH}'", "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 '{SIZE}'", "SIZE",
113               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