blob: 61746101febf46c0d7a2eca4645b1e3e01d0dbab [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
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080018#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070019#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080020#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070021#include "health.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080022#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080023#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070024#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080025#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080026#include "registries/privilege_registry.hpp"
27#include "utils/dbus_utils.hpp"
28#include "utils/json_utils.hpp"
29#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070030#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080031
Ed Tanous9712f8a2018-09-21 13:38:49 -070032#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080033#include <boost/system/error_code.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070034#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020035#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050036
George Liu7a1dbc42022-12-07 16:03:22 +080037#include <array>
38#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080039#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020040
Ed Tanous1abe55e2018-09-05 08:30:59 -070041namespace redfish
42{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020043
Abhishek Patel5c3e9272021-06-24 10:11:33 -050044const static std::array<std::pair<std::string_view, std::string_view>, 2>
45 protocolToDBusForSystems{
46 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
47
Alpana Kumari9d3ae102019-04-12 06:49:32 -050048/**
49 * @brief Updates the Functional State of DIMMs
50 *
51 * @param[in] aResp Shared pointer for completing asynchronous calls
52 * @param[in] dimmState Dimm's Functional state, true/false
53 *
54 * @return None.
55 */
zhanghch058d1b46d2021-04-01 11:18:24 +080056inline void
57 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070058 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050059{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070060 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050061
Gunnar Mills4e0453b2020-07-08 14:00:30 -050062 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050063 // Update STATE only if previous State was DISABLED and current Dimm is
64 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070065 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050066 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
67 if (prevMemSummary == "Disabled")
68 {
Ed Tanouse05aec52022-01-25 10:28:56 -080069 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050070 {
71 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
72 "Enabled";
73 }
74 }
75}
76
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050077/*
78 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
79 *
80 * @param[in] aResp Shared pointer for completing asynchronous calls
81 * @param[in] cpuPresenceState CPU present or not
82 *
83 * @return None.
84 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070085inline void
86 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
87 bool isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050088{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070089 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050090
Ed Tanous55f79e62022-01-25 11:26:16 -080091 if (isCpuPresent)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050092 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -050093 nlohmann::json& procCount =
James Feistb4b95952019-12-05 15:01:55 -080094 aResp->res.jsonValue["ProcessorSummary"]["Count"];
Ed Tanous55f79e62022-01-25 11:26:16 -080095 auto* procCountPtr =
Gunnar Mills1214b7e2020-06-04 10:11:30 -050096 procCount.get_ptr<nlohmann::json::number_integer_t*>();
James Feistb4b95952019-12-05 15:01:55 -080097 if (procCountPtr != nullptr)
98 {
99 // shouldn't be possible to be nullptr
100 *procCountPtr += 1;
101 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500102 }
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500103}
104
105/*
106 * @brief Update "ProcessorSummary" "Status" "State" based on
107 * CPU Functional State
108 *
109 * @param[in] aResp Shared pointer for completing asynchronous calls
110 * @param[in] cpuFunctionalState is CPU functional true/false
111 *
112 * @return None.
113 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700114inline void
115 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
116 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500117{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700118 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500119
Ed Tanous02cad962022-06-30 16:50:15 -0700120 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500121 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
122
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500123 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500124 // Update STATE only if previous State was Non_Functional and current CPU is
125 // Functional.
126 if (prevProcState == "Disabled")
127 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800128 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500129 {
130 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
131 "Enabled";
132 }
133 }
134}
135
Ali Ahmed382d6472021-09-03 16:53:53 -0500136inline void getProcessorProperties(
137 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
138 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
139 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500140{
141
142 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
143
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200144 // TODO: Get Model
145
146 const uint16_t* coreCount = nullptr;
147
148 const bool success = sdbusplus::unpackPropertiesNoThrow(
149 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
150
151 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500152 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200153 messages::internalError(aResp->res);
154 return;
155 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500156
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200157 if (coreCount != nullptr)
158 {
159 nlohmann::json& coreCountJson =
160 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
161 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500162
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200163 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500164 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200165 coreCountJson = *coreCount;
166 }
167 else
168 {
169 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500170 }
171 }
172}
173
174/*
175 * @brief Get ProcessorSummary fields
176 *
177 * @param[in] aResp Shared pointer for completing asynchronous calls
178 * @param[in] service dbus service for Cpu Information
179 * @param[in] path dbus path for Cpu
180 *
181 * @return None.
182 */
183inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
184 const std::string& service,
185 const std::string& path)
186{
187
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800188 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500189 const bool cpuPresenceCheck) {
190 if (ec3)
191 {
192 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
193 return;
194 }
195 modifyCpuPresenceState(aResp, cpuPresenceCheck);
196 };
197
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800198 auto getCpuFunctionalState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500199 const bool cpuFunctionalCheck) {
200 if (ec3)
201 {
202 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
203 return;
204 }
205 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
206 };
207
208 // Get the Presence of CPU
209 sdbusplus::asio::getProperty<bool>(
210 *crow::connections::systemBus, service, path,
211 "xyz.openbmc_project.Inventory.Item", "Present",
212 std::move(getCpuPresenceState));
213
214 // Get the Functional State
215 sdbusplus::asio::getProperty<bool>(
216 *crow::connections::systemBus, service, path,
217 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
218 std::move(getCpuFunctionalState));
219
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200220 sdbusplus::asio::getAllProperties(
221 *crow::connections::systemBus, service, path,
222 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500223 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800224 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800225 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700226 if (ec2)
227 {
228 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
229 messages::internalError(aResp->res);
230 return;
231 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500232 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200233 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500234}
235
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500236/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700237 * @brief Retrieves computer system properties over dbus
238 *
239 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500240 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700241 *
242 * @return None.
243 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700244inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800245 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700246 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700247{
Ed Tanous6c34de42018-08-29 13:37:36 -0700248 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800249 constexpr std::array<std::string_view, 5> interfaces = {
250 "xyz.openbmc_project.Inventory.Decorator.Asset",
251 "xyz.openbmc_project.Inventory.Item.Cpu",
252 "xyz.openbmc_project.Inventory.Item.Dimm",
253 "xyz.openbmc_project.Inventory.Item.System",
254 "xyz.openbmc_project.Common.UUID",
255 };
256 dbus::utility::getSubTree(
257 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800258 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800259 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800260 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700261 if (ec)
262 {
263 BMCWEB_LOG_DEBUG << "DBUS response error";
264 messages::internalError(aResp->res);
265 return;
266 }
267 // Iterate over all retrieved ObjectPaths.
268 for (const std::pair<
269 std::string,
270 std::vector<std::pair<std::string, std::vector<std::string>>>>&
271 object : subtree)
272 {
273 const std::string& path = object.first;
274 BMCWEB_LOG_DEBUG << "Got path: " << path;
275 const std::vector<std::pair<std::string, std::vector<std::string>>>&
276 connectionNames = object.second;
277 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700278 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700279 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700280 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700281
282 auto memoryHealth = std::make_shared<HealthPopulate>(
283 aResp, "/MemorySummary/Status"_json_pointer);
284
285 auto cpuHealth = std::make_shared<HealthPopulate>(
286 aResp, "/ProcessorSummary/Status"_json_pointer);
287
288 systemHealth->children.emplace_back(memoryHealth);
289 systemHealth->children.emplace_back(cpuHealth);
290
291 // This is not system, so check if it's cpu, dimm, UUID or
292 // BiosVer
293 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700294 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700295 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700296 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700297 if (interfaceName ==
298 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700299 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700300 BMCWEB_LOG_DEBUG
301 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500302
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200303 sdbusplus::asio::getAllProperties(
304 *crow::connections::systemBus, connection.first,
305 path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanous002d39b2022-05-31 08:59:27 -0700306 [aResp, service{connection.first},
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800307 path](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700308 const dbus::utility::DBusPropertiesMap&
309 properties) {
310 if (ec2)
311 {
312 BMCWEB_LOG_ERROR << "DBUS response error "
313 << ec2;
314 messages::internalError(aResp->res);
315 return;
316 }
317 BMCWEB_LOG_DEBUG << "Got " << properties.size()
318 << " Dimm properties.";
319
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200320 if (properties.empty())
Ed Tanous002d39b2022-05-31 08:59:27 -0700321 {
322 sdbusplus::asio::getProperty<bool>(
323 *crow::connections::systemBus, service,
324 path,
325 "xyz.openbmc_project.State."
326 "Decorator.OperationalStatus",
327 "Functional",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800328 [aResp](
329 const boost::system::error_code& ec3,
330 bool dimmState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700331 if (ec3)
332 {
333 BMCWEB_LOG_ERROR
Ed Tanouscb13a392020-07-25 19:02:03 +0000334 << "DBUS response error " << ec3;
Ed Tanous029573d2019-02-01 10:57:49 -0800335 return;
336 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700337 updateDimmProperties(aResp, dimmState);
338 });
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200339 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700340 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200341
342 const uint32_t* memorySizeInKB = nullptr;
343
344 const bool success =
345 sdbusplus::unpackPropertiesNoThrow(
346 dbus_utils::UnpackErrorPrinter(),
347 properties, "MemorySizeInKB",
348 memorySizeInKB);
349
350 if (!success)
351 {
352 messages::internalError(aResp->res);
353 return;
354 }
355
356 if (memorySizeInKB != nullptr)
357 {
358 nlohmann::json& totalMemory =
359 aResp->res
360 .jsonValue["MemorySummary"]
361 ["TotalSystemMemoryGiB"];
362 const uint64_t* preValue =
363 totalMemory.get_ptr<const uint64_t*>();
364 if (preValue == nullptr)
365 {
366 aResp->res
367 .jsonValue["MemorySummary"]
368 ["TotalSystemMemoryGiB"] =
369 *memorySizeInKB / (1024 * 1024);
370 }
371 else
372 {
373 aResp->res
374 .jsonValue["MemorySummary"]
375 ["TotalSystemMemoryGiB"] =
376 *memorySizeInKB / (1024 * 1024) +
377 *preValue;
378 }
379 aResp->res.jsonValue["MemorySummary"]["Status"]
380 ["State"] = "Enabled";
381 }
382 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700383
384 memoryHealth->inventory.emplace_back(path);
385 }
386 else if (interfaceName ==
387 "xyz.openbmc_project.Inventory.Item.Cpu")
388 {
389 BMCWEB_LOG_DEBUG
390 << "Found Cpu, now get its properties.";
391
392 getProcessorSummary(aResp, connection.first, path);
393
394 cpuHealth->inventory.emplace_back(path);
395 }
396 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
397 {
398 BMCWEB_LOG_DEBUG
399 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200400
401 sdbusplus::asio::getAllProperties(
402 *crow::connections::systemBus, connection.first,
403 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800404 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700405 const dbus::utility::DBusPropertiesMap&
406 properties) {
407 if (ec3)
408 {
409 BMCWEB_LOG_DEBUG << "DBUS response error "
410 << ec3;
411 messages::internalError(aResp->res);
412 return;
413 }
414 BMCWEB_LOG_DEBUG << "Got " << properties.size()
415 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700416
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200417 const std::string* uUID = nullptr;
418
419 const bool success =
420 sdbusplus::unpackPropertiesNoThrow(
421 dbus_utils::UnpackErrorPrinter(),
422 properties, "UUID", uUID);
423
424 if (!success)
425 {
426 messages::internalError(aResp->res);
427 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700428 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200429
430 if (uUID != nullptr)
431 {
432 std::string valueStr = *uUID;
433 if (valueStr.size() == 32)
434 {
435 valueStr.insert(8, 1, '-');
436 valueStr.insert(13, 1, '-');
437 valueStr.insert(18, 1, '-');
438 valueStr.insert(23, 1, '-');
439 }
440 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
441 aResp->res.jsonValue["UUID"] = valueStr;
442 }
443 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700444 }
445 else if (interfaceName ==
446 "xyz.openbmc_project.Inventory.Item.System")
447 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200448 sdbusplus::asio::getAllProperties(
449 *crow::connections::systemBus, connection.first,
450 path,
451 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800452 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700453 const dbus::utility::DBusPropertiesMap&
454 propertiesList) {
455 if (ec2)
456 {
457 // doesn't have to include this
458 // interface
459 return;
460 }
461 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
462 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200463
464 const std::string* partNumber = nullptr;
465 const std::string* serialNumber = nullptr;
466 const std::string* manufacturer = nullptr;
467 const std::string* model = nullptr;
468 const std::string* subModel = nullptr;
469
470 const bool success =
471 sdbusplus::unpackPropertiesNoThrow(
472 dbus_utils::UnpackErrorPrinter(),
473 propertiesList, "PartNumber", partNumber,
474 "SerialNumber", serialNumber,
475 "Manufacturer", manufacturer, "Model",
476 model, "SubModel", subModel);
477
478 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700479 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200480 messages::internalError(aResp->res);
481 return;
482 }
483
484 if (partNumber != nullptr)
485 {
486 aResp->res.jsonValue["PartNumber"] =
487 *partNumber;
488 }
489
490 if (serialNumber != nullptr)
491 {
492 aResp->res.jsonValue["SerialNumber"] =
493 *serialNumber;
494 }
495
496 if (manufacturer != nullptr)
497 {
498 aResp->res.jsonValue["Manufacturer"] =
499 *manufacturer;
500 }
501
502 if (model != nullptr)
503 {
504 aResp->res.jsonValue["Model"] = *model;
505 }
506
507 if (subModel != nullptr)
508 {
509 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700510 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500511
Ed Tanous002d39b2022-05-31 08:59:27 -0700512 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700513 sw_util::populateSoftwareInformation(
514 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700515 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200516 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700517
Ed Tanous002d39b2022-05-31 08:59:27 -0700518 sdbusplus::asio::getProperty<std::string>(
519 *crow::connections::systemBus, connection.first,
520 path,
521 "xyz.openbmc_project.Inventory.Decorator."
522 "AssetTag",
523 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800524 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700525 const std::string& value) {
526 if (ec2)
527 {
528 // doesn't have to include this
529 // interface
530 return;
531 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700532
Ed Tanous002d39b2022-05-31 08:59:27 -0700533 aResp->res.jsonValue["AssetTag"] = value;
534 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700535 }
536 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200537 break;
Ed Tanous6c34de42018-08-29 13:37:36 -0700538 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700539 }
Ed Tanous66173382018-08-15 18:20:59 -0700540 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700541}
542
543/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700544 * @brief Retrieves host state properties over dbus
545 *
546 * @param[in] aResp Shared pointer for completing asynchronous calls.
547 *
548 * @return None.
549 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800550inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700551{
552 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700553 sdbusplus::asio::getProperty<std::string>(
554 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
555 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
556 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800557 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700558 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 if (ec)
560 {
561 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700562 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700563 // Service not available, no error, just don't return
564 // host state info
565 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700566 return;
567 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700568 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
569 messages::internalError(aResp->res);
570 return;
571 }
Ed Tanous66173382018-08-15 18:20:59 -0700572
Ed Tanous002d39b2022-05-31 08:59:27 -0700573 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
574 // Verify Host State
575 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
576 {
577 aResp->res.jsonValue["PowerState"] = "On";
578 aResp->res.jsonValue["Status"]["State"] = "Enabled";
579 }
580 else if (hostState ==
581 "xyz.openbmc_project.State.Host.HostState.Quiesced")
582 {
583 aResp->res.jsonValue["PowerState"] = "On";
584 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
585 }
586 else if (hostState ==
587 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
588 {
589 aResp->res.jsonValue["PowerState"] = "On";
590 aResp->res.jsonValue["Status"]["State"] = "InTest";
591 }
592 else if (
593 hostState ==
594 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
595 {
596 aResp->res.jsonValue["PowerState"] = "PoweringOn";
597 aResp->res.jsonValue["Status"]["State"] = "Starting";
598 }
599 else if (hostState ==
600 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
601 {
602 aResp->res.jsonValue["PowerState"] = "PoweringOff";
603 aResp->res.jsonValue["Status"]["State"] = "Disabled";
604 }
605 else
606 {
607 aResp->res.jsonValue["PowerState"] = "Off";
608 aResp->res.jsonValue["Status"]["State"] = "Disabled";
609 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700610 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700611}
612
613/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500614 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530615 *
616 * @param[in] dbusSource The boot source in DBUS speak.
617 *
618 * @return Returns as a string, the boot source in Redfish terms. If translation
619 * cannot be done, returns an empty string.
620 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000621inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530622{
623 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
624 {
625 return "None";
626 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700627 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530628 {
629 return "Hdd";
630 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700631 if (dbusSource ==
632 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530633 {
634 return "Cd";
635 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700636 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530637 {
638 return "Pxe";
639 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700640 if (dbusSource ==
641 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700642 {
643 return "Usb";
644 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700645 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530646}
647
648/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300649 * @brief Translates boot type DBUS property value to redfish.
650 *
651 * @param[in] dbusType The boot type in DBUS speak.
652 *
653 * @return Returns as a string, the boot type in Redfish terms. If translation
654 * cannot be done, returns an empty string.
655 */
656inline std::string dbusToRfBootType(const std::string& dbusType)
657{
658 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
659 {
660 return "Legacy";
661 }
662 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
663 {
664 return "UEFI";
665 }
666 return "";
667}
668
669/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500670 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530671 *
672 * @param[in] dbusMode The boot mode in DBUS speak.
673 *
674 * @return Returns as a string, the boot mode in Redfish terms. If translation
675 * cannot be done, returns an empty string.
676 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000677inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530678{
679 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
680 {
681 return "None";
682 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700683 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530684 {
685 return "Diags";
686 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700687 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530688 {
689 return "BiosSetup";
690 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700691 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530692}
693
694/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600695 * @brief Translates boot progress DBUS property value to redfish.
696 *
697 * @param[in] dbusBootProgress The boot progress in DBUS speak.
698 *
699 * @return Returns as a string, the boot progress in Redfish terms. If
700 * translation cannot be done, returns "None".
701 */
702inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
703{
704 // Now convert the D-Bus BootProgress to the appropriate Redfish
705 // enum
706 std::string rfBpLastState = "None";
707 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
708 "ProgressStages.Unspecified")
709 {
710 rfBpLastState = "None";
711 }
712 else if (dbusBootProgress ==
713 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
714 "PrimaryProcInit")
715 {
716 rfBpLastState = "PrimaryProcessorInitializationStarted";
717 }
718 else if (dbusBootProgress ==
719 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
720 "BusInit")
721 {
722 rfBpLastState = "BusInitializationStarted";
723 }
724 else if (dbusBootProgress ==
725 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
726 "MemoryInit")
727 {
728 rfBpLastState = "MemoryInitializationStarted";
729 }
730 else if (dbusBootProgress ==
731 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
732 "SecondaryProcInit")
733 {
734 rfBpLastState = "SecondaryProcessorInitializationStarted";
735 }
736 else if (dbusBootProgress ==
737 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
738 "PCIInit")
739 {
740 rfBpLastState = "PCIResourceConfigStarted";
741 }
742 else if (dbusBootProgress ==
743 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
744 "SystemSetup")
745 {
746 rfBpLastState = "SetupEntered";
747 }
748 else if (dbusBootProgress ==
749 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
750 "SystemInitComplete")
751 {
752 rfBpLastState = "SystemHardwareInitializationComplete";
753 }
754 else if (dbusBootProgress ==
755 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
756 "OSStart")
757 {
758 rfBpLastState = "OSBootStarted";
759 }
760 else if (dbusBootProgress ==
761 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
762 "OSRunning")
763 {
764 rfBpLastState = "OSRunning";
765 }
766 else
767 {
768 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
769 << dbusBootProgress;
770 // Just return the default
771 }
772 return rfBpLastState;
773}
774
775/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500776 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530777 *
778 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700779 * @param[out] bootSource The DBus source
780 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530781 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700782 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530783 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800784inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500785 const std::string& rfSource,
786 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530787{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300788 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
789 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700790
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530791 if (rfSource == "None")
792 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700793 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530794 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700795 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530796 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700797 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
798 }
799 else if (rfSource == "Hdd")
800 {
801 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
802 }
803 else if (rfSource == "Diags")
804 {
805 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
806 }
807 else if (rfSource == "Cd")
808 {
809 bootSource =
810 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
811 }
812 else if (rfSource == "BiosSetup")
813 {
814 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530815 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700816 else if (rfSource == "Usb")
817 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700818 bootSource =
819 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700820 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530821 else
822 {
George Liu0fda0f12021-11-16 10:06:17 +0800823 BMCWEB_LOG_DEBUG
824 << "Invalid property value for BootSourceOverrideTarget: "
825 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700826 messages::propertyValueNotInList(aResp->res, rfSource,
827 "BootSourceTargetOverride");
828 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530829 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700830 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530831}
Ali Ahmed19817712021-06-29 17:01:52 -0500832
Andrew Geissler978b8802020-11-19 13:36:40 -0600833/**
834 * @brief Retrieves boot progress of the system
835 *
836 * @param[in] aResp Shared pointer for generating response message.
837 *
838 * @return None.
839 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800840inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600841{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700842 sdbusplus::asio::getProperty<std::string>(
843 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
844 "/xyz/openbmc_project/state/host0",
845 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800846 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700847 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700848 if (ec)
849 {
850 // BootProgress is an optional object so just do nothing if
851 // not found
852 return;
853 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600854
Ed Tanous002d39b2022-05-31 08:59:27 -0700855 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600856
Ed Tanous002d39b2022-05-31 08:59:27 -0700857 aResp->res.jsonValue["BootProgress"]["LastState"] =
858 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700859 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600860}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530861
862/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000863 * @brief Retrieves boot progress Last Update of the system
864 *
865 * @param[in] aResp Shared pointer for generating response message.
866 *
867 * @return None.
868 */
869inline void getBootProgressLastStateTime(
870 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
871{
872 sdbusplus::asio::getProperty<uint64_t>(
873 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
874 "/xyz/openbmc_project/state/host0",
875 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800876 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000877 const uint64_t lastStateTime) {
878 if (ec)
879 {
880 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
881 return;
882 }
883
884 // BootProgressLastUpdate is the last time the BootProgress property
885 // was updated. The time is the Epoch time, number of microseconds
886 // since 1 Jan 1970 00::00::00 UTC."
887 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
888 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
889
890 // Convert to ISO 8601 standard
891 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
892 redfish::time_utils::getDateTimeUintUs(lastStateTime);
893 });
894}
895
896/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300897 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300898 *
899 * @param[in] aResp Shared pointer for generating response message.
900 *
901 * @return None.
902 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300903
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300904inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300905{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700906 sdbusplus::asio::getProperty<std::string>(
907 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
908 "/xyz/openbmc_project/control/host0/boot",
909 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800910 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700911 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700912 if (ec)
913 {
914 // not an error, don't have to have the interface
915 return;
916 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300917
Ed Tanous002d39b2022-05-31 08:59:27 -0700918 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300919
Ed Tanous002d39b2022-05-31 08:59:27 -0700920 aResp->res.jsonValue["Boot"]
921 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700922 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923
Ed Tanous002d39b2022-05-31 08:59:27 -0700924 auto rfType = dbusToRfBootType(bootType);
925 if (rfType.empty())
926 {
927 messages::internalError(aResp->res);
928 return;
929 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300930
Ed Tanous002d39b2022-05-31 08:59:27 -0700931 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700932 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300933}
934
935/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300936 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530937 *
938 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530939 *
940 * @return None.
941 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300942
943inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700945 sdbusplus::asio::getProperty<std::string>(
946 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
947 "/xyz/openbmc_project/control/host0/boot",
948 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800949 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700950 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700951 if (ec)
952 {
953 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
954 messages::internalError(aResp->res);
955 return;
956 }
957
958 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
959
960 aResp->res
961 .jsonValue["Boot"]
962 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
963 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
964
965 if (bootModeStr !=
966 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
967 {
968 auto rfMode = dbusToRfBootMode(bootModeStr);
969 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530970 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700971 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
972 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530973 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700974 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700975 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530976}
977
978/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300979 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530980 *
981 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530982 *
983 * @return None.
984 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300985
986inline void
987 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530988{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700989 sdbusplus::asio::getProperty<std::string>(
990 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
991 "/xyz/openbmc_project/control/host0/boot",
992 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800993 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700994 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700995 if (ec)
996 {
997 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +0000998 if (ec.value() == boost::asio::error::host_unreachable)
999 {
1000 return;
1001 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001002 messages::internalError(aResp->res);
1003 return;
1004 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301005
Ed Tanous002d39b2022-05-31 08:59:27 -07001006 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301007
Ed Tanous002d39b2022-05-31 08:59:27 -07001008 auto rfSource = dbusToRfBootSource(bootSourceStr);
1009 if (!rfSource.empty())
1010 {
1011 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1012 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001013
Ed Tanous002d39b2022-05-31 08:59:27 -07001014 // Get BootMode as BootSourceOverrideTarget is constructed
1015 // from both BootSource and BootMode
1016 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001017 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301018}
1019
1020/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001021 * @brief This functions abstracts all the logic behind getting a
1022 * "BootSourceOverrideEnabled" property from an overall boot override enable
1023 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301024 *
1025 * @param[in] aResp Shared pointer for generating response message.
1026 *
1027 * @return None.
1028 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001030inline void
1031 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1032 const bool bootOverrideEnableSetting)
1033{
1034 if (!bootOverrideEnableSetting)
1035 {
1036 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1037 return;
1038 }
1039
1040 // If boot source override is enabled, we need to check 'one_time'
1041 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001042 sdbusplus::asio::getProperty<bool>(
1043 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1044 "/xyz/openbmc_project/control/host0/boot/one_time",
1045 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001046 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001047 if (ec)
1048 {
1049 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1050 messages::internalError(aResp->res);
1051 return;
1052 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301053
Ed Tanous002d39b2022-05-31 08:59:27 -07001054 if (oneTimeSetting)
1055 {
1056 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1057 }
1058 else
1059 {
1060 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1061 "Continuous";
1062 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001063 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301064}
1065
1066/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001067 * @brief Retrieves boot override enable over DBUS
1068 *
1069 * @param[in] aResp Shared pointer for generating response message.
1070 *
1071 * @return None.
1072 */
1073
1074inline void
1075 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1076{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001077 sdbusplus::asio::getProperty<bool>(
1078 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1079 "/xyz/openbmc_project/control/host0/boot",
1080 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001081 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001082 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001083 if (ec)
1084 {
1085 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001086 if (ec.value() == boost::asio::error::host_unreachable)
1087 {
1088 return;
1089 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001090 messages::internalError(aResp->res);
1091 return;
1092 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001093
Ed Tanous002d39b2022-05-31 08:59:27 -07001094 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001095 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001096}
1097
1098/**
1099 * @brief Retrieves boot source override properties
1100 *
1101 * @param[in] aResp Shared pointer for generating response message.
1102 *
1103 * @return None.
1104 */
1105inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1106{
1107 BMCWEB_LOG_DEBUG << "Get boot information.";
1108
1109 getBootOverrideSource(aResp);
1110 getBootOverrideType(aResp);
1111 getBootOverrideEnable(aResp);
1112}
1113
1114/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001115 * @brief Retrieves the Last Reset Time
1116 *
1117 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1118 * and power off. Even though this is the "system" Redfish object look at the
1119 * chassis D-Bus interface for the LastStateChangeTime since this has the
1120 * last power operation time.
1121 *
1122 * @param[in] aResp Shared pointer for generating response message.
1123 *
1124 * @return None.
1125 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001126inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001127{
1128 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1129
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001130 sdbusplus::asio::getProperty<uint64_t>(
1131 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1132 "/xyz/openbmc_project/state/chassis0",
1133 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001134 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001135 if (ec)
1136 {
1137 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1138 return;
1139 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001140
Ed Tanous002d39b2022-05-31 08:59:27 -07001141 // LastStateChangeTime is epoch time, in milliseconds
1142 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1143 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001144
Ed Tanous002d39b2022-05-31 08:59:27 -07001145 // Convert to ISO 8601 standard
1146 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001147 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001148 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001149}
1150
1151/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001152 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1153 *
1154 * @param[in] aResp Shared pointer for generating response message.
1155 *
1156 * @return None.
1157 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001158inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001159{
1160 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1161
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001162 sdbusplus::asio::getProperty<bool>(
1163 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1164 "/xyz/openbmc_project/control/host0/auto_reboot",
1165 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001166 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001167 if (ec)
1168 {
1169 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1170 return;
1171 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001172
Ed Tanous002d39b2022-05-31 08:59:27 -07001173 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1174 if (autoRebootEnabled)
1175 {
1176 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1177 "RetryAttempts";
1178 // If AutomaticRetry (AutoReboot) is enabled see how many
1179 // attempts are left
1180 sdbusplus::asio::getProperty<uint32_t>(
1181 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1182 "/xyz/openbmc_project/state/host0",
1183 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1184 "AttemptsLeft",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001185 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07001186 const uint32_t autoRebootAttemptsLeft) {
1187 if (ec2)
1188 {
1189 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2;
1190 return;
1191 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001192
Ed Tanous002d39b2022-05-31 08:59:27 -07001193 BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: "
1194 << autoRebootAttemptsLeft;
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001195
Ed Tanous002d39b2022-05-31 08:59:27 -07001196 aResp->res
1197 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1198 autoRebootAttemptsLeft;
1199 });
1200 }
1201 else
1202 {
1203 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1204 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001205
Ed Tanous002d39b2022-05-31 08:59:27 -07001206 // Not on D-Bus. Hardcoded here:
1207 // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71
1208 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3;
Gunnar Mills69f35302020-05-17 16:06:31 -05001209
Ed Tanous002d39b2022-05-31 08:59:27 -07001210 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1211 // and RetryAttempts. OpenBMC only supports Disabled and
1212 // RetryAttempts.
1213 aResp->res.jsonValue["Boot"]
1214 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1215 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001216 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001217}
1218
1219/**
George Liuc6a620f2020-04-10 17:18:11 +08001220 * @brief Retrieves power restore policy over DBUS.
1221 *
1222 * @param[in] aResp Shared pointer for generating response message.
1223 *
1224 * @return None.
1225 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001226inline void
1227 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001228{
1229 BMCWEB_LOG_DEBUG << "Get power restore policy";
1230
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001231 sdbusplus::asio::getProperty<std::string>(
1232 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1233 "/xyz/openbmc_project/control/host0/power_restore_policy",
1234 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001235 [aResp](const boost::system::error_code& ec,
1236 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001237 if (ec)
1238 {
1239 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1240 return;
1241 }
George Liuc6a620f2020-04-10 17:18:11 +08001242
Ed Tanous002d39b2022-05-31 08:59:27 -07001243 const boost::container::flat_map<std::string, std::string> policyMaps = {
1244 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1245 "AlwaysOn"},
1246 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1247 "AlwaysOff"},
1248 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1249 "LastState"},
1250 // Return `AlwaysOff` when power restore policy set to "None"
1251 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1252 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001253
Ed Tanous002d39b2022-05-31 08:59:27 -07001254 auto policyMapsIt = policyMaps.find(policy);
1255 if (policyMapsIt == policyMaps.end())
1256 {
1257 messages::internalError(aResp->res);
1258 return;
1259 }
George Liuc6a620f2020-04-10 17:18:11 +08001260
Ed Tanous002d39b2022-05-31 08:59:27 -07001261 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001262 });
George Liuc6a620f2020-04-10 17:18:11 +08001263}
1264
1265/**
Ali Ahmed19817712021-06-29 17:01:52 -05001266 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1267 * TPM is required for booting the host.
1268 *
1269 * @param[in] aResp Shared pointer for generating response message.
1270 *
1271 * @return None.
1272 */
1273inline void getTrustedModuleRequiredToBoot(
1274 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1275{
1276 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001277 constexpr std::array<std::string_view, 1> interfaces = {
1278 "xyz.openbmc_project.Control.TPM.Policy"};
1279 dbus::utility::getSubTree(
1280 "/", 0, interfaces,
1281 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001282 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001283 if (ec)
1284 {
1285 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1286 << ec;
1287 // This is an optional D-Bus object so just return if
1288 // error occurs
1289 return;
1290 }
1291 if (subtree.empty())
1292 {
1293 // As noted above, this is an optional interface so just return
1294 // if there is no instance found
1295 return;
1296 }
1297
1298 /* When there is more than one TPMEnable object... */
1299 if (subtree.size() > 1)
1300 {
1301 BMCWEB_LOG_DEBUG
1302 << "DBUS response has more than 1 TPM Enable object:"
1303 << subtree.size();
1304 // Throw an internal Error and return
1305 messages::internalError(aResp->res);
1306 return;
1307 }
1308
1309 // Make sure the Dbus response map has a service and objectPath
1310 // field
1311 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1312 {
1313 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1314 messages::internalError(aResp->res);
1315 return;
1316 }
1317
1318 const std::string& path = subtree[0].first;
1319 const std::string& serv = subtree[0].second.begin()->first;
1320
1321 // Valid TPM Enable object found, now reading the current value
1322 sdbusplus::asio::getProperty<bool>(
1323 *crow::connections::systemBus, serv, path,
1324 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001325 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001326 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001327 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001328 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001329 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001330 messages::internalError(aResp->res);
1331 return;
1332 }
1333
Ed Tanous002d39b2022-05-31 08:59:27 -07001334 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001335 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001336 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1337 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001338 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001339 else
1340 {
1341 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1342 "Disabled";
1343 }
1344 });
George Liue99073f2022-12-09 11:06:16 +08001345 });
Ali Ahmed19817712021-06-29 17:01:52 -05001346}
1347
1348/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001349 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1350 * TPM is required for booting the host.
1351 *
1352 * @param[in] aResp Shared pointer for generating response message.
1353 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1354 *
1355 * @return None.
1356 */
1357inline void setTrustedModuleRequiredToBoot(
1358 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1359{
1360 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001361 constexpr std::array<std::string_view, 1> interfaces = {
1362 "xyz.openbmc_project.Control.TPM.Policy"};
1363 dbus::utility::getSubTree(
1364 "/", 0, interfaces,
1365 [aResp,
1366 tpmRequired](const boost::system::error_code& ec,
1367 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001368 if (ec)
1369 {
1370 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1371 << ec;
1372 messages::internalError(aResp->res);
1373 return;
1374 }
1375 if (subtree.empty())
1376 {
1377 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1378 "TrustedModuleRequiredToBoot");
1379 return;
1380 }
1381
1382 /* When there is more than one TPMEnable object... */
1383 if (subtree.size() > 1)
1384 {
1385 BMCWEB_LOG_DEBUG
1386 << "DBUS response has more than 1 TPM Enable object:"
1387 << subtree.size();
1388 // Throw an internal Error and return
1389 messages::internalError(aResp->res);
1390 return;
1391 }
1392
1393 // Make sure the Dbus response map has a service and objectPath
1394 // field
1395 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1396 {
1397 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1398 messages::internalError(aResp->res);
1399 return;
1400 }
1401
1402 const std::string& path = subtree[0].first;
1403 const std::string& serv = subtree[0].second.begin()->first;
1404
1405 if (serv.empty())
1406 {
1407 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1408 messages::internalError(aResp->res);
1409 return;
1410 }
1411
1412 // Valid TPM Enable object found, now setting the value
1413 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001414 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001415 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001416 {
1417 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001418 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001419 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001420 messages::internalError(aResp->res);
1421 return;
1422 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001423 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1424 },
1425 serv, path, "org.freedesktop.DBus.Properties", "Set",
1426 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1427 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001428 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001429}
1430
1431/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301432 * @brief Sets boot properties into DBUS object(s).
1433 *
1434 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001435 * @param[in] bootType The boot type to set.
1436 * @return Integer error code.
1437 */
1438inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001439 const std::optional<std::string>& bootType)
1440{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001441 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001442
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001443 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001444 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001445 return;
1446 }
1447
1448 // Source target specified
1449 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1450 // Figure out which DBUS interface and property to use
1451 if (*bootType == "Legacy")
1452 {
1453 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1454 }
1455 else if (*bootType == "UEFI")
1456 {
1457 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1458 }
1459 else
1460 {
1461 BMCWEB_LOG_DEBUG << "Invalid property value for "
1462 "BootSourceOverrideMode: "
1463 << *bootType;
1464 messages::propertyValueNotInList(aResp->res, *bootType,
1465 "BootSourceOverrideMode");
1466 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001467 }
1468
1469 // Act on validated parameters
1470 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1471
1472 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001473 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001474 if (ec)
1475 {
1476 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1477 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001478 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001479 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001480 return;
1481 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001482 messages::internalError(aResp->res);
1483 return;
1484 }
1485 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001486 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001487 "xyz.openbmc_project.Settings",
1488 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001489 "org.freedesktop.DBus.Properties", "Set",
1490 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001491 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001492}
1493
1494/**
1495 * @brief Sets boot properties into DBUS object(s).
1496 *
1497 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001498 * @param[in] bootType The boot type to set.
1499 * @return Integer error code.
1500 */
1501inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1502 const std::optional<std::string>& bootEnable)
1503{
1504 if (!bootEnable)
1505 {
1506 return;
1507 }
1508 // Source target specified
1509 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1510
1511 bool bootOverrideEnable = false;
1512 bool bootOverridePersistent = false;
1513 // Figure out which DBUS interface and property to use
1514 if (*bootEnable == "Disabled")
1515 {
1516 bootOverrideEnable = false;
1517 }
1518 else if (*bootEnable == "Once")
1519 {
1520 bootOverrideEnable = true;
1521 bootOverridePersistent = false;
1522 }
1523 else if (*bootEnable == "Continuous")
1524 {
1525 bootOverrideEnable = true;
1526 bootOverridePersistent = true;
1527 }
1528 else
1529 {
George Liu0fda0f12021-11-16 10:06:17 +08001530 BMCWEB_LOG_DEBUG
1531 << "Invalid property value for BootSourceOverrideEnabled: "
1532 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001533 messages::propertyValueNotInList(aResp->res, *bootEnable,
1534 "BootSourceOverrideEnabled");
1535 return;
1536 }
1537
1538 // Act on validated parameters
1539 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1540
1541 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001542 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001543 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001544 {
Ed Tanous8a592812022-06-04 09:06:59 -07001545 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001546 messages::internalError(aResp->res);
1547 return;
1548 }
1549 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001550 },
1551 "xyz.openbmc_project.Settings",
1552 "/xyz/openbmc_project/control/host0/boot",
1553 "org.freedesktop.DBus.Properties", "Set",
1554 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001555 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001556
1557 if (!bootOverrideEnable)
1558 {
1559 return;
1560 }
1561
1562 // In case boot override is enabled we need to set correct value for the
1563 // 'one_time' enable DBus interface
1564 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1565 << bootOverridePersistent;
1566
1567 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001568 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001569 if (ec)
1570 {
1571 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1572 messages::internalError(aResp->res);
1573 return;
1574 }
1575 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001576 },
1577 "xyz.openbmc_project.Settings",
1578 "/xyz/openbmc_project/control/host0/boot/one_time",
1579 "org.freedesktop.DBus.Properties", "Set",
1580 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001581 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001582}
1583
1584/**
1585 * @brief Sets boot properties into DBUS object(s).
1586 *
1587 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301588 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301589 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001590 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301591 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001592inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001593 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301594{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001595 std::string bootSourceStr;
1596 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001597
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001598 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301599 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001600 return;
1601 }
1602
1603 // Source target specified
1604 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1605 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001606 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1607 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001608 {
1609 BMCWEB_LOG_DEBUG
1610 << "Invalid property value for BootSourceOverrideTarget: "
1611 << *bootSource;
1612 messages::propertyValueNotInList(aResp->res, *bootSource,
1613 "BootSourceTargetOverride");
1614 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001615 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301616
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001617 // Act on validated parameters
1618 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1619 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001620
1621 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001622 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001623 if (ec)
1624 {
1625 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1626 messages::internalError(aResp->res);
1627 return;
1628 }
1629 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001630 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001631 "xyz.openbmc_project.Settings",
1632 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001633 "org.freedesktop.DBus.Properties", "Set",
1634 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001635 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001636
1637 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001638 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001639 if (ec)
1640 {
1641 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1642 messages::internalError(aResp->res);
1643 return;
1644 }
1645 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001646 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001647 "xyz.openbmc_project.Settings",
1648 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001649 "org.freedesktop.DBus.Properties", "Set",
1650 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001651 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001652}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001653
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001654/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001655 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301656 *
1657 * @param[in] aResp Shared pointer for generating response message.
1658 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001659 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301660 * @param[in] bootEnable The boot override enable from incoming RF request.
1661 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001662 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301663 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001664
1665inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1666 const std::optional<std::string>& bootSource,
1667 const std::optional<std::string>& bootType,
1668 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301669{
1670 BMCWEB_LOG_DEBUG << "Set boot information.";
1671
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001672 setBootModeOrSource(aResp, bootSource);
1673 setBootType(aResp, bootType);
1674 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301675}
1676
George Liuc6a620f2020-04-10 17:18:11 +08001677/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001678 * @brief Sets AssetTag
1679 *
1680 * @param[in] aResp Shared pointer for generating response message.
1681 * @param[in] assetTag "AssetTag" from request.
1682 *
1683 * @return None.
1684 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001685inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001686 const std::string& assetTag)
1687{
George Liue99073f2022-12-09 11:06:16 +08001688 constexpr std::array<std::string_view, 1> interfaces = {
1689 "xyz.openbmc_project.Inventory.Item.System"};
1690 dbus::utility::getSubTree(
1691 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001692 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001693 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001694 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001695 if (ec)
1696 {
1697 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1698 messages::internalError(aResp->res);
1699 return;
1700 }
1701 if (subtree.empty())
1702 {
1703 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1704 messages::internalError(aResp->res);
1705 return;
1706 }
1707 // Assume only 1 system D-Bus object
1708 // Throw an error if there is more than 1
1709 if (subtree.size() > 1)
1710 {
1711 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1712 messages::internalError(aResp->res);
1713 return;
1714 }
1715 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1716 {
1717 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1718 messages::internalError(aResp->res);
1719 return;
1720 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001721
Ed Tanous002d39b2022-05-31 08:59:27 -07001722 const std::string& path = subtree[0].first;
1723 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001724
Ed Tanous002d39b2022-05-31 08:59:27 -07001725 if (service.empty())
1726 {
1727 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1728 messages::internalError(aResp->res);
1729 return;
1730 }
1731
1732 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001733 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001734 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001735 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001736 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1737 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001738 messages::internalError(aResp->res);
1739 return;
1740 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001741 },
1742 service, path, "org.freedesktop.DBus.Properties", "Set",
1743 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1744 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001745 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001746}
1747
1748/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001749 * @brief Sets automaticRetry (Auto Reboot)
1750 *
1751 * @param[in] aResp Shared pointer for generating response message.
1752 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1753 *
1754 * @return None.
1755 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001756inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001757 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001758{
1759 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1760
1761 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001762 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001763
1764 if (automaticRetryConfig == "Disabled")
1765 {
1766 autoRebootEnabled = false;
1767 }
1768 else if (automaticRetryConfig == "RetryAttempts")
1769 {
1770 autoRebootEnabled = true;
1771 }
1772 else
1773 {
George Liu0fda0f12021-11-16 10:06:17 +08001774 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001775 << automaticRetryConfig;
1776 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1777 "AutomaticRetryConfig");
1778 return;
1779 }
1780
1781 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001782 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001783 if (ec)
1784 {
1785 messages::internalError(aResp->res);
1786 return;
1787 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001788 },
1789 "xyz.openbmc_project.Settings",
1790 "/xyz/openbmc_project/control/host0/auto_reboot",
1791 "org.freedesktop.DBus.Properties", "Set",
1792 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001793 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001794}
1795
1796/**
George Liuc6a620f2020-04-10 17:18:11 +08001797 * @brief Sets power restore policy properties.
1798 *
1799 * @param[in] aResp Shared pointer for generating response message.
1800 * @param[in] policy power restore policy properties from request.
1801 *
1802 * @return None.
1803 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001804inline void
1805 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1806 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001807{
1808 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1809
1810 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001811 {"AlwaysOn",
1812 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1813 {"AlwaysOff",
1814 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1815 {"LastState",
1816 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001817
1818 std::string powerRestorPolicy;
1819
Gunnar Mills4e69c902021-01-05 19:50:11 -06001820 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001821 if (policyMapsIt == policyMaps.end())
1822 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001823 messages::propertyValueNotInList(aResp->res, policy,
1824 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001825 return;
1826 }
1827
1828 powerRestorPolicy = policyMapsIt->second;
1829
1830 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001831 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001832 if (ec)
1833 {
1834 messages::internalError(aResp->res);
1835 return;
1836 }
George Liuc6a620f2020-04-10 17:18:11 +08001837 },
1838 "xyz.openbmc_project.Settings",
1839 "/xyz/openbmc_project/control/host0/power_restore_policy",
1840 "org.freedesktop.DBus.Properties", "Set",
1841 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001842 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001843}
1844
AppaRao Pulia6349912019-10-18 17:16:08 +05301845#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1846/**
1847 * @brief Retrieves provisioning status
1848 *
1849 * @param[in] aResp Shared pointer for completing asynchronous calls.
1850 *
1851 * @return None.
1852 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001853inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301854{
1855 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001856 sdbusplus::asio::getAllProperties(
1857 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1858 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001859 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001860 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001861 nlohmann::json& oemPFR =
1862 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1863 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1864 "#OemComputerSystem.OpenBmc";
1865 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001866
Ed Tanous002d39b2022-05-31 08:59:27 -07001867 if (ec)
1868 {
1869 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1870 // not an error, don't have to have the interface
1871 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1872 return;
1873 }
1874
1875 const bool* provState = nullptr;
1876 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001877
1878 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001879 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1880 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001881
1882 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001883 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001884 messages::internalError(aResp->res);
1885 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001886 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301887
Ed Tanous002d39b2022-05-31 08:59:27 -07001888 if ((provState == nullptr) || (lockState == nullptr))
1889 {
1890 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1891 messages::internalError(aResp->res);
1892 return;
1893 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301894
Ed Tanous002d39b2022-05-31 08:59:27 -07001895 if (*provState == true)
1896 {
1897 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301898 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001899 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301900 }
1901 else
1902 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001903 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301904 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001905 }
1906 else
1907 {
1908 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1909 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001910 });
AppaRao Pulia6349912019-10-18 17:16:08 +05301911}
1912#endif
1913
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301914/**
Chris Cain3a2d04242021-05-28 16:57:10 -05001915 * @brief Translate the PowerMode to a response message.
1916 *
1917 * @param[in] aResp Shared pointer for generating response message.
1918 * @param[in] modeValue PowerMode value to be translated
1919 *
1920 * @return None.
1921 */
1922inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1923 const std::string& modeValue)
1924{
George Liu0fda0f12021-11-16 10:06:17 +08001925 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05001926 {
1927 aResp->res.jsonValue["PowerMode"] = "Static";
1928 }
George Liu0fda0f12021-11-16 10:06:17 +08001929 else if (
1930 modeValue ==
1931 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05001932 {
1933 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
1934 }
George Liu0fda0f12021-11-16 10:06:17 +08001935 else if (modeValue ==
1936 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05001937 {
1938 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
1939 }
George Liu0fda0f12021-11-16 10:06:17 +08001940 else if (modeValue ==
1941 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05001942 {
1943 aResp->res.jsonValue["PowerMode"] = "OEM";
1944 }
1945 else
1946 {
1947 // Any other values would be invalid
1948 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
1949 messages::internalError(aResp->res);
1950 }
1951}
1952
1953/**
1954 * @brief Retrieves system power mode
1955 *
1956 * @param[in] aResp Shared pointer for generating response message.
1957 *
1958 * @return None.
1959 */
1960inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1961{
1962 BMCWEB_LOG_DEBUG << "Get power mode.";
1963
1964 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08001965 constexpr std::array<std::string_view, 1> interfaces = {
1966 "xyz.openbmc_project.Control.Power.Mode"};
1967 dbus::utility::getSubTree(
1968 "/", 0, interfaces,
1969 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001970 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001971 if (ec)
1972 {
1973 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
1974 << ec;
1975 // This is an optional D-Bus object so just return if
1976 // error occurs
1977 return;
1978 }
1979 if (subtree.empty())
1980 {
1981 // As noted above, this is an optional interface so just return
1982 // if there is no instance found
1983 return;
1984 }
1985 if (subtree.size() > 1)
1986 {
1987 // More then one PowerMode object is not supported and is an
1988 // error
1989 BMCWEB_LOG_DEBUG
1990 << "Found more than 1 system D-Bus Power.Mode objects: "
1991 << subtree.size();
1992 messages::internalError(aResp->res);
1993 return;
1994 }
1995 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
1996 {
1997 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
1998 messages::internalError(aResp->res);
1999 return;
2000 }
2001 const std::string& path = subtree[0].first;
2002 const std::string& service = subtree[0].second.begin()->first;
2003 if (service.empty())
2004 {
2005 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2006 messages::internalError(aResp->res);
2007 return;
2008 }
2009 // Valid Power Mode object found, now read the current value
2010 sdbusplus::asio::getProperty<std::string>(
2011 *crow::connections::systemBus, service, path,
2012 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002013 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002014 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002015 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002016 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002017 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002018 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002019 messages::internalError(aResp->res);
2020 return;
2021 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002022
Ed Tanous002d39b2022-05-31 08:59:27 -07002023 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2024 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002025
Ed Tanous002d39b2022-05-31 08:59:27 -07002026 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2027 translatePowerMode(aResp, pmode);
2028 });
George Liue99073f2022-12-09 11:06:16 +08002029 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002030}
2031
2032/**
2033 * @brief Validate the specified mode is valid and return the PowerMode
2034 * name associated with that string
2035 *
2036 * @param[in] aResp Shared pointer for generating response message.
2037 * @param[in] modeString String representing the desired PowerMode
2038 *
2039 * @return PowerMode value or empty string if mode is not valid
2040 */
2041inline std::string
2042 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2043 const std::string& modeString)
2044{
2045 std::string mode;
2046
2047 if (modeString == "Static")
2048 {
2049 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2050 }
2051 else if (modeString == "MaximumPerformance")
2052 {
George Liu0fda0f12021-11-16 10:06:17 +08002053 mode =
2054 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002055 }
2056 else if (modeString == "PowerSaving")
2057 {
2058 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2059 }
2060 else
2061 {
2062 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2063 }
2064 return mode;
2065}
2066
2067/**
2068 * @brief Sets system power mode.
2069 *
2070 * @param[in] aResp Shared pointer for generating response message.
2071 * @param[in] pmode System power mode from request.
2072 *
2073 * @return None.
2074 */
2075inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2076 const std::string& pmode)
2077{
2078 BMCWEB_LOG_DEBUG << "Set power mode.";
2079
2080 std::string powerMode = validatePowerMode(aResp, pmode);
2081 if (powerMode.empty())
2082 {
2083 return;
2084 }
2085
2086 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002087 constexpr std::array<std::string_view, 1> interfaces = {
2088 "xyz.openbmc_project.Control.Power.Mode"};
2089 dbus::utility::getSubTree(
2090 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002091 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002092 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002093 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002094 if (ec)
2095 {
2096 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2097 << ec;
2098 // This is an optional D-Bus object, but user attempted to patch
2099 messages::internalError(aResp->res);
2100 return;
2101 }
2102 if (subtree.empty())
2103 {
2104 // This is an optional D-Bus object, but user attempted to patch
2105 messages::resourceNotFound(aResp->res, "ComputerSystem",
2106 "PowerMode");
2107 return;
2108 }
2109 if (subtree.size() > 1)
2110 {
2111 // More then one PowerMode object is not supported and is an
2112 // error
2113 BMCWEB_LOG_DEBUG
2114 << "Found more than 1 system D-Bus Power.Mode objects: "
2115 << subtree.size();
2116 messages::internalError(aResp->res);
2117 return;
2118 }
2119 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2120 {
2121 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2122 messages::internalError(aResp->res);
2123 return;
2124 }
2125 const std::string& path = subtree[0].first;
2126 const std::string& service = subtree[0].second.begin()->first;
2127 if (service.empty())
2128 {
2129 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2130 messages::internalError(aResp->res);
2131 return;
2132 }
2133
2134 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2135 << path;
2136
2137 // Set the Power Mode property
2138 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002139 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002140 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002141 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002142 messages::internalError(aResp->res);
2143 return;
2144 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002145 },
2146 service, path, "org.freedesktop.DBus.Properties", "Set",
2147 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2148 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002149 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002150}
2151
2152/**
Yong Li51709ff2019-09-30 14:13:04 +08002153 * @brief Translates watchdog timeout action DBUS property value to redfish.
2154 *
2155 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2156 *
2157 * @return Returns as a string, the timeout action in Redfish terms. If
2158 * translation cannot be done, returns an empty string.
2159 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002160inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002161{
2162 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2163 {
2164 return "None";
2165 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002166 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002167 {
2168 return "ResetSystem";
2169 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002170 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002171 {
2172 return "PowerDown";
2173 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002174 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002175 {
2176 return "PowerCycle";
2177 }
2178
2179 return "";
2180}
2181
2182/**
Yong Lic45f0082019-10-10 14:19:01 +08002183 *@brief Translates timeout action from Redfish to DBUS property value.
2184 *
2185 *@param[in] rfAction The timeout action in Redfish.
2186 *
2187 *@return Returns as a string, the time_out action as expected by DBUS.
2188 *If translation cannot be done, returns an empty string.
2189 */
2190
Ed Tanous23a21a12020-07-25 04:45:05 +00002191inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002192{
2193 if (rfAction == "None")
2194 {
2195 return "xyz.openbmc_project.State.Watchdog.Action.None";
2196 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002197 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002198 {
2199 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2200 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002201 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002202 {
2203 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2204 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002205 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002206 {
2207 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2208 }
2209
2210 return "";
2211}
2212
2213/**
Yong Li51709ff2019-09-30 14:13:04 +08002214 * @brief Retrieves host watchdog timer properties over DBUS
2215 *
2216 * @param[in] aResp Shared pointer for completing asynchronous calls.
2217 *
2218 * @return None.
2219 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002220inline void
2221 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002222{
2223 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002224 sdbusplus::asio::getAllProperties(
2225 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2226 "/xyz/openbmc_project/watchdog/host0",
2227 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002228 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002229 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002230 if (ec)
2231 {
2232 // watchdog service is stopped
2233 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2234 return;
2235 }
2236
2237 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2238
2239 nlohmann::json& hostWatchdogTimer =
2240 aResp->res.jsonValue["HostWatchdogTimer"];
2241
2242 // watchdog service is running/enabled
2243 hostWatchdogTimer["Status"]["State"] = "Enabled";
2244
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002245 const bool* enabled = nullptr;
2246 const std::string* expireAction = nullptr;
2247
2248 const bool success = sdbusplus::unpackPropertiesNoThrow(
2249 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2250 "ExpireAction", expireAction);
2251
2252 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002253 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002254 messages::internalError(aResp->res);
2255 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002256 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002257
2258 if (enabled != nullptr)
2259 {
2260 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2261 }
2262
2263 if (expireAction != nullptr)
2264 {
2265 std::string action = dbusToRfWatchdogAction(*expireAction);
2266 if (action.empty())
2267 {
2268 messages::internalError(aResp->res);
2269 return;
2270 }
2271 hostWatchdogTimer["TimeoutAction"] = action;
2272 }
2273 });
Yong Li51709ff2019-09-30 14:13:04 +08002274}
2275
2276/**
Yong Lic45f0082019-10-10 14:19:01 +08002277 * @brief Sets Host WatchDog Timer properties.
2278 *
2279 * @param[in] aResp Shared pointer for generating response message.
2280 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2281 * RF request.
2282 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2283 *
2284 * @return None.
2285 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002286inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002287 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002288 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002289{
2290 BMCWEB_LOG_DEBUG << "Set host watchdog";
2291
2292 if (wdtTimeOutAction)
2293 {
2294 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2295 // check if TimeOut Action is Valid
2296 if (wdtTimeOutActStr.empty())
2297 {
2298 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2299 << *wdtTimeOutAction;
2300 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2301 "TimeoutAction");
2302 return;
2303 }
2304
2305 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002306 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002307 if (ec)
2308 {
2309 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2310 messages::internalError(aResp->res);
2311 return;
2312 }
Yong Lic45f0082019-10-10 14:19:01 +08002313 },
2314 "xyz.openbmc_project.Watchdog",
2315 "/xyz/openbmc_project/watchdog/host0",
2316 "org.freedesktop.DBus.Properties", "Set",
2317 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002318 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002319 }
2320
2321 if (wdtEnable)
2322 {
2323 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002324 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002325 if (ec)
2326 {
2327 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2328 messages::internalError(aResp->res);
2329 return;
2330 }
Yong Lic45f0082019-10-10 14:19:01 +08002331 },
2332 "xyz.openbmc_project.Watchdog",
2333 "/xyz/openbmc_project/watchdog/host0",
2334 "org.freedesktop.DBus.Properties", "Set",
2335 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002336 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002337 }
2338}
2339
Chris Cain37bbf982021-09-20 10:53:09 -05002340/**
2341 * @brief Parse the Idle Power Saver properties into json
2342 *
2343 * @param[in] aResp Shared pointer for completing asynchronous calls.
2344 * @param[in] properties IPS property data from DBus.
2345 *
2346 * @return true if successful
2347 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002348inline bool
2349 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2350 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002351{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002352 const bool* enabled = nullptr;
2353 const uint8_t* enterUtilizationPercent = nullptr;
2354 const uint64_t* enterDwellTime = nullptr;
2355 const uint8_t* exitUtilizationPercent = nullptr;
2356 const uint64_t* exitDwellTime = nullptr;
2357
2358 const bool success = sdbusplus::unpackPropertiesNoThrow(
2359 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2360 "EnterUtilizationPercent", enterUtilizationPercent,
2361 "ExitUtilizationPercent", exitUtilizationPercent, "ExitDwellTime",
2362 exitDwellTime);
2363
2364 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002365 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002366 return false;
2367 }
2368
2369 if (enabled != nullptr)
2370 {
2371 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2372 }
2373
2374 if (enterUtilizationPercent != nullptr)
2375 {
2376 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2377 *enterUtilizationPercent;
2378 }
2379
2380 if (enterDwellTime != nullptr)
2381 {
2382 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2383 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2384 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2385 .count();
2386 }
2387
2388 if (exitUtilizationPercent != nullptr)
2389 {
2390 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2391 *exitUtilizationPercent;
2392 }
2393
2394 if (exitDwellTime != nullptr)
2395 {
2396 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2397 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2398 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2399 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002400 }
2401
2402 return true;
2403}
2404
2405/**
2406 * @brief Retrieves host watchdog timer properties over DBUS
2407 *
2408 * @param[in] aResp Shared pointer for completing asynchronous calls.
2409 *
2410 * @return None.
2411 */
2412inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2413{
2414 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2415
2416 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002417 constexpr std::array<std::string_view, 1> interfaces = {
2418 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2419 dbus::utility::getSubTree(
2420 "/", 0, interfaces,
2421 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002422 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002423 if (ec)
2424 {
2425 BMCWEB_LOG_DEBUG
2426 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2427 << ec;
2428 messages::internalError(aResp->res);
2429 return;
2430 }
2431 if (subtree.empty())
2432 {
2433 // This is an optional interface so just return
2434 // if there is no instance found
2435 BMCWEB_LOG_DEBUG << "No instances found";
2436 return;
2437 }
2438 if (subtree.size() > 1)
2439 {
2440 // More then one PowerIdlePowerSaver object is not supported and
2441 // is an error
2442 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2443 "Power.IdlePowerSaver objects: "
2444 << subtree.size();
2445 messages::internalError(aResp->res);
2446 return;
2447 }
2448 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2449 {
2450 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2451 messages::internalError(aResp->res);
2452 return;
2453 }
2454 const std::string& path = subtree[0].first;
2455 const std::string& service = subtree[0].second.begin()->first;
2456 if (service.empty())
2457 {
2458 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2459 messages::internalError(aResp->res);
2460 return;
2461 }
2462
2463 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002464 sdbusplus::asio::getAllProperties(
2465 *crow::connections::systemBus, service, path,
2466 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002467 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002468 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002469 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002470 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002471 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002472 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002473 messages::internalError(aResp->res);
2474 return;
2475 }
2476
Ed Tanous002d39b2022-05-31 08:59:27 -07002477 if (!parseIpsProperties(aResp, properties))
2478 {
2479 messages::internalError(aResp->res);
2480 return;
2481 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002482 });
George Liue99073f2022-12-09 11:06:16 +08002483 });
Chris Cain37bbf982021-09-20 10:53:09 -05002484
2485 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2486}
2487
2488/**
2489 * @brief Sets Idle Power Saver properties.
2490 *
2491 * @param[in] aResp Shared pointer for generating response message.
2492 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2493 * RF request.
2494 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2495 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2496 * before entering idle state.
2497 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2498 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2499 * before exiting idle state
2500 *
2501 * @return None.
2502 */
2503inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2504 const std::optional<bool> ipsEnable,
2505 const std::optional<uint8_t> ipsEnterUtil,
2506 const std::optional<uint64_t> ipsEnterTime,
2507 const std::optional<uint8_t> ipsExitUtil,
2508 const std::optional<uint64_t> ipsExitTime)
2509{
2510 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2511
2512 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002513 constexpr std::array<std::string_view, 1> interfaces = {
2514 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2515 dbus::utility::getSubTree(
2516 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002517 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002518 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002519 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002520 if (ec)
2521 {
2522 BMCWEB_LOG_DEBUG
2523 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2524 << ec;
2525 messages::internalError(aResp->res);
2526 return;
2527 }
2528 if (subtree.empty())
2529 {
2530 // This is an optional D-Bus object, but user attempted to patch
2531 messages::resourceNotFound(aResp->res, "ComputerSystem",
2532 "IdlePowerSaver");
2533 return;
2534 }
2535 if (subtree.size() > 1)
2536 {
2537 // More then one PowerIdlePowerSaver object is not supported and
2538 // is an error
2539 BMCWEB_LOG_DEBUG
2540 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2541 << subtree.size();
2542 messages::internalError(aResp->res);
2543 return;
2544 }
2545 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2546 {
2547 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2548 messages::internalError(aResp->res);
2549 return;
2550 }
2551 const std::string& path = subtree[0].first;
2552 const std::string& service = subtree[0].second.begin()->first;
2553 if (service.empty())
2554 {
2555 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2556 messages::internalError(aResp->res);
2557 return;
2558 }
Chris Cain37bbf982021-09-20 10:53:09 -05002559
Ed Tanous002d39b2022-05-31 08:59:27 -07002560 // Valid Power IdlePowerSaver object found, now set any values that
2561 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002562
Ed Tanous002d39b2022-05-31 08:59:27 -07002563 if (ipsEnable)
2564 {
2565 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002566 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002567 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002568 {
Ed Tanous8a592812022-06-04 09:06:59 -07002569 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002570 messages::internalError(aResp->res);
2571 return;
2572 }
2573 },
2574 service, path, "org.freedesktop.DBus.Properties", "Set",
2575 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2576 dbus::utility::DbusVariantType(*ipsEnable));
2577 }
2578 if (ipsEnterUtil)
2579 {
2580 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002581 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002582 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002583 {
Ed Tanous8a592812022-06-04 09:06:59 -07002584 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002585 messages::internalError(aResp->res);
2586 return;
2587 }
2588 },
2589 service, path, "org.freedesktop.DBus.Properties", "Set",
2590 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2591 "EnterUtilizationPercent",
2592 dbus::utility::DbusVariantType(*ipsEnterUtil));
2593 }
2594 if (ipsEnterTime)
2595 {
2596 // Convert from seconds into milliseconds for DBus
2597 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2598 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002599 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002600 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002601 {
Ed Tanous8a592812022-06-04 09:06:59 -07002602 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002603 messages::internalError(aResp->res);
2604 return;
2605 }
2606 },
2607 service, path, "org.freedesktop.DBus.Properties", "Set",
2608 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2609 "EnterDwellTime",
2610 dbus::utility::DbusVariantType(timeMilliseconds));
2611 }
2612 if (ipsExitUtil)
2613 {
2614 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002615 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002616 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002617 {
Ed Tanous8a592812022-06-04 09:06:59 -07002618 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002619 messages::internalError(aResp->res);
2620 return;
2621 }
2622 },
2623 service, path, "org.freedesktop.DBus.Properties", "Set",
2624 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2625 "ExitUtilizationPercent",
2626 dbus::utility::DbusVariantType(*ipsExitUtil));
2627 }
2628 if (ipsExitTime)
2629 {
2630 // Convert from seconds into milliseconds for DBus
2631 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2632 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002633 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002634 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002635 {
Ed Tanous8a592812022-06-04 09:06:59 -07002636 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002637 messages::internalError(aResp->res);
2638 return;
2639 }
2640 },
2641 service, path, "org.freedesktop.DBus.Properties", "Set",
2642 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2643 "ExitDwellTime",
2644 dbus::utility::DbusVariantType(timeMilliseconds));
2645 }
George Liue99073f2022-12-09 11:06:16 +08002646 });
Chris Cain37bbf982021-09-20 10:53:09 -05002647
2648 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2649}
2650
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002651inline void handleComputerSystemHead(
2652 crow::App& app, const crow::Request& req,
2653 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2654{
2655 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2656 {
2657 return;
2658 }
2659 asyncResp->res.addHeader(
2660 boost::beast::http::field::link,
2661 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2662}
2663
Yong Lic45f0082019-10-10 14:19:01 +08002664/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002665 * SystemsCollection derived class for delivering ComputerSystems Collection
2666 * Schema
2667 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002668inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002669{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002670 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002671 .privileges(redfish::privileges::headComputerSystemCollection)
2672 .methods(boost::beast::http::verb::head)(
2673 std::bind_front(handleComputerSystemHead, std::ref(app)));
2674
2675 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002676 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002677 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002678 [&app](const crow::Request& req,
2679 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002680 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002681 {
2682 return;
2683 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002684
2685 asyncResp->res.addHeader(
2686 boost::beast::http::field::link,
2687 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002688 asyncResp->res.jsonValue["@odata.type"] =
2689 "#ComputerSystemCollection.ComputerSystemCollection";
2690 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2691 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002692
Ed Tanous002d39b2022-05-31 08:59:27 -07002693 sdbusplus::asio::getProperty<std::string>(
2694 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2695 "/xyz/openbmc_project/network/hypervisor",
2696 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002697 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002698 const std::string& /*hostName*/) {
2699 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2700 ifaceArray = nlohmann::json::array();
2701 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002702
Ed Tanous002d39b2022-05-31 08:59:27 -07002703 nlohmann::json::object_t system;
2704 system["@odata.id"] = "/redfish/v1/Systems/system";
2705 ifaceArray.push_back(std::move(system));
2706 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002707 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002708 {
2709 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2710 nlohmann::json::object_t hypervisor;
2711 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
2712 ifaceArray.push_back(std::move(hypervisor));
2713 count = ifaceArray.size();
2714 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002715 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002716 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002717}
Sunitha Harish462023a2020-02-19 08:34:59 -06002718
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002719/**
2720 * Function transceives data with dbus directly.
2721 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002722inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002723{
2724 constexpr char const* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2725 constexpr char const* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2726 constexpr char const* interfaceName =
2727 "xyz.openbmc_project.Control.Host.NMI";
2728 constexpr char const* method = "NMI";
2729
2730 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002731 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002732 if (ec)
2733 {
2734 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2735 messages::internalError(asyncResp->res);
2736 return;
2737 }
2738 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002739 },
2740 serviceName, objectPath, interfaceName, method);
2741}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002742
2743/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002744 * SystemActionsReset class supports handle POST method for Reset action.
2745 * The class retrieves and sends data directly to D-Bus.
2746 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002747inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002748{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002749 /**
2750 * Function handles POST method request.
2751 * Analyzes POST body message before sends Reset request data to D-Bus.
2752 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002753 BMCWEB_ROUTE(app,
2754 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002755 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002756 .methods(boost::beast::http::verb::post)(
2757 [&app](const crow::Request& req,
2758 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002759 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002760 {
2761 return;
2762 }
2763 std::string resetType;
2764 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2765 resetType))
2766 {
2767 return;
2768 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002769
Ed Tanous002d39b2022-05-31 08:59:27 -07002770 // Get the command and host vs. chassis
2771 std::string command;
2772 bool hostCommand = true;
2773 if ((resetType == "On") || (resetType == "ForceOn"))
2774 {
2775 command = "xyz.openbmc_project.State.Host.Transition.On";
2776 hostCommand = true;
2777 }
2778 else if (resetType == "ForceOff")
2779 {
2780 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2781 hostCommand = false;
2782 }
2783 else if (resetType == "ForceRestart")
2784 {
2785 command =
2786 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2787 hostCommand = true;
2788 }
2789 else if (resetType == "GracefulShutdown")
2790 {
2791 command = "xyz.openbmc_project.State.Host.Transition.Off";
2792 hostCommand = true;
2793 }
2794 else if (resetType == "GracefulRestart")
2795 {
2796 command =
2797 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2798 hostCommand = true;
2799 }
2800 else if (resetType == "PowerCycle")
2801 {
2802 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2803 hostCommand = true;
2804 }
2805 else if (resetType == "Nmi")
2806 {
2807 doNMI(asyncResp);
2808 return;
2809 }
2810 else
2811 {
2812 messages::actionParameterUnknown(asyncResp->res, "Reset",
2813 resetType);
2814 return;
2815 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002816
Ed Tanous002d39b2022-05-31 08:59:27 -07002817 if (hostCommand)
2818 {
2819 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002820 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002821 if (ec)
2822 {
2823 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2824 if (ec.value() == boost::asio::error::invalid_argument)
2825 {
2826 messages::actionParameterNotSupported(
2827 asyncResp->res, resetType, "Reset");
2828 }
2829 else
2830 {
2831 messages::internalError(asyncResp->res);
2832 }
2833 return;
2834 }
2835 messages::success(asyncResp->res);
2836 },
2837 "xyz.openbmc_project.State.Host",
2838 "/xyz/openbmc_project/state/host0",
2839 "org.freedesktop.DBus.Properties", "Set",
2840 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2841 dbus::utility::DbusVariantType{command});
2842 }
2843 else
2844 {
2845 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002846 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002847 if (ec)
2848 {
2849 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2850 if (ec.value() == boost::asio::error::invalid_argument)
2851 {
2852 messages::actionParameterNotSupported(
2853 asyncResp->res, resetType, "Reset");
2854 }
2855 else
2856 {
2857 messages::internalError(asyncResp->res);
2858 }
2859 return;
2860 }
2861 messages::success(asyncResp->res);
2862 },
2863 "xyz.openbmc_project.State.Chassis",
2864 "/xyz/openbmc_project/state/chassis0",
2865 "org.freedesktop.DBus.Properties", "Set",
2866 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2867 dbus::utility::DbusVariantType{command});
2868 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002869 });
2870}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002871
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002872inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002873 App& app, const crow::Request& req,
2874 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2875{
2876 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2877 {
2878 return;
2879 }
2880
2881 asyncResp->res.addHeader(
2882 boost::beast::http::field::link,
2883 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2884}
2885
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002886inline void afterPortRequest(
2887 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2888 const boost::system::error_code& ec,
2889 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2890{
2891 if (ec)
2892 {
2893 messages::internalError(asyncResp->res);
2894 return;
2895 }
2896 for (const auto& data : socketData)
2897 {
2898 const std::string& socketPath = get<0>(data);
2899 const std::string& protocolName = get<1>(data);
2900 bool isProtocolEnabled = get<2>(data);
2901 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2902 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2903 // need to retrieve port number for
2904 // obmc-console-ssh service
2905 if (protocolName == "SSH")
2906 {
2907 getPortNumber(socketPath, [asyncResp, protocolName](
2908 const boost::system::error_code ec1,
2909 int portNumber) {
2910 if (ec1)
2911 {
2912 messages::internalError(asyncResp->res);
2913 return;
2914 }
2915 nlohmann::json& dataJson1 =
2916 asyncResp->res.jsonValue["SerialConsole"];
2917 dataJson1[protocolName]["Port"] = portNumber;
2918 });
2919 }
2920 }
2921}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002922/**
Ed Tanous66173382018-08-15 18:20:59 -07002923 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002924 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002925inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002926{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002927
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002928 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
2929 .privileges(redfish::privileges::headComputerSystem)
2930 .methods(boost::beast::http::verb::head)(
2931 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07002932 /**
2933 * Functions triggers appropriate requests on DBus
2934 */
Ed Tanous22d268c2022-05-19 09:39:07 -07002935 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07002936 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002937 .methods(boost::beast::http::verb::get)(
2938 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07002939 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2940 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002941 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002942 {
2943 return;
2944 }
Ed Tanous22d268c2022-05-19 09:39:07 -07002945 if (systemName != "system")
2946 {
2947 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2948 systemName);
2949 return;
2950 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002951 asyncResp->res.addHeader(
2952 boost::beast::http::field::link,
2953 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002954 asyncResp->res.jsonValue["@odata.type"] =
2955 "#ComputerSystem.v1_16_0.ComputerSystem";
2956 asyncResp->res.jsonValue["Name"] = "system";
2957 asyncResp->res.jsonValue["Id"] = "system";
2958 asyncResp->res.jsonValue["SystemType"] = "Physical";
2959 asyncResp->res.jsonValue["Description"] = "Computer System";
2960 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
2961 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
2962 "Disabled";
2963 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
2964 uint64_t(0);
2965 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
2966 "Disabled";
2967 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07002968
Ed Tanous002d39b2022-05-31 08:59:27 -07002969 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
2970 "/redfish/v1/Systems/system/Processors";
2971 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
2972 "/redfish/v1/Systems/system/Memory";
2973 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
2974 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06002975 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
2976 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08002977
Ed Tanous002d39b2022-05-31 08:59:27 -07002978 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
2979 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
2980 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
2981 ["@Redfish.ActionInfo"] =
2982 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002983
Ed Tanous002d39b2022-05-31 08:59:27 -07002984 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
2985 "/redfish/v1/Systems/system/LogServices";
2986 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
2987 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08002988
Ed Tanous002d39b2022-05-31 08:59:27 -07002989 nlohmann::json::array_t managedBy;
2990 nlohmann::json& manager = managedBy.emplace_back();
2991 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
2992 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
2993 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
2994 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06002995
Ed Tanous002d39b2022-05-31 08:59:27 -07002996 // Fill in SerialConsole info
2997 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
2998 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
2999 true;
Ed Tanous14766872022-03-15 10:44:42 -07003000
Ed Tanous002d39b2022-05-31 08:59:27 -07003001 // TODO (Gunnar): Should look for obmc-console-ssh@2200.service
3002 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3003 true;
3004 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3005 asyncResp->res
3006 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3007 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003008 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3009 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003010
3011#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003012 // Fill in GraphicalConsole info
3013 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3014 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3015 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003016 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3017 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003018
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003019#endif // BMCWEB_ENABLE_KVM
George Liu7a1dbc42022-12-07 16:03:22 +08003020 constexpr std::array<std::string_view, 4> inventoryForSystems{
Ed Tanous002d39b2022-05-31 08:59:27 -07003021 "xyz.openbmc_project.Inventory.Item.Dimm",
3022 "xyz.openbmc_project.Inventory.Item.Cpu",
3023 "xyz.openbmc_project.Inventory.Item.Drive",
3024 "xyz.openbmc_project.Inventory.Item.StorageController"};
James Feistb49ac872019-05-21 15:12:01 -07003025
Ed Tanous002d39b2022-05-31 08:59:27 -07003026 auto health = std::make_shared<HealthPopulate>(asyncResp);
George Liu7a1dbc42022-12-07 16:03:22 +08003027 dbus::utility::getSubTreePaths(
3028 "/", 0, inventoryForSystems,
3029 [health](const boost::system::error_code& ec,
Ed Tanous002d39b2022-05-31 08:59:27 -07003030 const std::vector<std::string>& resp) {
3031 if (ec)
3032 {
3033 // no inventory
3034 return;
3035 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003036
Ed Tanous002d39b2022-05-31 08:59:27 -07003037 health->inventory = resp;
George Liu7a1dbc42022-12-07 16:03:22 +08003038 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003039
Ed Tanous002d39b2022-05-31 08:59:27 -07003040 health->populate();
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003041
Ed Tanous002d39b2022-05-31 08:59:27 -07003042 getMainChassisId(asyncResp,
3043 [](const std::string& chassisId,
3044 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3045 nlohmann::json::array_t chassisArray;
3046 nlohmann::json& chassis = chassisArray.emplace_back();
Willy Tueddfc432022-09-26 16:46:38 +00003047 chassis["@odata.id"] = crow::utility::urlFromPieces(
3048 "redfish", "v1", "Chassis", chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003049 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3050 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003051
Ed Tanous002d39b2022-05-31 08:59:27 -07003052 getLocationIndicatorActive(asyncResp);
3053 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3054 getIndicatorLedState(asyncResp);
3055 getComputerSystem(asyncResp, health);
3056 getHostState(asyncResp);
3057 getBootProperties(asyncResp);
3058 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003059 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003060 getPCIeDeviceList(asyncResp, "PCIeDevices");
3061 getHostWatchdogTimer(asyncResp);
3062 getPowerRestorePolicy(asyncResp);
3063 getAutomaticRetry(asyncResp);
3064 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003065#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003066 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003067#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003068 getTrustedModuleRequiredToBoot(asyncResp);
3069 getPowerMode(asyncResp);
3070 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003071 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003072
Ed Tanous22d268c2022-05-19 09:39:07 -07003073 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003074 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003075 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003076 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003077 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3078 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003079 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003080 {
3081 return;
3082 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003083 if (systemName != "system")
3084 {
3085 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3086 systemName);
3087 return;
3088 }
3089
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003090 asyncResp->res.addHeader(
3091 boost::beast::http::field::link,
3092 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3093
Ed Tanous002d39b2022-05-31 08:59:27 -07003094 std::optional<bool> locationIndicatorActive;
3095 std::optional<std::string> indicatorLed;
3096 std::optional<std::string> assetTag;
3097 std::optional<std::string> powerRestorePolicy;
3098 std::optional<std::string> powerMode;
3099 std::optional<bool> wdtEnable;
3100 std::optional<std::string> wdtTimeOutAction;
3101 std::optional<std::string> bootSource;
3102 std::optional<std::string> bootType;
3103 std::optional<std::string> bootEnable;
3104 std::optional<std::string> bootAutomaticRetry;
3105 std::optional<bool> bootTrustedModuleRequired;
3106 std::optional<bool> ipsEnable;
3107 std::optional<uint8_t> ipsEnterUtil;
3108 std::optional<uint64_t> ipsEnterTime;
3109 std::optional<uint8_t> ipsExitUtil;
3110 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003111
Ed Tanous002d39b2022-05-31 08:59:27 -07003112 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003113 if (!json_util::readJsonPatch(
3114 req, asyncResp->res,
3115 "IndicatorLED", indicatorLed,
3116 "LocationIndicatorActive", locationIndicatorActive,
3117 "AssetTag", assetTag,
3118 "PowerRestorePolicy", powerRestorePolicy,
3119 "PowerMode", powerMode,
3120 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3121 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3122 "Boot/BootSourceOverrideTarget", bootSource,
3123 "Boot/BootSourceOverrideMode", bootType,
3124 "Boot/BootSourceOverrideEnabled", bootEnable,
3125 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
3126 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3127 "IdlePowerSaver/Enabled", ipsEnable,
3128 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3129 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3130 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3131 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3132 {
3133 return;
3134 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003135 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003136
Ed Tanous002d39b2022-05-31 08:59:27 -07003137 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003138
Ed Tanous002d39b2022-05-31 08:59:27 -07003139 if (assetTag)
3140 {
3141 setAssetTag(asyncResp, *assetTag);
3142 }
James Feistb49ac872019-05-21 15:12:01 -07003143
Ed Tanous002d39b2022-05-31 08:59:27 -07003144 if (wdtEnable || wdtTimeOutAction)
3145 {
3146 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3147 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003148
Ed Tanous002d39b2022-05-31 08:59:27 -07003149 if (bootSource || bootType || bootEnable)
3150 {
3151 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3152 }
3153 if (bootAutomaticRetry)
3154 {
3155 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3156 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003157
Ed Tanous002d39b2022-05-31 08:59:27 -07003158 if (bootTrustedModuleRequired)
3159 {
3160 setTrustedModuleRequiredToBoot(asyncResp,
3161 *bootTrustedModuleRequired);
3162 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003163
Ed Tanous002d39b2022-05-31 08:59:27 -07003164 if (locationIndicatorActive)
3165 {
3166 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3167 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003168
Ed Tanous002d39b2022-05-31 08:59:27 -07003169 // TODO (Gunnar): Remove IndicatorLED after enough time has
3170 // passed
3171 if (indicatorLed)
3172 {
3173 setIndicatorLedState(asyncResp, *indicatorLed);
3174 asyncResp->res.addHeader(boost::beast::http::field::warning,
3175 "299 - \"IndicatorLED is deprecated. Use "
3176 "LocationIndicatorActive instead.\"");
3177 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003178
Ed Tanous002d39b2022-05-31 08:59:27 -07003179 if (powerRestorePolicy)
3180 {
3181 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3182 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003183
Ed Tanous002d39b2022-05-31 08:59:27 -07003184 if (powerMode)
3185 {
3186 setPowerMode(asyncResp, *powerMode);
3187 }
Chris Cain37bbf982021-09-20 10:53:09 -05003188
Ed Tanous002d39b2022-05-31 08:59:27 -07003189 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3190 ipsExitTime)
3191 {
3192 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3193 ipsExitUtil, ipsExitTime);
3194 }
3195 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003196}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303197
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003198inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003199 crow::App& app, const crow::Request& req,
3200 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3201{
3202 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3203 {
3204 return;
3205 }
3206 asyncResp->res.addHeader(
3207 boost::beast::http::field::link,
3208 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3209}
3210
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303211/**
3212 * SystemResetActionInfo derived class for delivering Computer Systems
3213 * ResetType AllowableValues using ResetInfo schema.
3214 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003215inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303216{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003217 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3218 .privileges(redfish::privileges::headActionInfo)
3219 .methods(boost::beast::http::verb::head)(std::bind_front(
3220 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303221 /**
3222 * Functions triggers appropriate requests on DBus
3223 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003224 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003225 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003226 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003227 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003228 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3229 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003230 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003231 {
3232 return;
3233 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003234 if (systemName != "system")
3235 {
3236 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3237 systemName);
3238 return;
3239 }
3240
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003241 asyncResp->res.addHeader(
3242 boost::beast::http::field::link,
3243 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003244
Ed Tanous002d39b2022-05-31 08:59:27 -07003245 asyncResp->res.jsonValue["@odata.id"] =
3246 "/redfish/v1/Systems/system/ResetActionInfo";
3247 asyncResp->res.jsonValue["@odata.type"] =
3248 "#ActionInfo.v1_1_2.ActionInfo";
3249 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3250 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003251
3252 nlohmann::json::array_t parameters;
3253 nlohmann::json::object_t parameter;
3254
3255 parameter["Name"] = "ResetType";
3256 parameter["Required"] = true;
3257 parameter["DataType"] = "String";
3258 nlohmann::json::array_t allowableValues;
3259 allowableValues.emplace_back("On");
3260 allowableValues.emplace_back("ForceOff");
3261 allowableValues.emplace_back("ForceOn");
3262 allowableValues.emplace_back("ForceRestart");
3263 allowableValues.emplace_back("GracefulRestart");
3264 allowableValues.emplace_back("GracefulShutdown");
3265 allowableValues.emplace_back("PowerCycle");
3266 allowableValues.emplace_back("Nmi");
3267 parameter["AllowableValues"] = std::move(allowableValues);
3268 parameters.emplace_back(std::move(parameter));
3269
3270 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003271 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003272}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003273} // namespace redfish