xref: /openbmc/bmcweb/features/redfish/lib/processor.hpp (revision 2bab9831767c180bedd005dfcbeb65af8798f088)
1ac6a4445SGunnar Mills /*
2ac6a4445SGunnar Mills // Copyright (c) 2018 Intel Corporation
3ac6a4445SGunnar Mills //
4ac6a4445SGunnar Mills // Licensed under the Apache License, Version 2.0 (the "License");
5ac6a4445SGunnar Mills // you may not use this file except in compliance with the License.
6ac6a4445SGunnar Mills // You may obtain a copy of the License at
7ac6a4445SGunnar Mills //
8ac6a4445SGunnar Mills //      http://www.apache.org/licenses/LICENSE-2.0
9ac6a4445SGunnar Mills //
10ac6a4445SGunnar Mills // Unless required by applicable law or agreed to in writing, software
11ac6a4445SGunnar Mills // distributed under the License is distributed on an "AS IS" BASIS,
12ac6a4445SGunnar Mills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ac6a4445SGunnar Mills // See the License for the specific language governing permissions and
14ac6a4445SGunnar Mills // limitations under the License.
15ac6a4445SGunnar Mills */
16ac6a4445SGunnar Mills #pragma once
17ac6a4445SGunnar Mills 
18ac6a4445SGunnar Mills #include "health.hpp"
19ac6a4445SGunnar Mills 
20ac6a4445SGunnar Mills #include <boost/container/flat_map.hpp>
21ac6a4445SGunnar Mills #include <node.hpp>
22ac6a4445SGunnar Mills #include <utils/collection.hpp>
23ac6a4445SGunnar Mills #include <utils/json_utils.hpp>
24ac6a4445SGunnar Mills 
25ac6a4445SGunnar Mills namespace redfish
26ac6a4445SGunnar Mills {
27ac6a4445SGunnar Mills 
28ac6a4445SGunnar Mills using InterfacesProperties = boost::container::flat_map<
29ac6a4445SGunnar Mills     std::string,
30ac6a4445SGunnar Mills     boost::container::flat_map<std::string, dbus::utility::DbusVariantType>>;
31ac6a4445SGunnar Mills 
32*2bab9831SJonathan Doman using MapperGetSubTreeResponse = std::vector<
33*2bab9831SJonathan Doman     std::pair<std::string,
34*2bab9831SJonathan Doman               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
35*2bab9831SJonathan Doman 
36ac6a4445SGunnar Mills inline void
37ac6a4445SGunnar Mills     getCpuDataByInterface(const std::shared_ptr<AsyncResp>& aResp,
38ac6a4445SGunnar Mills                           const InterfacesProperties& cpuInterfacesProperties)
39ac6a4445SGunnar Mills {
40ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
41ac6a4445SGunnar Mills 
42ac6a4445SGunnar Mills     // Added for future purpose. Once present and functional attributes added
43ac6a4445SGunnar Mills     // in busctl call, need to add actual logic to fetch original values.
44ac6a4445SGunnar Mills     bool present = false;
45ac6a4445SGunnar Mills     const bool functional = true;
46ac6a4445SGunnar Mills     auto health = std::make_shared<HealthPopulate>(aResp);
47ac6a4445SGunnar Mills     health->populate();
48ac6a4445SGunnar Mills 
49ac6a4445SGunnar Mills     for (const auto& interface : cpuInterfacesProperties)
50ac6a4445SGunnar Mills     {
51ac6a4445SGunnar Mills         for (const auto& property : interface.second)
52ac6a4445SGunnar Mills         {
53ac6a4445SGunnar Mills             if (property.first == "CoreCount")
54ac6a4445SGunnar Mills             {
55ac6a4445SGunnar Mills                 const uint16_t* coresCount =
56ac6a4445SGunnar Mills                     std::get_if<uint16_t>(&property.second);
57ac6a4445SGunnar Mills                 if (coresCount == nullptr)
58ac6a4445SGunnar Mills                 {
59ac6a4445SGunnar Mills                     // Important property not in desired type
60ac6a4445SGunnar Mills                     messages::internalError(aResp->res);
61ac6a4445SGunnar Mills                     return;
62ac6a4445SGunnar Mills                 }
63ac6a4445SGunnar Mills                 if (*coresCount == 0)
64ac6a4445SGunnar Mills                 {
65ac6a4445SGunnar Mills                     // Slot is not populated, set status end return
66ac6a4445SGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "Absent";
67ac6a4445SGunnar Mills                     // HTTP Code will be set up automatically, just return
68ac6a4445SGunnar Mills                     return;
69ac6a4445SGunnar Mills                 }
70ac6a4445SGunnar Mills                 aResp->res.jsonValue["Status"]["State"] = "Enabled";
71ac6a4445SGunnar Mills                 present = true;
72ac6a4445SGunnar Mills                 aResp->res.jsonValue["TotalCores"] = *coresCount;
73ac6a4445SGunnar Mills             }
74dc3fa667SJonathan Doman             else if (property.first == "MaxSpeedInMhz")
75dc3fa667SJonathan Doman             {
76dc3fa667SJonathan Doman                 const uint32_t* value = std::get_if<uint32_t>(&property.second);
77dc3fa667SJonathan Doman                 if (value != nullptr)
78dc3fa667SJonathan Doman                 {
79dc3fa667SJonathan Doman                     aResp->res.jsonValue["MaxSpeedMHz"] = *value;
80dc3fa667SJonathan Doman                 }
81dc3fa667SJonathan Doman             }
82ac6a4445SGunnar Mills             else if (property.first == "Socket")
83ac6a4445SGunnar Mills             {
84ac6a4445SGunnar Mills                 const std::string* value =
85ac6a4445SGunnar Mills                     std::get_if<std::string>(&property.second);
86ac6a4445SGunnar Mills                 if (value != nullptr)
87ac6a4445SGunnar Mills                 {
88ac6a4445SGunnar Mills                     aResp->res.jsonValue["Socket"] = *value;
89ac6a4445SGunnar Mills                 }
90ac6a4445SGunnar Mills             }
91ac6a4445SGunnar Mills             else if (property.first == "ThreadCount")
92ac6a4445SGunnar Mills             {
93dc3fa667SJonathan Doman                 const uint16_t* value = std::get_if<uint16_t>(&property.second);
94ac6a4445SGunnar Mills                 if (value != nullptr)
95ac6a4445SGunnar Mills                 {
96ac6a4445SGunnar Mills                     aResp->res.jsonValue["TotalThreads"] = *value;
97ac6a4445SGunnar Mills                 }
98ac6a4445SGunnar Mills             }
99ac6a4445SGunnar Mills             else if (property.first == "Family")
100ac6a4445SGunnar Mills             {
101ac6a4445SGunnar Mills                 const std::string* value =
102ac6a4445SGunnar Mills                     std::get_if<std::string>(&property.second);
103ac6a4445SGunnar Mills                 if (value != nullptr)
104ac6a4445SGunnar Mills                 {
105ac6a4445SGunnar Mills                     aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
106ac6a4445SGunnar Mills                         *value;
107ac6a4445SGunnar Mills                 }
108ac6a4445SGunnar Mills             }
109ac6a4445SGunnar Mills             else if (property.first == "Id")
110ac6a4445SGunnar Mills             {
111ac6a4445SGunnar Mills                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
112ac6a4445SGunnar Mills                 if (value != nullptr && *value != 0)
113ac6a4445SGunnar Mills                 {
114ac6a4445SGunnar Mills                     present = true;
115ac6a4445SGunnar Mills                     aResp->res
116ac6a4445SGunnar Mills                         .jsonValue["ProcessorId"]["IdentificationRegisters"] =
117ac6a4445SGunnar Mills                         boost::lexical_cast<std::string>(*value);
118ac6a4445SGunnar Mills                 }
119ac6a4445SGunnar Mills             }
120ac6a4445SGunnar Mills         }
121ac6a4445SGunnar Mills     }
122ac6a4445SGunnar Mills 
123ac6a4445SGunnar Mills     if (present == false)
124ac6a4445SGunnar Mills     {
125ac6a4445SGunnar Mills         aResp->res.jsonValue["Status"]["State"] = "Absent";
126ac6a4445SGunnar Mills         aResp->res.jsonValue["Status"]["Health"] = "OK";
127ac6a4445SGunnar Mills     }
128ac6a4445SGunnar Mills     else
129ac6a4445SGunnar Mills     {
130ac6a4445SGunnar Mills         aResp->res.jsonValue["Status"]["State"] = "Enabled";
131ac6a4445SGunnar Mills         if (functional)
132ac6a4445SGunnar Mills         {
133ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["Health"] = "OK";
134ac6a4445SGunnar Mills         }
135ac6a4445SGunnar Mills         else
136ac6a4445SGunnar Mills         {
137ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["Health"] = "Critical";
138ac6a4445SGunnar Mills         }
139ac6a4445SGunnar Mills     }
140ac6a4445SGunnar Mills 
141ac6a4445SGunnar Mills     return;
142ac6a4445SGunnar Mills }
143ac6a4445SGunnar Mills 
144ac6a4445SGunnar Mills inline void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
145ac6a4445SGunnar Mills                                 const std::string& cpuId,
146ac6a4445SGunnar Mills                                 const std::string& service,
147ac6a4445SGunnar Mills                                 const std::string& objPath)
148ac6a4445SGunnar Mills {
149ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system cpu resources by service.";
150ac6a4445SGunnar Mills 
151ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
152ac6a4445SGunnar Mills         [cpuId, service, objPath, aResp{std::move(aResp)}](
153ac6a4445SGunnar Mills             const boost::system::error_code ec,
154ac6a4445SGunnar Mills             const dbus::utility::ManagedObjectType& dbusData) {
155ac6a4445SGunnar Mills             if (ec)
156ac6a4445SGunnar Mills             {
157ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
158ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
159ac6a4445SGunnar Mills                 return;
160ac6a4445SGunnar Mills             }
161ac6a4445SGunnar Mills             aResp->res.jsonValue["Id"] = cpuId;
162ac6a4445SGunnar Mills             aResp->res.jsonValue["Name"] = "Processor";
163ac6a4445SGunnar Mills             aResp->res.jsonValue["ProcessorType"] = "CPU";
164ac6a4445SGunnar Mills 
165ac6a4445SGunnar Mills             bool slotPresent = false;
166ac6a4445SGunnar Mills             std::string corePath = objPath + "/core";
167ac6a4445SGunnar Mills             size_t totalCores = 0;
168ac6a4445SGunnar Mills             for (const auto& object : dbusData)
169ac6a4445SGunnar Mills             {
170ac6a4445SGunnar Mills                 if (object.first.str == objPath)
171ac6a4445SGunnar Mills                 {
172ac6a4445SGunnar Mills                     getCpuDataByInterface(aResp, object.second);
173ac6a4445SGunnar Mills                 }
174ac6a4445SGunnar Mills                 else if (boost::starts_with(object.first.str, corePath))
175ac6a4445SGunnar Mills                 {
176ac6a4445SGunnar Mills                     for (const auto& interface : object.second)
177ac6a4445SGunnar Mills                     {
178ac6a4445SGunnar Mills                         if (interface.first ==
179ac6a4445SGunnar Mills                             "xyz.openbmc_project.Inventory.Item")
180ac6a4445SGunnar Mills                         {
181ac6a4445SGunnar Mills                             for (const auto& property : interface.second)
182ac6a4445SGunnar Mills                             {
183ac6a4445SGunnar Mills                                 if (property.first == "Present")
184ac6a4445SGunnar Mills                                 {
185ac6a4445SGunnar Mills                                     const bool* present =
186ac6a4445SGunnar Mills                                         std::get_if<bool>(&property.second);
187ac6a4445SGunnar Mills                                     if (present != nullptr)
188ac6a4445SGunnar Mills                                     {
189ac6a4445SGunnar Mills                                         if (*present == true)
190ac6a4445SGunnar Mills                                         {
191ac6a4445SGunnar Mills                                             slotPresent = true;
192ac6a4445SGunnar Mills                                             totalCores++;
193ac6a4445SGunnar Mills                                         }
194ac6a4445SGunnar Mills                                     }
195ac6a4445SGunnar Mills                                 }
196ac6a4445SGunnar Mills                             }
197ac6a4445SGunnar Mills                         }
198ac6a4445SGunnar Mills                     }
199ac6a4445SGunnar Mills                 }
200ac6a4445SGunnar Mills             }
201ac6a4445SGunnar Mills             // In getCpuDataByInterface(), state and health are set
202ac6a4445SGunnar Mills             // based on the present and functional status. If core
203ac6a4445SGunnar Mills             // count is zero, then it has a higher precedence.
204ac6a4445SGunnar Mills             if (slotPresent)
205ac6a4445SGunnar Mills             {
206ac6a4445SGunnar Mills                 if (totalCores == 0)
207ac6a4445SGunnar Mills                 {
208ac6a4445SGunnar Mills                     // Slot is not populated, set status end return
209ac6a4445SGunnar Mills                     aResp->res.jsonValue["Status"]["State"] = "Absent";
210ac6a4445SGunnar Mills                     aResp->res.jsonValue["Status"]["Health"] = "OK";
211ac6a4445SGunnar Mills                 }
212ac6a4445SGunnar Mills                 aResp->res.jsonValue["TotalCores"] = totalCores;
213ac6a4445SGunnar Mills             }
214ac6a4445SGunnar Mills             return;
215ac6a4445SGunnar Mills         },
216ac6a4445SGunnar Mills         service, "/xyz/openbmc_project/inventory",
217ac6a4445SGunnar Mills         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
218ac6a4445SGunnar Mills }
219ac6a4445SGunnar Mills 
220ac6a4445SGunnar Mills inline void getCpuAssetData(std::shared_ptr<AsyncResp> aResp,
221ac6a4445SGunnar Mills                             const std::string& service,
222ac6a4445SGunnar Mills                             const std::string& objPath)
223ac6a4445SGunnar Mills {
224ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get Cpu Asset Data";
225ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
226ac6a4445SGunnar Mills         [objPath, aResp{std::move(aResp)}](
227ac6a4445SGunnar Mills             const boost::system::error_code ec,
228ac6a4445SGunnar Mills             const boost::container::flat_map<
229ac6a4445SGunnar Mills                 std::string, std::variant<std::string, uint32_t, uint16_t,
230ac6a4445SGunnar Mills                                           bool>>& properties) {
231ac6a4445SGunnar Mills             if (ec)
232ac6a4445SGunnar Mills             {
233ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
234ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
235ac6a4445SGunnar Mills                 return;
236ac6a4445SGunnar Mills             }
237ac6a4445SGunnar Mills 
238ac6a4445SGunnar Mills             for (const auto& property : properties)
239ac6a4445SGunnar Mills             {
240ac6a4445SGunnar Mills                 if (property.first == "SerialNumber")
241ac6a4445SGunnar Mills                 {
242ac6a4445SGunnar Mills                     const std::string* sn =
243ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
244ac6a4445SGunnar Mills                     if (sn != nullptr && !sn->empty())
245ac6a4445SGunnar Mills                     {
246ac6a4445SGunnar Mills                         aResp->res.jsonValue["SerialNumber"] = *sn;
247ac6a4445SGunnar Mills                     }
248ac6a4445SGunnar Mills                 }
249ac6a4445SGunnar Mills                 else if (property.first == "Model")
250ac6a4445SGunnar Mills                 {
251ac6a4445SGunnar Mills                     const std::string* model =
252ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
253ac6a4445SGunnar Mills                     if (model != nullptr && !model->empty())
254ac6a4445SGunnar Mills                     {
255ac6a4445SGunnar Mills                         aResp->res.jsonValue["Model"] = *model;
256ac6a4445SGunnar Mills                     }
257ac6a4445SGunnar Mills                 }
258ac6a4445SGunnar Mills                 else if (property.first == "Manufacturer")
259ac6a4445SGunnar Mills                 {
260ac6a4445SGunnar Mills 
261ac6a4445SGunnar Mills                     const std::string* mfg =
262ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
263ac6a4445SGunnar Mills                     if (mfg != nullptr)
264ac6a4445SGunnar Mills                     {
265ac6a4445SGunnar Mills                         aResp->res.jsonValue["Manufacturer"] = *mfg;
266ac6a4445SGunnar Mills 
267ac6a4445SGunnar Mills                         // Otherwise would be unexpected.
268ac6a4445SGunnar Mills                         if (mfg->find("Intel") != std::string::npos)
269ac6a4445SGunnar Mills                         {
270ac6a4445SGunnar Mills                             aResp->res.jsonValue["ProcessorArchitecture"] =
271ac6a4445SGunnar Mills                                 "x86";
272ac6a4445SGunnar Mills                             aResp->res.jsonValue["InstructionSet"] = "x86-64";
273ac6a4445SGunnar Mills                         }
274ac6a4445SGunnar Mills                         else if (mfg->find("IBM") != std::string::npos)
275ac6a4445SGunnar Mills                         {
276ac6a4445SGunnar Mills                             aResp->res.jsonValue["ProcessorArchitecture"] =
277ac6a4445SGunnar Mills                                 "Power";
278ac6a4445SGunnar Mills                             aResp->res.jsonValue["InstructionSet"] = "PowerISA";
279ac6a4445SGunnar Mills                         }
280ac6a4445SGunnar Mills                     }
281ac6a4445SGunnar Mills                 }
282ac6a4445SGunnar Mills             }
283ac6a4445SGunnar Mills         },
284ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
285ac6a4445SGunnar Mills         "xyz.openbmc_project.Inventory.Decorator.Asset");
286ac6a4445SGunnar Mills }
287ac6a4445SGunnar Mills 
288ac6a4445SGunnar Mills inline void getCpuRevisionData(std::shared_ptr<AsyncResp> aResp,
289ac6a4445SGunnar Mills                                const std::string& service,
290ac6a4445SGunnar Mills                                const std::string& objPath)
291ac6a4445SGunnar Mills {
292ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get Cpu Revision Data";
293ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
294ac6a4445SGunnar Mills         [objPath, aResp{std::move(aResp)}](
295ac6a4445SGunnar Mills             const boost::system::error_code ec,
296ac6a4445SGunnar Mills             const boost::container::flat_map<
297ac6a4445SGunnar Mills                 std::string, std::variant<std::string, uint32_t, uint16_t,
298ac6a4445SGunnar Mills                                           bool>>& properties) {
299ac6a4445SGunnar Mills             if (ec)
300ac6a4445SGunnar Mills             {
301ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
302ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
303ac6a4445SGunnar Mills                 return;
304ac6a4445SGunnar Mills             }
305ac6a4445SGunnar Mills 
306ac6a4445SGunnar Mills             for (const auto& property : properties)
307ac6a4445SGunnar Mills             {
308ac6a4445SGunnar Mills                 if (property.first == "Version")
309ac6a4445SGunnar Mills                 {
310ac6a4445SGunnar Mills                     const std::string* ver =
311ac6a4445SGunnar Mills                         std::get_if<std::string>(&property.second);
312ac6a4445SGunnar Mills                     if (ver != nullptr)
313ac6a4445SGunnar Mills                     {
314ac6a4445SGunnar Mills                         aResp->res.jsonValue["Version"] = *ver;
315ac6a4445SGunnar Mills                     }
316ac6a4445SGunnar Mills                     break;
317ac6a4445SGunnar Mills                 }
318ac6a4445SGunnar Mills             }
319ac6a4445SGunnar Mills         },
320ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
321ac6a4445SGunnar Mills         "xyz.openbmc_project.Inventory.Decorator.Revision");
322ac6a4445SGunnar Mills }
323ac6a4445SGunnar Mills 
324ac6a4445SGunnar Mills inline void getAcceleratorDataByService(std::shared_ptr<AsyncResp> aResp,
325ac6a4445SGunnar Mills                                         const std::string& acclrtrId,
326ac6a4445SGunnar Mills                                         const std::string& service,
327ac6a4445SGunnar Mills                                         const std::string& objPath)
328ac6a4445SGunnar Mills {
329ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG
330ac6a4445SGunnar Mills         << "Get available system Accelerator resources by service.";
331ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
332ac6a4445SGunnar Mills         [acclrtrId, aResp{std::move(aResp)}](
333ac6a4445SGunnar Mills             const boost::system::error_code ec,
334ac6a4445SGunnar Mills             const boost::container::flat_map<
335ac6a4445SGunnar Mills                 std::string, std::variant<std::string, uint32_t, uint16_t,
336ac6a4445SGunnar Mills                                           bool>>& properties) {
337ac6a4445SGunnar Mills             if (ec)
338ac6a4445SGunnar Mills             {
339ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
340ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
341ac6a4445SGunnar Mills                 return;
342ac6a4445SGunnar Mills             }
343ac6a4445SGunnar Mills             aResp->res.jsonValue["Id"] = acclrtrId;
344ac6a4445SGunnar Mills             aResp->res.jsonValue["Name"] = "Processor";
345ac6a4445SGunnar Mills             const bool* accPresent = nullptr;
346ac6a4445SGunnar Mills             const bool* accFunctional = nullptr;
347ac6a4445SGunnar Mills 
348ac6a4445SGunnar Mills             for (const auto& property : properties)
349ac6a4445SGunnar Mills             {
350ac6a4445SGunnar Mills                 if (property.first == "Functional")
351ac6a4445SGunnar Mills                 {
352ac6a4445SGunnar Mills                     accFunctional = std::get_if<bool>(&property.second);
353ac6a4445SGunnar Mills                 }
354ac6a4445SGunnar Mills                 else if (property.first == "Present")
355ac6a4445SGunnar Mills                 {
356ac6a4445SGunnar Mills                     accPresent = std::get_if<bool>(&property.second);
357ac6a4445SGunnar Mills                 }
358ac6a4445SGunnar Mills             }
359ac6a4445SGunnar Mills 
360ac6a4445SGunnar Mills             std::string state = "Enabled";
361ac6a4445SGunnar Mills             std::string health = "OK";
362ac6a4445SGunnar Mills 
363ac6a4445SGunnar Mills             if (accPresent != nullptr && *accPresent == false)
364ac6a4445SGunnar Mills             {
365ac6a4445SGunnar Mills                 state = "Absent";
366ac6a4445SGunnar Mills             }
367ac6a4445SGunnar Mills 
368ac6a4445SGunnar Mills             if ((accFunctional != nullptr) && (*accFunctional == false))
369ac6a4445SGunnar Mills             {
370ac6a4445SGunnar Mills                 if (state == "Enabled")
371ac6a4445SGunnar Mills                 {
372ac6a4445SGunnar Mills                     health = "Critical";
373ac6a4445SGunnar Mills                 }
374ac6a4445SGunnar Mills             }
375ac6a4445SGunnar Mills 
376ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["State"] = state;
377ac6a4445SGunnar Mills             aResp->res.jsonValue["Status"]["Health"] = health;
378ac6a4445SGunnar Mills             aResp->res.jsonValue["ProcessorType"] = "Accelerator";
379ac6a4445SGunnar Mills         },
380ac6a4445SGunnar Mills         service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
381ac6a4445SGunnar Mills }
382ac6a4445SGunnar Mills 
383ac6a4445SGunnar Mills inline void getProcessorData(std::shared_ptr<AsyncResp> aResp,
384*2bab9831SJonathan Doman                              const std::string& processorId)
385ac6a4445SGunnar Mills {
386ac6a4445SGunnar Mills     BMCWEB_LOG_DEBUG << "Get available system processor resources.";
387ac6a4445SGunnar Mills 
388ac6a4445SGunnar Mills     crow::connections::systemBus->async_method_call(
389*2bab9831SJonathan Doman         [processorId,
390*2bab9831SJonathan Doman          aResp{std::move(aResp)}](const boost::system::error_code ec,
391*2bab9831SJonathan Doman                                   const MapperGetSubTreeResponse& subtree) {
392ac6a4445SGunnar Mills             if (ec)
393ac6a4445SGunnar Mills             {
394ac6a4445SGunnar Mills                 BMCWEB_LOG_DEBUG << "DBUS response error";
395ac6a4445SGunnar Mills                 messages::internalError(aResp->res);
396ac6a4445SGunnar Mills                 return;
397ac6a4445SGunnar Mills             }
398*2bab9831SJonathan Doman             for (const auto& [objectPath, serviceMap] : subtree)
399ac6a4445SGunnar Mills             {
400*2bab9831SJonathan Doman                 // Ignore any objects which don't end with our desired cpu name
401*2bab9831SJonathan Doman                 if (!boost::ends_with(objectPath, processorId))
402ac6a4445SGunnar Mills                 {
403*2bab9831SJonathan Doman                     continue;
404ac6a4445SGunnar Mills                 }
405*2bab9831SJonathan Doman 
406*2bab9831SJonathan Doman                 // Process the first object which does match our cpu name
407*2bab9831SJonathan Doman                 // suffix, and potentially ignore any other matching objects.
408*2bab9831SJonathan Doman                 // Assume all interfaces we want to process must be on the same
409*2bab9831SJonathan Doman                 // object.
410*2bab9831SJonathan Doman 
411*2bab9831SJonathan Doman                 for (const auto& [serviceName, interfaceList] : serviceMap)
412ac6a4445SGunnar Mills                 {
413*2bab9831SJonathan Doman                     for (const auto& interface : interfaceList)
414*2bab9831SJonathan Doman                     {
415*2bab9831SJonathan Doman                         if (interface ==
416*2bab9831SJonathan Doman                             "xyz.openbmc_project.Inventory.Decorator.Asset")
417*2bab9831SJonathan Doman                         {
418*2bab9831SJonathan Doman                             getCpuAssetData(aResp, serviceName, objectPath);
419ac6a4445SGunnar Mills                         }
420*2bab9831SJonathan Doman                         else if (interface == "xyz.openbmc_project.Inventory."
421*2bab9831SJonathan Doman                                               "Decorator.Revision")
422ac6a4445SGunnar Mills                         {
423*2bab9831SJonathan Doman                             getCpuRevisionData(aResp, serviceName, objectPath);
424ac6a4445SGunnar Mills                         }
425*2bab9831SJonathan Doman                         else if (interface ==
426*2bab9831SJonathan Doman                                  "xyz.openbmc_project.Inventory.Item.Cpu")
427ac6a4445SGunnar Mills                         {
428*2bab9831SJonathan Doman                             getCpuDataByService(aResp, processorId, serviceName,
429*2bab9831SJonathan Doman                                                 objectPath);
430*2bab9831SJonathan Doman                         }
431*2bab9831SJonathan Doman                         else if (interface == "xyz.openbmc_project.Inventory."
432*2bab9831SJonathan Doman                                               "Item.Accelerator")
433*2bab9831SJonathan Doman                         {
434*2bab9831SJonathan Doman                             getAcceleratorDataByService(
435*2bab9831SJonathan Doman                                 aResp, processorId, serviceName, objectPath);
436ac6a4445SGunnar Mills                         }
437ac6a4445SGunnar Mills                     }
438ac6a4445SGunnar Mills                 }
439ac6a4445SGunnar Mills                 return;
440ac6a4445SGunnar Mills             }
441ac6a4445SGunnar Mills             // Object not found
442ac6a4445SGunnar Mills             messages::resourceNotFound(aResp->res, "Processor", processorId);
443ac6a4445SGunnar Mills             return;
444ac6a4445SGunnar Mills         },
445ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper",
446ac6a4445SGunnar Mills         "/xyz/openbmc_project/object_mapper",
447ac6a4445SGunnar Mills         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
448*2bab9831SJonathan Doman         "/xyz/openbmc_project/inventory", 0,
449*2bab9831SJonathan Doman         std::array<const char*, 4>{
450*2bab9831SJonathan Doman             "xyz.openbmc_project.Inventory.Decorator.Asset",
451*2bab9831SJonathan Doman             "xyz.openbmc_project.Inventory.Decorator.Revision",
452*2bab9831SJonathan Doman             "xyz.openbmc_project.Inventory.Item.Cpu",
453*2bab9831SJonathan Doman             "xyz.openbmc_project.Inventory.Item.Accelerator"});
454ac6a4445SGunnar Mills }
455ac6a4445SGunnar Mills 
456ac6a4445SGunnar Mills class ProcessorCollection : public Node
457ac6a4445SGunnar Mills {
458ac6a4445SGunnar Mills   public:
459ac6a4445SGunnar Mills     /*
460ac6a4445SGunnar Mills      * Default Constructor
461ac6a4445SGunnar Mills      */
462ac6a4445SGunnar Mills     ProcessorCollection(App& app) :
463ac6a4445SGunnar Mills         Node(app, "/redfish/v1/Systems/system/Processors/")
464ac6a4445SGunnar Mills     {
465ac6a4445SGunnar Mills         entityPrivileges = {
466ac6a4445SGunnar Mills             {boost::beast::http::verb::get, {{"Login"}}},
467ac6a4445SGunnar Mills             {boost::beast::http::verb::head, {{"Login"}}},
468ac6a4445SGunnar Mills             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
469ac6a4445SGunnar Mills             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
470ac6a4445SGunnar Mills             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
471ac6a4445SGunnar Mills             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
472ac6a4445SGunnar Mills     }
473ac6a4445SGunnar Mills 
474ac6a4445SGunnar Mills   private:
475ac6a4445SGunnar Mills     /**
476ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
477ac6a4445SGunnar Mills      */
478ac6a4445SGunnar Mills     void doGet(crow::Response& res, const crow::Request&,
479ac6a4445SGunnar Mills                const std::vector<std::string>&) override
480ac6a4445SGunnar Mills     {
481ac6a4445SGunnar Mills         res.jsonValue["@odata.type"] =
482ac6a4445SGunnar Mills             "#ProcessorCollection.ProcessorCollection";
483ac6a4445SGunnar Mills         res.jsonValue["Name"] = "Processor Collection";
484ac6a4445SGunnar Mills 
4859dedf572SGunnar Mills         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Processors";
486ac6a4445SGunnar Mills         auto asyncResp = std::make_shared<AsyncResp>(res);
487ac6a4445SGunnar Mills 
48805030b8eSGunnar Mills         collection_util::getCollectionMembers(
48905030b8eSGunnar Mills             asyncResp, "/redfish/v1/Systems/system/Processors",
490ac6a4445SGunnar Mills             {"xyz.openbmc_project.Inventory.Item.Cpu",
491ac6a4445SGunnar Mills              "xyz.openbmc_project.Inventory.Item.Accelerator"});
492ac6a4445SGunnar Mills     }
493ac6a4445SGunnar Mills };
494ac6a4445SGunnar Mills 
495ac6a4445SGunnar Mills class Processor : public Node
496ac6a4445SGunnar Mills {
497ac6a4445SGunnar Mills   public:
498ac6a4445SGunnar Mills     /*
499ac6a4445SGunnar Mills      * Default Constructor
500ac6a4445SGunnar Mills      */
501ac6a4445SGunnar Mills     Processor(App& app) :
502ac6a4445SGunnar Mills         Node(app, "/redfish/v1/Systems/system/Processors/<str>/", std::string())
503ac6a4445SGunnar Mills     {
504ac6a4445SGunnar Mills         entityPrivileges = {
505ac6a4445SGunnar Mills             {boost::beast::http::verb::get, {{"Login"}}},
506ac6a4445SGunnar Mills             {boost::beast::http::verb::head, {{"Login"}}},
507ac6a4445SGunnar Mills             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
508ac6a4445SGunnar Mills             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
509ac6a4445SGunnar Mills             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
510ac6a4445SGunnar Mills             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
511ac6a4445SGunnar Mills     }
512ac6a4445SGunnar Mills 
513ac6a4445SGunnar Mills   private:
514ac6a4445SGunnar Mills     /**
515ac6a4445SGunnar Mills      * Functions triggers appropriate requests on DBus
516ac6a4445SGunnar Mills      */
517ac6a4445SGunnar Mills     void doGet(crow::Response& res, const crow::Request&,
518ac6a4445SGunnar Mills                const std::vector<std::string>& params) override
519ac6a4445SGunnar Mills     {
520ac6a4445SGunnar Mills         // Check if there is required param, truly entering this shall be
521ac6a4445SGunnar Mills         // impossible
522ac6a4445SGunnar Mills         if (params.size() != 1)
523ac6a4445SGunnar Mills         {
524ac6a4445SGunnar Mills             messages::internalError(res);
525ac6a4445SGunnar Mills 
526ac6a4445SGunnar Mills             res.end();
527ac6a4445SGunnar Mills             return;
528ac6a4445SGunnar Mills         }
529ac6a4445SGunnar Mills         const std::string& processorId = params[0];
530ac6a4445SGunnar Mills         res.jsonValue["@odata.type"] = "#Processor.v1_9_0.Processor";
531ac6a4445SGunnar Mills         res.jsonValue["@odata.id"] =
532ac6a4445SGunnar Mills             "/redfish/v1/Systems/system/Processors/" + processorId;
533ac6a4445SGunnar Mills 
534ac6a4445SGunnar Mills         auto asyncResp = std::make_shared<AsyncResp>(res);
535ac6a4445SGunnar Mills 
536*2bab9831SJonathan Doman         getProcessorData(asyncResp, processorId);
537ac6a4445SGunnar Mills     }
538ac6a4445SGunnar Mills };
539ac6a4445SGunnar Mills 
540ac6a4445SGunnar Mills } // namespace redfish
541