blob: 4d37f5ec8e7459e293ecf7125bebcde384f3f2e3 [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
Jonathan Doman1e1e5982021-06-11 09:36:17 -070018#include "dbus_singleton.hpp"
James Feistb49ac872019-05-21 15:12:01 -070019#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080020#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080021#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070022#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080023#include "redfish_util.hpp"
24
John Edward Broadbent7e860f12021-04-08 15:57:16 -070025#include <app.hpp>
Ed Tanous9712f8a2018-09-21 13:38:49 -070026#include <boost/container/flat_map.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -080027#include <dbus_utility.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070028#include <registries/privilege_registry.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070029#include <sdbusplus/asio/property.hpp>
Andrew Geisslercb7e1e72019-02-19 13:05:38 -060030#include <utils/fw_utils.hpp>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020031#include <utils/json_utils.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050032
Ed Tanousabf2add2019-01-22 16:40:12 -080033#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020034
Ed Tanous1abe55e2018-09-05 08:30:59 -070035namespace redfish
36{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020037
Alpana Kumari9d3ae102019-04-12 06:49:32 -050038/**
39 * @brief Updates the Functional State of DIMMs
40 *
41 * @param[in] aResp Shared pointer for completing asynchronous calls
42 * @param[in] dimmState Dimm's Functional state, true/false
43 *
44 * @return None.
45 */
zhanghch058d1b46d2021-04-01 11:18:24 +080046inline void
47 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070048 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050049{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070050 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050051
Gunnar Mills4e0453b2020-07-08 14:00:30 -050052 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050053 // Update STATE only if previous State was DISABLED and current Dimm is
54 // ENABLED.
Gunnar Mills1214b7e2020-06-04 10:11:30 -050055 nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050056 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
57 if (prevMemSummary == "Disabled")
58 {
Ed Tanouse05aec52022-01-25 10:28:56 -080059 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050060 {
61 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
62 "Enabled";
63 }
64 }
65}
66
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050067/*
68 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
69 *
70 * @param[in] aResp Shared pointer for completing asynchronous calls
71 * @param[in] cpuPresenceState CPU present or not
72 *
73 * @return None.
74 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070075inline void
76 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
77 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050078{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070079 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050080
Ed Tanous55f79e62022-01-25 11:26:16 -080081 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050082 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050083 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080084 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080085 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050086 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080087 if (procCountPtr != nullptr)
88 {
89 // shouldn't be possible to be nullptr
90 *procCountPtr += 1;
91 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093}
94
95/*
96 * @brief Update "ProcessorSummary" "Status" "State" based on
97 * CPU Functional State
98 *
99 * @param[in] aResp Shared pointer for completing asynchronous calls
100 * @param[in] cpuFunctionalState is CPU functional true/false
101 *
102 * @return None.
103 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700104inline void
105 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
106 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500107{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700108 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500109
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500110 nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500111 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
112
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500113 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500114 // Update STATE only if previous State was Non_Functional and current CPU is
115 // Functional.
116 if (prevProcState == "Disabled")
117 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800118 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500119 {
120 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
121 "Enabled";
122 }
123 }
124}
125
Ed Tanousb9d36b42022-02-26 21:42:46 -0800126inline void
127 getProcessorProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
128 const std::string& service, const std::string& path,
129 const dbus::utility::DBusPropertiesMap& properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500130{
131
132 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
133
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700134 auto getCpuPresenceState = [aResp](const boost::system::error_code ec3,
135 const bool cpuPresenceCheck) {
136 if (ec3)
137 {
138 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
139 return;
140 }
141 modifyCpuPresenceState(aResp, cpuPresenceCheck);
142 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500143
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700144 auto getCpuFunctionalState = [aResp](const boost::system::error_code ec3,
145 const bool cpuFunctionalCheck) {
146 if (ec3)
147 {
148 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
149 return;
150 }
151 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
152 };
Ali Ahmed03fbed92021-09-03 02:33:43 -0500153
154 // Get the Presence of CPU
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700155 sdbusplus::asio::getProperty<bool>(
156 *crow::connections::systemBus, service, path,
157 "xyz.openbmc_project.Inventory.Item", "Present",
158 std::move(getCpuPresenceState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
160 // Get the Functional State
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700161 sdbusplus::asio::getProperty<bool>(
162 *crow::connections::systemBus, service, path,
163 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
164 std::move(getCpuFunctionalState));
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
166 for (const auto& property : properties)
167 {
168
169 // TODO: Get Model
170
171 // Get CoreCount
172 if (property.first == "CoreCount")
173 {
174
175 // Get CPU CoreCount and add it to the total
176 const uint16_t* coreCountVal =
177 std::get_if<uint16_t>(&property.second);
178
Ed Tanouse662eae2022-01-25 10:39:19 -0800179 if (coreCountVal == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500180 {
181 messages::internalError(aResp->res);
182 return;
183 }
184
185 nlohmann::json& coreCount =
186 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
187 uint64_t* coreCountPtr = coreCount.get_ptr<uint64_t*>();
188
189 if (coreCountPtr == nullptr)
190 {
191 coreCount = 0;
192 }
193 else
194 {
195 *coreCountPtr += *coreCountVal;
196 }
197 }
198 }
199}
200
201/*
202 * @brief Get ProcessorSummary fields
203 *
204 * @param[in] aResp Shared pointer for completing asynchronous calls
205 * @param[in] service dbus service for Cpu Information
206 * @param[in] path dbus path for Cpu
207 *
208 * @return None.
209 */
210inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
211 const std::string& service,
212 const std::string& path)
213{
214
215 crow::connections::systemBus->async_method_call(
216 [aResp, service,
217 path](const boost::system::error_code ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800218 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700219 if (ec2)
220 {
221 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
222 messages::internalError(aResp->res);
223 return;
224 }
225 getProcessorProperties(aResp, service, path, properties);
Ali Ahmed03fbed92021-09-03 02:33:43 -0500226 },
227 service, path, "org.freedesktop.DBus.Properties", "GetAll",
228 "xyz.openbmc_project.Inventory.Item.Cpu");
229}
230
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500231/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700232 * @brief Retrieves computer system properties over dbus
233 *
234 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500235 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700236 *
237 * @return None.
238 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700239inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800240 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700241 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700242{
Ed Tanous6c34de42018-08-29 13:37:36 -0700243 BMCWEB_LOG_DEBUG << "Get available system components.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500244
Ed Tanous6c34de42018-08-29 13:37:36 -0700245 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -0800246 [aResp,
247 systemHealth](const boost::system::error_code ec,
248 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700249 if (ec)
250 {
251 BMCWEB_LOG_DEBUG << "DBUS response error";
252 messages::internalError(aResp->res);
253 return;
254 }
255 // Iterate over all retrieved ObjectPaths.
256 for (const std::pair<
257 std::string,
258 std::vector<std::pair<std::string, std::vector<std::string>>>>&
259 object : subtree)
260 {
261 const std::string& path = object.first;
262 BMCWEB_LOG_DEBUG << "Got path: " << path;
263 const std::vector<std::pair<std::string, std::vector<std::string>>>&
264 connectionNames = object.second;
265 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700266 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700267 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700268 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700269
270 auto memoryHealth = std::make_shared<HealthPopulate>(
271 aResp, "/MemorySummary/Status"_json_pointer);
272
273 auto cpuHealth = std::make_shared<HealthPopulate>(
274 aResp, "/ProcessorSummary/Status"_json_pointer);
275
276 systemHealth->children.emplace_back(memoryHealth);
277 systemHealth->children.emplace_back(cpuHealth);
278
279 // This is not system, so check if it's cpu, dimm, UUID or
280 // BiosVer
281 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700282 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700283 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700284 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700285 if (interfaceName ==
286 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700287 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700288 BMCWEB_LOG_DEBUG
289 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500290
Ed Tanous002d39b2022-05-31 08:59:27 -0700291 crow::connections::systemBus->async_method_call(
292 [aResp, service{connection.first},
293 path](const boost::system::error_code ec2,
294 const dbus::utility::DBusPropertiesMap&
295 properties) {
296 if (ec2)
297 {
298 BMCWEB_LOG_ERROR << "DBUS response error "
299 << ec2;
300 messages::internalError(aResp->res);
301 return;
302 }
303 BMCWEB_LOG_DEBUG << "Got " << properties.size()
304 << " Dimm properties.";
305
306 if (!properties.empty())
307 {
308 for (const std::pair<
309 std::string,
310 dbus::utility::DbusVariantType>&
311 property : properties)
312 {
313 if (property.first != "MemorySizeInKB")
Ed Tanous029573d2019-02-01 10:57:49 -0800314 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700315 continue;
Ed Tanous029573d2019-02-01 10:57:49 -0800316 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700317 const uint32_t* value =
318 std::get_if<uint32_t>(&property.second);
319 if (value == nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800320 {
321 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -0700322 << "Find incorrect type of MemorySize";
323 continue;
324 }
325 nlohmann::json& totalMemory =
326 aResp->res
327 .jsonValue["MemorySummary"]
328 ["TotalSystemMemoryGiB"];
329 uint64_t* preValue =
330 totalMemory.get_ptr<uint64_t*>();
331 if (preValue == nullptr)
332 {
333 continue;
334 }
335 aResp->res
336 .jsonValue["MemorySummary"]
337 ["TotalSystemMemoryGiB"] =
338 *value / (1024 * 1024) + *preValue;
339 aResp->res.jsonValue["MemorySummary"]
340 ["Status"]["State"] =
341 "Enabled";
342 }
343 }
344 else
345 {
346 sdbusplus::asio::getProperty<bool>(
347 *crow::connections::systemBus, service,
348 path,
349 "xyz.openbmc_project.State."
350 "Decorator.OperationalStatus",
351 "Functional",
352 [aResp](const boost::system::error_code ec3,
353 bool dimmState) {
354 if (ec3)
355 {
356 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000357 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800358 return;
359 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700360 updateDimmProperties(aResp, dimmState);
361 });
362 }
363 },
364 connection.first, path,
365 "org.freedesktop.DBus.Properties", "GetAll",
366 "xyz.openbmc_project.Inventory.Item.Dimm");
367
368 memoryHealth->inventory.emplace_back(path);
369 }
370 else if (interfaceName ==
371 "xyz.openbmc_project.Inventory.Item.Cpu")
372 {
373 BMCWEB_LOG_DEBUG
374 << "Found Cpu, now get its properties.";
375
376 getProcessorSummary(aResp, connection.first, path);
377
378 cpuHealth->inventory.emplace_back(path);
379 }
380 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
381 {
382 BMCWEB_LOG_DEBUG
383 << "Found UUID, now get its properties.";
384 crow::connections::systemBus->async_method_call(
385 [aResp](const boost::system::error_code ec3,
386 const dbus::utility::DBusPropertiesMap&
387 properties) {
388 if (ec3)
389 {
390 BMCWEB_LOG_DEBUG << "DBUS response error "
391 << ec3;
392 messages::internalError(aResp->res);
393 return;
394 }
395 BMCWEB_LOG_DEBUG << "Got " << properties.size()
396 << " UUID properties.";
397 for (const std::pair<
398 std::string,
399 dbus::utility::DbusVariantType>& property :
400 properties)
401 {
402 if (property.first == "UUID")
403 {
404 const std::string* value =
405 std::get_if<std::string>(
406 &property.second);
407
408 if (value != nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800409 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700410 std::string valueStr = *value;
411 if (valueStr.size() == 32)
Ed Tanous029573d2019-02-01 10:57:49 -0800412 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700413 valueStr.insert(8, 1, '-');
414 valueStr.insert(13, 1, '-');
415 valueStr.insert(18, 1, '-');
416 valueStr.insert(23, 1, '-');
Ed Tanous6c34de42018-08-29 13:37:36 -0700417 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700418 BMCWEB_LOG_DEBUG << "UUID = "
419 << valueStr;
420 aResp->res.jsonValue["UUID"] = valueStr;
Ed Tanous029573d2019-02-01 10:57:49 -0800421 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700422 }
423 }
424 },
425 connection.first, path,
426 "org.freedesktop.DBus.Properties", "GetAll",
427 "xyz.openbmc_project.Common.UUID");
428 }
429 else if (interfaceName ==
430 "xyz.openbmc_project.Inventory.Item.System")
431 {
432 crow::connections::systemBus->async_method_call(
433 [aResp](const boost::system::error_code ec2,
434 const dbus::utility::DBusPropertiesMap&
435 propertiesList) {
436 if (ec2)
437 {
438 // doesn't have to include this
439 // interface
440 return;
441 }
442 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
443 << " properties for system";
444 for (const std::pair<
445 std::string,
446 dbus::utility::DbusVariantType>& property :
447 propertiesList)
448 {
449 const std::string& propertyName =
450 property.first;
451 if ((propertyName == "PartNumber") ||
452 (propertyName == "SerialNumber") ||
453 (propertyName == "Manufacturer") ||
454 (propertyName == "Model") ||
455 (propertyName == "SubModel"))
456 {
457 const std::string* value =
458 std::get_if<std::string>(
459 &property.second);
460 if (value != nullptr)
Ed Tanous029573d2019-02-01 10:57:49 -0800461 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700462 aResp->res.jsonValue[propertyName] =
463 *value;
Ed Tanous029573d2019-02-01 10:57:49 -0800464 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700465 }
466 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500467
Ed Tanous002d39b2022-05-31 08:59:27 -0700468 // Grab the bios version
469 fw_util::populateFirmwareInformation(
470 aResp, fw_util::biosPurpose, "BiosVersion",
471 false);
472 },
473 connection.first, path,
474 "org.freedesktop.DBus.Properties", "GetAll",
475 "xyz.openbmc_project.Inventory.Decorator.Asset");
James Feiste4a4b9a2019-06-20 14:08:07 -0700476
Ed Tanous002d39b2022-05-31 08:59:27 -0700477 sdbusplus::asio::getProperty<std::string>(
478 *crow::connections::systemBus, connection.first,
479 path,
480 "xyz.openbmc_project.Inventory.Decorator."
481 "AssetTag",
482 "AssetTag",
483 [aResp](const boost::system::error_code ec2,
484 const std::string& value) {
485 if (ec2)
486 {
487 // doesn't have to include this
488 // interface
489 return;
490 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700491
Ed Tanous002d39b2022-05-31 08:59:27 -0700492 aResp->res.jsonValue["AssetTag"] = value;
493 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700494 }
495 }
496 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700497 }
Ed Tanous6c34de42018-08-29 13:37:36 -0700498 },
499 "xyz.openbmc_project.ObjectMapper",
500 "/xyz/openbmc_project/object_mapper",
501 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
Ed Tanous66173382018-08-15 18:20:59 -0700502 "/xyz/openbmc_project/inventory", int32_t(0),
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500503 std::array<const char*, 5>{
Ed Tanous66173382018-08-15 18:20:59 -0700504 "xyz.openbmc_project.Inventory.Decorator.Asset",
505 "xyz.openbmc_project.Inventory.Item.Cpu",
506 "xyz.openbmc_project.Inventory.Item.Dimm",
507 "xyz.openbmc_project.Inventory.Item.System",
508 "xyz.openbmc_project.Common.UUID",
509 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700510}
511
512/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700513 * @brief Retrieves host state properties over dbus
514 *
515 * @param[in] aResp Shared pointer for completing asynchronous calls.
516 *
517 * @return None.
518 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800519inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700520{
521 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700522 sdbusplus::asio::getProperty<std::string>(
523 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
524 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
525 "CurrentHostState",
Jennifer Leec5d03ff2019-03-08 15:42:58 -0800526 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700527 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700528 if (ec)
529 {
530 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700531 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700532 // Service not available, no error, just don't return
533 // host state info
534 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700535 return;
536 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700537 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
538 messages::internalError(aResp->res);
539 return;
540 }
Ed Tanous66173382018-08-15 18:20:59 -0700541
Ed Tanous002d39b2022-05-31 08:59:27 -0700542 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
543 // Verify Host State
544 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
545 {
546 aResp->res.jsonValue["PowerState"] = "On";
547 aResp->res.jsonValue["Status"]["State"] = "Enabled";
548 }
549 else if (hostState ==
550 "xyz.openbmc_project.State.Host.HostState.Quiesced")
551 {
552 aResp->res.jsonValue["PowerState"] = "On";
553 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
554 }
555 else if (hostState ==
556 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
557 {
558 aResp->res.jsonValue["PowerState"] = "On";
559 aResp->res.jsonValue["Status"]["State"] = "InTest";
560 }
561 else if (
562 hostState ==
563 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
564 {
565 aResp->res.jsonValue["PowerState"] = "PoweringOn";
566 aResp->res.jsonValue["Status"]["State"] = "Starting";
567 }
568 else if (hostState ==
569 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
570 {
571 aResp->res.jsonValue["PowerState"] = "PoweringOff";
572 aResp->res.jsonValue["Status"]["State"] = "Disabled";
573 }
574 else
575 {
576 aResp->res.jsonValue["PowerState"] = "Off";
577 aResp->res.jsonValue["Status"]["State"] = "Disabled";
578 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700579 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700580}
581
582/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500583 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530584 *
585 * @param[in] dbusSource The boot source in DBUS speak.
586 *
587 * @return Returns as a string, the boot source in Redfish terms. If translation
588 * cannot be done, returns an empty string.
589 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000590inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530591{
592 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
593 {
594 return "None";
595 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700596 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530597 {
598 return "Hdd";
599 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700600 if (dbusSource ==
601 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530602 {
603 return "Cd";
604 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700605 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530606 {
607 return "Pxe";
608 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700609 if (dbusSource ==
610 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700611 {
612 return "Usb";
613 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700614 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615}
616
617/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300618 * @brief Translates boot type DBUS property value to redfish.
619 *
620 * @param[in] dbusType The boot type in DBUS speak.
621 *
622 * @return Returns as a string, the boot type in Redfish terms. If translation
623 * cannot be done, returns an empty string.
624 */
625inline std::string dbusToRfBootType(const std::string& dbusType)
626{
627 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
628 {
629 return "Legacy";
630 }
631 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
632 {
633 return "UEFI";
634 }
635 return "";
636}
637
638/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500639 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530640 *
641 * @param[in] dbusMode The boot mode in DBUS speak.
642 *
643 * @return Returns as a string, the boot mode in Redfish terms. If translation
644 * cannot be done, returns an empty string.
645 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000646inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530647{
648 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
649 {
650 return "None";
651 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700652 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530653 {
654 return "Diags";
655 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700656 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530657 {
658 return "BiosSetup";
659 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700660 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530661}
662
663/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600664 * @brief Translates boot progress DBUS property value to redfish.
665 *
666 * @param[in] dbusBootProgress The boot progress in DBUS speak.
667 *
668 * @return Returns as a string, the boot progress in Redfish terms. If
669 * translation cannot be done, returns "None".
670 */
671inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
672{
673 // Now convert the D-Bus BootProgress to the appropriate Redfish
674 // enum
675 std::string rfBpLastState = "None";
676 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
677 "ProgressStages.Unspecified")
678 {
679 rfBpLastState = "None";
680 }
681 else if (dbusBootProgress ==
682 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
683 "PrimaryProcInit")
684 {
685 rfBpLastState = "PrimaryProcessorInitializationStarted";
686 }
687 else if (dbusBootProgress ==
688 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
689 "BusInit")
690 {
691 rfBpLastState = "BusInitializationStarted";
692 }
693 else if (dbusBootProgress ==
694 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
695 "MemoryInit")
696 {
697 rfBpLastState = "MemoryInitializationStarted";
698 }
699 else if (dbusBootProgress ==
700 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
701 "SecondaryProcInit")
702 {
703 rfBpLastState = "SecondaryProcessorInitializationStarted";
704 }
705 else if (dbusBootProgress ==
706 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
707 "PCIInit")
708 {
709 rfBpLastState = "PCIResourceConfigStarted";
710 }
711 else if (dbusBootProgress ==
712 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
713 "SystemSetup")
714 {
715 rfBpLastState = "SetupEntered";
716 }
717 else if (dbusBootProgress ==
718 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
719 "SystemInitComplete")
720 {
721 rfBpLastState = "SystemHardwareInitializationComplete";
722 }
723 else if (dbusBootProgress ==
724 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
725 "OSStart")
726 {
727 rfBpLastState = "OSBootStarted";
728 }
729 else if (dbusBootProgress ==
730 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
731 "OSRunning")
732 {
733 rfBpLastState = "OSRunning";
734 }
735 else
736 {
737 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
738 << dbusBootProgress;
739 // Just return the default
740 }
741 return rfBpLastState;
742}
743
744/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500745 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530746 *
747 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700748 * @param[out] bootSource The DBus source
749 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530750 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700751 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530752 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800753inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500754 const std::string& rfSource,
755 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530756{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300757 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
758 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700759
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530760 if (rfSource == "None")
761 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700762 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530763 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700764 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530765 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
767 }
768 else if (rfSource == "Hdd")
769 {
770 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
771 }
772 else if (rfSource == "Diags")
773 {
774 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
775 }
776 else if (rfSource == "Cd")
777 {
778 bootSource =
779 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
780 }
781 else if (rfSource == "BiosSetup")
782 {
783 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530784 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700785 else if (rfSource == "Usb")
786 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700787 bootSource =
788 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700789 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530790 else
791 {
George Liu0fda0f12021-11-16 10:06:17 +0800792 BMCWEB_LOG_DEBUG
793 << "Invalid property value for BootSourceOverrideTarget: "
794 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700795 messages::propertyValueNotInList(aResp->res, rfSource,
796 "BootSourceTargetOverride");
797 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530798 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700799 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530800}
Ali Ahmed19817712021-06-29 17:01:52 -0500801
Andrew Geissler978b8802020-11-19 13:36:40 -0600802/**
803 * @brief Retrieves boot progress of the system
804 *
805 * @param[in] aResp Shared pointer for generating response message.
806 *
807 * @return None.
808 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800809inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600810{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700811 sdbusplus::asio::getProperty<std::string>(
812 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
813 "/xyz/openbmc_project/state/host0",
814 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Andrew Geissler978b8802020-11-19 13:36:40 -0600815 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700816 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700817 if (ec)
818 {
819 // BootProgress is an optional object so just do nothing if
820 // not found
821 return;
822 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600823
Ed Tanous002d39b2022-05-31 08:59:27 -0700824 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600825
Ed Tanous002d39b2022-05-31 08:59:27 -0700826 aResp->res.jsonValue["BootProgress"]["LastState"] =
827 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700828 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600829}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530830
831/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300832 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300833 *
834 * @param[in] aResp Shared pointer for generating response message.
835 *
836 * @return None.
837 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300838
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300839inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300840{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700841 sdbusplus::asio::getProperty<std::string>(
842 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
843 "/xyz/openbmc_project/control/host0/boot",
844 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300845 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700846 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700847 if (ec)
848 {
849 // not an error, don't have to have the interface
850 return;
851 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300852
Ed Tanous002d39b2022-05-31 08:59:27 -0700853 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300854
Ed Tanous002d39b2022-05-31 08:59:27 -0700855 aResp->res.jsonValue["Boot"]
856 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
857 {"Legacy", "UEFI"};
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300858
Ed Tanous002d39b2022-05-31 08:59:27 -0700859 auto rfType = dbusToRfBootType(bootType);
860 if (rfType.empty())
861 {
862 messages::internalError(aResp->res);
863 return;
864 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300865
Ed Tanous002d39b2022-05-31 08:59:27 -0700866 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700867 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868}
869
870/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300871 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530872 *
873 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530874 *
875 * @return None.
876 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300877
878inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530879{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700880 sdbusplus::asio::getProperty<std::string>(
881 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
882 "/xyz/openbmc_project/control/host0/boot",
883 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300884 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700885 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700886 if (ec)
887 {
888 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
889 messages::internalError(aResp->res);
890 return;
891 }
892
893 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
894
895 aResp->res
896 .jsonValue["Boot"]
897 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
898 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
899
900 if (bootModeStr !=
901 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
902 {
903 auto rfMode = dbusToRfBootMode(bootModeStr);
904 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530905 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700906 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
907 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700909 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700910 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530911}
912
913/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300914 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530915 *
916 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530917 *
918 * @return None.
919 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300920
921inline void
922 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700924 sdbusplus::asio::getProperty<std::string>(
925 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
926 "/xyz/openbmc_project/control/host0/boot",
927 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300928 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700929 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700930 if (ec)
931 {
932 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
933 messages::internalError(aResp->res);
934 return;
935 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530936
Ed Tanous002d39b2022-05-31 08:59:27 -0700937 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938
Ed Tanous002d39b2022-05-31 08:59:27 -0700939 auto rfSource = dbusToRfBootSource(bootSourceStr);
940 if (!rfSource.empty())
941 {
942 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
943 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300944
Ed Tanous002d39b2022-05-31 08:59:27 -0700945 // Get BootMode as BootSourceOverrideTarget is constructed
946 // from both BootSource and BootMode
947 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700948 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530949}
950
951/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300952 * @brief This functions abstracts all the logic behind getting a
953 * "BootSourceOverrideEnabled" property from an overall boot override enable
954 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530955 *
956 * @param[in] aResp Shared pointer for generating response message.
957 *
958 * @return None.
959 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530960
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300961inline void
962 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
963 const bool bootOverrideEnableSetting)
964{
965 if (!bootOverrideEnableSetting)
966 {
967 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
968 return;
969 }
970
971 // If boot source override is enabled, we need to check 'one_time'
972 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700973 sdbusplus::asio::getProperty<bool>(
974 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
975 "/xyz/openbmc_project/control/host0/boot/one_time",
976 "xyz.openbmc_project.Object.Enable", "Enabled",
977 [aResp](const boost::system::error_code ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700978 if (ec)
979 {
980 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
981 messages::internalError(aResp->res);
982 return;
983 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530984
Ed Tanous002d39b2022-05-31 08:59:27 -0700985 if (oneTimeSetting)
986 {
987 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
988 }
989 else
990 {
991 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
992 "Continuous";
993 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700994 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530995}
996
997/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300998 * @brief Retrieves boot override enable over DBUS
999 *
1000 * @param[in] aResp Shared pointer for generating response message.
1001 *
1002 * @return None.
1003 */
1004
1005inline void
1006 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1007{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001008 sdbusplus::asio::getProperty<bool>(
1009 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1010 "/xyz/openbmc_project/control/host0/boot",
1011 "xyz.openbmc_project.Object.Enable", "Enabled",
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001012 [aResp](const boost::system::error_code ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001013 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001014 if (ec)
1015 {
1016 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1017 messages::internalError(aResp->res);
1018 return;
1019 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001020
Ed Tanous002d39b2022-05-31 08:59:27 -07001021 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001022 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001023}
1024
1025/**
1026 * @brief Retrieves boot source override properties
1027 *
1028 * @param[in] aResp Shared pointer for generating response message.
1029 *
1030 * @return None.
1031 */
1032inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1033{
1034 BMCWEB_LOG_DEBUG << "Get boot information.";
1035
1036 getBootOverrideSource(aResp);
1037 getBootOverrideType(aResp);
1038 getBootOverrideEnable(aResp);
1039}
1040
1041/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001042 * @brief Retrieves the Last Reset Time
1043 *
1044 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1045 * and power off. Even though this is the "system" Redfish object look at the
1046 * chassis D-Bus interface for the LastStateChangeTime since this has the
1047 * last power operation time.
1048 *
1049 * @param[in] aResp Shared pointer for generating response message.
1050 *
1051 * @return None.
1052 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001053inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001054{
1055 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1056
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001057 sdbusplus::asio::getProperty<uint64_t>(
1058 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1059 "/xyz/openbmc_project/state/chassis0",
1060 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
1061 [aResp](const boost::system::error_code ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001062 if (ec)
1063 {
1064 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1065 return;
1066 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001067
Ed Tanous002d39b2022-05-31 08:59:27 -07001068 // LastStateChangeTime is epoch time, in milliseconds
1069 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1070 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001071
Ed Tanous002d39b2022-05-31 08:59:27 -07001072 // Convert to ISO 8601 standard
1073 aResp->res.jsonValue["LastResetTime"] =
1074 crow::utility::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001075 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001076}
1077
1078/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001079 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1080 *
1081 * @param[in] aResp Shared pointer for generating response message.
1082 *
1083 * @return None.
1084 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001085inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001086{
1087 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1088
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001089 sdbusplus::asio::getProperty<bool>(
1090 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1091 "/xyz/openbmc_project/control/host0/auto_reboot",
1092 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
1093 [aResp](const boost::system::error_code ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001094 if (ec)
1095 {
1096 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1097 return;
1098 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001099
Ed Tanous002d39b2022-05-31 08:59:27 -07001100 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1101 if (autoRebootEnabled)
1102 {
1103 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1104 "RetryAttempts";
1105 // If AutomaticRetry (AutoReboot) is enabled see how many
1106 // attempts are left
1107 sdbusplus::asio::getProperty<uint32_t>(
1108 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1109 "/xyz/openbmc_project/state/host0",
1110 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1111 "AttemptsLeft",
1112 [aResp](const boost::system::error_code ec2,
1113 const uint32_t autoRebootAttemptsLeft) {
1114 if (ec2)
1115 {
1116 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1117 return;
1118 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001119
Ed Tanous002d39b2022-05-31 08:59:27 -07001120 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1121 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001122
Ed Tanous002d39b2022-05-31 08:59:27 -07001123 aResp->res
1124 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1125 autoRebootAttemptsLeft;
1126 });
1127 }
1128 else
1129 {
1130 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1131 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001132
Ed Tanous002d39b2022-05-31 08:59:27 -07001133 // Not on D-Bus. Hardcoded here:
1134 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1135 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001136
Ed Tanous002d39b2022-05-31 08:59:27 -07001137 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1138 // and RetryAttempts. OpenBMC only supports Disabled and
1139 // RetryAttempts.
1140 aResp->res.jsonValue["Boot"]
1141 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1142 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001143 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001144}
1145
1146/**
George Liuc6a620f2020-04-10 17:18:11 +08001147 * @brief Retrieves power restore policy over DBUS.
1148 *
1149 * @param[in] aResp Shared pointer for generating response message.
1150 *
1151 * @return None.
1152 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001153inline void
1154 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001155{
1156 BMCWEB_LOG_DEBUG << "Get power restore policy";
1157
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001158 sdbusplus::asio::getProperty<std::string>(
1159 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1160 "/xyz/openbmc_project/control/host0/power_restore_policy",
1161 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
1162 [aResp](const boost::system::error_code ec, const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001163 if (ec)
1164 {
1165 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1166 return;
1167 }
George Liuc6a620f2020-04-10 17:18:11 +08001168
Ed Tanous002d39b2022-05-31 08:59:27 -07001169 const boost::container::flat_map<std::string, std::string> policyMaps = {
1170 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1171 "AlwaysOn"},
1172 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1173 "AlwaysOff"},
1174 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1175 "LastState"},
1176 // Return `AlwaysOff` when power restore policy set to "None"
1177 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1178 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001179
Ed Tanous002d39b2022-05-31 08:59:27 -07001180 auto policyMapsIt = policyMaps.find(policy);
1181 if (policyMapsIt == policyMaps.end())
1182 {
1183 messages::internalError(aResp->res);
1184 return;
1185 }
George Liuc6a620f2020-04-10 17:18:11 +08001186
Ed Tanous002d39b2022-05-31 08:59:27 -07001187 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001188 });
George Liuc6a620f2020-04-10 17:18:11 +08001189}
1190
1191/**
Ali Ahmed19817712021-06-29 17:01:52 -05001192 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1193 * TPM is required for booting the host.
1194 *
1195 * @param[in] aResp Shared pointer for generating response message.
1196 *
1197 * @return None.
1198 */
1199inline void getTrustedModuleRequiredToBoot(
1200 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1201{
1202 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
1203
1204 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001205 [aResp](const boost::system::error_code ec,
1206 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001207 if (ec)
1208 {
1209 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1210 << ec;
1211 // This is an optional D-Bus object so just return if
1212 // error occurs
1213 return;
1214 }
1215 if (subtree.empty())
1216 {
1217 // As noted above, this is an optional interface so just return
1218 // if there is no instance found
1219 return;
1220 }
1221
1222 /* When there is more than one TPMEnable object... */
1223 if (subtree.size() > 1)
1224 {
1225 BMCWEB_LOG_DEBUG
1226 << "DBUS response has more than 1 TPM Enable object:"
1227 << subtree.size();
1228 // Throw an internal Error and return
1229 messages::internalError(aResp->res);
1230 return;
1231 }
1232
1233 // Make sure the Dbus response map has a service and objectPath
1234 // field
1235 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1236 {
1237 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1238 messages::internalError(aResp->res);
1239 return;
1240 }
1241
1242 const std::string& path = subtree[0].first;
1243 const std::string& serv = subtree[0].second.begin()->first;
1244
1245 // Valid TPM Enable object found, now reading the current value
1246 sdbusplus::asio::getProperty<bool>(
1247 *crow::connections::systemBus, serv, path,
1248 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1249 [aResp](const boost::system::error_code ec, bool tpmRequired) {
Ali Ahmed19817712021-06-29 17:01:52 -05001250 if (ec)
1251 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001252 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
1253 << ec;
Ali Ahmed19817712021-06-29 17:01:52 -05001254 messages::internalError(aResp->res);
1255 return;
1256 }
1257
Ed Tanous002d39b2022-05-31 08:59:27 -07001258 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001259 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001260 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1261 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001262 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001263 else
1264 {
1265 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1266 "Disabled";
1267 }
1268 });
Ali Ahmed19817712021-06-29 17:01:52 -05001269 },
1270 "xyz.openbmc_project.ObjectMapper",
1271 "/xyz/openbmc_project/object_mapper",
1272 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1273 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1274}
1275
1276/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001277 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1278 * TPM is required for booting the host.
1279 *
1280 * @param[in] aResp Shared pointer for generating response message.
1281 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1282 *
1283 * @return None.
1284 */
1285inline void setTrustedModuleRequiredToBoot(
1286 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1287{
1288 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
1289
1290 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001291 [aResp, tpmRequired](const boost::system::error_code ec,
1292 dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001293 if (ec)
1294 {
1295 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1296 << ec;
1297 messages::internalError(aResp->res);
1298 return;
1299 }
1300 if (subtree.empty())
1301 {
1302 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1303 "TrustedModuleRequiredToBoot");
1304 return;
1305 }
1306
1307 /* When there is more than one TPMEnable object... */
1308 if (subtree.size() > 1)
1309 {
1310 BMCWEB_LOG_DEBUG
1311 << "DBUS response has more than 1 TPM Enable object:"
1312 << subtree.size();
1313 // Throw an internal Error and return
1314 messages::internalError(aResp->res);
1315 return;
1316 }
1317
1318 // Make sure the Dbus response map has a service and objectPath
1319 // field
1320 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1321 {
1322 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1323 messages::internalError(aResp->res);
1324 return;
1325 }
1326
1327 const std::string& path = subtree[0].first;
1328 const std::string& serv = subtree[0].second.begin()->first;
1329
1330 if (serv.empty())
1331 {
1332 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1333 messages::internalError(aResp->res);
1334 return;
1335 }
1336
1337 // Valid TPM Enable object found, now setting the value
1338 crow::connections::systemBus->async_method_call(
1339 [aResp](const boost::system::error_code ec) {
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001340 if (ec)
1341 {
1342 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001343 << "DBUS response error: Set TrustedModuleRequiredToBoot"
1344 << ec;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001345 messages::internalError(aResp->res);
1346 return;
1347 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001348 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1349 },
1350 serv, path, "org.freedesktop.DBus.Properties", "Set",
1351 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1352 dbus::utility::DbusVariantType(tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001353 },
1354 "xyz.openbmc_project.ObjectMapper",
1355 "/xyz/openbmc_project/object_mapper",
1356 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1357 std::array<const char*, 1>{"xyz.openbmc_project.Control.TPM.Policy"});
1358}
1359
1360/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301361 * @brief Sets boot properties into DBUS object(s).
1362 *
1363 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001364 * @param[in] bootType The boot type to set.
1365 * @return Integer error code.
1366 */
1367inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001368 const std::optional<std::string>& bootType)
1369{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001370 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001371
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001372 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001373 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001374 return;
1375 }
1376
1377 // Source target specified
1378 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1379 // Figure out which DBUS interface and property to use
1380 if (*bootType == "Legacy")
1381 {
1382 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1383 }
1384 else if (*bootType == "UEFI")
1385 {
1386 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1387 }
1388 else
1389 {
1390 BMCWEB_LOG_DEBUG << "Invalid property value for "
1391 "BootSourceOverrideMode: "
1392 << *bootType;
1393 messages::propertyValueNotInList(aResp->res, *bootType,
1394 "BootSourceOverrideMode");
1395 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001396 }
1397
1398 // Act on validated parameters
1399 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1400
1401 crow::connections::systemBus->async_method_call(
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001402 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001403 if (ec)
1404 {
1405 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1406 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001407 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001408 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001409 return;
1410 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001411 messages::internalError(aResp->res);
1412 return;
1413 }
1414 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001415 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001416 "xyz.openbmc_project.Settings",
1417 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001418 "org.freedesktop.DBus.Properties", "Set",
1419 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001420 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001421}
1422
1423/**
1424 * @brief Sets boot properties into DBUS object(s).
1425 *
1426 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001427 * @param[in] bootType The boot type to set.
1428 * @return Integer error code.
1429 */
1430inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1431 const std::optional<std::string>& bootEnable)
1432{
1433 if (!bootEnable)
1434 {
1435 return;
1436 }
1437 // Source target specified
1438 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1439
1440 bool bootOverrideEnable = false;
1441 bool bootOverridePersistent = false;
1442 // Figure out which DBUS interface and property to use
1443 if (*bootEnable == "Disabled")
1444 {
1445 bootOverrideEnable = false;
1446 }
1447 else if (*bootEnable == "Once")
1448 {
1449 bootOverrideEnable = true;
1450 bootOverridePersistent = false;
1451 }
1452 else if (*bootEnable == "Continuous")
1453 {
1454 bootOverrideEnable = true;
1455 bootOverridePersistent = true;
1456 }
1457 else
1458 {
George Liu0fda0f12021-11-16 10:06:17 +08001459 BMCWEB_LOG_DEBUG
1460 << "Invalid property value for BootSourceOverrideEnabled: "
1461 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001462 messages::propertyValueNotInList(aResp->res, *bootEnable,
1463 "BootSourceOverrideEnabled");
1464 return;
1465 }
1466
1467 // Act on validated parameters
1468 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1469
1470 crow::connections::systemBus->async_method_call(
1471 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001472 if (ec)
1473 {
1474 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1475 messages::internalError(aResp->res);
1476 return;
1477 }
1478 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001479 },
1480 "xyz.openbmc_project.Settings",
1481 "/xyz/openbmc_project/control/host0/boot",
1482 "org.freedesktop.DBus.Properties", "Set",
1483 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001484 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001485
1486 if (!bootOverrideEnable)
1487 {
1488 return;
1489 }
1490
1491 // In case boot override is enabled we need to set correct value for the
1492 // 'one_time' enable DBus interface
1493 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1494 << bootOverridePersistent;
1495
1496 crow::connections::systemBus->async_method_call(
1497 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001498 if (ec)
1499 {
1500 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1501 messages::internalError(aResp->res);
1502 return;
1503 }
1504 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001505 },
1506 "xyz.openbmc_project.Settings",
1507 "/xyz/openbmc_project/control/host0/boot/one_time",
1508 "org.freedesktop.DBus.Properties", "Set",
1509 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001510 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001511}
1512
1513/**
1514 * @brief Sets boot properties into DBUS object(s).
1515 *
1516 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301517 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301518 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001519 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301520 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001521inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001522 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301523{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001524 std::string bootSourceStr;
1525 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001526
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001527 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301528 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001529 return;
1530 }
1531
1532 // Source target specified
1533 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1534 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001535 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1536 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001537 {
1538 BMCWEB_LOG_DEBUG
1539 << "Invalid property value for BootSourceOverrideTarget: "
1540 << *bootSource;
1541 messages::propertyValueNotInList(aResp->res, *bootSource,
1542 "BootSourceTargetOverride");
1543 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001544 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301545
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001546 // Act on validated parameters
1547 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1548 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001549
1550 crow::connections::systemBus->async_method_call(
1551 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001552 if (ec)
1553 {
1554 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1555 messages::internalError(aResp->res);
1556 return;
1557 }
1558 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001559 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001560 "xyz.openbmc_project.Settings",
1561 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001562 "org.freedesktop.DBus.Properties", "Set",
1563 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001564 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001565
1566 crow::connections::systemBus->async_method_call(
1567 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001568 if (ec)
1569 {
1570 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1571 messages::internalError(aResp->res);
1572 return;
1573 }
1574 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001575 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001576 "xyz.openbmc_project.Settings",
1577 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001578 "org.freedesktop.DBus.Properties", "Set",
1579 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001580 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001581}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001582
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001583/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001584 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301585 *
1586 * @param[in] aResp Shared pointer for generating response message.
1587 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001588 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301589 * @param[in] bootEnable The boot override enable from incoming RF request.
1590 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001591 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301592 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001593
1594inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1595 const std::optional<std::string>& bootSource,
1596 const std::optional<std::string>& bootType,
1597 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301598{
1599 BMCWEB_LOG_DEBUG << "Set boot information.";
1600
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001601 setBootModeOrSource(aResp, bootSource);
1602 setBootType(aResp, bootType);
1603 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301604}
1605
George Liuc6a620f2020-04-10 17:18:11 +08001606/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001607 * @brief Sets AssetTag
1608 *
1609 * @param[in] aResp Shared pointer for generating response message.
1610 * @param[in] assetTag "AssetTag" from request.
1611 *
1612 * @return None.
1613 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001614inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001615 const std::string& assetTag)
1616{
1617 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001618 [aResp,
1619 assetTag](const boost::system::error_code ec,
1620 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001621 if (ec)
1622 {
1623 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1624 messages::internalError(aResp->res);
1625 return;
1626 }
1627 if (subtree.empty())
1628 {
1629 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1630 messages::internalError(aResp->res);
1631 return;
1632 }
1633 // Assume only 1 system D-Bus object
1634 // Throw an error if there is more than 1
1635 if (subtree.size() > 1)
1636 {
1637 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1638 messages::internalError(aResp->res);
1639 return;
1640 }
1641 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1642 {
1643 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1644 messages::internalError(aResp->res);
1645 return;
1646 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001647
Ed Tanous002d39b2022-05-31 08:59:27 -07001648 const std::string& path = subtree[0].first;
1649 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001650
Ed Tanous002d39b2022-05-31 08:59:27 -07001651 if (service.empty())
1652 {
1653 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1654 messages::internalError(aResp->res);
1655 return;
1656 }
1657
1658 crow::connections::systemBus->async_method_call(
1659 [aResp](const boost::system::error_code ec2) {
1660 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001661 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001662 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1663 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001664 messages::internalError(aResp->res);
1665 return;
1666 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001667 },
1668 service, path, "org.freedesktop.DBus.Properties", "Set",
1669 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1670 dbus::utility::DbusVariantType(assetTag));
Gunnar Mills98e386e2020-10-30 14:58:09 -05001671 },
1672 "xyz.openbmc_project.ObjectMapper",
1673 "/xyz/openbmc_project/object_mapper",
1674 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
1675 "/xyz/openbmc_project/inventory", int32_t(0),
1676 std::array<const char*, 1>{
1677 "xyz.openbmc_project.Inventory.Item.System"});
1678}
1679
1680/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001681 * @brief Sets automaticRetry (Auto Reboot)
1682 *
1683 * @param[in] aResp Shared pointer for generating response message.
1684 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1685 *
1686 * @return None.
1687 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001688inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001689 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001690{
1691 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1692
1693 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001694 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001695
1696 if (automaticRetryConfig == "Disabled")
1697 {
1698 autoRebootEnabled = false;
1699 }
1700 else if (automaticRetryConfig == "RetryAttempts")
1701 {
1702 autoRebootEnabled = true;
1703 }
1704 else
1705 {
George Liu0fda0f12021-11-16 10:06:17 +08001706 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001707 << automaticRetryConfig;
1708 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1709 "AutomaticRetryConfig");
1710 return;
1711 }
1712
1713 crow::connections::systemBus->async_method_call(
1714 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001715 if (ec)
1716 {
1717 messages::internalError(aResp->res);
1718 return;
1719 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001720 },
1721 "xyz.openbmc_project.Settings",
1722 "/xyz/openbmc_project/control/host0/auto_reboot",
1723 "org.freedesktop.DBus.Properties", "Set",
1724 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001725 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001726}
1727
1728/**
George Liuc6a620f2020-04-10 17:18:11 +08001729 * @brief Sets power restore policy properties.
1730 *
1731 * @param[in] aResp Shared pointer for generating response message.
1732 * @param[in] policy power restore policy properties from request.
1733 *
1734 * @return None.
1735 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001736inline void
1737 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1738 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001739{
1740 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1741
1742 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001743 {"AlwaysOn",
1744 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1745 {"AlwaysOff",
1746 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1747 {"LastState",
1748 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001749
1750 std::string powerRestorPolicy;
1751
Gunnar Mills4e69c902021-01-05 19:50:11 -06001752 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001753 if (policyMapsIt == policyMaps.end())
1754 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001755 messages::propertyValueNotInList(aResp->res, policy,
1756 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001757 return;
1758 }
1759
1760 powerRestorPolicy = policyMapsIt->second;
1761
1762 crow::connections::systemBus->async_method_call(
1763 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001764 if (ec)
1765 {
1766 messages::internalError(aResp->res);
1767 return;
1768 }
George Liuc6a620f2020-04-10 17:18:11 +08001769 },
1770 "xyz.openbmc_project.Settings",
1771 "/xyz/openbmc_project/control/host0/power_restore_policy",
1772 "org.freedesktop.DBus.Properties", "Set",
1773 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001774 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001775}
1776
AppaRao Pulia6349912019-10-18 17:16:08 +05301777#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1778/**
1779 * @brief Retrieves provisioning status
1780 *
1781 * @param[in] aResp Shared pointer for completing asynchronous calls.
1782 *
1783 * @return None.
1784 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001785inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301786{
1787 BMCWEB_LOG_DEBUG << "Get OEM information.";
1788 crow::connections::systemBus->async_method_call(
1789 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001790 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001791 nlohmann::json& oemPFR =
1792 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1793 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1794 "#OemComputerSystem.OpenBmc";
1795 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001796
Ed Tanous002d39b2022-05-31 08:59:27 -07001797 if (ec)
1798 {
1799 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1800 // not an error, don't have to have the interface
1801 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1802 return;
1803 }
1804
1805 const bool* provState = nullptr;
1806 const bool* lockState = nullptr;
1807 for (const std::pair<std::string, dbus::utility::DbusVariantType>&
1808 property : propertiesList)
1809 {
1810 if (property.first == "UfmProvisioned")
AppaRao Pulia6349912019-10-18 17:16:08 +05301811 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001812 provState = std::get_if<bool>(&property.second);
AppaRao Pulia6349912019-10-18 17:16:08 +05301813 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001814 else if (property.first == "UfmLocked")
AppaRao Pulia6349912019-10-18 17:16:08 +05301815 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001816 lockState = std::get_if<bool>(&property.second);
AppaRao Pulia6349912019-10-18 17:16:08 +05301817 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001818 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301819
Ed Tanous002d39b2022-05-31 08:59:27 -07001820 if ((provState == nullptr) || (lockState == nullptr))
1821 {
1822 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1823 messages::internalError(aResp->res);
1824 return;
1825 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301826
Ed Tanous002d39b2022-05-31 08:59:27 -07001827 if (*provState == true)
1828 {
1829 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301830 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001831 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301832 }
1833 else
1834 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001835 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301836 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001837 }
1838 else
1839 {
1840 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1841 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301842 },
1843 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1844 "org.freedesktop.DBus.Properties", "GetAll",
1845 "xyz.openbmc_project.PFR.Attributes");
1846}
1847#endif
1848
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301849/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001850 * @brief Translate the PowerMode to a response message.
1851 *
1852 * @param[in] aResp Shared pointer for generating response message.
1853 * @param[in] modeValue PowerMode value to be translated
1854 *
1855 * @return None.
1856 */
1857inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1858 const std::string& modeValue)
1859{
George Liu0fda0f12021-11-16 10:06:17 +08001860 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001861 {
1862 aResp->res.jsonValue["PowerMode"] = "Static";
1863 }
George Liu0fda0f12021-11-16 10:06:17 +08001864 else if (
1865 modeValue ==
1866 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001867 {
1868 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1869 }
George Liu0fda0f12021-11-16 10:06:17 +08001870 else if (modeValue ==
1871 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001872 {
1873 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1874 }
George Liu0fda0f12021-11-16 10:06:17 +08001875 else if (modeValue ==
1876 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001877 {
1878 aResp->res.jsonValue["PowerMode"] = "OEM";
1879 }
1880 else
1881 {
1882 // Any other values would be invalid
1883 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1884 messages::internalError(aResp->res);
1885 }
1886}
1887
1888/**
1889 * @brief Retrieves system power mode
1890 *
1891 * @param[in] aResp Shared pointer for generating response message.
1892 *
1893 * @return None.
1894 */
1895inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1896{
1897 BMCWEB_LOG_DEBUG << "Get power mode.";
1898
1899 // Get Power Mode object path:
1900 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08001901 [aResp](const boost::system::error_code ec,
1902 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001903 if (ec)
1904 {
1905 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
1906 << ec;
1907 // This is an optional D-Bus object so just return if
1908 // error occurs
1909 return;
1910 }
1911 if (subtree.empty())
1912 {
1913 // As noted above, this is an optional interface so just return
1914 // if there is no instance found
1915 return;
1916 }
1917 if (subtree.size() > 1)
1918 {
1919 // More then one PowerMode object is not supported and is an
1920 // error
1921 BMCWEB_LOG_DEBUG
1922 << "Found more than 1 system D-Bus Power.Mode objects: "
1923 << subtree.size();
1924 messages::internalError(aResp->res);
1925 return;
1926 }
1927 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1928 {
1929 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1930 messages::internalError(aResp->res);
1931 return;
1932 }
1933 const std::string& path = subtree[0].first;
1934 const std::string& service = subtree[0].second.begin()->first;
1935 if (service.empty())
1936 {
1937 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
1938 messages::internalError(aResp->res);
1939 return;
1940 }
1941 // Valid Power Mode object found, now read the current value
1942 sdbusplus::asio::getProperty<std::string>(
1943 *crow::connections::systemBus, service, path,
1944 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
1945 [aResp](const boost::system::error_code ec,
1946 const std::string& pmode) {
Chris Cain3a2d04242021-05-28 16:57:10 -05001947 if (ec)
1948 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001949 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
1950 << ec;
Chris Cain3a2d04242021-05-28 16:57:10 -05001951 messages::internalError(aResp->res);
1952 return;
1953 }
Chris Cain3a2d04242021-05-28 16:57:10 -05001954
Ed Tanous002d39b2022-05-31 08:59:27 -07001955 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
1956 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05001957
Ed Tanous002d39b2022-05-31 08:59:27 -07001958 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
1959 translatePowerMode(aResp, pmode);
1960 });
Chris Cain3a2d04242021-05-28 16:57:10 -05001961 },
1962 "xyz.openbmc_project.ObjectMapper",
1963 "/xyz/openbmc_project/object_mapper",
1964 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
1965 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
1966}
1967
1968/**
1969 * @brief Validate the specified mode is valid and return the PowerMode
1970 * name associated with that string
1971 *
1972 * @param[in] aResp Shared pointer for generating response message.
1973 * @param[in] modeString String representing the desired PowerMode
1974 *
1975 * @return PowerMode value or empty string if mode is not valid
1976 */
1977inline std::string
1978 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1979 const std::string& modeString)
1980{
1981 std::string mode;
1982
1983 if (modeString == "Static")
1984 {
1985 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
1986 }
1987 else if (modeString == "MaximumPerformance")
1988 {
George Liu0fda0f12021-11-16 10:06:17 +08001989 mode =
1990 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05001991 }
1992 else if (modeString == "PowerSaving")
1993 {
1994 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
1995 }
1996 else
1997 {
1998 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
1999 }
2000 return mode;
2001}
2002
2003/**
2004 * @brief Sets system power mode.
2005 *
2006 * @param[in] aResp Shared pointer for generating response message.
2007 * @param[in] pmode System power mode from request.
2008 *
2009 * @return None.
2010 */
2011inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2012 const std::string& pmode)
2013{
2014 BMCWEB_LOG_DEBUG << "Set power mode.";
2015
2016 std::string powerMode = validatePowerMode(aResp, pmode);
2017 if (powerMode.empty())
2018 {
2019 return;
2020 }
2021
2022 // Get Power Mode object path:
2023 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002024 [aResp,
2025 powerMode](const boost::system::error_code ec,
2026 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002027 if (ec)
2028 {
2029 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2030 << ec;
2031 // This is an optional D-Bus object, but user attempted to patch
2032 messages::internalError(aResp->res);
2033 return;
2034 }
2035 if (subtree.empty())
2036 {
2037 // This is an optional D-Bus object, but user attempted to patch
2038 messages::resourceNotFound(aResp->res, "ComputerSystem",
2039 "PowerMode");
2040 return;
2041 }
2042 if (subtree.size() > 1)
2043 {
2044 // More then one PowerMode object is not supported and is an
2045 // error
2046 BMCWEB_LOG_DEBUG
2047 << "Found more than 1 system D-Bus Power.Mode objects: "
2048 << subtree.size();
2049 messages::internalError(aResp->res);
2050 return;
2051 }
2052 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2053 {
2054 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2055 messages::internalError(aResp->res);
2056 return;
2057 }
2058 const std::string& path = subtree[0].first;
2059 const std::string& service = subtree[0].second.begin()->first;
2060 if (service.empty())
2061 {
2062 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2063 messages::internalError(aResp->res);
2064 return;
2065 }
2066
2067 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2068 << path;
2069
2070 // Set the Power Mode property
2071 crow::connections::systemBus->async_method_call(
2072 [aResp](const boost::system::error_code ec) {
Chris Cain3a2d04242021-05-28 16:57:10 -05002073 if (ec)
2074 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002075 messages::internalError(aResp->res);
2076 return;
2077 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002078 },
2079 service, path, "org.freedesktop.DBus.Properties", "Set",
2080 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2081 dbus::utility::DbusVariantType(powerMode));
Chris Cain3a2d04242021-05-28 16:57:10 -05002082 },
2083 "xyz.openbmc_project.ObjectMapper",
2084 "/xyz/openbmc_project/object_mapper",
2085 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2086 std::array<const char*, 1>{"xyz.openbmc_project.Control.Power.Mode"});
2087}
2088
2089/**
Yong Li51709ff2019-09-30 14:13:04 +08002090 * @brief Translates watchdog timeout action DBUS property value to redfish.
2091 *
2092 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2093 *
2094 * @return Returns as a string, the timeout action in Redfish terms. If
2095 * translation cannot be done, returns an empty string.
2096 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002097inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002098{
2099 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2100 {
2101 return "None";
2102 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002103 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002104 {
2105 return "ResetSystem";
2106 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002107 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002108 {
2109 return "PowerDown";
2110 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002111 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002112 {
2113 return "PowerCycle";
2114 }
2115
2116 return "";
2117}
2118
2119/**
Yong Lic45f0082019-10-10 14:19:01 +08002120 *@brief Translates timeout action from Redfish to DBUS property value.
2121 *
2122 *@param[in] rfAction The timeout action in Redfish.
2123 *
2124 *@return Returns as a string, the time_out action as expected by DBUS.
2125 *If translation cannot be done, returns an empty string.
2126 */
2127
Ed Tanous23a21a12020-07-25 04:45:05 +00002128inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002129{
2130 if (rfAction == "None")
2131 {
2132 return "xyz.openbmc_project.State.Watchdog.Action.None";
2133 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002134 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002135 {
2136 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2137 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002138 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002139 {
2140 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2141 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002142 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002143 {
2144 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2145 }
2146
2147 return "";
2148}
2149
2150/**
Yong Li51709ff2019-09-30 14:13:04 +08002151 * @brief Retrieves host watchdog timer properties over DBUS
2152 *
2153 * @param[in] aResp Shared pointer for completing asynchronous calls.
2154 *
2155 * @return None.
2156 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002157inline void
2158 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002159{
2160 BMCWEB_LOG_DEBUG << "Get host watchodg";
2161 crow::connections::systemBus->async_method_call(
2162 [aResp](const boost::system::error_code ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002163 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002164 if (ec)
2165 {
2166 // watchdog service is stopped
2167 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2168 return;
2169 }
2170
2171 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2172
2173 nlohmann::json& hostWatchdogTimer =
2174 aResp->res.jsonValue["HostWatchdogTimer"];
2175
2176 // watchdog service is running/enabled
2177 hostWatchdogTimer["Status"]["State"] = "Enabled";
2178
2179 for (const auto& property : properties)
2180 {
2181 BMCWEB_LOG_DEBUG << "prop=" << property.first;
2182 if (property.first == "Enabled")
Yong Li51709ff2019-09-30 14:13:04 +08002183 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002184 const bool* state = std::get_if<bool>(&property.second);
2185
2186 if (state == nullptr)
2187 {
2188 messages::internalError(aResp->res);
2189 return;
2190 }
2191
2192 hostWatchdogTimer["FunctionEnabled"] = *state;
Yong Li51709ff2019-09-30 14:13:04 +08002193 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002194 else if (property.first == "ExpireAction")
Yong Li51709ff2019-09-30 14:13:04 +08002195 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002196 const std::string* s =
2197 std::get_if<std::string>(&property.second);
2198 if (s == nullptr)
Yong Li51709ff2019-09-30 14:13:04 +08002199 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002200 messages::internalError(aResp->res);
2201 return;
Yong Li51709ff2019-09-30 14:13:04 +08002202 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002203
2204 std::string action = dbusToRfWatchdogAction(*s);
2205 if (action.empty())
Yong Li51709ff2019-09-30 14:13:04 +08002206 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002207 messages::internalError(aResp->res);
2208 return;
Yong Li51709ff2019-09-30 14:13:04 +08002209 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002210 hostWatchdogTimer["TimeoutAction"] = action;
Yong Li51709ff2019-09-30 14:13:04 +08002211 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002212 }
Yong Li51709ff2019-09-30 14:13:04 +08002213 },
2214 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
2215 "org.freedesktop.DBus.Properties", "GetAll",
2216 "xyz.openbmc_project.State.Watchdog");
2217}
2218
2219/**
Yong Lic45f0082019-10-10 14:19:01 +08002220 * @brief Sets Host WatchDog Timer properties.
2221 *
2222 * @param[in] aResp Shared pointer for generating response message.
2223 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2224 * RF request.
2225 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2226 *
2227 * @return None.
2228 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002229inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002230 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002231 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002232{
2233 BMCWEB_LOG_DEBUG << "Set host watchdog";
2234
2235 if (wdtTimeOutAction)
2236 {
2237 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2238 // check if TimeOut Action is Valid
2239 if (wdtTimeOutActStr.empty())
2240 {
2241 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2242 << *wdtTimeOutAction;
2243 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2244 "TimeoutAction");
2245 return;
2246 }
2247
2248 crow::connections::systemBus->async_method_call(
2249 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002250 if (ec)
2251 {
2252 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2253 messages::internalError(aResp->res);
2254 return;
2255 }
Yong Lic45f0082019-10-10 14:19:01 +08002256 },
2257 "xyz.openbmc_project.Watchdog",
2258 "/xyz/openbmc_project/watchdog/host0",
2259 "org.freedesktop.DBus.Properties", "Set",
2260 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002261 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002262 }
2263
2264 if (wdtEnable)
2265 {
2266 crow::connections::systemBus->async_method_call(
2267 [aResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002268 if (ec)
2269 {
2270 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2271 messages::internalError(aResp->res);
2272 return;
2273 }
Yong Lic45f0082019-10-10 14:19:01 +08002274 },
2275 "xyz.openbmc_project.Watchdog",
2276 "/xyz/openbmc_project/watchdog/host0",
2277 "org.freedesktop.DBus.Properties", "Set",
2278 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002279 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002280 }
2281}
2282
Chris Cain37bbf982021-09-20 10:53:09 -05002283using ipsPropertiesType =
2284 std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>;
2285/**
2286 * @brief Parse the Idle Power Saver properties into json
2287 *
2288 * @param[in] aResp Shared pointer for completing asynchronous calls.
2289 * @param[in] properties IPS property data from DBus.
2290 *
2291 * @return true if successful
2292 */
Ed Tanousf6674222021-11-13 09:41:41 -08002293inline bool parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2294 ipsPropertiesType& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002295{
2296 for (const auto& property : properties)
2297 {
2298 if (property.first == "Enabled")
2299 {
2300 const bool* state = std::get_if<bool>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002301 if (state == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002302 {
2303 return false;
2304 }
2305 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *state;
2306 }
2307 else if (property.first == "EnterUtilizationPercent")
2308 {
2309 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002310 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002311 {
2312 return false;
2313 }
2314 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2315 }
2316 else if (property.first == "EnterDwellTime")
2317 {
2318 // Convert Dbus time from milliseconds to seconds
2319 const uint64_t* timeMilliseconds =
2320 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002321 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002322 {
2323 return false;
2324 }
2325 const std::chrono::duration<uint64_t, std::milli> ms(
2326 *timeMilliseconds);
2327 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2328 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2329 .count();
2330 }
2331 else if (property.first == "ExitUtilizationPercent")
2332 {
2333 const uint8_t* util = std::get_if<uint8_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002334 if (util == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002335 {
2336 return false;
2337 }
2338 aResp->res.jsonValue["IdlePowerSaver"][property.first] = *util;
2339 }
2340 else if (property.first == "ExitDwellTime")
2341 {
2342 // Convert Dbus time from milliseconds to seconds
2343 const uint64_t* timeMilliseconds =
2344 std::get_if<uint64_t>(&property.second);
Ed Tanouse662eae2022-01-25 10:39:19 -08002345 if (timeMilliseconds == nullptr)
Chris Cain37bbf982021-09-20 10:53:09 -05002346 {
2347 return false;
2348 }
2349 const std::chrono::duration<uint64_t, std::milli> ms(
2350 *timeMilliseconds);
2351 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2352 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2353 .count();
2354 }
2355 else
2356 {
2357 BMCWEB_LOG_WARNING << "Unexpected IdlePowerSaver property: "
2358 << property.first;
2359 }
2360 }
2361
2362 return true;
2363}
2364
2365/**
2366 * @brief Retrieves host watchdog timer properties over DBUS
2367 *
2368 * @param[in] aResp Shared pointer for completing asynchronous calls.
2369 *
2370 * @return None.
2371 */
2372inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2373{
2374 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2375
2376 // Get IdlePowerSaver object path:
2377 crow::connections::systemBus->async_method_call(
Ed Tanousb9d36b42022-02-26 21:42:46 -08002378 [aResp](const boost::system::error_code ec,
2379 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002380 if (ec)
2381 {
2382 BMCWEB_LOG_DEBUG
2383 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2384 << ec;
2385 messages::internalError(aResp->res);
2386 return;
2387 }
2388 if (subtree.empty())
2389 {
2390 // This is an optional interface so just return
2391 // if there is no instance found
2392 BMCWEB_LOG_DEBUG << "No instances found";
2393 return;
2394 }
2395 if (subtree.size() > 1)
2396 {
2397 // More then one PowerIdlePowerSaver object is not supported and
2398 // is an error
2399 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2400 "Power.IdlePowerSaver objects: "
2401 << subtree.size();
2402 messages::internalError(aResp->res);
2403 return;
2404 }
2405 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2406 {
2407 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2408 messages::internalError(aResp->res);
2409 return;
2410 }
2411 const std::string& path = subtree[0].first;
2412 const std::string& service = subtree[0].second.begin()->first;
2413 if (service.empty())
2414 {
2415 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2416 messages::internalError(aResp->res);
2417 return;
2418 }
2419
2420 // Valid IdlePowerSaver object found, now read the current values
2421 crow::connections::systemBus->async_method_call(
2422 [aResp](const boost::system::error_code ec,
2423 ipsPropertiesType& properties) {
Chris Cain37bbf982021-09-20 10:53:09 -05002424 if (ec)
2425 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002426 BMCWEB_LOG_ERROR
2427 << "DBUS response error on IdlePowerSaver GetAll: " << ec;
Chris Cain37bbf982021-09-20 10:53:09 -05002428 messages::internalError(aResp->res);
2429 return;
2430 }
2431
Ed Tanous002d39b2022-05-31 08:59:27 -07002432 if (!parseIpsProperties(aResp, properties))
2433 {
2434 messages::internalError(aResp->res);
2435 return;
2436 }
2437 },
2438 service, path, "org.freedesktop.DBus.Properties", "GetAll",
2439 "xyz.openbmc_project.Control.Power.IdlePowerSaver");
Chris Cain37bbf982021-09-20 10:53:09 -05002440 },
2441 "xyz.openbmc_project.ObjectMapper",
2442 "/xyz/openbmc_project/object_mapper",
2443 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2444 std::array<const char*, 1>{
2445 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2446
2447 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2448}
2449
2450/**
2451 * @brief Sets Idle Power Saver properties.
2452 *
2453 * @param[in] aResp Shared pointer for generating response message.
2454 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2455 * RF request.
2456 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2457 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2458 * before entering idle state.
2459 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2460 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2461 * before exiting idle state
2462 *
2463 * @return None.
2464 */
2465inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2466 const std::optional<bool> ipsEnable,
2467 const std::optional<uint8_t> ipsEnterUtil,
2468 const std::optional<uint64_t> ipsEnterTime,
2469 const std::optional<uint8_t> ipsExitUtil,
2470 const std::optional<uint64_t> ipsExitTime)
2471{
2472 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2473
2474 // Get IdlePowerSaver object path:
2475 crow::connections::systemBus->async_method_call(
2476 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002477 ipsExitTime](const boost::system::error_code ec,
2478 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002479 if (ec)
2480 {
2481 BMCWEB_LOG_DEBUG
2482 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2483 << ec;
2484 messages::internalError(aResp->res);
2485 return;
2486 }
2487 if (subtree.empty())
2488 {
2489 // This is an optional D-Bus object, but user attempted to patch
2490 messages::resourceNotFound(aResp->res, "ComputerSystem",
2491 "IdlePowerSaver");
2492 return;
2493 }
2494 if (subtree.size() > 1)
2495 {
2496 // More then one PowerIdlePowerSaver object is not supported and
2497 // is an error
2498 BMCWEB_LOG_DEBUG
2499 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2500 << subtree.size();
2501 messages::internalError(aResp->res);
2502 return;
2503 }
2504 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2505 {
2506 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2507 messages::internalError(aResp->res);
2508 return;
2509 }
2510 const std::string& path = subtree[0].first;
2511 const std::string& service = subtree[0].second.begin()->first;
2512 if (service.empty())
2513 {
2514 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2515 messages::internalError(aResp->res);
2516 return;
2517 }
Chris Cain37bbf982021-09-20 10:53:09 -05002518
Ed Tanous002d39b2022-05-31 08:59:27 -07002519 // Valid Power IdlePowerSaver object found, now set any values that
2520 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002521
Ed Tanous002d39b2022-05-31 08:59:27 -07002522 if (ipsEnable)
2523 {
2524 crow::connections::systemBus->async_method_call(
2525 [aResp](const boost::system::error_code ec) {
2526 if (ec)
2527 {
2528 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2529 messages::internalError(aResp->res);
2530 return;
2531 }
2532 },
2533 service, path, "org.freedesktop.DBus.Properties", "Set",
2534 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2535 dbus::utility::DbusVariantType(*ipsEnable));
2536 }
2537 if (ipsEnterUtil)
2538 {
2539 crow::connections::systemBus->async_method_call(
2540 [aResp](const boost::system::error_code ec) {
2541 if (ec)
2542 {
2543 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2544 messages::internalError(aResp->res);
2545 return;
2546 }
2547 },
2548 service, path, "org.freedesktop.DBus.Properties", "Set",
2549 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2550 "EnterUtilizationPercent",
2551 dbus::utility::DbusVariantType(*ipsEnterUtil));
2552 }
2553 if (ipsEnterTime)
2554 {
2555 // Convert from seconds into milliseconds for DBus
2556 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2557 crow::connections::systemBus->async_method_call(
2558 [aResp](const boost::system::error_code ec) {
2559 if (ec)
2560 {
2561 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2562 messages::internalError(aResp->res);
2563 return;
2564 }
2565 },
2566 service, path, "org.freedesktop.DBus.Properties", "Set",
2567 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2568 "EnterDwellTime",
2569 dbus::utility::DbusVariantType(timeMilliseconds));
2570 }
2571 if (ipsExitUtil)
2572 {
2573 crow::connections::systemBus->async_method_call(
2574 [aResp](const boost::system::error_code ec) {
2575 if (ec)
2576 {
2577 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2578 messages::internalError(aResp->res);
2579 return;
2580 }
2581 },
2582 service, path, "org.freedesktop.DBus.Properties", "Set",
2583 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2584 "ExitUtilizationPercent",
2585 dbus::utility::DbusVariantType(*ipsExitUtil));
2586 }
2587 if (ipsExitTime)
2588 {
2589 // Convert from seconds into milliseconds for DBus
2590 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2591 crow::connections::systemBus->async_method_call(
2592 [aResp](const boost::system::error_code ec) {
2593 if (ec)
2594 {
2595 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2596 messages::internalError(aResp->res);
2597 return;
2598 }
2599 },
2600 service, path, "org.freedesktop.DBus.Properties", "Set",
2601 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2602 "ExitDwellTime",
2603 dbus::utility::DbusVariantType(timeMilliseconds));
2604 }
Chris Cain37bbf982021-09-20 10:53:09 -05002605 },
2606 "xyz.openbmc_project.ObjectMapper",
2607 "/xyz/openbmc_project/object_mapper",
2608 "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
2609 std::array<const char*, 1>{
2610 "xyz.openbmc_project.Control.Power.IdlePowerSaver"});
2611
2612 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2613}
2614
Yong Lic45f0082019-10-10 14:19:01 +08002615/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002616 * SystemsCollection derived class for delivering ComputerSystems Collection
2617 * Schema
2618 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002619inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002620{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002621 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002622 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002623 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002624 [&app](const crow::Request& req,
2625 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002626 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2627 {
2628 return;
2629 }
2630 asyncResp->res.jsonValue["@odata.type"] =
2631 "#ComputerSystemCollection.ComputerSystemCollection";
2632 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2633 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002634
Ed Tanous002d39b2022-05-31 08:59:27 -07002635 sdbusplus::asio::getProperty<std::string>(
2636 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2637 "/xyz/openbmc_project/network/hypervisor",
2638 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
2639 [asyncResp](const boost::system::error_code ec,
2640 const std::string& /*hostName*/) {
2641 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2642 ifaceArray = nlohmann::json::array();
2643 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002644
Ed Tanous002d39b2022-05-31 08:59:27 -07002645 nlohmann::json::object_t system;
2646 system["@odata.id"] = "/redfish/v1/Systems/system";
2647 ifaceArray.push_back(std::move(system));
2648 count = ifaceArray.size();
2649 if (!ec)
2650 {
2651 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2652 nlohmann::json::object_t hypervisor;
2653 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2654 ifaceArray.push_back(std::move(hypervisor));
2655 count = ifaceArray.size();
2656 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002657 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002658 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002659}
Sunitha Harish462023a2020-02-19 08:34:59 -06002660
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002661/**
2662 * Function transceives data with dbus directly.
2663 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002664inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002665{
2666 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2667 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2668 constexpr char const* interfaceName =
2669 "xyz.openbmc_project.Control.Host.NMI";
2670 constexpr char const* method = "NMI";
2671
2672 crow::connections::systemBus->async_method_call(
2673 [asyncResp](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002674 if (ec)
2675 {
2676 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2677 messages::internalError(asyncResp->res);
2678 return;
2679 }
2680 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002681 },
2682 serviceName, objectPath, interfaceName, method);
2683}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002684
2685/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002686 * SystemActionsReset class supports handle POST method for Reset action.
2687 * The class retrieves and sends data directly to D-Bus.
2688 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002689inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002690{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002691 /**
2692 * Function handles POST method request.
2693 * Analyzes POST body message before sends Reset request data to D-Bus.
2694 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002695 BMCWEB_ROUTE(app,
2696 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002697 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002698 .methods(boost::beast::http::verb::post)(
2699 [&app](const crow::Request& req,
2700 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2701 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2702 {
2703 return;
2704 }
2705 std::string resetType;
2706 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2707 resetType))
2708 {
2709 return;
2710 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002711
Ed Tanous002d39b2022-05-31 08:59:27 -07002712 // Get the command and host vs. chassis
2713 std::string command;
2714 bool hostCommand = true;
2715 if ((resetType == "On") || (resetType == "ForceOn"))
2716 {
2717 command = "xyz.openbmc_project.State.Host.Transition.On";
2718 hostCommand = true;
2719 }
2720 else if (resetType == "ForceOff")
2721 {
2722 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2723 hostCommand = false;
2724 }
2725 else if (resetType == "ForceRestart")
2726 {
2727 command =
2728 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2729 hostCommand = true;
2730 }
2731 else if (resetType == "GracefulShutdown")
2732 {
2733 command = "xyz.openbmc_project.State.Host.Transition.Off";
2734 hostCommand = true;
2735 }
2736 else if (resetType == "GracefulRestart")
2737 {
2738 command =
2739 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2740 hostCommand = true;
2741 }
2742 else if (resetType == "PowerCycle")
2743 {
2744 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2745 hostCommand = true;
2746 }
2747 else if (resetType == "Nmi")
2748 {
2749 doNMI(asyncResp);
2750 return;
2751 }
2752 else
2753 {
2754 messages::actionParameterUnknown(asyncResp->res, "Reset",
2755 resetType);
2756 return;
2757 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002758
Ed Tanous002d39b2022-05-31 08:59:27 -07002759 if (hostCommand)
2760 {
2761 crow::connections::systemBus->async_method_call(
2762 [asyncResp, resetType](const boost::system::error_code ec) {
2763 if (ec)
2764 {
2765 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2766 if (ec.value() == boost::asio::error::invalid_argument)
2767 {
2768 messages::actionParameterNotSupported(
2769 asyncResp->res, resetType, "Reset");
2770 }
2771 else
2772 {
2773 messages::internalError(asyncResp->res);
2774 }
2775 return;
2776 }
2777 messages::success(asyncResp->res);
2778 },
2779 "xyz.openbmc_project.State.Host",
2780 "/xyz/openbmc_project/state/host0",
2781 "org.freedesktop.DBus.Properties", "Set",
2782 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2783 dbus::utility::DbusVariantType{command});
2784 }
2785 else
2786 {
2787 crow::connections::systemBus->async_method_call(
2788 [asyncResp, resetType](const boost::system::error_code ec) {
2789 if (ec)
2790 {
2791 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2792 if (ec.value() == boost::asio::error::invalid_argument)
2793 {
2794 messages::actionParameterNotSupported(
2795 asyncResp->res, resetType, "Reset");
2796 }
2797 else
2798 {
2799 messages::internalError(asyncResp->res);
2800 }
2801 return;
2802 }
2803 messages::success(asyncResp->res);
2804 },
2805 "xyz.openbmc_project.State.Chassis",
2806 "/xyz/openbmc_project/state/chassis0",
2807 "org.freedesktop.DBus.Properties", "Set",
2808 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2809 dbus::utility::DbusVariantType{command});
2810 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002811 });
2812}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002813
2814/**
Ed Tanous66173382018-08-15 18:20:59 -07002815 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002816 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002817inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002818{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002819
Ed Tanous1abe55e2018-09-05 08:30:59 -07002820 /**
2821 * Functions triggers appropriate requests on DBus
2822 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002823 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002824 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002825 .methods(boost::beast::http::verb::get)(
2826 [&app](const crow::Request& req,
2827 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2828 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2829 {
2830 return;
2831 }
2832 asyncResp->res.jsonValue["@odata.type"] =
2833 "#ComputerSystem.v1_16_0.ComputerSystem";
2834 asyncResp->res.jsonValue["Name"] = "system";
2835 asyncResp->res.jsonValue["Id"] = "system";
2836 asyncResp->res.jsonValue["SystemType"] = "Physical";
2837 asyncResp->res.jsonValue["Description"] = "Computer System";
2838 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2839 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2840 "Disabled";
2841 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2842 uint64_t(0);
2843 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2844 "Disabled";
2845 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002846
Ed Tanous002d39b2022-05-31 08:59:27 -07002847 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
2848 "/redfish/v1/Systems/system/Processors";
2849 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
2850 "/redfish/v1/Systems/system/Memory";
2851 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
2852 "/redfish/v1/Systems/system/Storage";
Ed Tanous029573d2019-02-01 10:57:49 -08002853
Ed Tanous002d39b2022-05-31 08:59:27 -07002854 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
2855 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
2856 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
2857 ["@Redfish.ActionInfo"] =
2858 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002859
Ed Tanous002d39b2022-05-31 08:59:27 -07002860 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
2861 "/redfish/v1/Systems/system/LogServices";
2862 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
2863 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002864
Ed Tanous002d39b2022-05-31 08:59:27 -07002865 nlohmann::json::array_t managedBy;
2866 nlohmann::json& manager = managedBy.emplace_back();
2867 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
2868 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
2869 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
2870 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002871
Ed Tanous002d39b2022-05-31 08:59:27 -07002872 // Fill in SerialConsole info
2873 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
2874 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
2875 true;
Ed Tanous14766872022-03-15 10:44:42 -07002876
Ed Tanous002d39b2022-05-31 08:59:27 -07002877 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
2878 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
2879 true;
2880 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
2881 asyncResp->res
2882 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
2883 "Press ~. to exit console";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002884
2885#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002886 // Fill in GraphicalConsole info
2887 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
2888 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
2889 4;
2890 asyncResp->res
2891 .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"};
Ed Tanous14766872022-03-15 10:44:42 -07002892
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002893#endif // BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07002894 constexpr const std::array<const char*, 4> inventoryForSystems = {
2895 "xyz.openbmc_project.Inventory.Item.Dimm",
2896 "xyz.openbmc_project.Inventory.Item.Cpu",
2897 "xyz.openbmc_project.Inventory.Item.Drive",
2898 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07002899
Ed Tanous002d39b2022-05-31 08:59:27 -07002900 auto health = std::make_shared<HealthPopulate>(asyncResp);
2901 crow::connections::systemBus->async_method_call(
2902 [health](const boost::system::error_code ec,
2903 const std::vector<std::string>& resp) {
2904 if (ec)
2905 {
2906 // no inventory
2907 return;
2908 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002909
Ed Tanous002d39b2022-05-31 08:59:27 -07002910 health->inventory = resp;
2911 },
2912 "xyz.openbmc_project.ObjectMapper",
2913 "/xyz/openbmc_project/object_mapper",
2914 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
2915 int32_t(0), inventoryForSystems);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002916
Ed Tanous002d39b2022-05-31 08:59:27 -07002917 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002918
Ed Tanous002d39b2022-05-31 08:59:27 -07002919 getMainChassisId(asyncResp,
2920 [](const std::string& chassisId,
2921 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
2922 nlohmann::json::array_t chassisArray;
2923 nlohmann::json& chassis = chassisArray.emplace_back();
2924 chassis["@odata.id"] = "/redfish/v1/Chassis/" + chassisId;
2925 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
2926 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002927
Ed Tanous002d39b2022-05-31 08:59:27 -07002928 getLocationIndicatorActive(asyncResp);
2929 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
2930 getIndicatorLedState(asyncResp);
2931 getComputerSystem(asyncResp, health);
2932 getHostState(asyncResp);
2933 getBootProperties(asyncResp);
2934 getBootProgress(asyncResp);
2935 getPCIeDeviceList(asyncResp, "PCIeDevices");
2936 getHostWatchdogTimer(asyncResp);
2937 getPowerRestorePolicy(asyncResp);
2938 getAutomaticRetry(asyncResp);
2939 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002940#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07002941 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002942#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07002943 getTrustedModuleRequiredToBoot(asyncResp);
2944 getPowerMode(asyncResp);
2945 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002946 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002947
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002948 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
Ed Tanoused398212021-06-09 17:05:54 -07002949 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002950 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07002951 [&app](const crow::Request& req,
2952 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002953 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
2954 {
2955 return;
2956 }
2957 std::optional<bool> locationIndicatorActive;
2958 std::optional<std::string> indicatorLed;
2959 std::optional<std::string> assetTag;
2960 std::optional<std::string> powerRestorePolicy;
2961 std::optional<std::string> powerMode;
2962 std::optional<bool> wdtEnable;
2963 std::optional<std::string> wdtTimeOutAction;
2964 std::optional<std::string> bootSource;
2965 std::optional<std::string> bootType;
2966 std::optional<std::string> bootEnable;
2967 std::optional<std::string> bootAutomaticRetry;
2968 std::optional<bool> bootTrustedModuleRequired;
2969 std::optional<bool> ipsEnable;
2970 std::optional<uint8_t> ipsEnterUtil;
2971 std::optional<uint64_t> ipsEnterTime;
2972 std::optional<uint8_t> ipsExitUtil;
2973 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08002974
Ed Tanous002d39b2022-05-31 08:59:27 -07002975 // clang-format off
Jiaqing Zhaoaa6d4532022-06-02 17:47:58 +08002976 if (!json_util::readJsonPatch(
2977 req, asyncResp->res,
2978 "IndicatorLED", indicatorLed,
2979 "LocationIndicatorActive", locationIndicatorActive,
2980 "AssetTag", assetTag,
2981 "PowerRestorePolicy", powerRestorePolicy,
2982 "PowerMode", powerMode,
2983 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
2984 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
2985 "Boot/BootSourceOverrideTarget", bootSource,
2986 "Boot/BootSourceOverrideMode", bootType,
2987 "Boot/BootSourceOverrideEnabled", bootEnable,
2988 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
2989 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
2990 "IdlePowerSaver/Enabled", ipsEnable,
2991 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
2992 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
2993 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
2994 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
2995 {
2996 return;
2997 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002998 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07002999
Ed Tanous002d39b2022-05-31 08:59:27 -07003000 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003001
Ed Tanous002d39b2022-05-31 08:59:27 -07003002 if (assetTag)
3003 {
3004 setAssetTag(asyncResp, *assetTag);
3005 }
James Feistb49ac872019-05-21 15:12:01 -07003006
Ed Tanous002d39b2022-05-31 08:59:27 -07003007 if (wdtEnable || wdtTimeOutAction)
3008 {
3009 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3010 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003011
Ed Tanous002d39b2022-05-31 08:59:27 -07003012 if (bootSource || bootType || bootEnable)
3013 {
3014 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3015 }
3016 if (bootAutomaticRetry)
3017 {
3018 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3019 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003020
Ed Tanous002d39b2022-05-31 08:59:27 -07003021 if (bootTrustedModuleRequired)
3022 {
3023 setTrustedModuleRequiredToBoot(asyncResp,
3024 *bootTrustedModuleRequired);
3025 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003026
Ed Tanous002d39b2022-05-31 08:59:27 -07003027 if (locationIndicatorActive)
3028 {
3029 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3030 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003031
Ed Tanous002d39b2022-05-31 08:59:27 -07003032 // TODO (Gunnar): Remove IndicatorLED after enough time has
3033 // passed
3034 if (indicatorLed)
3035 {
3036 setIndicatorLedState(asyncResp, *indicatorLed);
3037 asyncResp->res.addHeader(boost::beast::http::field::warning,
3038 "299 - \"IndicatorLED is deprecated. Use "
3039 "LocationIndicatorActive instead.\"");
3040 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003041
Ed Tanous002d39b2022-05-31 08:59:27 -07003042 if (powerRestorePolicy)
3043 {
3044 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3045 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003046
Ed Tanous002d39b2022-05-31 08:59:27 -07003047 if (powerMode)
3048 {
3049 setPowerMode(asyncResp, *powerMode);
3050 }
Chris Cain37bbf982021-09-20 10:53:09 -05003051
Ed Tanous002d39b2022-05-31 08:59:27 -07003052 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3053 ipsExitTime)
3054 {
3055 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3056 ipsExitUtil, ipsExitTime);
3057 }
3058 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003059}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303060
3061/**
3062 * SystemResetActionInfo derived class for delivering Computer Systems
3063 * ResetType AllowableValues using ResetInfo schema.
3064 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003065inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303066{
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303067 /**
3068 * Functions triggers appropriate requests on DBus
3069 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003070 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003071 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003072 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003073 [&app](const crow::Request& req,
3074 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Ed Tanous002d39b2022-05-31 08:59:27 -07003075 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
3076 {
3077 return;
3078 }
Ed Tanous14766872022-03-15 10:44:42 -07003079
Ed Tanous002d39b2022-05-31 08:59:27 -07003080 asyncResp->res.jsonValue["@odata.id"] =
3081 "/redfish/v1/Systems/system/ResetActionInfo";
3082 asyncResp->res.jsonValue["@odata.type"] =
3083 "#ActionInfo.v1_1_2.ActionInfo";
3084 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3085 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003086
3087 nlohmann::json::array_t parameters;
3088 nlohmann::json::object_t parameter;
3089
3090 parameter["Name"] = "ResetType";
3091 parameter["Required"] = true;
3092 parameter["DataType"] = "String";
3093 nlohmann::json::array_t allowableValues;
3094 allowableValues.emplace_back("On");
3095 allowableValues.emplace_back("ForceOff");
3096 allowableValues.emplace_back("ForceOn");
3097 allowableValues.emplace_back("ForceRestart");
3098 allowableValues.emplace_back("GracefulRestart");
3099 allowableValues.emplace_back("GracefulShutdown");
3100 allowableValues.emplace_back("PowerCycle");
3101 allowableValues.emplace_back("Nmi");
3102 parameter["AllowableValues"] = std::move(allowableValues);
3103 parameters.emplace_back(std::move(parameter));
3104
3105 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003106 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003107}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003108} // namespace redfish