blob: 0724c85cd2c070c3deb1128723f31e3cf076a8a7 [file] [log] [blame]
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001/*
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#pragma once
17
James Feistb49ac872019-05-21 15:12:01 -070018#include "health.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080019#include "pcie.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080020#include "redfish_util.hpp"
21
Ed Tanous9712f8a2018-09-21 13:38:49 -070022#include <boost/container/flat_map.hpp>
23#include <node.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060024#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020025#include <utils/json_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080026#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace redfish
29{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020030
Alpana Kumari9d3ae102019-04-12 06:49:32 -050031/**
32 * @brief Updates the Functional State of DIMMs
33 *
34 * @param[in] aResp Shared pointer for completing asynchronous calls
35 * @param[in] dimmState Dimm's Functional state, true/false
36 *
37 * @return None.
38 */
39void updateDimmProperties(std::shared_ptr<AsyncResp> aResp,
40 const std::variant<bool> &dimmState)
41{
42 const bool *isDimmFunctional = std::get_if<bool>(&dimmState);
43 if (isDimmFunctional == nullptr)
44 {
45 messages::internalError(aResp->res);
46 return;
47 }
Gunnar Mills698654b2019-10-16 13:17:37 -050048 BMCWEB_LOG_DEBUG << "Dimm Functional: " << *isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049
50 // Set it as Enabled if atleast one DIMM is functional
51 // Update STATE only if previous State was DISABLED and current Dimm is
52 // ENABLED.
53 nlohmann::json &prevMemSummary =
54 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
55 if (prevMemSummary == "Disabled")
56 {
57 if (*isDimmFunctional == true)
58 {
59 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
60 "Enabled";
61 }
62 }
63}
64
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050065/*
66 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
67 *
68 * @param[in] aResp Shared pointer for completing asynchronous calls
69 * @param[in] cpuPresenceState CPU present or not
70 *
71 * @return None.
72 */
73void modifyCpuPresenceState(std::shared_ptr<AsyncResp> aResp,
74 const std::variant<bool> &cpuPresenceState)
75{
76 const bool *isCpuPresent = std::get_if<bool>(&cpuPresenceState);
77
78 if (isCpuPresent == nullptr)
79 {
80 messages::internalError(aResp->res);
81 return;
82 }
Gunnar Mills698654b2019-10-16 13:17:37 -050083 BMCWEB_LOG_DEBUG << "Cpu Present: " << *isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050084
85 nlohmann::json &procCount =
86 aResp->res.jsonValue["ProcessorSummary"]["Count"];
87 if (*isCpuPresent == true)
88 {
89 procCount = procCount.get<int>() + 1;
90 }
91 aResp->res.jsonValue["ProcessorSummary"]["Count"] = procCount;
92}
93
94/*
95 * @brief Update "ProcessorSummary" "Status" "State" based on
96 * CPU Functional State
97 *
98 * @param[in] aResp Shared pointer for completing asynchronous calls
99 * @param[in] cpuFunctionalState is CPU functional true/false
100 *
101 * @return None.
102 */
103void modifyCpuFunctionalState(std::shared_ptr<AsyncResp> aResp,
104 const std::variant<bool> &cpuFunctionalState)
105{
106 const bool *isCpuFunctional = std::get_if<bool>(&cpuFunctionalState);
107
108 if (isCpuFunctional == nullptr)
109 {
110 messages::internalError(aResp->res);
111 return;
112 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500113 BMCWEB_LOG_DEBUG << "Cpu Functional: " << *isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114
115 nlohmann::json &prevProcState =
116 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
117
118 // Set it as Enabled if atleast one CPU is functional
119 // Update STATE only if previous State was Non_Functional and current CPU is
120 // Functional.
121 if (prevProcState == "Disabled")
122 {
123 if (*isCpuFunctional == true)
124 {
125 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
126 "Enabled";
127 }
128 }
129}
130
131/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700132 * @brief Retrieves computer system properties over dbus
133 *
134 * @param[in] aResp Shared pointer for completing asynchronous calls
135 * @param[in] name Computer system name from request
136 *
137 * @return None.
138 */
Ed Tanous029573d2019-02-01 10:57:49 -0800139void getComputerSystem(std::shared_ptr<AsyncResp> aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700140{
Ed Tanous6c34de42018-08-29 13:37:36 -0700141 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500142
Ed Tanous6c34de42018-08-29 13:37:36 -0700143 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800144 [aResp](
Ed Tanous6c34de42018-08-29 13:37:36 -0700145 const boost::system::error_code ec,
146 const std::vector<std::pair<
147 std::string,
148 std::vector<std::pair<std::string, std::vector<std::string>>>>>
149 &subtree) {
150 if (ec)
151 {
152 BMCWEB_LOG_DEBUG << "DBUS response error";
Jason M. Billsf12894f2018-10-09 12:45:45 -0700153 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700154 return;
155 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700156 // Iterate over all retrieved ObjectPaths.
157 for (const std::pair<std::string,
158 std::vector<std::pair<
159 std::string, std::vector<std::string>>>>
160 &object : subtree)
161 {
162 const std::string &path = object.first;
163 BMCWEB_LOG_DEBUG << "Got path: " << path;
164 const std::vector<
165 std::pair<std::string, std::vector<std::string>>>
166 &connectionNames = object.second;
167 if (connectionNames.size() < 1)
168 {
169 continue;
170 }
Ed Tanous029573d2019-02-01 10:57:49 -0800171
172 // This is not system, so check if it's cpu, dimm, UUID or
173 // BiosVer
174 for (const auto &connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700175 {
Ed Tanous029573d2019-02-01 10:57:49 -0800176 for (const auto &interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700177 {
Ed Tanous029573d2019-02-01 10:57:49 -0800178 if (interfaceName ==
179 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700180 {
Ed Tanous029573d2019-02-01 10:57:49 -0800181 BMCWEB_LOG_DEBUG
182 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500183
Ed Tanous029573d2019-02-01 10:57:49 -0800184 crow::connections::systemBus->async_method_call(
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500185 [aResp, service{connection.first},
186 path(std::move(path))](
187 const boost::system::error_code ec,
188 const std::vector<
189 std::pair<std::string, VariantType>>
190 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800191 if (ec)
192 {
193 BMCWEB_LOG_ERROR
194 << "DBUS response error " << ec;
195 messages::internalError(aResp->res);
196 return;
197 }
198 BMCWEB_LOG_DEBUG << "Got "
199 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500200 << " Dimm properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500201
202 if (properties.size() > 0)
Ed Tanous029573d2019-02-01 10:57:49 -0800203 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500204 for (const std::pair<std::string,
205 VariantType>
206 &property : properties)
Ed Tanous6c34de42018-08-29 13:37:36 -0700207 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500208 if (property.first ==
209 "MemorySizeInKb")
Ed Tanous6c34de42018-08-29 13:37:36 -0700210 {
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500211 const uint64_t *value =
212 sdbusplus::message::
213 variant_ns::get_if<
214 uint64_t>(
215 &property.second);
216 if (value != nullptr)
217 {
218 aResp->res.jsonValue
219 ["TotalSystemMemoryGi"
220 "B"] +=
221 *value / (1024 * 1024);
222 aResp->res.jsonValue
223 ["MemorySummary"]
224 ["Status"]["State"] =
225 "Enabled";
226 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700227 }
228 }
Ed Tanous029573d2019-02-01 10:57:49 -0800229 }
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500230 else
231 {
232 auto getDimmProperties =
233 [aResp](
234 const boost::system::error_code
235 ec,
236 const std::variant<bool>
237 &dimmState) {
238 if (ec)
239 {
240 BMCWEB_LOG_ERROR
241 << "DBUS response "
242 "error "
243 << ec;
244 return;
245 }
246 updateDimmProperties(aResp,
247 dimmState);
248 };
249 crow::connections::systemBus
250 ->async_method_call(
251 std::move(getDimmProperties),
252 service, path,
253 "org.freedesktop.DBus."
254 "Properties",
255 "Get",
256 "xyz.openbmc_project.State."
257 "Decorator.OperationalStatus",
258 "Functional");
259 }
Ed Tanous029573d2019-02-01 10:57:49 -0800260 },
261 connection.first, path,
262 "org.freedesktop.DBus.Properties", "GetAll",
263 "xyz.openbmc_project.Inventory.Item.Dimm");
264 }
265 else if (interfaceName ==
266 "xyz.openbmc_project.Inventory.Item.Cpu")
267 {
268 BMCWEB_LOG_DEBUG
269 << "Found Cpu, now get its properties.";
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500270
Ed Tanous029573d2019-02-01 10:57:49 -0800271 crow::connections::systemBus->async_method_call(
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500272 [aResp, service{connection.first},
273 path(std::move(path))](
274 const boost::system::error_code ec,
275 const std::vector<
276 std::pair<std::string, VariantType>>
277 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800278 if (ec)
279 {
280 BMCWEB_LOG_ERROR
281 << "DBUS response error " << ec;
282 messages::internalError(aResp->res);
283 return;
284 }
285 BMCWEB_LOG_DEBUG << "Got "
286 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500287 << " Cpu properties.";
Ed Tanous04a258f2018-10-15 08:00:41 -0700288
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500289 if (properties.size() > 0)
290 {
291 for (const auto &property : properties)
292 {
293 if (property.first ==
294 "ProcessorFamily")
295 {
296 const std::string *value =
297 sdbusplus::message::
298 variant_ns::get_if<
299 std::string>(
300 &property.second);
301 if (value != nullptr)
302 {
303 nlohmann::json
304 &procSummary =
305 aResp->res.jsonValue
306 ["ProcessorSumm"
307 "ary"];
308 nlohmann::json &procCount =
309 procSummary["Count"];
310 procCount =
311 procCount.get<int>() +
312 1;
313 procSummary["Status"]
314 ["State"] =
315 "Enabled";
316 procSummary["Model"] =
317 *value;
318 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700319 }
320 }
Ed Tanous029573d2019-02-01 10:57:49 -0800321 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500322 else
323 {
324 auto getCpuPresenceState =
325 [aResp](
326 const boost::system::error_code
327 ec,
328 const std::variant<bool>
329 &cpuPresenceCheck) {
330 if (ec)
331 {
332 BMCWEB_LOG_ERROR
333 << "DBUS response "
334 "error "
335 << ec;
336 return;
337 }
338 modifyCpuPresenceState(
339 aResp, cpuPresenceCheck);
340 };
341
342 auto getCpuFunctionalState =
343 [aResp](
344 const boost::system::error_code
345 ec,
346 const std::variant<bool>
347 &cpuFunctionalCheck) {
348 if (ec)
349 {
350 BMCWEB_LOG_ERROR
351 << "DBUS response "
352 "error "
353 << ec;
354 return;
355 }
356 modifyCpuFunctionalState(
357 aResp, cpuFunctionalCheck);
358 };
359 // Get the Presence of CPU
360 crow::connections::systemBus
361 ->async_method_call(
362 std::move(getCpuPresenceState),
363 service, path,
364 "org.freedesktop.DBus."
365 "Properties",
366 "Get",
367 "xyz.openbmc_project.Inventory."
368 "Item",
369 "Present");
370
371 // Get the Functional State
372 crow::connections::systemBus
373 ->async_method_call(
374 std::move(
375 getCpuFunctionalState),
376 service, path,
377 "org.freedesktop.DBus."
378 "Properties",
379 "Get",
380 "xyz.openbmc_project.State."
381 "Decorator."
382 "OperationalStatus",
383 "Functional");
384
385 // Get the MODEL from
386 // xyz.openbmc_project.Inventory.Decorator.Asset
387 // support it later as Model is Empty
388 // currently.
389 }
Ed Tanous029573d2019-02-01 10:57:49 -0800390 },
391 connection.first, path,
392 "org.freedesktop.DBus.Properties", "GetAll",
393 "xyz.openbmc_project.Inventory.Item.Cpu");
394 }
395 else if (interfaceName ==
396 "xyz.openbmc_project.Common.UUID")
397 {
398 BMCWEB_LOG_DEBUG
399 << "Found UUID, now get its properties.";
400 crow::connections::systemBus->async_method_call(
401 [aResp](const boost::system::error_code ec,
Ed Tanous6c34de42018-08-29 13:37:36 -0700402 const std::vector<
403 std::pair<std::string, VariantType>>
404 &properties) {
Ed Tanous029573d2019-02-01 10:57:49 -0800405 if (ec)
406 {
407 BMCWEB_LOG_DEBUG
408 << "DBUS response error " << ec;
409 messages::internalError(aResp->res);
410 return;
411 }
412 BMCWEB_LOG_DEBUG << "Got "
413 << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500414 << " UUID properties.";
Ed Tanous029573d2019-02-01 10:57:49 -0800415 for (const std::pair<std::string,
416 VariantType>
417 &property : properties)
418 {
Ed Tanous029573d2019-02-01 10:57:49 -0800419 if (property.first == "UUID")
420 {
421 const std::string *value =
422 sdbusplus::message::variant_ns::
423 get_if<std::string>(
424 &property.second);
Ed Tanous04a258f2018-10-15 08:00:41 -0700425
Ed Tanous029573d2019-02-01 10:57:49 -0800426 if (value != nullptr)
427 {
428 std::string valueStr = *value;
429 if (valueStr.size() == 32)
Ed Tanous6c34de42018-08-29 13:37:36 -0700430 {
Ed Tanous029573d2019-02-01 10:57:49 -0800431 valueStr.insert(8, 1, '-');
432 valueStr.insert(13, 1, '-');
433 valueStr.insert(18, 1, '-');
434 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700435 }
Ed Tanous029573d2019-02-01 10:57:49 -0800436 BMCWEB_LOG_DEBUG << "UUID = "
437 << valueStr;
438 aResp->res.jsonValue["UUID"] =
439 valueStr;
Ed Tanous6c34de42018-08-29 13:37:36 -0700440 }
441 }
Ed Tanous029573d2019-02-01 10:57:49 -0800442 }
443 },
444 connection.first, path,
445 "org.freedesktop.DBus.Properties", "GetAll",
446 "xyz.openbmc_project.Common.UUID");
447 }
448 else if (interfaceName ==
449 "xyz.openbmc_project.Inventory.Item.System")
450 {
451 crow::connections::systemBus->async_method_call(
452 [aResp](const boost::system::error_code ec,
453 const std::vector<
454 std::pair<std::string, VariantType>>
455 &propertiesList) {
456 if (ec)
457 {
James Feiste4a4b9a2019-06-20 14:08:07 -0700458 // doesn't have to include this
459 // interface
Ed Tanous029573d2019-02-01 10:57:49 -0800460 return;
461 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500462 BMCWEB_LOG_DEBUG
463 << "Got " << propertiesList.size()
464 << " properties for system";
Ed Tanous029573d2019-02-01 10:57:49 -0800465 for (const std::pair<std::string,
466 VariantType>
467 &property : propertiesList)
468 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600469 const std::string &propertyName =
470 property.first;
471 if ((propertyName == "PartNumber") ||
472 (propertyName == "SerialNumber") ||
473 (propertyName == "Manufacturer") ||
474 (propertyName == "Model"))
Ed Tanous029573d2019-02-01 10:57:49 -0800475 {
beccabroekfc5afcf2019-03-05 14:35:15 -0600476 const std::string *value =
477 std::get_if<std::string>(
478 &property.second);
479 if (value != nullptr)
480 {
481 aResp->res
482 .jsonValue[propertyName] =
483 *value;
484 }
Ed Tanous029573d2019-02-01 10:57:49 -0800485 }
486 }
487 aResp->res.jsonValue["Name"] = "system";
488 aResp->res.jsonValue["Id"] =
489 aResp->res.jsonValue["SerialNumber"];
Andrew Geisslercb7e1e72019-02-19 13:05:38 -0600490 // Grab the bios version
491 fw_util::getActiveFwVersion(
492 aResp, fw_util::biosPurpose,
493 "BiosVersion");
Ed Tanous029573d2019-02-01 10:57:49 -0800494 },
495 connection.first, path,
496 "org.freedesktop.DBus.Properties", "GetAll",
497 "xyz.openbmc_project.Inventory.Decorator."
498 "Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700499
500 crow::connections::systemBus->async_method_call(
501 [aResp](
502 const boost::system::error_code ec,
503 const std::variant<std::string> &property) {
504 if (ec)
505 {
506 // doesn't have to include this
507 // interface
508 return;
509 }
510
511 const std::string *value =
512 std::get_if<std::string>(&property);
513 if (value != nullptr)
514 {
515 aResp->res.jsonValue["AssetTag"] =
516 *value;
517 }
518 },
519 connection.first, path,
520 "org.freedesktop.DBus.Properties", "Get",
521 "xyz.openbmc_project.Inventory.Decorator."
522 "AssetTag",
523 "AssetTag");
Ed Tanous6c34de42018-08-29 13:37:36 -0700524 }
525 }
526 }
527 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700528 },
529 "xyz.openbmc_project.ObjectMapper",
530 "/xyz/openbmc_project/object_mapper",
531 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700532 "/xyz/openbmc_project/inventory", int32_t(0),
533 std::array<const char *, 5>{
534 "xyz.openbmc_project.Inventory.Decorator.Asset",
535 "xyz.openbmc_project.Inventory.Item.Cpu",
536 "xyz.openbmc_project.Inventory.Item.Dimm",
537 "xyz.openbmc_project.Inventory.Item.System",
538 "xyz.openbmc_project.Common.UUID",
539 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700540}
541
542/**
543 * @brief Retrieves identify led group properties over dbus
544 *
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530545 * @param[in] aResp Shared pointer for generating response message.
Ed Tanous6c34de42018-08-29 13:37:36 -0700546 * @param[in] callback Callback for process retrieved data.
547 *
548 * @return None.
549 */
550template <typename CallbackFunc>
551void getLedGroupIdentify(std::shared_ptr<AsyncResp> aResp,
552 CallbackFunc &&callback)
553{
554 BMCWEB_LOG_DEBUG << "Get led groups";
555 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800556 [aResp,
Ed Tanous66173382018-08-15 18:20:59 -0700557 callback{std::move(callback)}](const boost::system::error_code &ec,
558 const ManagedObjectsType &resp) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700559 if (ec)
560 {
561 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700562 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700563 return;
564 }
Gunnar Mills698654b2019-10-16 13:17:37 -0500565 BMCWEB_LOG_DEBUG << "Got " << resp.size() << " led group objects.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 for (const auto &objPath : resp)
567 {
568 const std::string &path = objPath.first;
569 if (path.rfind("enclosure_identify") != std::string::npos)
570 {
571 for (const auto &interface : objPath.second)
572 {
573 if (interface.first == "xyz.openbmc_project.Led.Group")
574 {
575 for (const auto &property : interface.second)
576 {
577 if (property.first == "Asserted")
578 {
579 const bool *asserted =
Ed Tanousabf2add2019-01-22 16:40:12 -0800580 std::get_if<bool>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700581 if (nullptr != asserted)
582 {
583 callback(*asserted, aResp);
584 }
585 else
586 {
587 callback(false, aResp);
588 }
589 }
590 }
591 }
592 }
593 }
594 }
595 },
596 "xyz.openbmc_project.LED.GroupManager",
597 "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
598 "GetManagedObjects");
599}
600
601template <typename CallbackFunc>
602void getLedIdentify(std::shared_ptr<AsyncResp> aResp, CallbackFunc &&callback)
603{
604 BMCWEB_LOG_DEBUG << "Get identify led properties";
605 crow::connections::systemBus->async_method_call(
Ed Tanous66173382018-08-15 18:20:59 -0700606 [aResp,
607 callback{std::move(callback)}](const boost::system::error_code ec,
608 const PropertiesType &properties) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700609 if (ec)
610 {
611 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700612 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700613 return;
614 }
615 BMCWEB_LOG_DEBUG << "Got " << properties.size()
Gunnar Mills698654b2019-10-16 13:17:37 -0500616 << " led properties.";
Ed Tanous6c34de42018-08-29 13:37:36 -0700617 std::string output;
618 for (const auto &property : properties)
619 {
620 if (property.first == "State")
621 {
622 const std::string *s =
Ed Tanousabf2add2019-01-22 16:40:12 -0800623 std::get_if<std::string>(&property.second);
Ed Tanous6c34de42018-08-29 13:37:36 -0700624 if (nullptr != s)
625 {
626 BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
627 const auto pos = s->rfind('.');
628 if (pos != std::string::npos)
629 {
630 auto led = s->substr(pos + 1);
631 for (const std::pair<const char *, const char *>
632 &p :
633 std::array<
634 std::pair<const char *, const char *>, 3>{
635 {{"On", "Lit"},
636 {"Blink", "Blinking"},
637 {"Off", "Off"}}})
638 {
639 if (led == p.first)
640 {
641 output = p.second;
642 }
643 }
644 }
645 }
646 }
647 }
648 callback(output, aResp);
649 },
650 "xyz.openbmc_project.LED.Controller.identify",
651 "/xyz/openbmc_project/led/physical/identify",
652 "org.freedesktop.DBus.Properties", "GetAll",
653 "xyz.openbmc_project.Led.Physical");
654}
Ed Tanous6c34de42018-08-29 13:37:36 -0700655/**
656 * @brief Retrieves host state properties over dbus
657 *
658 * @param[in] aResp Shared pointer for completing asynchronous calls.
659 *
660 * @return None.
661 */
662void getHostState(std::shared_ptr<AsyncResp> aResp)
663{
664 BMCWEB_LOG_DEBUG << "Get host information.";
665 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800666 [aResp](const boost::system::error_code ec,
667 const std::variant<std::string> &hostState) {
Ed Tanous6c34de42018-08-29 13:37:36 -0700668 if (ec)
669 {
670 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700671 messages::internalError(aResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700672 return;
673 }
Ed Tanous66173382018-08-15 18:20:59 -0700674
Ed Tanousabf2add2019-01-22 16:40:12 -0800675 const std::string *s = std::get_if<std::string>(&hostState);
Ed Tanous66173382018-08-15 18:20:59 -0700676 BMCWEB_LOG_DEBUG << "Host state: " << *s;
677 if (s != nullptr)
Ed Tanous6c34de42018-08-29 13:37:36 -0700678 {
Ed Tanous66173382018-08-15 18:20:59 -0700679 // Verify Host State
Andrew Geissler94732662019-01-08 19:32:16 -0800680 if (*s == "xyz.openbmc_project.State.Host.HostState.Running")
Ed Tanous6c34de42018-08-29 13:37:36 -0700681 {
Ed Tanous66173382018-08-15 18:20:59 -0700682 aResp->res.jsonValue["PowerState"] = "On";
683 aResp->res.jsonValue["Status"]["State"] = "Enabled";
684 }
685 else
686 {
687 aResp->res.jsonValue["PowerState"] = "Off";
688 aResp->res.jsonValue["Status"]["State"] = "Disabled";
Ed Tanous6c34de42018-08-29 13:37:36 -0700689 }
690 }
691 },
692 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
Ed Tanous66173382018-08-15 18:20:59 -0700693 "org.freedesktop.DBus.Properties", "Get",
694 "xyz.openbmc_project.State.Host", "CurrentHostState");
Ed Tanous6c34de42018-08-29 13:37:36 -0700695}
696
697/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530698 * @brief Traslates boot source DBUS property value to redfish.
699 *
700 * @param[in] dbusSource The boot source in DBUS speak.
701 *
702 * @return Returns as a string, the boot source in Redfish terms. If translation
703 * cannot be done, returns an empty string.
704 */
705static std::string dbusToRfBootSource(const std::string &dbusSource)
706{
707 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
708 {
709 return "None";
710 }
711 else if (dbusSource ==
712 "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
713 {
714 return "Hdd";
715 }
716 else if (dbusSource ==
Santosh Puranika71dc0b2019-05-23 20:10:49 +0530717 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530718 {
719 return "Cd";
720 }
721 else if (dbusSource ==
722 "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
723 {
724 return "Pxe";
725 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700726 else if (dbusSource ==
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700727 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700728 {
729 return "Usb";
730 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 else
732 {
733 return "";
734 }
735}
736
737/**
738 * @brief Traslates boot mode DBUS property value to redfish.
739 *
740 * @param[in] dbusMode The boot mode in DBUS speak.
741 *
742 * @return Returns as a string, the boot mode in Redfish terms. If translation
743 * cannot be done, returns an empty string.
744 */
745static std::string dbusToRfBootMode(const std::string &dbusMode)
746{
747 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
748 {
749 return "None";
750 }
751 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
752 {
753 return "Diags";
754 }
755 else if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
756 {
757 return "BiosSetup";
758 }
759 else
760 {
761 return "";
762 }
763}
764
765/**
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 * @brief Traslates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530767 *
768 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700769 * @param[out] bootSource The DBus source
770 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530771 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700772 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530773 */
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700774static int assignBootParameters(std::shared_ptr<AsyncResp> aResp,
775 const std::string &rfSource,
776 std::string &bootSource, std::string &bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700778 // The caller has initialized the bootSource and bootMode to:
779 // bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
780 // bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
781 // Only modify the bootSource/bootMode variable needed to achieve the
782 // desired boot action.
783
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 if (rfSource == "None")
785 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700786 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787 }
788 else if (rfSource == "Pxe")
789 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
791 }
792 else if (rfSource == "Hdd")
793 {
794 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
795 }
796 else if (rfSource == "Diags")
797 {
798 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
799 }
800 else if (rfSource == "Cd")
801 {
802 bootSource =
803 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
804 }
805 else if (rfSource == "BiosSetup")
806 {
807 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530808 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700809 else if (rfSource == "Usb")
810 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700811 bootSource =
812 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700813 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530814 else
815 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700816 BMCWEB_LOG_DEBUG << "Invalid property value for "
817 "BootSourceOverrideTarget: "
818 << bootSource;
819 messages::propertyValueNotInList(aResp->res, rfSource,
820 "BootSourceTargetOverride");
821 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530822 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700823 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530824}
825
826/**
827 * @brief Retrieves boot mode over DBUS and fills out the response
828 *
829 * @param[in] aResp Shared pointer for generating response message.
830 * @param[in] bootDbusObj The dbus object to query for boot properties.
831 *
832 * @return None.
833 */
834static void getBootMode(std::shared_ptr<AsyncResp> aResp,
835 std::string bootDbusObj)
836{
837 crow::connections::systemBus->async_method_call(
838 [aResp](const boost::system::error_code ec,
839 const std::variant<std::string> &bootMode) {
840 if (ec)
841 {
842 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
843 messages::internalError(aResp->res);
844 return;
845 }
846
847 const std::string *bootModeStr =
848 std::get_if<std::string>(&bootMode);
849
850 if (!bootModeStr)
851 {
852 messages::internalError(aResp->res);
853 return;
854 }
855
856 BMCWEB_LOG_DEBUG << "Boot mode: " << *bootModeStr;
857
858 // TODO (Santosh): Do we need to support override mode?
859 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = "Legacy";
860 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget@Redfish."
861 "AllowableValues"] = {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700862 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530863
864 if (*bootModeStr !=
865 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
866 {
867 auto rfMode = dbusToRfBootMode(*bootModeStr);
868 if (!rfMode.empty())
869 {
870 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
871 rfMode;
872 }
873 }
874
875 // If the BootSourceOverrideTarget is still "None" at the end,
876 // reset the BootSourceOverrideEnabled to indicate that
877 // overrides are disabled
878 if (aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] ==
879 "None")
880 {
881 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
882 "Disabled";
883 }
884 },
885 "xyz.openbmc_project.Settings", bootDbusObj,
886 "org.freedesktop.DBus.Properties", "Get",
887 "xyz.openbmc_project.Control.Boot.Mode", "BootMode");
888}
889
890/**
891 * @brief Retrieves boot source over DBUS
892 *
893 * @param[in] aResp Shared pointer for generating response message.
894 * @param[in] oneTimeEnable Boolean to indicate boot properties are one-time.
895 *
896 * @return None.
897 */
898static void getBootSource(std::shared_ptr<AsyncResp> aResp, bool oneTimeEnabled)
899{
900 std::string bootDbusObj =
901 oneTimeEnabled ? "/xyz/openbmc_project/control/host0/boot/one_time"
902 : "/xyz/openbmc_project/control/host0/boot";
903
904 BMCWEB_LOG_DEBUG << "Is one time: " << oneTimeEnabled;
905 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
906 (oneTimeEnabled) ? "Once" : "Continuous";
907
908 crow::connections::systemBus->async_method_call(
909 [aResp, bootDbusObj](const boost::system::error_code ec,
910 const std::variant<std::string> &bootSource) {
911 if (ec)
912 {
913 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
914 messages::internalError(aResp->res);
915 return;
916 }
917
918 const std::string *bootSourceStr =
919 std::get_if<std::string>(&bootSource);
920
921 if (!bootSourceStr)
922 {
923 messages::internalError(aResp->res);
924 return;
925 }
926 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSourceStr;
927
928 auto rfSource = dbusToRfBootSource(*bootSourceStr);
929 if (!rfSource.empty())
930 {
931 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
932 rfSource;
933 }
934 },
935 "xyz.openbmc_project.Settings", bootDbusObj,
936 "org.freedesktop.DBus.Properties", "Get",
937 "xyz.openbmc_project.Control.Boot.Source", "BootSource");
938 getBootMode(std::move(aResp), std::move(bootDbusObj));
939}
940
941/**
942 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
943 * get boot source and boot mode.
944 *
945 * @param[in] aResp Shared pointer for generating response message.
946 *
947 * @return None.
948 */
949static void getBootProperties(std::shared_ptr<AsyncResp> aResp)
950{
951 BMCWEB_LOG_DEBUG << "Get boot information.";
952
953 crow::connections::systemBus->async_method_call(
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800954 [aResp](const boost::system::error_code ec,
955 const sdbusplus::message::variant<bool> &oneTime) {
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530956 if (ec)
957 {
958 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
James Feist2a833c72019-07-19 10:17:13 -0700959 // not an error, don't have to have the interface
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530960 return;
961 }
962
963 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
964
965 if (!oneTimePtr)
966 {
967 messages::internalError(aResp->res);
968 return;
969 }
970 getBootSource(aResp, *oneTimePtr);
971 },
972 "xyz.openbmc_project.Settings",
973 "/xyz/openbmc_project/control/host0/boot/one_time",
974 "org.freedesktop.DBus.Properties", "Get",
975 "xyz.openbmc_project.Object.Enable", "Enabled");
976}
977
978/**
979 * @brief Sets boot properties into DBUS object(s).
980 *
981 * @param[in] aResp Shared pointer for generating response message.
982 * @param[in] oneTimeEnabled Is "one-time" setting already enabled.
983 * @param[in] bootSource The boot source to set.
984 * @param[in] bootEnable The source override "enable" to set.
985 *
Johnathan Mantey265c1602019-08-08 11:02:51 -0700986 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530987 */
988static void setBootModeOrSource(std::shared_ptr<AsyncResp> aResp,
989 bool oneTimeEnabled,
990 std::optional<std::string> bootSource,
991 std::optional<std::string> bootEnable)
992{
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700993 std::string bootSourceStr =
994 "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
995 std::string bootModeStr =
996 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530997 bool oneTimeSetting = oneTimeEnabled;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700998 bool useBootSource = true;
999
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000 // Validate incoming parameters
1001 if (bootEnable)
1002 {
1003 if (*bootEnable == "Once")
1004 {
1005 oneTimeSetting = true;
1006 }
1007 else if (*bootEnable == "Continuous")
1008 {
1009 oneTimeSetting = false;
1010 }
1011 else if (*bootEnable == "Disabled")
1012 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001013 BMCWEB_LOG_DEBUG << "Boot source override will be disabled";
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301014 oneTimeSetting = false;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001015 useBootSource = false;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301016 }
1017 else
1018 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019 BMCWEB_LOG_DEBUG << "Unsupported value for "
1020 "BootSourceOverrideEnabled: "
1021 << *bootEnable;
1022 messages::propertyValueNotInList(aResp->res, *bootEnable,
1023 "BootSourceOverrideEnabled");
1024 return;
1025 }
1026 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301027
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001028 if (bootSource && useBootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029 {
1030 // Source target specified
1031 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1032 // Figure out which DBUS interface and property to use
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001033 if (assignBootParameters(aResp, *bootSource, bootSourceStr,
1034 bootModeStr))
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301035 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001036 BMCWEB_LOG_DEBUG
1037 << "Invalid property value for BootSourceOverrideTarget: "
1038 << *bootSource;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301039 messages::propertyValueNotInList(aResp->res, *bootSource,
1040 "BootSourceTargetOverride");
1041 return;
1042 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001043 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001045 // Act on validated parameters
1046 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1047 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
1048 const char *bootObj =
1049 oneTimeSetting ? "/xyz/openbmc_project/control/host0/boot/one_time"
1050 : "/xyz/openbmc_project/control/host0/boot";
1051
1052 crow::connections::systemBus->async_method_call(
1053 [aResp](const boost::system::error_code ec) {
1054 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301055 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001056 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1057 messages::internalError(aResp->res);
1058 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301059 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001060 BMCWEB_LOG_DEBUG << "Boot source update done.";
1061 },
1062 "xyz.openbmc_project.Settings", bootObj,
1063 "org.freedesktop.DBus.Properties", "Set",
1064 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
1065 std::variant<std::string>(bootSourceStr));
1066
1067 crow::connections::systemBus->async_method_call(
1068 [aResp](const boost::system::error_code ec) {
1069 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301070 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001071 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1072 messages::internalError(aResp->res);
1073 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301074 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001075 BMCWEB_LOG_DEBUG << "Boot mode update done.";
1076 },
1077 "xyz.openbmc_project.Settings", bootObj,
1078 "org.freedesktop.DBus.Properties", "Set",
1079 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
1080 std::variant<std::string>(bootModeStr));
1081
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301082 crow::connections::systemBus->async_method_call(
1083 [aResp{std::move(aResp)}](const boost::system::error_code ec) {
1084 if (ec)
1085 {
1086 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1087 messages::internalError(aResp->res);
1088 return;
1089 }
1090 BMCWEB_LOG_DEBUG << "Boot enable update done.";
1091 },
1092 "xyz.openbmc_project.Settings",
1093 "/xyz/openbmc_project/control/host0/boot/one_time",
1094 "org.freedesktop.DBus.Properties", "Set",
1095 "xyz.openbmc_project.Object.Enable", "Enabled",
1096 std::variant<bool>(oneTimeSetting));
1097}
1098
1099/**
1100 * @brief Retrieves "One time" enabled setting over DBUS and calls function to
1101 * set boot source/boot mode properties.
1102 *
1103 * @param[in] aResp Shared pointer for generating response message.
1104 * @param[in] bootSource The boot source from incoming RF request.
1105 * @param[in] bootEnable The boot override enable from incoming RF request.
1106 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001107 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301108 */
1109static void setBootProperties(std::shared_ptr<AsyncResp> aResp,
1110 std::optional<std::string> bootSource,
1111 std::optional<std::string> bootEnable)
1112{
1113 BMCWEB_LOG_DEBUG << "Set boot information.";
1114
1115 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001116 [aResp, bootSource{std::move(bootSource)},
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301117 bootEnable{std::move(bootEnable)}](
1118 const boost::system::error_code ec,
1119 const sdbusplus::message::variant<bool> &oneTime) {
1120 if (ec)
1121 {
1122 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1123 messages::internalError(aResp->res);
1124 return;
1125 }
1126
1127 const bool *oneTimePtr = std::get_if<bool>(&oneTime);
1128
1129 if (!oneTimePtr)
1130 {
1131 messages::internalError(aResp->res);
1132 return;
1133 }
1134
1135 BMCWEB_LOG_DEBUG << "Got one time: " << *oneTimePtr;
1136
1137 setBootModeOrSource(aResp, *oneTimePtr, std::move(bootSource),
1138 std::move(bootEnable));
1139 },
1140 "xyz.openbmc_project.Settings",
1141 "/xyz/openbmc_project/control/host0/boot/one_time",
1142 "org.freedesktop.DBus.Properties", "Get",
1143 "xyz.openbmc_project.Object.Enable", "Enabled");
1144}
1145
1146/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001147 * SystemsCollection derived class for delivering ComputerSystems Collection
1148 * Schema
1149 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001150class SystemsCollection : public Node
1151{
1152 public:
1153 SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
1154 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001155 entityPrivileges = {
1156 {boost::beast::http::verb::get, {{"Login"}}},
1157 {boost::beast::http::verb::head, {{"Login"}}},
1158 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1159 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1160 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1161 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1162 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001163
Ed Tanous1abe55e2018-09-05 08:30:59 -07001164 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001165 void doGet(crow::Response &res, const crow::Request &req,
1166 const std::vector<std::string> &params) override
1167 {
Ed Tanous0f74e642018-11-12 15:17:05 -08001168 res.jsonValue["@odata.type"] =
1169 "#ComputerSystemCollection.ComputerSystemCollection";
1170 res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
1171 res.jsonValue["@odata.context"] =
1172 "/redfish/v1/"
1173 "$metadata#ComputerSystemCollection.ComputerSystemCollection";
1174 res.jsonValue["Name"] = "Computer System Collection";
Ed Tanous029573d2019-02-01 10:57:49 -08001175 res.jsonValue["Members"] = {
1176 {{"@odata.id", "/redfish/v1/Systems/system"}}};
1177 res.jsonValue["Members@odata.count"] = 1;
1178 res.end();
Ed Tanous1abe55e2018-09-05 08:30:59 -07001179 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001180};
1181
1182/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07001183 * SystemActionsReset class supports handle POST method for Reset action.
1184 * The class retrieves and sends data directly to D-Bus.
1185 */
1186class SystemActionsReset : public Node
1187{
1188 public:
1189 SystemActionsReset(CrowApp &app) :
Ed Tanous029573d2019-02-01 10:57:49 -08001190 Node(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanouscc340dd2018-08-29 13:43:38 -07001191 {
1192 entityPrivileges = {
1193 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1194 }
1195
1196 private:
1197 /**
1198 * Function handles POST method request.
1199 * Analyzes POST body message before sends Reset request data to D-Bus.
1200 */
1201 void doPost(crow::Response &res, const crow::Request &req,
1202 const std::vector<std::string> &params) override
1203 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001204 auto asyncResp = std::make_shared<AsyncResp>(res);
1205
1206 std::string resetType;
1207 if (!json_util::readJson(req, res, "ResetType", resetType))
Ed Tanouscc340dd2018-08-29 13:43:38 -07001208 {
1209 return;
1210 }
1211
Jason M. Billsd22c8392019-06-03 13:59:03 -07001212 // Get the command and host vs. chassis
Ed Tanous9712f8a2018-09-21 13:38:49 -07001213 std::string command;
Jason M. Billsd22c8392019-06-03 13:59:03 -07001214 bool hostCommand;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001215 if (resetType == "On")
1216 {
1217 command = "xyz.openbmc_project.State.Host.Transition.On";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001218 hostCommand = true;
1219 }
1220 else if (resetType == "ForceOff")
1221 {
1222 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
1223 hostCommand = false;
1224 }
1225 else if (resetType == "ForceOn")
1226 {
1227 command = "xyz.openbmc_project.State.Host.Transition.On";
1228 hostCommand = true;
1229 }
1230 else if (resetType == "ForceRestart")
1231 {
1232 command = "xyz.openbmc_project.State.Chassis.Transition.Reset";
1233 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001234 }
1235 else if (resetType == "GracefulShutdown")
1236 {
1237 command = "xyz.openbmc_project.State.Host.Transition.Off";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001238 hostCommand = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001239 }
1240 else if (resetType == "GracefulRestart")
1241 {
1242 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
Jason M. Billsd22c8392019-06-03 13:59:03 -07001243 hostCommand = true;
1244 }
1245 else if (resetType == "PowerCycle")
1246 {
1247 command = "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
1248 hostCommand = false;
Ed Tanous9712f8a2018-09-21 13:38:49 -07001249 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001250 else if (resetType == "Nmi")
1251 {
1252 doNMI(asyncResp);
1253 return;
1254 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001255 else
1256 {
Jason M. Billsf12894f2018-10-09 12:45:45 -07001257 messages::actionParameterUnknown(res, "Reset", resetType);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001258 return;
1259 }
1260
Jason M. Billsd22c8392019-06-03 13:59:03 -07001261 if (hostCommand)
1262 {
1263 crow::connections::systemBus->async_method_call(
1264 [asyncResp, resetType](const boost::system::error_code ec) {
1265 if (ec)
1266 {
1267 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1268 if (ec.value() == boost::asio::error::invalid_argument)
1269 {
1270 messages::actionParameterNotSupported(
1271 asyncResp->res, resetType, "Reset");
1272 }
1273 else
1274 {
1275 messages::internalError(asyncResp->res);
1276 }
1277 return;
1278 }
1279 messages::success(asyncResp->res);
1280 },
1281 "xyz.openbmc_project.State.Host",
1282 "/xyz/openbmc_project/state/host0",
1283 "org.freedesktop.DBus.Properties", "Set",
1284 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
1285 std::variant<std::string>{command});
1286 }
1287 else
1288 {
1289 crow::connections::systemBus->async_method_call(
1290 [asyncResp, resetType](const boost::system::error_code ec) {
1291 if (ec)
1292 {
1293 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1294 if (ec.value() == boost::asio::error::invalid_argument)
1295 {
1296 messages::actionParameterNotSupported(
1297 asyncResp->res, resetType, "Reset");
1298 }
1299 else
1300 {
1301 messages::internalError(asyncResp->res);
1302 }
1303 return;
1304 }
1305 messages::success(asyncResp->res);
1306 },
1307 "xyz.openbmc_project.State.Chassis",
1308 "/xyz/openbmc_project/state/chassis0",
1309 "org.freedesktop.DBus.Properties", "Set",
1310 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
1311 std::variant<std::string>{command});
1312 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001313 }
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001314 /**
1315 * Function transceives data with dbus directly.
1316 */
1317 void doNMI(const std::shared_ptr<AsyncResp> &asyncResp)
1318 {
1319 constexpr char const *serviceName =
1320 "xyz.openbmc_project.Control.Host.NMI";
1321 constexpr char const *objectPath =
1322 "/xyz/openbmc_project/control/host0/nmi";
1323 constexpr char const *interfaceName =
1324 "xyz.openbmc_project.Control.Host.NMI";
1325 constexpr char const *method = "NMI";
1326
1327 crow::connections::systemBus->async_method_call(
1328 [asyncResp](const boost::system::error_code ec) {
1329 if (ec)
1330 {
1331 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
1332 messages::internalError(asyncResp->res);
1333 return;
1334 }
1335 messages::success(asyncResp->res);
1336 },
1337 serviceName, objectPath, interfaceName, method);
1338 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07001339};
1340
1341/**
Ed Tanous66173382018-08-15 18:20:59 -07001342 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001343 */
Ed Tanous1abe55e2018-09-05 08:30:59 -07001344class Systems : public Node
1345{
1346 public:
1347 /*
1348 * Default Constructor
1349 */
Ed Tanous029573d2019-02-01 10:57:49 -08001350 Systems(CrowApp &app) : Node(app, "/redfish/v1/Systems/system/")
Ed Tanous1abe55e2018-09-05 08:30:59 -07001351 {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001352 entityPrivileges = {
1353 {boost::beast::http::verb::get, {{"Login"}}},
1354 {boost::beast::http::verb::head, {{"Login"}}},
1355 {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1356 {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1357 {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1358 {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001359 }
1360
Ed Tanous1abe55e2018-09-05 08:30:59 -07001361 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -07001362 /**
1363 * Functions triggers appropriate requests on DBus
1364 */
1365 void doGet(crow::Response &res, const crow::Request &req,
1366 const std::vector<std::string> &params) override
1367 {
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301368 res.jsonValue["@odata.type"] = "#ComputerSystem.v1_6_0.ComputerSystem";
Ed Tanous0f74e642018-11-12 15:17:05 -08001369 res.jsonValue["@odata.context"] =
1370 "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
Ed Tanous029573d2019-02-01 10:57:49 -08001371 res.jsonValue["Name"] = "Computer System";
1372 res.jsonValue["Id"] = "system";
Ed Tanous0f74e642018-11-12 15:17:05 -08001373 res.jsonValue["SystemType"] = "Physical";
1374 res.jsonValue["Description"] = "Computer System";
Ed Tanous0f74e642018-11-12 15:17:05 -08001375 res.jsonValue["ProcessorSummary"]["Count"] = 0;
1376 res.jsonValue["ProcessorSummary"]["Status"]["State"] = "Disabled";
1377 res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
1378 res.jsonValue["MemorySummary"]["Status"]["State"] = "Disabled";
Ed Tanous029573d2019-02-01 10:57:49 -08001379 res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07001380
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001381 res.jsonValue["Processors"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001382 {"@odata.id", "/redfish/v1/Systems/system/Processors"}};
Rapkiewicz, Pawel443c2932018-10-22 15:08:49 +02001383 res.jsonValue["Memory"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001384 {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
Nikhil Potadea25aecc2019-08-23 16:35:26 -07001385 res.jsonValue["Storage"] = {
1386 {"@odata.id", "/redfish/v1/Systems/system/Storage"}};
Ed Tanous029573d2019-02-01 10:57:49 -08001387
Ed Tanouscc340dd2018-08-29 13:43:38 -07001388 // TODO Need to support ForceRestart.
1389 res.jsonValue["Actions"]["#ComputerSystem.Reset"] = {
1390 {"target",
Ed Tanous029573d2019-02-01 10:57:49 -08001391 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"},
Ed Tanouscc340dd2018-08-29 13:43:38 -07001392 {"ResetType@Redfish.AllowableValues",
Jason M. Billsd22c8392019-06-03 13:59:03 -07001393 {"On", "ForceOff", "ForceOn", "ForceRestart", "GracefulRestart",
Lakshminarayana R. Kammathbfd5b822019-06-17 12:11:01 -05001394 "GracefulShutdown", "PowerCycle", "Nmi"}}};
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001395
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001396 res.jsonValue["LogServices"] = {
Ed Tanous029573d2019-02-01 10:57:49 -08001397 {"@odata.id", "/redfish/v1/Systems/system/LogServices"}};
Jason M. Billsc4bf6372018-11-05 13:48:27 -08001398
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001399 res.jsonValue["Links"]["ManagedBy"] = {
1400 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
1401
1402 res.jsonValue["Status"] = {
1403 {"Health", "OK"},
1404 {"State", "Enabled"},
1405 };
Ed Tanousa0803ef2018-08-29 13:29:23 -07001406 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous1abe55e2018-09-05 08:30:59 -07001407
James Feistb49ac872019-05-21 15:12:01 -07001408 constexpr const std::array<const char *, 2> inventoryForSystems = {
1409 "xyz.openbmc_project.Inventory.Item.Dimm",
1410 "xyz.openbmc_project.Inventory.Item.Cpu"};
1411
1412 auto health = std::make_shared<HealthPopulate>(asyncResp);
1413 crow::connections::systemBus->async_method_call(
1414 [health](const boost::system::error_code ec,
1415 std::vector<std::string> &resp) {
1416 if (ec)
1417 {
1418 // no inventory
1419 return;
1420 }
1421
1422 health->inventory = std::move(resp);
1423 },
1424 "xyz.openbmc_project.ObjectMapper",
1425 "/xyz/openbmc_project/object_mapper",
1426 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
1427 int32_t(0), inventoryForSystems);
1428
1429 health->populate();
1430
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001431 getMainChassisId(asyncResp, [](const std::string &chassisId,
1432 std::shared_ptr<AsyncResp> aRsp) {
1433 aRsp->res.jsonValue["Links"]["Chassis"] = {
1434 {{"@odata.id", "/redfish/v1/Chassis/" + chassisId}}};
1435 });
Ed Tanous6c34de42018-08-29 13:37:36 -07001436 getLedGroupIdentify(
Ed Tanousa0803ef2018-08-29 13:29:23 -07001437 asyncResp,
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001438 [](const bool &asserted, const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001439 if (asserted)
1440 {
1441 // If led group is asserted, then another call is needed to
1442 // get led status
Ed Tanous6c34de42018-08-29 13:37:36 -07001443 getLedIdentify(
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001444 aRsp, [](const std::string &ledStatus,
1445 const std::shared_ptr<AsyncResp> aRsp) {
Ed Tanous1abe55e2018-09-05 08:30:59 -07001446 if (!ledStatus.empty())
1447 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001448 aRsp->res.jsonValue["IndicatorLED"] = ledStatus;
Ed Tanous1abe55e2018-09-05 08:30:59 -07001449 }
1450 });
1451 }
1452 else
1453 {
Jennifer Leec5d03ff2019-03-08 15:42:58 -08001454 aRsp->res.jsonValue["IndicatorLED"] = "Off";
Ed Tanous1abe55e2018-09-05 08:30:59 -07001455 }
1456 });
Ed Tanous029573d2019-02-01 10:57:49 -08001457 getComputerSystem(asyncResp);
Ed Tanous6c34de42018-08-29 13:37:36 -07001458 getHostState(asyncResp);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301459 getBootProperties(asyncResp);
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -08001460 getPCIeDeviceList(asyncResp);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001461 }
1462
Ed Tanous1abe55e2018-09-05 08:30:59 -07001463 void doPatch(crow::Response &res, const crow::Request &req,
1464 const std::vector<std::string> &params) override
1465 {
Santosh Puranikcde19e52019-02-20 00:10:56 +05301466 std::optional<std::string> indicatorLed;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301467 std::optional<nlohmann::json> bootProps;
Santosh Puranik41352c22019-07-03 05:35:49 -05001468 auto asyncResp = std::make_shared<AsyncResp>(res);
1469
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001470 if (!json_util::readJson(req, res, "IndicatorLED", indicatorLed, "Boot",
1471 bootProps))
Ed Tanous66173382018-08-15 18:20:59 -07001472 {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001473 return;
1474 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301475
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001476 res.result(boost::beast::http::status::no_content);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301477 if (bootProps)
1478 {
1479 std::optional<std::string> bootSource;
1480 std::optional<std::string> bootEnable;
1481
1482 if (!json_util::readJson(*bootProps, asyncResp->res,
1483 "BootSourceOverrideTarget", bootSource,
1484 "BootSourceOverrideEnabled", bootEnable))
1485 {
1486 return;
1487 }
1488 setBootProperties(asyncResp, std::move(bootSource),
1489 std::move(bootEnable));
1490 }
Johnathan Mantey265c1602019-08-08 11:02:51 -07001491
Ed Tanous9712f8a2018-09-21 13:38:49 -07001492 if (indicatorLed)
1493 {
1494 std::string dbusLedState;
Jennifer Leed573bb22019-04-10 13:49:51 -07001495 if (*indicatorLed == "Lit")
Ed Tanous66173382018-08-15 18:20:59 -07001496 {
Jennifer Leed573bb22019-04-10 13:49:51 -07001497 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.On";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001498 }
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001499 else if (*indicatorLed == "Blinking")
Ed Tanous9712f8a2018-09-21 13:38:49 -07001500 {
Gunnar Mills5c6221a2019-02-22 11:24:29 -06001501 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Blink";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001502 }
1503 else if (*indicatorLed == "Off")
1504 {
1505 dbusLedState = "xyz.openbmc_project.Led.Physical.Action.Off";
Ed Tanous66173382018-08-15 18:20:59 -07001506 }
1507 else
1508 {
Jason M. Billsa08b46c2018-11-06 15:01:08 -08001509 messages::propertyValueNotInList(res, *indicatorLed,
1510 "IndicatorLED");
Ed Tanous66173382018-08-15 18:20:59 -07001511 return;
1512 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07001513
Ed Tanous9712f8a2018-09-21 13:38:49 -07001514 // Update led group
1515 BMCWEB_LOG_DEBUG << "Update led group.";
1516 crow::connections::systemBus->async_method_call(
Santosh Puranikcde19e52019-02-20 00:10:56 +05301517 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001518 if (ec)
1519 {
1520 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001521 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001522 return;
1523 }
1524 BMCWEB_LOG_DEBUG << "Led group update done.";
1525 },
1526 "xyz.openbmc_project.LED.GroupManager",
1527 "/xyz/openbmc_project/led/groups/enclosure_identify",
1528 "org.freedesktop.DBus.Properties", "Set",
1529 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousabf2add2019-01-22 16:40:12 -08001530 std::variant<bool>(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001531 (dbusLedState !=
1532 "xyz.openbmc_project.Led.Physical.Action.Off")));
1533
Ed Tanous9712f8a2018-09-21 13:38:49 -07001534 // Update identify led status
1535 BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
1536 crow::connections::systemBus->async_method_call(
Johnathan Mantey265c1602019-08-08 11:02:51 -07001537 [asyncResp](const boost::system::error_code ec) {
Ed Tanous9712f8a2018-09-21 13:38:49 -07001538 if (ec)
1539 {
1540 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -07001541 messages::internalError(asyncResp->res);
Ed Tanous9712f8a2018-09-21 13:38:49 -07001542 return;
1543 }
1544 BMCWEB_LOG_DEBUG << "Led state update done.";
Ed Tanous9712f8a2018-09-21 13:38:49 -07001545 },
1546 "xyz.openbmc_project.LED.Controller.identify",
1547 "/xyz/openbmc_project/led/physical/identify",
1548 "org.freedesktop.DBus.Properties", "Set",
1549 "xyz.openbmc_project.Led.Physical", "State",
Ed Tanousabf2add2019-01-22 16:40:12 -08001550 std::variant<std::string>(dbusLedState));
Ed Tanous1abe55e2018-09-05 08:30:59 -07001551 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001552 }
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02001553};
Ed Tanous1abe55e2018-09-05 08:30:59 -07001554} // namespace redfish