blob: 3123f068bd0c7050e492cbc45a098f5992f313bd [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"
Myung Baef7e62c12025-09-07 14:02:08 -050024#include "utils/asset_utils.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080025#include "utils/dbus_utils.hpp"
26#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050027#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080028#include "utils/sw_utils.hpp"
Oliver Brewkafc5ae942024-08-12 15:04:41 +020029#include "utils/systems_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070030#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080031
Ed Tanousd7857202025-01-28 15:32:26 -080032#include <asm-generic/errno.h>
33
Andrew Geisslerfc903b32023-05-31 14:15:42 -040034#include <boost/asio/error.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080035#include <boost/beast/http/field.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080036#include <boost/beast/http/verb.hpp>
George Liue99073f2022-12-09 11:06:16 +080037#include <boost/system/error_code.hpp>
Andrew Geissler33e1f122024-02-26 21:10:16 -060038#include <boost/system/linux_error.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070039#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080040#include <nlohmann/json.hpp>
41#include <sdbusplus/message/native_types.hpp>
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020042#include <sdbusplus/unpack_properties.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050043
George Liu7a1dbc42022-12-07 16:03:22 +080044#include <array>
Ed Tanousd7857202025-01-28 15:32:26 -080045#include <chrono>
46#include <cstddef>
47#include <cstdint>
48#include <functional>
Andrew Geissler33e1f122024-02-26 21:10:16 -060049#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080050#include <optional>
51#include <ratio>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060052#include <string>
George Liu7a1dbc42022-12-07 16:03:22 +080053#include <string_view>
Ed Tanousd7857202025-01-28 15:32:26 -080054#include <tuple>
Ed Tanous20fa6a22024-05-20 18:02:58 -070055#include <utility>
Chris Cain6b9ac4f2024-02-15 12:59:32 -060056#include <vector>
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020057
Ed Tanous1abe55e2018-09-05 08:30:59 -070058namespace redfish
59{
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +020060
Abhishek Patel5c3e9272021-06-24 10:11:33 -050061const static std::array<std::pair<std::string_view, std::string_view>, 2>
62 protocolToDBusForSystems{
63 {{"SSH", "obmc-console-ssh"}, {"IPMI", "phosphor-ipmi-net"}}};
64
Ninad Palsulecf0e0042023-05-18 17:18:09 -050065/*
66 * @brief Update "ProcessorSummary" "Count" based on Cpu PresenceState
67 *
Ed Tanousac106bf2023-06-07 09:24:59 -070068 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -050069 * @param[in] cpuPresenceState CPU present or not
70 *
71 * @return None.
72 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -040073inline void modifyCpuPresenceState(
74 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuPresent)
Ninad Palsulecf0e0042023-05-18 17:18:09 -050075{
Ed Tanous62598e32023-07-17 17:06:25 -070076 BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
Ninad Palsulecf0e0042023-05-18 17:18:09 -050077
78 if (isCpuPresent)
79 {
80 nlohmann::json& procCount =
Ed Tanousac106bf2023-06-07 09:24:59 -070081 asyncResp->res.jsonValue["ProcessorSummary"]["Count"];
Ninad Palsulecf0e0042023-05-18 17:18:09 -050082 auto* procCountPtr =
83 procCount.get_ptr<nlohmann::json::number_integer_t*>();
84 if (procCountPtr != nullptr)
85 {
86 // shouldn't be possible to be nullptr
87 *procCountPtr += 1;
88 }
89 }
90}
91
Ali Ahmed382d6472021-09-03 16:53:53 -050092inline void getProcessorProperties(
Ed Tanousac106bf2023-06-07 09:24:59 -070093 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ali Ahmed382d6472021-09-03 16:53:53 -050094 const std::vector<std::pair<std::string, dbus::utility::DbusVariantType>>&
95 properties)
Ali Ahmed03fbed92021-09-03 02:33:43 -050096{
Ed Tanous62598e32023-07-17 17:06:25 -070097 BMCWEB_LOG_DEBUG("Got {} Cpu properties.", properties.size());
Ali Ahmed03fbed92021-09-03 02:33:43 -050098
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +020099 // TODO: Get Model
100
101 const uint16_t* coreCount = nullptr;
102
103 const bool success = sdbusplus::unpackPropertiesNoThrow(
104 dbus_utils::UnpackErrorPrinter(), properties, "CoreCount", coreCount);
105
106 if (!success)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500107 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700108 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200109 return;
110 }
Ali Ahmed03fbed92021-09-03 02:33:43 -0500111
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200112 if (coreCount != nullptr)
113 {
114 nlohmann::json& coreCountJson =
Ed Tanousac106bf2023-06-07 09:24:59 -0700115 asyncResp->res.jsonValue["ProcessorSummary"]["CoreCount"];
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200116 uint64_t* coreCountJsonPtr = coreCountJson.get_ptr<uint64_t*>();
Ali Ahmed03fbed92021-09-03 02:33:43 -0500117
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200118 if (coreCountJsonPtr == nullptr)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500119 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +0200120 coreCountJson = *coreCount;
121 }
122 else
123 {
124 *coreCountJsonPtr += *coreCount;
Ali Ahmed03fbed92021-09-03 02:33:43 -0500125 }
126 }
127}
128
129/*
130 * @brief Get ProcessorSummary fields
131 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700132 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ali Ahmed03fbed92021-09-03 02:33:43 -0500133 * @param[in] service dbus service for Cpu Information
134 * @param[in] path dbus path for Cpu
135 *
136 * @return None.
137 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500138inline void getProcessorSummary(
139 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
140 const std::string& service, const std::string& path)
Ali Ahmed03fbed92021-09-03 02:33:43 -0500141{
Ed Tanousac106bf2023-06-07 09:24:59 -0700142 auto getCpuPresenceState = [asyncResp](const boost::system::error_code& ec3,
143 const bool cpuPresenceCheck) {
Ali Ahmed382d6472021-09-03 16:53:53 -0500144 if (ec3)
145 {
Ed Tanous62598e32023-07-17 17:06:25 -0700146 BMCWEB_LOG_ERROR("DBUS response error {}", ec3);
Ali Ahmed382d6472021-09-03 16:53:53 -0500147 return;
148 }
Ed Tanousac106bf2023-06-07 09:24:59 -0700149 modifyCpuPresenceState(asyncResp, cpuPresenceCheck);
Ali Ahmed382d6472021-09-03 16:53:53 -0500150 };
151
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500152 // Get the Presence of CPU
Ed Tanousdeae6a72024-11-11 21:58:57 -0800153 dbus::utility::getProperty<bool>(*crow::connections::systemBus, service,
154 path, "xyz.openbmc_project.Inventory.Item",
155 "Present", std::move(getCpuPresenceState));
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500156
Ed Tanousdeae6a72024-11-11 21:58:57 -0800157 dbus::utility::getAllProperties(
158 service, path, "xyz.openbmc_project.Inventory.Item.Cpu",
Ed Tanousac106bf2023-06-07 09:24:59 -0700159 [asyncResp, service,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800160 path](const boost::system::error_code& ec2,
Ed Tanousb9d36b42022-02-26 21:42:46 -0800161 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400162 if (ec2)
163 {
164 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
165 messages::internalError(asyncResp->res);
166 return;
167 }
168 getProcessorProperties(asyncResp, properties);
169 });
Ali Ahmed03fbed92021-09-03 02:33:43 -0500170}
171
Alpana Kumari57e8c9b2019-04-15 01:09:36 -0500172/*
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500173 * @brief processMemoryProperties fields
174 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700175 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500176 * @param[in] DBUS properties for memory
177 *
178 * @return None.
179 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500180inline void processMemoryProperties(
181 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
182 const dbus::utility::DBusPropertiesMap& properties)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500183{
Ed Tanous62598e32023-07-17 17:06:25 -0700184 BMCWEB_LOG_DEBUG("Got {} Dimm properties.", properties.size());
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500185
186 if (properties.empty())
187 {
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500188 return;
189 }
190
191 const size_t* memorySizeInKB = nullptr;
192
193 const bool success = sdbusplus::unpackPropertiesNoThrow(
194 dbus_utils::UnpackErrorPrinter(), properties, "MemorySizeInKB",
195 memorySizeInKB);
196
197 if (!success)
198 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700199 messages::internalError(asyncResp->res);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500200 return;
201 }
202
203 if (memorySizeInKB != nullptr)
204 {
205 nlohmann::json& totalMemory =
Ed Tanousac106bf2023-06-07 09:24:59 -0700206 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"];
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500207 const double* preValue = totalMemory.get_ptr<const double*>();
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500208 if (preValue == nullptr)
209 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700210 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500211 static_cast<double>(*memorySizeInKB) / (1024 * 1024);
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500212 }
213 else
214 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700215 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -0500216 static_cast<double>(*memorySizeInKB) / (1024 * 1024) +
217 *preValue;
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500218 }
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500219 }
220}
221
222/*
223 * @brief Get getMemorySummary fields
224 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700225 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500226 * @param[in] service dbus service for memory Information
227 * @param[in] path dbus path for memory
228 *
229 * @return None.
230 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500231inline void getMemorySummary(
232 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
233 const std::string& service, const std::string& path)
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500234{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800235 dbus::utility::getAllProperties(
236 service, path, "xyz.openbmc_project.Inventory.Item.Dimm",
Ed Tanousac106bf2023-06-07 09:24:59 -0700237 [asyncResp, service,
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500238 path](const boost::system::error_code& ec2,
239 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400240 if (ec2)
241 {
242 BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
243 messages::internalError(asyncResp->res);
244 return;
245 }
246 processMemoryProperties(asyncResp, properties);
247 });
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500248}
249
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500250inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
251 const boost::system::error_code& ec,
252 const dbus::utility::DBusPropertiesMap& properties)
253{
254 if (ec)
255 {
256 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
257 messages::internalError(asyncResp->res);
258 return;
259 }
260 BMCWEB_LOG_DEBUG("Got {} UUID properties.", properties.size());
261
262 const std::string* uUID = nullptr;
263
264 const bool success = sdbusplus::unpackPropertiesNoThrow(
265 dbus_utils::UnpackErrorPrinter(), properties, "UUID", uUID);
266
267 if (!success)
268 {
269 messages::internalError(asyncResp->res);
270 return;
271 }
272
273 if (uUID != nullptr)
274 {
275 std::string valueStr = *uUID;
276 if (valueStr.size() == 32)
277 {
278 valueStr.insert(8, 1, '-');
279 valueStr.insert(13, 1, '-');
280 valueStr.insert(18, 1, '-');
281 valueStr.insert(23, 1, '-');
282 }
283 BMCWEB_LOG_DEBUG("UUID = {}", valueStr);
284 asyncResp->res.jsonValue["UUID"] = valueStr;
285 }
286}
287
Patrick Williams504af5a2025-02-03 14:29:03 -0500288inline void afterGetInventory(
289 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
290 const boost::system::error_code& ec,
291 const dbus::utility::DBusPropertiesMap& propertiesList)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500292{
293 if (ec)
294 {
295 // doesn't have to include this
296 // interface
297 return;
298 }
299 BMCWEB_LOG_DEBUG("Got {} properties for system", propertiesList.size());
300
Myung Baef7e62c12025-09-07 14:02:08 -0500301 asset_utils::extractAssetInfo(asyncResp, ""_json_pointer, propertiesList,
302 false);
303
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500304 const std::string* subModel = nullptr;
305
306 const bool success = sdbusplus::unpackPropertiesNoThrow(
Myung Baef7e62c12025-09-07 14:02:08 -0500307 dbus_utils::UnpackErrorPrinter(), propertiesList, "SubModel", subModel);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500308
309 if (!success)
310 {
311 messages::internalError(asyncResp->res);
312 return;
313 }
314
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500315 if (subModel != nullptr)
316 {
317 asyncResp->res.jsonValue["SubModel"] = *subModel;
318 }
319
320 // Grab the bios version
321 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
322 "BiosVersion", false);
323}
324
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400325inline void afterGetAssetTag(
326 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
327 const boost::system::error_code& ec, const std::string& value)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500328{
329 if (ec)
330 {
331 // doesn't have to include this
332 // interface
333 return;
334 }
335
336 asyncResp->res.jsonValue["AssetTag"] = value;
337}
338
339inline void afterSystemGetSubTree(
340 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500341 const boost::system::error_code& ec,
342 const dbus::utility::MapperGetSubTreeResponse& subtree)
343{
344 if (ec)
345 {
346 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
347 messages::internalError(asyncResp->res);
348 return;
349 }
350 // Iterate over all retrieved ObjectPaths.
351 for (const std::pair<
352 std::string,
353 std::vector<std::pair<std::string, std::vector<std::string>>>>&
354 object : subtree)
355 {
356 const std::string& path = object.first;
357 BMCWEB_LOG_DEBUG("Got path: {}", path);
358 const std::vector<std::pair<std::string, std::vector<std::string>>>&
359 connectionNames = object.second;
360 if (connectionNames.empty())
361 {
362 continue;
363 }
364
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500365 // This is not system, so check if it's cpu, dimm, UUID or
366 // BiosVer
367 for (const auto& connection : connectionNames)
368 {
369 for (const auto& interfaceName : connection.second)
370 {
371 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
372 {
373 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
374
375 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500376 }
377 else if (interfaceName ==
378 "xyz.openbmc_project.Inventory.Item.Cpu")
379 {
380 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
381
382 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500383 }
384 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
385 {
386 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
387
Ed Tanousdeae6a72024-11-11 21:58:57 -0800388 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500389 *crow::connections::systemBus, connection.first, path,
390 "xyz.openbmc_project.Common.UUID",
391 [asyncResp](const boost::system::error_code& ec3,
392 const dbus::utility::DBusPropertiesMap&
393 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400394 afterGetUUID(asyncResp, ec3, properties);
395 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500396 }
397 else if (interfaceName ==
398 "xyz.openbmc_project.Inventory.Item.System")
399 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800400 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500401 *crow::connections::systemBus, connection.first, path,
402 "xyz.openbmc_project.Inventory.Decorator.Asset",
403 [asyncResp](const boost::system::error_code& ec3,
404 const dbus::utility::DBusPropertiesMap&
405 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400406 afterGetInventory(asyncResp, ec3, properties);
407 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500408
Ed Tanousdeae6a72024-11-11 21:58:57 -0800409 dbus::utility::getProperty<std::string>(
410 connection.first, path,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500411 "xyz.openbmc_project.Inventory.Decorator."
412 "AssetTag",
413 "AssetTag",
414 std::bind_front(afterGetAssetTag, asyncResp));
415 }
416 }
417 }
418 }
419}
420
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500421/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700422 * @brief Retrieves computer system properties over dbus
423 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700424 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700425 *
426 * @return None.
427 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500428inline void getComputerSystem(
429 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700430{
Ed Tanous62598e32023-07-17 17:06:25 -0700431 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800432 constexpr std::array<std::string_view, 5> interfaces = {
433 "xyz.openbmc_project.Inventory.Decorator.Asset",
434 "xyz.openbmc_project.Inventory.Item.Cpu",
435 "xyz.openbmc_project.Inventory.Item.Dimm",
436 "xyz.openbmc_project.Inventory.Item.System",
437 "xyz.openbmc_project.Common.UUID",
438 };
439 dbus::utility::getSubTree(
440 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500441 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700442}
443
444/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700445 * @brief Retrieves host state properties over dbus
446 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700447 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200448 * @param[in] computerSystemIndex Index associated with the requested system
Ed Tanous6c34de42018-08-29 13:37:36 -0700449 *
450 * @return None.
451 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200452inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
453 const uint64_t computerSystemIndex)
Ed Tanous6c34de42018-08-29 13:37:36 -0700454{
Ed Tanous62598e32023-07-17 17:06:25 -0700455 BMCWEB_LOG_DEBUG("Get host information.");
Ed Tanousa52f1d52025-08-26 16:34:24 -0700456 sdbusplus::message::object_path path =
457 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800458 dbus::utility::getProperty<std::string>(
Ed Tanousa52f1d52025-08-26 16:34:24 -0700459 getHostStateServiceName(computerSystemIndex), path,
Ed Tanousdeae6a72024-11-11 21:58:57 -0800460 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700461 [asyncResp](const boost::system::error_code& ec,
462 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400463 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700464 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400465 if (ec == boost::system::errc::host_unreachable)
466 {
467 // Service not available, no error, just don't return
468 // host state info
469 BMCWEB_LOG_DEBUG("Service not available {}", ec);
470 return;
471 }
472 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
473 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700474 return;
475 }
Ed Tanous66173382018-08-15 18:20:59 -0700476
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400477 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
478 // Verify Host State
479 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
480 {
481 asyncResp->res.jsonValue["PowerState"] =
482 resource::PowerState::On;
483 asyncResp->res.jsonValue["Status"]["State"] =
484 resource::State::Enabled;
485 }
486 else if (hostState ==
487 "xyz.openbmc_project.State.Host.HostState.Quiesced")
488 {
489 asyncResp->res.jsonValue["PowerState"] =
490 resource::PowerState::On;
491 asyncResp->res.jsonValue["Status"]["State"] =
492 resource::State::Quiesced;
493 }
494 else if (hostState ==
495 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
496 {
497 asyncResp->res.jsonValue["PowerState"] =
498 resource::PowerState::On;
499 asyncResp->res.jsonValue["Status"]["State"] =
500 resource::State::InTest;
501 }
502 else if (
503 hostState ==
504 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
505 {
506 asyncResp->res.jsonValue["PowerState"] =
507 resource::PowerState::PoweringOn;
508 asyncResp->res.jsonValue["Status"]["State"] =
509 resource::State::Starting;
510 }
511 else if (
512 hostState ==
513 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
514 {
515 asyncResp->res.jsonValue["PowerState"] =
516 resource::PowerState::PoweringOff;
517 asyncResp->res.jsonValue["Status"]["State"] =
518 resource::State::Disabled;
519 }
520 else
521 {
522 asyncResp->res.jsonValue["PowerState"] =
523 resource::PowerState::Off;
524 asyncResp->res.jsonValue["Status"]["State"] =
525 resource::State::Disabled;
526 }
527 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700528}
529
530/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500531 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530532 *
533 * @param[in] dbusSource The boot source in DBUS speak.
534 *
535 * @return Returns as a string, the boot source in Redfish terms. If translation
536 * cannot be done, returns an empty string.
537 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000538inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530539{
540 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
541 {
542 return "None";
543 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700544 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530545 {
546 return "Hdd";
547 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700548 if (dbusSource ==
549 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530550 {
551 return "Cd";
552 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700553 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530554 {
555 return "Pxe";
556 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700557 if (dbusSource ==
558 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700559 {
560 return "Usb";
561 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700562 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530563}
564
565/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300566 * @brief Translates boot type DBUS property value to redfish.
567 *
568 * @param[in] dbusType The boot type in DBUS speak.
569 *
570 * @return Returns as a string, the boot type in Redfish terms. If translation
571 * cannot be done, returns an empty string.
572 */
573inline std::string dbusToRfBootType(const std::string& dbusType)
574{
575 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
576 {
577 return "Legacy";
578 }
579 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
580 {
581 return "UEFI";
582 }
583 return "";
584}
585
586/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500587 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530588 *
589 * @param[in] dbusMode The boot mode in DBUS speak.
590 *
591 * @return Returns as a string, the boot mode in Redfish terms. If translation
592 * cannot be done, returns an empty string.
593 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000594inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530595{
596 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
597 {
598 return "None";
599 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700600 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530601 {
602 return "Diags";
603 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700604 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530605 {
606 return "BiosSetup";
607 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700608 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530609}
610
611/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600612 * @brief Translates boot progress DBUS property value to redfish.
613 *
614 * @param[in] dbusBootProgress The boot progress in DBUS speak.
615 *
616 * @return Returns as a string, the boot progress in Redfish terms. If
617 * translation cannot be done, returns "None".
618 */
619inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
620{
621 // Now convert the D-Bus BootProgress to the appropriate Redfish
622 // enum
623 std::string rfBpLastState = "None";
624 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
625 "ProgressStages.Unspecified")
626 {
627 rfBpLastState = "None";
628 }
629 else if (dbusBootProgress ==
630 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
631 "PrimaryProcInit")
632 {
633 rfBpLastState = "PrimaryProcessorInitializationStarted";
634 }
635 else if (dbusBootProgress ==
636 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
637 "BusInit")
638 {
639 rfBpLastState = "BusInitializationStarted";
640 }
641 else if (dbusBootProgress ==
642 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
643 "MemoryInit")
644 {
645 rfBpLastState = "MemoryInitializationStarted";
646 }
647 else if (dbusBootProgress ==
648 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
649 "SecondaryProcInit")
650 {
651 rfBpLastState = "SecondaryProcessorInitializationStarted";
652 }
653 else if (dbusBootProgress ==
654 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
655 "PCIInit")
656 {
657 rfBpLastState = "PCIResourceConfigStarted";
658 }
659 else if (dbusBootProgress ==
660 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
661 "SystemSetup")
662 {
663 rfBpLastState = "SetupEntered";
664 }
665 else if (dbusBootProgress ==
666 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
667 "SystemInitComplete")
668 {
669 rfBpLastState = "SystemHardwareInitializationComplete";
670 }
671 else if (dbusBootProgress ==
672 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
673 "OSStart")
674 {
675 rfBpLastState = "OSBootStarted";
676 }
677 else if (dbusBootProgress ==
678 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
679 "OSRunning")
680 {
681 rfBpLastState = "OSRunning";
682 }
683 else
684 {
Ed Tanous62598e32023-07-17 17:06:25 -0700685 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600686 // Just return the default
687 }
688 return rfBpLastState;
689}
690
691/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500692 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530693 *
694 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700695 * @param[out] bootSource The DBus source
696 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530697 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700698 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530699 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400700inline int assignBootParameters(
701 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
702 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530703{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300704 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
705 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700706
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530707 if (rfSource == "None")
708 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700709 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530710 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700711 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530712 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700713 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
714 }
715 else if (rfSource == "Hdd")
716 {
717 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
718 }
719 else if (rfSource == "Diags")
720 {
721 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
722 }
723 else if (rfSource == "Cd")
724 {
725 bootSource =
726 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
727 }
728 else if (rfSource == "BiosSetup")
729 {
730 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530731 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700732 else if (rfSource == "Usb")
733 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700734 bootSource =
735 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700736 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530737 else
738 {
Ed Tanous62598e32023-07-17 17:06:25 -0700739 BMCWEB_LOG_DEBUG(
740 "Invalid property value for BootSourceOverrideTarget: {}",
741 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700742 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700743 "BootSourceTargetOverride");
744 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530745 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700746 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530747}
Ali Ahmed19817712021-06-29 17:01:52 -0500748
Andrew Geissler978b8802020-11-19 13:36:40 -0600749/**
750 * @brief Retrieves boot progress of the system
751 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700752 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200753 * @param[in] computerSystemIndex Index associated with the requested system
Andrew Geissler978b8802020-11-19 13:36:40 -0600754 *
755 * @return None.
756 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200757inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
758 const uint64_t computerSystemIndex)
Andrew Geissler978b8802020-11-19 13:36:40 -0600759{
Ed Tanousa52f1d52025-08-26 16:34:24 -0700760 sdbusplus::message::object_path path =
761 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800762 dbus::utility::getProperty<std::string>(
Ed Tanousa52f1d52025-08-26 16:34:24 -0700763 getHostStateServiceName(computerSystemIndex), path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700764 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousa52f1d52025-08-26 16:34:24 -0700765 [asyncResp](const boost::system::error_code ec,
Ed Tanousac106bf2023-06-07 09:24:59 -0700766 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400767 if (ec)
768 {
769 // BootProgress is an optional object so just do nothing if
770 // not found
771 return;
772 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600773
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400774 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600775
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400776 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
777 dbusToRfBootProgress(bootProgressStr);
778 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600779}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530780
781/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000782 * @brief Retrieves boot progress Last Update of the system
783 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700784 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200785 * @param[in] computerSystemIndex Index associated with the requested system
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000786 *
787 * @return None.
788 */
789inline void getBootProgressLastStateTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200790 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
791 const uint64_t computerSystemIndex)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000792{
Ed Tanousa52f1d52025-08-26 16:34:24 -0700793 sdbusplus::message::object_path path =
794 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -0800795 dbus::utility::getProperty<uint64_t>(
Ed Tanousa52f1d52025-08-26 16:34:24 -0700796 getHostStateServiceName(computerSystemIndex), path,
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000797 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700798 [asyncResp](const boost::system::error_code& ec,
799 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400800 if (ec)
801 {
802 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
803 return;
804 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000805
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400806 // BootProgressLastUpdate is the last time the BootProgress property
807 // was updated. The time is the Epoch time, number of microseconds
808 // since 1 Jan 1970 00::00::00 UTC."
809 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
810 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000811
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400812 // Convert to ISO 8601 standard
813 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
814 redfish::time_utils::getDateTimeUintUs(lastStateTime);
815 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000816}
817
818/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300819 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300820 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700821 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200822 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300823 *
824 * @return None.
825 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500826inline void getBootOverrideType(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200827 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
828 const uint64_t computerSystemIndex)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300829{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200830 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
831 std::to_string(computerSystemIndex));
832 path /= "boot";
833
Ed Tanousdeae6a72024-11-11 21:58:57 -0800834 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200835 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700836 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700837 [asyncResp](const boost::system::error_code& ec,
838 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400839 if (ec)
840 {
841 // not an error, don't have to have the interface
842 return;
843 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300844
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400845 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300846
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400847 asyncResp->res
848 .jsonValue["Boot"]
849 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
850 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300851
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400852 auto rfType = dbusToRfBootType(bootType);
853 if (rfType.empty())
854 {
855 messages::internalError(asyncResp->res);
856 return;
857 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300858
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400859 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
860 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300861}
862
863/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300864 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530865 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700866 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200867 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530868 *
869 * @return None.
870 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500871inline void getBootOverrideMode(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200872 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
873 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530874{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200875 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
876 std::to_string(computerSystemIndex));
877 path /= "boot";
Ed Tanousdeae6a72024-11-11 21:58:57 -0800878 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200879 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700880 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700881 [asyncResp](const boost::system::error_code& ec,
882 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400883 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530884 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400885 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
886 messages::internalError(asyncResp->res);
887 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530888 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400889
890 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
891
892 nlohmann::json::array_t allowed;
893 allowed.emplace_back("None");
894 allowed.emplace_back("Pxe");
895 allowed.emplace_back("Hdd");
896 allowed.emplace_back("Cd");
897 allowed.emplace_back("Diags");
898 allowed.emplace_back("BiosSetup");
899 allowed.emplace_back("Usb");
900
901 asyncResp->res
902 .jsonValue["Boot"]
903 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
904 std::move(allowed);
905 if (bootModeStr !=
906 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
907 {
908 auto rfMode = dbusToRfBootMode(bootModeStr);
909 if (!rfMode.empty())
910 {
911 asyncResp->res
912 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
913 }
914 }
915 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530916}
917
918/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300919 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530920 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700921 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200922 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530923 *
924 * @return None.
925 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500926inline void getBootOverrideSource(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200927 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
928 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530929{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200930 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
931 std::to_string(computerSystemIndex));
932 path /= "boot";
933
Ed Tanousdeae6a72024-11-11 21:58:57 -0800934 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200935 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700936 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200937 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
938 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400939 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +0000940 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800941 // Service not available, no error, just don't return
942 // Boot Override Source information
943 if (ec.value() != EBADR &&
944 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400945 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800946 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
947 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400948 }
Nan Zhou5ef735c2022-06-22 05:24:21 +0000949 return;
950 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530951
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400952 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530953
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400954 auto rfSource = dbusToRfBootSource(bootSourceStr);
955 if (!rfSource.empty())
956 {
957 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
958 rfSource;
959 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300960
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400961 // Get BootMode as BootSourceOverrideTarget is constructed
962 // from both BootSource and BootMode
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200963 getBootOverrideMode(asyncResp, computerSystemIndex);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400964 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530965}
966
967/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300968 * @brief This functions abstracts all the logic behind getting a
969 * "BootSourceOverrideEnabled" property from an overall boot override enable
970 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530971 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700972 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200973 * @param[in] computerSystemIndex Index associated with the requested system
974 * @param[in] bootOverrideEnableSetting
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530975 *
976 * @return None.
977 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530978
Ed Tanousac106bf2023-06-07 09:24:59 -0700979inline void processBootOverrideEnable(
980 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200981 const uint64_t computerSystemIndex, const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300982{
983 if (!bootOverrideEnableSetting)
984 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700985 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
986 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300987 return;
988 }
989
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200990 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
991 std::to_string(computerSystemIndex));
992 path /= "boot";
993 path /= "one_time";
994
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300995 // If boot source override is enabled, we need to check 'one_time'
996 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -0800997 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200998 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700999 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001000 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001001 if (ec)
1002 {
1003 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1004 messages::internalError(asyncResp->res);
1005 return;
1006 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301007
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001008 if (oneTimeSetting)
1009 {
1010 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1011 "Once";
1012 }
1013 else
1014 {
1015 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1016 "Continuous";
1017 }
1018 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301019}
1020
1021/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001022 * @brief Retrieves boot override enable over DBUS
1023 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001024 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001025 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001026 *
1027 * @return None.
1028 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001029inline void getBootOverrideEnable(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001030 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1031 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001032{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001033 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1034 std::to_string(computerSystemIndex));
1035 path /= "boot";
1036
Ed Tanousdeae6a72024-11-11 21:58:57 -08001037 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001038 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001039 "xyz.openbmc_project.Object.Enable", "Enabled",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001040 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1041 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001042 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001043 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001044 // Service not available, no error, just don't return
1045 // Boot Override Enable information
1046 if (ec.value() != EBADR &&
1047 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001048 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001049 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1050 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001051 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001052 return;
1053 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001054
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001055 processBootOverrideEnable(asyncResp, computerSystemIndex,
1056 bootOverrideEnable);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001057 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001058}
1059
1060/**
1061 * @brief Retrieves boot source override properties
1062 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001063 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001064 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001065 *
1066 * @return None.
1067 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001068inline void getBootProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001069 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1070 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001071{
Ed Tanous62598e32023-07-17 17:06:25 -07001072 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001073
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001074 getBootOverrideSource(asyncResp, computerSystemIndex);
1075 getBootOverrideType(asyncResp, computerSystemIndex);
1076 getBootOverrideEnable(asyncResp, computerSystemIndex);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001077}
1078
1079/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001080 * @brief Retrieves the Last Reset Time
1081 *
1082 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1083 * and power off. Even though this is the "system" Redfish object look at the
1084 * chassis D-Bus interface for the LastStateChangeTime since this has the
1085 * last power operation time.
1086 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001087 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001088 *
1089 * @return None.
1090 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001091inline void getLastResetTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001092 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1093 const uint64_t computerSystemIndex)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001094{
Ed Tanous62598e32023-07-17 17:06:25 -07001095 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Ed Tanousa52f1d52025-08-26 16:34:24 -07001096 sdbusplus::message::object_path path =
1097 getChassisStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -08001098 dbus::utility::getProperty<uint64_t>(
Ed Tanousa52f1d52025-08-26 16:34:24 -07001099 getChassisStateServiceName(computerSystemIndex), path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001100 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001101 [asyncResp](const boost::system::error_code& ec,
1102 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001103 if (ec)
1104 {
1105 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1106 return;
1107 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001108
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001109 // LastStateChangeTime is epoch time, in milliseconds
1110 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1111 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001112
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001113 // Convert to ISO 8601 standard
1114 asyncResp->res.jsonValue["LastResetTime"] =
1115 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1116 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001117}
1118
1119/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001120 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1121 *
1122 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1123 * corresponding property "AttemptsLeft" that keeps track of the amount of
1124 * automatic retry attempts left are hosted in phosphor-state-manager through
1125 * dbus.
1126 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001127 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001128 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001129 *
1130 * @return None.
1131 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001132inline void getAutomaticRebootAttempts(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001133 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1134 const uint64_t computerSystemIndex)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001135{
Ed Tanous62598e32023-07-17 17:06:25 -07001136 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Ed Tanousa52f1d52025-08-26 16:34:24 -07001137 sdbusplus::message::object_path path =
1138 getHostStateObjectPath(computerSystemIndex);
Ed Tanousdeae6a72024-11-11 21:58:57 -08001139 dbus::utility::getAllProperties(
Ed Tanousa52f1d52025-08-26 16:34:24 -07001140 getHostStateServiceName(computerSystemIndex), path,
Corey Hardesty797d5da2022-04-26 17:54:52 +08001141 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001142 [asyncResp{asyncResp}](
1143 const boost::system::error_code& ec,
1144 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001145 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001146 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301147 if (ec.value() != EBADR &&
1148 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001149 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301150 // Service not available, no error, just don't return
1151 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001152 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1153 messages::internalError(asyncResp->res);
1154 }
1155 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001156 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001157
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001158 const uint32_t* attemptsLeft = nullptr;
1159 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001160
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001161 const bool success = sdbusplus::unpackPropertiesNoThrow(
1162 dbus_utils::UnpackErrorPrinter(), propertiesList,
1163 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001164
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001165 if (!success)
1166 {
1167 messages::internalError(asyncResp->res);
1168 return;
1169 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001170
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001171 if (attemptsLeft != nullptr)
1172 {
1173 asyncResp->res
1174 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1175 *attemptsLeft;
1176 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001177
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001178 if (retryAttempts != nullptr)
1179 {
1180 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1181 *retryAttempts;
1182 }
1183 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001184}
1185
1186/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001187 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1188 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001189 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001190 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001191 *
1192 * @return None.
1193 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001194inline void getAutomaticRetryPolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001195 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1196 const uint64_t computerSystemIndex)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001197{
Ed Tanous62598e32023-07-17 17:06:25 -07001198 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001199
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001200 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1201 std::to_string(computerSystemIndex));
1202 path /= "auto_reboot";
1203
Ed Tanousdeae6a72024-11-11 21:58:57 -08001204 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001205 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001206 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001207 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1208 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001209 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001210 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301211 // Service not available, no error, just don't return
1212 // AutoReboot information
1213 if (ec.value() != EBADR &&
1214 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001215 {
1216 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1217 messages::internalError(asyncResp->res);
1218 }
1219 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001220 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001221
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001222 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1223 if (autoRebootEnabled)
1224 {
1225 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1226 "RetryAttempts";
1227 }
1228 else
1229 {
1230 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1231 "Disabled";
1232 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001233 getAutomaticRebootAttempts(asyncResp, computerSystemIndex);
Gunnar Mills69f35302020-05-17 16:06:31 -05001234
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001235 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1236 // and RetryAttempts. OpenBMC only supports Disabled and
1237 // RetryAttempts.
1238 nlohmann::json::array_t allowed;
1239 allowed.emplace_back("Disabled");
1240 allowed.emplace_back("RetryAttempts");
1241 asyncResp->res
1242 .jsonValue["Boot"]
1243 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1244 std::move(allowed);
1245 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001246}
1247
1248/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001249 * @brief Sets RetryAttempts
1250 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001251 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001252 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001253 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1254 *
1255 *@return None.
1256 */
1257
Ed Tanousac106bf2023-06-07 09:24:59 -07001258inline void setAutomaticRetryAttempts(
1259 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001260 const uint64_t computerSystemIndex, const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001261{
Ed Tanous62598e32023-07-17 17:06:25 -07001262 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001263
1264 setDbusProperty(asyncResp, "Boot/AutomaticRetryAttempts",
1265 getHostStateServiceName(computerSystemIndex),
1266 getHostStateObjectPath(computerSystemIndex),
1267 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1268 "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001269}
1270
Ed Tanous8d69c662023-06-21 10:29:06 -07001271inline computer_system::PowerRestorePolicyTypes
1272 redfishPowerRestorePolicyFromDbus(std::string_view value)
1273{
1274 if (value ==
1275 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1276 {
1277 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1278 }
1279 if (value ==
1280 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1281 {
1282 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1283 }
1284 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001285 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001286 {
1287 return computer_system::PowerRestorePolicyTypes::LastState;
1288 }
1289 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1290 {
1291 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1292 }
1293 return computer_system::PowerRestorePolicyTypes::Invalid;
1294}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001295/**
George Liuc6a620f2020-04-10 17:18:11 +08001296 * @brief Retrieves power restore policy over DBUS.
1297 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001298 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001299 *
1300 * @return None.
1301 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001302inline void getPowerRestorePolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001303 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1304 const uint64_t computerSystemIndex)
George Liuc6a620f2020-04-10 17:18:11 +08001305{
Ed Tanous62598e32023-07-17 17:06:25 -07001306 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001307
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001308 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1309 std::to_string(computerSystemIndex));
1310 path /= "power_restore_policy";
1311
Ed Tanousdeae6a72024-11-11 21:58:57 -08001312 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001313 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001314 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001315 [asyncResp](const boost::system::error_code& ec,
1316 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001317 if (ec)
1318 {
1319 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1320 return;
1321 }
1322 computer_system::PowerRestorePolicyTypes restore =
1323 redfishPowerRestorePolicyFromDbus(policy);
1324 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1325 {
1326 messages::internalError(asyncResp->res);
1327 return;
1328 }
George Liuc6a620f2020-04-10 17:18:11 +08001329
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001330 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1331 });
George Liuc6a620f2020-04-10 17:18:11 +08001332}
1333
1334/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001335 * @brief Stop Boot On Fault over DBUS.
1336 *
1337 * @param[in] asyncResp Shared pointer for generating response message.
1338 *
1339 * @return None.
1340 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001341inline void getStopBootOnFault(
1342 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001343{
Ed Tanous62598e32023-07-17 17:06:25 -07001344 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001345
Ed Tanousdeae6a72024-11-11 21:58:57 -08001346 dbus::utility::getProperty<bool>(
1347 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001348 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1349 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001350 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001351 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301352 // Service not available, no error, just don't return
1353 // StopBootOnFault information
1354 if (ec.value() != EBADR ||
1355 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001356 {
1357 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1358 messages::internalError(asyncResp->res);
1359 }
1360 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001361 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001362
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001363 if (value)
1364 {
1365 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1366 computer_system::StopBootOnFault::AnyFault;
1367 }
1368 else
1369 {
1370 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1371 computer_system::StopBootOnFault::Never;
1372 }
1373 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001374}
1375
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001376inline void getTrustedModuleRequiredToBootCallback(
1377 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1378 const uint64_t computerSystemIndex, const boost::system::error_code& ec,
1379 const dbus::utility::MapperGetSubTreeResponse& subtree)
1380{
1381 if (ec)
1382 {
1383 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}", ec);
1384 // This is an optional D-Bus object so just return if
1385 // error occurs
1386 return;
1387 }
1388 if (subtree.empty())
1389 {
1390 // As noted above, this is an optional interface so just return
1391 // if there is no instance found
1392 return;
1393 }
1394
1395 std::string path;
1396 std::string service;
1397
1398 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1399 {
1400 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1401 subtree, path, service))
1402 {
1403 return;
1404 }
1405 }
1406 else
1407 {
1408 // Make sure the Dbus response map has a service and objectPath
1409 // field
1410 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1411 {
1412 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1413 messages::internalError(asyncResp->res);
1414 return;
1415 }
1416
1417 path = subtree[0].first;
1418 service = subtree[0].second.begin()->first;
1419 }
1420
1421 BMCWEB_LOG_DEBUG("found tpm service {}", service);
1422 BMCWEB_LOG_DEBUG("found tpm path {}", path);
1423
1424 // Valid TPM Enable object found, now reading the current value
1425 dbus::utility::getProperty<bool>(
1426 service, path, "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1427 [asyncResp](const boost::system::error_code& ec2, bool tpmRequired) {
1428 if (ec2)
1429 {
1430 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
1431 ec2);
1432 messages::internalError(asyncResp->res);
1433 return;
1434 }
1435
1436 if (tpmRequired)
1437 {
1438 asyncResp->res
1439 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1440 "Required";
1441 }
1442 else
1443 {
1444 asyncResp->res
1445 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1446 "Disabled";
1447 }
1448 });
1449}
1450
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001451/**
Ali Ahmed19817712021-06-29 17:01:52 -05001452 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1453 * TPM is required for booting the host.
1454 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001455 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001456 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed19817712021-06-29 17:01:52 -05001457 *
1458 * @return None.
1459 */
1460inline void getTrustedModuleRequiredToBoot(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001461 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1462 const uint64_t computerSystemIndex)
Ali Ahmed19817712021-06-29 17:01:52 -05001463{
Ed Tanous62598e32023-07-17 17:06:25 -07001464 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001465 constexpr std::array<std::string_view, 1> interfaces = {
1466 "xyz.openbmc_project.Control.TPM.Policy"};
1467 dbus::utility::getSubTree(
1468 "/", 0, interfaces,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001469 std::bind_front(getTrustedModuleRequiredToBootCallback, asyncResp,
1470 computerSystemIndex));
Ali Ahmed19817712021-06-29 17:01:52 -05001471}
1472
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001473inline void setTrustedModuleRequiredToBootCallback(
1474 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1475 const uint64_t computerSystemIndex, const bool tpmRequired,
1476 const boost::system::error_code& ec,
1477 const dbus::utility::MapperGetSubTreeResponse& subtree)
1478{
1479 if (ec)
1480 {
1481 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}", ec);
1482 messages::internalError(asyncResp->res);
1483 return;
1484 }
1485 if (subtree.empty())
1486 {
1487 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
1488 "TrustedModuleRequiredToBoot");
1489 return;
1490 }
1491
1492 std::string path;
1493 std::string serv;
1494
1495 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1496 {
1497 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1498 subtree, path, serv))
1499 {
1500 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1501 messages::internalError(asyncResp->res);
1502 return;
1503 }
1504 }
1505 else
1506 {
1507 // Make sure the Dbus response map has a service and objectPath
1508 // field
1509 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1510 {
1511 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1512 messages::internalError(asyncResp->res);
1513 return;
1514 }
1515
1516 path = subtree[0].first;
1517 serv = subtree[0].second.begin()->first;
1518 }
1519
1520 if (serv.empty())
1521 {
1522 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1523 messages::internalError(asyncResp->res);
1524 return;
1525 }
1526
1527 // Valid TPM Enable object found, now setting the value
1528 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv, path,
1529 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1530 tpmRequired);
1531}
1532
Ali Ahmed19817712021-06-29 17:01:52 -05001533/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001534 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1535 * TPM is required for booting the host.
1536 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001537 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001538 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001539 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1540 *
1541 * @return None.
1542 */
1543inline void setTrustedModuleRequiredToBoot(
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001544 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1545 const uint64_t computerSystemIndex, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001546{
Ed Tanous62598e32023-07-17 17:06:25 -07001547 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001548 constexpr std::array<std::string_view, 1> interfaces = {
1549 "xyz.openbmc_project.Control.TPM.Policy"};
1550 dbus::utility::getSubTree(
1551 "/", 0, interfaces,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001552 std::bind_front(setTrustedModuleRequiredToBootCallback, asyncResp,
1553 computerSystemIndex, tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001554}
1555
1556/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301557 * @brief Sets boot properties into DBUS object(s).
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
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001561 * @param[in] bootType The boot type to set.
1562 * @return Integer error code.
1563 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001564inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001565 const uint64_t computerSystemIndex,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001566 const std::optional<std::string>& bootType)
1567{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001568 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001569
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001570 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001571 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001572 return;
1573 }
1574
1575 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001576 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001577 // Figure out which DBUS interface and property to use
1578 if (*bootType == "Legacy")
1579 {
1580 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1581 }
1582 else if (*bootType == "UEFI")
1583 {
1584 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1585 }
1586 else
1587 {
Ed Tanous62598e32023-07-17 17:06:25 -07001588 BMCWEB_LOG_DEBUG("Invalid property value for "
1589 "BootSourceOverrideMode: {}",
1590 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001591 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001592 "BootSourceOverrideMode");
1593 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001594 }
1595
1596 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001597 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001598
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001599 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1600 std::to_string(computerSystemIndex));
1601 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301602 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001603 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001604 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301605 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001606}
1607
1608/**
1609 * @brief Sets boot properties into DBUS object(s).
1610 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001611 * @param[in] asyncResp Shared pointer for generating response
1612 * message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001613 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001614 * @param[in] bootType The boot type to set.
1615 * @return Integer error code.
1616 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001617inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001618 const uint64_t computerSystemIndex,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001619 const std::optional<std::string>& bootEnable)
1620{
1621 if (!bootEnable)
1622 {
1623 return;
1624 }
1625 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001626 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001627
1628 bool bootOverrideEnable = false;
1629 bool bootOverridePersistent = false;
1630 // Figure out which DBUS interface and property to use
1631 if (*bootEnable == "Disabled")
1632 {
1633 bootOverrideEnable = false;
1634 }
1635 else if (*bootEnable == "Once")
1636 {
1637 bootOverrideEnable = true;
1638 bootOverridePersistent = false;
1639 }
1640 else if (*bootEnable == "Continuous")
1641 {
1642 bootOverrideEnable = true;
1643 bootOverridePersistent = true;
1644 }
1645 else
1646 {
Ed Tanous62598e32023-07-17 17:06:25 -07001647 BMCWEB_LOG_DEBUG(
1648 "Invalid property value for BootSourceOverrideEnabled: {}",
1649 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001650 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001651 "BootSourceOverrideEnabled");
1652 return;
1653 }
1654
1655 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001656 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001657
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001658 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1659 std::to_string(computerSystemIndex));
1660 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301661 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001662 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001663 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301664 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001665
1666 if (!bootOverrideEnable)
1667 {
1668 return;
1669 }
1670
1671 // In case boot override is enabled we need to set correct value for the
1672 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001673 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1674 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001675
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001676 path /= "one_time";
Ginu Georgee93abac2024-06-14 17:35:27 +05301677 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001678 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001679 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301680 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001681}
1682
1683/**
1684 * @brief Sets boot properties into DBUS object(s).
1685 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001686 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001687 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301688 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301689 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001690 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301691 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001692inline void setBootModeOrSource(
1693 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001694 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001695 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301696{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001697 std::string bootSourceStr;
1698 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001699
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001700 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301701 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001702 return;
1703 }
1704
1705 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001706 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001707 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001708 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1709 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001710 {
Ed Tanous62598e32023-07-17 17:06:25 -07001711 BMCWEB_LOG_DEBUG(
1712 "Invalid property value for BootSourceOverrideTarget: {}",
1713 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001714 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001715 "BootSourceTargetOverride");
1716 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001717 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301718
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001719 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001720 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1721 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001722
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001723 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1724 std::to_string(computerSystemIndex));
1725 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301726 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001727 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001728 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301729 bootSourceStr);
1730 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001731 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001732 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301733 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001734}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001735
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001736/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001737 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301738 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001739 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001740 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301741 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001742 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301743 * @param[in] bootEnable The boot override enable from incoming RF request.
1744 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001745 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301746 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001747
Patrick Williams504af5a2025-02-03 14:29:03 -05001748inline void setBootProperties(
1749 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001750 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001751 const std::optional<std::string>& bootSource,
1752 const std::optional<std::string>& bootType,
1753 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301754{
Ed Tanous62598e32023-07-17 17:06:25 -07001755 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301756
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001757 setBootModeOrSource(asyncResp, computerSystemIndex, bootSource);
1758 setBootType(asyncResp, computerSystemIndex, bootType);
1759 setBootEnable(asyncResp, computerSystemIndex, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301760}
1761
George Liuc6a620f2020-04-10 17:18:11 +08001762/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001763 * @brief Sets AssetTag
1764 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001765 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001766 * @param[in] assetTag "AssetTag" from request.
1767 *
1768 * @return None.
1769 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001770inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001771 const std::string& assetTag)
1772{
George Liue99073f2022-12-09 11:06:16 +08001773 constexpr std::array<std::string_view, 1> interfaces = {
1774 "xyz.openbmc_project.Inventory.Item.System"};
1775 dbus::utility::getSubTree(
1776 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001777 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001778 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001779 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001780 if (ec)
1781 {
1782 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1783 messages::internalError(asyncResp->res);
1784 return;
1785 }
1786 if (subtree.empty())
1787 {
1788 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1789 messages::internalError(asyncResp->res);
1790 return;
1791 }
1792 // Assume only 1 system D-Bus object
1793 // Throw an error if there is more than 1
1794 if (subtree.size() > 1)
1795 {
1796 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1797 messages::internalError(asyncResp->res);
1798 return;
1799 }
1800 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1801 {
1802 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1803 messages::internalError(asyncResp->res);
1804 return;
1805 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001806
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001807 const std::string& path = subtree[0].first;
1808 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001809
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001810 if (service.empty())
1811 {
1812 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1813 messages::internalError(asyncResp->res);
1814 return;
1815 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001816
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001817 setDbusProperty(asyncResp, "AssetTag", service, path,
1818 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1819 "AssetTag", assetTag);
1820 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001821}
1822
1823/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001824 * @brief Validate the specified stopBootOnFault is valid and return the
1825 * stopBootOnFault name associated with that string
1826 *
1827 * @param[in] stopBootOnFaultString String representing the desired
1828 * stopBootOnFault
1829 *
1830 * @return stopBootOnFault value or empty if incoming value is not valid
1831 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001832inline std::optional<bool> validstopBootOnFault(
1833 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001834{
1835 if (stopBootOnFaultString == "AnyFault")
1836 {
1837 return true;
1838 }
1839
1840 if (stopBootOnFaultString == "Never")
1841 {
1842 return false;
1843 }
1844
1845 return std::nullopt;
1846}
1847
1848/**
1849 * @brief Sets stopBootOnFault
1850 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001851 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001852 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1853 *
1854 * @return None.
1855 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001856inline void setStopBootOnFault(
1857 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1858 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001859{
Ed Tanous62598e32023-07-17 17:06:25 -07001860 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001861
1862 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1863 if (!stopBootEnabled)
1864 {
Ed Tanous62598e32023-07-17 17:06:25 -07001865 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1866 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001867 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001868 "StopBootOnFault");
1869 return;
1870 }
1871
Ginu Georgee93abac2024-06-14 17:35:27 +05301872 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1873 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001874 sdbusplus::message::object_path(
1875 "/xyz/openbmc_project/logging/settings"),
1876 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301877 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001878}
1879
1880/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001881 * @brief Sets automaticRetry (Auto Reboot)
1882 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001883 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001884 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills69f35302020-05-17 16:06:31 -05001885 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1886 *
1887 * @return None.
1888 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001889inline void setAutomaticRetry(
1890 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001891 const uint64_t computerSystemIndex, const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001892{
Ed Tanous62598e32023-07-17 17:06:25 -07001893 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001894
1895 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001896 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001897
1898 if (automaticRetryConfig == "Disabled")
1899 {
1900 autoRebootEnabled = false;
1901 }
1902 else if (automaticRetryConfig == "RetryAttempts")
1903 {
1904 autoRebootEnabled = true;
1905 }
1906 else
1907 {
Ed Tanous62598e32023-07-17 17:06:25 -07001908 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1909 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001910 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001911 "AutomaticRetryConfig");
1912 return;
1913 }
1914
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001915 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1916 std::to_string(computerSystemIndex));
1917 path /= "auto_reboot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301918 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001919 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001920 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301921 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001922}
1923
Ed Tanous8d69c662023-06-21 10:29:06 -07001924inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1925{
1926 if (policy == "AlwaysOn")
1927 {
1928 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1929 }
1930 if (policy == "AlwaysOff")
1931 {
1932 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1933 }
1934 if (policy == "LastState")
1935 {
1936 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1937 }
1938 return "";
1939}
1940
Gunnar Mills69f35302020-05-17 16:06:31 -05001941/**
George Liuc6a620f2020-04-10 17:18:11 +08001942 * @brief Sets power restore policy properties.
1943 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001944 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001945 * @param[in] computerSystemIndex Index associated with the requested system
George Liuc6a620f2020-04-10 17:18:11 +08001946 * @param[in] policy power restore policy properties from request.
1947 *
1948 * @return None.
1949 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001950inline void setPowerRestorePolicy(
1951 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001952 const uint64_t computerSystemIndex, std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001953{
Ed Tanous62598e32023-07-17 17:06:25 -07001954 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001955
Ed Tanous8d69c662023-06-21 10:29:06 -07001956 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001957
Ed Tanous8d69c662023-06-21 10:29:06 -07001958 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001959 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001960 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001961 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001962 return;
1963 }
1964
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001965 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1966 std::to_string(computerSystemIndex));
1967 path /= "power_restore_policy";
1968 setDbusProperty(asyncResp, "PowerRestorePolicy",
1969 "xyz.openbmc_project.Settings", path,
1970 "xyz.openbmc_project.Control.Power.RestorePolicy",
1971 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001972}
1973
AppaRao Pulia6349912019-10-18 17:16:08 +05301974/**
1975 * @brief Retrieves provisioning status
1976 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001977 * @param[in] asyncResp Shared pointer for completing asynchronous
1978 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05301979 *
1980 * @return None.
1981 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001982inline void getProvisioningStatus(
1983 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05301984{
Ed Tanous62598e32023-07-17 17:06:25 -07001985 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08001986 dbus::utility::getAllProperties(
1987 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
1988 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07001989 [asyncResp](const boost::system::error_code& ec,
1990 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001991 nlohmann::json& oemPFR =
1992 asyncResp->res
1993 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
1994 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
1995 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
1996 oemPFR["@odata.type"] =
1997 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07001998
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001999 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05302000 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002001 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2002 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002003 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002004 FirmwareProvisioningStatus::NotProvisioned;
2005 return;
2006 }
2007
2008 const bool* provState = nullptr;
2009 const bool* lockState = nullptr;
2010
2011 const bool success = sdbusplus::unpackPropertiesNoThrow(
2012 dbus_utils::UnpackErrorPrinter(), propertiesList,
2013 "UfmProvisioned", provState, "UfmLocked", lockState);
2014
2015 if (!success)
2016 {
2017 messages::internalError(asyncResp->res);
2018 return;
2019 }
2020
2021 if ((provState == nullptr) || (lockState == nullptr))
2022 {
2023 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2024 messages::internalError(asyncResp->res);
2025 return;
2026 }
2027
2028 if (*provState)
2029 {
2030 if (*lockState)
2031 {
2032 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2033 FirmwareProvisioningStatus::ProvisionedAndLocked;
2034 }
2035 else
2036 {
2037 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2038 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2039 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302040 }
2041 else
2042 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002043 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002044 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302045 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002046 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302047}
AppaRao Pulia6349912019-10-18 17:16:08 +05302048
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302049/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002050 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002051 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002052 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002053 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002054 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002055 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002056inline computer_system::PowerMode translatePowerModeString(
2057 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002058{
Chris Cainb6655102024-02-01 14:35:33 -06002059 using PowerMode = computer_system::PowerMode;
2060
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002061 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002062 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002063 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002064 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002065 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002066 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002067 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002068 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002069 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002070 if (modeString ==
2071 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002072 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002073 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002074 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002075 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002076 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2077 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002078 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002079 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002080 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002081 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2082 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002083 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002084 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002085 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002086 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2087 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002088 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002089 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002090 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002091 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002092 return PowerMode::OEM;
2093 }
2094 // Any other values would be invalid
2095 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2096 return PowerMode::Invalid;
2097}
2098
Patrick Williams504af5a2025-02-03 14:29:03 -05002099inline void afterGetPowerMode(
2100 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2101 const boost::system::error_code& ec,
2102 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002103{
2104 if (ec)
2105 {
2106 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2107 messages::internalError(asyncResp->res);
2108 return;
2109 }
2110
2111 std::string powerMode;
2112 const std::vector<std::string>* allowedModes = nullptr;
2113 const bool success = sdbusplus::unpackPropertiesNoThrow(
2114 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2115 "AllowedPowerModes", allowedModes);
2116
2117 if (!success)
2118 {
2119 messages::internalError(asyncResp->res);
2120 return;
2121 }
2122
2123 nlohmann::json::array_t modeList;
2124 if (allowedModes == nullptr)
2125 {
2126 modeList.emplace_back("Static");
2127 modeList.emplace_back("MaximumPerformance");
2128 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002129 }
2130 else
2131 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002132 for (const auto& aMode : *allowedModes)
2133 {
2134 computer_system::PowerMode modeValue =
2135 translatePowerModeString(aMode);
2136 if (modeValue == computer_system::PowerMode::Invalid)
2137 {
2138 messages::internalError(asyncResp->res);
2139 continue;
2140 }
2141 modeList.emplace_back(modeValue);
2142 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002143 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002144 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002145
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002146 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2147 const computer_system::PowerMode modeValue =
2148 translatePowerModeString(powerMode);
2149 if (modeValue == computer_system::PowerMode::Invalid)
2150 {
2151 messages::internalError(asyncResp->res);
2152 return;
2153 }
2154 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2155}
Chris Cain3a2d04242021-05-28 16:57:10 -05002156/**
2157 * @brief Retrieves system power mode
2158 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002159 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002160 *
2161 * @return None.
2162 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002163inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002164{
Ed Tanous62598e32023-07-17 17:06:25 -07002165 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002166
2167 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002168 constexpr std::array<std::string_view, 1> interfaces = {
2169 "xyz.openbmc_project.Control.Power.Mode"};
2170 dbus::utility::getSubTree(
2171 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002172 [asyncResp](const boost::system::error_code& ec,
2173 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002174 if (ec)
2175 {
2176 BMCWEB_LOG_DEBUG(
2177 "DBUS response error on Power.Mode GetSubTree {}", ec);
2178 // This is an optional D-Bus object so just return if
2179 // error occurs
2180 return;
2181 }
2182 if (subtree.empty())
2183 {
2184 // As noted above, this is an optional interface so just return
2185 // if there is no instance found
2186 return;
2187 }
2188 if (subtree.size() > 1)
2189 {
2190 // More then one PowerMode object is not supported and is an
2191 // error
2192 BMCWEB_LOG_DEBUG(
2193 "Found more than 1 system D-Bus Power.Mode objects: {}",
2194 subtree.size());
2195 messages::internalError(asyncResp->res);
2196 return;
2197 }
2198 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2199 {
2200 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2201 messages::internalError(asyncResp->res);
2202 return;
2203 }
2204 const std::string& path = subtree[0].first;
2205 const std::string& service = subtree[0].second.begin()->first;
2206 if (service.empty())
2207 {
2208 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2209 messages::internalError(asyncResp->res);
2210 return;
2211 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002212
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002213 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002214 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002215 *crow::connections::systemBus, service, path,
2216 "xyz.openbmc_project.Control.Power.Mode",
2217 [asyncResp](
2218 const boost::system::error_code& ec2,
2219 const dbus::utility::DBusPropertiesMap& properties) {
2220 afterGetPowerMode(asyncResp, ec2, properties);
2221 });
George Liue99073f2022-12-09 11:06:16 +08002222 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002223}
2224
2225/**
2226 * @brief Validate the specified mode is valid and return the PowerMode
2227 * name associated with that string
2228 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002229 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002230 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002231 *
2232 * @return PowerMode value or empty string if mode is not valid
2233 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002234inline std::string validatePowerMode(
2235 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2236 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002237{
Chris Cainb6655102024-02-01 14:35:33 -06002238 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002239 std::string mode;
2240
Chris Cainb6655102024-02-01 14:35:33 -06002241 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002242 {
2243 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2244 }
Chris Cainb6655102024-02-01 14:35:33 -06002245 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002246 {
George Liu0fda0f12021-11-16 10:06:17 +08002247 mode =
2248 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002249 }
Chris Cainb6655102024-02-01 14:35:33 -06002250 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002251 {
2252 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2253 }
Chris Cainb6655102024-02-01 14:35:33 -06002254 else if (modeValue == PowerMode::BalancedPerformance)
2255 {
2256 mode =
2257 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2258 }
2259 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2260 {
2261 mode =
2262 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2263 }
2264 else if (modeValue == PowerMode::EfficiencyFavorPower)
2265 {
2266 mode =
2267 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2268 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002269 else
2270 {
Chris Cainb6655102024-02-01 14:35:33 -06002271 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002272 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002273 }
2274 return mode;
2275}
2276
2277/**
2278 * @brief Sets system power mode.
2279 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002280 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002281 * @param[in] pmode System power mode from request.
2282 *
2283 * @return None.
2284 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002285inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002286 const std::string& pmode)
2287{
Ed Tanous62598e32023-07-17 17:06:25 -07002288 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002289
Ed Tanousac106bf2023-06-07 09:24:59 -07002290 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002291 if (powerMode.empty())
2292 {
2293 return;
2294 }
2295
2296 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002297 constexpr std::array<std::string_view, 1> interfaces = {
2298 "xyz.openbmc_project.Control.Power.Mode"};
2299 dbus::utility::getSubTree(
2300 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002301 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002302 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002303 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002304 if (ec)
2305 {
2306 BMCWEB_LOG_ERROR(
2307 "DBUS response error on Power.Mode GetSubTree {}", ec);
2308 // This is an optional D-Bus object, but user attempted to patch
2309 messages::internalError(asyncResp->res);
2310 return;
2311 }
2312 if (subtree.empty())
2313 {
2314 // This is an optional D-Bus object, but user attempted to patch
2315 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2316 "PowerMode");
2317 return;
2318 }
2319 if (subtree.size() > 1)
2320 {
2321 // More then one PowerMode object is not supported and is an
2322 // error
2323 BMCWEB_LOG_DEBUG(
2324 "Found more than 1 system D-Bus Power.Mode objects: {}",
2325 subtree.size());
2326 messages::internalError(asyncResp->res);
2327 return;
2328 }
2329 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2330 {
2331 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2332 messages::internalError(asyncResp->res);
2333 return;
2334 }
2335 const std::string& path = subtree[0].first;
2336 const std::string& service = subtree[0].second.begin()->first;
2337 if (service.empty())
2338 {
2339 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2340 messages::internalError(asyncResp->res);
2341 return;
2342 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002343
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002344 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002345
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002346 // Set the Power Mode property
2347 setDbusProperty(asyncResp, "PowerMode", service, path,
2348 "xyz.openbmc_project.Control.Power.Mode",
2349 "PowerMode", powerMode);
2350 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002351}
2352
2353/**
Yong Li51709ff2019-09-30 14:13:04 +08002354 * @brief Translates watchdog timeout action DBUS property value to redfish.
2355 *
2356 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2357 *
2358 * @return Returns as a string, the timeout action in Redfish terms. If
2359 * translation cannot be done, returns an empty string.
2360 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002361inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002362{
2363 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2364 {
2365 return "None";
2366 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002367 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002368 {
2369 return "ResetSystem";
2370 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002371 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002372 {
2373 return "PowerDown";
2374 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002375 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002376 {
2377 return "PowerCycle";
2378 }
2379
2380 return "";
2381}
2382
2383/**
Yong Lic45f0082019-10-10 14:19:01 +08002384 *@brief Translates timeout action from Redfish to DBUS property value.
2385 *
2386 *@param[in] rfAction The timeout action in Redfish.
2387 *
2388 *@return Returns as a string, the time_out action as expected by DBUS.
2389 *If translation cannot be done, returns an empty string.
2390 */
2391
Ed Tanous23a21a12020-07-25 04:45:05 +00002392inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002393{
2394 if (rfAction == "None")
2395 {
2396 return "xyz.openbmc_project.State.Watchdog.Action.None";
2397 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002398 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002399 {
2400 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2401 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002402 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002403 {
2404 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2405 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002406 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002407 {
2408 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2409 }
2410
2411 return "";
2412}
2413
2414/**
Yong Li51709ff2019-09-30 14:13:04 +08002415 * @brief Retrieves host watchdog timer properties over DBUS
2416 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002417 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002418 *
2419 * @return None.
2420 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002421inline void getHostWatchdogTimer(
2422 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002423{
Ed Tanous62598e32023-07-17 17:06:25 -07002424 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002425 dbus::utility::getAllProperties(
2426 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002427 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002428 [asyncResp](const boost::system::error_code& ec,
2429 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002430 if (ec)
2431 {
2432 // watchdog service is stopped
2433 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2434 return;
2435 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002436
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002437 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002438
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002439 nlohmann::json& hostWatchdogTimer =
2440 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002441
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002442 // watchdog service is running/enabled
2443 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002444
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002445 const bool* enabled = nullptr;
2446 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002447
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002448 const bool success = sdbusplus::unpackPropertiesNoThrow(
2449 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2450 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002451
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002452 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002453 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002454 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002455 return;
2456 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002457
2458 if (enabled != nullptr)
2459 {
2460 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2461 }
2462
2463 if (expireAction != nullptr)
2464 {
2465 std::string action = dbusToRfWatchdogAction(*expireAction);
2466 if (action.empty())
2467 {
2468 messages::internalError(asyncResp->res);
2469 return;
2470 }
2471 hostWatchdogTimer["TimeoutAction"] = action;
2472 }
2473 });
Yong Li51709ff2019-09-30 14:13:04 +08002474}
2475
2476/**
Yong Lic45f0082019-10-10 14:19:01 +08002477 * @brief Sets Host WatchDog Timer properties.
2478 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002479 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002480 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2481 * RF request.
2482 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2483 *
2484 * @return None.
2485 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002486inline void setWDTProperties(
2487 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2488 const std::optional<bool> wdtEnable,
2489 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002490{
Ed Tanous62598e32023-07-17 17:06:25 -07002491 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002492
2493 if (wdtTimeOutAction)
2494 {
2495 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2496 // check if TimeOut Action is Valid
2497 if (wdtTimeOutActStr.empty())
2498 {
Ed Tanous62598e32023-07-17 17:06:25 -07002499 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2500 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002501 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002502 "TimeoutAction");
2503 return;
2504 }
2505
Ginu Georgee93abac2024-06-14 17:35:27 +05302506 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2507 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002508 sdbusplus::message::object_path(
2509 "/xyz/openbmc_project/watchdog/host0"),
2510 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302511 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002512 }
2513
2514 if (wdtEnable)
2515 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302516 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2517 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002518 sdbusplus::message::object_path(
2519 "/xyz/openbmc_project/watchdog/host0"),
2520 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302521 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002522 }
2523}
2524
Chris Cain37bbf982021-09-20 10:53:09 -05002525/**
2526 * @brief Parse the Idle Power Saver properties into json
2527 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002528 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002529 * @param[in] properties IPS property data from DBus.
2530 *
2531 * @return true if successful
2532 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002533inline bool parseIpsProperties(
2534 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2535 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002536{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002537 const bool* enabled = nullptr;
2538 const uint8_t* enterUtilizationPercent = nullptr;
2539 const uint64_t* enterDwellTime = nullptr;
2540 const uint8_t* exitUtilizationPercent = nullptr;
2541 const uint64_t* exitDwellTime = nullptr;
2542
2543 const bool success = sdbusplus::unpackPropertiesNoThrow(
2544 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002545 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2546 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2547 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002548
2549 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002550 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002551 return false;
2552 }
2553
2554 if (enabled != nullptr)
2555 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002556 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002557 }
2558
2559 if (enterUtilizationPercent != nullptr)
2560 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002561 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002562 *enterUtilizationPercent;
2563 }
2564
2565 if (enterDwellTime != nullptr)
2566 {
2567 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002568 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002569 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2570 .count();
2571 }
2572
2573 if (exitUtilizationPercent != nullptr)
2574 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002575 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002576 *exitUtilizationPercent;
2577 }
2578
2579 if (exitDwellTime != nullptr)
2580 {
2581 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002582 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002583 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2584 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002585 }
2586
2587 return true;
2588}
2589
2590/**
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002591 * @brief Retrieves idle power saver properties over DBUS
Chris Cain37bbf982021-09-20 10:53:09 -05002592 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002593 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002594 *
2595 * @return None.
2596 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002597inline void getIdlePowerSaver(
2598 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002599{
Ed Tanous62598e32023-07-17 17:06:25 -07002600 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002601
2602 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002603 constexpr std::array<std::string_view, 1> interfaces = {
2604 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2605 dbus::utility::getSubTree(
2606 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002607 [asyncResp](const boost::system::error_code& ec,
2608 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002609 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002610 {
Ed Tanous62598e32023-07-17 17:06:25 -07002611 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002612 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2613 ec);
2614 messages::internalError(asyncResp->res);
2615 return;
2616 }
2617 if (subtree.empty())
2618 {
2619 // This is an optional interface so just return
2620 // if there is no instance found
2621 BMCWEB_LOG_DEBUG("No instances found");
2622 return;
2623 }
2624 if (subtree.size() > 1)
2625 {
2626 // More then one PowerIdlePowerSaver object is not supported and
2627 // is an error
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002628 BMCWEB_LOG_DEBUG(
2629 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2630 subtree.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002631 messages::internalError(asyncResp->res);
2632 return;
2633 }
2634 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2635 {
2636 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2637 messages::internalError(asyncResp->res);
2638 return;
2639 }
2640 const std::string& path = subtree[0].first;
2641 const std::string& service = subtree[0].second.begin()->first;
2642 if (service.empty())
2643 {
2644 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002645 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002646 return;
2647 }
2648
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002649 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002650 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002651 *crow::connections::systemBus, service, path,
2652 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2653 [asyncResp](
2654 const boost::system::error_code& ec2,
2655 const dbus::utility::DBusPropertiesMap& properties) {
2656 if (ec2)
2657 {
2658 BMCWEB_LOG_ERROR(
2659 "DBUS response error on IdlePowerSaver GetAll: {}",
2660 ec2);
2661 messages::internalError(asyncResp->res);
2662 return;
2663 }
2664
2665 if (!parseIpsProperties(asyncResp, properties))
2666 {
2667 messages::internalError(asyncResp->res);
2668 return;
2669 }
2670 });
George Liue99073f2022-12-09 11:06:16 +08002671 });
Chris Cain37bbf982021-09-20 10:53:09 -05002672
Ed Tanous62598e32023-07-17 17:06:25 -07002673 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002674}
2675
2676/**
2677 * @brief Sets Idle Power Saver properties.
2678 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002679 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002680 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2681 * RF request.
2682 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2683 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2684 * before entering idle state.
2685 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2686 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2687 * before exiting idle state
2688 *
2689 * @return None.
2690 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002691inline void setIdlePowerSaver(
2692 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2693 const std::optional<bool> ipsEnable,
2694 const std::optional<uint8_t> ipsEnterUtil,
2695 const std::optional<uint64_t> ipsEnterTime,
2696 const std::optional<uint8_t> ipsExitUtil,
2697 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002698{
Ed Tanous62598e32023-07-17 17:06:25 -07002699 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002700
2701 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002702 constexpr std::array<std::string_view, 1> interfaces = {
2703 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2704 dbus::utility::getSubTree(
2705 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002706 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002707 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002708 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002709 if (ec)
2710 {
2711 BMCWEB_LOG_ERROR(
2712 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2713 ec);
2714 messages::internalError(asyncResp->res);
2715 return;
2716 }
2717 if (subtree.empty())
2718 {
2719 // This is an optional D-Bus object, but user attempted to patch
2720 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2721 "IdlePowerSaver");
2722 return;
2723 }
2724 if (subtree.size() > 1)
2725 {
2726 // More then one PowerIdlePowerSaver object is not supported and
2727 // is an error
2728 BMCWEB_LOG_DEBUG(
2729 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2730 subtree.size());
2731 messages::internalError(asyncResp->res);
2732 return;
2733 }
2734 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2735 {
2736 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2737 messages::internalError(asyncResp->res);
2738 return;
2739 }
2740 const std::string& path = subtree[0].first;
2741 const std::string& service = subtree[0].second.begin()->first;
2742 if (service.empty())
2743 {
2744 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2745 messages::internalError(asyncResp->res);
2746 return;
2747 }
Chris Cain37bbf982021-09-20 10:53:09 -05002748
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002749 // Valid Power IdlePowerSaver object found, now set any values that
2750 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002751
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002752 if (ipsEnable)
2753 {
2754 setDbusProperty(
2755 asyncResp, "IdlePowerSaver/Enabled", service, path,
2756 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2757 "Enabled", *ipsEnable);
2758 }
2759 if (ipsEnterUtil)
2760 {
2761 setDbusProperty(
2762 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2763 service, path,
2764 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2765 "EnterUtilizationPercent", *ipsEnterUtil);
2766 }
2767 if (ipsEnterTime)
2768 {
2769 // Convert from seconds into milliseconds for DBus
2770 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2771 setDbusProperty(
2772 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2773 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2774 "EnterDwellTime", timeMilliseconds);
2775 }
2776 if (ipsExitUtil)
2777 {
2778 setDbusProperty(
2779 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2780 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2781 "ExitUtilizationPercent", *ipsExitUtil);
2782 }
2783 if (ipsExitTime)
2784 {
2785 // Convert from seconds into milliseconds for DBus
2786 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2787 setDbusProperty(
2788 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2789 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2790 "ExitDwellTime", timeMilliseconds);
2791 }
2792 });
Chris Cain37bbf982021-09-20 10:53:09 -05002793
Ed Tanous62598e32023-07-17 17:06:25 -07002794 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002795}
2796
Ed Tanousc1e219d2023-06-07 10:34:33 -07002797inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002798 crow::App& app, const crow::Request& req,
2799 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2800{
2801 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2802 {
2803 return;
2804 }
2805 asyncResp->res.addHeader(
2806 boost::beast::http::field::link,
2807 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2808}
2809
Ed Tanousc1e219d2023-06-07 10:34:33 -07002810inline void handleComputerSystemCollectionGet(
2811 crow::App& app, const crow::Request& req,
2812 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2813{
2814 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2815 {
2816 return;
2817 }
2818
2819 asyncResp->res.addHeader(
2820 boost::beast::http::field::link,
2821 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2822 asyncResp->res.jsonValue["@odata.type"] =
2823 "#ComputerSystemCollection.ComputerSystemCollection";
2824 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2825 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2826
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002827 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002828}
2829
Yong Lic45f0082019-10-10 14:19:01 +08002830/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002831 * Function transceives data with dbus directly.
2832 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002833inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002834{
Patrick Williams89492a12023-05-10 07:51:34 -05002835 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2836 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2837 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002838 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002839 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002840
Ed Tanous177612a2025-02-14 15:16:09 -08002841 dbus::utility::async_method_call(
2842 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002843 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002844 if (ec)
2845 {
2846 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2847 messages::internalError(asyncResp->res);
2848 return;
2849 }
2850 messages::success(asyncResp->res);
2851 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002852 serviceName, objectPath, interfaceName, method);
2853}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002854
Oliver Brewka06c055e2025-07-23 16:42:24 +02002855/**
2856 * @brief process the POST request after getting the computerSystemIndex
2857 *
2858 * @param[in] asyncResp Shared pointer for completing asynchronous
2859 * calls
2860 * @param[in] resetType The requested reset action
2861 * @param[in] computerSystemIndex Index associated with the requested system
2862 *
2863 * @return None
2864 */
2865inline void processComputerSystemResetActionPost(
2866 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string& resetType,
2867 const uint64_t computerSystemIndex)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002868{
Ed Tanousc1e219d2023-06-07 10:34:33 -07002869 // Get the command and host vs. chassis
2870 std::string command;
2871 bool hostCommand = true;
2872 if ((resetType == "On") || (resetType == "ForceOn"))
2873 {
2874 command = "xyz.openbmc_project.State.Host.Transition.On";
2875 hostCommand = true;
2876 }
2877 else if (resetType == "ForceOff")
2878 {
2879 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2880 hostCommand = false;
2881 }
2882 else if (resetType == "ForceRestart")
2883 {
2884 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2885 hostCommand = true;
2886 }
2887 else if (resetType == "GracefulShutdown")
2888 {
2889 command = "xyz.openbmc_project.State.Host.Transition.Off";
2890 hostCommand = true;
2891 }
2892 else if (resetType == "GracefulRestart")
2893 {
2894 command =
2895 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2896 hostCommand = true;
2897 }
2898 else if (resetType == "PowerCycle")
2899 {
2900 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2901 hostCommand = true;
2902 }
2903 else if (resetType == "Nmi")
2904 {
2905 doNMI(asyncResp);
2906 return;
2907 }
2908 else
2909 {
2910 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2911 return;
2912 }
2913
2914 if (hostCommand)
2915 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002916 setDbusProperty(asyncResp, "Reset",
2917 getHostStateServiceName(computerSystemIndex),
2918 getHostStateObjectPath(computerSystemIndex),
2919 "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302920 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002921 }
2922 else
2923 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002924 setDbusProperty(asyncResp, "Reset",
2925 getChassisStateServiceName(computerSystemIndex),
2926 getChassisStateObjectPath(computerSystemIndex),
Ed Tanousd02aad32024-02-13 14:43:34 -08002927 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302928 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002929 }
2930}
2931
Oliver Brewka06c055e2025-07-23 16:42:24 +02002932inline void handleComputerSystemResetActionPost(
2933 crow::App& app, const crow::Request& req,
2934 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2935 const std::string& systemName)
2936{
2937 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2938 {
2939 return;
2940 }
2941
2942 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2943 {
2944 if (systemName == "hypervisor")
2945 {
2946 handleHypervisorSystemResetPost(req, asyncResp);
2947 return;
2948 }
2949 }
2950
2951 if (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2952 {
2953 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2954 {
2955 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2956 systemName);
2957 return;
2958 }
2959 }
2960
2961 std::string resetType;
2962 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2963 {
2964 return;
2965 }
2966
2967 getComputerSystemIndex(asyncResp, systemName,
2968 std::bind_front(processComputerSystemResetActionPost,
2969 asyncResp, resetType));
2970}
2971
Ed Tanousc1e219d2023-06-07 10:34:33 -07002972inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002973 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002974 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2975 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002976{
2977 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2978 {
2979 return;
2980 }
2981
2982 asyncResp->res.addHeader(
2983 boost::beast::http::field::link,
2984 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
2985}
2986
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002987inline void afterPortRequest(
2988 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2989 const boost::system::error_code& ec,
2990 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
2991{
2992 if (ec)
2993 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05002994 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05002995 messages::internalError(asyncResp->res);
2996 return;
2997 }
2998 for (const auto& data : socketData)
2999 {
3000 const std::string& socketPath = get<0>(data);
3001 const std::string& protocolName = get<1>(data);
3002 bool isProtocolEnabled = get<2>(data);
3003 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3004 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3005 // need to retrieve port number for
3006 // obmc-console-ssh service
3007 if (protocolName == "SSH")
3008 {
3009 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003010 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003011 int portNumber) {
3012 if (ec1)
3013 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003014 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003015 messages::internalError(asyncResp->res);
3016 return;
3017 }
3018 nlohmann::json& dataJson1 =
3019 asyncResp->res.jsonValue["SerialConsole"];
3020 dataJson1[protocolName]["Port"] = portNumber;
3021 });
3022 }
3023 }
3024}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003025
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003026/**
3027 * @brief process the GET request after getting the computerSystemIndex
3028 *
3029 * @param[in] asyncResp Shared pointer for completing asynchronous
3030 * calls
3031 * @param[in] systemName Name of the requested system
3032 * @param[in] computerSystemIndex Index associated with the requested system
3033 *
3034 * @return None
3035 */
3036inline void processComputerSystemGet(
Patrick Williams504af5a2025-02-03 14:29:03 -05003037 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003038 const std::string& systemName, const uint64_t computerSystemIndex)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003039{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003040 asyncResp->res.addHeader(
3041 boost::beast::http::field::link,
3042 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3043 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003044 "#ComputerSystem.v1_22_0.ComputerSystem";
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003045 asyncResp->res.jsonValue["Name"] = systemName;
3046 asyncResp->res.jsonValue["Id"] = systemName;
Ed Tanous539d8c62024-06-19 14:38:27 -07003047 asyncResp->res.jsonValue["SystemType"] =
3048 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003049 asyncResp->res.jsonValue["Description"] = "Computer System";
3050 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003051 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003052 double(0);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003053 asyncResp->res.jsonValue["@odata.id"] =
3054 boost::urls::format("/redfish/v1/Systems/{}", systemName);
Ed Tanous04a258f2018-10-15 08:00:41 -07003055
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003056 // Currently not supported on multi-host. TBD
3057 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3058 {
3059 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3060 boost::urls::format("/redfish/v1/Systems/{}/Bios", systemName);
3061 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3062 boost::urls::format("/redfish/v1/Systems/{}/Processors",
3063 systemName);
3064 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3065 boost::urls::format("/redfish/v1/Systems/{}/Memory", systemName);
3066 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3067 boost::urls::format("/redfish/v1/Systems/{}/Storage", systemName);
3068 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3069 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3070 systemName);
3071 }
Ed Tanous029573d2019-02-01 10:57:49 -08003072
Ed Tanousc1e219d2023-06-07 10:34:33 -07003073 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003074 boost::urls::format(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003075 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003076 asyncResp->res
3077 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003078 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003079 systemName);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003080
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003081 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3082 boost::urls::format("/redfish/v1/Systems/{}/LogServices", systemName);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003083
Ed Tanousc1e219d2023-06-07 10:34:33 -07003084 nlohmann::json::array_t managedBy;
3085 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003086 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3087 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003088 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003089 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3090 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003091
Ed Tanousc1e219d2023-06-07 10:34:33 -07003092 // Fill in SerialConsole info
3093 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3094 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003095
Ed Tanousc1e219d2023-06-07 10:34:33 -07003096 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3097 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3098 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3099 "Press ~. to exit console";
3100 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3101 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003102
Ed Tanous25b54db2024-04-17 15:40:31 -07003103 if constexpr (BMCWEB_KVM)
3104 {
3105 // Fill in GraphicalConsole info
3106 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3107 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3108 4;
3109 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3110 nlohmann::json::array_t({"KVMIP"});
3111 }
James Feistb49ac872019-05-21 15:12:01 -07003112
Janet Adkinseb261e12025-09-15 13:25:45 -05003113 if constexpr (BMCWEB_REDFISH_USE_HARDCODED_SYSTEM_LOCATION_INDICATOR)
3114 {
3115 getSystemLocationIndicatorActive(asyncResp);
3116 }
3117 else
3118 {
3119 systems_utils::getValidSystemsPath(
3120 asyncResp, systemName,
3121 [asyncResp,
3122 systemName](const std::optional<std::string>& validSystemsPath) {
3123 if (validSystemsPath)
3124 {
3125 getLocationIndicatorActive(asyncResp, *validSystemsPath);
3126 }
3127 });
3128 }
Janet Adkins2eaa9272025-04-17 10:30:43 -05003129
Janet Adkinsf664fd82025-07-23 14:01:43 -05003130 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3131 {
3132 getIndicatorLedState(asyncResp);
3133 }
3134
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003135 // Currently not supported on multi-host.
3136 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3137 {
3138 getComputerSystem(asyncResp);
3139 // Todo: chassis matching could be handled by patch
3140 // https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60793
3141 getMainChassisId(
3142 asyncResp, [](const std::string& chassisId,
3143 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3144 nlohmann::json::array_t chassisArray;
3145 nlohmann::json& chassis = chassisArray.emplace_back();
3146 chassis["@odata.id"] =
3147 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3148 aRsp->res.jsonValue["Links"]["Chassis"] =
3149 std::move(chassisArray);
3150 });
3151
3152 pcie_util::getPCIeDeviceList(
3153 asyncResp, nlohmann::json::json_pointer("/PCIeDevices"));
3154 }
3155 getHostState(asyncResp, computerSystemIndex);
3156 getBootProperties(asyncResp, computerSystemIndex);
3157 getBootProgress(asyncResp, computerSystemIndex);
3158 getBootProgressLastStateTime(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003159 getHostWatchdogTimer(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003160 getPowerRestorePolicy(asyncResp, computerSystemIndex);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003161 getStopBootOnFault(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003162 getAutomaticRetryPolicy(asyncResp, computerSystemIndex);
3163 getLastResetTime(asyncResp, computerSystemIndex);
Ed Tanous25b54db2024-04-17 15:40:31 -07003164 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3165 {
3166 getProvisioningStatus(asyncResp);
3167 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003168 getTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003169 getPowerMode(asyncResp);
3170 getIdlePowerSaver(asyncResp);
3171}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003172
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003173inline void handleComputerSystemGet(
3174 crow::App& app, const crow::Request& req,
3175 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3176 const std::string& systemName)
3177{
3178 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3179 {
3180 return;
3181 }
3182
3183 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
3184 {
3185 if (systemName == "hypervisor")
3186 {
3187 handleHypervisorSystemGet(asyncResp);
3188 return;
3189 }
3190 }
3191
3192 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3193 {
3194 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3195 {
3196 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3197 systemName);
3198 return;
3199 }
3200 }
3201
3202 BMCWEB_LOG_DEBUG("requested system = {}", systemName);
3203 getComputerSystemIndex(
3204 asyncResp, systemName,
3205 std::bind_front(processComputerSystemGet, asyncResp, systemName));
3206}
3207
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003208struct PatchParams
Ed Tanousc1e219d2023-06-07 10:34:33 -07003209{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003210 std::optional<bool> locationIndicatorActive;
3211 std::optional<std::string> indicatorLed;
3212 std::optional<std::string> assetTag;
3213 std::optional<std::string> powerRestorePolicy;
3214 std::optional<std::string> powerMode;
3215 std::optional<bool> wdtEnable;
3216 std::optional<std::string> wdtTimeOutAction;
3217 std::optional<std::string> bootSource;
3218 std::optional<std::string> bootType;
3219 std::optional<std::string> bootEnable;
3220 std::optional<std::string> bootAutomaticRetry;
3221 std::optional<uint32_t> bootAutomaticRetryAttempts;
3222 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003223 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003224 std::optional<bool> ipsEnable;
3225 std::optional<uint8_t> ipsEnterUtil;
3226 std::optional<uint64_t> ipsEnterTime;
3227 std::optional<uint8_t> ipsExitUtil;
3228 std::optional<uint64_t> ipsExitTime;
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003229};
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003230
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003231/**
3232 * @brief process the POST request after getting the computerSystemIndex
3233 *
3234 * @param[in] asyncResp Shared pointer for completing asynchronous
3235 * calls
3236 * @param[in] patchParams Struct containing the property we want to
3237 * patch
3238 * @param[in] computerSystemIndex Index associated with the requested system
3239 *
3240 * @return None
3241 */
James Feistb49ac872019-05-21 15:12:01 -07003242
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003243inline void processComputerSystemPatch(
3244 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3245 std::string& systemName, PatchParams& patchParams,
3246 const uint64_t computerSystemIndex)
3247{
Janet Adkinsf664fd82025-07-23 14:01:43 -05003248 if constexpr (!BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3249 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003250 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003251 {
3252 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
3253 return;
3254 }
3255 }
3256
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003257 if (patchParams.assetTag)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003258 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003259 setAssetTag(asyncResp, *patchParams.assetTag);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003260 }
James Feistb49ac872019-05-21 15:12:01 -07003261
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003262 if (patchParams.wdtEnable || patchParams.wdtTimeOutAction)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003263 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003264 setWDTProperties(asyncResp, patchParams.wdtEnable,
3265 patchParams.wdtTimeOutAction);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003266 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003267
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003268 if (patchParams.bootSource || patchParams.bootType ||
3269 patchParams.bootEnable)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003270 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003271 setBootProperties(asyncResp, computerSystemIndex,
3272 patchParams.bootSource, patchParams.bootType,
3273 patchParams.bootEnable);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003274 }
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003275 if (patchParams.bootAutomaticRetry)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003276 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003277 setAutomaticRetry(asyncResp, computerSystemIndex,
3278 *patchParams.bootAutomaticRetry);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003279 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003280
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003281 if (patchParams.bootAutomaticRetryAttempts)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003282 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003283 setAutomaticRetryAttempts(
3284 asyncResp, computerSystemIndex,
3285 patchParams.bootAutomaticRetryAttempts.value());
Ed Tanousc1e219d2023-06-07 10:34:33 -07003286 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003287
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003288 if (patchParams.bootTrustedModuleRequired)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003289 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003290 setTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex,
3291 *patchParams.bootTrustedModuleRequired);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003292 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003293
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003294 if (patchParams.stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003295 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003296 setStopBootOnFault(asyncResp, *patchParams.stopBootOnFault);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003297 }
3298
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003299 if (patchParams.locationIndicatorActive)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003300 {
Janet Adkinseb261e12025-09-15 13:25:45 -05003301 if constexpr (BMCWEB_REDFISH_USE_HARDCODED_SYSTEM_LOCATION_INDICATOR)
3302 {
3303 setSystemLocationIndicatorActive(
3304 asyncResp, *patchParams.locationIndicatorActive);
3305 }
3306 else
3307 {
3308 systems_utils::getValidSystemsPath(
3309 asyncResp, systemName,
3310 [asyncResp, systemName,
3311 locationIndicatorActive{*patchParams.locationIndicatorActive}](
3312 const std::optional<std::string>& validSystemsPath) {
3313 if (!validSystemsPath)
3314 {
3315 messages::resourceNotFound(asyncResp->res, "Systems",
3316 systemName);
3317 return;
3318 }
3319 setLocationIndicatorActive(asyncResp, *validSystemsPath,
3320 locationIndicatorActive);
3321 });
3322 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003323 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003324
Janet Adkinsf664fd82025-07-23 14:01:43 -05003325 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003326 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003327 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003328 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003329 setIndicatorLedState(asyncResp, *patchParams.indicatorLed);
Janet Adkinsf664fd82025-07-23 14:01:43 -05003330 asyncResp->res.addHeader(boost::beast::http::field::warning,
3331 "299 - \"IndicatorLED is deprecated. Use "
3332 "LocationIndicatorActive instead.\"");
3333 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003334 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003335
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003336 if (patchParams.powerRestorePolicy)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003337 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003338 setPowerRestorePolicy(asyncResp, computerSystemIndex,
3339 *patchParams.powerRestorePolicy);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003340 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003341
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003342 if (patchParams.powerMode)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003343 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003344 setPowerMode(asyncResp, *patchParams.powerMode);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003345 }
Chris Cain37bbf982021-09-20 10:53:09 -05003346
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003347 if (patchParams.ipsEnable || patchParams.ipsEnterUtil ||
3348 patchParams.ipsEnterTime || patchParams.ipsExitUtil ||
3349 patchParams.ipsExitTime)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003350 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003351 setIdlePowerSaver(asyncResp, patchParams.ipsEnable,
3352 patchParams.ipsEnterUtil, patchParams.ipsEnterTime,
3353 patchParams.ipsExitUtil, patchParams.ipsExitTime);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003354 }
3355}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303356
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003357inline void handleComputerSystemPatch(
3358 crow::App& app, const crow::Request& req,
3359 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3360 const std::string& systemName)
3361{
3362 PatchParams patchParams;
3363
3364 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3365 {
3366 return;
3367 }
3368
3369 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3370 {
3371 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3372 {
3373 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3374 systemName);
3375 return;
3376 }
3377 }
3378
3379 asyncResp->res.addHeader(
3380 boost::beast::http::field::link,
3381 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3382
3383 if (!json_util::readJsonPatch(
3384 req, asyncResp->res, //
3385 "AssetTag", patchParams.assetTag, //
3386 "Boot/AutomaticRetryAttempts",
3387 patchParams.bootAutomaticRetryAttempts, //
3388 "Boot/AutomaticRetryConfig", patchParams.bootAutomaticRetry, //
3389 "Boot/BootSourceOverrideEnabled", patchParams.bootEnable, //
3390 "Boot/BootSourceOverrideMode", patchParams.bootType, //
3391 "Boot/BootSourceOverrideTarget", patchParams.bootSource, //
3392 "Boot/StopBootOnFault", patchParams.stopBootOnFault, //
3393 "Boot/TrustedModuleRequiredToBoot",
3394 patchParams.bootTrustedModuleRequired, //
3395 "HostWatchdogTimer/FunctionEnabled", patchParams.wdtEnable, //
3396 "HostWatchdogTimer/TimeoutAction", patchParams.wdtTimeOutAction, //
3397 "IdlePowerSaver/Enabled", patchParams.ipsEnable, //
3398 "IdlePowerSaver/EnterDwellTimeSeconds", patchParams.ipsEnterTime, //
3399 "IdlePowerSaver/EnterUtilizationPercent",
3400 patchParams.ipsEnterUtil, //
3401 "IdlePowerSaver/ExitDwellTimeSeconds", patchParams.ipsExitTime, //
3402 "IdlePowerSaver/ExitUtilizationPercent", patchParams.ipsExitUtil, //
3403 "IndicatorLED", patchParams.indicatorLed, //
3404 "LocationIndicatorActive", patchParams.locationIndicatorActive, //
3405 "PowerMode", patchParams.powerMode, //
3406 "PowerRestorePolicy", patchParams.powerRestorePolicy))
3407 {
3408 return;
3409 }
3410
3411 getComputerSystemIndex(asyncResp, systemName,
3412 std::bind_front(processComputerSystemPatch,
3413 asyncResp, systemName, patchParams));
3414}
3415
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003416inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003417 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003418 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003419 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003420{
3421 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3422 {
3423 return;
3424 }
3425 asyncResp->res.addHeader(
3426 boost::beast::http::field::link,
3427 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3428}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003429
3430/**
3431 * @brief Translates allowed host transitions to redfish string
3432 *
3433 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3434 * @param[out] allowableValues The translated host transition(s)
3435 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303436 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003437 * allowableValues. If translation not possible, does nothing to
3438 * allowableValues.
3439 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003440inline void dbusToRfAllowedHostTransitions(
3441 const std::string& dbusAllowedHostTran,
3442 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003443{
3444 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3445 {
3446 allowableValues.emplace_back(resource::ResetType::On);
3447 allowableValues.emplace_back(resource::ResetType::ForceOn);
3448 }
3449 else if (dbusAllowedHostTran ==
3450 "xyz.openbmc_project.State.Host.Transition.Off")
3451 {
3452 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3453 }
3454 else if (dbusAllowedHostTran ==
3455 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3456 {
3457 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3458 }
3459 else if (dbusAllowedHostTran ==
3460 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3461 {
3462 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3463 }
3464 else
3465 {
3466 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3467 }
3468}
3469
3470inline void afterGetAllowedHostTransitions(
3471 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3472 const boost::system::error_code& ec,
3473 const std::vector<std::string>& allowedHostTransitions)
3474{
3475 nlohmann::json::array_t allowableValues;
3476
3477 // Supported on all systems currently
3478 allowableValues.emplace_back(resource::ResetType::ForceOff);
3479 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3480 allowableValues.emplace_back(resource::ResetType::Nmi);
3481
3482 if (ec)
3483 {
Ed Tanouse715d142024-03-07 15:47:37 -08003484 if ((ec.value() ==
3485 boost::system::linux_error::bad_request_descriptor) ||
3486 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003487 {
3488 // Property not implemented so just return defaults
3489 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3490 allowableValues.emplace_back(resource::ResetType::On);
3491 allowableValues.emplace_back(resource::ResetType::ForceOn);
3492 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3493 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3494 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3495 }
3496 else
3497 {
3498 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3499 messages::internalError(asyncResp->res);
3500 return;
3501 }
3502 }
3503 else
3504 {
3505 for (const std::string& transition : allowedHostTransitions)
3506 {
3507 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3508 dbusToRfAllowedHostTransitions(transition, allowableValues);
3509 }
3510 }
3511
3512 nlohmann::json::object_t parameter;
3513 parameter["Name"] = "ResetType";
3514 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003515 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003516 parameter["AllowableValues"] = std::move(allowableValues);
3517 nlohmann::json::array_t parameters;
3518 parameters.emplace_back(std::move(parameter));
3519 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3520}
3521
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003522inline void getAllowedHostTransitions(
3523 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3524 const uint64_t computerSystemIndex)
3525{
Ed Tanousa52f1d52025-08-26 16:34:24 -07003526 sdbusplus::message::object_path path =
3527 getHostStateObjectPath(computerSystemIndex);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003528 dbus::utility::getProperty<std::vector<std::string>>(
Ed Tanousa52f1d52025-08-26 16:34:24 -07003529 getHostStateServiceName(computerSystemIndex), path,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003530 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
3531 std::bind_front(afterGetAllowedHostTransitions, asyncResp));
3532}
3533
Ed Tanousc1e219d2023-06-07 10:34:33 -07003534inline void handleSystemCollectionResetActionGet(
3535 crow::App& app, const crow::Request& req,
3536 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3537 const std::string& systemName)
3538{
3539 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3540 {
3541 return;
3542 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003543
Gunnar Mills68896202024-08-21 11:34:20 -05003544 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003545 {
Gunnar Mills68896202024-08-21 11:34:20 -05003546 if (systemName == "hypervisor")
3547 {
3548 handleHypervisorResetActionGet(asyncResp);
3549 return;
3550 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003551 }
3552
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003553 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003554 {
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003555 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3556 {
3557 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3558 systemName);
3559 return;
3560 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003561 }
3562
3563 asyncResp->res.addHeader(
3564 boost::beast::http::field::link,
3565 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3566
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003567 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3568 "/redfish/v1/Systems/{}/ResetActionInfo", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003569 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3570 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3571 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3572
Andrew Geissler33e1f122024-02-26 21:10:16 -06003573 // Look to see if system defines AllowedHostTransitions
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003574 getComputerSystemIndex(
3575 asyncResp, systemName,
3576 std::bind_front(getAllowedHostTransitions, asyncResp));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003577}
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003578
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303579/**
3580 * SystemResetActionInfo derived class for delivering Computer Systems
3581 * ResetType AllowableValues using ResetInfo schema.
3582 */
Ed Tanous100afe52023-06-07 13:30:46 -07003583inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303584{
Ed Tanous100afe52023-06-07 13:30:46 -07003585 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3586 .privileges(redfish::privileges::headComputerSystemCollection)
3587 .methods(boost::beast::http::verb::head)(
3588 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3589
3590 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3591 .privileges(redfish::privileges::getComputerSystemCollection)
3592 .methods(boost::beast::http::verb::get)(
3593 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3594
3595 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3596 .privileges(redfish::privileges::headComputerSystem)
3597 .methods(boost::beast::http::verb::head)(
3598 std::bind_front(handleComputerSystemHead, std::ref(app)));
3599
3600 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3601 .privileges(redfish::privileges::getComputerSystem)
3602 .methods(boost::beast::http::verb::get)(
3603 std::bind_front(handleComputerSystemGet, std::ref(app)));
3604
3605 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3606 .privileges(redfish::privileges::patchComputerSystem)
3607 .methods(boost::beast::http::verb::patch)(
3608 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3609
3610 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3611 .privileges(redfish::privileges::postComputerSystem)
3612 .methods(boost::beast::http::verb::post)(std::bind_front(
3613 handleComputerSystemResetActionPost, std::ref(app)));
3614
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003615 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003616 .privileges(redfish::privileges::headActionInfo)
3617 .methods(boost::beast::http::verb::head)(std::bind_front(
3618 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003619 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003620 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003621 .methods(boost::beast::http::verb::get)(std::bind_front(
3622 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003623}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003624} // namespace redfish