blob: c6b6bb1408b836c58284e701ff38a338281a3fea [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02004#pragma once
5
Willy Tu13451e32023-05-24 16:08:18 -07006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070010#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070013#include "generated/enums/action_info.hpp"
Ed Tanous8d69c662023-06-21 10:29:06 -070014#include "generated/enums/computer_system.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070015#include "generated/enums/open_bmc_computer_system.hpp"
Andrew Geissler33e1f122024-02-26 21:10:16 -060016#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080017#include "http_request.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060018#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "logging.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070021#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "registries/privilege_registry.hpp"
24#include "utils/dbus_utils.hpp"
25#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050026#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080027#include "utils/sw_utils.hpp"
Oliver Brewkafc5ae942024-08-12 15:04:41 +020028#include "utils/systems_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070029#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080030
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <asm-generic/errno.h>
32
Andrew Geisslerfc903b32023-05-31 14:15:42 -040033#include <boost/asio/error.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <boost/beast/http/field.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080035#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080036#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060037#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070038#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080039#include <nlohmann/json.hpp>
40#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020041#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042
George Liu7a1dbc42022-12-07 16:03:22 +080043#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080044#include <chrono>
45#include <cstddef>
46#include <cstdint>
47#include <functional>
Andrew Geissler33e1f122024-02-26 21:10:16 -060048#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080049#include <optional>
50#include <ratio>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060051#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080052#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080053#include <tuple>
Ed Tanous20fa6a22024-05-20 18:02:58 -070054#include <utility>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060055#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020056
Ed Tanous1abe55e2018-09-05 08:30:59 -070057namespace redfish
58{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020059
Abhishek Patel5c3e9272021-06-24 10:11:33 -050060const static std::array<std::pair<std::string_view, std::string_view>, 2>
61 protocolToDBusForSystems{
62 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
63
Ninad Palsulecf0e0042023-05-18 17:18:09 -050064/*
65 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
66 *
Ed Tanousac106bf2023-06-07 09:24:59 -070067 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -050068 * @param[in] cpuPresenceState CPU present or not
69 *
70 * @return None.
71 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040072inline void modifyCpuPresenceState(
73 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuPresent)
Ninad Palsulecf0e0042023-05-18 17:18:09 -050074{
Ed Tanous62598e32023-07-17 17:06:25 -070075 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -050076
77 if (isCpuPresent)
78 {
79 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -070080 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -050081 auto* procCountPtr =
82 procCount.get_ptr<nlohmann::json::number_integer_t*>();
83 if (procCountPtr != nullptr)
84 {
85 // shouldn't be possible to be nullptr
86 *procCountPtr += 1;
87 }
88 }
89}
90
Ali Ahmed382d6472021-09-03 16:53:53 -050091inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -070092 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -050093 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
94 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -050095{
Ed Tanous62598e32023-07-17 17:06:25 -070096 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -050097
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020098 // TODO: Get Model
99
100 const uint16_t* coreCount = nullptr;
101
102 const bool success = sdbusplus::unpackPropertiesNoThrow(
103 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
104
105 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500106 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700107 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200108 return;
109 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500110
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200111 if (coreCount != nullptr)
112 {
113 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700114 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200115 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500116
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200117 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500118 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200119 coreCountJson = *coreCount;
120 }
121 else
122 {
123 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500124 }
125 }
126}
127
128/*
129 * @brief Get ProcessorSummary fields
130 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700131 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500132 * @param[in] service dbus service for Cpu Information
133 * @param[in] path dbus path for Cpu
134 *
135 * @return None.
136 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500137inline void getProcessorSummary(
138 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
139 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500140{
Ed Tanousac106bf2023-06-07 09:24:59 -0700141 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
142 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500143 if (ec3)
144 {
Ed Tanous62598e32023-07-17 17:06:25 -0700145 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500146 return;
147 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700148 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500149 };
150
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500151 // Get the Presence of CPU
Ed Tanousdeae6a72024-11-11 21:58:57 -0800152 dbus::utility::getProperty<bool>(*crow::connections::systemBus, service,
153 path, "xyz.openbmc_project.Inventory.Item",
154 "Present", std::move(getCpuPresenceState));
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500155
Ed Tanousdeae6a72024-11-11 21:58:57 -0800156 dbus::utility::getAllProperties(
157 service, path, "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700158 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800159 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800160 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400161 if (ec2)
162 {
163 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
164 messages::internalError(asyncResp->res);
165 return;
166 }
167 getProcessorProperties(asyncResp, properties);
168 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500169}
170
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500171/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500172 * @brief processMemoryProperties fields
173 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700174 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500175 * @param[in] DBUS properties for memory
176 *
177 * @return None.
178 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500179inline void processMemoryProperties(
180 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
181 const dbus::utility::DBusPropertiesMap& properties)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500182{
Ed Tanous62598e32023-07-17 17:06:25 -0700183 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500184
185 if (properties.empty())
186 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500187 return;
188 }
189
190 const size_t* memorySizeInKB = nullptr;
191
192 const bool success = sdbusplus::unpackPropertiesNoThrow(
193 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
194 memorySizeInKB);
195
196 if (!success)
197 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700198 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500199 return;
200 }
201
202 if (memorySizeInKB != nullptr)
203 {
204 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700205 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500206 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500207 if (preValue == nullptr)
208 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700209 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500210 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500211 }
212 else
213 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700214 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500215 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
216 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500217 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500218 }
219}
220
221/*
222 * @brief Get getMemorySummary fields
223 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700224 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500225 * @param[in] service dbus service for memory Information
226 * @param[in] path dbus path for memory
227 *
228 * @return None.
229 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500230inline void getMemorySummary(
231 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
232 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500233{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800234 dbus::utility::getAllProperties(
235 service, path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700236 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500237 path](const boost::system::error_code& ec2,
238 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400239 if (ec2)
240 {
241 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
242 messages::internalError(asyncResp->res);
243 return;
244 }
245 processMemoryProperties(asyncResp, properties);
246 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500247}
248
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500249inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
250 const boost::system::error_code& ec,
251 const dbus::utility::DBusPropertiesMap& properties)
252{
253 if (ec)
254 {
255 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
256 messages::internalError(asyncResp->res);
257 return;
258 }
259 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
260
261 const std::string* uUID = nullptr;
262
263 const bool success = sdbusplus::unpackPropertiesNoThrow(
264 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
265
266 if (!success)
267 {
268 messages::internalError(asyncResp->res);
269 return;
270 }
271
272 if (uUID != nullptr)
273 {
274 std::string valueStr = *uUID;
275 if (valueStr.size() == 32)
276 {
277 valueStr.insert(8, 1, '-');
278 valueStr.insert(13, 1, '-');
279 valueStr.insert(18, 1, '-');
280 valueStr.insert(23, 1, '-');
281 }
282 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
283 asyncResp->res.jsonValue["UUID"] = valueStr;
284 }
285}
286
Patrick Williams504af5a2025-02-03 14:29:03 -0500287inline void afterGetInventory(
288 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
289 const boost::system::error_code& ec,
290 const dbus::utility::DBusPropertiesMap& propertiesList)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500291{
292 if (ec)
293 {
294 // doesn't have to include this
295 // interface
296 return;
297 }
298 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
299
300 const std::string* partNumber = nullptr;
301 const std::string* serialNumber = nullptr;
302 const std::string* manufacturer = nullptr;
303 const std::string* model = nullptr;
304 const std::string* subModel = nullptr;
305
306 const bool success = sdbusplus::unpackPropertiesNoThrow(
307 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
308 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
309 "Model", model, "SubModel", subModel);
310
311 if (!success)
312 {
313 messages::internalError(asyncResp->res);
314 return;
315 }
316
317 if (partNumber != nullptr)
318 {
319 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
320 }
321
322 if (serialNumber != nullptr)
323 {
324 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
325 }
326
327 if (manufacturer != nullptr)
328 {
329 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
330 }
331
332 if (model != nullptr)
333 {
334 asyncResp->res.jsonValue["Model"] = *model;
335 }
336
337 if (subModel != nullptr)
338 {
339 asyncResp->res.jsonValue["SubModel"] = *subModel;
340 }
341
342 // Grab the bios version
343 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
344 "BiosVersion", false);
345}
346
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400347inline void afterGetAssetTag(
348 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
349 const boost::system::error_code& ec, const std::string& value)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500350{
351 if (ec)
352 {
353 // doesn't have to include this
354 // interface
355 return;
356 }
357
358 asyncResp->res.jsonValue["AssetTag"] = value;
359}
360
361inline void afterSystemGetSubTree(
362 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500363 const boost::system::error_code& ec,
364 const dbus::utility::MapperGetSubTreeResponse& subtree)
365{
366 if (ec)
367 {
368 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
369 messages::internalError(asyncResp->res);
370 return;
371 }
372 // Iterate over all retrieved ObjectPaths.
373 for (const std::pair<
374 std::string,
375 std::vector<std::pair<std::string, std::vector<std::string>>>>&
376 object : subtree)
377 {
378 const std::string& path = object.first;
379 BMCWEB_LOG_DEBUG("Got path: {}", path);
380 const std::vector<std::pair<std::string, std::vector<std::string>>>&
381 connectionNames = object.second;
382 if (connectionNames.empty())
383 {
384 continue;
385 }
386
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500387 // This is not system, so check if it's cpu, dimm, UUID or
388 // BiosVer
389 for (const auto& connection : connectionNames)
390 {
391 for (const auto& interfaceName : connection.second)
392 {
393 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
394 {
395 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
396
397 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500398 }
399 else if (interfaceName ==
400 "xyz.openbmc_project.Inventory.Item.Cpu")
401 {
402 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
403
404 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500405 }
406 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
407 {
408 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
409
Ed Tanousdeae6a72024-11-11 21:58:57 -0800410 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500411 *crow::connections::systemBus, connection.first, path,
412 "xyz.openbmc_project.Common.UUID",
413 [asyncResp](const boost::system::error_code& ec3,
414 const dbus::utility::DBusPropertiesMap&
415 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400416 afterGetUUID(asyncResp, ec3, properties);
417 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500418 }
419 else if (interfaceName ==
420 "xyz.openbmc_project.Inventory.Item.System")
421 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800422 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500423 *crow::connections::systemBus, connection.first, path,
424 "xyz.openbmc_project.Inventory.Decorator.Asset",
425 [asyncResp](const boost::system::error_code& ec3,
426 const dbus::utility::DBusPropertiesMap&
427 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400428 afterGetInventory(asyncResp, ec3, properties);
429 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500430
Ed Tanousdeae6a72024-11-11 21:58:57 -0800431 dbus::utility::getProperty<std::string>(
432 connection.first, path,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500433 "xyz.openbmc_project.Inventory.Decorator."
434 "AssetTag",
435 "AssetTag",
436 std::bind_front(afterGetAssetTag, asyncResp));
437 }
438 }
439 }
440 }
441}
442
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500443/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700444 * @brief Retrieves computer system properties over dbus
445 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700446 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700447 *
448 * @return None.
449 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500450inline void getComputerSystem(
451 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700452{
Ed Tanous62598e32023-07-17 17:06:25 -0700453 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800454 constexpr std::array<std::string_view, 5> interfaces = {
455 "xyz.openbmc_project.Inventory.Decorator.Asset",
456 "xyz.openbmc_project.Inventory.Item.Cpu",
457 "xyz.openbmc_project.Inventory.Item.Dimm",
458 "xyz.openbmc_project.Inventory.Item.System",
459 "xyz.openbmc_project.Common.UUID",
460 };
461 dbus::utility::getSubTree(
462 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500463 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700464}
465
466/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700467 * @brief Retrieves host state properties over dbus
468 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700469 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200470 * @param[in] computerSystemIndex Index associated with the requested system
Ed Tanous6c34de42018-08-29 13:37:36 -0700471 *
472 * @return None.
473 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200474inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
475 const uint64_t computerSystemIndex)
Ed Tanous6c34de42018-08-29 13:37:36 -0700476{
Ed Tanous62598e32023-07-17 17:06:25 -0700477 BMCWEB_LOG_DEBUG("Get host information.");
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200478
Ed Tanousdeae6a72024-11-11 21:58:57 -0800479 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200480 getHostStateServiceName(computerSystemIndex),
481 getHostStateObjectPath(computerSystemIndex),
Ed Tanousdeae6a72024-11-11 21:58:57 -0800482 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700483 [asyncResp](const boost::system::error_code& ec,
484 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400485 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700486 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400487 if (ec == boost::system::errc::host_unreachable)
488 {
489 // Service not available, no error, just don't return
490 // host state info
491 BMCWEB_LOG_DEBUG("Service not available {}", ec);
492 return;
493 }
494 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
495 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700496 return;
497 }
Ed Tanous66173382018-08-15 18:20:59 -0700498
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400499 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
500 // Verify Host State
501 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
502 {
503 asyncResp->res.jsonValue["PowerState"] =
504 resource::PowerState::On;
505 asyncResp->res.jsonValue["Status"]["State"] =
506 resource::State::Enabled;
507 }
508 else if (hostState ==
509 "xyz.openbmc_project.State.Host.HostState.Quiesced")
510 {
511 asyncResp->res.jsonValue["PowerState"] =
512 resource::PowerState::On;
513 asyncResp->res.jsonValue["Status"]["State"] =
514 resource::State::Quiesced;
515 }
516 else if (hostState ==
517 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
518 {
519 asyncResp->res.jsonValue["PowerState"] =
520 resource::PowerState::On;
521 asyncResp->res.jsonValue["Status"]["State"] =
522 resource::State::InTest;
523 }
524 else if (
525 hostState ==
526 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
527 {
528 asyncResp->res.jsonValue["PowerState"] =
529 resource::PowerState::PoweringOn;
530 asyncResp->res.jsonValue["Status"]["State"] =
531 resource::State::Starting;
532 }
533 else if (
534 hostState ==
535 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
536 {
537 asyncResp->res.jsonValue["PowerState"] =
538 resource::PowerState::PoweringOff;
539 asyncResp->res.jsonValue["Status"]["State"] =
540 resource::State::Disabled;
541 }
542 else
543 {
544 asyncResp->res.jsonValue["PowerState"] =
545 resource::PowerState::Off;
546 asyncResp->res.jsonValue["Status"]["State"] =
547 resource::State::Disabled;
548 }
549 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700550}
551
552/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500553 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530554 *
555 * @param[in] dbusSource The boot source in DBUS speak.
556 *
557 * @return Returns as a string, the boot source in Redfish terms. If translation
558 * cannot be done, returns an empty string.
559 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000560inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530561{
562 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
563 {
564 return "None";
565 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700566 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530567 {
568 return "Hdd";
569 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700570 if (dbusSource ==
571 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530572 {
573 return "Cd";
574 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700575 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530576 {
577 return "Pxe";
578 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700579 if (dbusSource ==
580 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700581 {
582 return "Usb";
583 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700584 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530585}
586
587/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300588 * @brief Translates boot type DBUS property value to redfish.
589 *
590 * @param[in] dbusType The boot type in DBUS speak.
591 *
592 * @return Returns as a string, the boot type in Redfish terms. If translation
593 * cannot be done, returns an empty string.
594 */
595inline std::string dbusToRfBootType(const std::string& dbusType)
596{
597 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
598 {
599 return "Legacy";
600 }
601 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
602 {
603 return "UEFI";
604 }
605 return "";
606}
607
608/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500609 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530610 *
611 * @param[in] dbusMode The boot mode in DBUS speak.
612 *
613 * @return Returns as a string, the boot mode in Redfish terms. If translation
614 * cannot be done, returns an empty string.
615 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000616inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530617{
618 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
619 {
620 return "None";
621 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700622 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530623 {
624 return "Diags";
625 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700626 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530627 {
628 return "BiosSetup";
629 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700630 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530631}
632
633/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600634 * @brief Translates boot progress DBUS property value to redfish.
635 *
636 * @param[in] dbusBootProgress The boot progress in DBUS speak.
637 *
638 * @return Returns as a string, the boot progress in Redfish terms. If
639 * translation cannot be done, returns "None".
640 */
641inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
642{
643 // Now convert the D-Bus BootProgress to the appropriate Redfish
644 // enum
645 std::string rfBpLastState = "None";
646 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
647 "ProgressStages.Unspecified")
648 {
649 rfBpLastState = "None";
650 }
651 else if (dbusBootProgress ==
652 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
653 "PrimaryProcInit")
654 {
655 rfBpLastState = "PrimaryProcessorInitializationStarted";
656 }
657 else if (dbusBootProgress ==
658 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
659 "BusInit")
660 {
661 rfBpLastState = "BusInitializationStarted";
662 }
663 else if (dbusBootProgress ==
664 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
665 "MemoryInit")
666 {
667 rfBpLastState = "MemoryInitializationStarted";
668 }
669 else if (dbusBootProgress ==
670 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
671 "SecondaryProcInit")
672 {
673 rfBpLastState = "SecondaryProcessorInitializationStarted";
674 }
675 else if (dbusBootProgress ==
676 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
677 "PCIInit")
678 {
679 rfBpLastState = "PCIResourceConfigStarted";
680 }
681 else if (dbusBootProgress ==
682 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
683 "SystemSetup")
684 {
685 rfBpLastState = "SetupEntered";
686 }
687 else if (dbusBootProgress ==
688 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
689 "SystemInitComplete")
690 {
691 rfBpLastState = "SystemHardwareInitializationComplete";
692 }
693 else if (dbusBootProgress ==
694 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
695 "OSStart")
696 {
697 rfBpLastState = "OSBootStarted";
698 }
699 else if (dbusBootProgress ==
700 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
701 "OSRunning")
702 {
703 rfBpLastState = "OSRunning";
704 }
705 else
706 {
Ed Tanous62598e32023-07-17 17:06:25 -0700707 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600708 // Just return the default
709 }
710 return rfBpLastState;
711}
712
713/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500714 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530715 *
716 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700717 * @param[out] bootSource The DBus source
718 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530719 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700720 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530721 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400722inline int assignBootParameters(
723 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
724 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530725{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300726 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
727 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700728
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530729 if (rfSource == "None")
730 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700731 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530732 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700733 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530734 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700735 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
736 }
737 else if (rfSource == "Hdd")
738 {
739 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
740 }
741 else if (rfSource == "Diags")
742 {
743 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
744 }
745 else if (rfSource == "Cd")
746 {
747 bootSource =
748 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
749 }
750 else if (rfSource == "BiosSetup")
751 {
752 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530753 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700754 else if (rfSource == "Usb")
755 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700756 bootSource =
757 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700758 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530759 else
760 {
Ed Tanous62598e32023-07-17 17:06:25 -0700761 BMCWEB_LOG_DEBUG(
762 "Invalid property value for BootSourceOverrideTarget: {}",
763 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700764 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700765 "BootSourceTargetOverride");
766 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530767 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700768 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530769}
Ali Ahmed19817712021-06-29 17:01:52 -0500770
Andrew Geissler978b8802020-11-19 13:36:40 -0600771/**
772 * @brief Retrieves boot progress of the system
773 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700774 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200775 * @param[in] computerSystemIndex Index associated with the requested system
Andrew Geissler978b8802020-11-19 13:36:40 -0600776 *
777 * @return None.
778 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200779inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
780 const uint64_t computerSystemIndex)
Andrew Geissler978b8802020-11-19 13:36:40 -0600781{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800782 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200783 getHostStateServiceName(computerSystemIndex),
784 getHostStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700785 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700786 [asyncResp](const boost::system::error_code& ec,
787 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400788 if (ec)
789 {
790 // BootProgress is an optional object so just do nothing if
791 // not found
792 return;
793 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600794
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400795 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600796
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400797 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
798 dbusToRfBootProgress(bootProgressStr);
799 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600800}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530801
802/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000803 * @brief Retrieves boot progress Last Update of the system
804 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700805 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200806 * @param[in] computerSystemIndex Index associated with the requested system
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000807 *
808 * @return None.
809 */
810inline void getBootProgressLastStateTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200811 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
812 const uint64_t computerSystemIndex)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000813{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800814 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200815 getHostStateServiceName(computerSystemIndex),
816 getHostStateObjectPath(computerSystemIndex),
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000817 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700818 [asyncResp](const boost::system::error_code& ec,
819 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400820 if (ec)
821 {
822 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
823 return;
824 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000825
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400826 // BootProgressLastUpdate is the last time the BootProgress property
827 // was updated. The time is the Epoch time, number of microseconds
828 // since 1 Jan 1970 00::00::00 UTC."
829 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
830 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000831
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400832 // Convert to ISO 8601 standard
833 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
834 redfish::time_utils::getDateTimeUintUs(lastStateTime);
835 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000836}
837
838/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300839 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300840 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700841 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200842 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300843 *
844 * @return None.
845 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500846inline void getBootOverrideType(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200847 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
848 const uint64_t computerSystemIndex)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300849{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200850 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
851 std::to_string(computerSystemIndex));
852 path /= "boot";
853
Ed Tanousdeae6a72024-11-11 21:58:57 -0800854 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200855 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700856 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700857 [asyncResp](const boost::system::error_code& ec,
858 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400859 if (ec)
860 {
861 // not an error, don't have to have the interface
862 return;
863 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300864
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400865 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400867 asyncResp->res
868 .jsonValue["Boot"]
869 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
870 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300871
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400872 auto rfType = dbusToRfBootType(bootType);
873 if (rfType.empty())
874 {
875 messages::internalError(asyncResp->res);
876 return;
877 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300878
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400879 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
880 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300881}
882
883/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300884 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530885 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700886 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200887 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530888 *
889 * @return None.
890 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500891inline void getBootOverrideMode(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200892 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
893 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530894{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200895 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
896 std::to_string(computerSystemIndex));
897 path /= "boot";
Ed Tanousdeae6a72024-11-11 21:58:57 -0800898 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200899 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700900 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700901 [asyncResp](const boost::system::error_code& ec,
902 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400903 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530904 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400905 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
906 messages::internalError(asyncResp->res);
907 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530908 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400909
910 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
911
912 nlohmann::json::array_t allowed;
913 allowed.emplace_back("None");
914 allowed.emplace_back("Pxe");
915 allowed.emplace_back("Hdd");
916 allowed.emplace_back("Cd");
917 allowed.emplace_back("Diags");
918 allowed.emplace_back("BiosSetup");
919 allowed.emplace_back("Usb");
920
921 asyncResp->res
922 .jsonValue["Boot"]
923 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
924 std::move(allowed);
925 if (bootModeStr !=
926 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
927 {
928 auto rfMode = dbusToRfBootMode(bootModeStr);
929 if (!rfMode.empty())
930 {
931 asyncResp->res
932 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
933 }
934 }
935 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530936}
937
938/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300939 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530940 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700941 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200942 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530943 *
944 * @return None.
945 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500946inline void getBootOverrideSource(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200947 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
948 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530949{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200950 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
951 std::to_string(computerSystemIndex));
952 path /= "boot";
953
Ed Tanousdeae6a72024-11-11 21:58:57 -0800954 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200955 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700956 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200957 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
958 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400959 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +0000960 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800961 // Service not available, no error, just don't return
962 // Boot Override Source information
963 if (ec.value() != EBADR &&
964 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400965 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800966 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
967 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400968 }
Nan Zhou5ef735c2022-06-22 05:24:21 +0000969 return;
970 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530971
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400972 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530973
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400974 auto rfSource = dbusToRfBootSource(bootSourceStr);
975 if (!rfSource.empty())
976 {
977 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
978 rfSource;
979 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300980
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400981 // Get BootMode as BootSourceOverrideTarget is constructed
982 // from both BootSource and BootMode
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200983 getBootOverrideMode(asyncResp, computerSystemIndex);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400984 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530985}
986
987/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300988 * @brief This functions abstracts all the logic behind getting a
989 * "BootSourceOverrideEnabled" property from an overall boot override enable
990 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530991 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700992 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200993 * @param[in] computerSystemIndex Index associated with the requested system
994 * @param[in] bootOverrideEnableSetting
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530995 *
996 * @return None.
997 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530998
Ed Tanousac106bf2023-06-07 09:24:59 -0700999inline void processBootOverrideEnable(
1000 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001001 const uint64_t computerSystemIndex, const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001002{
1003 if (!bootOverrideEnableSetting)
1004 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001005 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1006 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001007 return;
1008 }
1009
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001010 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1011 std::to_string(computerSystemIndex));
1012 path /= "boot";
1013 path /= "one_time";
1014
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001015 // If boot source override is enabled, we need to check 'one_time'
1016 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001017 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001018 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001019 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001020 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001021 if (ec)
1022 {
1023 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1024 messages::internalError(asyncResp->res);
1025 return;
1026 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301027
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001028 if (oneTimeSetting)
1029 {
1030 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1031 "Once";
1032 }
1033 else
1034 {
1035 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1036 "Continuous";
1037 }
1038 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301039}
1040
1041/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001042 * @brief Retrieves boot override enable over DBUS
1043 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001044 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001045 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001046 *
1047 * @return None.
1048 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001049inline void getBootOverrideEnable(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001050 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1051 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001052{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001053 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1054 std::to_string(computerSystemIndex));
1055 path /= "boot";
1056
Ed Tanousdeae6a72024-11-11 21:58:57 -08001057 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001058 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001059 "xyz.openbmc_project.Object.Enable", "Enabled",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001060 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1061 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001062 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001063 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001064 // Service not available, no error, just don't return
1065 // Boot Override Enable information
1066 if (ec.value() != EBADR &&
1067 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001068 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001069 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1070 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001071 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001072 return;
1073 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001074
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001075 processBootOverrideEnable(asyncResp, computerSystemIndex,
1076 bootOverrideEnable);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001077 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001078}
1079
1080/**
1081 * @brief Retrieves boot source override properties
1082 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001083 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001084 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001085 *
1086 * @return None.
1087 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001088inline void getBootProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001089 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1090 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001091{
Ed Tanous62598e32023-07-17 17:06:25 -07001092 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001093
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001094 getBootOverrideSource(asyncResp, computerSystemIndex);
1095 getBootOverrideType(asyncResp, computerSystemIndex);
1096 getBootOverrideEnable(asyncResp, computerSystemIndex);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001097}
1098
1099/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001100 * @brief Retrieves the Last Reset Time
1101 *
1102 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1103 * and power off. Even though this is the "system" Redfish object look at the
1104 * chassis D-Bus interface for the LastStateChangeTime since this has the
1105 * last power operation time.
1106 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001107 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001108 *
1109 * @return None.
1110 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001111inline void getLastResetTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001112 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1113 const uint64_t computerSystemIndex)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001114{
Ed Tanous62598e32023-07-17 17:06:25 -07001115 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001116
Ed Tanousdeae6a72024-11-11 21:58:57 -08001117 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001118 getChassisStateServiceName(computerSystemIndex),
1119 getChassisStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001120 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001121 [asyncResp](const boost::system::error_code& ec,
1122 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001123 if (ec)
1124 {
1125 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1126 return;
1127 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001128
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001129 // LastStateChangeTime is epoch time, in milliseconds
1130 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1131 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001132
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001133 // Convert to ISO 8601 standard
1134 asyncResp->res.jsonValue["LastResetTime"] =
1135 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1136 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001137}
1138
1139/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001140 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1141 *
1142 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1143 * corresponding property "AttemptsLeft" that keeps track of the amount of
1144 * automatic retry attempts left are hosted in phosphor-state-manager through
1145 * dbus.
1146 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001147 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001148 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001149 *
1150 * @return None.
1151 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001152inline void getAutomaticRebootAttempts(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001153 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1154 const uint64_t computerSystemIndex)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001155{
Ed Tanous62598e32023-07-17 17:06:25 -07001156 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001157
Ed Tanousdeae6a72024-11-11 21:58:57 -08001158 dbus::utility::getAllProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001159 getHostStateServiceName(computerSystemIndex),
1160 getHostStateObjectPath(computerSystemIndex),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001161 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001162 [asyncResp{asyncResp}](
1163 const boost::system::error_code& ec,
1164 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001165 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001166 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301167 if (ec.value() != EBADR &&
1168 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001169 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301170 // Service not available, no error, just don't return
1171 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001172 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1173 messages::internalError(asyncResp->res);
1174 }
1175 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001176 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001177
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001178 const uint32_t* attemptsLeft = nullptr;
1179 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001180
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001181 const bool success = sdbusplus::unpackPropertiesNoThrow(
1182 dbus_utils::UnpackErrorPrinter(), propertiesList,
1183 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001184
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001185 if (!success)
1186 {
1187 messages::internalError(asyncResp->res);
1188 return;
1189 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001190
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001191 if (attemptsLeft != nullptr)
1192 {
1193 asyncResp->res
1194 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1195 *attemptsLeft;
1196 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001197
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001198 if (retryAttempts != nullptr)
1199 {
1200 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1201 *retryAttempts;
1202 }
1203 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001204}
1205
1206/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001207 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1208 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001209 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001210 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001211 *
1212 * @return None.
1213 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001214inline void getAutomaticRetryPolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001215 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1216 const uint64_t computerSystemIndex)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001217{
Ed Tanous62598e32023-07-17 17:06:25 -07001218 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001219
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001220 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1221 std::to_string(computerSystemIndex));
1222 path /= "auto_reboot";
1223
Ed Tanousdeae6a72024-11-11 21:58:57 -08001224 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001225 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001226 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001227 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1228 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001229 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001230 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301231 // Service not available, no error, just don't return
1232 // AutoReboot information
1233 if (ec.value() != EBADR &&
1234 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001235 {
1236 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1237 messages::internalError(asyncResp->res);
1238 }
1239 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001240 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001241
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001242 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1243 if (autoRebootEnabled)
1244 {
1245 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1246 "RetryAttempts";
1247 }
1248 else
1249 {
1250 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1251 "Disabled";
1252 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001253 getAutomaticRebootAttempts(asyncResp, computerSystemIndex);
Gunnar Mills69f35302020-05-17 16:06:31 -05001254
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001255 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1256 // and RetryAttempts. OpenBMC only supports Disabled and
1257 // RetryAttempts.
1258 nlohmann::json::array_t allowed;
1259 allowed.emplace_back("Disabled");
1260 allowed.emplace_back("RetryAttempts");
1261 asyncResp->res
1262 .jsonValue["Boot"]
1263 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1264 std::move(allowed);
1265 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001266}
1267
1268/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001269 * @brief Sets RetryAttempts
1270 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001271 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001272 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001273 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1274 *
1275 *@return None.
1276 */
1277
Ed Tanousac106bf2023-06-07 09:24:59 -07001278inline void setAutomaticRetryAttempts(
1279 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001280 const uint64_t computerSystemIndex, const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001281{
Ed Tanous62598e32023-07-17 17:06:25 -07001282 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001283
1284 setDbusProperty(asyncResp, "Boot/AutomaticRetryAttempts",
1285 getHostStateServiceName(computerSystemIndex),
1286 getHostStateObjectPath(computerSystemIndex),
1287 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1288 "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001289}
1290
Ed Tanous8d69c662023-06-21 10:29:06 -07001291inline computer_system::PowerRestorePolicyTypes
1292 redfishPowerRestorePolicyFromDbus(std::string_view value)
1293{
1294 if (value ==
1295 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1296 {
1297 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1298 }
1299 if (value ==
1300 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1301 {
1302 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1303 }
1304 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001305 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001306 {
1307 return computer_system::PowerRestorePolicyTypes::LastState;
1308 }
1309 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1310 {
1311 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1312 }
1313 return computer_system::PowerRestorePolicyTypes::Invalid;
1314}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001315/**
George Liuc6a620f2020-04-10 17:18:11 +08001316 * @brief Retrieves power restore policy over DBUS.
1317 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001318 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001319 *
1320 * @return None.
1321 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001322inline void getPowerRestorePolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001323 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1324 const uint64_t computerSystemIndex)
George Liuc6a620f2020-04-10 17:18:11 +08001325{
Ed Tanous62598e32023-07-17 17:06:25 -07001326 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001327
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001328 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1329 std::to_string(computerSystemIndex));
1330 path /= "power_restore_policy";
1331
Ed Tanousdeae6a72024-11-11 21:58:57 -08001332 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001333 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001334 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001335 [asyncResp](const boost::system::error_code& ec,
1336 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001337 if (ec)
1338 {
1339 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1340 return;
1341 }
1342 computer_system::PowerRestorePolicyTypes restore =
1343 redfishPowerRestorePolicyFromDbus(policy);
1344 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1345 {
1346 messages::internalError(asyncResp->res);
1347 return;
1348 }
George Liuc6a620f2020-04-10 17:18:11 +08001349
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001350 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1351 });
George Liuc6a620f2020-04-10 17:18:11 +08001352}
1353
1354/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001355 * @brief Stop Boot On Fault over DBUS.
1356 *
1357 * @param[in] asyncResp Shared pointer for generating response message.
1358 *
1359 * @return None.
1360 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001361inline void getStopBootOnFault(
1362 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001363{
Ed Tanous62598e32023-07-17 17:06:25 -07001364 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001365
Ed Tanousdeae6a72024-11-11 21:58:57 -08001366 dbus::utility::getProperty<bool>(
1367 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001368 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1369 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001370 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001371 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301372 // Service not available, no error, just don't return
1373 // StopBootOnFault information
1374 if (ec.value() != EBADR ||
1375 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001376 {
1377 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1378 messages::internalError(asyncResp->res);
1379 }
1380 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001381 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001382
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001383 if (value)
1384 {
1385 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1386 computer_system::StopBootOnFault::AnyFault;
1387 }
1388 else
1389 {
1390 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1391 computer_system::StopBootOnFault::Never;
1392 }
1393 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001394}
1395
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001396inline void getTrustedModuleRequiredToBootCallback(
1397 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1398 const uint64_t computerSystemIndex, const boost::system::error_code& ec,
1399 const dbus::utility::MapperGetSubTreeResponse& subtree)
1400{
1401 if (ec)
1402 {
1403 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}", ec);
1404 // This is an optional D-Bus object so just return if
1405 // error occurs
1406 return;
1407 }
1408 if (subtree.empty())
1409 {
1410 // As noted above, this is an optional interface so just return
1411 // if there is no instance found
1412 return;
1413 }
1414
1415 std::string path;
1416 std::string service;
1417
1418 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1419 {
1420 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1421 subtree, path, service))
1422 {
1423 return;
1424 }
1425 }
1426 else
1427 {
1428 // Make sure the Dbus response map has a service and objectPath
1429 // field
1430 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1431 {
1432 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1433 messages::internalError(asyncResp->res);
1434 return;
1435 }
1436
1437 path = subtree[0].first;
1438 service = subtree[0].second.begin()->first;
1439 }
1440
1441 BMCWEB_LOG_DEBUG("found tpm service {}", service);
1442 BMCWEB_LOG_DEBUG("found tpm path {}", path);
1443
1444 // Valid TPM Enable object found, now reading the current value
1445 dbus::utility::getProperty<bool>(
1446 service, path, "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1447 [asyncResp](const boost::system::error_code& ec2, bool tpmRequired) {
1448 if (ec2)
1449 {
1450 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
1451 ec2);
1452 messages::internalError(asyncResp->res);
1453 return;
1454 }
1455
1456 if (tpmRequired)
1457 {
1458 asyncResp->res
1459 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1460 "Required";
1461 }
1462 else
1463 {
1464 asyncResp->res
1465 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1466 "Disabled";
1467 }
1468 });
1469}
1470
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001471/**
Ali Ahmed19817712021-06-29 17:01:52 -05001472 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1473 * TPM is required for booting the host.
1474 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001475 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001476 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed19817712021-06-29 17:01:52 -05001477 *
1478 * @return None.
1479 */
1480inline void getTrustedModuleRequiredToBoot(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001481 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1482 const uint64_t computerSystemIndex)
Ali Ahmed19817712021-06-29 17:01:52 -05001483{
Ed Tanous62598e32023-07-17 17:06:25 -07001484 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001485 constexpr std::array<std::string_view, 1> interfaces = {
1486 "xyz.openbmc_project.Control.TPM.Policy"};
1487 dbus::utility::getSubTree(
1488 "/", 0, interfaces,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001489 std::bind_front(getTrustedModuleRequiredToBootCallback, asyncResp,
1490 computerSystemIndex));
Ali Ahmed19817712021-06-29 17:01:52 -05001491}
1492
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001493inline void setTrustedModuleRequiredToBootCallback(
1494 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1495 const uint64_t computerSystemIndex, const bool tpmRequired,
1496 const boost::system::error_code& ec,
1497 const dbus::utility::MapperGetSubTreeResponse& subtree)
1498{
1499 if (ec)
1500 {
1501 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}", ec);
1502 messages::internalError(asyncResp->res);
1503 return;
1504 }
1505 if (subtree.empty())
1506 {
1507 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
1508 "TrustedModuleRequiredToBoot");
1509 return;
1510 }
1511
1512 std::string path;
1513 std::string serv;
1514
1515 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1516 {
1517 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1518 subtree, path, serv))
1519 {
1520 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1521 messages::internalError(asyncResp->res);
1522 return;
1523 }
1524 }
1525 else
1526 {
1527 // Make sure the Dbus response map has a service and objectPath
1528 // field
1529 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1530 {
1531 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1532 messages::internalError(asyncResp->res);
1533 return;
1534 }
1535
1536 path = subtree[0].first;
1537 serv = subtree[0].second.begin()->first;
1538 }
1539
1540 if (serv.empty())
1541 {
1542 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1543 messages::internalError(asyncResp->res);
1544 return;
1545 }
1546
1547 // Valid TPM Enable object found, now setting the value
1548 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv, path,
1549 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1550 tpmRequired);
1551}
1552
Ali Ahmed19817712021-06-29 17:01:52 -05001553/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001554 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1555 * TPM is required for booting the host.
1556 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001557 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001558 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001559 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1560 *
1561 * @return None.
1562 */
1563inline void setTrustedModuleRequiredToBoot(
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001564 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1565 const uint64_t computerSystemIndex, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001566{
Ed Tanous62598e32023-07-17 17:06:25 -07001567 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001568 constexpr std::array<std::string_view, 1> interfaces = {
1569 "xyz.openbmc_project.Control.TPM.Policy"};
1570 dbus::utility::getSubTree(
1571 "/", 0, interfaces,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001572 std::bind_front(setTrustedModuleRequiredToBootCallback, asyncResp,
1573 computerSystemIndex, tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001574}
1575
1576/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301577 * @brief Sets boot properties into DBUS object(s).
1578 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001579 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001580 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001581 * @param[in] bootType The boot type to set.
1582 * @return Integer error code.
1583 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001584inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001585 const uint64_t computerSystemIndex,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001586 const std::optional<std::string>& bootType)
1587{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001588 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001589
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001590 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001591 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001592 return;
1593 }
1594
1595 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001596 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001597 // Figure out which DBUS interface and property to use
1598 if (*bootType == "Legacy")
1599 {
1600 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1601 }
1602 else if (*bootType == "UEFI")
1603 {
1604 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1605 }
1606 else
1607 {
Ed Tanous62598e32023-07-17 17:06:25 -07001608 BMCWEB_LOG_DEBUG("Invalid property value for "
1609 "BootSourceOverrideMode: {}",
1610 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001611 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001612 "BootSourceOverrideMode");
1613 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001614 }
1615
1616 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001617 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001618
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001619 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1620 std::to_string(computerSystemIndex));
1621 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301622 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001623 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001624 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301625 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001626}
1627
1628/**
1629 * @brief Sets boot properties into DBUS object(s).
1630 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001631 * @param[in] asyncResp Shared pointer for generating response
1632 * message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001633 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001634 * @param[in] bootType The boot type to set.
1635 * @return Integer error code.
1636 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001637inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001638 const uint64_t computerSystemIndex,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001639 const std::optional<std::string>& bootEnable)
1640{
1641 if (!bootEnable)
1642 {
1643 return;
1644 }
1645 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001646 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001647
1648 bool bootOverrideEnable = false;
1649 bool bootOverridePersistent = false;
1650 // Figure out which DBUS interface and property to use
1651 if (*bootEnable == "Disabled")
1652 {
1653 bootOverrideEnable = false;
1654 }
1655 else if (*bootEnable == "Once")
1656 {
1657 bootOverrideEnable = true;
1658 bootOverridePersistent = false;
1659 }
1660 else if (*bootEnable == "Continuous")
1661 {
1662 bootOverrideEnable = true;
1663 bootOverridePersistent = true;
1664 }
1665 else
1666 {
Ed Tanous62598e32023-07-17 17:06:25 -07001667 BMCWEB_LOG_DEBUG(
1668 "Invalid property value for BootSourceOverrideEnabled: {}",
1669 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001670 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001671 "BootSourceOverrideEnabled");
1672 return;
1673 }
1674
1675 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001676 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001677
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001678 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1679 std::to_string(computerSystemIndex));
1680 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301681 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001682 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001683 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301684 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001685
1686 if (!bootOverrideEnable)
1687 {
1688 return;
1689 }
1690
1691 // In case boot override is enabled we need to set correct value for the
1692 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001693 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1694 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001695
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001696 path /= "one_time";
Ginu Georgee93abac2024-06-14 17:35:27 +05301697 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001698 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001699 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301700 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001701}
1702
1703/**
1704 * @brief Sets boot properties into DBUS object(s).
1705 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001706 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001707 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301708 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301709 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001710 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301711 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001712inline void setBootModeOrSource(
1713 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001714 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001715 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301716{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001717 std::string bootSourceStr;
1718 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001719
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001720 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301721 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001722 return;
1723 }
1724
1725 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001726 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001727 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001728 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1729 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001730 {
Ed Tanous62598e32023-07-17 17:06:25 -07001731 BMCWEB_LOG_DEBUG(
1732 "Invalid property value for BootSourceOverrideTarget: {}",
1733 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001734 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001735 "BootSourceTargetOverride");
1736 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001737 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301738
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001739 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001740 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1741 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001742
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001743 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1744 std::to_string(computerSystemIndex));
1745 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301746 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001747 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001748 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301749 bootSourceStr);
1750 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001751 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001752 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301753 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001754}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001755
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001756/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001757 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301758 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001759 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001760 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301761 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001762 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301763 * @param[in] bootEnable The boot override enable from incoming RF request.
1764 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001765 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301766 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001767
Patrick Williams504af5a2025-02-03 14:29:03 -05001768inline void setBootProperties(
1769 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001770 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001771 const std::optional<std::string>& bootSource,
1772 const std::optional<std::string>& bootType,
1773 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301774{
Ed Tanous62598e32023-07-17 17:06:25 -07001775 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301776
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001777 setBootModeOrSource(asyncResp, computerSystemIndex, bootSource);
1778 setBootType(asyncResp, computerSystemIndex, bootType);
1779 setBootEnable(asyncResp, computerSystemIndex, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301780}
1781
George Liuc6a620f2020-04-10 17:18:11 +08001782/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001783 * @brief Sets AssetTag
1784 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001785 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001786 * @param[in] assetTag "AssetTag" from request.
1787 *
1788 * @return None.
1789 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001790inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001791 const std::string& assetTag)
1792{
George Liue99073f2022-12-09 11:06:16 +08001793 constexpr std::array<std::string_view, 1> interfaces = {
1794 "xyz.openbmc_project.Inventory.Item.System"};
1795 dbus::utility::getSubTree(
1796 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001797 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001798 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001799 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001800 if (ec)
1801 {
1802 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1803 messages::internalError(asyncResp->res);
1804 return;
1805 }
1806 if (subtree.empty())
1807 {
1808 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1809 messages::internalError(asyncResp->res);
1810 return;
1811 }
1812 // Assume only 1 system D-Bus object
1813 // Throw an error if there is more than 1
1814 if (subtree.size() > 1)
1815 {
1816 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1817 messages::internalError(asyncResp->res);
1818 return;
1819 }
1820 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1821 {
1822 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1823 messages::internalError(asyncResp->res);
1824 return;
1825 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001826
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001827 const std::string& path = subtree[0].first;
1828 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001829
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001830 if (service.empty())
1831 {
1832 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1833 messages::internalError(asyncResp->res);
1834 return;
1835 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001836
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001837 setDbusProperty(asyncResp, "AssetTag", service, path,
1838 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1839 "AssetTag", assetTag);
1840 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001841}
1842
1843/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001844 * @brief Validate the specified stopBootOnFault is valid and return the
1845 * stopBootOnFault name associated with that string
1846 *
1847 * @param[in] stopBootOnFaultString String representing the desired
1848 * stopBootOnFault
1849 *
1850 * @return stopBootOnFault value or empty if incoming value is not valid
1851 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001852inline std::optional<bool> validstopBootOnFault(
1853 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001854{
1855 if (stopBootOnFaultString == "AnyFault")
1856 {
1857 return true;
1858 }
1859
1860 if (stopBootOnFaultString == "Never")
1861 {
1862 return false;
1863 }
1864
1865 return std::nullopt;
1866}
1867
1868/**
1869 * @brief Sets stopBootOnFault
1870 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001871 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001872 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1873 *
1874 * @return None.
1875 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001876inline void setStopBootOnFault(
1877 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1878 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001879{
Ed Tanous62598e32023-07-17 17:06:25 -07001880 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001881
1882 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1883 if (!stopBootEnabled)
1884 {
Ed Tanous62598e32023-07-17 17:06:25 -07001885 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1886 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001887 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001888 "StopBootOnFault");
1889 return;
1890 }
1891
Ginu Georgee93abac2024-06-14 17:35:27 +05301892 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1893 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001894 sdbusplus::message::object_path(
1895 "/xyz/openbmc_project/logging/settings"),
1896 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301897 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001898}
1899
1900/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001901 * @brief Sets automaticRetry (Auto Reboot)
1902 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001903 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001904 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills69f35302020-05-17 16:06:31 -05001905 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1906 *
1907 * @return None.
1908 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001909inline void setAutomaticRetry(
1910 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001911 const uint64_t computerSystemIndex, const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001912{
Ed Tanous62598e32023-07-17 17:06:25 -07001913 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001914
1915 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001916 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001917
1918 if (automaticRetryConfig == "Disabled")
1919 {
1920 autoRebootEnabled = false;
1921 }
1922 else if (automaticRetryConfig == "RetryAttempts")
1923 {
1924 autoRebootEnabled = true;
1925 }
1926 else
1927 {
Ed Tanous62598e32023-07-17 17:06:25 -07001928 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1929 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001930 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001931 "AutomaticRetryConfig");
1932 return;
1933 }
1934
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001935 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1936 std::to_string(computerSystemIndex));
1937 path /= "auto_reboot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301938 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001939 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001940 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301941 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001942}
1943
Ed Tanous8d69c662023-06-21 10:29:06 -07001944inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1945{
1946 if (policy == "AlwaysOn")
1947 {
1948 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1949 }
1950 if (policy == "AlwaysOff")
1951 {
1952 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1953 }
1954 if (policy == "LastState")
1955 {
1956 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1957 }
1958 return "";
1959}
1960
Gunnar Mills69f35302020-05-17 16:06:31 -05001961/**
George Liuc6a620f2020-04-10 17:18:11 +08001962 * @brief Sets power restore policy properties.
1963 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001964 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001965 * @param[in] computerSystemIndex Index associated with the requested system
George Liuc6a620f2020-04-10 17:18:11 +08001966 * @param[in] policy power restore policy properties from request.
1967 *
1968 * @return None.
1969 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001970inline void setPowerRestorePolicy(
1971 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001972 const uint64_t computerSystemIndex, std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001973{
Ed Tanous62598e32023-07-17 17:06:25 -07001974 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001975
Ed Tanous8d69c662023-06-21 10:29:06 -07001976 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001977
Ed Tanous8d69c662023-06-21 10:29:06 -07001978 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001979 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001980 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001981 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001982 return;
1983 }
1984
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001985 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1986 std::to_string(computerSystemIndex));
1987 path /= "power_restore_policy";
1988 setDbusProperty(asyncResp, "PowerRestorePolicy",
1989 "xyz.openbmc_project.Settings", path,
1990 "xyz.openbmc_project.Control.Power.RestorePolicy",
1991 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001992}
1993
AppaRao Pulia6349912019-10-18 17:16:08 +05301994/**
1995 * @brief Retrieves provisioning status
1996 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001997 * @param[in] asyncResp Shared pointer for completing asynchronous
1998 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301999 *
2000 * @return None.
2001 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002002inline void getProvisioningStatus(
2003 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05302004{
Ed Tanous62598e32023-07-17 17:06:25 -07002005 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002006 dbus::utility::getAllProperties(
2007 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2008 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07002009 [asyncResp](const boost::system::error_code& ec,
2010 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002011 nlohmann::json& oemPFR =
2012 asyncResp->res
2013 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
2014 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
2015 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
2016 oemPFR["@odata.type"] =
2017 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07002018
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002019 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05302020 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002021 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2022 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002023 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002024 FirmwareProvisioningStatus::NotProvisioned;
2025 return;
2026 }
2027
2028 const bool* provState = nullptr;
2029 const bool* lockState = nullptr;
2030
2031 const bool success = sdbusplus::unpackPropertiesNoThrow(
2032 dbus_utils::UnpackErrorPrinter(), propertiesList,
2033 "UfmProvisioned", provState, "UfmLocked", lockState);
2034
2035 if (!success)
2036 {
2037 messages::internalError(asyncResp->res);
2038 return;
2039 }
2040
2041 if ((provState == nullptr) || (lockState == nullptr))
2042 {
2043 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2044 messages::internalError(asyncResp->res);
2045 return;
2046 }
2047
2048 if (*provState)
2049 {
2050 if (*lockState)
2051 {
2052 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2053 FirmwareProvisioningStatus::ProvisionedAndLocked;
2054 }
2055 else
2056 {
2057 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2058 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2059 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302060 }
2061 else
2062 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002063 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002064 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302065 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002066 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302067}
AppaRao Pulia6349912019-10-18 17:16:08 +05302068
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302069/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002070 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002071 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002072 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002073 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002074 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002075 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002076inline computer_system::PowerMode translatePowerModeString(
2077 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002078{
Chris Cainb6655102024-02-01 14:35:33 -06002079 using PowerMode = computer_system::PowerMode;
2080
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002081 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002082 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002083 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002084 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002085 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002086 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002087 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002088 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002089 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002090 if (modeString ==
2091 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002092 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002093 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002094 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002095 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002096 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2097 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002098 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002099 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002100 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002101 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2102 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002103 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002104 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002105 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002106 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2107 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002108 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002109 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002110 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002111 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002112 return PowerMode::OEM;
2113 }
2114 // Any other values would be invalid
2115 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2116 return PowerMode::Invalid;
2117}
2118
Patrick Williams504af5a2025-02-03 14:29:03 -05002119inline void afterGetPowerMode(
2120 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2121 const boost::system::error_code& ec,
2122 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002123{
2124 if (ec)
2125 {
2126 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2127 messages::internalError(asyncResp->res);
2128 return;
2129 }
2130
2131 std::string powerMode;
2132 const std::vector<std::string>* allowedModes = nullptr;
2133 const bool success = sdbusplus::unpackPropertiesNoThrow(
2134 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2135 "AllowedPowerModes", allowedModes);
2136
2137 if (!success)
2138 {
2139 messages::internalError(asyncResp->res);
2140 return;
2141 }
2142
2143 nlohmann::json::array_t modeList;
2144 if (allowedModes == nullptr)
2145 {
2146 modeList.emplace_back("Static");
2147 modeList.emplace_back("MaximumPerformance");
2148 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002149 }
2150 else
2151 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002152 for (const auto& aMode : *allowedModes)
2153 {
2154 computer_system::PowerMode modeValue =
2155 translatePowerModeString(aMode);
2156 if (modeValue == computer_system::PowerMode::Invalid)
2157 {
2158 messages::internalError(asyncResp->res);
2159 continue;
2160 }
2161 modeList.emplace_back(modeValue);
2162 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002163 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002164 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002165
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002166 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2167 const computer_system::PowerMode modeValue =
2168 translatePowerModeString(powerMode);
2169 if (modeValue == computer_system::PowerMode::Invalid)
2170 {
2171 messages::internalError(asyncResp->res);
2172 return;
2173 }
2174 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2175}
Chris Cain3a2d04242021-05-28 16:57:10 -05002176/**
2177 * @brief Retrieves system power mode
2178 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002179 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002180 *
2181 * @return None.
2182 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002183inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002184{
Ed Tanous62598e32023-07-17 17:06:25 -07002185 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002186
2187 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002188 constexpr std::array<std::string_view, 1> interfaces = {
2189 "xyz.openbmc_project.Control.Power.Mode"};
2190 dbus::utility::getSubTree(
2191 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002192 [asyncResp](const boost::system::error_code& ec,
2193 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002194 if (ec)
2195 {
2196 BMCWEB_LOG_DEBUG(
2197 "DBUS response error on Power.Mode GetSubTree {}", ec);
2198 // This is an optional D-Bus object so just return if
2199 // error occurs
2200 return;
2201 }
2202 if (subtree.empty())
2203 {
2204 // As noted above, this is an optional interface so just return
2205 // if there is no instance found
2206 return;
2207 }
2208 if (subtree.size() > 1)
2209 {
2210 // More then one PowerMode object is not supported and is an
2211 // error
2212 BMCWEB_LOG_DEBUG(
2213 "Found more than 1 system D-Bus Power.Mode objects: {}",
2214 subtree.size());
2215 messages::internalError(asyncResp->res);
2216 return;
2217 }
2218 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2219 {
2220 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2221 messages::internalError(asyncResp->res);
2222 return;
2223 }
2224 const std::string& path = subtree[0].first;
2225 const std::string& service = subtree[0].second.begin()->first;
2226 if (service.empty())
2227 {
2228 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2229 messages::internalError(asyncResp->res);
2230 return;
2231 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002232
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002233 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002234 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002235 *crow::connections::systemBus, service, path,
2236 "xyz.openbmc_project.Control.Power.Mode",
2237 [asyncResp](
2238 const boost::system::error_code& ec2,
2239 const dbus::utility::DBusPropertiesMap& properties) {
2240 afterGetPowerMode(asyncResp, ec2, properties);
2241 });
George Liue99073f2022-12-09 11:06:16 +08002242 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002243}
2244
2245/**
2246 * @brief Validate the specified mode is valid and return the PowerMode
2247 * name associated with that string
2248 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002249 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002250 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002251 *
2252 * @return PowerMode value or empty string if mode is not valid
2253 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002254inline std::string validatePowerMode(
2255 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2256 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002257{
Chris Cainb6655102024-02-01 14:35:33 -06002258 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002259 std::string mode;
2260
Chris Cainb6655102024-02-01 14:35:33 -06002261 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002262 {
2263 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2264 }
Chris Cainb6655102024-02-01 14:35:33 -06002265 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002266 {
George Liu0fda0f12021-11-16 10:06:17 +08002267 mode =
2268 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002269 }
Chris Cainb6655102024-02-01 14:35:33 -06002270 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002271 {
2272 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2273 }
Chris Cainb6655102024-02-01 14:35:33 -06002274 else if (modeValue == PowerMode::BalancedPerformance)
2275 {
2276 mode =
2277 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2278 }
2279 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2280 {
2281 mode =
2282 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2283 }
2284 else if (modeValue == PowerMode::EfficiencyFavorPower)
2285 {
2286 mode =
2287 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2288 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002289 else
2290 {
Chris Cainb6655102024-02-01 14:35:33 -06002291 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002292 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002293 }
2294 return mode;
2295}
2296
2297/**
2298 * @brief Sets system power mode.
2299 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002300 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002301 * @param[in] pmode System power mode from request.
2302 *
2303 * @return None.
2304 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002305inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002306 const std::string& pmode)
2307{
Ed Tanous62598e32023-07-17 17:06:25 -07002308 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002309
Ed Tanousac106bf2023-06-07 09:24:59 -07002310 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002311 if (powerMode.empty())
2312 {
2313 return;
2314 }
2315
2316 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002317 constexpr std::array<std::string_view, 1> interfaces = {
2318 "xyz.openbmc_project.Control.Power.Mode"};
2319 dbus::utility::getSubTree(
2320 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002321 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002322 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002323 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002324 if (ec)
2325 {
2326 BMCWEB_LOG_ERROR(
2327 "DBUS response error on Power.Mode GetSubTree {}", ec);
2328 // This is an optional D-Bus object, but user attempted to patch
2329 messages::internalError(asyncResp->res);
2330 return;
2331 }
2332 if (subtree.empty())
2333 {
2334 // This is an optional D-Bus object, but user attempted to patch
2335 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2336 "PowerMode");
2337 return;
2338 }
2339 if (subtree.size() > 1)
2340 {
2341 // More then one PowerMode object is not supported and is an
2342 // error
2343 BMCWEB_LOG_DEBUG(
2344 "Found more than 1 system D-Bus Power.Mode objects: {}",
2345 subtree.size());
2346 messages::internalError(asyncResp->res);
2347 return;
2348 }
2349 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2350 {
2351 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2352 messages::internalError(asyncResp->res);
2353 return;
2354 }
2355 const std::string& path = subtree[0].first;
2356 const std::string& service = subtree[0].second.begin()->first;
2357 if (service.empty())
2358 {
2359 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2360 messages::internalError(asyncResp->res);
2361 return;
2362 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002363
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002364 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002365
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002366 // Set the Power Mode property
2367 setDbusProperty(asyncResp, "PowerMode", service, path,
2368 "xyz.openbmc_project.Control.Power.Mode",
2369 "PowerMode", powerMode);
2370 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002371}
2372
2373/**
Yong Li51709ff2019-09-30 14:13:04 +08002374 * @brief Translates watchdog timeout action DBUS property value to redfish.
2375 *
2376 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2377 *
2378 * @return Returns as a string, the timeout action in Redfish terms. If
2379 * translation cannot be done, returns an empty string.
2380 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002381inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002382{
2383 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2384 {
2385 return "None";
2386 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002387 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002388 {
2389 return "ResetSystem";
2390 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002391 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002392 {
2393 return "PowerDown";
2394 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002395 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002396 {
2397 return "PowerCycle";
2398 }
2399
2400 return "";
2401}
2402
2403/**
Yong Lic45f0082019-10-10 14:19:01 +08002404 *@brief Translates timeout action from Redfish to DBUS property value.
2405 *
2406 *@param[in] rfAction The timeout action in Redfish.
2407 *
2408 *@return Returns as a string, the time_out action as expected by DBUS.
2409 *If translation cannot be done, returns an empty string.
2410 */
2411
Ed Tanous23a21a12020-07-25 04:45:05 +00002412inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002413{
2414 if (rfAction == "None")
2415 {
2416 return "xyz.openbmc_project.State.Watchdog.Action.None";
2417 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002418 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002419 {
2420 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2421 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002422 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002423 {
2424 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2425 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002426 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002427 {
2428 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2429 }
2430
2431 return "";
2432}
2433
2434/**
Yong Li51709ff2019-09-30 14:13:04 +08002435 * @brief Retrieves host watchdog timer properties over DBUS
2436 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002437 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002438 *
2439 * @return None.
2440 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002441inline void getHostWatchdogTimer(
2442 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002443{
Ed Tanous62598e32023-07-17 17:06:25 -07002444 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002445 dbus::utility::getAllProperties(
2446 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002447 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002448 [asyncResp](const boost::system::error_code& ec,
2449 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002450 if (ec)
2451 {
2452 // watchdog service is stopped
2453 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2454 return;
2455 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002456
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002457 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002458
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002459 nlohmann::json& hostWatchdogTimer =
2460 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002461
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002462 // watchdog service is running/enabled
2463 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002464
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002465 const bool* enabled = nullptr;
2466 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002467
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002468 const bool success = sdbusplus::unpackPropertiesNoThrow(
2469 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2470 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002471
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002472 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002473 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002474 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002475 return;
2476 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002477
2478 if (enabled != nullptr)
2479 {
2480 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2481 }
2482
2483 if (expireAction != nullptr)
2484 {
2485 std::string action = dbusToRfWatchdogAction(*expireAction);
2486 if (action.empty())
2487 {
2488 messages::internalError(asyncResp->res);
2489 return;
2490 }
2491 hostWatchdogTimer["TimeoutAction"] = action;
2492 }
2493 });
Yong Li51709ff2019-09-30 14:13:04 +08002494}
2495
2496/**
Yong Lic45f0082019-10-10 14:19:01 +08002497 * @brief Sets Host WatchDog Timer properties.
2498 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002499 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002500 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2501 * RF request.
2502 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2503 *
2504 * @return None.
2505 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002506inline void setWDTProperties(
2507 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2508 const std::optional<bool> wdtEnable,
2509 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002510{
Ed Tanous62598e32023-07-17 17:06:25 -07002511 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002512
2513 if (wdtTimeOutAction)
2514 {
2515 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2516 // check if TimeOut Action is Valid
2517 if (wdtTimeOutActStr.empty())
2518 {
Ed Tanous62598e32023-07-17 17:06:25 -07002519 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2520 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002521 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002522 "TimeoutAction");
2523 return;
2524 }
2525
Ginu Georgee93abac2024-06-14 17:35:27 +05302526 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2527 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002528 sdbusplus::message::object_path(
2529 "/xyz/openbmc_project/watchdog/host0"),
2530 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302531 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002532 }
2533
2534 if (wdtEnable)
2535 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302536 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2537 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002538 sdbusplus::message::object_path(
2539 "/xyz/openbmc_project/watchdog/host0"),
2540 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302541 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002542 }
2543}
2544
Chris Cain37bbf982021-09-20 10:53:09 -05002545/**
2546 * @brief Parse the Idle Power Saver properties into json
2547 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002548 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002549 * @param[in] properties IPS property data from DBus.
2550 *
2551 * @return true if successful
2552 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002553inline bool parseIpsProperties(
2554 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2555 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002556{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002557 const bool* enabled = nullptr;
2558 const uint8_t* enterUtilizationPercent = nullptr;
2559 const uint64_t* enterDwellTime = nullptr;
2560 const uint8_t* exitUtilizationPercent = nullptr;
2561 const uint64_t* exitDwellTime = nullptr;
2562
2563 const bool success = sdbusplus::unpackPropertiesNoThrow(
2564 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002565 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2566 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2567 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002568
2569 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002570 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002571 return false;
2572 }
2573
2574 if (enabled != nullptr)
2575 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002576 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002577 }
2578
2579 if (enterUtilizationPercent != nullptr)
2580 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002581 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002582 *enterUtilizationPercent;
2583 }
2584
2585 if (enterDwellTime != nullptr)
2586 {
2587 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002588 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002589 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2590 .count();
2591 }
2592
2593 if (exitUtilizationPercent != nullptr)
2594 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002595 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002596 *exitUtilizationPercent;
2597 }
2598
2599 if (exitDwellTime != nullptr)
2600 {
2601 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002602 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002603 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2604 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002605 }
2606
2607 return true;
2608}
2609
2610/**
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002611 * @brief Retrieves idle power saver properties over DBUS
Chris Cain37bbf982021-09-20 10:53:09 -05002612 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002613 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002614 *
2615 * @return None.
2616 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002617inline void getIdlePowerSaver(
2618 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002619{
Ed Tanous62598e32023-07-17 17:06:25 -07002620 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002621
2622 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002623 constexpr std::array<std::string_view, 1> interfaces = {
2624 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2625 dbus::utility::getSubTree(
2626 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002627 [asyncResp](const boost::system::error_code& ec,
2628 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002629 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002630 {
Ed Tanous62598e32023-07-17 17:06:25 -07002631 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002632 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2633 ec);
2634 messages::internalError(asyncResp->res);
2635 return;
2636 }
2637 if (subtree.empty())
2638 {
2639 // This is an optional interface so just return
2640 // if there is no instance found
2641 BMCWEB_LOG_DEBUG("No instances found");
2642 return;
2643 }
2644 if (subtree.size() > 1)
2645 {
2646 // More then one PowerIdlePowerSaver object is not supported and
2647 // is an error
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002648 BMCWEB_LOG_DEBUG(
2649 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2650 subtree.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002651 messages::internalError(asyncResp->res);
2652 return;
2653 }
2654 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2655 {
2656 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2657 messages::internalError(asyncResp->res);
2658 return;
2659 }
2660 const std::string& path = subtree[0].first;
2661 const std::string& service = subtree[0].second.begin()->first;
2662 if (service.empty())
2663 {
2664 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002665 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002666 return;
2667 }
2668
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002669 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002670 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002671 *crow::connections::systemBus, service, path,
2672 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2673 [asyncResp](
2674 const boost::system::error_code& ec2,
2675 const dbus::utility::DBusPropertiesMap& properties) {
2676 if (ec2)
2677 {
2678 BMCWEB_LOG_ERROR(
2679 "DBUS response error on IdlePowerSaver GetAll: {}",
2680 ec2);
2681 messages::internalError(asyncResp->res);
2682 return;
2683 }
2684
2685 if (!parseIpsProperties(asyncResp, properties))
2686 {
2687 messages::internalError(asyncResp->res);
2688 return;
2689 }
2690 });
George Liue99073f2022-12-09 11:06:16 +08002691 });
Chris Cain37bbf982021-09-20 10:53:09 -05002692
Ed Tanous62598e32023-07-17 17:06:25 -07002693 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002694}
2695
2696/**
2697 * @brief Sets Idle Power Saver properties.
2698 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002699 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002700 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2701 * RF request.
2702 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2703 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2704 * before entering idle state.
2705 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2706 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2707 * before exiting idle state
2708 *
2709 * @return None.
2710 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002711inline void setIdlePowerSaver(
2712 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2713 const std::optional<bool> ipsEnable,
2714 const std::optional<uint8_t> ipsEnterUtil,
2715 const std::optional<uint64_t> ipsEnterTime,
2716 const std::optional<uint8_t> ipsExitUtil,
2717 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002718{
Ed Tanous62598e32023-07-17 17:06:25 -07002719 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002720
2721 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002722 constexpr std::array<std::string_view, 1> interfaces = {
2723 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2724 dbus::utility::getSubTree(
2725 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002726 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002727 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002728 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002729 if (ec)
2730 {
2731 BMCWEB_LOG_ERROR(
2732 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2733 ec);
2734 messages::internalError(asyncResp->res);
2735 return;
2736 }
2737 if (subtree.empty())
2738 {
2739 // This is an optional D-Bus object, but user attempted to patch
2740 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2741 "IdlePowerSaver");
2742 return;
2743 }
2744 if (subtree.size() > 1)
2745 {
2746 // More then one PowerIdlePowerSaver object is not supported and
2747 // is an error
2748 BMCWEB_LOG_DEBUG(
2749 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2750 subtree.size());
2751 messages::internalError(asyncResp->res);
2752 return;
2753 }
2754 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2755 {
2756 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2757 messages::internalError(asyncResp->res);
2758 return;
2759 }
2760 const std::string& path = subtree[0].first;
2761 const std::string& service = subtree[0].second.begin()->first;
2762 if (service.empty())
2763 {
2764 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2765 messages::internalError(asyncResp->res);
2766 return;
2767 }
Chris Cain37bbf982021-09-20 10:53:09 -05002768
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002769 // Valid Power IdlePowerSaver object found, now set any values that
2770 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002771
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002772 if (ipsEnable)
2773 {
2774 setDbusProperty(
2775 asyncResp, "IdlePowerSaver/Enabled", service, path,
2776 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2777 "Enabled", *ipsEnable);
2778 }
2779 if (ipsEnterUtil)
2780 {
2781 setDbusProperty(
2782 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2783 service, path,
2784 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2785 "EnterUtilizationPercent", *ipsEnterUtil);
2786 }
2787 if (ipsEnterTime)
2788 {
2789 // Convert from seconds into milliseconds for DBus
2790 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2791 setDbusProperty(
2792 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2793 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2794 "EnterDwellTime", timeMilliseconds);
2795 }
2796 if (ipsExitUtil)
2797 {
2798 setDbusProperty(
2799 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2800 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2801 "ExitUtilizationPercent", *ipsExitUtil);
2802 }
2803 if (ipsExitTime)
2804 {
2805 // Convert from seconds into milliseconds for DBus
2806 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2807 setDbusProperty(
2808 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2809 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2810 "ExitDwellTime", timeMilliseconds);
2811 }
2812 });
Chris Cain37bbf982021-09-20 10:53:09 -05002813
Ed Tanous62598e32023-07-17 17:06:25 -07002814 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002815}
2816
Ed Tanousc1e219d2023-06-07 10:34:33 -07002817inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002818 crow::App& app, const crow::Request& req,
2819 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2820{
2821 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2822 {
2823 return;
2824 }
2825 asyncResp->res.addHeader(
2826 boost::beast::http::field::link,
2827 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2828}
2829
Ed Tanousc1e219d2023-06-07 10:34:33 -07002830inline void handleComputerSystemCollectionGet(
2831 crow::App& app, const crow::Request& req,
2832 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2833{
2834 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2835 {
2836 return;
2837 }
2838
2839 asyncResp->res.addHeader(
2840 boost::beast::http::field::link,
2841 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2842 asyncResp->res.jsonValue["@odata.type"] =
2843 "#ComputerSystemCollection.ComputerSystemCollection";
2844 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2845 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2846
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002847 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002848}
2849
Yong Lic45f0082019-10-10 14:19:01 +08002850/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002851 * Function transceives data with dbus directly.
2852 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002853inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002854{
Patrick Williams89492a12023-05-10 07:51:34 -05002855 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2856 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2857 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002858 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002859 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002860
Ed Tanous177612a2025-02-14 15:16:09 -08002861 dbus::utility::async_method_call(
2862 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002863 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002864 if (ec)
2865 {
2866 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2867 messages::internalError(asyncResp->res);
2868 return;
2869 }
2870 messages::success(asyncResp->res);
2871 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002872 serviceName, objectPath, interfaceName, method);
2873}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002874
Oliver Brewka06c055e2025-07-23 16:42:24 +02002875/**
2876 * @brief process the POST request after getting the computerSystemIndex
2877 *
2878 * @param[in] asyncResp Shared pointer for completing asynchronous
2879 * calls
2880 * @param[in] resetType The requested reset action
2881 * @param[in] computerSystemIndex Index associated with the requested system
2882 *
2883 * @return None
2884 */
2885inline void processComputerSystemResetActionPost(
2886 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string& resetType,
2887 const uint64_t computerSystemIndex)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002888{
Ed Tanousc1e219d2023-06-07 10:34:33 -07002889 // Get the command and host vs. chassis
2890 std::string command;
2891 bool hostCommand = true;
2892 if ((resetType == "On") || (resetType == "ForceOn"))
2893 {
2894 command = "xyz.openbmc_project.State.Host.Transition.On";
2895 hostCommand = true;
2896 }
2897 else if (resetType == "ForceOff")
2898 {
2899 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2900 hostCommand = false;
2901 }
2902 else if (resetType == "ForceRestart")
2903 {
2904 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2905 hostCommand = true;
2906 }
2907 else if (resetType == "GracefulShutdown")
2908 {
2909 command = "xyz.openbmc_project.State.Host.Transition.Off";
2910 hostCommand = true;
2911 }
2912 else if (resetType == "GracefulRestart")
2913 {
2914 command =
2915 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2916 hostCommand = true;
2917 }
2918 else if (resetType == "PowerCycle")
2919 {
2920 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2921 hostCommand = true;
2922 }
2923 else if (resetType == "Nmi")
2924 {
2925 doNMI(asyncResp);
2926 return;
2927 }
2928 else
2929 {
2930 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2931 return;
2932 }
2933
2934 if (hostCommand)
2935 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002936 setDbusProperty(asyncResp, "Reset",
2937 getHostStateServiceName(computerSystemIndex),
2938 getHostStateObjectPath(computerSystemIndex),
2939 "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302940 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002941 }
2942 else
2943 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002944 setDbusProperty(asyncResp, "Reset",
2945 getChassisStateServiceName(computerSystemIndex),
2946 getChassisStateObjectPath(computerSystemIndex),
Ed Tanousd02aad32024-02-13 14:43:34 -08002947 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302948 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002949 }
2950}
2951
Oliver Brewka06c055e2025-07-23 16:42:24 +02002952inline void handleComputerSystemResetActionPost(
2953 crow::App& app, const crow::Request& req,
2954 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2955 const std::string& systemName)
2956{
2957 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2958 {
2959 return;
2960 }
2961
2962 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2963 {
2964 if (systemName == "hypervisor")
2965 {
2966 handleHypervisorSystemResetPost(req, asyncResp);
2967 return;
2968 }
2969 }
2970
2971 if (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2972 {
2973 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2974 {
2975 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2976 systemName);
2977 return;
2978 }
2979 }
2980
2981 std::string resetType;
2982 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2983 {
2984 return;
2985 }
2986
2987 getComputerSystemIndex(asyncResp, systemName,
2988 std::bind_front(processComputerSystemResetActionPost,
2989 asyncResp, resetType));
2990}
2991
Ed Tanousc1e219d2023-06-07 10:34:33 -07002992inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002993 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002994 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2995 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002996{
2997 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2998 {
2999 return;
3000 }
3001
3002 asyncResp->res.addHeader(
3003 boost::beast::http::field::link,
3004 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3005}
3006
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003007inline void afterPortRequest(
3008 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3009 const boost::system::error_code& ec,
3010 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3011{
3012 if (ec)
3013 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003014 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003015 messages::internalError(asyncResp->res);
3016 return;
3017 }
3018 for (const auto& data : socketData)
3019 {
3020 const std::string& socketPath = get<0>(data);
3021 const std::string& protocolName = get<1>(data);
3022 bool isProtocolEnabled = get<2>(data);
3023 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3024 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3025 // need to retrieve port number for
3026 // obmc-console-ssh service
3027 if (protocolName == "SSH")
3028 {
3029 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003030 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003031 int portNumber) {
3032 if (ec1)
3033 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003034 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003035 messages::internalError(asyncResp->res);
3036 return;
3037 }
3038 nlohmann::json& dataJson1 =
3039 asyncResp->res.jsonValue["SerialConsole"];
3040 dataJson1[protocolName]["Port"] = portNumber;
3041 });
3042 }
3043 }
3044}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003045
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003046/**
3047 * @brief process the GET request after getting the computerSystemIndex
3048 *
3049 * @param[in] asyncResp Shared pointer for completing asynchronous
3050 * calls
3051 * @param[in] systemName Name of the requested system
3052 * @param[in] computerSystemIndex Index associated with the requested system
3053 *
3054 * @return None
3055 */
3056inline void processComputerSystemGet(
Patrick Williams504af5a2025-02-03 14:29:03 -05003057 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003058 const std::string& systemName, const uint64_t computerSystemIndex)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003059{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003060 asyncResp->res.addHeader(
3061 boost::beast::http::field::link,
3062 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3063 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003064 "#ComputerSystem.v1_22_0.ComputerSystem";
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003065 asyncResp->res.jsonValue["Name"] = systemName;
3066 asyncResp->res.jsonValue["Id"] = systemName;
Ed Tanous539d8c62024-06-19 14:38:27 -07003067 asyncResp->res.jsonValue["SystemType"] =
3068 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003069 asyncResp->res.jsonValue["Description"] = "Computer System";
3070 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003071 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003072 double(0);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003073 asyncResp->res.jsonValue["@odata.id"] =
3074 boost::urls::format("/redfish/v1/Systems/{}", systemName);
Ed Tanous04a258f2018-10-15 08:00:41 -07003075
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003076 // Currently not supported on multi-host. TBD
3077 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3078 {
3079 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3080 boost::urls::format("/redfish/v1/Systems/{}/Bios", systemName);
3081 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3082 boost::urls::format("/redfish/v1/Systems/{}/Processors",
3083 systemName);
3084 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3085 boost::urls::format("/redfish/v1/Systems/{}/Memory", systemName);
3086 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3087 boost::urls::format("/redfish/v1/Systems/{}/Storage", systemName);
3088 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3089 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3090 systemName);
3091 }
Ed Tanous029573d2019-02-01 10:57:49 -08003092
Ed Tanousc1e219d2023-06-07 10:34:33 -07003093 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003094 boost::urls::format(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003095 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003096 asyncResp->res
3097 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003098 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003099 systemName);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003100
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003101 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3102 boost::urls::format("/redfish/v1/Systems/{}/LogServices", systemName);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003103
Ed Tanousc1e219d2023-06-07 10:34:33 -07003104 nlohmann::json::array_t managedBy;
3105 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003106 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3107 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003108 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003109 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3110 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003111
Ed Tanousc1e219d2023-06-07 10:34:33 -07003112 // Fill in SerialConsole info
3113 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3114 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003115
Ed Tanousc1e219d2023-06-07 10:34:33 -07003116 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3117 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3118 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3119 "Press ~. to exit console";
3120 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3121 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003122
Ed Tanous25b54db2024-04-17 15:40:31 -07003123 if constexpr (BMCWEB_KVM)
3124 {
3125 // Fill in GraphicalConsole info
3126 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3127 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3128 4;
3129 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3130 nlohmann::json::array_t({"KVMIP"});
3131 }
James Feistb49ac872019-05-21 15:12:01 -07003132
Janet Adkins2eaa9272025-04-17 10:30:43 -05003133 systems_utils::getValidSystemsPath(
3134 asyncResp, systemName,
3135 [asyncResp,
3136 systemName](const std::optional<std::string>& validSystemsPath) {
3137 if (validSystemsPath)
3138 {
3139 getLocationIndicatorActive(asyncResp, *validSystemsPath);
3140 }
3141 });
3142
Janet Adkinsf664fd82025-07-23 14:01:43 -05003143 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3144 {
3145 getIndicatorLedState(asyncResp);
3146 }
3147
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003148 // Currently not supported on multi-host.
3149 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3150 {
3151 getComputerSystem(asyncResp);
3152 // Todo: chassis matching could be handled by patch
3153 // https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60793
3154 getMainChassisId(
3155 asyncResp, [](const std::string& chassisId,
3156 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3157 nlohmann::json::array_t chassisArray;
3158 nlohmann::json& chassis = chassisArray.emplace_back();
3159 chassis["@odata.id"] =
3160 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3161 aRsp->res.jsonValue["Links"]["Chassis"] =
3162 std::move(chassisArray);
3163 });
3164
3165 pcie_util::getPCIeDeviceList(
3166 asyncResp, nlohmann::json::json_pointer("/PCIeDevices"));
3167 }
3168 getHostState(asyncResp, computerSystemIndex);
3169 getBootProperties(asyncResp, computerSystemIndex);
3170 getBootProgress(asyncResp, computerSystemIndex);
3171 getBootProgressLastStateTime(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003172 getHostWatchdogTimer(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003173 getPowerRestorePolicy(asyncResp, computerSystemIndex);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003174 getStopBootOnFault(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003175 getAutomaticRetryPolicy(asyncResp, computerSystemIndex);
3176 getLastResetTime(asyncResp, computerSystemIndex);
Ed Tanous25b54db2024-04-17 15:40:31 -07003177 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3178 {
3179 getProvisioningStatus(asyncResp);
3180 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003181 getTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003182 getPowerMode(asyncResp);
3183 getIdlePowerSaver(asyncResp);
3184}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003185
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003186inline void handleComputerSystemGet(
3187 crow::App& app, const crow::Request& req,
3188 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3189 const std::string& systemName)
3190{
3191 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3192 {
3193 return;
3194 }
3195
3196 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
3197 {
3198 if (systemName == "hypervisor")
3199 {
3200 handleHypervisorSystemGet(asyncResp);
3201 return;
3202 }
3203 }
3204
3205 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3206 {
3207 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3208 {
3209 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3210 systemName);
3211 return;
3212 }
3213 }
3214
3215 BMCWEB_LOG_DEBUG("requested system = {}", systemName);
3216 getComputerSystemIndex(
3217 asyncResp, systemName,
3218 std::bind_front(processComputerSystemGet, asyncResp, systemName));
3219}
3220
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003221struct PatchParams
Ed Tanousc1e219d2023-06-07 10:34:33 -07003222{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003223 std::optional<bool> locationIndicatorActive;
3224 std::optional<std::string> indicatorLed;
3225 std::optional<std::string> assetTag;
3226 std::optional<std::string> powerRestorePolicy;
3227 std::optional<std::string> powerMode;
3228 std::optional<bool> wdtEnable;
3229 std::optional<std::string> wdtTimeOutAction;
3230 std::optional<std::string> bootSource;
3231 std::optional<std::string> bootType;
3232 std::optional<std::string> bootEnable;
3233 std::optional<std::string> bootAutomaticRetry;
3234 std::optional<uint32_t> bootAutomaticRetryAttempts;
3235 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003236 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003237 std::optional<bool> ipsEnable;
3238 std::optional<uint8_t> ipsEnterUtil;
3239 std::optional<uint64_t> ipsEnterTime;
3240 std::optional<uint8_t> ipsExitUtil;
3241 std::optional<uint64_t> ipsExitTime;
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003242};
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003243
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003244/**
3245 * @brief process the POST request after getting the computerSystemIndex
3246 *
3247 * @param[in] asyncResp Shared pointer for completing asynchronous
3248 * calls
3249 * @param[in] patchParams Struct containing the property we want to
3250 * patch
3251 * @param[in] computerSystemIndex Index associated with the requested system
3252 *
3253 * @return None
3254 */
James Feistb49ac872019-05-21 15:12:01 -07003255
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003256inline void processComputerSystemPatch(
3257 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3258 std::string& systemName, PatchParams& patchParams,
3259 const uint64_t computerSystemIndex)
3260{
Janet Adkinsf664fd82025-07-23 14:01:43 -05003261 if constexpr (!BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3262 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003263 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003264 {
3265 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
3266 return;
3267 }
3268 }
3269
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003270 if (patchParams.assetTag)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003271 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003272 setAssetTag(asyncResp, *patchParams.assetTag);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003273 }
James Feistb49ac872019-05-21 15:12:01 -07003274
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003275 if (patchParams.wdtEnable || patchParams.wdtTimeOutAction)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003276 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003277 setWDTProperties(asyncResp, patchParams.wdtEnable,
3278 patchParams.wdtTimeOutAction);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003279 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003280
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003281 if (patchParams.bootSource || patchParams.bootType ||
3282 patchParams.bootEnable)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003283 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003284 setBootProperties(asyncResp, computerSystemIndex,
3285 patchParams.bootSource, patchParams.bootType,
3286 patchParams.bootEnable);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003287 }
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003288 if (patchParams.bootAutomaticRetry)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003289 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003290 setAutomaticRetry(asyncResp, computerSystemIndex,
3291 *patchParams.bootAutomaticRetry);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003292 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003293
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003294 if (patchParams.bootAutomaticRetryAttempts)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003295 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003296 setAutomaticRetryAttempts(
3297 asyncResp, computerSystemIndex,
3298 patchParams.bootAutomaticRetryAttempts.value());
Ed Tanousc1e219d2023-06-07 10:34:33 -07003299 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003300
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003301 if (patchParams.bootTrustedModuleRequired)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003302 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003303 setTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex,
3304 *patchParams.bootTrustedModuleRequired);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003305 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003306
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003307 if (patchParams.stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003308 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003309 setStopBootOnFault(asyncResp, *patchParams.stopBootOnFault);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003310 }
3311
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003312 if (patchParams.locationIndicatorActive)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003313 {
Janet Adkins2eaa9272025-04-17 10:30:43 -05003314 systems_utils::getValidSystemsPath(
3315 asyncResp, systemName,
3316 [asyncResp, systemName,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003317 locationIndicatorActive{*patchParams.locationIndicatorActive}](
Janet Adkins2eaa9272025-04-17 10:30:43 -05003318 const std::optional<std::string>& validSystemsPath) {
3319 if (!validSystemsPath)
3320 {
3321 messages::resourceNotFound(asyncResp->res, "Systems",
3322 systemName);
3323 return;
3324 }
3325 setLocationIndicatorActive(asyncResp, *validSystemsPath,
3326 locationIndicatorActive);
3327 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003328 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003329
Janet Adkinsf664fd82025-07-23 14:01:43 -05003330 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003331 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003332 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003333 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003334 setIndicatorLedState(asyncResp, *patchParams.indicatorLed);
Janet Adkinsf664fd82025-07-23 14:01:43 -05003335 asyncResp->res.addHeader(boost::beast::http::field::warning,
3336 "299 - \"IndicatorLED is deprecated. Use "
3337 "LocationIndicatorActive instead.\"");
3338 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003339 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003340
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003341 if (patchParams.powerRestorePolicy)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003342 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003343 setPowerRestorePolicy(asyncResp, computerSystemIndex,
3344 *patchParams.powerRestorePolicy);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003345 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003346
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003347 if (patchParams.powerMode)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003348 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003349 setPowerMode(asyncResp, *patchParams.powerMode);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003350 }
Chris Cain37bbf982021-09-20 10:53:09 -05003351
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003352 if (patchParams.ipsEnable || patchParams.ipsEnterUtil ||
3353 patchParams.ipsEnterTime || patchParams.ipsExitUtil ||
3354 patchParams.ipsExitTime)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003355 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003356 setIdlePowerSaver(asyncResp, patchParams.ipsEnable,
3357 patchParams.ipsEnterUtil, patchParams.ipsEnterTime,
3358 patchParams.ipsExitUtil, patchParams.ipsExitTime);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003359 }
3360}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303361
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003362inline void handleComputerSystemPatch(
3363 crow::App& app, const crow::Request& req,
3364 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3365 const std::string& systemName)
3366{
3367 PatchParams patchParams;
3368
3369 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3370 {
3371 return;
3372 }
3373
3374 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3375 {
3376 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3377 {
3378 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3379 systemName);
3380 return;
3381 }
3382 }
3383
3384 asyncResp->res.addHeader(
3385 boost::beast::http::field::link,
3386 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3387
3388 if (!json_util::readJsonPatch(
3389 req, asyncResp->res, //
3390 "AssetTag", patchParams.assetTag, //
3391 "Boot/AutomaticRetryAttempts",
3392 patchParams.bootAutomaticRetryAttempts, //
3393 "Boot/AutomaticRetryConfig", patchParams.bootAutomaticRetry, //
3394 "Boot/BootSourceOverrideEnabled", patchParams.bootEnable, //
3395 "Boot/BootSourceOverrideMode", patchParams.bootType, //
3396 "Boot/BootSourceOverrideTarget", patchParams.bootSource, //
3397 "Boot/StopBootOnFault", patchParams.stopBootOnFault, //
3398 "Boot/TrustedModuleRequiredToBoot",
3399 patchParams.bootTrustedModuleRequired, //
3400 "HostWatchdogTimer/FunctionEnabled", patchParams.wdtEnable, //
3401 "HostWatchdogTimer/TimeoutAction", patchParams.wdtTimeOutAction, //
3402 "IdlePowerSaver/Enabled", patchParams.ipsEnable, //
3403 "IdlePowerSaver/EnterDwellTimeSeconds", patchParams.ipsEnterTime, //
3404 "IdlePowerSaver/EnterUtilizationPercent",
3405 patchParams.ipsEnterUtil, //
3406 "IdlePowerSaver/ExitDwellTimeSeconds", patchParams.ipsExitTime, //
3407 "IdlePowerSaver/ExitUtilizationPercent", patchParams.ipsExitUtil, //
3408 "IndicatorLED", patchParams.indicatorLed, //
3409 "LocationIndicatorActive", patchParams.locationIndicatorActive, //
3410 "PowerMode", patchParams.powerMode, //
3411 "PowerRestorePolicy", patchParams.powerRestorePolicy))
3412 {
3413 return;
3414 }
3415
3416 getComputerSystemIndex(asyncResp, systemName,
3417 std::bind_front(processComputerSystemPatch,
3418 asyncResp, systemName, patchParams));
3419}
3420
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003421inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003422 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003423 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003424 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003425{
3426 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3427 {
3428 return;
3429 }
3430 asyncResp->res.addHeader(
3431 boost::beast::http::field::link,
3432 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3433}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003434
3435/**
3436 * @brief Translates allowed host transitions to redfish string
3437 *
3438 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3439 * @param[out] allowableValues The translated host transition(s)
3440 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303441 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003442 * allowableValues. If translation not possible, does nothing to
3443 * allowableValues.
3444 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003445inline void dbusToRfAllowedHostTransitions(
3446 const std::string& dbusAllowedHostTran,
3447 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003448{
3449 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3450 {
3451 allowableValues.emplace_back(resource::ResetType::On);
3452 allowableValues.emplace_back(resource::ResetType::ForceOn);
3453 }
3454 else if (dbusAllowedHostTran ==
3455 "xyz.openbmc_project.State.Host.Transition.Off")
3456 {
3457 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3458 }
3459 else if (dbusAllowedHostTran ==
3460 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3461 {
3462 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3463 }
3464 else if (dbusAllowedHostTran ==
3465 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3466 {
3467 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3468 }
3469 else
3470 {
3471 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3472 }
3473}
3474
3475inline void afterGetAllowedHostTransitions(
3476 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3477 const boost::system::error_code& ec,
3478 const std::vector<std::string>& allowedHostTransitions)
3479{
3480 nlohmann::json::array_t allowableValues;
3481
3482 // Supported on all systems currently
3483 allowableValues.emplace_back(resource::ResetType::ForceOff);
3484 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3485 allowableValues.emplace_back(resource::ResetType::Nmi);
3486
3487 if (ec)
3488 {
Ed Tanouse715d142024-03-07 15:47:37 -08003489 if ((ec.value() ==
3490 boost::system::linux_error::bad_request_descriptor) ||
3491 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003492 {
3493 // Property not implemented so just return defaults
3494 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3495 allowableValues.emplace_back(resource::ResetType::On);
3496 allowableValues.emplace_back(resource::ResetType::ForceOn);
3497 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3498 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3499 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3500 }
3501 else
3502 {
3503 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3504 messages::internalError(asyncResp->res);
3505 return;
3506 }
3507 }
3508 else
3509 {
3510 for (const std::string& transition : allowedHostTransitions)
3511 {
3512 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3513 dbusToRfAllowedHostTransitions(transition, allowableValues);
3514 }
3515 }
3516
3517 nlohmann::json::object_t parameter;
3518 parameter["Name"] = "ResetType";
3519 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003520 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003521 parameter["AllowableValues"] = std::move(allowableValues);
3522 nlohmann::json::array_t parameters;
3523 parameters.emplace_back(std::move(parameter));
3524 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3525}
3526
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003527inline void getAllowedHostTransitions(
3528 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3529 const uint64_t computerSystemIndex)
3530{
3531 dbus::utility::getProperty<std::vector<std::string>>(
3532 getHostStateServiceName(computerSystemIndex),
3533 getHostStateObjectPath(computerSystemIndex),
3534 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
3535 std::bind_front(afterGetAllowedHostTransitions, asyncResp));
3536}
3537
Ed Tanousc1e219d2023-06-07 10:34:33 -07003538inline void handleSystemCollectionResetActionGet(
3539 crow::App& app, const crow::Request& req,
3540 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3541 const std::string& systemName)
3542{
3543 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3544 {
3545 return;
3546 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003547
Gunnar Mills68896202024-08-21 11:34:20 -05003548 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003549 {
Gunnar Mills68896202024-08-21 11:34:20 -05003550 if (systemName == "hypervisor")
3551 {
3552 handleHypervisorResetActionGet(asyncResp);
3553 return;
3554 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003555 }
3556
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003557 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003558 {
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003559 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3560 {
3561 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3562 systemName);
3563 return;
3564 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003565 }
3566
3567 asyncResp->res.addHeader(
3568 boost::beast::http::field::link,
3569 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3570
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003571 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3572 "/redfish/v1/Systems/{}/ResetActionInfo", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003573 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3574 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3575 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3576
Andrew Geissler33e1f122024-02-26 21:10:16 -06003577 // Look to see if system defines AllowedHostTransitions
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003578 getComputerSystemIndex(
3579 asyncResp, systemName,
3580 std::bind_front(getAllowedHostTransitions, asyncResp));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003581}
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003582
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303583/**
3584 * SystemResetActionInfo derived class for delivering Computer Systems
3585 * ResetType AllowableValues using ResetInfo schema.
3586 */
Ed Tanous100afe52023-06-07 13:30:46 -07003587inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303588{
Ed Tanous100afe52023-06-07 13:30:46 -07003589 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3590 .privileges(redfish::privileges::headComputerSystemCollection)
3591 .methods(boost::beast::http::verb::head)(
3592 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3593
3594 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3595 .privileges(redfish::privileges::getComputerSystemCollection)
3596 .methods(boost::beast::http::verb::get)(
3597 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3598
3599 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3600 .privileges(redfish::privileges::headComputerSystem)
3601 .methods(boost::beast::http::verb::head)(
3602 std::bind_front(handleComputerSystemHead, std::ref(app)));
3603
3604 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3605 .privileges(redfish::privileges::getComputerSystem)
3606 .methods(boost::beast::http::verb::get)(
3607 std::bind_front(handleComputerSystemGet, std::ref(app)));
3608
3609 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3610 .privileges(redfish::privileges::patchComputerSystem)
3611 .methods(boost::beast::http::verb::patch)(
3612 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3613
3614 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3615 .privileges(redfish::privileges::postComputerSystem)
3616 .methods(boost::beast::http::verb::post)(std::bind_front(
3617 handleComputerSystemResetActionPost, std::ref(app)));
3618
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003619 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003620 .privileges(redfish::privileges::headActionInfo)
3621 .methods(boost::beast::http::verb::head)(std::bind_front(
3622 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003623 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003624 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003625 .methods(boost::beast::http::verb::get)(std::bind_front(
3626 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003627}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003628} // namespace redfish