blob: 19d04b1114e3e0b0588072ca1bc06180e2ac8985 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02004#pragma once
5
Willy Tu13451e32023-05-24 16:08:18 -07006#include "bmcweb_config.h"
7
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08008#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "async_resp.hpp"
Jonathan Doman1e1e5982021-06-11 09:36:17 -070010#include "dbus_singleton.hpp"
George Liu7a1dbc42022-12-07 16:03:22 +080011#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080012#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070013#include "generated/enums/action_info.hpp"
Ed Tanous8d69c662023-06-21 10:29:06 -070014#include "generated/enums/computer_system.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070015#include "generated/enums/open_bmc_computer_system.hpp"
Andrew Geissler33e1f122024-02-26 21:10:16 -060016#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080017#include "http_request.hpp"
Asmitha Karunanithi746b56f2023-02-27 23:29:49 -060018#include "hypervisor_system.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080019#include "led.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080020#include "logging.hpp"
Ed Tanousf4c99e72021-10-04 17:02:43 -070021#include "query.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080022#include "redfish_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080023#include "registries/privilege_registry.hpp"
24#include "utils/dbus_utils.hpp"
25#include "utils/json_utils.hpp"
Lakshmi Yadlapati472bd202023-03-22 09:57:05 -050026#include "utils/pcie_util.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080027#include "utils/sw_utils.hpp"
Oliver Brewkafc5ae942024-08-12 15:04:41 +020028#include "utils/systems_utils.hpp"
Ed Tanous2b829372022-08-03 14:22:34 -070029#include "utils/time_utils.hpp"
Jennifer Leec5d03ff2019-03-08 15:42:58 -080030
Ed Tanousd7857202025-01-28 15:32:26 -080031#include <asm-generic/errno.h>
32
Andrew Geisslerfc903b32023-05-31 14:15:42 -040033#include <boost/asio/error.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080034#include <boost/beast/http/field.hpp>
35#include <boost/beast/http/status.hpp>
36#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
301 const std::string* partNumber = nullptr;
302 const std::string* serialNumber = nullptr;
303 const std::string* manufacturer = nullptr;
304 const std::string* model = nullptr;
305 const std::string* subModel = nullptr;
306
307 const bool success = sdbusplus::unpackPropertiesNoThrow(
308 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
309 partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer,
310 "Model", model, "SubModel", subModel);
311
312 if (!success)
313 {
314 messages::internalError(asyncResp->res);
315 return;
316 }
317
318 if (partNumber != nullptr)
319 {
320 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
321 }
322
323 if (serialNumber != nullptr)
324 {
325 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
326 }
327
328 if (manufacturer != nullptr)
329 {
330 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
331 }
332
333 if (model != nullptr)
334 {
335 asyncResp->res.jsonValue["Model"] = *model;
336 }
337
338 if (subModel != nullptr)
339 {
340 asyncResp->res.jsonValue["SubModel"] = *subModel;
341 }
342
343 // Grab the bios version
344 sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose,
345 "BiosVersion", false);
346}
347
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400348inline void afterGetAssetTag(
349 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
350 const boost::system::error_code& ec, const std::string& value)
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500351{
352 if (ec)
353 {
354 // doesn't have to include this
355 // interface
356 return;
357 }
358
359 asyncResp->res.jsonValue["AssetTag"] = value;
360}
361
362inline void afterSystemGetSubTree(
363 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500364 const boost::system::error_code& ec,
365 const dbus::utility::MapperGetSubTreeResponse& subtree)
366{
367 if (ec)
368 {
369 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
370 messages::internalError(asyncResp->res);
371 return;
372 }
373 // Iterate over all retrieved ObjectPaths.
374 for (const std::pair<
375 std::string,
376 std::vector<std::pair<std::string, std::vector<std::string>>>>&
377 object : subtree)
378 {
379 const std::string& path = object.first;
380 BMCWEB_LOG_DEBUG("Got path: {}", path);
381 const std::vector<std::pair<std::string, std::vector<std::string>>>&
382 connectionNames = object.second;
383 if (connectionNames.empty())
384 {
385 continue;
386 }
387
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500388 // This is not system, so check if it's cpu, dimm, UUID or
389 // BiosVer
390 for (const auto& connection : connectionNames)
391 {
392 for (const auto& interfaceName : connection.second)
393 {
394 if (interfaceName == "xyz.openbmc_project.Inventory.Item.Dimm")
395 {
396 BMCWEB_LOG_DEBUG("Found Dimm, now get its properties.");
397
398 getMemorySummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500399 }
400 else if (interfaceName ==
401 "xyz.openbmc_project.Inventory.Item.Cpu")
402 {
403 BMCWEB_LOG_DEBUG("Found Cpu, now get its properties.");
404
405 getProcessorSummary(asyncResp, connection.first, path);
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500406 }
407 else if (interfaceName == "xyz.openbmc_project.Common.UUID")
408 {
409 BMCWEB_LOG_DEBUG("Found UUID, now get its properties.");
410
Ed Tanousdeae6a72024-11-11 21:58:57 -0800411 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500412 *crow::connections::systemBus, connection.first, path,
413 "xyz.openbmc_project.Common.UUID",
414 [asyncResp](const boost::system::error_code& ec3,
415 const dbus::utility::DBusPropertiesMap&
416 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400417 afterGetUUID(asyncResp, ec3, properties);
418 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500419 }
420 else if (interfaceName ==
421 "xyz.openbmc_project.Inventory.Item.System")
422 {
Ed Tanousdeae6a72024-11-11 21:58:57 -0800423 dbus::utility::getAllProperties(
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500424 *crow::connections::systemBus, connection.first, path,
425 "xyz.openbmc_project.Inventory.Decorator.Asset",
426 [asyncResp](const boost::system::error_code& ec3,
427 const dbus::utility::DBusPropertiesMap&
428 properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400429 afterGetInventory(asyncResp, ec3, properties);
430 });
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500431
Ed Tanousdeae6a72024-11-11 21:58:57 -0800432 dbus::utility::getProperty<std::string>(
433 connection.first, path,
Lakshmi Yadlapatia974c132023-10-25 15:31:25 -0500434 "xyz.openbmc_project.Inventory.Decorator."
435 "AssetTag",
436 "AssetTag",
437 std::bind_front(afterGetAssetTag, asyncResp));
438 }
439 }
440 }
441 }
442}
443
Ninad Palsulecf0e0042023-05-18 17:18:09 -0500444/*
Ed Tanous6c34de42018-08-29 13:37:36 -0700445 * @brief Retrieves computer system properties over dbus
446 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700447 * @param[in] asyncResp Shared pointer for completing asynchronous calls
Ed Tanous6c34de42018-08-29 13:37:36 -0700448 *
449 * @return None.
450 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500451inline void getComputerSystem(
452 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous6c34de42018-08-29 13:37:36 -0700453{
Ed Tanous62598e32023-07-17 17:06:25 -0700454 BMCWEB_LOG_DEBUG("Get available system components.");
George Liue99073f2022-12-09 11:06:16 +0800455 constexpr std::array<std::string_view, 5> interfaces = {
456 "xyz.openbmc_project.Inventory.Decorator.Asset",
457 "xyz.openbmc_project.Inventory.Item.Cpu",
458 "xyz.openbmc_project.Inventory.Item.Dimm",
459 "xyz.openbmc_project.Inventory.Item.System",
460 "xyz.openbmc_project.Common.UUID",
461 };
462 dbus::utility::getSubTree(
463 "/xyz/openbmc_project/inventory", 0, interfaces,
Gunnar Mills51bd2d82024-04-01 15:25:51 -0500464 std::bind_front(afterSystemGetSubTree, asyncResp));
Ed Tanous6c34de42018-08-29 13:37:36 -0700465}
466
467/**
Ed Tanous6c34de42018-08-29 13:37:36 -0700468 * @brief Retrieves host state properties over dbus
469 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700470 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200471 * @param[in] computerSystemIndex Index associated with the requested system
Ed Tanous6c34de42018-08-29 13:37:36 -0700472 *
473 * @return None.
474 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200475inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
476 const uint64_t computerSystemIndex)
Ed Tanous6c34de42018-08-29 13:37:36 -0700477{
Ed Tanous62598e32023-07-17 17:06:25 -0700478 BMCWEB_LOG_DEBUG("Get host information.");
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200479
Ed Tanousdeae6a72024-11-11 21:58:57 -0800480 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200481 getHostStateServiceName(computerSystemIndex),
482 getHostStateObjectPath(computerSystemIndex),
Ed Tanousdeae6a72024-11-11 21:58:57 -0800483 "xyz.openbmc_project.State.Host", "CurrentHostState",
Ed Tanousac106bf2023-06-07 09:24:59 -0700484 [asyncResp](const boost::system::error_code& ec,
485 const std::string& hostState) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400486 if (ec)
Ed Tanous6c34de42018-08-29 13:37:36 -0700487 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400488 if (ec == boost::system::errc::host_unreachable)
489 {
490 // Service not available, no error, just don't return
491 // host state info
492 BMCWEB_LOG_DEBUG("Service not available {}", ec);
493 return;
494 }
495 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
496 messages::internalError(asyncResp->res);
Ed Tanous6c34de42018-08-29 13:37:36 -0700497 return;
498 }
Ed Tanous66173382018-08-15 18:20:59 -0700499
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400500 BMCWEB_LOG_DEBUG("Host state: {}", hostState);
501 // Verify Host State
502 if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
503 {
504 asyncResp->res.jsonValue["PowerState"] =
505 resource::PowerState::On;
506 asyncResp->res.jsonValue["Status"]["State"] =
507 resource::State::Enabled;
508 }
509 else if (hostState ==
510 "xyz.openbmc_project.State.Host.HostState.Quiesced")
511 {
512 asyncResp->res.jsonValue["PowerState"] =
513 resource::PowerState::On;
514 asyncResp->res.jsonValue["Status"]["State"] =
515 resource::State::Quiesced;
516 }
517 else if (hostState ==
518 "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
519 {
520 asyncResp->res.jsonValue["PowerState"] =
521 resource::PowerState::On;
522 asyncResp->res.jsonValue["Status"]["State"] =
523 resource::State::InTest;
524 }
525 else if (
526 hostState ==
527 "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
528 {
529 asyncResp->res.jsonValue["PowerState"] =
530 resource::PowerState::PoweringOn;
531 asyncResp->res.jsonValue["Status"]["State"] =
532 resource::State::Starting;
533 }
534 else if (
535 hostState ==
536 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
537 {
538 asyncResp->res.jsonValue["PowerState"] =
539 resource::PowerState::PoweringOff;
540 asyncResp->res.jsonValue["Status"]["State"] =
541 resource::State::Disabled;
542 }
543 else
544 {
545 asyncResp->res.jsonValue["PowerState"] =
546 resource::PowerState::Off;
547 asyncResp->res.jsonValue["Status"]["State"] =
548 resource::State::Disabled;
549 }
550 });
Ed Tanous6c34de42018-08-29 13:37:36 -0700551}
552
553/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500554 * @brief Translates boot source DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530555 *
556 * @param[in] dbusSource The boot source in DBUS speak.
557 *
558 * @return Returns as a string, the boot source in Redfish terms. If translation
559 * cannot be done, returns an empty string.
560 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000561inline std::string dbusToRfBootSource(const std::string& dbusSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530562{
563 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Default")
564 {
565 return "None";
566 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700567 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Disk")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530568 {
569 return "Hdd";
570 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700571 if (dbusSource ==
572 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530573 {
574 return "Cd";
575 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700576 if (dbusSource == "xyz.openbmc_project.Control.Boot.Source.Sources.Network")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530577 {
578 return "Pxe";
579 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700580 if (dbusSource ==
581 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia")
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700582 {
583 return "Usb";
584 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700585 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530586}
587
588/**
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300589 * @brief Translates boot type DBUS property value to redfish.
590 *
591 * @param[in] dbusType The boot type in DBUS speak.
592 *
593 * @return Returns as a string, the boot type in Redfish terms. If translation
594 * cannot be done, returns an empty string.
595 */
596inline std::string dbusToRfBootType(const std::string& dbusType)
597{
598 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.Legacy")
599 {
600 return "Legacy";
601 }
602 if (dbusType == "xyz.openbmc_project.Control.Boot.Type.Types.EFI")
603 {
604 return "UEFI";
605 }
606 return "";
607}
608
609/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500610 * @brief Translates boot mode DBUS property value to redfish.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530611 *
612 * @param[in] dbusMode The boot mode in DBUS speak.
613 *
614 * @return Returns as a string, the boot mode in Redfish terms. If translation
615 * cannot be done, returns an empty string.
616 */
Ed Tanous23a21a12020-07-25 04:45:05 +0000617inline std::string dbusToRfBootMode(const std::string& dbusMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530618{
619 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
620 {
621 return "None";
622 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700623 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530624 {
625 return "Diags";
626 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700627 if (dbusMode == "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530628 {
629 return "BiosSetup";
630 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700631 return "";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530632}
633
634/**
Andrew Geisslere43914b2022-01-06 13:59:39 -0600635 * @brief Translates boot progress DBUS property value to redfish.
636 *
637 * @param[in] dbusBootProgress The boot progress in DBUS speak.
638 *
639 * @return Returns as a string, the boot progress in Redfish terms. If
640 * translation cannot be done, returns "None".
641 */
642inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
643{
644 // Now convert the D-Bus BootProgress to the appropriate Redfish
645 // enum
646 std::string rfBpLastState = "None";
647 if (dbusBootProgress == "xyz.openbmc_project.State.Boot.Progress."
648 "ProgressStages.Unspecified")
649 {
650 rfBpLastState = "None";
651 }
652 else if (dbusBootProgress ==
653 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
654 "PrimaryProcInit")
655 {
656 rfBpLastState = "PrimaryProcessorInitializationStarted";
657 }
658 else if (dbusBootProgress ==
659 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
660 "BusInit")
661 {
662 rfBpLastState = "BusInitializationStarted";
663 }
664 else if (dbusBootProgress ==
665 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
666 "MemoryInit")
667 {
668 rfBpLastState = "MemoryInitializationStarted";
669 }
670 else if (dbusBootProgress ==
671 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
672 "SecondaryProcInit")
673 {
674 rfBpLastState = "SecondaryProcessorInitializationStarted";
675 }
676 else if (dbusBootProgress ==
677 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
678 "PCIInit")
679 {
680 rfBpLastState = "PCIResourceConfigStarted";
681 }
682 else if (dbusBootProgress ==
683 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
684 "SystemSetup")
685 {
686 rfBpLastState = "SetupEntered";
687 }
688 else if (dbusBootProgress ==
689 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
690 "SystemInitComplete")
691 {
692 rfBpLastState = "SystemHardwareInitializationComplete";
693 }
694 else if (dbusBootProgress ==
695 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
696 "OSStart")
697 {
698 rfBpLastState = "OSBootStarted";
699 }
700 else if (dbusBootProgress ==
701 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
702 "OSRunning")
703 {
704 rfBpLastState = "OSRunning";
705 }
706 else
707 {
Ed Tanous62598e32023-07-17 17:06:25 -0700708 BMCWEB_LOG_DEBUG("Unsupported D-Bus BootProgress {}", dbusBootProgress);
Andrew Geisslere43914b2022-01-06 13:59:39 -0600709 // Just return the default
710 }
711 return rfBpLastState;
712}
713
714/**
Gunnar Mills786d0f62020-07-08 13:43:15 -0500715 * @brief Translates boot source from Redfish to the DBus boot paths.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530716 *
717 * @param[in] rfSource The boot source in Redfish.
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700718 * @param[out] bootSource The DBus source
719 * @param[out] bootMode the DBus boot mode
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530720 *
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700721 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530722 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400723inline int assignBootParameters(
724 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
725 const std::string& rfSource, std::string& bootSource, std::string& bootMode)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530726{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300727 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
728 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700729
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530730 if (rfSource == "None")
731 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700732 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530733 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700734 if (rfSource == "Pxe")
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530735 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700736 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Network";
737 }
738 else if (rfSource == "Hdd")
739 {
740 bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Disk";
741 }
742 else if (rfSource == "Diags")
743 {
744 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe";
745 }
746 else if (rfSource == "Cd")
747 {
748 bootSource =
749 "xyz.openbmc_project.Control.Boot.Source.Sources.ExternalMedia";
750 }
751 else if (rfSource == "BiosSetup")
752 {
753 bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup";
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530754 }
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700755 else if (rfSource == "Usb")
756 {
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700757 bootSource =
758 "xyz.openbmc_project.Control.Boot.Source.Sources.RemovableMedia";
Jennifer Lee9f16b2c2019-04-19 15:33:48 -0700759 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530760 else
761 {
Ed Tanous62598e32023-07-17 17:06:25 -0700762 BMCWEB_LOG_DEBUG(
763 "Invalid property value for BootSourceOverrideTarget: {}",
764 bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -0700765 messages::propertyValueNotInList(asyncResp->res, rfSource,
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700766 "BootSourceTargetOverride");
767 return -1;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530768 }
Johnathan Mantey944ffaf2019-08-12 16:16:14 -0700769 return 0;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530770}
Ali Ahmed19817712021-06-29 17:01:52 -0500771
Andrew Geissler978b8802020-11-19 13:36:40 -0600772/**
773 * @brief Retrieves boot progress of the system
774 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700775 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200776 * @param[in] computerSystemIndex Index associated with the requested system
Andrew Geissler978b8802020-11-19 13:36:40 -0600777 *
778 * @return None.
779 */
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200780inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
781 const uint64_t computerSystemIndex)
Andrew Geissler978b8802020-11-19 13:36:40 -0600782{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800783 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200784 getHostStateServiceName(computerSystemIndex),
785 getHostStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700786 "xyz.openbmc_project.State.Boot.Progress", "BootProgress",
Ed Tanousac106bf2023-06-07 09:24:59 -0700787 [asyncResp](const boost::system::error_code& ec,
788 const std::string& bootProgressStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400789 if (ec)
790 {
791 // BootProgress is an optional object so just do nothing if
792 // not found
793 return;
794 }
Andrew Geissler978b8802020-11-19 13:36:40 -0600795
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400796 BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
Andrew Geissler978b8802020-11-19 13:36:40 -0600797
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400798 asyncResp->res.jsonValue["BootProgress"]["LastState"] =
799 dbusToRfBootProgress(bootProgressStr);
800 });
Andrew Geissler978b8802020-11-19 13:36:40 -0600801}
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530802
803/**
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000804 * @brief Retrieves boot progress Last Update of the system
805 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700806 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200807 * @param[in] computerSystemIndex Index associated with the requested system
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000808 *
809 * @return None.
810 */
811inline void getBootProgressLastStateTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200812 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
813 const uint64_t computerSystemIndex)
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000814{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800815 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200816 getHostStateServiceName(computerSystemIndex),
817 getHostStateObjectPath(computerSystemIndex),
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000818 "xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
Ed Tanousac106bf2023-06-07 09:24:59 -0700819 [asyncResp](const boost::system::error_code& ec,
820 const uint64_t lastStateTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400821 if (ec)
822 {
823 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
824 return;
825 }
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000826
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400827 // BootProgressLastUpdate is the last time the BootProgress property
828 // was updated. The time is the Epoch time, number of microseconds
829 // since 1 Jan 1970 00::00::00 UTC."
830 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
831 // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000832
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400833 // Convert to ISO 8601 standard
834 asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
835 redfish::time_utils::getDateTimeUintUs(lastStateTime);
836 });
Hieu Huynhb6d5d452022-10-07 09:41:46 +0000837}
838
839/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300840 * @brief Retrieves boot override type over DBUS and fills out the response
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300841 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700842 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200843 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300844 *
845 * @return None.
846 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500847inline void getBootOverrideType(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200848 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
849 const uint64_t computerSystemIndex)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300850{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200851 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
852 std::to_string(computerSystemIndex));
853 path /= "boot";
854
Ed Tanousdeae6a72024-11-11 21:58:57 -0800855 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200856 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700857 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ed Tanousac106bf2023-06-07 09:24:59 -0700858 [asyncResp](const boost::system::error_code& ec,
859 const std::string& bootType) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400860 if (ec)
861 {
862 // not an error, don't have to have the interface
863 return;
864 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300865
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400866 BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300867
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400868 asyncResp->res
869 .jsonValue["Boot"]
870 ["BootSourceOverrideMode@Redfish.AllowableValues"] =
871 nlohmann::json::array_t({"Legacy", "UEFI"});
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300872
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400873 auto rfType = dbusToRfBootType(bootType);
874 if (rfType.empty())
875 {
876 messages::internalError(asyncResp->res);
877 return;
878 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300879
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400880 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
881 });
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300882}
883
884/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300885 * @brief Retrieves boot override mode over DBUS and fills out the response
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530886 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700887 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200888 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530889 *
890 * @return None.
891 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500892inline void getBootOverrideMode(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200893 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
894 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530895{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200896 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
897 std::to_string(computerSystemIndex));
898 path /= "boot";
Ed Tanousdeae6a72024-11-11 21:58:57 -0800899 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200900 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700901 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ed Tanousac106bf2023-06-07 09:24:59 -0700902 [asyncResp](const boost::system::error_code& ec,
903 const std::string& bootModeStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400904 if (ec)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530905 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400906 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
907 messages::internalError(asyncResp->res);
908 return;
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530909 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400910
911 BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
912
913 nlohmann::json::array_t allowed;
914 allowed.emplace_back("None");
915 allowed.emplace_back("Pxe");
916 allowed.emplace_back("Hdd");
917 allowed.emplace_back("Cd");
918 allowed.emplace_back("Diags");
919 allowed.emplace_back("BiosSetup");
920 allowed.emplace_back("Usb");
921
922 asyncResp->res
923 .jsonValue["Boot"]
924 ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
925 std::move(allowed);
926 if (bootModeStr !=
927 "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
928 {
929 auto rfMode = dbusToRfBootMode(bootModeStr);
930 if (!rfMode.empty())
931 {
932 asyncResp->res
933 .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
934 }
935 }
936 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530937}
938
939/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300940 * @brief Retrieves boot override source over DBUS
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530941 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700942 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200943 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530944 *
945 * @return None.
946 */
Patrick Williams504af5a2025-02-03 14:29:03 -0500947inline void getBootOverrideSource(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200948 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
949 const uint64_t computerSystemIndex)
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530950{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200951 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
952 std::to_string(computerSystemIndex));
953 path /= "boot";
954
Ed Tanousdeae6a72024-11-11 21:58:57 -0800955 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200956 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700957 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200958 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
959 const std::string& bootSourceStr) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400960 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +0000961 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800962 // Service not available, no error, just don't return
963 // Boot Override Source information
964 if (ec.value() != EBADR &&
965 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400966 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +0800967 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
968 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400969 }
Nan Zhou5ef735c2022-06-22 05:24:21 +0000970 return;
971 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530972
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400973 BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530974
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400975 auto rfSource = dbusToRfBootSource(bootSourceStr);
976 if (!rfSource.empty())
977 {
978 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
979 rfSource;
980 }
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +0300981
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400982 // Get BootMode as BootSourceOverrideTarget is constructed
983 // from both BootSource and BootMode
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200984 getBootOverrideMode(asyncResp, computerSystemIndex);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400985 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530986}
987
988/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +0300989 * @brief This functions abstracts all the logic behind getting a
990 * "BootSourceOverrideEnabled" property from an overall boot override enable
991 * state
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530992 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700993 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +0200994 * @param[in] computerSystemIndex Index associated with the requested system
995 * @param[in] bootOverrideEnableSetting
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530996 *
997 * @return None.
998 */
Santosh Puranik491d8ee2019-02-06 19:46:56 +0530999
Ed Tanousac106bf2023-06-07 09:24:59 -07001000inline void processBootOverrideEnable(
1001 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001002 const uint64_t computerSystemIndex, const bool bootOverrideEnableSetting)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001003{
1004 if (!bootOverrideEnableSetting)
1005 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001006 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1007 "Disabled";
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001008 return;
1009 }
1010
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001011 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1012 std::to_string(computerSystemIndex));
1013 path /= "boot";
1014 path /= "one_time";
1015
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001016 // If boot source override is enabled, we need to check 'one_time'
1017 // property to set a correct value for the "BootSourceOverrideEnabled"
Ed Tanousdeae6a72024-11-11 21:58:57 -08001018 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001019 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001020 "xyz.openbmc_project.Object.Enable", "Enabled",
Ed Tanousac106bf2023-06-07 09:24:59 -07001021 [asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001022 if (ec)
1023 {
1024 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1025 messages::internalError(asyncResp->res);
1026 return;
1027 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301028
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001029 if (oneTimeSetting)
1030 {
1031 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1032 "Once";
1033 }
1034 else
1035 {
1036 asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
1037 "Continuous";
1038 }
1039 });
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301040}
1041
1042/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001043 * @brief Retrieves boot override enable over DBUS
1044 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001045 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001046 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001047 *
1048 * @return None.
1049 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001050inline void getBootOverrideEnable(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001051 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1052 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001053{
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001054 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1055 std::to_string(computerSystemIndex));
1056 path /= "boot";
1057
Ed Tanousdeae6a72024-11-11 21:58:57 -08001058 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001059 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001060 "xyz.openbmc_project.Object.Enable", "Enabled",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001061 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1062 const bool bootOverrideEnable) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001063 if (ec)
Nan Zhou5ef735c2022-06-22 05:24:21 +00001064 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001065 // Service not available, no error, just don't return
1066 // Boot Override Enable information
1067 if (ec.value() != EBADR &&
1068 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001069 {
Allen.Wang8f1a35b2025-06-17 20:39:56 +08001070 BMCWEB_LOG_ERROR("D-Bus response error: {}", ec);
1071 messages::internalError(asyncResp->res);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001072 }
Nan Zhou5ef735c2022-06-22 05:24:21 +00001073 return;
1074 }
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001075
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001076 processBootOverrideEnable(asyncResp, computerSystemIndex,
1077 bootOverrideEnable);
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001078 });
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001079}
1080
1081/**
1082 * @brief Retrieves boot source override properties
1083 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001084 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001085 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001086 *
1087 * @return None.
1088 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001089inline void getBootProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001090 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1091 const uint64_t computerSystemIndex)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001092{
Ed Tanous62598e32023-07-17 17:06:25 -07001093 BMCWEB_LOG_DEBUG("Get boot information.");
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001094
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001095 getBootOverrideSource(asyncResp, computerSystemIndex);
1096 getBootOverrideType(asyncResp, computerSystemIndex);
1097 getBootOverrideEnable(asyncResp, computerSystemIndex);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001098}
1099
1100/**
Gunnar Millsc0557e12020-06-30 11:26:20 -05001101 * @brief Retrieves the Last Reset Time
1102 *
1103 * "Reset" is an overloaded term in Redfish, "Reset" includes power on
1104 * and power off. Even though this is the "system" Redfish object look at the
1105 * chassis D-Bus interface for the LastStateChangeTime since this has the
1106 * last power operation time.
1107 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001108 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Millsc0557e12020-06-30 11:26:20 -05001109 *
1110 * @return None.
1111 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001112inline void getLastResetTime(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001113 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1114 const uint64_t computerSystemIndex)
Gunnar Millsc0557e12020-06-30 11:26:20 -05001115{
Ed Tanous62598e32023-07-17 17:06:25 -07001116 BMCWEB_LOG_DEBUG("Getting System Last Reset Time");
Gunnar Millsc0557e12020-06-30 11:26:20 -05001117
Ed Tanousdeae6a72024-11-11 21:58:57 -08001118 dbus::utility::getProperty<uint64_t>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001119 getChassisStateServiceName(computerSystemIndex),
1120 getChassisStateObjectPath(computerSystemIndex),
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001121 "xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
Ed Tanousac106bf2023-06-07 09:24:59 -07001122 [asyncResp](const boost::system::error_code& ec,
1123 uint64_t lastResetTime) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001124 if (ec)
1125 {
1126 BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
1127 return;
1128 }
Gunnar Millsc0557e12020-06-30 11:26:20 -05001129
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001130 // LastStateChangeTime is epoch time, in milliseconds
1131 // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
1132 uint64_t lastResetTimeStamp = lastResetTime / 1000;
Gunnar Millsc0557e12020-06-30 11:26:20 -05001133
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001134 // Convert to ISO 8601 standard
1135 asyncResp->res.jsonValue["LastResetTime"] =
1136 redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
1137 });
Gunnar Millsc0557e12020-06-30 11:26:20 -05001138}
1139
1140/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001141 * @brief Retrieves the number of automatic boot Retry attempts allowed/left.
1142 *
1143 * The total number of automatic reboot retries allowed "RetryAttempts" and its
1144 * corresponding property "AttemptsLeft" that keeps track of the amount of
1145 * automatic retry attempts left are hosted in phosphor-state-manager through
1146 * dbus.
1147 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001148 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001149 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001150 *
1151 * @return None.
1152 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001153inline void getAutomaticRebootAttempts(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001154 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1155 const uint64_t computerSystemIndex)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001156{
Ed Tanous62598e32023-07-17 17:06:25 -07001157 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Corey Hardesty797d5da2022-04-26 17:54:52 +08001158
Ed Tanousdeae6a72024-11-11 21:58:57 -08001159 dbus::utility::getAllProperties(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001160 getHostStateServiceName(computerSystemIndex),
1161 getHostStateObjectPath(computerSystemIndex),
Corey Hardesty797d5da2022-04-26 17:54:52 +08001162 "xyz.openbmc_project.Control.Boot.RebootAttempts",
Ed Tanousac106bf2023-06-07 09:24:59 -07001163 [asyncResp{asyncResp}](
1164 const boost::system::error_code& ec,
1165 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001166 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001167 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301168 if (ec.value() != EBADR &&
1169 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001170 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301171 // Service not available, no error, just don't return
1172 // RebootAttempts information
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001173 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1174 messages::internalError(asyncResp->res);
1175 }
1176 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001177 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001178
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001179 const uint32_t* attemptsLeft = nullptr;
1180 const uint32_t* retryAttempts = nullptr;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001181
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001182 const bool success = sdbusplus::unpackPropertiesNoThrow(
1183 dbus_utils::UnpackErrorPrinter(), propertiesList,
1184 "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001185
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001186 if (!success)
1187 {
1188 messages::internalError(asyncResp->res);
1189 return;
1190 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001191
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001192 if (attemptsLeft != nullptr)
1193 {
1194 asyncResp->res
1195 .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
1196 *attemptsLeft;
1197 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08001198
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001199 if (retryAttempts != nullptr)
1200 {
1201 asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
1202 *retryAttempts;
1203 }
1204 });
Corey Hardesty797d5da2022-04-26 17:54:52 +08001205}
1206
1207/**
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001208 * @brief Retrieves Automatic Retry properties. Known on D-Bus as AutoReboot.
1209 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001210 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001211 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001212 *
1213 * @return None.
1214 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001215inline void getAutomaticRetryPolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001216 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1217 const uint64_t computerSystemIndex)
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001218{
Ed Tanous62598e32023-07-17 17:06:25 -07001219 BMCWEB_LOG_DEBUG("Get Automatic Retry policy");
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001220
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001221 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1222 std::to_string(computerSystemIndex));
1223 path /= "auto_reboot";
1224
Ed Tanousdeae6a72024-11-11 21:58:57 -08001225 dbus::utility::getProperty<bool>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001226 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001227 "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001228 [asyncResp, computerSystemIndex](const boost::system::error_code& ec,
1229 bool autoRebootEnabled) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001230 if (ec)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001231 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301232 // Service not available, no error, just don't return
1233 // AutoReboot information
1234 if (ec.value() != EBADR &&
1235 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001236 {
1237 BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1238 messages::internalError(asyncResp->res);
1239 }
1240 return;
Corey Hardesty797d5da2022-04-26 17:54:52 +08001241 }
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001242
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001243 BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
1244 if (autoRebootEnabled)
1245 {
1246 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1247 "RetryAttempts";
1248 }
1249 else
1250 {
1251 asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
1252 "Disabled";
1253 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001254 getAutomaticRebootAttempts(asyncResp, computerSystemIndex);
Gunnar Mills69f35302020-05-17 16:06:31 -05001255
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001256 // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
1257 // and RetryAttempts. OpenBMC only supports Disabled and
1258 // RetryAttempts.
1259 nlohmann::json::array_t allowed;
1260 allowed.emplace_back("Disabled");
1261 allowed.emplace_back("RetryAttempts");
1262 asyncResp->res
1263 .jsonValue["Boot"]
1264 ["AutomaticRetryConfig@Redfish.AllowableValues"] =
1265 std::move(allowed);
1266 });
Gunnar Mills6bd5a8d2020-05-16 18:49:33 -05001267}
1268
1269/**
Corey Hardesty797d5da2022-04-26 17:54:52 +08001270 * @brief Sets RetryAttempts
1271 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001272 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001273 * @param[in] computerSystemIndex Index associated with the requested system
Corey Hardesty797d5da2022-04-26 17:54:52 +08001274 * @param[in] retryAttempts "AutomaticRetryAttempts" from request.
1275 *
1276 *@return None.
1277 */
1278
Ed Tanousac106bf2023-06-07 09:24:59 -07001279inline void setAutomaticRetryAttempts(
1280 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001281 const uint64_t computerSystemIndex, const uint32_t retryAttempts)
Corey Hardesty797d5da2022-04-26 17:54:52 +08001282{
Ed Tanous62598e32023-07-17 17:06:25 -07001283 BMCWEB_LOG_DEBUG("Set Automatic Retry Attempts.");
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001284
1285 setDbusProperty(asyncResp, "Boot/AutomaticRetryAttempts",
1286 getHostStateServiceName(computerSystemIndex),
1287 getHostStateObjectPath(computerSystemIndex),
1288 "xyz.openbmc_project.Control.Boot.RebootAttempts",
1289 "RetryAttempts", retryAttempts);
Corey Hardesty797d5da2022-04-26 17:54:52 +08001290}
1291
Ed Tanous8d69c662023-06-21 10:29:06 -07001292inline computer_system::PowerRestorePolicyTypes
1293 redfishPowerRestorePolicyFromDbus(std::string_view value)
1294{
1295 if (value ==
1296 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn")
1297 {
1298 return computer_system::PowerRestorePolicyTypes::AlwaysOn;
1299 }
1300 if (value ==
1301 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff")
1302 {
1303 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1304 }
1305 if (value ==
Gunnar Mills3a34b742023-07-28 10:17:14 -05001306 "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore")
Ed Tanous8d69c662023-06-21 10:29:06 -07001307 {
1308 return computer_system::PowerRestorePolicyTypes::LastState;
1309 }
1310 if (value == "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None")
1311 {
1312 return computer_system::PowerRestorePolicyTypes::AlwaysOff;
1313 }
1314 return computer_system::PowerRestorePolicyTypes::Invalid;
1315}
Corey Hardesty797d5da2022-04-26 17:54:52 +08001316/**
George Liuc6a620f2020-04-10 17:18:11 +08001317 * @brief Retrieves power restore policy over DBUS.
1318 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001319 * @param[in] asyncResp Shared pointer for generating response message.
George Liuc6a620f2020-04-10 17:18:11 +08001320 *
1321 * @return None.
1322 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001323inline void getPowerRestorePolicy(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001324 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1325 const uint64_t computerSystemIndex)
George Liuc6a620f2020-04-10 17:18:11 +08001326{
Ed Tanous62598e32023-07-17 17:06:25 -07001327 BMCWEB_LOG_DEBUG("Get power restore policy");
George Liuc6a620f2020-04-10 17:18:11 +08001328
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001329 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1330 std::to_string(computerSystemIndex));
1331 path /= "power_restore_policy";
1332
Ed Tanousdeae6a72024-11-11 21:58:57 -08001333 dbus::utility::getProperty<std::string>(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001334 "xyz.openbmc_project.Settings", path,
Jonathan Doman1e1e5982021-06-11 09:36:17 -07001335 "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
Ed Tanousac106bf2023-06-07 09:24:59 -07001336 [asyncResp](const boost::system::error_code& ec,
1337 const std::string& policy) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001338 if (ec)
1339 {
1340 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
1341 return;
1342 }
1343 computer_system::PowerRestorePolicyTypes restore =
1344 redfishPowerRestorePolicyFromDbus(policy);
1345 if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
1346 {
1347 messages::internalError(asyncResp->res);
1348 return;
1349 }
George Liuc6a620f2020-04-10 17:18:11 +08001350
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001351 asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
1352 });
George Liuc6a620f2020-04-10 17:18:11 +08001353}
1354
1355/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001356 * @brief Stop Boot On Fault over DBUS.
1357 *
1358 * @param[in] asyncResp Shared pointer for generating response message.
1359 *
1360 * @return None.
1361 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001362inline void getStopBootOnFault(
1363 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001364{
Ed Tanous62598e32023-07-17 17:06:25 -07001365 BMCWEB_LOG_DEBUG("Get Stop Boot On Fault");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001366
Ed Tanousdeae6a72024-11-11 21:58:57 -08001367 dbus::utility::getProperty<bool>(
1368 "xyz.openbmc_project.Settings", "/xyz/openbmc_project/logging/settings",
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001369 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
1370 [asyncResp](const boost::system::error_code& ec, bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001371 if (ec)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001372 {
Aishwary Joshid39a8c22025-05-08 19:18:43 +05301373 // Service not available, no error, just don't return
1374 // StopBootOnFault information
1375 if (ec.value() != EBADR ||
1376 ec.value() != boost::asio::error::host_unreachable)
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001377 {
1378 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
1379 messages::internalError(asyncResp->res);
1380 }
1381 return;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001382 }
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001383
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001384 if (value)
1385 {
1386 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1387 computer_system::StopBootOnFault::AnyFault;
1388 }
1389 else
1390 {
1391 asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
1392 computer_system::StopBootOnFault::Never;
1393 }
1394 });
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001395}
1396
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001397inline void getTrustedModuleRequiredToBootCallback(
1398 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1399 const uint64_t computerSystemIndex, const boost::system::error_code& ec,
1400 const dbus::utility::MapperGetSubTreeResponse& subtree)
1401{
1402 if (ec)
1403 {
1404 BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}", ec);
1405 // This is an optional D-Bus object so just return if
1406 // error occurs
1407 return;
1408 }
1409 if (subtree.empty())
1410 {
1411 // As noted above, this is an optional interface so just return
1412 // if there is no instance found
1413 return;
1414 }
1415
1416 std::string path;
1417 std::string service;
1418
1419 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1420 {
1421 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1422 subtree, path, service))
1423 {
1424 return;
1425 }
1426 }
1427 else
1428 {
1429 // Make sure the Dbus response map has a service and objectPath
1430 // field
1431 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1432 {
1433 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1434 messages::internalError(asyncResp->res);
1435 return;
1436 }
1437
1438 path = subtree[0].first;
1439 service = subtree[0].second.begin()->first;
1440 }
1441
1442 BMCWEB_LOG_DEBUG("found tpm service {}", service);
1443 BMCWEB_LOG_DEBUG("found tpm path {}", path);
1444
1445 // Valid TPM Enable object found, now reading the current value
1446 dbus::utility::getProperty<bool>(
1447 service, path, "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1448 [asyncResp](const boost::system::error_code& ec2, bool tpmRequired) {
1449 if (ec2)
1450 {
1451 BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
1452 ec2);
1453 messages::internalError(asyncResp->res);
1454 return;
1455 }
1456
1457 if (tpmRequired)
1458 {
1459 asyncResp->res
1460 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1461 "Required";
1462 }
1463 else
1464 {
1465 asyncResp->res
1466 .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
1467 "Disabled";
1468 }
1469 });
1470}
1471
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001472/**
Ali Ahmed19817712021-06-29 17:01:52 -05001473 * @brief Get TrustedModuleRequiredToBoot property. Determines whether or not
1474 * TPM is required for booting the host.
1475 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001476 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001477 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed19817712021-06-29 17:01:52 -05001478 *
1479 * @return None.
1480 */
1481inline void getTrustedModuleRequiredToBoot(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001482 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1483 const uint64_t computerSystemIndex)
Ali Ahmed19817712021-06-29 17:01:52 -05001484{
Ed Tanous62598e32023-07-17 17:06:25 -07001485 BMCWEB_LOG_DEBUG("Get TPM required to boot.");
George Liue99073f2022-12-09 11:06:16 +08001486 constexpr std::array<std::string_view, 1> interfaces = {
1487 "xyz.openbmc_project.Control.TPM.Policy"};
1488 dbus::utility::getSubTree(
1489 "/", 0, interfaces,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02001490 std::bind_front(getTrustedModuleRequiredToBootCallback, asyncResp,
1491 computerSystemIndex));
Ali Ahmed19817712021-06-29 17:01:52 -05001492}
1493
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001494inline void setTrustedModuleRequiredToBootCallback(
1495 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1496 const uint64_t computerSystemIndex, const bool tpmRequired,
1497 const boost::system::error_code& ec,
1498 const dbus::utility::MapperGetSubTreeResponse& subtree)
1499{
1500 if (ec)
1501 {
1502 BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}", ec);
1503 messages::internalError(asyncResp->res);
1504 return;
1505 }
1506 if (subtree.empty())
1507 {
1508 messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
1509 "TrustedModuleRequiredToBoot");
1510 return;
1511 }
1512
1513 std::string path;
1514 std::string serv;
1515
1516 if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
1517 {
1518 if (!indexMatchingSubTreeMapObjectPath(asyncResp, computerSystemIndex,
1519 subtree, path, serv))
1520 {
1521 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1522 messages::internalError(asyncResp->res);
1523 return;
1524 }
1525 }
1526 else
1527 {
1528 // Make sure the Dbus response map has a service and objectPath
1529 // field
1530 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1531 {
1532 BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
1533 messages::internalError(asyncResp->res);
1534 return;
1535 }
1536
1537 path = subtree[0].first;
1538 serv = subtree[0].second.begin()->first;
1539 }
1540
1541 if (serv.empty())
1542 {
1543 BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
1544 messages::internalError(asyncResp->res);
1545 return;
1546 }
1547
1548 // Valid TPM Enable object found, now setting the value
1549 setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv, path,
1550 "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
1551 tpmRequired);
1552}
1553
Ali Ahmed19817712021-06-29 17:01:52 -05001554/**
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001555 * @brief Set TrustedModuleRequiredToBoot property. Determines whether or not
1556 * TPM is required for booting the host.
1557 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001558 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001559 * @param[in] computerSystemIndex Index associated with the requested system
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001560 * @param[in] tpmRequired Value to set TPM Required To Boot property to.
1561 *
1562 * @return None.
1563 */
1564inline void setTrustedModuleRequiredToBoot(
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001565 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1566 const uint64_t computerSystemIndex, const bool tpmRequired)
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001567{
Ed Tanous62598e32023-07-17 17:06:25 -07001568 BMCWEB_LOG_DEBUG("Set TrustedModuleRequiredToBoot.");
George Liue99073f2022-12-09 11:06:16 +08001569 constexpr std::array<std::string_view, 1> interfaces = {
1570 "xyz.openbmc_project.Control.TPM.Policy"};
1571 dbus::utility::getSubTree(
1572 "/", 0, interfaces,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001573 std::bind_front(setTrustedModuleRequiredToBootCallback, asyncResp,
1574 computerSystemIndex, tpmRequired));
Ali Ahmed1c05dae2021-06-29 17:49:22 -05001575}
1576
1577/**
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301578 * @brief Sets boot properties into DBUS object(s).
1579 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001580 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001581 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001582 * @param[in] bootType The boot type to set.
1583 * @return Integer error code.
1584 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001585inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001586 const uint64_t computerSystemIndex,
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001587 const std::optional<std::string>& bootType)
1588{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001589 std::string bootTypeStr;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001590
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001591 if (!bootType)
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001592 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001593 return;
1594 }
1595
1596 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001597 BMCWEB_LOG_DEBUG("Boot type: {}", *bootType);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001598 // Figure out which DBUS interface and property to use
1599 if (*bootType == "Legacy")
1600 {
1601 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.Legacy";
1602 }
1603 else if (*bootType == "UEFI")
1604 {
1605 bootTypeStr = "xyz.openbmc_project.Control.Boot.Type.Types.EFI";
1606 }
1607 else
1608 {
Ed Tanous62598e32023-07-17 17:06:25 -07001609 BMCWEB_LOG_DEBUG("Invalid property value for "
1610 "BootSourceOverrideMode: {}",
1611 *bootType);
Ed Tanousac106bf2023-06-07 09:24:59 -07001612 messages::propertyValueNotInList(asyncResp->res, *bootType,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001613 "BootSourceOverrideMode");
1614 return;
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001615 }
1616
1617 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001618 BMCWEB_LOG_DEBUG("DBUS boot type: {}", bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001619
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001620 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1621 std::to_string(computerSystemIndex));
1622 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301623 setDbusProperty(asyncResp, "Boot/BootSourceOverrideMode",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001624 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001625 "xyz.openbmc_project.Control.Boot.Type", "BootType",
Ginu Georgee93abac2024-06-14 17:35:27 +05301626 bootTypeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001627}
1628
1629/**
1630 * @brief Sets boot properties into DBUS object(s).
1631 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001632 * @param[in] asyncResp Shared pointer for generating response
1633 * message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001634 * @param[in] computerSystemIndex Index associated with the requested system
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001635 * @param[in] bootType The boot type to set.
1636 * @return Integer error code.
1637 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001638inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001639 const uint64_t computerSystemIndex,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001640 const std::optional<std::string>& bootEnable)
1641{
1642 if (!bootEnable)
1643 {
1644 return;
1645 }
1646 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001647 BMCWEB_LOG_DEBUG("Boot enable: {}", *bootEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001648
1649 bool bootOverrideEnable = false;
1650 bool bootOverridePersistent = false;
1651 // Figure out which DBUS interface and property to use
1652 if (*bootEnable == "Disabled")
1653 {
1654 bootOverrideEnable = false;
1655 }
1656 else if (*bootEnable == "Once")
1657 {
1658 bootOverrideEnable = true;
1659 bootOverridePersistent = false;
1660 }
1661 else if (*bootEnable == "Continuous")
1662 {
1663 bootOverrideEnable = true;
1664 bootOverridePersistent = true;
1665 }
1666 else
1667 {
Ed Tanous62598e32023-07-17 17:06:25 -07001668 BMCWEB_LOG_DEBUG(
1669 "Invalid property value for BootSourceOverrideEnabled: {}",
1670 *bootEnable);
Ed Tanousac106bf2023-06-07 09:24:59 -07001671 messages::propertyValueNotInList(asyncResp->res, *bootEnable,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001672 "BootSourceOverrideEnabled");
1673 return;
1674 }
1675
1676 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001677 BMCWEB_LOG_DEBUG("DBUS boot override enable: {}", bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001678
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001679 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1680 std::to_string(computerSystemIndex));
1681 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301682 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001683 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001684 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301685 bootOverrideEnable);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001686
1687 if (!bootOverrideEnable)
1688 {
1689 return;
1690 }
1691
1692 // In case boot override is enabled we need to set correct value for the
1693 // 'one_time' enable DBus interface
Ed Tanous62598e32023-07-17 17:06:25 -07001694 BMCWEB_LOG_DEBUG("DBUS boot override persistent: {}",
1695 bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001696
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001697 path /= "one_time";
Ginu Georgee93abac2024-06-14 17:35:27 +05301698 setDbusProperty(asyncResp, "Boot/BootSourceOverrideEnabled",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001699 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001700 "xyz.openbmc_project.Object.Enable", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05301701 !bootOverridePersistent);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001702}
1703
1704/**
1705 * @brief Sets boot properties into DBUS object(s).
1706 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001707 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001708 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301709 * @param[in] bootSource The boot source to set.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301710 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001711 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301712 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001713inline void setBootModeOrSource(
1714 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001715 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001716 const std::optional<std::string>& bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301717{
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001718 std::string bootSourceStr;
1719 std::string bootModeStr;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001720
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001721 if (!bootSource)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301722 {
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001723 return;
1724 }
1725
1726 // Source target specified
Ed Tanous62598e32023-07-17 17:06:25 -07001727 BMCWEB_LOG_DEBUG("Boot source: {}", *bootSource);
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001728 // Figure out which DBUS interface and property to use
Ed Tanousac106bf2023-06-07 09:24:59 -07001729 if (assignBootParameters(asyncResp, *bootSource, bootSourceStr,
1730 bootModeStr) != 0)
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001731 {
Ed Tanous62598e32023-07-17 17:06:25 -07001732 BMCWEB_LOG_DEBUG(
1733 "Invalid property value for BootSourceOverrideTarget: {}",
1734 *bootSource);
Ed Tanousac106bf2023-06-07 09:24:59 -07001735 messages::propertyValueNotInList(asyncResp->res, *bootSource,
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001736 "BootSourceTargetOverride");
1737 return;
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001738 }
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301739
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001740 // Act on validated parameters
Ed Tanous62598e32023-07-17 17:06:25 -07001741 BMCWEB_LOG_DEBUG("DBUS boot source: {}", bootSourceStr);
1742 BMCWEB_LOG_DEBUG("DBUS boot mode: {}", bootModeStr);
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001743
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001744 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1745 std::to_string(computerSystemIndex));
1746 path /= "boot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301747 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001748 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001749 "xyz.openbmc_project.Control.Boot.Source", "BootSource",
Ginu Georgee93abac2024-06-14 17:35:27 +05301750 bootSourceStr);
1751 setDbusProperty(asyncResp, "Boot/BootSourceOverrideTarget",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001752 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001753 "xyz.openbmc_project.Control.Boot.Mode", "BootMode",
Ginu Georgee93abac2024-06-14 17:35:27 +05301754 bootModeStr);
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001755}
Johnathan Mantey944ffaf2019-08-12 16:16:14 -07001756
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001757/**
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001758 * @brief Sets Boot source override properties.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301759 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001760 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001761 * @param[in] computerSystemIndex Index associated with the requested system
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301762 * @param[in] bootSource The boot source from incoming RF request.
Konstantin Aladyshevcd9a4662021-02-26 12:37:07 +03001763 * @param[in] bootType The boot type from incoming RF request.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301764 * @param[in] bootEnable The boot override enable from incoming RF request.
1765 *
Johnathan Mantey265c1602019-08-08 11:02:51 -07001766 * @return Integer error code.
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301767 */
Konstantin Aladyshevc21865c2021-06-21 14:49:16 +03001768
Patrick Williams504af5a2025-02-03 14:29:03 -05001769inline void setBootProperties(
1770 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001771 const uint64_t computerSystemIndex,
Patrick Williams504af5a2025-02-03 14:29:03 -05001772 const std::optional<std::string>& bootSource,
1773 const std::optional<std::string>& bootType,
1774 const std::optional<std::string>& bootEnable)
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301775{
Ed Tanous62598e32023-07-17 17:06:25 -07001776 BMCWEB_LOG_DEBUG("Set boot information.");
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301777
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001778 setBootModeOrSource(asyncResp, computerSystemIndex, bootSource);
1779 setBootType(asyncResp, computerSystemIndex, bootType);
1780 setBootEnable(asyncResp, computerSystemIndex, bootEnable);
Santosh Puranik491d8ee2019-02-06 19:46:56 +05301781}
1782
George Liuc6a620f2020-04-10 17:18:11 +08001783/**
Gunnar Mills98e386e2020-10-30 14:58:09 -05001784 * @brief Sets AssetTag
1785 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001786 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills98e386e2020-10-30 14:58:09 -05001787 * @param[in] assetTag "AssetTag" from request.
1788 *
1789 * @return None.
1790 */
Ed Tanousac106bf2023-06-07 09:24:59 -07001791inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills98e386e2020-10-30 14:58:09 -05001792 const std::string& assetTag)
1793{
George Liue99073f2022-12-09 11:06:16 +08001794 constexpr std::array<std::string_view, 1> interfaces = {
1795 "xyz.openbmc_project.Inventory.Item.System"};
1796 dbus::utility::getSubTree(
1797 "/xyz/openbmc_project/inventory", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07001798 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08001799 assetTag](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08001800 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001801 if (ec)
1802 {
1803 BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
1804 messages::internalError(asyncResp->res);
1805 return;
1806 }
1807 if (subtree.empty())
1808 {
1809 BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
1810 messages::internalError(asyncResp->res);
1811 return;
1812 }
1813 // Assume only 1 system D-Bus object
1814 // Throw an error if there is more than 1
1815 if (subtree.size() > 1)
1816 {
1817 BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
1818 messages::internalError(asyncResp->res);
1819 return;
1820 }
1821 if (subtree[0].first.empty() || subtree[0].second.size() != 1)
1822 {
1823 BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
1824 messages::internalError(asyncResp->res);
1825 return;
1826 }
Gunnar Mills98e386e2020-10-30 14:58:09 -05001827
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001828 const std::string& path = subtree[0].first;
1829 const std::string& service = subtree[0].second.begin()->first;
Gunnar Mills98e386e2020-10-30 14:58:09 -05001830
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001831 if (service.empty())
1832 {
1833 BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
1834 messages::internalError(asyncResp->res);
1835 return;
1836 }
Ed Tanous002d39b2022-05-31 08:59:27 -07001837
Patrick Williamsbd79bce2024-08-16 15:22:20 -04001838 setDbusProperty(asyncResp, "AssetTag", service, path,
1839 "xyz.openbmc_project.Inventory.Decorator.AssetTag",
1840 "AssetTag", assetTag);
1841 });
Gunnar Mills98e386e2020-10-30 14:58:09 -05001842}
1843
1844/**
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001845 * @brief Validate the specified stopBootOnFault is valid and return the
1846 * stopBootOnFault name associated with that string
1847 *
1848 * @param[in] stopBootOnFaultString String representing the desired
1849 * stopBootOnFault
1850 *
1851 * @return stopBootOnFault value or empty if incoming value is not valid
1852 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001853inline std::optional<bool> validstopBootOnFault(
1854 const std::string& stopBootOnFaultString)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001855{
1856 if (stopBootOnFaultString == "AnyFault")
1857 {
1858 return true;
1859 }
1860
1861 if (stopBootOnFaultString == "Never")
1862 {
1863 return false;
1864 }
1865
1866 return std::nullopt;
1867}
1868
1869/**
1870 * @brief Sets stopBootOnFault
1871 *
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001872 * @param[in] asyncResp Shared pointer for generating response message.
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001873 * @param[in] stopBootOnFault "StopBootOnFault" from request.
1874 *
1875 * @return None.
1876 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001877inline void setStopBootOnFault(
1878 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1879 const std::string& stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001880{
Ed Tanous62598e32023-07-17 17:06:25 -07001881 BMCWEB_LOG_DEBUG("Set Stop Boot On Fault.");
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001882
1883 std::optional<bool> stopBootEnabled = validstopBootOnFault(stopBootOnFault);
1884 if (!stopBootEnabled)
1885 {
Ed Tanous62598e32023-07-17 17:06:25 -07001886 BMCWEB_LOG_DEBUG("Invalid property value for StopBootOnFault: {}",
1887 stopBootOnFault);
Ed Tanousfc3edfd2023-07-20 12:41:30 -07001888 messages::propertyValueNotInList(asyncResp->res, stopBootOnFault,
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001889 "StopBootOnFault");
1890 return;
1891 }
1892
Ginu Georgee93abac2024-06-14 17:35:27 +05301893 setDbusProperty(asyncResp, "Boot/StopBootOnFault",
1894 "xyz.openbmc_project.Settings",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001895 sdbusplus::message::object_path(
1896 "/xyz/openbmc_project/logging/settings"),
1897 "xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
Ginu Georgee93abac2024-06-14 17:35:27 +05301898 *stopBootEnabled);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08001899}
1900
1901/**
Gunnar Mills69f35302020-05-17 16:06:31 -05001902 * @brief Sets automaticRetry (Auto Reboot)
1903 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001904 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001905 * @param[in] computerSystemIndex Index associated with the requested system
Gunnar Mills69f35302020-05-17 16:06:31 -05001906 * @param[in] automaticRetryConfig "AutomaticRetryConfig" from request.
1907 *
1908 * @return None.
1909 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001910inline void setAutomaticRetry(
1911 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001912 const uint64_t computerSystemIndex, const std::string& automaticRetryConfig)
Gunnar Mills69f35302020-05-17 16:06:31 -05001913{
Ed Tanous62598e32023-07-17 17:06:25 -07001914 BMCWEB_LOG_DEBUG("Set Automatic Retry.");
Gunnar Mills69f35302020-05-17 16:06:31 -05001915
1916 // OpenBMC only supports "Disabled" and "RetryAttempts".
Ed Tanous543f4402022-01-06 13:12:53 -08001917 bool autoRebootEnabled = false;
Gunnar Mills69f35302020-05-17 16:06:31 -05001918
1919 if (automaticRetryConfig == "Disabled")
1920 {
1921 autoRebootEnabled = false;
1922 }
1923 else if (automaticRetryConfig == "RetryAttempts")
1924 {
1925 autoRebootEnabled = true;
1926 }
1927 else
1928 {
Ed Tanous62598e32023-07-17 17:06:25 -07001929 BMCWEB_LOG_DEBUG("Invalid property value for AutomaticRetryConfig: {}",
1930 automaticRetryConfig);
Ed Tanousac106bf2023-06-07 09:24:59 -07001931 messages::propertyValueNotInList(asyncResp->res, automaticRetryConfig,
Gunnar Mills69f35302020-05-17 16:06:31 -05001932 "AutomaticRetryConfig");
1933 return;
1934 }
1935
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001936 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1937 std::to_string(computerSystemIndex));
1938 path /= "auto_reboot";
Ginu Georgee93abac2024-06-14 17:35:27 +05301939 setDbusProperty(asyncResp, "Boot/AutomaticRetryConfig",
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001940 "xyz.openbmc_project.Settings", path,
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00001941 "xyz.openbmc_project.Control.Boot.RebootPolicy",
Ginu Georgee93abac2024-06-14 17:35:27 +05301942 "AutoReboot", autoRebootEnabled);
Gunnar Mills69f35302020-05-17 16:06:31 -05001943}
1944
Ed Tanous8d69c662023-06-21 10:29:06 -07001945inline std::string dbusPowerRestorePolicyFromRedfish(std::string_view policy)
1946{
1947 if (policy == "AlwaysOn")
1948 {
1949 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn";
1950 }
1951 if (policy == "AlwaysOff")
1952 {
1953 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff";
1954 }
1955 if (policy == "LastState")
1956 {
1957 return "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore";
1958 }
1959 return "";
1960}
1961
Gunnar Mills69f35302020-05-17 16:06:31 -05001962/**
George Liuc6a620f2020-04-10 17:18:11 +08001963 * @brief Sets power restore policy properties.
1964 *
Ed Tanousac106bf2023-06-07 09:24:59 -07001965 * @param[in] asyncResp Shared pointer for generating response message.
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001966 * @param[in] computerSystemIndex Index associated with the requested system
George Liuc6a620f2020-04-10 17:18:11 +08001967 * @param[in] policy power restore policy properties from request.
1968 *
1969 * @return None.
1970 */
Patrick Williams504af5a2025-02-03 14:29:03 -05001971inline void setPowerRestorePolicy(
1972 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001973 const uint64_t computerSystemIndex, std::string_view policy)
George Liuc6a620f2020-04-10 17:18:11 +08001974{
Ed Tanous62598e32023-07-17 17:06:25 -07001975 BMCWEB_LOG_DEBUG("Set power restore policy.");
George Liuc6a620f2020-04-10 17:18:11 +08001976
Ed Tanous8d69c662023-06-21 10:29:06 -07001977 std::string powerRestorePolicy = dbusPowerRestorePolicyFromRedfish(policy);
George Liuc6a620f2020-04-10 17:18:11 +08001978
Ed Tanous8d69c662023-06-21 10:29:06 -07001979 if (powerRestorePolicy.empty())
George Liuc6a620f2020-04-10 17:18:11 +08001980 {
Ed Tanousac106bf2023-06-07 09:24:59 -07001981 messages::propertyValueNotInList(asyncResp->res, policy,
Gunnar Mills4e69c902021-01-05 19:50:11 -06001982 "PowerRestorePolicy");
George Liuc6a620f2020-04-10 17:18:11 +08001983 return;
1984 }
1985
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02001986 sdbusplus::message::object_path path("/xyz/openbmc_project/control/host" +
1987 std::to_string(computerSystemIndex));
1988 path /= "power_restore_policy";
1989 setDbusProperty(asyncResp, "PowerRestorePolicy",
1990 "xyz.openbmc_project.Settings", path,
1991 "xyz.openbmc_project.Control.Power.RestorePolicy",
1992 "PowerRestorePolicy", powerRestorePolicy);
George Liuc6a620f2020-04-10 17:18:11 +08001993}
1994
AppaRao Pulia6349912019-10-18 17:16:08 +05301995/**
1996 * @brief Retrieves provisioning status
1997 *
Ed Tanous25b54db2024-04-17 15:40:31 -07001998 * @param[in] asyncResp Shared pointer for completing asynchronous
1999 * calls.
AppaRao Pulia6349912019-10-18 17:16:08 +05302000 *
2001 * @return None.
2002 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002003inline void getProvisioningStatus(
2004 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
AppaRao Pulia6349912019-10-18 17:16:08 +05302005{
Ed Tanous62598e32023-07-17 17:06:25 -07002006 BMCWEB_LOG_DEBUG("Get OEM information.");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002007 dbus::utility::getAllProperties(
2008 "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr",
2009 "xyz.openbmc_project.PFR.Attributes",
Ed Tanousac106bf2023-06-07 09:24:59 -07002010 [asyncResp](const boost::system::error_code& ec,
2011 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002012 nlohmann::json& oemPFR =
2013 asyncResp->res
2014 .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
2015 asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
2016 "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
2017 oemPFR["@odata.type"] =
2018 "#OpenBMCComputerSystem.FirmwareProvisioning";
James Feist50626f42020-09-23 14:40:47 -07002019
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002020 if (ec)
AppaRao Pulia6349912019-10-18 17:16:08 +05302021 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002022 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2023 // not an error, don't have to have the interface
Ed Tanous539d8c62024-06-19 14:38:27 -07002024 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002025 FirmwareProvisioningStatus::NotProvisioned;
2026 return;
2027 }
2028
2029 const bool* provState = nullptr;
2030 const bool* lockState = nullptr;
2031
2032 const bool success = sdbusplus::unpackPropertiesNoThrow(
2033 dbus_utils::UnpackErrorPrinter(), propertiesList,
2034 "UfmProvisioned", provState, "UfmLocked", lockState);
2035
2036 if (!success)
2037 {
2038 messages::internalError(asyncResp->res);
2039 return;
2040 }
2041
2042 if ((provState == nullptr) || (lockState == nullptr))
2043 {
2044 BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
2045 messages::internalError(asyncResp->res);
2046 return;
2047 }
2048
2049 if (*provState)
2050 {
2051 if (*lockState)
2052 {
2053 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2054 FirmwareProvisioningStatus::ProvisionedAndLocked;
2055 }
2056 else
2057 {
2058 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
2059 FirmwareProvisioningStatus::ProvisionedButNotLocked;
2060 }
AppaRao Pulia6349912019-10-18 17:16:08 +05302061 }
2062 else
2063 {
Ed Tanous539d8c62024-06-19 14:38:27 -07002064 oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002065 FirmwareProvisioningStatus::NotProvisioned;
AppaRao Pulia6349912019-10-18 17:16:08 +05302066 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002067 });
AppaRao Pulia6349912019-10-18 17:16:08 +05302068}
AppaRao Pulia6349912019-10-18 17:16:08 +05302069
Santosh Puranik491d8ee2019-02-06 19:46:56 +05302070/**
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002071 * @brief Translate the PowerMode string to enum value
Chris Cain3a2d04242021-05-28 16:57:10 -05002072 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002073 * @param[in] modeString PowerMode string to be translated
Chris Cain3a2d04242021-05-28 16:57:10 -05002074 *
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002075 * @return PowerMode enum
Chris Cain3a2d04242021-05-28 16:57:10 -05002076 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002077inline computer_system::PowerMode translatePowerModeString(
2078 const std::string& modeString)
Chris Cain3a2d04242021-05-28 16:57:10 -05002079{
Chris Cainb6655102024-02-01 14:35:33 -06002080 using PowerMode = computer_system::PowerMode;
2081
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002082 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static")
Chris Cain3a2d04242021-05-28 16:57:10 -05002083 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002084 return PowerMode::Static;
Chris Cain3a2d04242021-05-28 16:57:10 -05002085 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002086 if (modeString ==
George Liu0fda0f12021-11-16 10:06:17 +08002087 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance")
Chris Cain3a2d04242021-05-28 16:57:10 -05002088 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002089 return PowerMode::MaximumPerformance;
Chris Cain3a2d04242021-05-28 16:57:10 -05002090 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002091 if (modeString ==
2092 "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving")
Chris Cain3a2d04242021-05-28 16:57:10 -05002093 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002094 return PowerMode::PowerSaving;
Chris Cainb6655102024-02-01 14:35:33 -06002095 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002096 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002097 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance")
2098 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002099 return PowerMode::BalancedPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002100 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002101 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002102 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance")
2103 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002104 return PowerMode::EfficiencyFavorPerformance;
Chris Cainb6655102024-02-01 14:35:33 -06002105 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002106 if (modeString ==
Chris Cainb6655102024-02-01 14:35:33 -06002107 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower")
2108 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002109 return PowerMode::EfficiencyFavorPower;
Chris Cain3a2d04242021-05-28 16:57:10 -05002110 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002111 if (modeString == "xyz.openbmc_project.Control.Power.Mode.PowerMode.OEM")
Chris Cain3a2d04242021-05-28 16:57:10 -05002112 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002113 return PowerMode::OEM;
2114 }
2115 // Any other values would be invalid
2116 BMCWEB_LOG_ERROR("PowerMode value was not valid: {}", modeString);
2117 return PowerMode::Invalid;
2118}
2119
Patrick Williams504af5a2025-02-03 14:29:03 -05002120inline void afterGetPowerMode(
2121 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2122 const boost::system::error_code& ec,
2123 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002124{
2125 if (ec)
2126 {
2127 BMCWEB_LOG_ERROR("DBUS response error on PowerMode GetAll: {}", ec);
2128 messages::internalError(asyncResp->res);
2129 return;
2130 }
2131
2132 std::string powerMode;
2133 const std::vector<std::string>* allowedModes = nullptr;
2134 const bool success = sdbusplus::unpackPropertiesNoThrow(
2135 dbus_utils::UnpackErrorPrinter(), properties, "PowerMode", powerMode,
2136 "AllowedPowerModes", allowedModes);
2137
2138 if (!success)
2139 {
2140 messages::internalError(asyncResp->res);
2141 return;
2142 }
2143
2144 nlohmann::json::array_t modeList;
2145 if (allowedModes == nullptr)
2146 {
2147 modeList.emplace_back("Static");
2148 modeList.emplace_back("MaximumPerformance");
2149 modeList.emplace_back("PowerSaving");
Chris Cain3a2d04242021-05-28 16:57:10 -05002150 }
2151 else
2152 {
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002153 for (const auto& aMode : *allowedModes)
2154 {
2155 computer_system::PowerMode modeValue =
2156 translatePowerModeString(aMode);
2157 if (modeValue == computer_system::PowerMode::Invalid)
2158 {
2159 messages::internalError(asyncResp->res);
2160 continue;
2161 }
2162 modeList.emplace_back(modeValue);
2163 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002164 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002165 asyncResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = modeList;
Chris Cain3a2d04242021-05-28 16:57:10 -05002166
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002167 BMCWEB_LOG_DEBUG("Current power mode: {}", powerMode);
2168 const computer_system::PowerMode modeValue =
2169 translatePowerModeString(powerMode);
2170 if (modeValue == computer_system::PowerMode::Invalid)
2171 {
2172 messages::internalError(asyncResp->res);
2173 return;
2174 }
2175 asyncResp->res.jsonValue["PowerMode"] = modeValue;
2176}
Chris Cain3a2d04242021-05-28 16:57:10 -05002177/**
2178 * @brief Retrieves system power mode
2179 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002180 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002181 *
2182 * @return None.
2183 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002184inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain3a2d04242021-05-28 16:57:10 -05002185{
Ed Tanous62598e32023-07-17 17:06:25 -07002186 BMCWEB_LOG_DEBUG("Get power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002187
2188 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002189 constexpr std::array<std::string_view, 1> interfaces = {
2190 "xyz.openbmc_project.Control.Power.Mode"};
2191 dbus::utility::getSubTree(
2192 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002193 [asyncResp](const boost::system::error_code& ec,
2194 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002195 if (ec)
2196 {
2197 BMCWEB_LOG_DEBUG(
2198 "DBUS response error on Power.Mode GetSubTree {}", ec);
2199 // This is an optional D-Bus object so just return if
2200 // error occurs
2201 return;
2202 }
2203 if (subtree.empty())
2204 {
2205 // As noted above, this is an optional interface so just return
2206 // if there is no instance found
2207 return;
2208 }
2209 if (subtree.size() > 1)
2210 {
2211 // More then one PowerMode object is not supported and is an
2212 // error
2213 BMCWEB_LOG_DEBUG(
2214 "Found more than 1 system D-Bus Power.Mode objects: {}",
2215 subtree.size());
2216 messages::internalError(asyncResp->res);
2217 return;
2218 }
2219 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2220 {
2221 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2222 messages::internalError(asyncResp->res);
2223 return;
2224 }
2225 const std::string& path = subtree[0].first;
2226 const std::string& service = subtree[0].second.begin()->first;
2227 if (service.empty())
2228 {
2229 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2230 messages::internalError(asyncResp->res);
2231 return;
2232 }
Chris Cain6b9ac4f2024-02-15 12:59:32 -06002233
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002234 // Valid Power Mode object found, now read the mode properties
Ed Tanousdeae6a72024-11-11 21:58:57 -08002235 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002236 *crow::connections::systemBus, service, path,
2237 "xyz.openbmc_project.Control.Power.Mode",
2238 [asyncResp](
2239 const boost::system::error_code& ec2,
2240 const dbus::utility::DBusPropertiesMap& properties) {
2241 afterGetPowerMode(asyncResp, ec2, properties);
2242 });
George Liue99073f2022-12-09 11:06:16 +08002243 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002244}
2245
2246/**
2247 * @brief Validate the specified mode is valid and return the PowerMode
2248 * name associated with that string
2249 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002250 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cainb6655102024-02-01 14:35:33 -06002251 * @param[in] modeValue String representing the desired PowerMode
Chris Cain3a2d04242021-05-28 16:57:10 -05002252 *
2253 * @return PowerMode value or empty string if mode is not valid
2254 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002255inline std::string validatePowerMode(
2256 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2257 const nlohmann::json& modeValue)
Chris Cain3a2d04242021-05-28 16:57:10 -05002258{
Chris Cainb6655102024-02-01 14:35:33 -06002259 using PowerMode = computer_system::PowerMode;
Chris Cain3a2d04242021-05-28 16:57:10 -05002260 std::string mode;
2261
Chris Cainb6655102024-02-01 14:35:33 -06002262 if (modeValue == PowerMode::Static)
Chris Cain3a2d04242021-05-28 16:57:10 -05002263 {
2264 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.Static";
2265 }
Chris Cainb6655102024-02-01 14:35:33 -06002266 else if (modeValue == PowerMode::MaximumPerformance)
Chris Cain3a2d04242021-05-28 16:57:10 -05002267 {
George Liu0fda0f12021-11-16 10:06:17 +08002268 mode =
2269 "xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance";
Chris Cain3a2d04242021-05-28 16:57:10 -05002270 }
Chris Cainb6655102024-02-01 14:35:33 -06002271 else if (modeValue == PowerMode::PowerSaving)
Chris Cain3a2d04242021-05-28 16:57:10 -05002272 {
2273 mode = "xyz.openbmc_project.Control.Power.Mode.PowerMode.PowerSaving";
2274 }
Chris Cainb6655102024-02-01 14:35:33 -06002275 else if (modeValue == PowerMode::BalancedPerformance)
2276 {
2277 mode =
2278 "xyz.openbmc_project.Control.Power.Mode.PowerMode.BalancedPerformance";
2279 }
2280 else if (modeValue == PowerMode::EfficiencyFavorPerformance)
2281 {
2282 mode =
2283 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPerformance";
2284 }
2285 else if (modeValue == PowerMode::EfficiencyFavorPower)
2286 {
2287 mode =
2288 "xyz.openbmc_project.Control.Power.Mode.PowerMode.EfficiencyFavorPower";
2289 }
Chris Cain3a2d04242021-05-28 16:57:10 -05002290 else
2291 {
Chris Cainb6655102024-02-01 14:35:33 -06002292 messages::propertyValueNotInList(asyncResp->res, modeValue.dump(),
Ed Tanousac106bf2023-06-07 09:24:59 -07002293 "PowerMode");
Chris Cain3a2d04242021-05-28 16:57:10 -05002294 }
2295 return mode;
2296}
2297
2298/**
2299 * @brief Sets system power mode.
2300 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002301 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain3a2d04242021-05-28 16:57:10 -05002302 * @param[in] pmode System power mode from request.
2303 *
2304 * @return None.
2305 */
Ed Tanousac106bf2023-06-07 09:24:59 -07002306inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Chris Cain3a2d04242021-05-28 16:57:10 -05002307 const std::string& pmode)
2308{
Ed Tanous62598e32023-07-17 17:06:25 -07002309 BMCWEB_LOG_DEBUG("Set power mode.");
Chris Cain3a2d04242021-05-28 16:57:10 -05002310
Ed Tanousac106bf2023-06-07 09:24:59 -07002311 std::string powerMode = validatePowerMode(asyncResp, pmode);
Chris Cain3a2d04242021-05-28 16:57:10 -05002312 if (powerMode.empty())
2313 {
2314 return;
2315 }
2316
2317 // Get Power Mode object path:
George Liue99073f2022-12-09 11:06:16 +08002318 constexpr std::array<std::string_view, 1> interfaces = {
2319 "xyz.openbmc_project.Control.Power.Mode"};
2320 dbus::utility::getSubTree(
2321 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002322 [asyncResp,
George Liue99073f2022-12-09 11:06:16 +08002323 powerMode](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002324 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002325 if (ec)
2326 {
2327 BMCWEB_LOG_ERROR(
2328 "DBUS response error on Power.Mode GetSubTree {}", ec);
2329 // This is an optional D-Bus object, but user attempted to patch
2330 messages::internalError(asyncResp->res);
2331 return;
2332 }
2333 if (subtree.empty())
2334 {
2335 // This is an optional D-Bus object, but user attempted to patch
2336 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2337 "PowerMode");
2338 return;
2339 }
2340 if (subtree.size() > 1)
2341 {
2342 // More then one PowerMode object is not supported and is an
2343 // error
2344 BMCWEB_LOG_DEBUG(
2345 "Found more than 1 system D-Bus Power.Mode objects: {}",
2346 subtree.size());
2347 messages::internalError(asyncResp->res);
2348 return;
2349 }
2350 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2351 {
2352 BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
2353 messages::internalError(asyncResp->res);
2354 return;
2355 }
2356 const std::string& path = subtree[0].first;
2357 const std::string& service = subtree[0].second.begin()->first;
2358 if (service.empty())
2359 {
2360 BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
2361 messages::internalError(asyncResp->res);
2362 return;
2363 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002364
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002365 BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
Ed Tanous002d39b2022-05-31 08:59:27 -07002366
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002367 // Set the Power Mode property
2368 setDbusProperty(asyncResp, "PowerMode", service, path,
2369 "xyz.openbmc_project.Control.Power.Mode",
2370 "PowerMode", powerMode);
2371 });
Chris Cain3a2d04242021-05-28 16:57:10 -05002372}
2373
2374/**
Yong Li51709ff2019-09-30 14:13:04 +08002375 * @brief Translates watchdog timeout action DBUS property value to redfish.
2376 *
2377 * @param[in] dbusAction The watchdog timeout action in D-BUS.
2378 *
2379 * @return Returns as a string, the timeout action in Redfish terms. If
2380 * translation cannot be done, returns an empty string.
2381 */
Ed Tanous23a21a12020-07-25 04:45:05 +00002382inline std::string dbusToRfWatchdogAction(const std::string& dbusAction)
Yong Li51709ff2019-09-30 14:13:04 +08002383{
2384 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.None")
2385 {
2386 return "None";
2387 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002388 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.HardReset")
Yong Li51709ff2019-09-30 14:13:04 +08002389 {
2390 return "ResetSystem";
2391 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002392 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerOff")
Yong Li51709ff2019-09-30 14:13:04 +08002393 {
2394 return "PowerDown";
2395 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002396 if (dbusAction == "xyz.openbmc_project.State.Watchdog.Action.PowerCycle")
Yong Li51709ff2019-09-30 14:13:04 +08002397 {
2398 return "PowerCycle";
2399 }
2400
2401 return "";
2402}
2403
2404/**
Yong Lic45f0082019-10-10 14:19:01 +08002405 *@brief Translates timeout action from Redfish to DBUS property value.
2406 *
2407 *@param[in] rfAction The timeout action in Redfish.
2408 *
2409 *@return Returns as a string, the time_out action as expected by DBUS.
2410 *If translation cannot be done, returns an empty string.
2411 */
2412
Ed Tanous23a21a12020-07-25 04:45:05 +00002413inline std::string rfToDbusWDTTimeOutAct(const std::string& rfAction)
Yong Lic45f0082019-10-10 14:19:01 +08002414{
2415 if (rfAction == "None")
2416 {
2417 return "xyz.openbmc_project.State.Watchdog.Action.None";
2418 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002419 if (rfAction == "PowerCycle")
Yong Lic45f0082019-10-10 14:19:01 +08002420 {
2421 return "xyz.openbmc_project.State.Watchdog.Action.PowerCycle";
2422 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002423 if (rfAction == "PowerDown")
Yong Lic45f0082019-10-10 14:19:01 +08002424 {
2425 return "xyz.openbmc_project.State.Watchdog.Action.PowerOff";
2426 }
Ed Tanous3174e4d2020-10-07 11:41:22 -07002427 if (rfAction == "ResetSystem")
Yong Lic45f0082019-10-10 14:19:01 +08002428 {
2429 return "xyz.openbmc_project.State.Watchdog.Action.HardReset";
2430 }
2431
2432 return "";
2433}
2434
2435/**
Yong Li51709ff2019-09-30 14:13:04 +08002436 * @brief Retrieves host watchdog timer properties over DBUS
2437 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002438 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Yong Li51709ff2019-09-30 14:13:04 +08002439 *
2440 * @return None.
2441 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002442inline void getHostWatchdogTimer(
2443 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Yong Li51709ff2019-09-30 14:13:04 +08002444{
Ed Tanous62598e32023-07-17 17:06:25 -07002445 BMCWEB_LOG_DEBUG("Get host watchodg");
Ed Tanousdeae6a72024-11-11 21:58:57 -08002446 dbus::utility::getAllProperties(
2447 "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0",
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002448 "xyz.openbmc_project.State.Watchdog",
Ed Tanousac106bf2023-06-07 09:24:59 -07002449 [asyncResp](const boost::system::error_code& ec,
2450 const dbus::utility::DBusPropertiesMap& properties) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002451 if (ec)
2452 {
2453 // watchdog service is stopped
2454 BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
2455 return;
2456 }
Ed Tanous002d39b2022-05-31 08:59:27 -07002457
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002458 BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
Ed Tanous002d39b2022-05-31 08:59:27 -07002459
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002460 nlohmann::json& hostWatchdogTimer =
2461 asyncResp->res.jsonValue["HostWatchdogTimer"];
Ed Tanous002d39b2022-05-31 08:59:27 -07002462
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002463 // watchdog service is running/enabled
2464 hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
Ed Tanous002d39b2022-05-31 08:59:27 -07002465
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002466 const bool* enabled = nullptr;
2467 const std::string* expireAction = nullptr;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002468
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002469 const bool success = sdbusplus::unpackPropertiesNoThrow(
2470 dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
2471 enabled, "ExpireAction", expireAction);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002472
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002473 if (!success)
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002474 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002475 messages::internalError(asyncResp->res);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002476 return;
2477 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002478
2479 if (enabled != nullptr)
2480 {
2481 hostWatchdogTimer["FunctionEnabled"] = *enabled;
2482 }
2483
2484 if (expireAction != nullptr)
2485 {
2486 std::string action = dbusToRfWatchdogAction(*expireAction);
2487 if (action.empty())
2488 {
2489 messages::internalError(asyncResp->res);
2490 return;
2491 }
2492 hostWatchdogTimer["TimeoutAction"] = action;
2493 }
2494 });
Yong Li51709ff2019-09-30 14:13:04 +08002495}
2496
2497/**
Yong Lic45f0082019-10-10 14:19:01 +08002498 * @brief Sets Host WatchDog Timer properties.
2499 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002500 * @param[in] asyncResp Shared pointer for generating response message.
Yong Lic45f0082019-10-10 14:19:01 +08002501 * @param[in] wdtEnable The WDTimer Enable value (true/false) from incoming
2502 * RF request.
2503 * @param[in] wdtTimeOutAction The WDT Timeout action, from incoming RF request.
2504 *
2505 * @return None.
2506 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002507inline void setWDTProperties(
2508 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2509 const std::optional<bool> wdtEnable,
2510 const std::optional<std::string>& wdtTimeOutAction)
Yong Lic45f0082019-10-10 14:19:01 +08002511{
Ed Tanous62598e32023-07-17 17:06:25 -07002512 BMCWEB_LOG_DEBUG("Set host watchdog");
Yong Lic45f0082019-10-10 14:19:01 +08002513
2514 if (wdtTimeOutAction)
2515 {
2516 std::string wdtTimeOutActStr = rfToDbusWDTTimeOutAct(*wdtTimeOutAction);
2517 // check if TimeOut Action is Valid
2518 if (wdtTimeOutActStr.empty())
2519 {
Ed Tanous62598e32023-07-17 17:06:25 -07002520 BMCWEB_LOG_DEBUG("Unsupported value for TimeoutAction: {}",
2521 *wdtTimeOutAction);
Ed Tanousac106bf2023-06-07 09:24:59 -07002522 messages::propertyValueNotInList(asyncResp->res, *wdtTimeOutAction,
Yong Lic45f0082019-10-10 14:19:01 +08002523 "TimeoutAction");
2524 return;
2525 }
2526
Ginu Georgee93abac2024-06-14 17:35:27 +05302527 setDbusProperty(asyncResp, "HostWatchdogTimer/TimeoutAction",
2528 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002529 sdbusplus::message::object_path(
2530 "/xyz/openbmc_project/watchdog/host0"),
2531 "xyz.openbmc_project.State.Watchdog", "ExpireAction",
Ginu Georgee93abac2024-06-14 17:35:27 +05302532 wdtTimeOutActStr);
Yong Lic45f0082019-10-10 14:19:01 +08002533 }
2534
2535 if (wdtEnable)
2536 {
Ginu Georgee93abac2024-06-14 17:35:27 +05302537 setDbusProperty(asyncResp, "HostWatchdogTimer/FunctionEnabled",
2538 "xyz.openbmc_project.Watchdog",
Asmitha Karunanithi87c44962024-04-04 18:28:33 +00002539 sdbusplus::message::object_path(
2540 "/xyz/openbmc_project/watchdog/host0"),
2541 "xyz.openbmc_project.State.Watchdog", "Enabled",
Ginu Georgee93abac2024-06-14 17:35:27 +05302542 *wdtEnable);
Yong Lic45f0082019-10-10 14:19:01 +08002543 }
2544}
2545
Chris Cain37bbf982021-09-20 10:53:09 -05002546/**
2547 * @brief Parse the Idle Power Saver properties into json
2548 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002549 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002550 * @param[in] properties IPS property data from DBus.
2551 *
2552 * @return true if successful
2553 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002554inline bool parseIpsProperties(
2555 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2556 const dbus::utility::DBusPropertiesMap& properties)
Chris Cain37bbf982021-09-20 10:53:09 -05002557{
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002558 const bool* enabled = nullptr;
2559 const uint8_t* enterUtilizationPercent = nullptr;
2560 const uint64_t* enterDwellTime = nullptr;
2561 const uint8_t* exitUtilizationPercent = nullptr;
2562 const uint64_t* exitDwellTime = nullptr;
2563
2564 const bool success = sdbusplus::unpackPropertiesNoThrow(
2565 dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
Chris Cain2661b722023-03-22 08:53:21 -05002566 "EnterUtilizationPercent", enterUtilizationPercent, "EnterDwellTime",
2567 enterDwellTime, "ExitUtilizationPercent", exitUtilizationPercent,
2568 "ExitDwellTime", exitDwellTime);
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002569
2570 if (!success)
Chris Cain37bbf982021-09-20 10:53:09 -05002571 {
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002572 return false;
2573 }
2574
2575 if (enabled != nullptr)
2576 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002577 asyncResp->res.jsonValue["IdlePowerSaver"]["Enabled"] = *enabled;
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002578 }
2579
2580 if (enterUtilizationPercent != nullptr)
2581 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002582 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002583 *enterUtilizationPercent;
2584 }
2585
2586 if (enterDwellTime != nullptr)
2587 {
2588 const std::chrono::duration<uint64_t, std::milli> ms(*enterDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002589 asyncResp->res.jsonValue["IdlePowerSaver"]["EnterDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002590 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2591 .count();
2592 }
2593
2594 if (exitUtilizationPercent != nullptr)
2595 {
Ed Tanousac106bf2023-06-07 09:24:59 -07002596 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitUtilizationPercent"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002597 *exitUtilizationPercent;
2598 }
2599
2600 if (exitDwellTime != nullptr)
2601 {
2602 const std::chrono::duration<uint64_t, std::milli> ms(*exitDwellTime);
Ed Tanousac106bf2023-06-07 09:24:59 -07002603 asyncResp->res.jsonValue["IdlePowerSaver"]["ExitDwellTimeSeconds"] =
Krzysztof Grobelnybc1d29d2022-08-09 14:17:34 +02002604 std::chrono::duration_cast<std::chrono::duration<uint64_t>>(ms)
2605 .count();
Chris Cain37bbf982021-09-20 10:53:09 -05002606 }
2607
2608 return true;
2609}
2610
2611/**
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002612 * @brief Retrieves idle power saver properties over DBUS
Chris Cain37bbf982021-09-20 10:53:09 -05002613 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002614 * @param[in] asyncResp Shared pointer for completing asynchronous calls.
Chris Cain37bbf982021-09-20 10:53:09 -05002615 *
2616 * @return None.
2617 */
Patrick Williams504af5a2025-02-03 14:29:03 -05002618inline void getIdlePowerSaver(
2619 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Chris Cain37bbf982021-09-20 10:53:09 -05002620{
Ed Tanous62598e32023-07-17 17:06:25 -07002621 BMCWEB_LOG_DEBUG("Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002622
2623 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002624 constexpr std::array<std::string_view, 1> interfaces = {
2625 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2626 dbus::utility::getSubTree(
2627 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002628 [asyncResp](const boost::system::error_code& ec,
2629 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002630 if (ec)
Chris Cain37bbf982021-09-20 10:53:09 -05002631 {
Ed Tanous62598e32023-07-17 17:06:25 -07002632 BMCWEB_LOG_ERROR(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002633 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2634 ec);
2635 messages::internalError(asyncResp->res);
2636 return;
2637 }
2638 if (subtree.empty())
2639 {
2640 // This is an optional interface so just return
2641 // if there is no instance found
2642 BMCWEB_LOG_DEBUG("No instances found");
2643 return;
2644 }
2645 if (subtree.size() > 1)
2646 {
2647 // More then one PowerIdlePowerSaver object is not supported and
2648 // is an error
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02002649 BMCWEB_LOG_DEBUG(
2650 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2651 subtree.size());
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002652 messages::internalError(asyncResp->res);
2653 return;
2654 }
2655 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2656 {
2657 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2658 messages::internalError(asyncResp->res);
2659 return;
2660 }
2661 const std::string& path = subtree[0].first;
2662 const std::string& service = subtree[0].second.begin()->first;
2663 if (service.empty())
2664 {
2665 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
Ed Tanousac106bf2023-06-07 09:24:59 -07002666 messages::internalError(asyncResp->res);
Chris Cain37bbf982021-09-20 10:53:09 -05002667 return;
2668 }
2669
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002670 // Valid IdlePowerSaver object found, now read the current values
Ed Tanousdeae6a72024-11-11 21:58:57 -08002671 dbus::utility::getAllProperties(
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002672 *crow::connections::systemBus, service, path,
2673 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2674 [asyncResp](
2675 const boost::system::error_code& ec2,
2676 const dbus::utility::DBusPropertiesMap& properties) {
2677 if (ec2)
2678 {
2679 BMCWEB_LOG_ERROR(
2680 "DBUS response error on IdlePowerSaver GetAll: {}",
2681 ec2);
2682 messages::internalError(asyncResp->res);
2683 return;
2684 }
2685
2686 if (!parseIpsProperties(asyncResp, properties))
2687 {
2688 messages::internalError(asyncResp->res);
2689 return;
2690 }
2691 });
George Liue99073f2022-12-09 11:06:16 +08002692 });
Chris Cain37bbf982021-09-20 10:53:09 -05002693
Ed Tanous62598e32023-07-17 17:06:25 -07002694 BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002695}
2696
2697/**
2698 * @brief Sets Idle Power Saver properties.
2699 *
Ed Tanousac106bf2023-06-07 09:24:59 -07002700 * @param[in] asyncResp Shared pointer for generating response message.
Chris Cain37bbf982021-09-20 10:53:09 -05002701 * @param[in] ipsEnable The IPS Enable value (true/false) from incoming
2702 * RF request.
2703 * @param[in] ipsEnterUtil The utilization limit to enter idle state.
2704 * @param[in] ipsEnterTime The time the utilization must be below ipsEnterUtil
2705 * before entering idle state.
2706 * @param[in] ipsExitUtil The utilization limit when exiting idle state.
2707 * @param[in] ipsExitTime The time the utilization must be above ipsExutUtil
2708 * before exiting idle state
2709 *
2710 * @return None.
2711 */
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002712inline void setIdlePowerSaver(
2713 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2714 const std::optional<bool> ipsEnable,
2715 const std::optional<uint8_t> ipsEnterUtil,
2716 const std::optional<uint64_t> ipsEnterTime,
2717 const std::optional<uint8_t> ipsExitUtil,
2718 const std::optional<uint64_t> ipsExitTime)
Chris Cain37bbf982021-09-20 10:53:09 -05002719{
Ed Tanous62598e32023-07-17 17:06:25 -07002720 BMCWEB_LOG_DEBUG("Set idle power saver properties");
Chris Cain37bbf982021-09-20 10:53:09 -05002721
2722 // Get IdlePowerSaver object path:
George Liue99073f2022-12-09 11:06:16 +08002723 constexpr std::array<std::string_view, 1> interfaces = {
2724 "xyz.openbmc_project.Control.Power.IdlePowerSaver"};
2725 dbus::utility::getSubTree(
2726 "/", 0, interfaces,
Ed Tanousac106bf2023-06-07 09:24:59 -07002727 [asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
George Liue99073f2022-12-09 11:06:16 +08002728 ipsExitTime](const boost::system::error_code& ec,
Ed Tanousb9d36b42022-02-26 21:42:46 -08002729 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002730 if (ec)
2731 {
2732 BMCWEB_LOG_ERROR(
2733 "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
2734 ec);
2735 messages::internalError(asyncResp->res);
2736 return;
2737 }
2738 if (subtree.empty())
2739 {
2740 // This is an optional D-Bus object, but user attempted to patch
2741 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2742 "IdlePowerSaver");
2743 return;
2744 }
2745 if (subtree.size() > 1)
2746 {
2747 // More then one PowerIdlePowerSaver object is not supported and
2748 // is an error
2749 BMCWEB_LOG_DEBUG(
2750 "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
2751 subtree.size());
2752 messages::internalError(asyncResp->res);
2753 return;
2754 }
2755 if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
2756 {
2757 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
2758 messages::internalError(asyncResp->res);
2759 return;
2760 }
2761 const std::string& path = subtree[0].first;
2762 const std::string& service = subtree[0].second.begin()->first;
2763 if (service.empty())
2764 {
2765 BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
2766 messages::internalError(asyncResp->res);
2767 return;
2768 }
Chris Cain37bbf982021-09-20 10:53:09 -05002769
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002770 // Valid Power IdlePowerSaver object found, now set any values that
2771 // need to be updated
Chris Cain37bbf982021-09-20 10:53:09 -05002772
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002773 if (ipsEnable)
2774 {
2775 setDbusProperty(
2776 asyncResp, "IdlePowerSaver/Enabled", service, path,
2777 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2778 "Enabled", *ipsEnable);
2779 }
2780 if (ipsEnterUtil)
2781 {
2782 setDbusProperty(
2783 asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
2784 service, path,
2785 "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2786 "EnterUtilizationPercent", *ipsEnterUtil);
2787 }
2788 if (ipsEnterTime)
2789 {
2790 // Convert from seconds into milliseconds for DBus
2791 const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
2792 setDbusProperty(
2793 asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
2794 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2795 "EnterDwellTime", timeMilliseconds);
2796 }
2797 if (ipsExitUtil)
2798 {
2799 setDbusProperty(
2800 asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
2801 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2802 "ExitUtilizationPercent", *ipsExitUtil);
2803 }
2804 if (ipsExitTime)
2805 {
2806 // Convert from seconds into milliseconds for DBus
2807 const uint64_t timeMilliseconds = *ipsExitTime * 1000;
2808 setDbusProperty(
2809 asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
2810 path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
2811 "ExitDwellTime", timeMilliseconds);
2812 }
2813 });
Chris Cain37bbf982021-09-20 10:53:09 -05002814
Ed Tanous62598e32023-07-17 17:06:25 -07002815 BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
Chris Cain37bbf982021-09-20 10:53:09 -05002816}
2817
Ed Tanousc1e219d2023-06-07 10:34:33 -07002818inline void handleComputerSystemCollectionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002819 crow::App& app, const crow::Request& req,
2820 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2821{
2822 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2823 {
2824 return;
2825 }
2826 asyncResp->res.addHeader(
2827 boost::beast::http::field::link,
2828 "</redfish/v1/JsonSchemas/ComputerSystemCollection/ComputerSystemCollection.json>; rel=describedby");
2829}
2830
Ed Tanousc1e219d2023-06-07 10:34:33 -07002831inline void handleComputerSystemCollectionGet(
2832 crow::App& app, const crow::Request& req,
2833 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
2834{
2835 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2836 {
2837 return;
2838 }
2839
2840 asyncResp->res.addHeader(
2841 boost::beast::http::field::link,
2842 "</redfish/v1/JsonSchemas/ComputerSystemCollection.json>; rel=describedby");
2843 asyncResp->res.jsonValue["@odata.type"] =
2844 "#ComputerSystemCollection.ComputerSystemCollection";
2845 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems";
2846 asyncResp->res.jsonValue["Name"] = "Computer System Collection";
2847
Oliver Brewkafc5ae942024-08-12 15:04:41 +02002848 getSystemCollectionMembers(asyncResp);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002849}
2850
Yong Lic45f0082019-10-10 14:19:01 +08002851/**
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002852 * Function transceives data with dbus directly.
2853 */
Ed Tanous4f48d5f2021-06-21 08:27:45 -07002854inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002855{
Patrick Williams89492a12023-05-10 07:51:34 -05002856 constexpr const char* serviceName = "xyz.openbmc_project.Control.Host.NMI";
2857 constexpr const char* objectPath = "/xyz/openbmc_project/control/host0/nmi";
2858 constexpr const char* interfaceName =
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002859 "xyz.openbmc_project.Control.Host.NMI";
Patrick Williams89492a12023-05-10 07:51:34 -05002860 constexpr const char* method = "NMI";
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002861
Ed Tanous177612a2025-02-14 15:16:09 -08002862 dbus::utility::async_method_call(
2863 asyncResp,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -08002864 [asyncResp](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -04002865 if (ec)
2866 {
2867 BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
2868 messages::internalError(asyncResp->res);
2869 return;
2870 }
2871 messages::success(asyncResp->res);
2872 },
John Edward Broadbent7e860f12021-04-08 15:57:16 -07002873 serviceName, objectPath, interfaceName, method);
2874}
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02002875
Oliver Brewka06c055e2025-07-23 16:42:24 +02002876/**
2877 * @brief process the POST request after getting the computerSystemIndex
2878 *
2879 * @param[in] asyncResp Shared pointer for completing asynchronous
2880 * calls
2881 * @param[in] resetType The requested reset action
2882 * @param[in] computerSystemIndex Index associated with the requested system
2883 *
2884 * @return None
2885 */
2886inline void processComputerSystemResetActionPost(
2887 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string& resetType,
2888 const uint64_t computerSystemIndex)
Ed Tanousc1e219d2023-06-07 10:34:33 -07002889{
Ed Tanousc1e219d2023-06-07 10:34:33 -07002890 // Get the command and host vs. chassis
2891 std::string command;
2892 bool hostCommand = true;
2893 if ((resetType == "On") || (resetType == "ForceOn"))
2894 {
2895 command = "xyz.openbmc_project.State.Host.Transition.On";
2896 hostCommand = true;
2897 }
2898 else if (resetType == "ForceOff")
2899 {
2900 command = "xyz.openbmc_project.State.Chassis.Transition.Off";
2901 hostCommand = false;
2902 }
2903 else if (resetType == "ForceRestart")
2904 {
2905 command = "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot";
2906 hostCommand = true;
2907 }
2908 else if (resetType == "GracefulShutdown")
2909 {
2910 command = "xyz.openbmc_project.State.Host.Transition.Off";
2911 hostCommand = true;
2912 }
2913 else if (resetType == "GracefulRestart")
2914 {
2915 command =
2916 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot";
2917 hostCommand = true;
2918 }
2919 else if (resetType == "PowerCycle")
2920 {
2921 command = "xyz.openbmc_project.State.Host.Transition.Reboot";
2922 hostCommand = true;
2923 }
2924 else if (resetType == "Nmi")
2925 {
2926 doNMI(asyncResp);
2927 return;
2928 }
2929 else
2930 {
2931 messages::actionParameterUnknown(asyncResp->res, "Reset", resetType);
2932 return;
2933 }
2934
2935 if (hostCommand)
2936 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002937 setDbusProperty(asyncResp, "Reset",
2938 getHostStateServiceName(computerSystemIndex),
2939 getHostStateObjectPath(computerSystemIndex),
2940 "xyz.openbmc_project.State.Host",
Ginu Georgee93abac2024-06-14 17:35:27 +05302941 "RequestedHostTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002942 }
2943 else
2944 {
Oliver Brewka06c055e2025-07-23 16:42:24 +02002945 setDbusProperty(asyncResp, "Reset",
2946 getChassisStateServiceName(computerSystemIndex),
2947 getChassisStateObjectPath(computerSystemIndex),
Ed Tanousd02aad32024-02-13 14:43:34 -08002948 "xyz.openbmc_project.State.Chassis",
Ginu Georgee93abac2024-06-14 17:35:27 +05302949 "RequestedPowerTransition", command);
Ed Tanousc1e219d2023-06-07 10:34:33 -07002950 }
2951}
2952
Oliver Brewka06c055e2025-07-23 16:42:24 +02002953inline void handleComputerSystemResetActionPost(
2954 crow::App& app, const crow::Request& req,
2955 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2956 const std::string& systemName)
2957{
2958 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2959 {
2960 return;
2961 }
2962
2963 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
2964 {
2965 if (systemName == "hypervisor")
2966 {
2967 handleHypervisorSystemResetPost(req, asyncResp);
2968 return;
2969 }
2970 }
2971
2972 if (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
2973 {
2974 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
2975 {
2976 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
2977 systemName);
2978 return;
2979 }
2980 }
2981
2982 std::string resetType;
2983 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
2984 {
2985 return;
2986 }
2987
2988 getComputerSystemIndex(asyncResp, systemName,
2989 std::bind_front(processComputerSystemResetActionPost,
2990 asyncResp, resetType));
2991}
2992
Ed Tanousc1e219d2023-06-07 10:34:33 -07002993inline void handleComputerSystemHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002994 App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08002995 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2996 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07002997{
2998 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2999 {
3000 return;
3001 }
3002
3003 asyncResp->res.addHeader(
3004 boost::beast::http::field::link,
3005 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3006}
3007
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003008inline void afterPortRequest(
3009 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3010 const boost::system::error_code& ec,
3011 const std::vector<std::tuple<std::string, std::string, bool>>& socketData)
3012{
3013 if (ec)
3014 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003015 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003016 messages::internalError(asyncResp->res);
3017 return;
3018 }
3019 for (const auto& data : socketData)
3020 {
3021 const std::string& socketPath = get<0>(data);
3022 const std::string& protocolName = get<1>(data);
3023 bool isProtocolEnabled = get<2>(data);
3024 nlohmann::json& dataJson = asyncResp->res.jsonValue["SerialConsole"];
3025 dataJson[protocolName]["ServiceEnabled"] = isProtocolEnabled;
3026 // need to retrieve port number for
3027 // obmc-console-ssh service
3028 if (protocolName == "SSH")
3029 {
3030 getPortNumber(socketPath, [asyncResp, protocolName](
Ed Tanous81c4e332023-05-18 10:30:34 -07003031 const boost::system::error_code& ec1,
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003032 int portNumber) {
3033 if (ec1)
3034 {
Gunnar Millsb3e86cb2023-08-31 13:01:14 -05003035 BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
Abhishek Patel5c3e9272021-06-24 10:11:33 -05003036 messages::internalError(asyncResp->res);
3037 return;
3038 }
3039 nlohmann::json& dataJson1 =
3040 asyncResp->res.jsonValue["SerialConsole"];
3041 dataJson1[protocolName]["Port"] = portNumber;
3042 });
3043 }
3044 }
3045}
Ed Tanousc1e219d2023-06-07 10:34:33 -07003046
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003047/**
3048 * @brief process the GET request after getting the computerSystemIndex
3049 *
3050 * @param[in] asyncResp Shared pointer for completing asynchronous
3051 * calls
3052 * @param[in] systemName Name of the requested system
3053 * @param[in] computerSystemIndex Index associated with the requested system
3054 *
3055 * @return None
3056 */
3057inline void processComputerSystemGet(
Patrick Williams504af5a2025-02-03 14:29:03 -05003058 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003059 const std::string& systemName, const uint64_t computerSystemIndex)
Ed Tanous1abe55e2018-09-05 08:30:59 -07003060{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003061 asyncResp->res.addHeader(
3062 boost::beast::http::field::link,
3063 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3064 asyncResp->res.jsonValue["@odata.type"] =
Chris Cainb6655102024-02-01 14:35:33 -06003065 "#ComputerSystem.v1_22_0.ComputerSystem";
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003066 asyncResp->res.jsonValue["Name"] = systemName;
3067 asyncResp->res.jsonValue["Id"] = systemName;
Ed Tanous539d8c62024-06-19 14:38:27 -07003068 asyncResp->res.jsonValue["SystemType"] =
3069 computer_system::SystemType::Physical;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003070 asyncResp->res.jsonValue["Description"] = "Computer System";
3071 asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003072 asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
Priyanga Ramasamydfb2b402023-07-06 08:37:08 -05003073 double(0);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003074 asyncResp->res.jsonValue["@odata.id"] =
3075 boost::urls::format("/redfish/v1/Systems/{}", systemName);
Ed Tanous04a258f2018-10-15 08:00:41 -07003076
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003077 // Currently not supported on multi-host. TBD
3078 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3079 {
3080 asyncResp->res.jsonValue["Bios"]["@odata.id"] =
3081 boost::urls::format("/redfish/v1/Systems/{}/Bios", systemName);
3082 asyncResp->res.jsonValue["Processors"]["@odata.id"] =
3083 boost::urls::format("/redfish/v1/Systems/{}/Processors",
3084 systemName);
3085 asyncResp->res.jsonValue["Memory"]["@odata.id"] =
3086 boost::urls::format("/redfish/v1/Systems/{}/Memory", systemName);
3087 asyncResp->res.jsonValue["Storage"]["@odata.id"] =
3088 boost::urls::format("/redfish/v1/Systems/{}/Storage", systemName);
3089 asyncResp->res.jsonValue["FabricAdapters"]["@odata.id"] =
3090 boost::urls::format("/redfish/v1/Systems/{}/FabricAdapters",
3091 systemName);
3092 }
Ed Tanous029573d2019-02-01 10:57:49 -08003093
Ed Tanousc1e219d2023-06-07 10:34:33 -07003094 asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003095 boost::urls::format(
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003096 "/redfish/v1/Systems/{}/Actions/ComputerSystem.Reset", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003097 asyncResp->res
3098 .jsonValue["Actions"]["#ComputerSystem.Reset"]["@Redfish.ActionInfo"] =
Ed Tanous253f11b2024-05-16 09:38:31 -07003099 boost::urls::format("/redfish/v1/Systems/{}/ResetActionInfo",
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003100 systemName);
Lewanczyk, Dawidc5b2abe2018-05-30 16:59:42 +02003101
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003102 asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
3103 boost::urls::format("/redfish/v1/Systems/{}/LogServices", systemName);
Jason M. Billsc4bf6372018-11-05 13:48:27 -08003104
Ed Tanousc1e219d2023-06-07 10:34:33 -07003105 nlohmann::json::array_t managedBy;
3106 nlohmann::json& manager = managedBy.emplace_back();
Ed Tanous253f11b2024-05-16 09:38:31 -07003107 manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
3108 BMCWEB_REDFISH_MANAGER_URI_NAME);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003109 asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
Ed Tanous539d8c62024-06-19 14:38:27 -07003110 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
3111 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003112
Ed Tanousc1e219d2023-06-07 10:34:33 -07003113 // Fill in SerialConsole info
3114 asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
3115 asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true;
Ed Tanous14766872022-03-15 10:44:42 -07003116
Ed Tanousc1e219d2023-06-07 10:34:33 -07003117 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = true;
3118 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200;
3119 asyncResp->res.jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] =
3120 "Press ~. to exit console";
3121 getPortStatusAndPath(std::span{protocolToDBusForSystems},
3122 std::bind_front(afterPortRequest, asyncResp));
Gunnar Mills0e8ac5e2020-11-06 15:33:24 -06003123
Ed Tanous25b54db2024-04-17 15:40:31 -07003124 if constexpr (BMCWEB_KVM)
3125 {
3126 // Fill in GraphicalConsole info
3127 asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true;
3128 asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] =
3129 4;
3130 asyncResp->res.jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
3131 nlohmann::json::array_t({"KVMIP"});
3132 }
James Feistb49ac872019-05-21 15:12:01 -07003133
Janet Adkins2eaa9272025-04-17 10:30:43 -05003134 systems_utils::getValidSystemsPath(
3135 asyncResp, systemName,
3136 [asyncResp,
3137 systemName](const std::optional<std::string>& validSystemsPath) {
3138 if (validSystemsPath)
3139 {
3140 getLocationIndicatorActive(asyncResp, *validSystemsPath);
3141 }
3142 });
3143
Janet Adkinsf664fd82025-07-23 14:01:43 -05003144 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3145 {
3146 getIndicatorLedState(asyncResp);
3147 }
3148
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003149 // Currently not supported on multi-host.
3150 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3151 {
3152 getComputerSystem(asyncResp);
3153 // Todo: chassis matching could be handled by patch
3154 // https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60793
3155 getMainChassisId(
3156 asyncResp, [](const std::string& chassisId,
3157 const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
3158 nlohmann::json::array_t chassisArray;
3159 nlohmann::json& chassis = chassisArray.emplace_back();
3160 chassis["@odata.id"] =
3161 boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
3162 aRsp->res.jsonValue["Links"]["Chassis"] =
3163 std::move(chassisArray);
3164 });
3165
3166 pcie_util::getPCIeDeviceList(
3167 asyncResp, nlohmann::json::json_pointer("/PCIeDevices"));
3168 }
3169 getHostState(asyncResp, computerSystemIndex);
3170 getBootProperties(asyncResp, computerSystemIndex);
3171 getBootProgress(asyncResp, computerSystemIndex);
3172 getBootProgressLastStateTime(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003173 getHostWatchdogTimer(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003174 getPowerRestorePolicy(asyncResp, computerSystemIndex);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003175 getStopBootOnFault(asyncResp);
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003176 getAutomaticRetryPolicy(asyncResp, computerSystemIndex);
3177 getLastResetTime(asyncResp, computerSystemIndex);
Ed Tanous25b54db2024-04-17 15:40:31 -07003178 if constexpr (BMCWEB_REDFISH_PROVISIONING_FEATURE)
3179 {
3180 getProvisioningStatus(asyncResp);
3181 }
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003182 getTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003183 getPowerMode(asyncResp);
3184 getIdlePowerSaver(asyncResp);
3185}
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003186
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003187inline void handleComputerSystemGet(
3188 crow::App& app, const crow::Request& req,
3189 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3190 const std::string& systemName)
3191{
3192 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3193 {
3194 return;
3195 }
3196
3197 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
3198 {
3199 if (systemName == "hypervisor")
3200 {
3201 handleHypervisorSystemGet(asyncResp);
3202 return;
3203 }
3204 }
3205
3206 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3207 {
3208 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3209 {
3210 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3211 systemName);
3212 return;
3213 }
3214 }
3215
3216 BMCWEB_LOG_DEBUG("requested system = {}", systemName);
3217 getComputerSystemIndex(
3218 asyncResp, systemName,
3219 std::bind_front(processComputerSystemGet, asyncResp, systemName));
3220}
3221
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003222struct PatchParams
Ed Tanousc1e219d2023-06-07 10:34:33 -07003223{
Ed Tanousc1e219d2023-06-07 10:34:33 -07003224 std::optional<bool> locationIndicatorActive;
3225 std::optional<std::string> indicatorLed;
3226 std::optional<std::string> assetTag;
3227 std::optional<std::string> powerRestorePolicy;
3228 std::optional<std::string> powerMode;
3229 std::optional<bool> wdtEnable;
3230 std::optional<std::string> wdtTimeOutAction;
3231 std::optional<std::string> bootSource;
3232 std::optional<std::string> bootType;
3233 std::optional<std::string> bootEnable;
3234 std::optional<std::string> bootAutomaticRetry;
3235 std::optional<uint32_t> bootAutomaticRetryAttempts;
3236 std::optional<bool> bootTrustedModuleRequired;
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003237 std::optional<std::string> stopBootOnFault;
Ed Tanousc1e219d2023-06-07 10:34:33 -07003238 std::optional<bool> ipsEnable;
3239 std::optional<uint8_t> ipsEnterUtil;
3240 std::optional<uint64_t> ipsEnterTime;
3241 std::optional<uint8_t> ipsExitUtil;
3242 std::optional<uint64_t> ipsExitTime;
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003243};
Jiaqing Zhao550a6bf2022-04-26 17:54:52 +08003244
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003245/**
3246 * @brief process the POST request after getting the computerSystemIndex
3247 *
3248 * @param[in] asyncResp Shared pointer for completing asynchronous
3249 * calls
3250 * @param[in] patchParams Struct containing the property we want to
3251 * patch
3252 * @param[in] computerSystemIndex Index associated with the requested system
3253 *
3254 * @return None
3255 */
James Feistb49ac872019-05-21 15:12:01 -07003256
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003257inline void processComputerSystemPatch(
3258 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3259 std::string& systemName, PatchParams& patchParams,
3260 const uint64_t computerSystemIndex)
3261{
Janet Adkinsf664fd82025-07-23 14:01:43 -05003262 if constexpr (!BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
3263 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003264 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003265 {
3266 messages::propertyUnknown(asyncResp->res, "IndicatorLED");
3267 return;
3268 }
3269 }
3270
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003271 if (patchParams.assetTag)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003272 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003273 setAssetTag(asyncResp, *patchParams.assetTag);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003274 }
James Feistb49ac872019-05-21 15:12:01 -07003275
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003276 if (patchParams.wdtEnable || patchParams.wdtTimeOutAction)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003277 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003278 setWDTProperties(asyncResp, patchParams.wdtEnable,
3279 patchParams.wdtTimeOutAction);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003280 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003281
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003282 if (patchParams.bootSource || patchParams.bootType ||
3283 patchParams.bootEnable)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003284 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003285 setBootProperties(asyncResp, computerSystemIndex,
3286 patchParams.bootSource, patchParams.bootType,
3287 patchParams.bootEnable);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003288 }
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003289 if (patchParams.bootAutomaticRetry)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003290 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003291 setAutomaticRetry(asyncResp, computerSystemIndex,
3292 *patchParams.bootAutomaticRetry);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003293 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003294
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003295 if (patchParams.bootAutomaticRetryAttempts)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003296 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003297 setAutomaticRetryAttempts(
3298 asyncResp, computerSystemIndex,
3299 patchParams.bootAutomaticRetryAttempts.value());
Ed Tanousc1e219d2023-06-07 10:34:33 -07003300 }
Corey Hardesty797d5da2022-04-26 17:54:52 +08003301
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003302 if (patchParams.bootTrustedModuleRequired)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003303 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003304 setTrustedModuleRequiredToBoot(asyncResp, computerSystemIndex,
3305 *patchParams.bootTrustedModuleRequired);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003306 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003307
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003308 if (patchParams.stopBootOnFault)
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003309 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003310 setStopBootOnFault(asyncResp, *patchParams.stopBootOnFault);
Albert Zhang9dcfe8c2021-07-05 09:38:06 +08003311 }
3312
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003313 if (patchParams.locationIndicatorActive)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003314 {
Janet Adkins2eaa9272025-04-17 10:30:43 -05003315 systems_utils::getValidSystemsPath(
3316 asyncResp, systemName,
3317 [asyncResp, systemName,
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003318 locationIndicatorActive{*patchParams.locationIndicatorActive}](
Janet Adkins2eaa9272025-04-17 10:30:43 -05003319 const std::optional<std::string>& validSystemsPath) {
3320 if (!validSystemsPath)
3321 {
3322 messages::resourceNotFound(asyncResp->res, "Systems",
3323 systemName);
3324 return;
3325 }
3326 setLocationIndicatorActive(asyncResp, *validSystemsPath,
3327 locationIndicatorActive);
3328 });
Ed Tanousc1e219d2023-06-07 10:34:33 -07003329 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003330
Janet Adkinsf664fd82025-07-23 14:01:43 -05003331 if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003332 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003333 if (patchParams.indicatorLed)
Janet Adkinsf664fd82025-07-23 14:01:43 -05003334 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003335 setIndicatorLedState(asyncResp, *patchParams.indicatorLed);
Janet Adkinsf664fd82025-07-23 14:01:43 -05003336 asyncResp->res.addHeader(boost::beast::http::field::warning,
3337 "299 - \"IndicatorLED is deprecated. Use "
3338 "LocationIndicatorActive instead.\"");
3339 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003340 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003341
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003342 if (patchParams.powerRestorePolicy)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003343 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003344 setPowerRestorePolicy(asyncResp, computerSystemIndex,
3345 *patchParams.powerRestorePolicy);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003346 }
Chris Cain3a2d04242021-05-28 16:57:10 -05003347
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003348 if (patchParams.powerMode)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003349 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003350 setPowerMode(asyncResp, *patchParams.powerMode);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003351 }
Chris Cain37bbf982021-09-20 10:53:09 -05003352
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003353 if (patchParams.ipsEnable || patchParams.ipsEnterUtil ||
3354 patchParams.ipsEnterTime || patchParams.ipsExitUtil ||
3355 patchParams.ipsExitTime)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003356 {
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003357 setIdlePowerSaver(asyncResp, patchParams.ipsEnable,
3358 patchParams.ipsEnterUtil, patchParams.ipsEnterTime,
3359 patchParams.ipsExitUtil, patchParams.ipsExitTime);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003360 }
3361}
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303362
Oliver Brewkad43cc6b2025-07-23 16:41:12 +02003363inline void handleComputerSystemPatch(
3364 crow::App& app, const crow::Request& req,
3365 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3366 const std::string& systemName)
3367{
3368 PatchParams patchParams;
3369
3370 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3371 {
3372 return;
3373 }
3374
3375 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
3376 {
3377 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3378 {
3379 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3380 systemName);
3381 return;
3382 }
3383 }
3384
3385 asyncResp->res.addHeader(
3386 boost::beast::http::field::link,
3387 "</redfish/v1/JsonSchemas/ComputerSystem/ComputerSystem.json>; rel=describedby");
3388
3389 if (!json_util::readJsonPatch(
3390 req, asyncResp->res, //
3391 "AssetTag", patchParams.assetTag, //
3392 "Boot/AutomaticRetryAttempts",
3393 patchParams.bootAutomaticRetryAttempts, //
3394 "Boot/AutomaticRetryConfig", patchParams.bootAutomaticRetry, //
3395 "Boot/BootSourceOverrideEnabled", patchParams.bootEnable, //
3396 "Boot/BootSourceOverrideMode", patchParams.bootType, //
3397 "Boot/BootSourceOverrideTarget", patchParams.bootSource, //
3398 "Boot/StopBootOnFault", patchParams.stopBootOnFault, //
3399 "Boot/TrustedModuleRequiredToBoot",
3400 patchParams.bootTrustedModuleRequired, //
3401 "HostWatchdogTimer/FunctionEnabled", patchParams.wdtEnable, //
3402 "HostWatchdogTimer/TimeoutAction", patchParams.wdtTimeOutAction, //
3403 "IdlePowerSaver/Enabled", patchParams.ipsEnable, //
3404 "IdlePowerSaver/EnterDwellTimeSeconds", patchParams.ipsEnterTime, //
3405 "IdlePowerSaver/EnterUtilizationPercent",
3406 patchParams.ipsEnterUtil, //
3407 "IdlePowerSaver/ExitDwellTimeSeconds", patchParams.ipsExitTime, //
3408 "IdlePowerSaver/ExitUtilizationPercent", patchParams.ipsExitUtil, //
3409 "IndicatorLED", patchParams.indicatorLed, //
3410 "LocationIndicatorActive", patchParams.locationIndicatorActive, //
3411 "PowerMode", patchParams.powerMode, //
3412 "PowerRestorePolicy", patchParams.powerRestorePolicy))
3413 {
3414 return;
3415 }
3416
3417 getComputerSystemIndex(asyncResp, systemName,
3418 std::bind_front(processComputerSystemPatch,
3419 asyncResp, systemName, patchParams));
3420}
3421
Ed Tanous38c8a6f2022-09-01 16:37:27 -07003422inline void handleSystemCollectionResetActionHead(
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003423 crow::App& app, const crow::Request& req,
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003424 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousc1e219d2023-06-07 10:34:33 -07003425 const std::string& /*systemName*/)
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003426{
3427 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3428 {
3429 return;
3430 }
3431 asyncResp->res.addHeader(
3432 boost::beast::http::field::link,
3433 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3434}
Andrew Geissler33e1f122024-02-26 21:10:16 -06003435
3436/**
3437 * @brief Translates allowed host transitions to redfish string
3438 *
3439 * @param[in] dbusAllowedHostTran The allowed host transition on dbus
3440 * @param[out] allowableValues The translated host transition(s)
3441 *
Manojkiran Edaefff2b52024-06-18 18:01:46 +05303442 * @return Emplaces corresponding Redfish translated value(s) in
Andrew Geissler33e1f122024-02-26 21:10:16 -06003443 * allowableValues. If translation not possible, does nothing to
3444 * allowableValues.
3445 */
Patrick Williams504af5a2025-02-03 14:29:03 -05003446inline void dbusToRfAllowedHostTransitions(
3447 const std::string& dbusAllowedHostTran,
3448 nlohmann::json::array_t& allowableValues)
Andrew Geissler33e1f122024-02-26 21:10:16 -06003449{
3450 if (dbusAllowedHostTran == "xyz.openbmc_project.State.Host.Transition.On")
3451 {
3452 allowableValues.emplace_back(resource::ResetType::On);
3453 allowableValues.emplace_back(resource::ResetType::ForceOn);
3454 }
3455 else if (dbusAllowedHostTran ==
3456 "xyz.openbmc_project.State.Host.Transition.Off")
3457 {
3458 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3459 }
3460 else if (dbusAllowedHostTran ==
3461 "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot")
3462 {
3463 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3464 }
3465 else if (dbusAllowedHostTran ==
3466 "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot")
3467 {
3468 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3469 }
3470 else
3471 {
3472 BMCWEB_LOG_WARNING("Unsupported host tran {}", dbusAllowedHostTran);
3473 }
3474}
3475
3476inline void afterGetAllowedHostTransitions(
3477 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3478 const boost::system::error_code& ec,
3479 const std::vector<std::string>& allowedHostTransitions)
3480{
3481 nlohmann::json::array_t allowableValues;
3482
3483 // Supported on all systems currently
3484 allowableValues.emplace_back(resource::ResetType::ForceOff);
3485 allowableValues.emplace_back(resource::ResetType::PowerCycle);
3486 allowableValues.emplace_back(resource::ResetType::Nmi);
3487
3488 if (ec)
3489 {
Ed Tanouse715d142024-03-07 15:47:37 -08003490 if ((ec.value() ==
3491 boost::system::linux_error::bad_request_descriptor) ||
3492 (ec.value() == boost::asio::error::basic_errors::host_unreachable))
Andrew Geissler33e1f122024-02-26 21:10:16 -06003493 {
3494 // Property not implemented so just return defaults
3495 BMCWEB_LOG_DEBUG("Property not available {}", ec);
3496 allowableValues.emplace_back(resource::ResetType::On);
3497 allowableValues.emplace_back(resource::ResetType::ForceOn);
3498 allowableValues.emplace_back(resource::ResetType::ForceRestart);
3499 allowableValues.emplace_back(resource::ResetType::GracefulRestart);
3500 allowableValues.emplace_back(resource::ResetType::GracefulShutdown);
3501 }
3502 else
3503 {
3504 BMCWEB_LOG_ERROR("DBUS response error {}", ec);
3505 messages::internalError(asyncResp->res);
3506 return;
3507 }
3508 }
3509 else
3510 {
3511 for (const std::string& transition : allowedHostTransitions)
3512 {
3513 BMCWEB_LOG_DEBUG("Found allowed host tran {}", transition);
3514 dbusToRfAllowedHostTransitions(transition, allowableValues);
3515 }
3516 }
3517
3518 nlohmann::json::object_t parameter;
3519 parameter["Name"] = "ResetType";
3520 parameter["Required"] = true;
Ed Tanous539d8c62024-06-19 14:38:27 -07003521 parameter["DataType"] = action_info::ParameterTypes::String;
Andrew Geissler33e1f122024-02-26 21:10:16 -06003522 parameter["AllowableValues"] = std::move(allowableValues);
3523 nlohmann::json::array_t parameters;
3524 parameters.emplace_back(std::move(parameter));
3525 asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
3526}
3527
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003528inline void getAllowedHostTransitions(
3529 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3530 const uint64_t computerSystemIndex)
3531{
3532 dbus::utility::getProperty<std::vector<std::string>>(
3533 getHostStateServiceName(computerSystemIndex),
3534 getHostStateObjectPath(computerSystemIndex),
3535 "xyz.openbmc_project.State.Host", "AllowedHostTransitions",
3536 std::bind_front(afterGetAllowedHostTransitions, asyncResp));
3537}
3538
Ed Tanousc1e219d2023-06-07 10:34:33 -07003539inline void handleSystemCollectionResetActionGet(
3540 crow::App& app, const crow::Request& req,
3541 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
3542 const std::string& systemName)
3543{
3544 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
3545 {
3546 return;
3547 }
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003548
Gunnar Mills68896202024-08-21 11:34:20 -05003549 if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003550 {
Gunnar Mills68896202024-08-21 11:34:20 -05003551 if (systemName == "hypervisor")
3552 {
3553 handleHypervisorResetActionGet(asyncResp);
3554 return;
3555 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003556 }
3557
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003558 if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003559 {
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003560 if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
3561 {
3562 messages::resourceNotFound(asyncResp->res, "ComputerSystem",
3563 systemName);
3564 return;
3565 }
Ed Tanousc1e219d2023-06-07 10:34:33 -07003566 }
3567
3568 asyncResp->res.addHeader(
3569 boost::beast::http::field::link,
3570 "</redfish/v1/JsonSchemas/ActionInfo/ActionInfo.json>; rel=describedby");
3571
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003572 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
3573 "/redfish/v1/Systems/{}/ResetActionInfo", systemName);
Ed Tanousc1e219d2023-06-07 10:34:33 -07003574 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
3575 asyncResp->res.jsonValue["Name"] = "Reset Action Info";
3576 asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
3577
Andrew Geissler33e1f122024-02-26 21:10:16 -06003578 // Look to see if system defines AllowedHostTransitions
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003579 getComputerSystemIndex(
3580 asyncResp, systemName,
3581 std::bind_front(getAllowedHostTransitions, asyncResp));
Ed Tanousc1e219d2023-06-07 10:34:33 -07003582}
Oliver Brewka5e7c1f32025-07-23 16:38:05 +02003583
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303584/**
3585 * SystemResetActionInfo derived class for delivering Computer Systems
3586 * ResetType AllowableValues using ResetInfo schema.
3587 */
Ed Tanous100afe52023-06-07 13:30:46 -07003588inline void requestRoutesSystems(App& app)
AppaRao Puli1cb1a9e2020-07-17 23:38:57 +05303589{
Ed Tanous100afe52023-06-07 13:30:46 -07003590 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3591 .privileges(redfish::privileges::headComputerSystemCollection)
3592 .methods(boost::beast::http::verb::head)(
3593 std::bind_front(handleComputerSystemCollectionHead, std::ref(app)));
3594
3595 BMCWEB_ROUTE(app, "/redfish/v1/Systems/")
3596 .privileges(redfish::privileges::getComputerSystemCollection)
3597 .methods(boost::beast::http::verb::get)(
3598 std::bind_front(handleComputerSystemCollectionGet, std::ref(app)));
3599
3600 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3601 .privileges(redfish::privileges::headComputerSystem)
3602 .methods(boost::beast::http::verb::head)(
3603 std::bind_front(handleComputerSystemHead, std::ref(app)));
3604
3605 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3606 .privileges(redfish::privileges::getComputerSystem)
3607 .methods(boost::beast::http::verb::get)(
3608 std::bind_front(handleComputerSystemGet, std::ref(app)));
3609
3610 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/")
3611 .privileges(redfish::privileges::patchComputerSystem)
3612 .methods(boost::beast::http::verb::patch)(
3613 std::bind_front(handleComputerSystemPatch, std::ref(app)));
3614
3615 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Actions/ComputerSystem.Reset/")
3616 .privileges(redfish::privileges::postComputerSystem)
3617 .methods(boost::beast::http::verb::post)(std::bind_front(
3618 handleComputerSystemResetActionPost, std::ref(app)));
3619
Ed Tanous7f3e84a2022-12-28 16:22:54 -08003620 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanousdd60b9e2022-07-07 17:03:54 -07003621 .privileges(redfish::privileges::headActionInfo)
3622 .methods(boost::beast::http::verb::head)(std::bind_front(
3623 handleSystemCollectionResetActionHead, std::ref(app)));
Ed Tanous22d268c2022-05-19 09:39:07 -07003624 BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/ResetActionInfo/")
Ed Tanoused398212021-06-09 17:05:54 -07003625 .privileges(redfish::privileges::getActionInfo)
Ed Tanousc1e219d2023-06-07 10:34:33 -07003626 .methods(boost::beast::http::verb::get)(std::bind_front(
3627 handleSystemCollectionResetActionGet, std::ref(app)));
John Edward Broadbent7e860f12021-04-08 15:57:16 -07003628}
Ed Tanous1abe55e2018-09-05 08:30:59 -07003629} // namespace redfish