1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #pragma once
18 #include "cpu.hpp"
19 #include "dimm.hpp"
20 #include "pcieslot.hpp"
21 #include "smbios_mdrv2.hpp"
22 #include "system.hpp"
23 #include "tpm.hpp"
24
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #include <boost/asio/io_context.hpp>
30 #include <boost/asio/steady_timer.hpp>
31 #include <boost/container/flat_map.hpp>
32 #include <phosphor-logging/elog-errors.hpp>
33 #include <phosphor-logging/lg2.hpp>
34 #include <phosphor-logging/log.hpp>
35 #include <sdbusplus/asio/object_server.hpp>
36 #include <sdbusplus/server.hpp>
37 #include <sdbusplus/timer.hpp>
38 #include <xyz/openbmc_project/Smbios/MDR_V2/server.hpp>
39
40 #include <filesystem>
41 #include <memory>
42
43 namespace phosphor
44 {
45 namespace smbios
46 {
47
48 using RecordVariant =
49 std::variant<std::string, uint64_t, uint32_t, uint16_t, uint8_t>;
50
51 static constexpr const char* defaultObjectPath =
52 "/xyz/openbmc_project/Smbios/MDR_V2";
53 static constexpr const char* smbiosInterfaceName =
54 "xyz.openbmc_project.Smbios.GetRecordType";
55 static constexpr const char* mapperBusName = "xyz.openbmc_project.ObjectMapper";
56 static constexpr const char* mapperPath = "/xyz/openbmc_project/object_mapper";
57 static constexpr const char* mapperInterface =
58 "xyz.openbmc_project.ObjectMapper";
59 static constexpr const char* defaultInventoryPath =
60 "/xyz/openbmc_project/inventory/system";
61 static constexpr const char* systemInterface =
62 "xyz.openbmc_project.Inventory.Item.System";
63 static constexpr const char* boardInterface =
64 "xyz.openbmc_project.Inventory.Item.Board";
65 constexpr const int limitEntryLen = 0xff;
66
67 // Avoid putting multiple interfaces with same name on same object
placeGetRecordType(const std::string & objectPath)68 static std::string placeGetRecordType(const std::string& objectPath)
69 {
70 if (objectPath != defaultObjectPath)
71 {
72 // Place GetRecordType interface on object itself, not parent
73 return objectPath;
74 }
75
76 std::filesystem::path path(objectPath);
77
78 // As there is only one default, safe to place it on the common parent
79 return path.parent_path().string();
80 }
81
82 class MDRV2 :
83 sdbusplus::server::object_t<
84 sdbusplus::server::xyz::openbmc_project::smbios::MDRV2>
85 {
86 public:
87 MDRV2() = delete;
88 MDRV2(const MDRV2&) = delete;
89 MDRV2& operator=(const MDRV2&) = delete;
90 MDRV2(MDRV2&&) = delete;
91 MDRV2& operator=(MDRV2&&) = delete;
92
~MDRV2()93 virtual ~MDRV2()
94 {
95 if (smbiosInterface)
96 {
97 if (objServer)
98 {
99 // Must manually undo add_interface()
100 objServer->remove_interface(smbiosInterface);
101 }
102 }
103 }
104
MDRV2(std::shared_ptr<boost::asio::io_context> io,std::shared_ptr<sdbusplus::asio::connection> conn,std::shared_ptr<sdbusplus::asio::object_server> obj,std::string filePath,std::string objectPath,std::string inventoryPath)105 MDRV2(std::shared_ptr<boost::asio::io_context> io,
106 std::shared_ptr<sdbusplus::asio::connection> conn,
107 std::shared_ptr<sdbusplus::asio::object_server> obj,
108 std::string filePath, std::string objectPath,
109 std::string inventoryPath) :
110 sdbusplus::server::object_t<
111 sdbusplus::server::xyz::openbmc_project::smbios::MDRV2>(
112 *conn, objectPath.c_str()),
113 timer(*io), bus(conn), objServer(std::move(obj)),
114 smbiosInterface(objServer->add_interface(placeGetRecordType(objectPath),
115 smbiosInterfaceName)),
116 smbiosFilePath(std::move(filePath)),
117 smbiosObjectPath(std::move(objectPath)),
118 smbiosInventoryPath(std::move(inventoryPath))
119 {
120 lg2::info("SMBIOS data file path: {F}", "F", smbiosFilePath);
121 lg2::info("SMBIOS control object: {O}", "O", smbiosObjectPath);
122 lg2::info("SMBIOS inventory path: {I}", "I", smbiosInventoryPath);
123
124 smbiosDir.agentVersion = smbiosAgentVersion;
125 smbiosDir.dirVersion = smbiosDirVersion;
126 smbiosDir.dirEntries = 1;
127 directoryEntries(smbiosDir.dirEntries);
128 smbiosDir.status = 1;
129 smbiosDir.remoteDirVersion = 0;
130
131 std::copy(smbiosTableId.begin(), smbiosTableId.end(),
132 smbiosDir.dir[smbiosDirIndex].common.id.dataInfo);
133
134 smbiosDir.dir[smbiosDirIndex].dataStorage = smbiosTableStorage;
135
136 agentSynchronizeData();
137
138 smbiosInterface->register_method("GetRecordType", [this](size_t type) {
139 return getRecordType(type);
140 });
141 smbiosInterface->initialize();
142 }
143
144 std::vector<uint8_t> getDirectoryInformation(uint8_t dirIndex) override;
145
146 std::vector<uint8_t> getDataInformation(uint8_t idIndex) override;
147
148 bool sendDirectoryInformation(
149 uint8_t dirVersion, uint8_t dirIndex, uint8_t returnedEntries,
150 uint8_t remainingEntries, std::vector<uint8_t> dirEntry) override;
151
152 std::vector<uint8_t> getDataOffer() override;
153
154 bool sendDataInformation(uint8_t idIndex, uint8_t flag, uint32_t dataLen,
155 uint32_t dataVer, uint32_t timeStamp) override;
156
157 int findIdIndex(std::vector<uint8_t> dataInfo) override;
158
159 bool agentSynchronizeData() override;
160
161 std::vector<uint32_t> synchronizeDirectoryCommonData(
162 uint8_t idIndex, uint32_t size) override;
163
164 uint8_t directoryEntries(uint8_t value) override;
165
166 std::vector<boost::container::flat_map<std::string, RecordVariant>>
167 getRecordType(size_t type);
168
169 private:
170 boost::asio::steady_timer timer;
171
172 std::shared_ptr<sdbusplus::asio::connection> bus;
173 std::shared_ptr<sdbusplus::asio::object_server> objServer;
174
175 Mdr2DirStruct smbiosDir;
176
177 bool readDataFromFlash(MDRSMBIOSHeader* mdrHdr, uint8_t* data);
178 bool checkSMBIOSVersion(uint8_t* dataIn);
179
180 const std::array<uint8_t, 16> smbiosTableId{
181 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 0x42};
182 uint8_t smbiosTableStorage[smbiosTableStorageSize] = {};
183
184 bool smbiosIsUpdating(uint8_t index);
185 bool smbiosIsAvailForUpdate(uint8_t index);
186 inline uint8_t smbiosValidFlag(uint8_t index);
187 void systemInfoUpdate(void);
188
189 std::optional<size_t> getTotalCpuSlot(void);
190 std::optional<size_t> getTotalDimmSlot(void);
191 std::optional<size_t> getTotalPcieSlot(void);
192 std::optional<size_t> getTotalTpm(void);
193 std::vector<std::unique_ptr<Cpu>> cpus;
194 std::vector<std::unique_ptr<Dimm>> dimms;
195 std::vector<std::unique_ptr<Pcie>> pcies;
196 std::vector<std::unique_ptr<Tpm>> tpms;
197 std::unique_ptr<System> system;
198 std::shared_ptr<sdbusplus::asio::dbus_interface> smbiosInterface;
199
200 std::string smbiosFilePath;
201 std::string smbiosObjectPath;
202 std::string smbiosInventoryPath;
203 std::unique_ptr<sdbusplus::bus::match_t> motherboardConfigMatch;
204 };
205
206 } // namespace smbios
207 } // namespace phosphor
208