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