blob: 8d978f1e111adb32a1361217a67b2b1bc7c6cbaf [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
Willy Tu13451e32023-05-24 16:08:18 -070018#include "bmcweb_config.h"
19
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080020#include "app.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070021#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080022#include "dbus_utility.hpp"
James Feistb49ac872019-05-21 15:12:01 -070023#include "health.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060024#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080025#include "led.hpp"
Jason M. Billsf5c9f8b2018-12-18 16:51:18 -080026#include "pcie.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070027#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080028#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080029#include "registries/privilege_registry.hpp"
30#include "utils/dbus_utils.hpp"
31#include "utils/json_utils.hpp"
32#include "utils/sw_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070033#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080034
Ed Tanous9712f8a2018-09-21 13:38:49 -070035#include <boost/container/flat_map.hpp>
George Liue99073f2022-12-09 11:06:16 +080036#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070037#include <boost/url/format.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070038#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020039#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050040
George Liu7a1dbc42022-12-07 16:03:22 +080041#include <array>
42#include <string_view>
Ed Tanousabf2add2019-01-22 16:40:12 -080043#include <variant>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020044
Ed Tanous1abe55e2018-09-05 08:30:59 -070045namespace redfish
46{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020047
Abhishek Patel5c3e9272021-06-24 10:11:33 -050048const static std::array<std::pair<std::string_view, std::string_view>, 2>
49 protocolToDBusForSystems{
50 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
51
Alpana Kumari9d3ae102019-04-12 06:49:32 -050052/**
53 * @brief Updates the Functional State of DIMMs
54 *
55 * @param[in] aResp Shared pointer for completing asynchronous calls
56 * @param[in] dimmState Dimm's Functional state, true/false
57 *
58 * @return None.
59 */
zhanghch058d1b46d2021-04-01 11:18:24 +080060inline void
61 updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Jonathan Doman1e1e5982021-06-11 09:36:17 -070062 bool isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050063{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070064 BMCWEB_LOG_DEBUG << "Dimm Functional: " << isDimmFunctional;
Alpana Kumari9d3ae102019-04-12 06:49:32 -050065
Gunnar Mills4e0453b2020-07-08 14:00:30 -050066 // Set it as Enabled if at least one DIMM is functional
Alpana Kumari9d3ae102019-04-12 06:49:32 -050067 // Update STATE only if previous State was DISABLED and current Dimm is
68 // ENABLED.
Ed Tanous02cad962022-06-30 16:50:15 -070069 const nlohmann::json& prevMemSummary =
Alpana Kumari9d3ae102019-04-12 06:49:32 -050070 aResp->res.jsonValue["MemorySummary"]["Status"]["State"];
71 if (prevMemSummary == "Disabled")
72 {
Ed Tanouse05aec52022-01-25 10:28:56 -080073 if (isDimmFunctional)
Alpana Kumari9d3ae102019-04-12 06:49:32 -050074 {
75 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
76 "Enabled";
77 }
78 }
79}
80
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050081/*
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050082 * @brief Update "ProcessorSummary" "Status" "State" based on
83 * CPU Functional State
84 *
85 * @param[in] aResp Shared pointer for completing asynchronous calls
86 * @param[in] cpuFunctionalState is CPU functional true/false
87 *
88 * @return None.
89 */
Jonathan Doman1e1e5982021-06-11 09:36:17 -070090inline void
91 modifyCpuFunctionalState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
92 bool isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050093{
Jonathan Doman1e1e5982021-06-11 09:36:17 -070094 BMCWEB_LOG_DEBUG << "Cpu Functional: " << isCpuFunctional;
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050095
Ed Tanous02cad962022-06-30 16:50:15 -070096 const nlohmann::json& prevProcState =
Alpana Kumari57e8c9b2019-04-15 01:09:36 -050097 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"];
98
Gunnar Mills4e0453b2020-07-08 14:00:30 -050099 // Set it as Enabled if at least one CPU is functional
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500100 // Update STATE only if previous State was Non_Functional and current CPU is
101 // Functional.
102 if (prevProcState == "Disabled")
103 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800104 if (isCpuFunctional)
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500105 {
106 aResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
107 "Enabled";
108 }
109 }
110}
111
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500112/*
113 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
114 *
115 * @param[in] aResp Shared pointer for completing asynchronous calls
116 * @param[in] cpuPresenceState CPU present or not
117 *
118 * @return None.
119 */
120inline void
121 modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
122 bool isCpuPresent)
123{
124 BMCWEB_LOG_DEBUG << "Cpu Present: " << isCpuPresent;
125
126 if (isCpuPresent)
127 {
128 nlohmann::json& procCount =
129 aResp->res.jsonValue["ProcessorSummary"]["Count"];
130 auto* procCountPtr =
131 procCount.get_ptr<nlohmann::json::number_integer_t*>();
132 if (procCountPtr != nullptr)
133 {
134 // shouldn't be possible to be nullptr
135 *procCountPtr += 1;
136 }
137 }
138}
139
Ali Ahmed382d6472021-09-03 16:53:53 -0500140inline void getProcessorProperties(
141 const std::shared_ptr<bmcweb::AsyncResp>& aResp,
142 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
143 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500144{
Ali Ahmed03fbed92021-09-03 02:33:43 -0500145 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Cpu properties.";
146
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200147 // TODO: Get Model
148
149 const uint16_t* coreCount = nullptr;
150
151 const bool success = sdbusplus::unpackPropertiesNoThrow(
152 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
153
154 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500155 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200156 messages::internalError(aResp->res);
157 return;
158 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500159
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200160 if (coreCount != nullptr)
161 {
162 nlohmann::json& coreCountJson =
163 aResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
164 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500165
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200166 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500167 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200168 coreCountJson = *coreCount;
169 }
170 else
171 {
172 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500173 }
174 }
175}
176
177/*
178 * @brief Get ProcessorSummary fields
179 *
180 * @param[in] aResp Shared pointer for completing asynchronous calls
181 * @param[in] service dbus service for Cpu Information
182 * @param[in] path dbus path for Cpu
183 *
184 * @return None.
185 */
186inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
187 const std::string& service,
188 const std::string& path)
189{
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800190 auto getCpuPresenceState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500191 const bool cpuPresenceCheck) {
192 if (ec3)
193 {
194 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
195 return;
196 }
197 modifyCpuPresenceState(aResp, cpuPresenceCheck);
198 };
199
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500200 // Get the Presence of CPU
201 sdbusplus::asio::getProperty<bool>(
202 *crow::connections::systemBus, service, path,
203 "xyz.openbmc_project.Inventory.Item", "Present",
204 std::move(getCpuPresenceState));
205
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800206 auto getCpuFunctionalState = [aResp](const boost::system::error_code& ec3,
Ali Ahmed382d6472021-09-03 16:53:53 -0500207 const bool cpuFunctionalCheck) {
208 if (ec3)
209 {
210 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
211 return;
212 }
213 modifyCpuFunctionalState(aResp, cpuFunctionalCheck);
214 };
215
Ali Ahmed382d6472021-09-03 16:53:53 -0500216 // Get the Functional State
217 sdbusplus::asio::getProperty<bool>(
218 *crow::connections::systemBus, service, path,
219 "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
220 std::move(getCpuFunctionalState));
221
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200222 sdbusplus::asio::getAllProperties(
223 *crow::connections::systemBus, service, path,
224 "xyz.openbmc_project.Inventory.Item.Cpu",
Ali Ahmed03fbed92021-09-03 02:33:43 -0500225 [aResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800226 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800227 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700228 if (ec2)
229 {
230 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
231 messages::internalError(aResp->res);
232 return;
233 }
Ali Ahmed382d6472021-09-03 16:53:53 -0500234 getProcessorProperties(aResp, properties);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200235 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500236}
237
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500238/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500239 * @brief processMemoryProperties fields
240 *
241 * @param[in] aResp Shared pointer for completing asynchronous calls
242 * @param[in] service dbus service for memory Information
243 * @param[in] path dbus path for Memory
244 * @param[in] DBUS properties for memory
245 *
246 * @return None.
247 */
248inline void
249 processMemoryProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
250 const std::string& service, const std::string& path,
251 const dbus::utility::DBusPropertiesMap& properties)
252{
253 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " Dimm properties.";
254
255 if (properties.empty())
256 {
257 sdbusplus::asio::getProperty<bool>(
258 *crow::connections::systemBus, service, path,
259 "xyz.openbmc_project.State."
260 "Decorator.OperationalStatus",
261 "Functional",
262 [aResp](const boost::system::error_code& ec3, bool dimmState) {
263 if (ec3)
264 {
265 BMCWEB_LOG_ERROR << "DBUS response error " << ec3;
266 return;
267 }
268 updateDimmProperties(aResp, dimmState);
269 });
270 return;
271 }
272
273 const size_t* memorySizeInKB = nullptr;
274
275 const bool success = sdbusplus::unpackPropertiesNoThrow(
276 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
277 memorySizeInKB);
278
279 if (!success)
280 {
281 messages::internalError(aResp->res);
282 return;
283 }
284
285 if (memorySizeInKB != nullptr)
286 {
287 nlohmann::json& totalMemory =
288 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
289 const uint64_t* preValue = totalMemory.get_ptr<const uint64_t*>();
290 if (preValue == nullptr)
291 {
292 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
293 *memorySizeInKB / static_cast<size_t>(1024 * 1024);
294 }
295 else
296 {
297 aResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
298 *memorySizeInKB / static_cast<size_t>(1024 * 1024) + *preValue;
299 }
300 aResp->res.jsonValue["MemorySummary"]["Status"]["State"] = "Enabled";
301 }
302}
303
304/*
305 * @brief Get getMemorySummary fields
306 *
307 * @param[in] aResp Shared pointer for completing asynchronous calls
308 * @param[in] service dbus service for memory Information
309 * @param[in] path dbus path for memory
310 *
311 * @return None.
312 */
313inline void getMemorySummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
314 const std::string& service,
315 const std::string& path)
316{
317 sdbusplus::asio::getAllProperties(
318 *crow::connections::systemBus, service, path,
319 "xyz.openbmc_project.Inventory.Item.Dimm",
320 [aResp, service,
321 path](const boost::system::error_code& ec2,
322 const dbus::utility::DBusPropertiesMap& properties) {
323 if (ec2)
324 {
325 BMCWEB_LOG_ERROR << "DBUS response error " << ec2;
326 messages::internalError(aResp->res);
327 return;
328 }
329 processMemoryProperties(aResp, service, path, properties);
330 });
331}
332
333/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700334 * @brief Retrieves computer system properties over dbus
335 *
336 * @param[in] aResp Shared pointer for completing asynchronous calls
Gunnar Mills8f9ee3c2020-10-30 16:15:13 -0500337 * @param[in] systemHealth Shared HealthPopulate pointer
Ed Tanous6c34de42018-08-29 13:37:36 -0700338 *
339 * @return None.
340 */
Ed Tanousb5a76932020-09-29 16:16:58 -0700341inline void
zhanghch058d1b46d2021-04-01 11:18:24 +0800342 getComputerSystem(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousb5a76932020-09-29 16:16:58 -0700343 const std::shared_ptr<HealthPopulate>& systemHealth)
Ed Tanous6c34de42018-08-29 13:37:36 -0700344{
Ed Tanous6c34de42018-08-29 13:37:36 -0700345 BMCWEB_LOG_DEBUG << "Get available system components.";
George Liue99073f2022-12-09 11:06:16 +0800346 constexpr std::array<std::string_view, 5> interfaces = {
347 "xyz.openbmc_project.Inventory.Decorator.Asset",
348 "xyz.openbmc_project.Inventory.Item.Cpu",
349 "xyz.openbmc_project.Inventory.Item.Dimm",
350 "xyz.openbmc_project.Inventory.Item.System",
351 "xyz.openbmc_project.Common.UUID",
352 };
353 dbus::utility::getSubTree(
354 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800355 [aResp,
George Liue99073f2022-12-09 11:06:16 +0800356 systemHealth](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800357 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700358 if (ec)
359 {
360 BMCWEB_LOG_DEBUG << "DBUS response error";
361 messages::internalError(aResp->res);
362 return;
363 }
364 // Iterate over all retrieved ObjectPaths.
365 for (const std::pair<
366 std::string,
367 std::vector<std::pair<std::string, std::vector<std::string>>>>&
368 object : subtree)
369 {
370 const std::string& path = object.first;
371 BMCWEB_LOG_DEBUG << "Got path: " << path;
372 const std::vector<std::pair<std::string, std::vector<std::string>>>&
373 connectionNames = object.second;
374 if (connectionNames.empty())
Ed Tanous6c34de42018-08-29 13:37:36 -0700375 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700376 continue;
Ed Tanous6c34de42018-08-29 13:37:36 -0700377 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700378
379 auto memoryHealth = std::make_shared<HealthPopulate>(
380 aResp, "/MemorySummary/Status"_json_pointer);
381
382 auto cpuHealth = std::make_shared<HealthPopulate>(
383 aResp, "/ProcessorSummary/Status"_json_pointer);
384
Willy Tu13451e32023-05-24 16:08:18 -0700385 if constexpr (bmcwebEnableHealthPopulate)
386 {
387 systemHealth->children.emplace_back(memoryHealth);
388 systemHealth->children.emplace_back(cpuHealth);
389 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700390
391 // This is not system, so check if it's cpu, dimm, UUID or
392 // BiosVer
393 for (const auto& connection : connectionNames)
Ed Tanous6c34de42018-08-29 13:37:36 -0700394 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700395 for (const auto& interfaceName : connection.second)
Ed Tanous6c34de42018-08-29 13:37:36 -0700396 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700397 if (interfaceName ==
398 "xyz.openbmc_project.Inventory.Item.Dimm")
Ed Tanous6c34de42018-08-29 13:37:36 -0700399 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700400 BMCWEB_LOG_DEBUG
401 << "Found Dimm, now get its properties.";
Alpana Kumari9d3ae102019-04-12 06:49:32 -0500402
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500403 getMemorySummary(aResp, connection.first, path);
Ed Tanous002d39b2022-05-31 08:59:27 -0700404
405 memoryHealth->inventory.emplace_back(path);
406 }
407 else if (interfaceName ==
408 "xyz.openbmc_project.Inventory.Item.Cpu")
409 {
410 BMCWEB_LOG_DEBUG
411 << "Found Cpu, now get its properties.";
412
413 getProcessorSummary(aResp, connection.first, path);
414
415 cpuHealth->inventory.emplace_back(path);
416 }
417 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
418 {
419 BMCWEB_LOG_DEBUG
420 << "Found UUID, now get its properties.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200421
422 sdbusplus::asio::getAllProperties(
423 *crow::connections::systemBus, connection.first,
424 path, "xyz.openbmc_project.Common.UUID",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800425 [aResp](const boost::system::error_code& ec3,
Ed Tanous002d39b2022-05-31 08:59:27 -0700426 const dbus::utility::DBusPropertiesMap&
427 properties) {
428 if (ec3)
429 {
430 BMCWEB_LOG_DEBUG << "DBUS response error "
431 << ec3;
432 messages::internalError(aResp->res);
433 return;
434 }
435 BMCWEB_LOG_DEBUG << "Got " << properties.size()
436 << " UUID properties.";
Ed Tanous002d39b2022-05-31 08:59:27 -0700437
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200438 const std::string* uUID = nullptr;
439
440 const bool success =
441 sdbusplus::unpackPropertiesNoThrow(
442 dbus_utils::UnpackErrorPrinter(),
443 properties, "UUID", uUID);
444
445 if (!success)
446 {
447 messages::internalError(aResp->res);
448 return;
Ed Tanous002d39b2022-05-31 08:59:27 -0700449 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200450
451 if (uUID != nullptr)
452 {
453 std::string valueStr = *uUID;
454 if (valueStr.size() == 32)
455 {
456 valueStr.insert(8, 1, '-');
457 valueStr.insert(13, 1, '-');
458 valueStr.insert(18, 1, '-');
459 valueStr.insert(23, 1, '-');
460 }
461 BMCWEB_LOG_DEBUG << "UUID = " << valueStr;
462 aResp->res.jsonValue["UUID"] = valueStr;
463 }
464 });
Ed Tanous002d39b2022-05-31 08:59:27 -0700465 }
466 else if (interfaceName ==
467 "xyz.openbmc_project.Inventory.Item.System")
468 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200469 sdbusplus::asio::getAllProperties(
470 *crow::connections::systemBus, connection.first,
471 path,
472 "xyz.openbmc_project.Inventory.Decorator.Asset",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800473 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700474 const dbus::utility::DBusPropertiesMap&
475 propertiesList) {
476 if (ec2)
477 {
478 // doesn't have to include this
479 // interface
480 return;
481 }
482 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
483 << " properties for system";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200484
485 const std::string* partNumber = nullptr;
486 const std::string* serialNumber = nullptr;
487 const std::string* manufacturer = nullptr;
488 const std::string* model = nullptr;
489 const std::string* subModel = nullptr;
490
491 const bool success =
492 sdbusplus::unpackPropertiesNoThrow(
493 dbus_utils::UnpackErrorPrinter(),
494 propertiesList, "PartNumber", partNumber,
495 "SerialNumber", serialNumber,
496 "Manufacturer", manufacturer, "Model",
497 model, "SubModel", subModel);
498
499 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -0700500 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200501 messages::internalError(aResp->res);
502 return;
503 }
504
505 if (partNumber != nullptr)
506 {
507 aResp->res.jsonValue["PartNumber"] =
508 *partNumber;
509 }
510
511 if (serialNumber != nullptr)
512 {
513 aResp->res.jsonValue["SerialNumber"] =
514 *serialNumber;
515 }
516
517 if (manufacturer != nullptr)
518 {
519 aResp->res.jsonValue["Manufacturer"] =
520 *manufacturer;
521 }
522
523 if (model != nullptr)
524 {
525 aResp->res.jsonValue["Model"] = *model;
526 }
527
528 if (subModel != nullptr)
529 {
530 aResp->res.jsonValue["SubModel"] = *subModel;
Ed Tanous002d39b2022-05-31 08:59:27 -0700531 }
Gunnar Millsc1e236a2020-04-14 21:36:33 -0500532
Ed Tanous002d39b2022-05-31 08:59:27 -0700533 // Grab the bios version
Willy Tueee00132022-06-14 14:53:17 -0700534 sw_util::populateSoftwareInformation(
535 aResp, sw_util::biosPurpose, "BiosVersion",
Ed Tanous002d39b2022-05-31 08:59:27 -0700536 false);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200537 });
James Feiste4a4b9a2019-06-20 14:08:07 -0700538
Ed Tanous002d39b2022-05-31 08:59:27 -0700539 sdbusplus::asio::getProperty<std::string>(
540 *crow::connections::systemBus, connection.first,
541 path,
542 "xyz.openbmc_project.Inventory.Decorator."
543 "AssetTag",
544 "AssetTag",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800545 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -0700546 const std::string& value) {
547 if (ec2)
548 {
549 // doesn't have to include this
550 // interface
551 return;
552 }
James Feiste4a4b9a2019-06-20 14:08:07 -0700553
Ed Tanous002d39b2022-05-31 08:59:27 -0700554 aResp->res.jsonValue["AssetTag"] = value;
555 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700556 }
557 }
558 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700559 }
Ed Tanous66173382018-08-15 18:20:59 -0700560 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700561}
562
563/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700564 * @brief Retrieves host state properties over dbus
565 *
566 * @param[in] aResp Shared pointer for completing asynchronous calls.
567 *
568 * @return None.
569 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800570inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700571{
572 BMCWEB_LOG_DEBUG << "Get host information.";
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700573 sdbusplus::asio::getProperty<std::string>(
574 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
575 "/xyz/openbmc_project/state/host0", "xyz.openbmc_project.State.Host",
576 "CurrentHostState",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800577 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700578 const std::string& hostState) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700579 if (ec)
580 {
581 if (ec == boost::system::errc::host_unreachable)
Ed Tanous6c34de42018-08-29 13:37:36 -0700582 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700583 // Service not available, no error, just don't return
584 // host state info
585 BMCWEB_LOG_DEBUG << "Service not available " << ec;
Ed Tanous6c34de42018-08-29 13:37:36 -0700586 return;
587 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700588 BMCWEB_LOG_ERROR << "DBUS response error " << ec;
589 messages::internalError(aResp->res);
590 return;
591 }
Ed Tanous66173382018-08-15 18:20:59 -0700592
Ed Tanous002d39b2022-05-31 08:59:27 -0700593 BMCWEB_LOG_DEBUG << "Host state: " << hostState;
594 // Verify Host State
595 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
596 {
597 aResp->res.jsonValue["PowerState"] = "On";
598 aResp->res.jsonValue["Status"]["State"] = "Enabled";
599 }
600 else if (hostState ==
601 "xyz.openbmc_project.State.Host.HostState.Quiesced")
602 {
603 aResp->res.jsonValue["PowerState"] = "On";
604 aResp->res.jsonValue["Status"]["State"] = "Quiesced";
605 }
606 else if (hostState ==
607 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
608 {
609 aResp->res.jsonValue["PowerState"] = "On";
610 aResp->res.jsonValue["Status"]["State"] = "InTest";
611 }
612 else if (
613 hostState ==
614 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
615 {
616 aResp->res.jsonValue["PowerState"] = "PoweringOn";
617 aResp->res.jsonValue["Status"]["State"] = "Starting";
618 }
619 else if (hostState ==
620 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
621 {
622 aResp->res.jsonValue["PowerState"] = "PoweringOff";
623 aResp->res.jsonValue["Status"]["State"] = "Disabled";
624 }
625 else
626 {
627 aResp->res.jsonValue["PowerState"] = "Off";
628 aResp->res.jsonValue["Status"]["State"] = "Disabled";
629 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700630 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700631}
632
633/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500634 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530635 *
636 * @param[in] dbusSource The boot source in DBUS speak.
637 *
638 * @return Returns as a string, the boot source in Redfish terms. If translation
639 * cannot be done, returns an empty string.
640 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000641inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530642{
643 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
644 {
645 return "None";
646 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700647 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530648 {
649 return "Hdd";
650 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700651 if (dbusSource ==
652 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530653 {
654 return "Cd";
655 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700656 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530657 {
658 return "Pxe";
659 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700660 if (dbusSource ==
661 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700662 {
663 return "Usb";
664 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700665 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530666}
667
668/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300669 * @brief Translates boot type DBUS property value to redfish.
670 *
671 * @param[in] dbusType The boot type in DBUS speak.
672 *
673 * @return Returns as a string, the boot type in Redfish terms. If translation
674 * cannot be done, returns an empty string.
675 */
676inline std::string dbusToRfBootType(const std::string& dbusType)
677{
678 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
679 {
680 return "Legacy";
681 }
682 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
683 {
684 return "UEFI";
685 }
686 return "";
687}
688
689/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500690 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530691 *
692 * @param[in] dbusMode The boot mode in DBUS speak.
693 *
694 * @return Returns as a string, the boot mode in Redfish terms. If translation
695 * cannot be done, returns an empty string.
696 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000697inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530698{
699 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
700 {
701 return "None";
702 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700703 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530704 {
705 return "Diags";
706 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700707 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530708 {
709 return "BiosSetup";
710 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700711 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530712}
713
714/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600715 * @brief Translates boot progress DBUS property value to redfish.
716 *
717 * @param[in] dbusBootProgress The boot progress in DBUS speak.
718 *
719 * @return Returns as a string, the boot progress in Redfish terms. If
720 * translation cannot be done, returns "None".
721 */
722inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
723{
724 // Now convert the D-Bus BootProgress to the appropriate Redfish
725 // enum
726 std::string rfBpLastState = "None";
727 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
728 "ProgressStages.Unspecified")
729 {
730 rfBpLastState = "None";
731 }
732 else if (dbusBootProgress ==
733 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
734 "PrimaryProcInit")
735 {
736 rfBpLastState = "PrimaryProcessorInitializationStarted";
737 }
738 else if (dbusBootProgress ==
739 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
740 "BusInit")
741 {
742 rfBpLastState = "BusInitializationStarted";
743 }
744 else if (dbusBootProgress ==
745 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
746 "MemoryInit")
747 {
748 rfBpLastState = "MemoryInitializationStarted";
749 }
750 else if (dbusBootProgress ==
751 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
752 "SecondaryProcInit")
753 {
754 rfBpLastState = "SecondaryProcessorInitializationStarted";
755 }
756 else if (dbusBootProgress ==
757 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
758 "PCIInit")
759 {
760 rfBpLastState = "PCIResourceConfigStarted";
761 }
762 else if (dbusBootProgress ==
763 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
764 "SystemSetup")
765 {
766 rfBpLastState = "SetupEntered";
767 }
768 else if (dbusBootProgress ==
769 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
770 "SystemInitComplete")
771 {
772 rfBpLastState = "SystemHardwareInitializationComplete";
773 }
774 else if (dbusBootProgress ==
775 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
776 "OSStart")
777 {
778 rfBpLastState = "OSBootStarted";
779 }
780 else if (dbusBootProgress ==
781 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
782 "OSRunning")
783 {
784 rfBpLastState = "OSRunning";
785 }
786 else
787 {
788 BMCWEB_LOG_DEBUG << "Unsupported D-Bus BootProgress "
789 << dbusBootProgress;
790 // Just return the default
791 }
792 return rfBpLastState;
793}
794
795/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500796 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530797 *
798 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700799 * @param[out] bootSource The DBus source
800 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530801 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700802 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530803 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800804inline int assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500805 const std::string& rfSource,
806 std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530807{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300808 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
809 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700810
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530811 if (rfSource == "None")
812 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700813 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530814 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700815 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530816 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700817 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
818 }
819 else if (rfSource == "Hdd")
820 {
821 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
822 }
823 else if (rfSource == "Diags")
824 {
825 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
826 }
827 else if (rfSource == "Cd")
828 {
829 bootSource =
830 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
831 }
832 else if (rfSource == "BiosSetup")
833 {
834 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530835 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700836 else if (rfSource == "Usb")
837 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700838 bootSource =
839 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700840 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530841 else
842 {
George Liu0fda0f12021-11-16 10:06:17 +0800843 BMCWEB_LOG_DEBUG
844 << "Invalid property value for BootSourceOverrideTarget: "
845 << bootSource;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700846 messages::propertyValueNotInList(aResp->res, rfSource,
847 "BootSourceTargetOverride");
848 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530849 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700850 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530851}
Ali Ahmed19817712021-06-29 17:01:52 -0500852
Andrew Geissler978b8802020-11-19 13:36:40 -0600853/**
854 * @brief Retrieves boot progress of the system
855 *
856 * @param[in] aResp Shared pointer for generating response message.
857 *
858 * @return None.
859 */
zhanghch058d1b46d2021-04-01 11:18:24 +0800860inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Andrew Geissler978b8802020-11-19 13:36:40 -0600861{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700862 sdbusplus::asio::getProperty<std::string>(
863 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
864 "/xyz/openbmc_project/state/host0",
865 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800866 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700867 const std::string& bootProgressStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700868 if (ec)
869 {
870 // BootProgress is an optional object so just do nothing if
871 // not found
872 return;
873 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600874
Ed Tanous002d39b2022-05-31 08:59:27 -0700875 BMCWEB_LOG_DEBUG << "Boot Progress: " << bootProgressStr;
Andrew Geissler978b8802020-11-19 13:36:40 -0600876
Ed Tanous002d39b2022-05-31 08:59:27 -0700877 aResp->res.jsonValue["BootProgress"]["LastState"] =
878 dbusToRfBootProgress(bootProgressStr);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700879 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600880}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530881
882/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000883 * @brief Retrieves boot progress Last Update of the system
884 *
885 * @param[in] aResp Shared pointer for generating response message.
886 *
887 * @return None.
888 */
889inline void getBootProgressLastStateTime(
890 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
891{
892 sdbusplus::asio::getProperty<uint64_t>(
893 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
894 "/xyz/openbmc_project/state/host0",
895 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800896 [aResp](const boost::system::error_code& ec,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000897 const uint64_t lastStateTime) {
898 if (ec)
899 {
900 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
901 return;
902 }
903
904 // BootProgressLastUpdate is the last time the BootProgress property
905 // was updated. The time is the Epoch time, number of microseconds
906 // since 1 Jan 1970 00::00::00 UTC."
907 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
908 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
909
910 // Convert to ISO 8601 standard
911 aResp->res.jsonValue["BootProgress"]["LastStateTime"] =
912 redfish::time_utils::getDateTimeUintUs(lastStateTime);
913 });
914}
915
916/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300917 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300918 *
919 * @param[in] aResp Shared pointer for generating response message.
920 *
921 * @return None.
922 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300923
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300924inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300925{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700926 sdbusplus::asio::getProperty<std::string>(
927 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
928 "/xyz/openbmc_project/control/host0/boot",
929 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800930 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700931 const std::string& bootType) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700932 if (ec)
933 {
934 // not an error, don't have to have the interface
935 return;
936 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300937
Ed Tanous002d39b2022-05-31 08:59:27 -0700938 BMCWEB_LOG_DEBUG << "Boot type: " << bootType;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300939
Ed Tanous002d39b2022-05-31 08:59:27 -0700940 aResp->res.jsonValue["Boot"]
941 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
Ed Tanous613dabe2022-07-09 11:17:36 -0700942 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300943
Ed Tanous002d39b2022-05-31 08:59:27 -0700944 auto rfType = dbusToRfBootType(bootType);
945 if (rfType.empty())
946 {
947 messages::internalError(aResp->res);
948 return;
949 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300950
Ed Tanous002d39b2022-05-31 08:59:27 -0700951 aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700952 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300953}
954
955/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300956 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530957 *
958 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530959 *
960 * @return None.
961 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300962
963inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530964{
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700965 sdbusplus::asio::getProperty<std::string>(
966 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
967 "/xyz/openbmc_project/control/host0/boot",
968 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800969 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700970 const std::string& bootModeStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700971 if (ec)
972 {
973 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
974 messages::internalError(aResp->res);
975 return;
976 }
977
978 BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr;
979
980 aResp->res
981 .jsonValue["Boot"]
982 ["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
983 "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"};
984
985 if (bootModeStr !=
986 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
987 {
988 auto rfMode = dbusToRfBootMode(bootModeStr);
989 if (!rfMode.empty())
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530990 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700991 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
992 rfMode;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530993 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700994 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700995 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530996}
997
998/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300999 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000 *
1001 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301002 *
1003 * @return None.
1004 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001005
1006inline void
1007 getBootOverrideSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301008{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001009 sdbusplus::asio::getProperty<std::string>(
1010 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1011 "/xyz/openbmc_project/control/host0/boot",
1012 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001013 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001014 const std::string& bootSourceStr) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001015 if (ec)
1016 {
1017 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001018 if (ec.value() == boost::asio::error::host_unreachable)
1019 {
1020 return;
1021 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001022 messages::internalError(aResp->res);
1023 return;
1024 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301025
Ed Tanous002d39b2022-05-31 08:59:27 -07001026 BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr;
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301027
Ed Tanous002d39b2022-05-31 08:59:27 -07001028 auto rfSource = dbusToRfBootSource(bootSourceStr);
1029 if (!rfSource.empty())
1030 {
1031 aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource;
1032 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001033
Ed Tanous002d39b2022-05-31 08:59:27 -07001034 // Get BootMode as BootSourceOverrideTarget is constructed
1035 // from both BootSource and BootMode
1036 getBootOverrideMode(aResp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001037 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301038}
1039
1040/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001041 * @brief This functions abstracts all the logic behind getting a
1042 * "BootSourceOverrideEnabled" property from an overall boot override enable
1043 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301044 *
1045 * @param[in] aResp Shared pointer for generating response message.
1046 *
1047 * @return None.
1048 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301049
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001050inline void
1051 processBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1052 const bool bootOverrideEnableSetting)
1053{
1054 if (!bootOverrideEnableSetting)
1055 {
1056 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Disabled";
1057 return;
1058 }
1059
1060 // If boot source override is enabled, we need to check 'one_time'
1061 // property to set a correct value for the "BootSourceOverrideEnabled"
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001062 sdbusplus::asio::getProperty<bool>(
1063 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1064 "/xyz/openbmc_project/control/host0/boot/one_time",
1065 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001066 [aResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001067 if (ec)
1068 {
1069 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1070 messages::internalError(aResp->res);
1071 return;
1072 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301073
Ed Tanous002d39b2022-05-31 08:59:27 -07001074 if (oneTimeSetting)
1075 {
1076 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once";
1077 }
1078 else
1079 {
1080 aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1081 "Continuous";
1082 }
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001083 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301084}
1085
1086/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001087 * @brief Retrieves boot override enable over DBUS
1088 *
1089 * @param[in] aResp Shared pointer for generating response message.
1090 *
1091 * @return None.
1092 */
1093
1094inline void
1095 getBootOverrideEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1096{
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001097 sdbusplus::asio::getProperty<bool>(
1098 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1099 "/xyz/openbmc_project/control/host0/boot",
1100 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001101 [aResp](const boost::system::error_code& ec,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001102 const bool bootOverrideEnable) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001103 if (ec)
1104 {
1105 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
Nan Zhou5ef735c2022-06-22 05:24:21 +00001106 if (ec.value() == boost::asio::error::host_unreachable)
1107 {
1108 return;
1109 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001110 messages::internalError(aResp->res);
1111 return;
1112 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001113
Ed Tanous002d39b2022-05-31 08:59:27 -07001114 processBootOverrideEnable(aResp, bootOverrideEnable);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001115 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001116}
1117
1118/**
1119 * @brief Retrieves boot source override properties
1120 *
1121 * @param[in] aResp Shared pointer for generating response message.
1122 *
1123 * @return None.
1124 */
1125inline void getBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1126{
1127 BMCWEB_LOG_DEBUG << "Get boot information.";
1128
1129 getBootOverrideSource(aResp);
1130 getBootOverrideType(aResp);
1131 getBootOverrideEnable(aResp);
1132}
1133
1134/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001135 * @brief Retrieves the Last Reset Time
1136 *
1137 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1138 * and power off. Even though this is the "system" Redfish object look at the
1139 * chassis D-Bus interface for the LastStateChangeTime since this has the
1140 * last power operation time.
1141 *
1142 * @param[in] aResp Shared pointer for generating response message.
1143 *
1144 * @return None.
1145 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001146inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001147{
1148 BMCWEB_LOG_DEBUG << "Getting System Last Reset Time";
1149
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001150 sdbusplus::asio::getProperty<uint64_t>(
1151 *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis",
1152 "/xyz/openbmc_project/state/chassis0",
1153 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001154 [aResp](const boost::system::error_code& ec, uint64_t lastResetTime) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001155 if (ec)
1156 {
1157 BMCWEB_LOG_DEBUG << "D-BUS response error " << ec;
1158 return;
1159 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001160
Ed Tanous002d39b2022-05-31 08:59:27 -07001161 // LastStateChangeTime is epoch time, in milliseconds
1162 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1163 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001164
Ed Tanous002d39b2022-05-31 08:59:27 -07001165 // Convert to ISO 8601 standard
1166 aResp->res.jsonValue["LastResetTime"] =
Ed Tanous2b829372022-08-03 14:22:34 -07001167 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001168 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001169}
1170
1171/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001172 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1173 *
1174 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1175 * corresponding property "AttemptsLeft" that keeps track of the amount of
1176 * automatic retry attempts left are hosted in phosphor-state-manager through
1177 * dbus.
1178 *
1179 * @param[in] aResp Shared pointer for generating response message.
1180 *
1181 * @return None.
1182 */
1183inline void
1184 getAutomaticRebootAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1185{
1186 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1187
1188 sdbusplus::asio::getAllProperties(
1189 *crow::connections::systemBus, "xyz.openbmc_project.State.Host",
1190 "/xyz/openbmc_project/state/host0",
1191 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1192 [aResp{aResp}](const boost::system::error_code& ec,
1193 const dbus::utility::DBusPropertiesMap& propertiesList) {
1194 if (ec)
1195 {
1196 if (ec.value() != EBADR)
1197 {
1198 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1199 messages::internalError(aResp->res);
1200 }
1201 return;
1202 }
1203
1204 const uint32_t* attemptsLeft = nullptr;
1205 const uint32_t* retryAttempts = nullptr;
1206
1207 const bool success = sdbusplus::unpackPropertiesNoThrow(
1208 dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
1209 attemptsLeft, "RetryAttempts", retryAttempts);
1210
1211 if (!success)
1212 {
1213 messages::internalError(aResp->res);
1214 return;
1215 }
1216
1217 if (attemptsLeft != nullptr)
1218 {
1219 aResp->res.jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1220 *attemptsLeft;
1221 }
1222
1223 if (retryAttempts != nullptr)
1224 {
1225 aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1226 *retryAttempts;
1227 }
1228 });
1229}
1230
1231/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001232 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1233 *
1234 * @param[in] aResp Shared pointer for generating response message.
1235 *
1236 * @return None.
1237 */
Corey Hardesty797d5da2022-04-26 17:54:52 +08001238inline void
1239 getAutomaticRetryPolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001240{
1241 BMCWEB_LOG_DEBUG << "Get Automatic Retry policy";
1242
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001243 sdbusplus::asio::getProperty<bool>(
1244 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1245 "/xyz/openbmc_project/control/host0/auto_reboot",
1246 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001247 [aResp](const boost::system::error_code& ec, bool autoRebootEnabled) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001248 if (ec)
1249 {
Corey Hardesty797d5da2022-04-26 17:54:52 +08001250 if (ec.value() != EBADR)
1251 {
1252 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1253 messages::internalError(aResp->res);
1254 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001255 return;
1256 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001257
Ed Tanous002d39b2022-05-31 08:59:27 -07001258 BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled;
1259 if (autoRebootEnabled)
1260 {
1261 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1262 "RetryAttempts";
Ed Tanous002d39b2022-05-31 08:59:27 -07001263 }
1264 else
1265 {
1266 aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled";
1267 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001268 getAutomaticRebootAttempts(aResp);
Gunnar Mills69f35302020-05-17 16:06:31 -05001269
Ed Tanous002d39b2022-05-31 08:59:27 -07001270 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1271 // and RetryAttempts. OpenBMC only supports Disabled and
1272 // RetryAttempts.
1273 aResp->res.jsonValue["Boot"]
1274 ["AutomaticRetryConfig@Redfish.AllowableValues"] = {
1275 "Disabled", "RetryAttempts"};
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001276 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001277}
1278
1279/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001280 * @brief Sets RetryAttempts
1281 *
1282 * @param[in] aResp Shared pointer for generating response message.
1283 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1284 *
1285 *@return None.
1286 */
1287
1288inline void
1289 setAutomaticRetryAttempts(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1290 const uint32_t retryAttempts)
1291{
1292 BMCWEB_LOG_DEBUG << "Set Automatic Retry Attempts.";
1293 crow::connections::systemBus->async_method_call(
1294 [aResp](const boost::system::error_code& ec) {
1295 if (ec)
1296 {
1297 BMCWEB_LOG_ERROR
1298 << "DBUS response error: Set setAutomaticRetryAttempts" << ec;
1299 messages::internalError(aResp->res);
1300 return;
1301 }
1302 },
1303 "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
1304 "org.freedesktop.DBus.Properties", "Set",
1305 "xyz.openbmc_project.Control.Boot.RebootAttempts", "RetryAttempts",
1306 std::variant<uint32_t>(retryAttempts));
1307}
1308
1309/**
George Liuc6a620f2020-04-10 17:18:11 +08001310 * @brief Retrieves power restore policy over DBUS.
1311 *
1312 * @param[in] aResp Shared pointer for generating response message.
1313 *
1314 * @return None.
1315 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001316inline void
1317 getPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
George Liuc6a620f2020-04-10 17:18:11 +08001318{
1319 BMCWEB_LOG_DEBUG << "Get power restore policy";
1320
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001321 sdbusplus::asio::getProperty<std::string>(
1322 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
1323 "/xyz/openbmc_project/control/host0/power_restore_policy",
1324 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001325 [aResp](const boost::system::error_code& ec,
1326 const std::string& policy) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001327 if (ec)
1328 {
1329 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1330 return;
1331 }
George Liuc6a620f2020-04-10 17:18:11 +08001332
Ed Tanous002d39b2022-05-31 08:59:27 -07001333 const boost::container::flat_map<std::string, std::string> policyMaps = {
1334 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn",
1335 "AlwaysOn"},
1336 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff",
1337 "AlwaysOff"},
1338 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore",
1339 "LastState"},
1340 // Return `AlwaysOff` when power restore policy set to "None"
1341 {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None",
1342 "AlwaysOff"}};
George Liuc6a620f2020-04-10 17:18:11 +08001343
Ed Tanous002d39b2022-05-31 08:59:27 -07001344 auto policyMapsIt = policyMaps.find(policy);
1345 if (policyMapsIt == policyMaps.end())
1346 {
1347 messages::internalError(aResp->res);
1348 return;
1349 }
George Liuc6a620f2020-04-10 17:18:11 +08001350
Ed Tanous002d39b2022-05-31 08:59:27 -07001351 aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second;
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001352 });
George Liuc6a620f2020-04-10 17:18:11 +08001353}
1354
1355/**
Ali Ahmed19817712021-06-29 17:01:52 -05001356 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1357 * TPM is required for booting the host.
1358 *
1359 * @param[in] aResp Shared pointer for generating response message.
1360 *
1361 * @return None.
1362 */
1363inline void getTrustedModuleRequiredToBoot(
1364 const std::shared_ptr<bmcweb::AsyncResp>& aResp)
1365{
1366 BMCWEB_LOG_DEBUG << "Get TPM required to boot.";
George Liue99073f2022-12-09 11:06:16 +08001367 constexpr std::array<std::string_view, 1> interfaces = {
1368 "xyz.openbmc_project.Control.TPM.Policy"};
1369 dbus::utility::getSubTree(
1370 "/", 0, interfaces,
1371 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001372 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001373 if (ec)
1374 {
1375 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1376 << ec;
1377 // This is an optional D-Bus object so just return if
1378 // error occurs
1379 return;
1380 }
1381 if (subtree.empty())
1382 {
1383 // As noted above, this is an optional interface so just return
1384 // if there is no instance found
1385 return;
1386 }
1387
1388 /* When there is more than one TPMEnable object... */
1389 if (subtree.size() > 1)
1390 {
1391 BMCWEB_LOG_DEBUG
1392 << "DBUS response has more than 1 TPM Enable object:"
1393 << subtree.size();
1394 // Throw an internal Error and return
1395 messages::internalError(aResp->res);
1396 return;
1397 }
1398
1399 // Make sure the Dbus response map has a service and objectPath
1400 // field
1401 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1402 {
1403 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1404 messages::internalError(aResp->res);
1405 return;
1406 }
1407
1408 const std::string& path = subtree[0].first;
1409 const std::string& serv = subtree[0].second.begin()->first;
1410
1411 // Valid TPM Enable object found, now reading the current value
1412 sdbusplus::asio::getProperty<bool>(
1413 *crow::connections::systemBus, serv, path,
1414 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001415 [aResp](const boost::system::error_code& ec2, bool tpmRequired) {
Ed Tanous8a592812022-06-04 09:06:59 -07001416 if (ec2)
Ali Ahmed19817712021-06-29 17:01:52 -05001417 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001418 BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get"
Ed Tanous8a592812022-06-04 09:06:59 -07001419 << ec2;
Ali Ahmed19817712021-06-29 17:01:52 -05001420 messages::internalError(aResp->res);
1421 return;
1422 }
1423
Ed Tanous002d39b2022-05-31 08:59:27 -07001424 if (tpmRequired)
Ali Ahmed19817712021-06-29 17:01:52 -05001425 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001426 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1427 "Required";
Ali Ahmed19817712021-06-29 17:01:52 -05001428 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001429 else
1430 {
1431 aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1432 "Disabled";
1433 }
1434 });
George Liue99073f2022-12-09 11:06:16 +08001435 });
Ali Ahmed19817712021-06-29 17:01:52 -05001436}
1437
1438/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001439 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1440 * TPM is required for booting the host.
1441 *
1442 * @param[in] aResp Shared pointer for generating response message.
1443 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1444 *
1445 * @return None.
1446 */
1447inline void setTrustedModuleRequiredToBoot(
1448 const std::shared_ptr<bmcweb::AsyncResp>& aResp, const bool tpmRequired)
1449{
1450 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot.";
George Liue99073f2022-12-09 11:06:16 +08001451 constexpr std::array<std::string_view, 1> interfaces = {
1452 "xyz.openbmc_project.Control.TPM.Policy"};
1453 dbus::utility::getSubTree(
1454 "/", 0, interfaces,
1455 [aResp,
1456 tpmRequired](const boost::system::error_code& ec,
1457 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001458 if (ec)
1459 {
1460 BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree"
1461 << ec;
1462 messages::internalError(aResp->res);
1463 return;
1464 }
1465 if (subtree.empty())
1466 {
1467 messages::propertyValueNotInList(aResp->res, "ComputerSystem",
1468 "TrustedModuleRequiredToBoot");
1469 return;
1470 }
1471
1472 /* When there is more than one TPMEnable object... */
1473 if (subtree.size() > 1)
1474 {
1475 BMCWEB_LOG_DEBUG
1476 << "DBUS response has more than 1 TPM Enable object:"
1477 << subtree.size();
1478 // Throw an internal Error and return
1479 messages::internalError(aResp->res);
1480 return;
1481 }
1482
1483 // Make sure the Dbus response map has a service and objectPath
1484 // field
1485 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1486 {
1487 BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!";
1488 messages::internalError(aResp->res);
1489 return;
1490 }
1491
1492 const std::string& path = subtree[0].first;
1493 const std::string& serv = subtree[0].second.begin()->first;
1494
1495 if (serv.empty())
1496 {
1497 BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!";
1498 messages::internalError(aResp->res);
1499 return;
1500 }
1501
1502 // Valid TPM Enable object found, now setting the value
1503 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001504 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001505 if (ec2)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001506 {
1507 BMCWEB_LOG_DEBUG
Ed Tanous002d39b2022-05-31 08:59:27 -07001508 << "DBUS response error: Set TrustedModuleRequiredToBoot"
Ed Tanous8a592812022-06-04 09:06:59 -07001509 << ec2;
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001510 messages::internalError(aResp->res);
1511 return;
1512 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001513 BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done.";
1514 },
1515 serv, path, "org.freedesktop.DBus.Properties", "Set",
1516 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1517 dbus::utility::DbusVariantType(tpmRequired));
George Liue99073f2022-12-09 11:06:16 +08001518 });
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001519}
1520
1521/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301522 * @brief Sets boot properties into DBUS object(s).
1523 *
1524 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001525 * @param[in] bootType The boot type to set.
1526 * @return Integer error code.
1527 */
1528inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001529 const std::optional<std::string>& bootType)
1530{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001531 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001532
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001533 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001534 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001535 return;
1536 }
1537
1538 // Source target specified
1539 BMCWEB_LOG_DEBUG << "Boot type: " << *bootType;
1540 // Figure out which DBUS interface and property to use
1541 if (*bootType == "Legacy")
1542 {
1543 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1544 }
1545 else if (*bootType == "UEFI")
1546 {
1547 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1548 }
1549 else
1550 {
1551 BMCWEB_LOG_DEBUG << "Invalid property value for "
1552 "BootSourceOverrideMode: "
1553 << *bootType;
1554 messages::propertyValueNotInList(aResp->res, *bootType,
1555 "BootSourceOverrideMode");
1556 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001557 }
1558
1559 // Act on validated parameters
1560 BMCWEB_LOG_DEBUG << "DBUS boot type: " << bootTypeStr;
1561
1562 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001563 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001564 if (ec)
1565 {
1566 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1567 if (ec.value() == boost::asio::error::host_unreachable)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001568 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001569 messages::resourceNotFound(aResp->res, "Set", "BootType");
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001570 return;
1571 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001572 messages::internalError(aResp->res);
1573 return;
1574 }
1575 BMCWEB_LOG_DEBUG << "Boot type update done.";
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001576 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001577 "xyz.openbmc_project.Settings",
1578 "/xyz/openbmc_project/control/host0/boot",
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001579 "org.freedesktop.DBus.Properties", "Set",
1580 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanous168e20c2021-12-13 14:39:53 -08001581 dbus::utility::DbusVariantType(bootTypeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001582}
1583
1584/**
1585 * @brief Sets boot properties into DBUS object(s).
1586 *
1587 * @param[in] aResp Shared pointer for generating response message.
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001588 * @param[in] bootType The boot type to set.
1589 * @return Integer error code.
1590 */
1591inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1592 const std::optional<std::string>& bootEnable)
1593{
1594 if (!bootEnable)
1595 {
1596 return;
1597 }
1598 // Source target specified
1599 BMCWEB_LOG_DEBUG << "Boot enable: " << *bootEnable;
1600
1601 bool bootOverrideEnable = false;
1602 bool bootOverridePersistent = false;
1603 // Figure out which DBUS interface and property to use
1604 if (*bootEnable == "Disabled")
1605 {
1606 bootOverrideEnable = false;
1607 }
1608 else if (*bootEnable == "Once")
1609 {
1610 bootOverrideEnable = true;
1611 bootOverridePersistent = false;
1612 }
1613 else if (*bootEnable == "Continuous")
1614 {
1615 bootOverrideEnable = true;
1616 bootOverridePersistent = true;
1617 }
1618 else
1619 {
George Liu0fda0f12021-11-16 10:06:17 +08001620 BMCWEB_LOG_DEBUG
1621 << "Invalid property value for BootSourceOverrideEnabled: "
1622 << *bootEnable;
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001623 messages::propertyValueNotInList(aResp->res, *bootEnable,
1624 "BootSourceOverrideEnabled");
1625 return;
1626 }
1627
1628 // Act on validated parameters
1629 BMCWEB_LOG_DEBUG << "DBUS boot override enable: " << bootOverrideEnable;
1630
1631 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001632 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07001633 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07001634 {
Ed Tanous8a592812022-06-04 09:06:59 -07001635 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07001636 messages::internalError(aResp->res);
1637 return;
1638 }
1639 BMCWEB_LOG_DEBUG << "Boot override enable update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001640 },
1641 "xyz.openbmc_project.Settings",
1642 "/xyz/openbmc_project/control/host0/boot",
1643 "org.freedesktop.DBus.Properties", "Set",
1644 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001645 dbus::utility::DbusVariantType(bootOverrideEnable));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001646
1647 if (!bootOverrideEnable)
1648 {
1649 return;
1650 }
1651
1652 // In case boot override is enabled we need to set correct value for the
1653 // 'one_time' enable DBus interface
1654 BMCWEB_LOG_DEBUG << "DBUS boot override persistent: "
1655 << bootOverridePersistent;
1656
1657 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001658 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001659 if (ec)
1660 {
1661 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1662 messages::internalError(aResp->res);
1663 return;
1664 }
1665 BMCWEB_LOG_DEBUG << "Boot one_time update done.";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001666 },
1667 "xyz.openbmc_project.Settings",
1668 "/xyz/openbmc_project/control/host0/boot/one_time",
1669 "org.freedesktop.DBus.Properties", "Set",
1670 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08001671 dbus::utility::DbusVariantType(!bootOverridePersistent));
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001672}
1673
1674/**
1675 * @brief Sets boot properties into DBUS object(s).
1676 *
1677 * @param[in] aResp Shared pointer for generating response message.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301678 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301679 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001680 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301681 */
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001682inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001683 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301684{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001685 std::string bootSourceStr;
1686 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001687
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001688 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301689 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001690 return;
1691 }
1692
1693 // Source target specified
1694 BMCWEB_LOG_DEBUG << "Boot source: " << *bootSource;
1695 // Figure out which DBUS interface and property to use
Ed Tanouse662eae2022-01-25 10:39:19 -08001696 if (assignBootParameters(aResp, *bootSource, bootSourceStr, bootModeStr) !=
1697 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001698 {
1699 BMCWEB_LOG_DEBUG
1700 << "Invalid property value for BootSourceOverrideTarget: "
1701 << *bootSource;
1702 messages::propertyValueNotInList(aResp->res, *bootSource,
1703 "BootSourceTargetOverride");
1704 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001705 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301706
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001707 // Act on validated parameters
1708 BMCWEB_LOG_DEBUG << "DBUS boot source: " << bootSourceStr;
1709 BMCWEB_LOG_DEBUG << "DBUS boot mode: " << bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001710
1711 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001712 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001713 if (ec)
1714 {
1715 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1716 messages::internalError(aResp->res);
1717 return;
1718 }
1719 BMCWEB_LOG_DEBUG << "Boot source update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001720 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001721 "xyz.openbmc_project.Settings",
1722 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001723 "org.freedesktop.DBus.Properties", "Set",
1724 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ed Tanous168e20c2021-12-13 14:39:53 -08001725 dbus::utility::DbusVariantType(bootSourceStr));
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001726
1727 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001728 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001729 if (ec)
1730 {
1731 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1732 messages::internalError(aResp->res);
1733 return;
1734 }
1735 BMCWEB_LOG_DEBUG << "Boot mode update done.";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001736 },
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001737 "xyz.openbmc_project.Settings",
1738 "/xyz/openbmc_project/control/host0/boot",
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001739 "org.freedesktop.DBus.Properties", "Set",
1740 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanous168e20c2021-12-13 14:39:53 -08001741 dbus::utility::DbusVariantType(bootModeStr));
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001742}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001743
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001744/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001745 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301746 *
1747 * @param[in] aResp Shared pointer for generating response message.
1748 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001749 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301750 * @param[in] bootEnable The boot override enable from incoming RF request.
1751 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001752 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301753 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001754
1755inline void setBootProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1756 const std::optional<std::string>& bootSource,
1757 const std::optional<std::string>& bootType,
1758 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301759{
1760 BMCWEB_LOG_DEBUG << "Set boot information.";
1761
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001762 setBootModeOrSource(aResp, bootSource);
1763 setBootType(aResp, bootType);
1764 setBootEnable(aResp, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301765}
1766
George Liuc6a620f2020-04-10 17:18:11 +08001767/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001768 * @brief Sets AssetTag
1769 *
1770 * @param[in] aResp Shared pointer for generating response message.
1771 * @param[in] assetTag "AssetTag" from request.
1772 *
1773 * @return None.
1774 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001775inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001776 const std::string& assetTag)
1777{
George Liue99073f2022-12-09 11:06:16 +08001778 constexpr std::array<std::string_view, 1> interfaces = {
1779 "xyz.openbmc_project.Inventory.Item.System"};
1780 dbus::utility::getSubTree(
1781 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001782 [aResp,
George Liue99073f2022-12-09 11:06:16 +08001783 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001784 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001785 if (ec)
1786 {
1787 BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
1788 messages::internalError(aResp->res);
1789 return;
1790 }
1791 if (subtree.empty())
1792 {
1793 BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!";
1794 messages::internalError(aResp->res);
1795 return;
1796 }
1797 // Assume only 1 system D-Bus object
1798 // Throw an error if there is more than 1
1799 if (subtree.size() > 1)
1800 {
1801 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus object!";
1802 messages::internalError(aResp->res);
1803 return;
1804 }
1805 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1806 {
1807 BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!";
1808 messages::internalError(aResp->res);
1809 return;
1810 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001811
Ed Tanous002d39b2022-05-31 08:59:27 -07001812 const std::string& path = subtree[0].first;
1813 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001814
Ed Tanous002d39b2022-05-31 08:59:27 -07001815 if (service.empty())
1816 {
1817 BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!";
1818 messages::internalError(aResp->res);
1819 return;
1820 }
1821
1822 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001823 [aResp](const boost::system::error_code& ec2) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001824 if (ec2)
Gunnar Mills98e386e2020-10-30 14:58:09 -05001825 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001826 BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set "
1827 << ec2;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001828 messages::internalError(aResp->res);
1829 return;
1830 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001831 },
1832 service, path, "org.freedesktop.DBus.Properties", "Set",
1833 "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
1834 dbus::utility::DbusVariantType(assetTag));
George Liue99073f2022-12-09 11:06:16 +08001835 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001836}
1837
1838/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001839 * @brief Sets automaticRetry (Auto Reboot)
1840 *
1841 * @param[in] aResp Shared pointer for generating response message.
1842 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1843 *
1844 * @return None.
1845 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001846inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Ed Tanousf23b7292020-10-15 09:41:17 -07001847 const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001848{
1849 BMCWEB_LOG_DEBUG << "Set Automatic Retry.";
1850
1851 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001852 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001853
1854 if (automaticRetryConfig == "Disabled")
1855 {
1856 autoRebootEnabled = false;
1857 }
1858 else if (automaticRetryConfig == "RetryAttempts")
1859 {
1860 autoRebootEnabled = true;
1861 }
1862 else
1863 {
George Liu0fda0f12021-11-16 10:06:17 +08001864 BMCWEB_LOG_DEBUG << "Invalid property value for AutomaticRetryConfig: "
Gunnar Mills69f35302020-05-17 16:06:31 -05001865 << automaticRetryConfig;
1866 messages::propertyValueNotInList(aResp->res, automaticRetryConfig,
1867 "AutomaticRetryConfig");
1868 return;
1869 }
1870
1871 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001872 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001873 if (ec)
1874 {
1875 messages::internalError(aResp->res);
1876 return;
1877 }
Gunnar Mills69f35302020-05-17 16:06:31 -05001878 },
1879 "xyz.openbmc_project.Settings",
1880 "/xyz/openbmc_project/control/host0/auto_reboot",
1881 "org.freedesktop.DBus.Properties", "Set",
1882 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Ed Tanous168e20c2021-12-13 14:39:53 -08001883 dbus::utility::DbusVariantType(autoRebootEnabled));
Gunnar Mills69f35302020-05-17 16:06:31 -05001884}
1885
1886/**
George Liuc6a620f2020-04-10 17:18:11 +08001887 * @brief Sets power restore policy properties.
1888 *
1889 * @param[in] aResp Shared pointer for generating response message.
1890 * @param[in] policy power restore policy properties from request.
1891 *
1892 * @return None.
1893 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001894inline void
1895 setPowerRestorePolicy(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
1896 const std::string& policy)
George Liuc6a620f2020-04-10 17:18:11 +08001897{
1898 BMCWEB_LOG_DEBUG << "Set power restore policy.";
1899
1900 const boost::container::flat_map<std::string, std::string> policyMaps = {
George Liu0fda0f12021-11-16 10:06:17 +08001901 {"AlwaysOn",
1902 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn"},
1903 {"AlwaysOff",
1904 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff"},
1905 {"LastState",
1906 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore"}};
George Liuc6a620f2020-04-10 17:18:11 +08001907
1908 std::string powerRestorPolicy;
1909
Gunnar Mills4e69c902021-01-05 19:50:11 -06001910 auto policyMapsIt = policyMaps.find(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001911 if (policyMapsIt == policyMaps.end())
1912 {
Gunnar Mills4e69c902021-01-05 19:50:11 -06001913 messages::propertyValueNotInList(aResp->res, policy,
1914 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001915 return;
1916 }
1917
1918 powerRestorPolicy = policyMapsIt->second;
1919
1920 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001921 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001922 if (ec)
1923 {
1924 messages::internalError(aResp->res);
1925 return;
1926 }
George Liuc6a620f2020-04-10 17:18:11 +08001927 },
1928 "xyz.openbmc_project.Settings",
1929 "/xyz/openbmc_project/control/host0/power_restore_policy",
1930 "org.freedesktop.DBus.Properties", "Set",
1931 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanous168e20c2021-12-13 14:39:53 -08001932 dbus::utility::DbusVariantType(powerRestorPolicy));
George Liuc6a620f2020-04-10 17:18:11 +08001933}
1934
AppaRao Pulia6349912019-10-18 17:16:08 +05301935#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
1936/**
1937 * @brief Retrieves provisioning status
1938 *
1939 * @param[in] aResp Shared pointer for completing asynchronous calls.
1940 *
1941 * @return None.
1942 */
zhanghch058d1b46d2021-04-01 11:18:24 +08001943inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301944{
1945 BMCWEB_LOG_DEBUG << "Get OEM information.";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001946 sdbusplus::asio::getAllProperties(
1947 *crow::connections::systemBus, "xyz.openbmc_project.PFR.Manager",
1948 "/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08001949 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001950 const dbus::utility::DBusPropertiesMap& propertiesList) {
Ed Tanous002d39b2022-05-31 08:59:27 -07001951 nlohmann::json& oemPFR =
1952 aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1953 aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1954 "#OemComputerSystem.OpenBmc";
1955 oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001956
Ed Tanous002d39b2022-05-31 08:59:27 -07001957 if (ec)
1958 {
1959 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
1960 // not an error, don't have to have the interface
1961 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1962 return;
1963 }
1964
1965 const bool* provState = nullptr;
1966 const bool* lockState = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001967
1968 const bool success = sdbusplus::unpackPropertiesNoThrow(
Jiaqing Zhao0d4befa2022-08-19 15:14:32 +08001969 dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
1970 provState, "UfmLocked", lockState);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001971
1972 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07001973 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02001974 messages::internalError(aResp->res);
1975 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07001976 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301977
Ed Tanous002d39b2022-05-31 08:59:27 -07001978 if ((provState == nullptr) || (lockState == nullptr))
1979 {
1980 BMCWEB_LOG_DEBUG << "Unable to get PFR attributes.";
1981 messages::internalError(aResp->res);
1982 return;
1983 }
AppaRao Pulia6349912019-10-18 17:16:08 +05301984
Ed Tanous002d39b2022-05-31 08:59:27 -07001985 if (*provState == true)
1986 {
1987 if (*lockState == true)
AppaRao Pulia6349912019-10-18 17:16:08 +05301988 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001989 oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301990 }
1991 else
1992 {
Ed Tanous002d39b2022-05-31 08:59:27 -07001993 oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
AppaRao Pulia6349912019-10-18 17:16:08 +05301994 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001995 }
1996 else
1997 {
1998 oemPFR["ProvisioningStatus"] = "NotProvisioned";
1999 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002000 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302001}
2002#endif
2003
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302004/**
Chris Cain3a2d04242021-05-28 16:57:10 -05002005 * @brief Translate the PowerMode to a response message.
2006 *
2007 * @param[in] aResp Shared pointer for generating response message.
2008 * @param[in] modeValue PowerMode value to be translated
2009 *
2010 * @return None.
2011 */
2012inline void translatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2013 const std::string& modeValue)
2014{
George Liu0fda0f12021-11-16 10:06:17 +08002015 if (modeValue == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002016 {
2017 aResp->res.jsonValue["PowerMode"] = "Static";
2018 }
George Liu0fda0f12021-11-16 10:06:17 +08002019 else if (
2020 modeValue ==
2021 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002022 {
2023 aResp->res.jsonValue["PowerMode"] = "MaximumPerformance";
2024 }
George Liu0fda0f12021-11-16 10:06:17 +08002025 else if (modeValue ==
2026 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002027 {
2028 aResp->res.jsonValue["PowerMode"] = "PowerSaving";
2029 }
George Liu0fda0f12021-11-16 10:06:17 +08002030 else if (modeValue ==
2031 "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002032 {
2033 aResp->res.jsonValue["PowerMode"] = "OEM";
2034 }
2035 else
2036 {
2037 // Any other values would be invalid
2038 BMCWEB_LOG_DEBUG << "PowerMode value was not valid: " << modeValue;
2039 messages::internalError(aResp->res);
2040 }
2041}
2042
2043/**
2044 * @brief Retrieves system power mode
2045 *
2046 * @param[in] aResp Shared pointer for generating response message.
2047 *
2048 * @return None.
2049 */
2050inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2051{
2052 BMCWEB_LOG_DEBUG << "Get power mode.";
2053
2054 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002055 constexpr std::array<std::string_view, 1> interfaces = {
2056 "xyz.openbmc_project.Control.Power.Mode"};
2057 dbus::utility::getSubTree(
2058 "/", 0, interfaces,
2059 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002060 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002061 if (ec)
2062 {
2063 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2064 << ec;
2065 // This is an optional D-Bus object so just return if
2066 // error occurs
2067 return;
2068 }
2069 if (subtree.empty())
2070 {
2071 // As noted above, this is an optional interface so just return
2072 // if there is no instance found
2073 return;
2074 }
2075 if (subtree.size() > 1)
2076 {
2077 // More then one PowerMode object is not supported and is an
2078 // error
2079 BMCWEB_LOG_DEBUG
2080 << "Found more than 1 system D-Bus Power.Mode objects: "
2081 << subtree.size();
2082 messages::internalError(aResp->res);
2083 return;
2084 }
2085 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2086 {
2087 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2088 messages::internalError(aResp->res);
2089 return;
2090 }
2091 const std::string& path = subtree[0].first;
2092 const std::string& service = subtree[0].second.begin()->first;
2093 if (service.empty())
2094 {
2095 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2096 messages::internalError(aResp->res);
2097 return;
2098 }
2099 // Valid Power Mode object found, now read the current value
2100 sdbusplus::asio::getProperty<std::string>(
2101 *crow::connections::systemBus, service, path,
2102 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002103 [aResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002104 const std::string& pmode) {
Ed Tanous8a592812022-06-04 09:06:59 -07002105 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002106 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002107 BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: "
Ed Tanous8a592812022-06-04 09:06:59 -07002108 << ec2;
Chris Cain3a2d04242021-05-28 16:57:10 -05002109 messages::internalError(aResp->res);
2110 return;
2111 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002112
Ed Tanous002d39b2022-05-31 08:59:27 -07002113 aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = {
2114 "Static", "MaximumPerformance", "PowerSaving"};
Chris Cain3a2d04242021-05-28 16:57:10 -05002115
Ed Tanous002d39b2022-05-31 08:59:27 -07002116 BMCWEB_LOG_DEBUG << "Current power mode: " << pmode;
2117 translatePowerMode(aResp, pmode);
2118 });
George Liue99073f2022-12-09 11:06:16 +08002119 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002120}
2121
2122/**
2123 * @brief Validate the specified mode is valid and return the PowerMode
2124 * name associated with that string
2125 *
2126 * @param[in] aResp Shared pointer for generating response message.
2127 * @param[in] modeString String representing the desired PowerMode
2128 *
2129 * @return PowerMode value or empty string if mode is not valid
2130 */
2131inline std::string
2132 validatePowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2133 const std::string& modeString)
2134{
2135 std::string mode;
2136
2137 if (modeString == "Static")
2138 {
2139 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2140 }
2141 else if (modeString == "MaximumPerformance")
2142 {
George Liu0fda0f12021-11-16 10:06:17 +08002143 mode =
2144 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002145 }
2146 else if (modeString == "PowerSaving")
2147 {
2148 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2149 }
2150 else
2151 {
2152 messages::propertyValueNotInList(aResp->res, modeString, "PowerMode");
2153 }
2154 return mode;
2155}
2156
2157/**
2158 * @brief Sets system power mode.
2159 *
2160 * @param[in] aResp Shared pointer for generating response message.
2161 * @param[in] pmode System power mode from request.
2162 *
2163 * @return None.
2164 */
2165inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2166 const std::string& pmode)
2167{
2168 BMCWEB_LOG_DEBUG << "Set power mode.";
2169
2170 std::string powerMode = validatePowerMode(aResp, pmode);
2171 if (powerMode.empty())
2172 {
2173 return;
2174 }
2175
2176 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002177 constexpr std::array<std::string_view, 1> interfaces = {
2178 "xyz.openbmc_project.Control.Power.Mode"};
2179 dbus::utility::getSubTree(
2180 "/", 0, interfaces,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002181 [aResp,
George Liue99073f2022-12-09 11:06:16 +08002182 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002183 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002184 if (ec)
2185 {
2186 BMCWEB_LOG_DEBUG << "DBUS response error on Power.Mode GetSubTree "
2187 << ec;
2188 // This is an optional D-Bus object, but user attempted to patch
2189 messages::internalError(aResp->res);
2190 return;
2191 }
2192 if (subtree.empty())
2193 {
2194 // This is an optional D-Bus object, but user attempted to patch
2195 messages::resourceNotFound(aResp->res, "ComputerSystem",
2196 "PowerMode");
2197 return;
2198 }
2199 if (subtree.size() > 1)
2200 {
2201 // More then one PowerMode object is not supported and is an
2202 // error
2203 BMCWEB_LOG_DEBUG
2204 << "Found more than 1 system D-Bus Power.Mode objects: "
2205 << subtree.size();
2206 messages::internalError(aResp->res);
2207 return;
2208 }
2209 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2210 {
2211 BMCWEB_LOG_DEBUG << "Power.Mode mapper error!";
2212 messages::internalError(aResp->res);
2213 return;
2214 }
2215 const std::string& path = subtree[0].first;
2216 const std::string& service = subtree[0].second.begin()->first;
2217 if (service.empty())
2218 {
2219 BMCWEB_LOG_DEBUG << "Power.Mode service mapper error!";
2220 messages::internalError(aResp->res);
2221 return;
2222 }
2223
2224 BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> "
2225 << path;
2226
2227 // Set the Power Mode property
2228 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002229 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002230 if (ec2)
Chris Cain3a2d04242021-05-28 16:57:10 -05002231 {
Chris Cain3a2d04242021-05-28 16:57:10 -05002232 messages::internalError(aResp->res);
2233 return;
2234 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002235 },
2236 service, path, "org.freedesktop.DBus.Properties", "Set",
2237 "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
2238 dbus::utility::DbusVariantType(powerMode));
George Liue99073f2022-12-09 11:06:16 +08002239 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002240}
2241
2242/**
Yong Li51709ff2019-09-30 14:13:04 +08002243 * @brief Translates watchdog timeout action DBUS property value to redfish.
2244 *
2245 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2246 *
2247 * @return Returns as a string, the timeout action in Redfish terms. If
2248 * translation cannot be done, returns an empty string.
2249 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002250inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002251{
2252 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2253 {
2254 return "None";
2255 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002256 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002257 {
2258 return "ResetSystem";
2259 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002260 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002261 {
2262 return "PowerDown";
2263 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002264 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002265 {
2266 return "PowerCycle";
2267 }
2268
2269 return "";
2270}
2271
2272/**
Yong Lic45f0082019-10-10 14:19:01 +08002273 *@brief Translates timeout action from Redfish to DBUS property value.
2274 *
2275 *@param[in] rfAction The timeout action in Redfish.
2276 *
2277 *@return Returns as a string, the time_out action as expected by DBUS.
2278 *If translation cannot be done, returns an empty string.
2279 */
2280
Ed Tanous23a21a12020-07-25 04:45:05 +00002281inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002282{
2283 if (rfAction == "None")
2284 {
2285 return "xyz.openbmc_project.State.Watchdog.Action.None";
2286 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002287 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002288 {
2289 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2290 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002291 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002292 {
2293 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2294 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002295 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002296 {
2297 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2298 }
2299
2300 return "";
2301}
2302
2303/**
Yong Li51709ff2019-09-30 14:13:04 +08002304 * @brief Retrieves host watchdog timer properties over DBUS
2305 *
2306 * @param[in] aResp Shared pointer for completing asynchronous calls.
2307 *
2308 * @return None.
2309 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002310inline void
2311 getHostWatchdogTimer(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
Yong Li51709ff2019-09-30 14:13:04 +08002312{
2313 BMCWEB_LOG_DEBUG << "Get host watchodg";
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002314 sdbusplus::asio::getAllProperties(
2315 *crow::connections::systemBus, "xyz.openbmc_project.Watchdog",
2316 "/xyz/openbmc_project/watchdog/host0",
2317 "xyz.openbmc_project.State.Watchdog",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002318 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002319 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002320 if (ec)
2321 {
2322 // watchdog service is stopped
2323 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2324 return;
2325 }
2326
2327 BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop.";
2328
2329 nlohmann::json& hostWatchdogTimer =
2330 aResp->res.jsonValue["HostWatchdogTimer"];
2331
2332 // watchdog service is running/enabled
2333 hostWatchdogTimer["Status"]["State"] = "Enabled";
2334
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002335 const bool* enabled = nullptr;
2336 const std::string* expireAction = nullptr;
2337
2338 const bool success = sdbusplus::unpackPropertiesNoThrow(
2339 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
2340 "ExpireAction", expireAction);
2341
2342 if (!success)
Ed Tanous002d39b2022-05-31 08:59:27 -07002343 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002344 messages::internalError(aResp->res);
2345 return;
Ed Tanous002d39b2022-05-31 08:59:27 -07002346 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002347
2348 if (enabled != nullptr)
2349 {
2350 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2351 }
2352
2353 if (expireAction != nullptr)
2354 {
2355 std::string action = dbusToRfWatchdogAction(*expireAction);
2356 if (action.empty())
2357 {
2358 messages::internalError(aResp->res);
2359 return;
2360 }
2361 hostWatchdogTimer["TimeoutAction"] = action;
2362 }
2363 });
Yong Li51709ff2019-09-30 14:13:04 +08002364}
2365
2366/**
Yong Lic45f0082019-10-10 14:19:01 +08002367 * @brief Sets Host WatchDog Timer properties.
2368 *
2369 * @param[in] aResp Shared pointer for generating response message.
2370 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2371 * RF request.
2372 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2373 *
2374 * @return None.
2375 */
zhanghch058d1b46d2021-04-01 11:18:24 +08002376inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
Yong Lic45f0082019-10-10 14:19:01 +08002377 const std::optional<bool> wdtEnable,
Gunnar Mills1214b7e2020-06-04 10:11:30 -05002378 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002379{
2380 BMCWEB_LOG_DEBUG << "Set host watchdog";
2381
2382 if (wdtTimeOutAction)
2383 {
2384 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2385 // check if TimeOut Action is Valid
2386 if (wdtTimeOutActStr.empty())
2387 {
2388 BMCWEB_LOG_DEBUG << "Unsupported value for TimeoutAction: "
2389 << *wdtTimeOutAction;
2390 messages::propertyValueNotInList(aResp->res, *wdtTimeOutAction,
2391 "TimeoutAction");
2392 return;
2393 }
2394
2395 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002396 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002397 if (ec)
2398 {
2399 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2400 messages::internalError(aResp->res);
2401 return;
2402 }
Yong Lic45f0082019-10-10 14:19:01 +08002403 },
2404 "xyz.openbmc_project.Watchdog",
2405 "/xyz/openbmc_project/watchdog/host0",
2406 "org.freedesktop.DBus.Properties", "Set",
2407 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ed Tanous168e20c2021-12-13 14:39:53 -08002408 dbus::utility::DbusVariantType(wdtTimeOutActStr));
Yong Lic45f0082019-10-10 14:19:01 +08002409 }
2410
2411 if (wdtEnable)
2412 {
2413 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002414 [aResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002415 if (ec)
2416 {
2417 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
2418 messages::internalError(aResp->res);
2419 return;
2420 }
Yong Lic45f0082019-10-10 14:19:01 +08002421 },
2422 "xyz.openbmc_project.Watchdog",
2423 "/xyz/openbmc_project/watchdog/host0",
2424 "org.freedesktop.DBus.Properties", "Set",
2425 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ed Tanous168e20c2021-12-13 14:39:53 -08002426 dbus::utility::DbusVariantType(*wdtEnable));
Yong Lic45f0082019-10-10 14:19:01 +08002427 }
2428}
2429
Chris Cain37bbf982021-09-20 10:53:09 -05002430/**
2431 * @brief Parse the Idle Power Saver properties into json
2432 *
2433 * @param[in] aResp Shared pointer for completing asynchronous calls.
2434 * @param[in] properties IPS property data from DBus.
2435 *
2436 * @return true if successful
2437 */
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002438inline bool
2439 parseIpsProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2440 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002441{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002442 const bool* enabled = nullptr;
2443 const uint8_t* enterUtilizationPercent = nullptr;
2444 const uint64_t* enterDwellTime = nullptr;
2445 const uint8_t* exitUtilizationPercent = nullptr;
2446 const uint64_t* exitDwellTime = nullptr;
2447
2448 const bool success = sdbusplus::unpackPropertiesNoThrow(
2449 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002450 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2451 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2452 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002453
2454 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002455 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002456 return false;
2457 }
2458
2459 if (enabled != nullptr)
2460 {
2461 aResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
2462 }
2463
2464 if (enterUtilizationPercent != nullptr)
2465 {
2466 aResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
2467 *enterUtilizationPercent;
2468 }
2469
2470 if (enterDwellTime != nullptr)
2471 {
2472 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
2473 aResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
2474 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2475 .count();
2476 }
2477
2478 if (exitUtilizationPercent != nullptr)
2479 {
2480 aResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
2481 *exitUtilizationPercent;
2482 }
2483
2484 if (exitDwellTime != nullptr)
2485 {
2486 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
2487 aResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
2488 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2489 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002490 }
2491
2492 return true;
2493}
2494
2495/**
2496 * @brief Retrieves host watchdog timer properties over DBUS
2497 *
2498 * @param[in] aResp Shared pointer for completing asynchronous calls.
2499 *
2500 * @return None.
2501 */
2502inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp)
2503{
2504 BMCWEB_LOG_DEBUG << "Get idle power saver parameters";
2505
2506 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002507 constexpr std::array<std::string_view, 1> interfaces = {
2508 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2509 dbus::utility::getSubTree(
2510 "/", 0, interfaces,
2511 [aResp](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002512 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002513 if (ec)
2514 {
2515 BMCWEB_LOG_DEBUG
2516 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2517 << ec;
2518 messages::internalError(aResp->res);
2519 return;
2520 }
2521 if (subtree.empty())
2522 {
2523 // This is an optional interface so just return
2524 // if there is no instance found
2525 BMCWEB_LOG_DEBUG << "No instances found";
2526 return;
2527 }
2528 if (subtree.size() > 1)
2529 {
2530 // More then one PowerIdlePowerSaver object is not supported and
2531 // is an error
2532 BMCWEB_LOG_DEBUG << "Found more than 1 system D-Bus "
2533 "Power.IdlePowerSaver objects: "
2534 << subtree.size();
2535 messages::internalError(aResp->res);
2536 return;
2537 }
2538 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2539 {
2540 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2541 messages::internalError(aResp->res);
2542 return;
2543 }
2544 const std::string& path = subtree[0].first;
2545 const std::string& service = subtree[0].second.begin()->first;
2546 if (service.empty())
2547 {
2548 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2549 messages::internalError(aResp->res);
2550 return;
2551 }
2552
2553 // Valid IdlePowerSaver object found, now read the current values
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002554 sdbusplus::asio::getAllProperties(
2555 *crow::connections::systemBus, service, path,
2556 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002557 [aResp](const boost::system::error_code& ec2,
Jiaqing Zhao1e5b7c82022-08-15 16:15:52 +08002558 const dbus::utility::DBusPropertiesMap& properties) {
Ed Tanous8a592812022-06-04 09:06:59 -07002559 if (ec2)
Chris Cain37bbf982021-09-20 10:53:09 -05002560 {
Ed Tanous002d39b2022-05-31 08:59:27 -07002561 BMCWEB_LOG_ERROR
Ed Tanous8a592812022-06-04 09:06:59 -07002562 << "DBUS response error on IdlePowerSaver GetAll: " << ec2;
Chris Cain37bbf982021-09-20 10:53:09 -05002563 messages::internalError(aResp->res);
2564 return;
2565 }
2566
Ed Tanous002d39b2022-05-31 08:59:27 -07002567 if (!parseIpsProperties(aResp, properties))
2568 {
2569 messages::internalError(aResp->res);
2570 return;
2571 }
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002572 });
George Liue99073f2022-12-09 11:06:16 +08002573 });
Chris Cain37bbf982021-09-20 10:53:09 -05002574
2575 BMCWEB_LOG_DEBUG << "EXIT: Get idle power saver parameters";
2576}
2577
2578/**
2579 * @brief Sets Idle Power Saver properties.
2580 *
2581 * @param[in] aResp Shared pointer for generating response message.
2582 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2583 * RF request.
2584 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2585 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2586 * before entering idle state.
2587 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2588 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2589 * before exiting idle state
2590 *
2591 * @return None.
2592 */
2593inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
2594 const std::optional<bool> ipsEnable,
2595 const std::optional<uint8_t> ipsEnterUtil,
2596 const std::optional<uint64_t> ipsEnterTime,
2597 const std::optional<uint8_t> ipsExitUtil,
2598 const std::optional<uint64_t> ipsExitTime)
2599{
2600 BMCWEB_LOG_DEBUG << "Set idle power saver properties";
2601
2602 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002603 constexpr std::array<std::string_view, 1> interfaces = {
2604 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2605 dbus::utility::getSubTree(
2606 "/", 0, interfaces,
Chris Cain37bbf982021-09-20 10:53:09 -05002607 [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002608 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002609 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002610 if (ec)
2611 {
2612 BMCWEB_LOG_DEBUG
2613 << "DBUS response error on Power.IdlePowerSaver GetSubTree "
2614 << ec;
2615 messages::internalError(aResp->res);
2616 return;
2617 }
2618 if (subtree.empty())
2619 {
2620 // This is an optional D-Bus object, but user attempted to patch
2621 messages::resourceNotFound(aResp->res, "ComputerSystem",
2622 "IdlePowerSaver");
2623 return;
2624 }
2625 if (subtree.size() > 1)
2626 {
2627 // More then one PowerIdlePowerSaver object is not supported and
2628 // is an error
2629 BMCWEB_LOG_DEBUG
2630 << "Found more than 1 system D-Bus Power.IdlePowerSaver objects: "
2631 << subtree.size();
2632 messages::internalError(aResp->res);
2633 return;
2634 }
2635 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2636 {
2637 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!";
2638 messages::internalError(aResp->res);
2639 return;
2640 }
2641 const std::string& path = subtree[0].first;
2642 const std::string& service = subtree[0].second.begin()->first;
2643 if (service.empty())
2644 {
2645 BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver service mapper error!";
2646 messages::internalError(aResp->res);
2647 return;
2648 }
Chris Cain37bbf982021-09-20 10:53:09 -05002649
Ed Tanous002d39b2022-05-31 08:59:27 -07002650 // Valid Power IdlePowerSaver object found, now set any values that
2651 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002652
Ed Tanous002d39b2022-05-31 08:59:27 -07002653 if (ipsEnable)
2654 {
2655 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002656 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002657 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002658 {
Ed Tanous8a592812022-06-04 09:06:59 -07002659 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002660 messages::internalError(aResp->res);
2661 return;
2662 }
2663 },
2664 service, path, "org.freedesktop.DBus.Properties", "Set",
2665 "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled",
2666 dbus::utility::DbusVariantType(*ipsEnable));
2667 }
2668 if (ipsEnterUtil)
2669 {
2670 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002671 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002672 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002673 {
Ed Tanous8a592812022-06-04 09:06:59 -07002674 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002675 messages::internalError(aResp->res);
2676 return;
2677 }
2678 },
2679 service, path, "org.freedesktop.DBus.Properties", "Set",
2680 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2681 "EnterUtilizationPercent",
2682 dbus::utility::DbusVariantType(*ipsEnterUtil));
2683 }
2684 if (ipsEnterTime)
2685 {
2686 // Convert from seconds into milliseconds for DBus
2687 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2688 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002689 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002690 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002691 {
Ed Tanous8a592812022-06-04 09:06:59 -07002692 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002693 messages::internalError(aResp->res);
2694 return;
2695 }
2696 },
2697 service, path, "org.freedesktop.DBus.Properties", "Set",
2698 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2699 "EnterDwellTime",
2700 dbus::utility::DbusVariantType(timeMilliseconds));
2701 }
2702 if (ipsExitUtil)
2703 {
2704 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002705 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002706 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002707 {
Ed Tanous8a592812022-06-04 09:06:59 -07002708 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002709 messages::internalError(aResp->res);
2710 return;
2711 }
2712 },
2713 service, path, "org.freedesktop.DBus.Properties", "Set",
2714 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2715 "ExitUtilizationPercent",
2716 dbus::utility::DbusVariantType(*ipsExitUtil));
2717 }
2718 if (ipsExitTime)
2719 {
2720 // Convert from seconds into milliseconds for DBus
2721 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2722 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002723 [aResp](const boost::system::error_code& ec2) {
Ed Tanous8a592812022-06-04 09:06:59 -07002724 if (ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002725 {
Ed Tanous8a592812022-06-04 09:06:59 -07002726 BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
Ed Tanous002d39b2022-05-31 08:59:27 -07002727 messages::internalError(aResp->res);
2728 return;
2729 }
2730 },
2731 service, path, "org.freedesktop.DBus.Properties", "Set",
2732 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2733 "ExitDwellTime",
2734 dbus::utility::DbusVariantType(timeMilliseconds));
2735 }
George Liue99073f2022-12-09 11:06:16 +08002736 });
Chris Cain37bbf982021-09-20 10:53:09 -05002737
2738 BMCWEB_LOG_DEBUG << "EXIT: Set idle power saver parameters";
2739}
2740
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002741inline void handleComputerSystemHead(
2742 crow::App& app, const crow::Request& req,
2743 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2744{
2745 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2746 {
2747 return;
2748 }
2749 asyncResp->res.addHeader(
2750 boost::beast::http::field::link,
2751 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2752}
2753
Yong Lic45f0082019-10-10 14:19:01 +08002754/**
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002755 * SystemsCollection derived class for delivering ComputerSystems Collection
2756 * Schema
2757 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002758inline void requestRoutesSystemsCollection(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07002759{
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002760 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002761 .privileges(redfish::privileges::headComputerSystemCollection)
2762 .methods(boost::beast::http::verb::head)(
2763 std::bind_front(handleComputerSystemHead, std::ref(app)));
2764
2765 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
Ed Tanoused398212021-06-09 17:05:54 -07002766 .privileges(redfish::privileges::getComputerSystemCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002767 .methods(boost::beast::http::verb::get)(
Ed Tanousf4c99e72021-10-04 17:02:43 -07002768 [&app](const crow::Request& req,
2769 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002770 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002771 {
2772 return;
2773 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002774
2775 asyncResp->res.addHeader(
2776 boost::beast::http::field::link,
2777 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07002778 asyncResp->res.jsonValue["@odata.type"] =
2779 "#ComputerSystemCollection.ComputerSystemCollection";
2780 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2781 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002782
Ed Tanous002d39b2022-05-31 08:59:27 -07002783 sdbusplus::asio::getProperty<std::string>(
2784 *crow::connections::systemBus, "xyz.openbmc_project.Settings",
2785 "/xyz/openbmc_project/network/hypervisor",
2786 "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002787 [asyncResp](const boost::system::error_code& ec2,
Ed Tanous002d39b2022-05-31 08:59:27 -07002788 const std::string& /*hostName*/) {
2789 nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2790 ifaceArray = nlohmann::json::array();
2791 auto& count = asyncResp->res.jsonValue["Members@odata.count"];
Ed Tanous14766872022-03-15 10:44:42 -07002792
Ed Tanous002d39b2022-05-31 08:59:27 -07002793 nlohmann::json::object_t system;
2794 system["@odata.id"] = "/redfish/v1/Systems/system";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002795 ifaceArray.emplace_back(std::move(system));
Ed Tanous002d39b2022-05-31 08:59:27 -07002796 count = ifaceArray.size();
Ed Tanous8a592812022-06-04 09:06:59 -07002797 if (!ec2)
Ed Tanous002d39b2022-05-31 08:59:27 -07002798 {
2799 BMCWEB_LOG_DEBUG << "Hypervisor is available";
2800 nlohmann::json::object_t hypervisor;
2801 hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
Patrick Williamsb2ba3072023-05-12 10:27:39 -05002802 ifaceArray.emplace_back(std::move(hypervisor));
Ed Tanous002d39b2022-05-31 08:59:27 -07002803 count = ifaceArray.size();
2804 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002805 });
Ed Tanous002d39b2022-05-31 08:59:27 -07002806 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002807}
Sunitha Harish462023a2020-02-19 08:34:59 -06002808
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002809/**
2810 * Function transceives data with dbus directly.
2811 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002812inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002813{
Patrick Williams89492a12023-05-10 07:51:34 -05002814 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2815 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2816 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002817 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002818 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002819
2820 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002821 [asyncResp](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002822 if (ec)
2823 {
2824 BMCWEB_LOG_ERROR << " Bad D-Bus request error: " << ec;
2825 messages::internalError(asyncResp->res);
2826 return;
2827 }
2828 messages::success(asyncResp->res);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002829 },
2830 serviceName, objectPath, interfaceName, method);
2831}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002832
2833/**
Ed Tanouscc340dd2018-08-29 13:43:38 -07002834 * SystemActionsReset class supports handle POST method for Reset action.
2835 * The class retrieves and sends data directly to D-Bus.
2836 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002837inline void requestRoutesSystemActionsReset(App& app)
Ed Tanouscc340dd2018-08-29 13:43:38 -07002838{
Ed Tanouscc340dd2018-08-29 13:43:38 -07002839 /**
2840 * Function handles POST method request.
2841 * Analyzes POST body message before sends Reset request data to D-Bus.
2842 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002843 BMCWEB_ROUTE(app,
2844 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/")
Ed Tanoused398212021-06-09 17:05:54 -07002845 .privileges(redfish::privileges::postComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07002846 .methods(boost::beast::http::verb::post)(
2847 [&app](const crow::Request& req,
2848 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +00002849 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07002850 {
2851 return;
2852 }
2853 std::string resetType;
2854 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
2855 resetType))
2856 {
2857 return;
2858 }
Ed Tanous9712f8a2018-09-21 13:38:49 -07002859
Ed Tanous002d39b2022-05-31 08:59:27 -07002860 // Get the command and host vs. chassis
2861 std::string command;
2862 bool hostCommand = true;
2863 if ((resetType == "On") || (resetType == "ForceOn"))
2864 {
2865 command = "xyz.openbmc_project.State.Host.Transition.On";
2866 hostCommand = true;
2867 }
2868 else if (resetType == "ForceOff")
2869 {
2870 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2871 hostCommand = false;
2872 }
2873 else if (resetType == "ForceRestart")
2874 {
2875 command =
2876 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2877 hostCommand = true;
2878 }
2879 else if (resetType == "GracefulShutdown")
2880 {
2881 command = "xyz.openbmc_project.State.Host.Transition.Off";
2882 hostCommand = true;
2883 }
2884 else if (resetType == "GracefulRestart")
2885 {
2886 command =
2887 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2888 hostCommand = true;
2889 }
2890 else if (resetType == "PowerCycle")
2891 {
2892 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2893 hostCommand = true;
2894 }
2895 else if (resetType == "Nmi")
2896 {
2897 doNMI(asyncResp);
2898 return;
2899 }
2900 else
2901 {
2902 messages::actionParameterUnknown(asyncResp->res, "Reset",
2903 resetType);
2904 return;
2905 }
Ed Tanouscc340dd2018-08-29 13:43:38 -07002906
Ed Tanous002d39b2022-05-31 08:59:27 -07002907 if (hostCommand)
2908 {
2909 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002910 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002911 if (ec)
2912 {
2913 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2914 if (ec.value() == boost::asio::error::invalid_argument)
2915 {
2916 messages::actionParameterNotSupported(
2917 asyncResp->res, resetType, "Reset");
2918 }
2919 else
2920 {
2921 messages::internalError(asyncResp->res);
2922 }
2923 return;
2924 }
2925 messages::success(asyncResp->res);
2926 },
2927 "xyz.openbmc_project.State.Host",
2928 "/xyz/openbmc_project/state/host0",
2929 "org.freedesktop.DBus.Properties", "Set",
2930 "xyz.openbmc_project.State.Host", "RequestedHostTransition",
2931 dbus::utility::DbusVariantType{command});
2932 }
2933 else
2934 {
2935 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002936 [asyncResp, resetType](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -07002937 if (ec)
2938 {
2939 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
2940 if (ec.value() == boost::asio::error::invalid_argument)
2941 {
2942 messages::actionParameterNotSupported(
2943 asyncResp->res, resetType, "Reset");
2944 }
2945 else
2946 {
2947 messages::internalError(asyncResp->res);
2948 }
2949 return;
2950 }
2951 messages::success(asyncResp->res);
2952 },
2953 "xyz.openbmc_project.State.Chassis",
2954 "/xyz/openbmc_project/state/chassis0",
2955 "org.freedesktop.DBus.Properties", "Set",
2956 "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition",
2957 dbus::utility::DbusVariantType{command});
2958 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002959 });
2960}
Ed Tanouscc340dd2018-08-29 13:43:38 -07002961
Ed Tanous38c8a6f2022-09-01 16:37:27 -07002962inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002963 App& app, const crow::Request& req,
2964 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2965{
2966 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2967 {
2968 return;
2969 }
2970
2971 asyncResp->res.addHeader(
2972 boost::beast::http::field::link,
2973 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2974}
2975
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002976inline void afterPortRequest(
2977 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2978 const boost::system::error_code& ec,
2979 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2980{
2981 if (ec)
2982 {
2983 messages::internalError(asyncResp->res);
2984 return;
2985 }
2986 for (const auto& data : socketData)
2987 {
2988 const std::string& socketPath = get<0>(data);
2989 const std::string& protocolName = get<1>(data);
2990 bool isProtocolEnabled = get<2>(data);
2991 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
2992 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
2993 // need to retrieve port number for
2994 // obmc-console-ssh service
2995 if (protocolName == "SSH")
2996 {
2997 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07002998 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002999 int portNumber) {
3000 if (ec1)
3001 {
3002 messages::internalError(asyncResp->res);
3003 return;
3004 }
3005 nlohmann::json& dataJson1 =
3006 asyncResp->res.jsonValue["SerialConsole"];
3007 dataJson1[protocolName]["Port"] = portNumber;
3008 });
3009 }
3010 }
3011}
Ed Tanouscc340dd2018-08-29 13:43:38 -07003012/**
Ed Tanous66173382018-08-15 18:20:59 -07003013 * Systems derived class for delivering Computer Systems Schema.
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003014 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003015inline void requestRoutesSystems(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003016{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003017 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/")
3018 .privileges(redfish::privileges::headComputerSystem)
3019 .methods(boost::beast::http::verb::head)(
3020 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
Ed Tanous1abe55e2018-09-05 08:30:59 -07003021 /**
3022 * Functions triggers appropriate requests on DBus
3023 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003024 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003025 .privileges(redfish::privileges::getComputerSystem)
Ed Tanous002d39b2022-05-31 08:59:27 -07003026 .methods(boost::beast::http::verb::get)(
3027 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003028 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3029 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003030 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003031 {
3032 return;
3033 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003034
3035 if (systemName == "hypervisor")
3036 {
3037 handleHypervisorSystemGet(asyncResp);
3038 return;
3039 }
3040
Ed Tanous22d268c2022-05-19 09:39:07 -07003041 if (systemName != "system")
3042 {
3043 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3044 systemName);
3045 return;
3046 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003047 asyncResp->res.addHeader(
3048 boost::beast::http::field::link,
3049 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
Ed Tanous002d39b2022-05-31 08:59:27 -07003050 asyncResp->res.jsonValue["@odata.type"] =
3051 "#ComputerSystem.v1_16_0.ComputerSystem";
3052 asyncResp->res.jsonValue["Name"] = "system";
3053 asyncResp->res.jsonValue["Id"] = "system";
3054 asyncResp->res.jsonValue["SystemType"] = "Physical";
3055 asyncResp->res.jsonValue["Description"] = "Computer System";
3056 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
3057 asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] =
3058 "Disabled";
Ed Tanous002d39b2022-05-31 08:59:27 -07003059 asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] =
3060 "Disabled";
Ninad Palsulecf0e0042023-05-18 17:18:09 -05003061 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
3062 uint64_t(0);
Ed Tanous002d39b2022-05-31 08:59:27 -07003063 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system";
Ed Tanous04a258f2018-10-15 08:00:41 -07003064
Ed Tanous002d39b2022-05-31 08:59:27 -07003065 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3066 "/redfish/v1/Systems/system/Processors";
3067 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3068 "/redfish/v1/Systems/system/Memory";
3069 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3070 "/redfish/v1/Systems/system/Storage";
Sunny Srivastava31791052021-03-12 10:39:16 -06003071 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3072 "/redfish/v1/Systems/system/FabricAdapters";
Ed Tanous029573d2019-02-01 10:57:49 -08003073
Ed Tanous002d39b2022-05-31 08:59:27 -07003074 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
3075 "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset";
3076 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]
3077 ["@Redfish.ActionInfo"] =
3078 "/redfish/v1/Systems/system/ResetActionInfo";
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003079
Ed Tanous002d39b2022-05-31 08:59:27 -07003080 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3081 "/redfish/v1/Systems/system/LogServices";
3082 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3083 "/redfish/v1/Systems/system/Bios";
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003084
Ed Tanous002d39b2022-05-31 08:59:27 -07003085 nlohmann::json::array_t managedBy;
3086 nlohmann::json& manager = managedBy.emplace_back();
3087 manager["@odata.id"] = "/redfish/v1/Managers/bmc";
3088 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
3089 asyncResp->res.jsonValue["Status"]["Health"] = "OK";
3090 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003091
Ed Tanous002d39b2022-05-31 08:59:27 -07003092 // Fill in SerialConsole info
3093 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3094 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] =
3095 true;
Ed Tanous14766872022-03-15 10:44:42 -07003096
Ed Tanous002d39b2022-05-31 08:59:27 -07003097 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] =
3098 true;
3099 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3100 asyncResp->res
3101 .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3102 "Press ~. to exit console";
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003103 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3104 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003105
3106#ifdef BMCWEB_ENABLE_KVM
Ed Tanous002d39b2022-05-31 08:59:27 -07003107 // Fill in GraphicalConsole info
3108 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3109 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3110 4;
Ed Tanous613dabe2022-07-09 11:17:36 -07003111 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3112 nlohmann::json::array_t({"KVMIP"});
Ed Tanous14766872022-03-15 10:44:42 -07003113
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003114#endif // BMCWEB_ENABLE_KVM
James Feistb49ac872019-05-21 15:12:01 -07003115
Ed Tanous002d39b2022-05-31 08:59:27 -07003116 auto health = std::make_shared<HealthPopulate>(asyncResp);
Willy Tu13451e32023-05-24 16:08:18 -07003117 if constexpr (bmcwebEnableHealthPopulate)
3118 {
3119 constexpr std::array<std::string_view, 4> inventoryForSystems{
3120 "xyz.openbmc_project.Inventory.Item.Dimm",
3121 "xyz.openbmc_project.Inventory.Item.Cpu",
3122 "xyz.openbmc_project.Inventory.Item.Drive",
3123 "xyz.openbmc_project.Inventory.Item.StorageController"};
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003124
Willy Tu13451e32023-05-24 16:08:18 -07003125 dbus::utility::getSubTreePaths(
3126 "/", 0, inventoryForSystems,
3127 [health](const boost::system::error_code& ec,
3128 const std::vector<std::string>& resp) {
3129 if (ec)
3130 {
3131 // no inventory
3132 return;
3133 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003134
Willy Tu13451e32023-05-24 16:08:18 -07003135 health->inventory = resp;
3136 });
3137 health->populate();
3138 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003139
Ed Tanous002d39b2022-05-31 08:59:27 -07003140 getMainChassisId(asyncResp,
3141 [](const std::string& chassisId,
3142 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3143 nlohmann::json::array_t chassisArray;
3144 nlohmann::json& chassis = chassisArray.emplace_back();
Ed Tanousef4c65b2023-04-24 15:28:50 -07003145 chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
3146 chassisId);
Ed Tanous002d39b2022-05-31 08:59:27 -07003147 aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
3148 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003149
Ed Tanous002d39b2022-05-31 08:59:27 -07003150 getLocationIndicatorActive(asyncResp);
3151 // TODO (Gunnar): Remove IndicatorLED after enough time has passed
3152 getIndicatorLedState(asyncResp);
3153 getComputerSystem(asyncResp, health);
3154 getHostState(asyncResp);
3155 getBootProperties(asyncResp);
3156 getBootProgress(asyncResp);
Hieu Huynhb6d5d452022-10-07 09:41:46 +00003157 getBootProgressLastStateTime(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003158 getPCIeDeviceList(asyncResp, "PCIeDevices");
3159 getHostWatchdogTimer(asyncResp);
3160 getPowerRestorePolicy(asyncResp);
Corey Hardesty797d5da2022-04-26 17:54:52 +08003161 getAutomaticRetryPolicy(asyncResp);
Ed Tanous002d39b2022-05-31 08:59:27 -07003162 getLastResetTime(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003163#ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE
Ed Tanous002d39b2022-05-31 08:59:27 -07003164 getProvisioningStatus(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003165#endif
Ed Tanous002d39b2022-05-31 08:59:27 -07003166 getTrustedModuleRequiredToBoot(asyncResp);
3167 getPowerMode(asyncResp);
3168 getIdlePowerSaver(asyncResp);
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003169 });
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003170
Ed Tanous22d268c2022-05-19 09:39:07 -07003171 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -07003172 .privileges(redfish::privileges::patchComputerSystem)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003173 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003174 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003175 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3176 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003177 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003178 {
3179 return;
3180 }
Ed Tanous22d268c2022-05-19 09:39:07 -07003181 if (systemName != "system")
3182 {
3183 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3184 systemName);
3185 return;
3186 }
3187
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003188 asyncResp->res.addHeader(
3189 boost::beast::http::field::link,
3190 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3191
Ed Tanous002d39b2022-05-31 08:59:27 -07003192 std::optional<bool> locationIndicatorActive;
3193 std::optional<std::string> indicatorLed;
3194 std::optional<std::string> assetTag;
3195 std::optional<std::string> powerRestorePolicy;
3196 std::optional<std::string> powerMode;
3197 std::optional<bool> wdtEnable;
3198 std::optional<std::string> wdtTimeOutAction;
3199 std::optional<std::string> bootSource;
3200 std::optional<std::string> bootType;
3201 std::optional<std::string> bootEnable;
3202 std::optional<std::string> bootAutomaticRetry;
Corey Hardesty797d5da2022-04-26 17:54:52 +08003203 std::optional<uint32_t> bootAutomaticRetryAttempts;
Ed Tanous002d39b2022-05-31 08:59:27 -07003204 std::optional<bool> bootTrustedModuleRequired;
3205 std::optional<bool> ipsEnable;
3206 std::optional<uint8_t> ipsEnterUtil;
3207 std::optional<uint64_t> ipsEnterTime;
3208 std::optional<uint8_t> ipsExitUtil;
3209 std::optional<uint64_t> ipsExitTime;
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003210
Ed Tanous002d39b2022-05-31 08:59:27 -07003211 // clang-format off
Ed Tanous22d268c2022-05-19 09:39:07 -07003212 if (!json_util::readJsonPatch(
3213 req, asyncResp->res,
3214 "IndicatorLED", indicatorLed,
3215 "LocationIndicatorActive", locationIndicatorActive,
3216 "AssetTag", assetTag,
3217 "PowerRestorePolicy", powerRestorePolicy,
3218 "PowerMode", powerMode,
3219 "HostWatchdogTimer/FunctionEnabled", wdtEnable,
3220 "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
3221 "Boot/BootSourceOverrideTarget", bootSource,
3222 "Boot/BootSourceOverrideMode", bootType,
3223 "Boot/BootSourceOverrideEnabled", bootEnable,
3224 "Boot/AutomaticRetryConfig", bootAutomaticRetry,
Corey Hardesty797d5da2022-04-26 17:54:52 +08003225 "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
Ed Tanous22d268c2022-05-19 09:39:07 -07003226 "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
3227 "IdlePowerSaver/Enabled", ipsEnable,
3228 "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
3229 "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
3230 "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
3231 "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
3232 {
3233 return;
3234 }
Ed Tanous002d39b2022-05-31 08:59:27 -07003235 // clang-format on
James Feistb49ac872019-05-21 15:12:01 -07003236
Ed Tanous002d39b2022-05-31 08:59:27 -07003237 asyncResp->res.result(boost::beast::http::status::no_content);
James Feistb49ac872019-05-21 15:12:01 -07003238
Ed Tanous002d39b2022-05-31 08:59:27 -07003239 if (assetTag)
3240 {
3241 setAssetTag(asyncResp, *assetTag);
3242 }
James Feistb49ac872019-05-21 15:12:01 -07003243
Ed Tanous002d39b2022-05-31 08:59:27 -07003244 if (wdtEnable || wdtTimeOutAction)
3245 {
3246 setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction);
3247 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003248
Ed Tanous002d39b2022-05-31 08:59:27 -07003249 if (bootSource || bootType || bootEnable)
3250 {
3251 setBootProperties(asyncResp, bootSource, bootType, bootEnable);
3252 }
3253 if (bootAutomaticRetry)
3254 {
3255 setAutomaticRetry(asyncResp, *bootAutomaticRetry);
3256 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003257
Corey Hardesty797d5da2022-04-26 17:54:52 +08003258 if (bootAutomaticRetryAttempts)
3259 {
3260 setAutomaticRetryAttempts(asyncResp,
3261 bootAutomaticRetryAttempts.value());
3262 }
3263
Ed Tanous002d39b2022-05-31 08:59:27 -07003264 if (bootTrustedModuleRequired)
3265 {
3266 setTrustedModuleRequiredToBoot(asyncResp,
3267 *bootTrustedModuleRequired);
3268 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003269
Ed Tanous002d39b2022-05-31 08:59:27 -07003270 if (locationIndicatorActive)
3271 {
3272 setLocationIndicatorActive(asyncResp, *locationIndicatorActive);
3273 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003274
Ed Tanous002d39b2022-05-31 08:59:27 -07003275 // TODO (Gunnar): Remove IndicatorLED after enough time has
3276 // passed
3277 if (indicatorLed)
3278 {
3279 setIndicatorLedState(asyncResp, *indicatorLed);
3280 asyncResp->res.addHeader(boost::beast::http::field::warning,
3281 "299 - \"IndicatorLED is deprecated. Use "
3282 "LocationIndicatorActive instead.\"");
3283 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003284
Ed Tanous002d39b2022-05-31 08:59:27 -07003285 if (powerRestorePolicy)
3286 {
3287 setPowerRestorePolicy(asyncResp, *powerRestorePolicy);
3288 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003289
Ed Tanous002d39b2022-05-31 08:59:27 -07003290 if (powerMode)
3291 {
3292 setPowerMode(asyncResp, *powerMode);
3293 }
Chris Cain37bbf982021-09-20 10:53:09 -05003294
Ed Tanous002d39b2022-05-31 08:59:27 -07003295 if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil ||
3296 ipsExitTime)
3297 {
3298 setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime,
3299 ipsExitUtil, ipsExitTime);
3300 }
3301 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003302}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303303
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003304inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003305 crow::App& app, const crow::Request& req,
3306 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
3307{
3308 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3309 {
3310 return;
3311 }
3312 asyncResp->res.addHeader(
3313 boost::beast::http::field::link,
3314 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3315}
3316
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303317/**
3318 * SystemResetActionInfo derived class for delivering Computer Systems
3319 * ResetType AllowableValues using ResetInfo schema.
3320 */
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003321inline void requestRoutesSystemResetActionInfo(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303322{
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003323 BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/ResetActionInfo/")
3324 .privileges(redfish::privileges::headActionInfo)
3325 .methods(boost::beast::http::verb::head)(std::bind_front(
3326 handleSystemCollectionResetActionHead, std::ref(app)));
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303327 /**
3328 * Functions triggers appropriate requests on DBus
3329 */
Ed Tanous22d268c2022-05-19 09:39:07 -07003330 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003331 .privileges(redfish::privileges::getActionInfo)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003332 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -07003333 [&app](const crow::Request& req,
Ed Tanous22d268c2022-05-19 09:39:07 -07003334 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3335 const std::string& systemName) {
Carson Labrado3ba00072022-06-06 19:40:56 +00003336 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -07003337 {
3338 return;
3339 }
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -06003340
3341 if (systemName == "hypervisor")
3342 {
3343 handleHypervisorResetActionGet(asyncResp);
3344 return;
3345 }
3346
Ed Tanous22d268c2022-05-19 09:39:07 -07003347 if (systemName != "system")
3348 {
3349 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3350 systemName);
3351 return;
3352 }
3353
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003354 asyncResp->res.addHeader(
3355 boost::beast::http::field::link,
3356 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
Ed Tanous14766872022-03-15 10:44:42 -07003357
Ed Tanous002d39b2022-05-31 08:59:27 -07003358 asyncResp->res.jsonValue["@odata.id"] =
3359 "/redfish/v1/Systems/system/ResetActionInfo";
3360 asyncResp->res.jsonValue["@odata.type"] =
3361 "#ActionInfo.v1_1_2.ActionInfo";
3362 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3363 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
Nan Zhou3215e702022-06-01 16:55:13 +00003364
3365 nlohmann::json::array_t parameters;
3366 nlohmann::json::object_t parameter;
3367
3368 parameter["Name"] = "ResetType";
3369 parameter["Required"] = true;
3370 parameter["DataType"] = "String";
3371 nlohmann::json::array_t allowableValues;
3372 allowableValues.emplace_back("On");
3373 allowableValues.emplace_back("ForceOff");
3374 allowableValues.emplace_back("ForceOn");
3375 allowableValues.emplace_back("ForceRestart");
3376 allowableValues.emplace_back("GracefulRestart");
3377 allowableValues.emplace_back("GracefulShutdown");
3378 allowableValues.emplace_back("PowerCycle");
3379 allowableValues.emplace_back("Nmi");
3380 parameter["AllowableValues"] = std::move(allowableValues);
3381 parameters.emplace_back(std::move(parameter));
3382
3383 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
Ed Tanous002d39b2022-05-31 08:59:27 -07003384 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003385}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003386} // namespace redfish