blob: a336988c3aa094209350e565128b33a78ebd6124 [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.");
Ed Tanousa52f1d52025-08-26 16:34:24 -0700478 sdbusplus::message::object_path path =
479 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800480 dbus::utility::getProperty<std::string>(
Ed Tanousa52f1d52025-08-26 16:34:24 -0700481 getHostStateServiceName(computerSystemIndex), path,
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 Tanousa52f1d52025-08-26 16:34:24 -0700782 sdbusplus::message::object_path path =
783 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800784 dbus::utility::getProperty<std::string>(
Ed Tanousa52f1d52025-08-26 16:34:24 -0700785 getHostStateServiceName(computerSystemIndex), path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700786 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousa52f1d52025-08-26 16:34:24 -0700787 [asyncResp](const boost::system::error_code ec,
Ed Tanousac106bf2023-06-07 09:24:59 -0700788 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400789 if (ec)
790 {
791 // BootProgress is an optional object so just do nothing if
792 // not found
793 return;
794 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600795
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400796 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600797
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400798 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
799 dbusToRfBootProgress(bootProgressStr);
800 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600801}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530802
803/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000804 * @brief Retrieves boot progress Last Update of the system
805 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700806 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200807 * @param[in] computerSystemIndex Index associated with the requested system
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000808 *
809 * @return None.
810 */
811inline void getBootProgressLastStateTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200812 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
813 const uint64_t computerSystemIndex)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000814{
Ed Tanousa52f1d52025-08-26 16:34:24 -0700815 sdbusplus::message::object_path path =
816 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800817 dbus::utility::getProperty<uint64_t>(
Ed Tanousa52f1d52025-08-26 16:34:24 -0700818 getHostStateServiceName(computerSystemIndex), path,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000819 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700820 [asyncResp](const boost::system::error_code& ec,
821 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400822 if (ec)
823 {
824 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
825 return;
826 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000827
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400828 // BootProgressLastUpdate is the last time the BootProgress property
829 // was updated. The time is the Epoch time, number of microseconds
830 // since 1 Jan 1970 00::00::00 UTC."
831 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
832 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000833
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400834 // Convert to ISO 8601 standard
835 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
836 redfish::time_utils::getDateTimeUintUs(lastStateTime);
837 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000838}
839
840/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300841 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300842 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700843 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200844 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300845 *
846 * @return None.
847 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500848inline void getBootOverrideType(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200849 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
850 const uint64_t computerSystemIndex)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300851{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200852 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
853 std::to_string(computerSystemIndex));
854 path /= "boot";
855
Ed Tanousdeae6a72024-11-11 21:58:57 -0800856 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200857 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700858 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700859 [asyncResp](const boost::system::error_code& ec,
860 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400861 if (ec)
862 {
863 // not an error, don't have to have the interface
864 return;
865 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300866
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400867 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300868
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400869 asyncResp->res
870 .jsonValue["Boot"]
871 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
872 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300873
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400874 auto rfType = dbusToRfBootType(bootType);
875 if (rfType.empty())
876 {
877 messages::internalError(asyncResp->res);
878 return;
879 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300880
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400881 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
882 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300883}
884
885/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300886 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530887 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700888 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200889 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530890 *
891 * @return None.
892 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500893inline void getBootOverrideMode(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200894 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
895 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530896{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200897 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
898 std::to_string(computerSystemIndex));
899 path /= "boot";
Ed Tanousdeae6a72024-11-11 21:58:57 -0800900 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200901 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700902 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700903 [asyncResp](const boost::system::error_code& ec,
904 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400905 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530906 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400907 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
908 messages::internalError(asyncResp->res);
909 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530910 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400911
912 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
913
914 nlohmann::json::array_t allowed;
915 allowed.emplace_back("None");
916 allowed.emplace_back("Pxe");
917 allowed.emplace_back("Hdd");
918 allowed.emplace_back("Cd");
919 allowed.emplace_back("Diags");
920 allowed.emplace_back("BiosSetup");
921 allowed.emplace_back("Usb");
922
923 asyncResp->res
924 .jsonValue["Boot"]
925 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
926 std::move(allowed);
927 if (bootModeStr !=
928 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
929 {
930 auto rfMode = dbusToRfBootMode(bootModeStr);
931 if (!rfMode.empty())
932 {
933 asyncResp->res
934 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
935 }
936 }
937 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530938}
939
940/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300941 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530942 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700943 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200944 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530945 *
946 * @return None.
947 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500948inline void getBootOverrideSource(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200949 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
950 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530951{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200952 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
953 std::to_string(computerSystemIndex));
954 path /= "boot";
955
Ed Tanousdeae6a72024-11-11 21:58:57 -0800956 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200957 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700958 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200959 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
960 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400961 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +0000962 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800963 // Service not available, no error, just don't return
964 // Boot Override Source information
965 if (ec.value() != EBADR &&
966 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400967 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800968 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
969 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400970 }
Nan Zhou5ef735c2022-06-22 05:24:21 +0000971 return;
972 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530973
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400974 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530975
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400976 auto rfSource = dbusToRfBootSource(bootSourceStr);
977 if (!rfSource.empty())
978 {
979 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
980 rfSource;
981 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300982
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400983 // Get BootMode as BootSourceOverrideTarget is constructed
984 // from both BootSource and BootMode
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200985 getBootOverrideMode(asyncResp, computerSystemIndex);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400986 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530987}
988
989/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300990 * @brief This functions abstracts all the logic behind getting a
991 * "BootSourceOverrideEnabled" property from an overall boot override enable
992 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530993 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700994 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200995 * @param[in] computerSystemIndex Index associated with the requested system
996 * @param[in] bootOverrideEnableSetting
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530997 *
998 * @return None.
999 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301000
Ed Tanousac106bf2023-06-07 09:24:59 -07001001inline void processBootOverrideEnable(
1002 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001003 const uint64_t computerSystemIndex, const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001004{
1005 if (!bootOverrideEnableSetting)
1006 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001007 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1008 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001009 return;
1010 }
1011
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001012 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1013 std::to_string(computerSystemIndex));
1014 path /= "boot";
1015 path /= "one_time";
1016
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001017 // If boot source override is enabled, we need to check 'one_time'
1018 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001019 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001020 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001021 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001022 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001023 if (ec)
1024 {
1025 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1026 messages::internalError(asyncResp->res);
1027 return;
1028 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301029
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001030 if (oneTimeSetting)
1031 {
1032 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1033 "Once";
1034 }
1035 else
1036 {
1037 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1038 "Continuous";
1039 }
1040 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301041}
1042
1043/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001044 * @brief Retrieves boot override enable over DBUS
1045 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001046 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001047 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001048 *
1049 * @return None.
1050 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001051inline void getBootOverrideEnable(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001052 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1053 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001054{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001055 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1056 std::to_string(computerSystemIndex));
1057 path /= "boot";
1058
Ed Tanousdeae6a72024-11-11 21:58:57 -08001059 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001060 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001061 "xyz.openbmc_project.Object.Enable", "Enabled",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001062 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1063 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001064 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001065 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001066 // Service not available, no error, just don't return
1067 // Boot Override Enable information
1068 if (ec.value() != EBADR &&
1069 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001070 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001071 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1072 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001073 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001074 return;
1075 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001076
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001077 processBootOverrideEnable(asyncResp, computerSystemIndex,
1078 bootOverrideEnable);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001079 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001080}
1081
1082/**
1083 * @brief Retrieves boot source override properties
1084 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001085 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001086 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001087 *
1088 * @return None.
1089 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001090inline void getBootProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001091 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1092 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001093{
Ed Tanous62598e32023-07-17 17:06:25 -07001094 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001095
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001096 getBootOverrideSource(asyncResp, computerSystemIndex);
1097 getBootOverrideType(asyncResp, computerSystemIndex);
1098 getBootOverrideEnable(asyncResp, computerSystemIndex);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001099}
1100
1101/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001102 * @brief Retrieves the Last Reset Time
1103 *
1104 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1105 * and power off. Even though this is the "system" Redfish object look at the
1106 * chassis D-Bus interface for the LastStateChangeTime since this has the
1107 * last power operation time.
1108 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001109 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001110 *
1111 * @return None.
1112 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001113inline void getLastResetTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001114 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1115 const uint64_t computerSystemIndex)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001116{
Ed Tanous62598e32023-07-17 17:06:25 -07001117 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Ed Tanousa52f1d52025-08-26 16:34:24 -07001118 sdbusplus::message::object_path path =
1119 getChassisStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -08001120 dbus::utility::getProperty<uint64_t>(
Ed Tanousa52f1d52025-08-26 16:34:24 -07001121 getChassisStateServiceName(computerSystemIndex), path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001122 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001123 [asyncResp](const boost::system::error_code& ec,
1124 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001125 if (ec)
1126 {
1127 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1128 return;
1129 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001130
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001131 // LastStateChangeTime is epoch time, in milliseconds
1132 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1133 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001134
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001135 // Convert to ISO 8601 standard
1136 asyncResp->res.jsonValue["LastResetTime"] =
1137 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1138 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001139}
1140
1141/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001142 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1143 *
1144 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1145 * corresponding property "AttemptsLeft" that keeps track of the amount of
1146 * automatic retry attempts left are hosted in phosphor-state-manager through
1147 * dbus.
1148 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001149 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001150 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001151 *
1152 * @return None.
1153 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001154inline void getAutomaticRebootAttempts(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001155 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1156 const uint64_t computerSystemIndex)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001157{
Ed Tanous62598e32023-07-17 17:06:25 -07001158 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Ed Tanousa52f1d52025-08-26 16:34:24 -07001159 sdbusplus::message::object_path path =
1160 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -08001161 dbus::utility::getAllProperties(
Ed Tanousa52f1d52025-08-26 16:34:24 -07001162 getHostStateServiceName(computerSystemIndex), path,
Corey Hardesty797d5da2022-04-26 17:54:52 +08001163 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001164 [asyncResp{asyncResp}](
1165 const boost::system::error_code& ec,
1166 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001167 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001168 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301169 if (ec.value() != EBADR &&
1170 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001171 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301172 // Service not available, no error, just don't return
1173 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001174 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1175 messages::internalError(asyncResp->res);
1176 }
1177 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001178 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001179
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001180 const uint32_t* attemptsLeft = nullptr;
1181 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001182
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001183 const bool success = sdbusplus::unpackPropertiesNoThrow(
1184 dbus_utils::UnpackErrorPrinter(), propertiesList,
1185 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001186
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001187 if (!success)
1188 {
1189 messages::internalError(asyncResp->res);
1190 return;
1191 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001192
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001193 if (attemptsLeft != nullptr)
1194 {
1195 asyncResp->res
1196 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1197 *attemptsLeft;
1198 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001199
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001200 if (retryAttempts != nullptr)
1201 {
1202 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1203 *retryAttempts;
1204 }
1205 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001206}
1207
1208/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001209 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1210 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001211 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001212 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001213 *
1214 * @return None.
1215 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001216inline void getAutomaticRetryPolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001217 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1218 const uint64_t computerSystemIndex)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001219{
Ed Tanous62598e32023-07-17 17:06:25 -07001220 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001221
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001222 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1223 std::to_string(computerSystemIndex));
1224 path /= "auto_reboot";
1225
Ed Tanousdeae6a72024-11-11 21:58:57 -08001226 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001227 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001228 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001229 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1230 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001231 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001232 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301233 // Service not available, no error, just don't return
1234 // AutoReboot information
1235 if (ec.value() != EBADR &&
1236 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001237 {
1238 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1239 messages::internalError(asyncResp->res);
1240 }
1241 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001242 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001243
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001244 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1245 if (autoRebootEnabled)
1246 {
1247 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1248 "RetryAttempts";
1249 }
1250 else
1251 {
1252 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1253 "Disabled";
1254 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001255 getAutomaticRebootAttempts(asyncResp, computerSystemIndex);
Gunnar Mills69f35302020-05-17 16:06:31 -05001256
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001257 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1258 // and RetryAttempts. OpenBMC only supports Disabled and
1259 // RetryAttempts.
1260 nlohmann::json::array_t allowed;
1261 allowed.emplace_back("Disabled");
1262 allowed.emplace_back("RetryAttempts");
1263 asyncResp->res
1264 .jsonValue["Boot"]
1265 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1266 std::move(allowed);
1267 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001268}
1269
1270/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001271 * @brief Sets RetryAttempts
1272 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001273 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001274 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001275 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1276 *
1277 *@return None.
1278 */
1279
Ed Tanousac106bf2023-06-07 09:24:59 -07001280inline void setAutomaticRetryAttempts(
1281 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001282 const uint64_t computerSystemIndex, const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001283{
Ed Tanous62598e32023-07-17 17:06:25 -07001284 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001285
1286 setDbusProperty(asyncResp, "Boot/AutomaticRetryAttempts",
1287 getHostStateServiceName(computerSystemIndex),
1288 getHostStateObjectPath(computerSystemIndex),
1289 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1290 "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001291}
1292
Ed Tanous8d69c662023-06-21 10:29:06 -07001293inline computer_system::PowerRestorePolicyTypes
1294 redfishPowerRestorePolicyFromDbus(std::string_view value)
1295{
1296 if (value ==
1297 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1298 {
1299 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1300 }
1301 if (value ==
1302 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1303 {
1304 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1305 }
1306 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001307 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001308 {
1309 return computer_system::PowerRestorePolicyTypes::LastState;
1310 }
1311 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1312 {
1313 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1314 }
1315 return computer_system::PowerRestorePolicyTypes::Invalid;
1316}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001317/**
George Liuc6a620f2020-04-10 17:18:11 +08001318 * @brief Retrieves power restore policy over DBUS.
1319 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001320 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001321 *
1322 * @return None.
1323 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001324inline void getPowerRestorePolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001325 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1326 const uint64_t computerSystemIndex)
George Liuc6a620f2020-04-10 17:18:11 +08001327{
Ed Tanous62598e32023-07-17 17:06:25 -07001328 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001329
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001330 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1331 std::to_string(computerSystemIndex));
1332 path /= "power_restore_policy";
1333
Ed Tanousdeae6a72024-11-11 21:58:57 -08001334 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001335 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001336 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001337 [asyncResp](const boost::system::error_code& ec,
1338 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001339 if (ec)
1340 {
1341 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1342 return;
1343 }
1344 computer_system::PowerRestorePolicyTypes restore =
1345 redfishPowerRestorePolicyFromDbus(policy);
1346 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1347 {
1348 messages::internalError(asyncResp->res);
1349 return;
1350 }
George Liuc6a620f2020-04-10 17:18:11 +08001351
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001352 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1353 });
George Liuc6a620f2020-04-10 17:18:11 +08001354}
1355
1356/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001357 * @brief Stop Boot On Fault over DBUS.
1358 *
1359 * @param[in] asyncResp Shared pointer for generating response message.
1360 *
1361 * @return None.
1362 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001363inline void getStopBootOnFault(
1364 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001365{
Ed Tanous62598e32023-07-17 17:06:25 -07001366 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001367
Ed Tanousdeae6a72024-11-11 21:58:57 -08001368 dbus::utility::getProperty<bool>(
1369 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001370 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1371 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001372 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001373 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301374 // Service not available, no error, just don't return
1375 // StopBootOnFault information
1376 if (ec.value() != EBADR ||
1377 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001378 {
1379 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1380 messages::internalError(asyncResp->res);
1381 }
1382 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001383 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001384
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001385 if (value)
1386 {
1387 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1388 computer_system::StopBootOnFault::AnyFault;
1389 }
1390 else
1391 {
1392 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1393 computer_system::StopBootOnFault::Never;
1394 }
1395 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001396}
1397
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001398inline void getTrustedModuleRequiredToBootCallback(
1399 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1400 const uint64_t computerSystemIndex, const boost::system::error_code& ec,
1401 const dbus::utility::MapperGetSubTreeResponse& subtree)
1402{
1403 if (ec)
1404 {
1405 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}", ec);
1406 // This is an optional D-Bus object so just return if
1407 // error occurs
1408 return;
1409 }
1410 if (subtree.empty())
1411 {
1412 // As noted above, this is an optional interface so just return
1413 // if there is no instance found
1414 return;
1415 }
1416
1417 std::string path;
1418 std::string service;
1419
1420 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1421 {
1422 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1423 subtree, path, service))
1424 {
1425 return;
1426 }
1427 }
1428 else
1429 {
1430 // Make sure the Dbus response map has a service and objectPath
1431 // field
1432 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1433 {
1434 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1435 messages::internalError(asyncResp->res);
1436 return;
1437 }
1438
1439 path = subtree[0].first;
1440 service = subtree[0].second.begin()->first;
1441 }
1442
1443 BMCWEB_LOG_DEBUG("found tpm service {}", service);
1444 BMCWEB_LOG_DEBUG("found tpm path {}", path);
1445
1446 // Valid TPM Enable object found, now reading the current value
1447 dbus::utility::getProperty<bool>(
1448 service, path, "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1449 [asyncResp](const boost::system::error_code& ec2, bool tpmRequired) {
1450 if (ec2)
1451 {
1452 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
1453 ec2);
1454 messages::internalError(asyncResp->res);
1455 return;
1456 }
1457
1458 if (tpmRequired)
1459 {
1460 asyncResp->res
1461 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1462 "Required";
1463 }
1464 else
1465 {
1466 asyncResp->res
1467 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1468 "Disabled";
1469 }
1470 });
1471}
1472
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001473/**
Ali Ahmed19817712021-06-29 17:01:52 -05001474 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1475 * TPM is required for booting the host.
1476 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001477 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001478 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed19817712021-06-29 17:01:52 -05001479 *
1480 * @return None.
1481 */
1482inline void getTrustedModuleRequiredToBoot(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001483 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1484 const uint64_t computerSystemIndex)
Ali Ahmed19817712021-06-29 17:01:52 -05001485{
Ed Tanous62598e32023-07-17 17:06:25 -07001486 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001487 constexpr std::array<std::string_view, 1> interfaces = {
1488 "xyz.openbmc_project.Control.TPM.Policy"};
1489 dbus::utility::getSubTree(
1490 "/", 0, interfaces,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001491 std::bind_front(getTrustedModuleRequiredToBootCallback, asyncResp,
1492 computerSystemIndex));
Ali Ahmed19817712021-06-29 17:01:52 -05001493}
1494
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001495inline void setTrustedModuleRequiredToBootCallback(
1496 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1497 const uint64_t computerSystemIndex, const bool tpmRequired,
1498 const boost::system::error_code& ec,
1499 const dbus::utility::MapperGetSubTreeResponse& subtree)
1500{
1501 if (ec)
1502 {
1503 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}", ec);
1504 messages::internalError(asyncResp->res);
1505 return;
1506 }
1507 if (subtree.empty())
1508 {
1509 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
1510 "TrustedModuleRequiredToBoot");
1511 return;
1512 }
1513
1514 std::string path;
1515 std::string serv;
1516
1517 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1518 {
1519 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1520 subtree, path, serv))
1521 {
1522 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1523 messages::internalError(asyncResp->res);
1524 return;
1525 }
1526 }
1527 else
1528 {
1529 // Make sure the Dbus response map has a service and objectPath
1530 // field
1531 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1532 {
1533 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1534 messages::internalError(asyncResp->res);
1535 return;
1536 }
1537
1538 path = subtree[0].first;
1539 serv = subtree[0].second.begin()->first;
1540 }
1541
1542 if (serv.empty())
1543 {
1544 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1545 messages::internalError(asyncResp->res);
1546 return;
1547 }
1548
1549 // Valid TPM Enable object found, now setting the value
1550 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv, path,
1551 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1552 tpmRequired);
1553}
1554
Ali Ahmed19817712021-06-29 17:01:52 -05001555/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001556 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1557 * TPM is required for booting the host.
1558 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001559 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001560 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001561 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1562 *
1563 * @return None.
1564 */
1565inline void setTrustedModuleRequiredToBoot(
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001566 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1567 const uint64_t computerSystemIndex, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001568{
Ed Tanous62598e32023-07-17 17:06:25 -07001569 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001570 constexpr std::array<std::string_view, 1> interfaces = {
1571 "xyz.openbmc_project.Control.TPM.Policy"};
1572 dbus::utility::getSubTree(
1573 "/", 0, interfaces,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001574 std::bind_front(setTrustedModuleRequiredToBootCallback, asyncResp,
1575 computerSystemIndex, tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001576}
1577
1578/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301579 * @brief Sets boot properties into DBUS object(s).
1580 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001581 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001582 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001583 * @param[in] bootType The boot type to set.
1584 * @return Integer error code.
1585 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001586inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001587 const uint64_t computerSystemIndex,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001588 const std::optional<std::string>& bootType)
1589{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001590 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001591
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001592 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001593 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001594 return;
1595 }
1596
1597 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001598 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001599 // Figure out which DBUS interface and property to use
1600 if (*bootType == "Legacy")
1601 {
1602 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1603 }
1604 else if (*bootType == "UEFI")
1605 {
1606 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1607 }
1608 else
1609 {
Ed Tanous62598e32023-07-17 17:06:25 -07001610 BMCWEB_LOG_DEBUG("Invalid property value for "
1611 "BootSourceOverrideMode: {}",
1612 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001613 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001614 "BootSourceOverrideMode");
1615 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001616 }
1617
1618 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001619 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001620
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001621 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1622 std::to_string(computerSystemIndex));
1623 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301624 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001625 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001626 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301627 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001628}
1629
1630/**
1631 * @brief Sets boot properties into DBUS object(s).
1632 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001633 * @param[in] asyncResp Shared pointer for generating response
1634 * message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001635 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001636 * @param[in] bootType The boot type to set.
1637 * @return Integer error code.
1638 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001639inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001640 const uint64_t computerSystemIndex,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001641 const std::optional<std::string>& bootEnable)
1642{
1643 if (!bootEnable)
1644 {
1645 return;
1646 }
1647 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001648 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001649
1650 bool bootOverrideEnable = false;
1651 bool bootOverridePersistent = false;
1652 // Figure out which DBUS interface and property to use
1653 if (*bootEnable == "Disabled")
1654 {
1655 bootOverrideEnable = false;
1656 }
1657 else if (*bootEnable == "Once")
1658 {
1659 bootOverrideEnable = true;
1660 bootOverridePersistent = false;
1661 }
1662 else if (*bootEnable == "Continuous")
1663 {
1664 bootOverrideEnable = true;
1665 bootOverridePersistent = true;
1666 }
1667 else
1668 {
Ed Tanous62598e32023-07-17 17:06:25 -07001669 BMCWEB_LOG_DEBUG(
1670 "Invalid property value for BootSourceOverrideEnabled: {}",
1671 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001672 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001673 "BootSourceOverrideEnabled");
1674 return;
1675 }
1676
1677 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001678 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001679
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001680 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1681 std::to_string(computerSystemIndex));
1682 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301683 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001684 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001685 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301686 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001687
1688 if (!bootOverrideEnable)
1689 {
1690 return;
1691 }
1692
1693 // In case boot override is enabled we need to set correct value for the
1694 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001695 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1696 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001697
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001698 path /= "one_time";
Ginu Georgee93abac2024-06-14 17:35:27 +05301699 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001700 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001701 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301702 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001703}
1704
1705/**
1706 * @brief Sets boot properties into DBUS object(s).
1707 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001708 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001709 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301710 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301711 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001712 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301713 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001714inline void setBootModeOrSource(
1715 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001716 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001717 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301718{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001719 std::string bootSourceStr;
1720 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001721
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001722 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301723 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001724 return;
1725 }
1726
1727 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001728 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001729 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001730 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1731 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001732 {
Ed Tanous62598e32023-07-17 17:06:25 -07001733 BMCWEB_LOG_DEBUG(
1734 "Invalid property value for BootSourceOverrideTarget: {}",
1735 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001736 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001737 "BootSourceTargetOverride");
1738 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001739 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301740
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001741 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001742 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1743 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001744
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001745 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1746 std::to_string(computerSystemIndex));
1747 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301748 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001749 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001750 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301751 bootSourceStr);
1752 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001753 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001754 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301755 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001756}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001757
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001758/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001759 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301760 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001761 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001762 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301763 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001764 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301765 * @param[in] bootEnable The boot override enable from incoming RF request.
1766 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001767 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301768 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001769
Patrick Williams504af5a2025-02-03 14:29:03 -05001770inline void setBootProperties(
1771 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001772 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001773 const std::optional<std::string>& bootSource,
1774 const std::optional<std::string>& bootType,
1775 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301776{
Ed Tanous62598e32023-07-17 17:06:25 -07001777 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301778
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001779 setBootModeOrSource(asyncResp, computerSystemIndex, bootSource);
1780 setBootType(asyncResp, computerSystemIndex, bootType);
1781 setBootEnable(asyncResp, computerSystemIndex, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301782}
1783
George Liuc6a620f2020-04-10 17:18:11 +08001784/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001785 * @brief Sets AssetTag
1786 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001787 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001788 * @param[in] assetTag "AssetTag" from request.
1789 *
1790 * @return None.
1791 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001792inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001793 const std::string& assetTag)
1794{
George Liue99073f2022-12-09 11:06:16 +08001795 constexpr std::array<std::string_view, 1> interfaces = {
1796 "xyz.openbmc_project.Inventory.Item.System"};
1797 dbus::utility::getSubTree(
1798 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001799 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001800 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001801 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001802 if (ec)
1803 {
1804 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1805 messages::internalError(asyncResp->res);
1806 return;
1807 }
1808 if (subtree.empty())
1809 {
1810 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1811 messages::internalError(asyncResp->res);
1812 return;
1813 }
1814 // Assume only 1 system D-Bus object
1815 // Throw an error if there is more than 1
1816 if (subtree.size() > 1)
1817 {
1818 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1819 messages::internalError(asyncResp->res);
1820 return;
1821 }
1822 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1823 {
1824 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1825 messages::internalError(asyncResp->res);
1826 return;
1827 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001828
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001829 const std::string& path = subtree[0].first;
1830 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001831
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001832 if (service.empty())
1833 {
1834 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1835 messages::internalError(asyncResp->res);
1836 return;
1837 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001838
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001839 setDbusProperty(asyncResp, "AssetTag", service, path,
1840 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1841 "AssetTag", assetTag);
1842 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001843}
1844
1845/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001846 * @brief Validate the specified stopBootOnFault is valid and return the
1847 * stopBootOnFault name associated with that string
1848 *
1849 * @param[in] stopBootOnFaultString String representing the desired
1850 * stopBootOnFault
1851 *
1852 * @return stopBootOnFault value or empty if incoming value is not valid
1853 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001854inline std::optional<bool> validstopBootOnFault(
1855 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001856{
1857 if (stopBootOnFaultString == "AnyFault")
1858 {
1859 return true;
1860 }
1861
1862 if (stopBootOnFaultString == "Never")
1863 {
1864 return false;
1865 }
1866
1867 return std::nullopt;
1868}
1869
1870/**
1871 * @brief Sets stopBootOnFault
1872 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001873 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001874 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1875 *
1876 * @return None.
1877 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001878inline void setStopBootOnFault(
1879 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1880 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001881{
Ed Tanous62598e32023-07-17 17:06:25 -07001882 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001883
1884 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1885 if (!stopBootEnabled)
1886 {
Ed Tanous62598e32023-07-17 17:06:25 -07001887 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1888 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001889 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001890 "StopBootOnFault");
1891 return;
1892 }
1893
Ginu Georgee93abac2024-06-14 17:35:27 +05301894 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1895 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001896 sdbusplus::message::object_path(
1897 "/xyz/openbmc_project/logging/settings"),
1898 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301899 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001900}
1901
1902/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001903 * @brief Sets automaticRetry (Auto Reboot)
1904 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001905 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001906 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills69f35302020-05-17 16:06:31 -05001907 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1908 *
1909 * @return None.
1910 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001911inline void setAutomaticRetry(
1912 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001913 const uint64_t computerSystemIndex, const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001914{
Ed Tanous62598e32023-07-17 17:06:25 -07001915 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001916
1917 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001918 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001919
1920 if (automaticRetryConfig == "Disabled")
1921 {
1922 autoRebootEnabled = false;
1923 }
1924 else if (automaticRetryConfig == "RetryAttempts")
1925 {
1926 autoRebootEnabled = true;
1927 }
1928 else
1929 {
Ed Tanous62598e32023-07-17 17:06:25 -07001930 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1931 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001932 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001933 "AutomaticRetryConfig");
1934 return;
1935 }
1936
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001937 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1938 std::to_string(computerSystemIndex));
1939 path /= "auto_reboot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301940 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001941 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001942 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301943 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001944}
1945
Ed Tanous8d69c662023-06-21 10:29:06 -07001946inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1947{
1948 if (policy == "AlwaysOn")
1949 {
1950 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1951 }
1952 if (policy == "AlwaysOff")
1953 {
1954 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1955 }
1956 if (policy == "LastState")
1957 {
1958 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1959 }
1960 return "";
1961}
1962
Gunnar Mills69f35302020-05-17 16:06:31 -05001963/**
George Liuc6a620f2020-04-10 17:18:11 +08001964 * @brief Sets power restore policy properties.
1965 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001966 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001967 * @param[in] computerSystemIndex Index associated with the requested system
George Liuc6a620f2020-04-10 17:18:11 +08001968 * @param[in] policy power restore policy properties from request.
1969 *
1970 * @return None.
1971 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001972inline void setPowerRestorePolicy(
1973 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001974 const uint64_t computerSystemIndex, std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001975{
Ed Tanous62598e32023-07-17 17:06:25 -07001976 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001977
Ed Tanous8d69c662023-06-21 10:29:06 -07001978 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001979
Ed Tanous8d69c662023-06-21 10:29:06 -07001980 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001981 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001982 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001983 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001984 return;
1985 }
1986
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001987 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1988 std::to_string(computerSystemIndex));
1989 path /= "power_restore_policy";
1990 setDbusProperty(asyncResp, "PowerRestorePolicy",
1991 "xyz.openbmc_project.Settings", path,
1992 "xyz.openbmc_project.Control.Power.RestorePolicy",
1993 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001994}
1995
AppaRao Pulia6349912019-10-18 17:16:08 +05301996/**
1997 * @brief Retrieves provisioning status
1998 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001999 * @param[in] asyncResp Shared pointer for completing asynchronous
2000 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05302001 *
2002 * @return None.
2003 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002004inline void getProvisioningStatus(
2005 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05302006{
Ed Tanous62598e32023-07-17 17:06:25 -07002007 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002008 dbus::utility::getAllProperties(
2009 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2010 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07002011 [asyncResp](const boost::system::error_code& ec,
2012 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002013 nlohmann::json& oemPFR =
2014 asyncResp->res
2015 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
2016 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
2017 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
2018 oemPFR["@odata.type"] =
2019 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07002020
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002021 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05302022 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002023 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2024 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002025 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002026 FirmwareProvisioningStatus::NotProvisioned;
2027 return;
2028 }
2029
2030 const bool* provState = nullptr;
2031 const bool* lockState = nullptr;
2032
2033 const bool success = sdbusplus::unpackPropertiesNoThrow(
2034 dbus_utils::UnpackErrorPrinter(), propertiesList,
2035 "UfmProvisioned", provState, "UfmLocked", lockState);
2036
2037 if (!success)
2038 {
2039 messages::internalError(asyncResp->res);
2040 return;
2041 }
2042
2043 if ((provState == nullptr) || (lockState == nullptr))
2044 {
2045 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2046 messages::internalError(asyncResp->res);
2047 return;
2048 }
2049
2050 if (*provState)
2051 {
2052 if (*lockState)
2053 {
2054 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2055 FirmwareProvisioningStatus::ProvisionedAndLocked;
2056 }
2057 else
2058 {
2059 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2060 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2061 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302062 }
2063 else
2064 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002065 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002066 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302067 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002068 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302069}
AppaRao Pulia6349912019-10-18 17:16:08 +05302070
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302071/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002072 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002073 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002074 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002075 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002076 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002077 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002078inline computer_system::PowerMode translatePowerModeString(
2079 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002080{
Chris Cainb6655102024-02-01 14:35:33 -06002081 using PowerMode = computer_system::PowerMode;
2082
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002083 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002084 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002085 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002086 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002087 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002088 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002089 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002090 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002091 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002092 if (modeString ==
2093 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002094 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002095 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002096 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002097 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002098 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2099 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002100 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002101 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002102 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002103 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2104 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002105 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002106 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002107 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002108 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2109 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002110 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002111 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002112 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002113 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002114 return PowerMode::OEM;
2115 }
2116 // Any other values would be invalid
2117 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2118 return PowerMode::Invalid;
2119}
2120
Patrick Williams504af5a2025-02-03 14:29:03 -05002121inline void afterGetPowerMode(
2122 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2123 const boost::system::error_code& ec,
2124 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002125{
2126 if (ec)
2127 {
2128 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2129 messages::internalError(asyncResp->res);
2130 return;
2131 }
2132
2133 std::string powerMode;
2134 const std::vector<std::string>* allowedModes = nullptr;
2135 const bool success = sdbusplus::unpackPropertiesNoThrow(
2136 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2137 "AllowedPowerModes", allowedModes);
2138
2139 if (!success)
2140 {
2141 messages::internalError(asyncResp->res);
2142 return;
2143 }
2144
2145 nlohmann::json::array_t modeList;
2146 if (allowedModes == nullptr)
2147 {
2148 modeList.emplace_back("Static");
2149 modeList.emplace_back("MaximumPerformance");
2150 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002151 }
2152 else
2153 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002154 for (const auto& aMode : *allowedModes)
2155 {
2156 computer_system::PowerMode modeValue =
2157 translatePowerModeString(aMode);
2158 if (modeValue == computer_system::PowerMode::Invalid)
2159 {
2160 messages::internalError(asyncResp->res);
2161 continue;
2162 }
2163 modeList.emplace_back(modeValue);
2164 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002165 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002166 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002167
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002168 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2169 const computer_system::PowerMode modeValue =
2170 translatePowerModeString(powerMode);
2171 if (modeValue == computer_system::PowerMode::Invalid)
2172 {
2173 messages::internalError(asyncResp->res);
2174 return;
2175 }
2176 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2177}
Chris Cain3a2d04242021-05-28 16:57:10 -05002178/**
2179 * @brief Retrieves system power mode
2180 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002181 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002182 *
2183 * @return None.
2184 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002185inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002186{
Ed Tanous62598e32023-07-17 17:06:25 -07002187 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002188
2189 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002190 constexpr std::array<std::string_view, 1> interfaces = {
2191 "xyz.openbmc_project.Control.Power.Mode"};
2192 dbus::utility::getSubTree(
2193 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002194 [asyncResp](const boost::system::error_code& ec,
2195 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002196 if (ec)
2197 {
2198 BMCWEB_LOG_DEBUG(
2199 "DBUS response error on Power.Mode GetSubTree {}", ec);
2200 // This is an optional D-Bus object so just return if
2201 // error occurs
2202 return;
2203 }
2204 if (subtree.empty())
2205 {
2206 // As noted above, this is an optional interface so just return
2207 // if there is no instance found
2208 return;
2209 }
2210 if (subtree.size() > 1)
2211 {
2212 // More then one PowerMode object is not supported and is an
2213 // error
2214 BMCWEB_LOG_DEBUG(
2215 "Found more than 1 system D-Bus Power.Mode objects: {}",
2216 subtree.size());
2217 messages::internalError(asyncResp->res);
2218 return;
2219 }
2220 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2221 {
2222 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2223 messages::internalError(asyncResp->res);
2224 return;
2225 }
2226 const std::string& path = subtree[0].first;
2227 const std::string& service = subtree[0].second.begin()->first;
2228 if (service.empty())
2229 {
2230 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2231 messages::internalError(asyncResp->res);
2232 return;
2233 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002234
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002235 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002236 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002237 *crow::connections::systemBus, service, path,
2238 "xyz.openbmc_project.Control.Power.Mode",
2239 [asyncResp](
2240 const boost::system::error_code& ec2,
2241 const dbus::utility::DBusPropertiesMap& properties) {
2242 afterGetPowerMode(asyncResp, ec2, properties);
2243 });
George Liue99073f2022-12-09 11:06:16 +08002244 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002245}
2246
2247/**
2248 * @brief Validate the specified mode is valid and return the PowerMode
2249 * name associated with that string
2250 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002251 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002252 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002253 *
2254 * @return PowerMode value or empty string if mode is not valid
2255 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002256inline std::string validatePowerMode(
2257 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2258 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002259{
Chris Cainb6655102024-02-01 14:35:33 -06002260 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002261 std::string mode;
2262
Chris Cainb6655102024-02-01 14:35:33 -06002263 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002264 {
2265 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2266 }
Chris Cainb6655102024-02-01 14:35:33 -06002267 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002268 {
George Liu0fda0f12021-11-16 10:06:17 +08002269 mode =
2270 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002271 }
Chris Cainb6655102024-02-01 14:35:33 -06002272 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002273 {
2274 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2275 }
Chris Cainb6655102024-02-01 14:35:33 -06002276 else if (modeValue == PowerMode::BalancedPerformance)
2277 {
2278 mode =
2279 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2280 }
2281 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2282 {
2283 mode =
2284 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2285 }
2286 else if (modeValue == PowerMode::EfficiencyFavorPower)
2287 {
2288 mode =
2289 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2290 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002291 else
2292 {
Chris Cainb6655102024-02-01 14:35:33 -06002293 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002294 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002295 }
2296 return mode;
2297}
2298
2299/**
2300 * @brief Sets system power mode.
2301 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002302 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002303 * @param[in] pmode System power mode from request.
2304 *
2305 * @return None.
2306 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002307inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002308 const std::string& pmode)
2309{
Ed Tanous62598e32023-07-17 17:06:25 -07002310 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002311
Ed Tanousac106bf2023-06-07 09:24:59 -07002312 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002313 if (powerMode.empty())
2314 {
2315 return;
2316 }
2317
2318 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002319 constexpr std::array<std::string_view, 1> interfaces = {
2320 "xyz.openbmc_project.Control.Power.Mode"};
2321 dbus::utility::getSubTree(
2322 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002323 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002324 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002325 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002326 if (ec)
2327 {
2328 BMCWEB_LOG_ERROR(
2329 "DBUS response error on Power.Mode GetSubTree {}", ec);
2330 // This is an optional D-Bus object, but user attempted to patch
2331 messages::internalError(asyncResp->res);
2332 return;
2333 }
2334 if (subtree.empty())
2335 {
2336 // This is an optional D-Bus object, but user attempted to patch
2337 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2338 "PowerMode");
2339 return;
2340 }
2341 if (subtree.size() > 1)
2342 {
2343 // More then one PowerMode object is not supported and is an
2344 // error
2345 BMCWEB_LOG_DEBUG(
2346 "Found more than 1 system D-Bus Power.Mode objects: {}",
2347 subtree.size());
2348 messages::internalError(asyncResp->res);
2349 return;
2350 }
2351 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2352 {
2353 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2354 messages::internalError(asyncResp->res);
2355 return;
2356 }
2357 const std::string& path = subtree[0].first;
2358 const std::string& service = subtree[0].second.begin()->first;
2359 if (service.empty())
2360 {
2361 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2362 messages::internalError(asyncResp->res);
2363 return;
2364 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002365
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002366 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002367
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002368 // Set the Power Mode property
2369 setDbusProperty(asyncResp, "PowerMode", service, path,
2370 "xyz.openbmc_project.Control.Power.Mode",
2371 "PowerMode", powerMode);
2372 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002373}
2374
2375/**
Yong Li51709ff2019-09-30 14:13:04 +08002376 * @brief Translates watchdog timeout action DBUS property value to redfish.
2377 *
2378 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2379 *
2380 * @return Returns as a string, the timeout action in Redfish terms. If
2381 * translation cannot be done, returns an empty string.
2382 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002383inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002384{
2385 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2386 {
2387 return "None";
2388 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002389 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002390 {
2391 return "ResetSystem";
2392 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002393 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002394 {
2395 return "PowerDown";
2396 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002397 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002398 {
2399 return "PowerCycle";
2400 }
2401
2402 return "";
2403}
2404
2405/**
Yong Lic45f0082019-10-10 14:19:01 +08002406 *@brief Translates timeout action from Redfish to DBUS property value.
2407 *
2408 *@param[in] rfAction The timeout action in Redfish.
2409 *
2410 *@return Returns as a string, the time_out action as expected by DBUS.
2411 *If translation cannot be done, returns an empty string.
2412 */
2413
Ed Tanous23a21a12020-07-25 04:45:05 +00002414inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002415{
2416 if (rfAction == "None")
2417 {
2418 return "xyz.openbmc_project.State.Watchdog.Action.None";
2419 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002420 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002421 {
2422 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2423 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002424 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002425 {
2426 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2427 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002428 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002429 {
2430 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2431 }
2432
2433 return "";
2434}
2435
2436/**
Yong Li51709ff2019-09-30 14:13:04 +08002437 * @brief Retrieves host watchdog timer properties over DBUS
2438 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002439 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002440 *
2441 * @return None.
2442 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002443inline void getHostWatchdogTimer(
2444 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002445{
Ed Tanous62598e32023-07-17 17:06:25 -07002446 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002447 dbus::utility::getAllProperties(
2448 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002449 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002450 [asyncResp](const boost::system::error_code& ec,
2451 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002452 if (ec)
2453 {
2454 // watchdog service is stopped
2455 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2456 return;
2457 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002458
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002459 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002460
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002461 nlohmann::json& hostWatchdogTimer =
2462 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002463
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002464 // watchdog service is running/enabled
2465 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002466
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002467 const bool* enabled = nullptr;
2468 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002469
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002470 const bool success = sdbusplus::unpackPropertiesNoThrow(
2471 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2472 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002473
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002474 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002475 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002476 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002477 return;
2478 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002479
2480 if (enabled != nullptr)
2481 {
2482 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2483 }
2484
2485 if (expireAction != nullptr)
2486 {
2487 std::string action = dbusToRfWatchdogAction(*expireAction);
2488 if (action.empty())
2489 {
2490 messages::internalError(asyncResp->res);
2491 return;
2492 }
2493 hostWatchdogTimer["TimeoutAction"] = action;
2494 }
2495 });
Yong Li51709ff2019-09-30 14:13:04 +08002496}
2497
2498/**
Yong Lic45f0082019-10-10 14:19:01 +08002499 * @brief Sets Host WatchDog Timer properties.
2500 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002501 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002502 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2503 * RF request.
2504 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2505 *
2506 * @return None.
2507 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002508inline void setWDTProperties(
2509 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2510 const std::optional<bool> wdtEnable,
2511 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002512{
Ed Tanous62598e32023-07-17 17:06:25 -07002513 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002514
2515 if (wdtTimeOutAction)
2516 {
2517 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2518 // check if TimeOut Action is Valid
2519 if (wdtTimeOutActStr.empty())
2520 {
Ed Tanous62598e32023-07-17 17:06:25 -07002521 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2522 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002523 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002524 "TimeoutAction");
2525 return;
2526 }
2527
Ginu Georgee93abac2024-06-14 17:35:27 +05302528 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2529 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002530 sdbusplus::message::object_path(
2531 "/xyz/openbmc_project/watchdog/host0"),
2532 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302533 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002534 }
2535
2536 if (wdtEnable)
2537 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302538 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2539 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002540 sdbusplus::message::object_path(
2541 "/xyz/openbmc_project/watchdog/host0"),
2542 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302543 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002544 }
2545}
2546
Chris Cain37bbf982021-09-20 10:53:09 -05002547/**
2548 * @brief Parse the Idle Power Saver properties into json
2549 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002550 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002551 * @param[in] properties IPS property data from DBus.
2552 *
2553 * @return true if successful
2554 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002555inline bool parseIpsProperties(
2556 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2557 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002558{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002559 const bool* enabled = nullptr;
2560 const uint8_t* enterUtilizationPercent = nullptr;
2561 const uint64_t* enterDwellTime = nullptr;
2562 const uint8_t* exitUtilizationPercent = nullptr;
2563 const uint64_t* exitDwellTime = nullptr;
2564
2565 const bool success = sdbusplus::unpackPropertiesNoThrow(
2566 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002567 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2568 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2569 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002570
2571 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002572 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002573 return false;
2574 }
2575
2576 if (enabled != nullptr)
2577 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002578 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002579 }
2580
2581 if (enterUtilizationPercent != nullptr)
2582 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002583 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002584 *enterUtilizationPercent;
2585 }
2586
2587 if (enterDwellTime != nullptr)
2588 {
2589 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002590 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002591 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2592 .count();
2593 }
2594
2595 if (exitUtilizationPercent != nullptr)
2596 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002597 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002598 *exitUtilizationPercent;
2599 }
2600
2601 if (exitDwellTime != nullptr)
2602 {
2603 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002604 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002605 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2606 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002607 }
2608
2609 return true;
2610}
2611
2612/**
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002613 * @brief Retrieves idle power saver properties over DBUS
Chris Cain37bbf982021-09-20 10:53:09 -05002614 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002615 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002616 *
2617 * @return None.
2618 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002619inline void getIdlePowerSaver(
2620 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002621{
Ed Tanous62598e32023-07-17 17:06:25 -07002622 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002623
2624 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002625 constexpr std::array<std::string_view, 1> interfaces = {
2626 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2627 dbus::utility::getSubTree(
2628 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002629 [asyncResp](const boost::system::error_code& ec,
2630 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002631 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002632 {
Ed Tanous62598e32023-07-17 17:06:25 -07002633 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002634 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2635 ec);
2636 messages::internalError(asyncResp->res);
2637 return;
2638 }
2639 if (subtree.empty())
2640 {
2641 // This is an optional interface so just return
2642 // if there is no instance found
2643 BMCWEB_LOG_DEBUG("No instances found");
2644 return;
2645 }
2646 if (subtree.size() > 1)
2647 {
2648 // More then one PowerIdlePowerSaver object is not supported and
2649 // is an error
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002650 BMCWEB_LOG_DEBUG(
2651 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2652 subtree.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002653 messages::internalError(asyncResp->res);
2654 return;
2655 }
2656 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2657 {
2658 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2659 messages::internalError(asyncResp->res);
2660 return;
2661 }
2662 const std::string& path = subtree[0].first;
2663 const std::string& service = subtree[0].second.begin()->first;
2664 if (service.empty())
2665 {
2666 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002667 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002668 return;
2669 }
2670
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002671 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002672 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002673 *crow::connections::systemBus, service, path,
2674 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2675 [asyncResp](
2676 const boost::system::error_code& ec2,
2677 const dbus::utility::DBusPropertiesMap& properties) {
2678 if (ec2)
2679 {
2680 BMCWEB_LOG_ERROR(
2681 "DBUS response error on IdlePowerSaver GetAll: {}",
2682 ec2);
2683 messages::internalError(asyncResp->res);
2684 return;
2685 }
2686
2687 if (!parseIpsProperties(asyncResp, properties))
2688 {
2689 messages::internalError(asyncResp->res);
2690 return;
2691 }
2692 });
George Liue99073f2022-12-09 11:06:16 +08002693 });
Chris Cain37bbf982021-09-20 10:53:09 -05002694
Ed Tanous62598e32023-07-17 17:06:25 -07002695 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002696}
2697
2698/**
2699 * @brief Sets Idle Power Saver properties.
2700 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002701 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002702 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2703 * RF request.
2704 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2705 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2706 * before entering idle state.
2707 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2708 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2709 * before exiting idle state
2710 *
2711 * @return None.
2712 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002713inline void setIdlePowerSaver(
2714 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2715 const std::optional<bool> ipsEnable,
2716 const std::optional<uint8_t> ipsEnterUtil,
2717 const std::optional<uint64_t> ipsEnterTime,
2718 const std::optional<uint8_t> ipsExitUtil,
2719 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002720{
Ed Tanous62598e32023-07-17 17:06:25 -07002721 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002722
2723 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002724 constexpr std::array<std::string_view, 1> interfaces = {
2725 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2726 dbus::utility::getSubTree(
2727 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002728 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002729 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002730 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002731 if (ec)
2732 {
2733 BMCWEB_LOG_ERROR(
2734 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2735 ec);
2736 messages::internalError(asyncResp->res);
2737 return;
2738 }
2739 if (subtree.empty())
2740 {
2741 // This is an optional D-Bus object, but user attempted to patch
2742 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2743 "IdlePowerSaver");
2744 return;
2745 }
2746 if (subtree.size() > 1)
2747 {
2748 // More then one PowerIdlePowerSaver object is not supported and
2749 // is an error
2750 BMCWEB_LOG_DEBUG(
2751 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2752 subtree.size());
2753 messages::internalError(asyncResp->res);
2754 return;
2755 }
2756 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2757 {
2758 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2759 messages::internalError(asyncResp->res);
2760 return;
2761 }
2762 const std::string& path = subtree[0].first;
2763 const std::string& service = subtree[0].second.begin()->first;
2764 if (service.empty())
2765 {
2766 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2767 messages::internalError(asyncResp->res);
2768 return;
2769 }
Chris Cain37bbf982021-09-20 10:53:09 -05002770
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002771 // Valid Power IdlePowerSaver object found, now set any values that
2772 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002773
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002774 if (ipsEnable)
2775 {
2776 setDbusProperty(
2777 asyncResp, "IdlePowerSaver/Enabled", service, path,
2778 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2779 "Enabled", *ipsEnable);
2780 }
2781 if (ipsEnterUtil)
2782 {
2783 setDbusProperty(
2784 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2785 service, path,
2786 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2787 "EnterUtilizationPercent", *ipsEnterUtil);
2788 }
2789 if (ipsEnterTime)
2790 {
2791 // Convert from seconds into milliseconds for DBus
2792 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2793 setDbusProperty(
2794 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2795 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2796 "EnterDwellTime", timeMilliseconds);
2797 }
2798 if (ipsExitUtil)
2799 {
2800 setDbusProperty(
2801 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2802 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2803 "ExitUtilizationPercent", *ipsExitUtil);
2804 }
2805 if (ipsExitTime)
2806 {
2807 // Convert from seconds into milliseconds for DBus
2808 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2809 setDbusProperty(
2810 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2811 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2812 "ExitDwellTime", timeMilliseconds);
2813 }
2814 });
Chris Cain37bbf982021-09-20 10:53:09 -05002815
Ed Tanous62598e32023-07-17 17:06:25 -07002816 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002817}
2818
Ed Tanousc1e219d2023-06-07 10:34:33 -07002819inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002820 crow::App& app, const crow::Request& req,
2821 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2822{
2823 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2824 {
2825 return;
2826 }
2827 asyncResp->res.addHeader(
2828 boost::beast::http::field::link,
2829 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2830}
2831
Ed Tanousc1e219d2023-06-07 10:34:33 -07002832inline void handleComputerSystemCollectionGet(
2833 crow::App& app, const crow::Request& req,
2834 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2835{
2836 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2837 {
2838 return;
2839 }
2840
2841 asyncResp->res.addHeader(
2842 boost::beast::http::field::link,
2843 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2844 asyncResp->res.jsonValue["@odata.type"] =
2845 "#ComputerSystemCollection.ComputerSystemCollection";
2846 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2847 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2848
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002849 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002850}
2851
Yong Lic45f0082019-10-10 14:19:01 +08002852/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002853 * Function transceives data with dbus directly.
2854 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002855inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002856{
Patrick Williams89492a12023-05-10 07:51:34 -05002857 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2858 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2859 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002860 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002861 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002862
Ed Tanous177612a2025-02-14 15:16:09 -08002863 dbus::utility::async_method_call(
2864 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002865 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002866 if (ec)
2867 {
2868 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2869 messages::internalError(asyncResp->res);
2870 return;
2871 }
2872 messages::success(asyncResp->res);
2873 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002874 serviceName, objectPath, interfaceName, method);
2875}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002876
Oliver Brewka06c055e2025-07-23 16:42:24 +02002877/**
2878 * @brief process the POST request after getting the computerSystemIndex
2879 *
2880 * @param[in] asyncResp Shared pointer for completing asynchronous
2881 * calls
2882 * @param[in] resetType The requested reset action
2883 * @param[in] computerSystemIndex Index associated with the requested system
2884 *
2885 * @return None
2886 */
2887inline void processComputerSystemResetActionPost(
2888 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string& resetType,
2889 const uint64_t computerSystemIndex)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002890{
Ed Tanousc1e219d2023-06-07 10:34:33 -07002891 // Get the command and host vs. chassis
2892 std::string command;
2893 bool hostCommand = true;
2894 if ((resetType == "On") || (resetType == "ForceOn"))
2895 {
2896 command = "xyz.openbmc_project.State.Host.Transition.On";
2897 hostCommand = true;
2898 }
2899 else if (resetType == "ForceOff")
2900 {
2901 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2902 hostCommand = false;
2903 }
2904 else if (resetType == "ForceRestart")
2905 {
2906 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2907 hostCommand = true;
2908 }
2909 else if (resetType == "GracefulShutdown")
2910 {
2911 command = "xyz.openbmc_project.State.Host.Transition.Off";
2912 hostCommand = true;
2913 }
2914 else if (resetType == "GracefulRestart")
2915 {
2916 command =
2917 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2918 hostCommand = true;
2919 }
2920 else if (resetType == "PowerCycle")
2921 {
2922 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2923 hostCommand = true;
2924 }
2925 else if (resetType == "Nmi")
2926 {
2927 doNMI(asyncResp);
2928 return;
2929 }
2930 else
2931 {
2932 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2933 return;
2934 }
2935
2936 if (hostCommand)
2937 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002938 setDbusProperty(asyncResp, "Reset",
2939 getHostStateServiceName(computerSystemIndex),
2940 getHostStateObjectPath(computerSystemIndex),
2941 "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302942 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002943 }
2944 else
2945 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002946 setDbusProperty(asyncResp, "Reset",
2947 getChassisStateServiceName(computerSystemIndex),
2948 getChassisStateObjectPath(computerSystemIndex),
Ed Tanousd02aad32024-02-13 14:43:34 -08002949 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302950 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002951 }
2952}
2953
Oliver Brewka06c055e2025-07-23 16:42:24 +02002954inline void handleComputerSystemResetActionPost(
2955 crow::App& app, const crow::Request& req,
2956 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2957 const std::string& systemName)
2958{
2959 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2960 {
2961 return;
2962 }
2963
2964 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2965 {
2966 if (systemName == "hypervisor")
2967 {
2968 handleHypervisorSystemResetPost(req, asyncResp);
2969 return;
2970 }
2971 }
2972
2973 if (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2974 {
2975 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2976 {
2977 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2978 systemName);
2979 return;
2980 }
2981 }
2982
2983 std::string resetType;
2984 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2985 {
2986 return;
2987 }
2988
2989 getComputerSystemIndex(asyncResp, systemName,
2990 std::bind_front(processComputerSystemResetActionPost,
2991 asyncResp, resetType));
2992}
2993
Ed Tanousc1e219d2023-06-07 10:34:33 -07002994inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002995 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002996 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2997 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002998{
2999 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3000 {
3001 return;
3002 }
3003
3004 asyncResp->res.addHeader(
3005 boost::beast::http::field::link,
3006 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3007}
3008
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003009inline void afterPortRequest(
3010 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3011 const boost::system::error_code& ec,
3012 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3013{
3014 if (ec)
3015 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003016 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003017 messages::internalError(asyncResp->res);
3018 return;
3019 }
3020 for (const auto& data : socketData)
3021 {
3022 const std::string& socketPath = get<0>(data);
3023 const std::string& protocolName = get<1>(data);
3024 bool isProtocolEnabled = get<2>(data);
3025 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3026 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3027 // need to retrieve port number for
3028 // obmc-console-ssh service
3029 if (protocolName == "SSH")
3030 {
3031 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003032 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003033 int portNumber) {
3034 if (ec1)
3035 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003036 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003037 messages::internalError(asyncResp->res);
3038 return;
3039 }
3040 nlohmann::json& dataJson1 =
3041 asyncResp->res.jsonValue["SerialConsole"];
3042 dataJson1[protocolName]["Port"] = portNumber;
3043 });
3044 }
3045 }
3046}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003047
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003048/**
3049 * @brief process the GET request after getting the computerSystemIndex
3050 *
3051 * @param[in] asyncResp Shared pointer for completing asynchronous
3052 * calls
3053 * @param[in] systemName Name of the requested system
3054 * @param[in] computerSystemIndex Index associated with the requested system
3055 *
3056 * @return None
3057 */
3058inline void processComputerSystemGet(
Patrick Williams504af5a2025-02-03 14:29:03 -05003059 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003060 const std::string& systemName, const uint64_t computerSystemIndex)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003061{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003062 asyncResp->res.addHeader(
3063 boost::beast::http::field::link,
3064 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3065 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003066 "#ComputerSystem.v1_22_0.ComputerSystem";
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003067 asyncResp->res.jsonValue["Name"] = systemName;
3068 asyncResp->res.jsonValue["Id"] = systemName;
Ed Tanous539d8c62024-06-19 14:38:27 -07003069 asyncResp->res.jsonValue["SystemType"] =
3070 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003071 asyncResp->res.jsonValue["Description"] = "Computer System";
3072 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003073 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003074 double(0);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003075 asyncResp->res.jsonValue["@odata.id"] =
3076 boost::urls::format("/redfish/v1/Systems/{}", systemName);
Ed Tanous04a258f2018-10-15 08:00:41 -07003077
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003078 // Currently not supported on multi-host. TBD
3079 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3080 {
3081 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3082 boost::urls::format("/redfish/v1/Systems/{}/Bios", systemName);
3083 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3084 boost::urls::format("/redfish/v1/Systems/{}/Processors",
3085 systemName);
3086 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3087 boost::urls::format("/redfish/v1/Systems/{}/Memory", systemName);
3088 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3089 boost::urls::format("/redfish/v1/Systems/{}/Storage", systemName);
3090 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3091 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3092 systemName);
3093 }
Ed Tanous029573d2019-02-01 10:57:49 -08003094
Ed Tanousc1e219d2023-06-07 10:34:33 -07003095 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003096 boost::urls::format(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003097 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003098 asyncResp->res
3099 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003100 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003101 systemName);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003102
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003103 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3104 boost::urls::format("/redfish/v1/Systems/{}/LogServices", systemName);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003105
Ed Tanousc1e219d2023-06-07 10:34:33 -07003106 nlohmann::json::array_t managedBy;
3107 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003108 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3109 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003110 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003111 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3112 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003113
Ed Tanousc1e219d2023-06-07 10:34:33 -07003114 // Fill in SerialConsole info
3115 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3116 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003117
Ed Tanousc1e219d2023-06-07 10:34:33 -07003118 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3119 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3120 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3121 "Press ~. to exit console";
3122 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3123 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003124
Ed Tanous25b54db2024-04-17 15:40:31 -07003125 if constexpr (BMCWEB_KVM)
3126 {
3127 // Fill in GraphicalConsole info
3128 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3129 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3130 4;
3131 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3132 nlohmann::json::array_t({"KVMIP"});
3133 }
James Feistb49ac872019-05-21 15:12:01 -07003134
Janet Adkinseb261e12025-09-15 13:25:45 -05003135 if constexpr (BMCWEB_REDFISH_USE_HARDCODED_SYSTEM_LOCATION_INDICATOR)
3136 {
3137 getSystemLocationIndicatorActive(asyncResp);
3138 }
3139 else
3140 {
3141 systems_utils::getValidSystemsPath(
3142 asyncResp, systemName,
3143 [asyncResp,
3144 systemName](const std::optional<std::string>& validSystemsPath) {
3145 if (validSystemsPath)
3146 {
3147 getLocationIndicatorActive(asyncResp, *validSystemsPath);
3148 }
3149 });
3150 }
Janet Adkins2eaa9272025-04-17 10:30:43 -05003151
Janet Adkinsf664fd82025-07-23 14:01:43 -05003152 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3153 {
3154 getIndicatorLedState(asyncResp);
3155 }
3156
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003157 // Currently not supported on multi-host.
3158 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3159 {
3160 getComputerSystem(asyncResp);
3161 // Todo: chassis matching could be handled by patch
3162 // https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60793
3163 getMainChassisId(
3164 asyncResp, [](const std::string& chassisId,
3165 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3166 nlohmann::json::array_t chassisArray;
3167 nlohmann::json& chassis = chassisArray.emplace_back();
3168 chassis["@odata.id"] =
3169 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3170 aRsp->res.jsonValue["Links"]["Chassis"] =
3171 std::move(chassisArray);
3172 });
3173
3174 pcie_util::getPCIeDeviceList(
3175 asyncResp, nlohmann::json::json_pointer("/PCIeDevices"));
3176 }
3177 getHostState(asyncResp, computerSystemIndex);
3178 getBootProperties(asyncResp, computerSystemIndex);
3179 getBootProgress(asyncResp, computerSystemIndex);
3180 getBootProgressLastStateTime(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003181 getHostWatchdogTimer(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003182 getPowerRestorePolicy(asyncResp, computerSystemIndex);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003183 getStopBootOnFault(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003184 getAutomaticRetryPolicy(asyncResp, computerSystemIndex);
3185 getLastResetTime(asyncResp, computerSystemIndex);
Ed Tanous25b54db2024-04-17 15:40:31 -07003186 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3187 {
3188 getProvisioningStatus(asyncResp);
3189 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003190 getTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003191 getPowerMode(asyncResp);
3192 getIdlePowerSaver(asyncResp);
3193}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003194
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003195inline void handleComputerSystemGet(
3196 crow::App& app, const crow::Request& req,
3197 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3198 const std::string& systemName)
3199{
3200 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3201 {
3202 return;
3203 }
3204
3205 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
3206 {
3207 if (systemName == "hypervisor")
3208 {
3209 handleHypervisorSystemGet(asyncResp);
3210 return;
3211 }
3212 }
3213
3214 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3215 {
3216 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3217 {
3218 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3219 systemName);
3220 return;
3221 }
3222 }
3223
3224 BMCWEB_LOG_DEBUG("requested system = {}", systemName);
3225 getComputerSystemIndex(
3226 asyncResp, systemName,
3227 std::bind_front(processComputerSystemGet, asyncResp, systemName));
3228}
3229
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003230struct PatchParams
Ed Tanousc1e219d2023-06-07 10:34:33 -07003231{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003232 std::optional<bool> locationIndicatorActive;
3233 std::optional<std::string> indicatorLed;
3234 std::optional<std::string> assetTag;
3235 std::optional<std::string> powerRestorePolicy;
3236 std::optional<std::string> powerMode;
3237 std::optional<bool> wdtEnable;
3238 std::optional<std::string> wdtTimeOutAction;
3239 std::optional<std::string> bootSource;
3240 std::optional<std::string> bootType;
3241 std::optional<std::string> bootEnable;
3242 std::optional<std::string> bootAutomaticRetry;
3243 std::optional<uint32_t> bootAutomaticRetryAttempts;
3244 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003245 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003246 std::optional<bool> ipsEnable;
3247 std::optional<uint8_t> ipsEnterUtil;
3248 std::optional<uint64_t> ipsEnterTime;
3249 std::optional<uint8_t> ipsExitUtil;
3250 std::optional<uint64_t> ipsExitTime;
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003251};
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003252
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003253/**
3254 * @brief process the POST request after getting the computerSystemIndex
3255 *
3256 * @param[in] asyncResp Shared pointer for completing asynchronous
3257 * calls
3258 * @param[in] patchParams Struct containing the property we want to
3259 * patch
3260 * @param[in] computerSystemIndex Index associated with the requested system
3261 *
3262 * @return None
3263 */
James Feistb49ac872019-05-21 15:12:01 -07003264
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003265inline void processComputerSystemPatch(
3266 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3267 std::string& systemName, PatchParams& patchParams,
3268 const uint64_t computerSystemIndex)
3269{
Janet Adkinsf664fd82025-07-23 14:01:43 -05003270 if constexpr (!BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3271 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003272 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003273 {
3274 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
3275 return;
3276 }
3277 }
3278
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003279 if (patchParams.assetTag)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003280 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003281 setAssetTag(asyncResp, *patchParams.assetTag);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003282 }
James Feistb49ac872019-05-21 15:12:01 -07003283
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003284 if (patchParams.wdtEnable || patchParams.wdtTimeOutAction)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003285 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003286 setWDTProperties(asyncResp, patchParams.wdtEnable,
3287 patchParams.wdtTimeOutAction);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003288 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003289
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003290 if (patchParams.bootSource || patchParams.bootType ||
3291 patchParams.bootEnable)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003292 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003293 setBootProperties(asyncResp, computerSystemIndex,
3294 patchParams.bootSource, patchParams.bootType,
3295 patchParams.bootEnable);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003296 }
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003297 if (patchParams.bootAutomaticRetry)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003298 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003299 setAutomaticRetry(asyncResp, computerSystemIndex,
3300 *patchParams.bootAutomaticRetry);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003301 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003302
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003303 if (patchParams.bootAutomaticRetryAttempts)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003304 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003305 setAutomaticRetryAttempts(
3306 asyncResp, computerSystemIndex,
3307 patchParams.bootAutomaticRetryAttempts.value());
Ed Tanousc1e219d2023-06-07 10:34:33 -07003308 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003309
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003310 if (patchParams.bootTrustedModuleRequired)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003311 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003312 setTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex,
3313 *patchParams.bootTrustedModuleRequired);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003314 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003315
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003316 if (patchParams.stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003317 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003318 setStopBootOnFault(asyncResp, *patchParams.stopBootOnFault);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003319 }
3320
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003321 if (patchParams.locationIndicatorActive)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003322 {
Janet Adkinseb261e12025-09-15 13:25:45 -05003323 if constexpr (BMCWEB_REDFISH_USE_HARDCODED_SYSTEM_LOCATION_INDICATOR)
3324 {
3325 setSystemLocationIndicatorActive(
3326 asyncResp, *patchParams.locationIndicatorActive);
3327 }
3328 else
3329 {
3330 systems_utils::getValidSystemsPath(
3331 asyncResp, systemName,
3332 [asyncResp, systemName,
3333 locationIndicatorActive{*patchParams.locationIndicatorActive}](
3334 const std::optional<std::string>& validSystemsPath) {
3335 if (!validSystemsPath)
3336 {
3337 messages::resourceNotFound(asyncResp->res, "Systems",
3338 systemName);
3339 return;
3340 }
3341 setLocationIndicatorActive(asyncResp, *validSystemsPath,
3342 locationIndicatorActive);
3343 });
3344 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003345 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003346
Janet Adkinsf664fd82025-07-23 14:01:43 -05003347 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003348 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003349 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003350 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003351 setIndicatorLedState(asyncResp, *patchParams.indicatorLed);
Janet Adkinsf664fd82025-07-23 14:01:43 -05003352 asyncResp->res.addHeader(boost::beast::http::field::warning,
3353 "299 - \"IndicatorLED is deprecated. Use "
3354 "LocationIndicatorActive instead.\"");
3355 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003356 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003357
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003358 if (patchParams.powerRestorePolicy)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003359 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003360 setPowerRestorePolicy(asyncResp, computerSystemIndex,
3361 *patchParams.powerRestorePolicy);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003362 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003363
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003364 if (patchParams.powerMode)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003365 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003366 setPowerMode(asyncResp, *patchParams.powerMode);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003367 }
Chris Cain37bbf982021-09-20 10:53:09 -05003368
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003369 if (patchParams.ipsEnable || patchParams.ipsEnterUtil ||
3370 patchParams.ipsEnterTime || patchParams.ipsExitUtil ||
3371 patchParams.ipsExitTime)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003372 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003373 setIdlePowerSaver(asyncResp, patchParams.ipsEnable,
3374 patchParams.ipsEnterUtil, patchParams.ipsEnterTime,
3375 patchParams.ipsExitUtil, patchParams.ipsExitTime);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003376 }
3377}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303378
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003379inline void handleComputerSystemPatch(
3380 crow::App& app, const crow::Request& req,
3381 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3382 const std::string& systemName)
3383{
3384 PatchParams patchParams;
3385
3386 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3387 {
3388 return;
3389 }
3390
3391 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3392 {
3393 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3394 {
3395 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3396 systemName);
3397 return;
3398 }
3399 }
3400
3401 asyncResp->res.addHeader(
3402 boost::beast::http::field::link,
3403 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3404
3405 if (!json_util::readJsonPatch(
3406 req, asyncResp->res, //
3407 "AssetTag", patchParams.assetTag, //
3408 "Boot/AutomaticRetryAttempts",
3409 patchParams.bootAutomaticRetryAttempts, //
3410 "Boot/AutomaticRetryConfig", patchParams.bootAutomaticRetry, //
3411 "Boot/BootSourceOverrideEnabled", patchParams.bootEnable, //
3412 "Boot/BootSourceOverrideMode", patchParams.bootType, //
3413 "Boot/BootSourceOverrideTarget", patchParams.bootSource, //
3414 "Boot/StopBootOnFault", patchParams.stopBootOnFault, //
3415 "Boot/TrustedModuleRequiredToBoot",
3416 patchParams.bootTrustedModuleRequired, //
3417 "HostWatchdogTimer/FunctionEnabled", patchParams.wdtEnable, //
3418 "HostWatchdogTimer/TimeoutAction", patchParams.wdtTimeOutAction, //
3419 "IdlePowerSaver/Enabled", patchParams.ipsEnable, //
3420 "IdlePowerSaver/EnterDwellTimeSeconds", patchParams.ipsEnterTime, //
3421 "IdlePowerSaver/EnterUtilizationPercent",
3422 patchParams.ipsEnterUtil, //
3423 "IdlePowerSaver/ExitDwellTimeSeconds", patchParams.ipsExitTime, //
3424 "IdlePowerSaver/ExitUtilizationPercent", patchParams.ipsExitUtil, //
3425 "IndicatorLED", patchParams.indicatorLed, //
3426 "LocationIndicatorActive", patchParams.locationIndicatorActive, //
3427 "PowerMode", patchParams.powerMode, //
3428 "PowerRestorePolicy", patchParams.powerRestorePolicy))
3429 {
3430 return;
3431 }
3432
3433 getComputerSystemIndex(asyncResp, systemName,
3434 std::bind_front(processComputerSystemPatch,
3435 asyncResp, systemName, patchParams));
3436}
3437
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003438inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003439 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003440 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003441 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003442{
3443 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3444 {
3445 return;
3446 }
3447 asyncResp->res.addHeader(
3448 boost::beast::http::field::link,
3449 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3450}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003451
3452/**
3453 * @brief Translates allowed host transitions to redfish string
3454 *
3455 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3456 * @param[out] allowableValues The translated host transition(s)
3457 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303458 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003459 * allowableValues. If translation not possible, does nothing to
3460 * allowableValues.
3461 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003462inline void dbusToRfAllowedHostTransitions(
3463 const std::string& dbusAllowedHostTran,
3464 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003465{
3466 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3467 {
3468 allowableValues.emplace_back(resource::ResetType::On);
3469 allowableValues.emplace_back(resource::ResetType::ForceOn);
3470 }
3471 else if (dbusAllowedHostTran ==
3472 "xyz.openbmc_project.State.Host.Transition.Off")
3473 {
3474 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3475 }
3476 else if (dbusAllowedHostTran ==
3477 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3478 {
3479 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3480 }
3481 else if (dbusAllowedHostTran ==
3482 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3483 {
3484 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3485 }
3486 else
3487 {
3488 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3489 }
3490}
3491
3492inline void afterGetAllowedHostTransitions(
3493 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3494 const boost::system::error_code& ec,
3495 const std::vector<std::string>& allowedHostTransitions)
3496{
3497 nlohmann::json::array_t allowableValues;
3498
3499 // Supported on all systems currently
3500 allowableValues.emplace_back(resource::ResetType::ForceOff);
3501 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3502 allowableValues.emplace_back(resource::ResetType::Nmi);
3503
3504 if (ec)
3505 {
Ed Tanouse715d142024-03-07 15:47:37 -08003506 if ((ec.value() ==
3507 boost::system::linux_error::bad_request_descriptor) ||
3508 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003509 {
3510 // Property not implemented so just return defaults
3511 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3512 allowableValues.emplace_back(resource::ResetType::On);
3513 allowableValues.emplace_back(resource::ResetType::ForceOn);
3514 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3515 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3516 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3517 }
3518 else
3519 {
3520 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3521 messages::internalError(asyncResp->res);
3522 return;
3523 }
3524 }
3525 else
3526 {
3527 for (const std::string& transition : allowedHostTransitions)
3528 {
3529 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3530 dbusToRfAllowedHostTransitions(transition, allowableValues);
3531 }
3532 }
3533
3534 nlohmann::json::object_t parameter;
3535 parameter["Name"] = "ResetType";
3536 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003537 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003538 parameter["AllowableValues"] = std::move(allowableValues);
3539 nlohmann::json::array_t parameters;
3540 parameters.emplace_back(std::move(parameter));
3541 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3542}
3543
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003544inline void getAllowedHostTransitions(
3545 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3546 const uint64_t computerSystemIndex)
3547{
Ed Tanousa52f1d52025-08-26 16:34:24 -07003548 sdbusplus::message::object_path path =
3549 getHostStateObjectPath(computerSystemIndex);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003550 dbus::utility::getProperty<std::vector<std::string>>(
Ed Tanousa52f1d52025-08-26 16:34:24 -07003551 getHostStateServiceName(computerSystemIndex), path,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003552 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
3553 std::bind_front(afterGetAllowedHostTransitions, asyncResp));
3554}
3555
Ed Tanousc1e219d2023-06-07 10:34:33 -07003556inline void handleSystemCollectionResetActionGet(
3557 crow::App& app, const crow::Request& req,
3558 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3559 const std::string& systemName)
3560{
3561 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3562 {
3563 return;
3564 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003565
Gunnar Mills68896202024-08-21 11:34:20 -05003566 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003567 {
Gunnar Mills68896202024-08-21 11:34:20 -05003568 if (systemName == "hypervisor")
3569 {
3570 handleHypervisorResetActionGet(asyncResp);
3571 return;
3572 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003573 }
3574
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003575 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003576 {
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003577 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3578 {
3579 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3580 systemName);
3581 return;
3582 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003583 }
3584
3585 asyncResp->res.addHeader(
3586 boost::beast::http::field::link,
3587 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3588
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003589 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3590 "/redfish/v1/Systems/{}/ResetActionInfo", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003591 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3592 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3593 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3594
Andrew Geissler33e1f122024-02-26 21:10:16 -06003595 // Look to see if system defines AllowedHostTransitions
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003596 getComputerSystemIndex(
3597 asyncResp, systemName,
3598 std::bind_front(getAllowedHostTransitions, asyncResp));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003599}
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003600
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303601/**
3602 * SystemResetActionInfo derived class for delivering Computer Systems
3603 * ResetType AllowableValues using ResetInfo schema.
3604 */
Ed Tanous100afe52023-06-07 13:30:46 -07003605inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303606{
Ed Tanous100afe52023-06-07 13:30:46 -07003607 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3608 .privileges(redfish::privileges::headComputerSystemCollection)
3609 .methods(boost::beast::http::verb::head)(
3610 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3611
3612 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3613 .privileges(redfish::privileges::getComputerSystemCollection)
3614 .methods(boost::beast::http::verb::get)(
3615 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3616
3617 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3618 .privileges(redfish::privileges::headComputerSystem)
3619 .methods(boost::beast::http::verb::head)(
3620 std::bind_front(handleComputerSystemHead, std::ref(app)));
3621
3622 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3623 .privileges(redfish::privileges::getComputerSystem)
3624 .methods(boost::beast::http::verb::get)(
3625 std::bind_front(handleComputerSystemGet, std::ref(app)));
3626
3627 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3628 .privileges(redfish::privileges::patchComputerSystem)
3629 .methods(boost::beast::http::verb::patch)(
3630 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3631
3632 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3633 .privileges(redfish::privileges::postComputerSystem)
3634 .methods(boost::beast::http::verb::post)(std::bind_front(
3635 handleComputerSystemResetActionPost, std::ref(app)));
3636
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003637 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003638 .privileges(redfish::privileges::headActionInfo)
3639 .methods(boost::beast::http::verb::head)(std::bind_front(
3640 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003641 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003642 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003643 .methods(boost::beast::http::verb::get)(std::bind_front(
3644 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003645}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003646} // namespace redfish